13 KiB
OrgChart P10.3 — Guard FAIL 10건 원인 분석 및 배포 차단 판정
RESULT: PARTIAL — FAIL 10건 모두 원인·영향·수정 방법 확인, 10/10 재현. 기술적 BLOCKER 0건. 단 Guard 원본 status는 FAIL 그대로이고, CI·조직 배포 정책에서 Guard가 필수인지는 근거가 없어 NOT VERIFIED다. 제품 코드·Guard 수정 없음.
1. 실행 기준
| 항목 | 값 |
|---|---|
| Worktree / 브랜치 | D:\디자인시스템\HMDesign-OrgChart-GuardReview / feature/orgchart-guard-review (신규, 커밋 없음) |
| 기준 HEAD | 5acaf8a29596317133e54e8ad437ee00beba1cf0 (P10.2 미커밋 변경 미포함) |
| Guard | scripts/ai-generation-guard.mjs (schemaVersion 2) + scripts/guard-theme-analysis.mjs. P10.2 작업본에서도 수정되지 않은 파일 |
| 원본 결과 | P10 작업본 test-results/org-chart-p10/guard.json (sha256 앞부분 a83d058656480fbf): status FAIL / staticStatus FAIL / runtimeStatus NOT VERIFIED, STORYBOOK / PARTIAL, FAIL 10 / NOT VERIFIED 19 |
| 재현 | Node v22.23.2. node scripts/ai-generation-guard.mjs --target <GuardReview> --scope PARTIAL --profile STORYBOOK --files department-colors.ts,expanded-content.ts,style-presets.ts --json → guard-repro.json |
| 재현 결과 | exit 1, FAIL 10, P10과 code/file/line/message 10/10 동일, 새 FAIL 0 |
P10 원래 실행의 정확한 15개 경로 --files 명령은 보고서·로그에 기록이 없다. 그래서 FAIL이 나온 3개 파일만 선택해 재현했다. 출력 파일은 Worktree의 gitignore 대상 경로와 scratchpad에만 썼다. Guard는 stdout 외에 파일을 쓰지 않는다.
2. Guard의 판정 방식 (근거)
guard-theme-analysis.mjs 기준:
- 정의(definitions) 수집 출처는 세 가지뿐이다. ① graph에 포함된 소비 CSS 파일의 선언, ② 공개 CSS 매핑(
@hm-design/ui/theme.css,@hm-design/ui/dashboard-status.css)과 그 상대@import(L85-89), ③ JS object literal의'--x'key(L102). element.style.setProperty('--hm-…', …)는 정의로 수집하지 않는다.@hm-design/org-chart/style.css는 공개 CSS 매핑에 없다. Storybook에서는 이 CSS를?url로 import해 Shadow DOM에 주입하므로 graph에서도 보이지 않는다(L83의r.css가 아님).--hm-참조가 미정의면 fallback이 있어도 FAIL이다(L128, Guard 정책 TOKEN-001: "fallback 색이 있어도 없는 HM token은 FAIL").- 같은 동작은 P6 최소 재현 스크립트
examples/org-chart/verify-guard-p1.mjs에도 assertion으로 고정되어 있다. Shadow CSS 제외 → FAIL, setProperty 정의 미수집 → FAIL.
3. 필수 요약표
| ID | 검사명 | 실제 원인 | 재현 | 영향 | 차단 등급 | 수정 방안 | 예상 시간 |
|---|---|---|---|---|---|---|---|
| F1 | TOKEN-001 department-colors.ts:47 --hm-orgchart-current-gradient |
B 런타임 선언(applyOrganizationStyle(row) setProperty, L28)을 Guard가 수집하지 못함 |
재현 | 없음. Storybook Department Colors 전용, dist 미포함 | LOW | Guard에 literal setProperty 정의 수집 추가(승인 필요) 또는 예외 승인 | F1·F2·F8 |
| F2 | TOKEN-001 department-colors.ts:47 --hm-orgchart-current-card-background |
B F1과 동일 | 재현 | 없음 | LOW | F1과 동일 | (F1에 포함) |
| F3 | TOKEN-001 department-colors.ts:75 --hm-orgchart-contrast-candidate-color |
D 저장소 어디에도 선언 없는 HM 토큰. 미승인 대비 후보 미리보기(UNAPPROVED_NOT_APPLIED)의 fallback #10243b로만 렌더 |
재현 | 외부 패키지 영향 없음(dist 미포함, createDepartmentColors 0회). Guard 규칙상 실제 위반 |
MEDIUM | 같은 값의 literal로 교체(색 변화 없음). 또는 미리보기 CSS에 선언(단 ?url CSS는 Guard graph 밖이라 해소 안 됨) |
F3 |
| F4 | TOKEN-001 department-colors.ts:78 --hm-orgchart-contrast-candidate-color |
D F3과 동일 (chip label) | 재현 | F3과 동일 | MEDIUM | F3과 동일 | (F3에 포함) |
| F5 | TOKEN-001 department-colors.ts:78 --hm-orgchart-contrast-candidate-chip-background |
D 선언 없음, fallback #ffffff |
재현 | F3과 동일 | MEDIUM | F3과 동일 | (F3에 포함) |
| F6 | TOKEN-001 expanded-content.ts:30 --hm-orgchart-resolved-fg-primary |
B+A 변수는 styles/design-tokens.css:12 → dist/style.css에 선언됨(Guard graph 밖). 그리고 이 줄의 --hm-orgchart-expanded-title-ink는 소비처가 없는 dead code(d0828a7에서 CSS color: var(--…title-ink) 삭제, 제목은 #ffffff 고정 L75) |
재현 | 렌더 영향 없음. 삼안·장헌산업만 어두운 글자를 쓰는 것처럼 오해할 수 있는 유지보수 위험 | LOW | dead setProperty 1줄 삭제(시각 변화 없음) |
5~10분 |
| F7 | TOKEN-001 expanded-content.ts:30 --hm-orgchart-resolved-on-action-primary |
B+A F6과 동일(design-tokens.css:20) |
재현 | F6과 동일 | LOW | F6과 동일 | (F6에 포함) |
| F8 | TOKEN-001 style-presets.ts:9 --hm-orgchart-resolved-bg-surface |
B design-tokens.css:8 → dist/style.css에 선언. 공개 CSS 매핑에 OrgChart CSS 없음 / ?url Shadow 주입 |
재현 | 없음(Fixed/Expanded 실행 PASS 이력) | LOW | Guard 공개 CSS 매핑에 @hm-design/org-chart/style.css 추가(승인 필요) 또는 예외 승인 |
(F1에 포함) |
| F9 | TOKEN-001 style-presets.ts:74 --hm-orgchart-current-border |
B 같은 함수 L69에서 같은 element에 setProperty로 선언 | 재현 | 없음. 배포 JS 경로(render.ts L84) | LOW | F1과 동일 | (F1에 포함) |
| F10 | TOKEN-001 style-presets.ts:75 --hm-orgchart-current-gradient |
B 같은 함수 L71에서 setProperty로 선언 | 재현 | 없음 | LOW | F1과 동일 | (F1에 포함) |
분류: A 0(단독) · B 7 (F1, F2, F6F10. F6·F7은 A 성격의 dead code 동반) · C 0 · D 3 (F3F5) · E 0 · UNKNOWN 0.
4. 개별 근거 (12개 필수 항목 요약)
공통 사항: 10건 모두 기존 문제다(P9.4와 동일, P10 신규 0). 모두 OrgChart 도입으로 발생했다(61c6f8d/a92913d/064517e, 2026-10-12. main에는 OrgChart가 없음. C 레거시 아님). 모두 재현됐다.
- F1·F2 — 조건: Storybook graph에 직접 import된
department-colors.ts가 선택 파일일 때. swatch는applyOrganizationStyle(row, index)가 실행된row의 자손이므로 실제 cascade로 값이 정의된다. 외부 사용 영향 없음. 배포 영향 없음. - F3~F5 — 조건: 같은 파일. 세 변수 모두 저장소 전체에서 선언 0건이다(rg 확인). override hook을 소비하는 곳도 없다. 렌더 결과는 fallback과 같다. Guard 정책 문구상 정당한 FAIL이며 오탐이 아니다. 다만 실행 영향은 없고 Storybook 전용이다. 접근성 대비 후보의 승인 여부와는 별개다.
- F6·F7 — 조건: Expanded Storybook graph. 참조 변수 자체는 공개 패키지 CSS에 선언되어 있다(dist 확인). 남은 문제는 dead setProperty다. 제거하면 두 FAIL이 사라지고 화면은 바뀌지 않는다.
- F8~F10 — 조건:
style-presets.ts가 선택 파일일 때. F8은 패키지 CSS에 선언되어 있지만 graph에서 보이지 않는다. F9·F10은 같은 함수 안의 setProperty 직후 참조라서 런타임에서 항상 정의된다.
5. 배포 차단 판정
| 구분 | 판정 | 근거 |
|---|---|---|
| 기술적 배포 차단 | 없음 (BLOCKER 0) | 빌드 실패·공개 API 파손·데이터 손상 없음. F1·F2·F6 |
| CI상 차단 | CI 근거 없음 | 저장소에 .github·.gitea·.husky·CI yaml이 없다. package.json에 Guard를 실행하는 build/test 훅도 없다(test:guard는 Guard 자체 단위 테스트). 원격 Gitea 서버 측 설정·브랜치 보호는 NOT VERIFIED |
| 조직 정책상 차단 | UNKNOWN — 사용자 결정 필요 | Guard 정책상 exit 1=FAIL이다. P10 보고서는 "Guard 잔여 수용 여부를 정리한 뒤 명시 승인"을 Commit/Push 조건으로 두었다. 이 근거만으로 배포 가능하다고 판정하지 않는다 |
건수: BLOCKER 0 / HIGH 0 / MEDIUM 3 (F3~F5) / LOW 7 / UNKNOWN 0.
6. 수정 우선순위 (실행하지 않음)
| 순서 | 구분 | 대상 | 최소 수정 | 예상 | 제품 영향 | 병렬 | 수정 후 검증 |
|---|---|---|---|---|---|---|---|
| 1 | 배포 전 권장 | packages/org-chart/src/core/expanded-content.ts:30 |
dead --hm-orgchart-expanded-title-ink setProperty 삭제 → F6·F7 해소 |
5~10분 | 없음(제목 #ffffff 유지, 회사색 불변) |
가능(P10.2 미수정 파일) | Core typecheck/test, Guard PARTIAL 해당 파일, Expanded 제목 computed color 1회 |
| 2 | 배포 전 권장 | packages/org-chart/src/core/department-colors.ts:75,78 |
미선언 HM var를 동일 값 literal로 교체 → F3~F5 해소. 후보 색은 미승인·미적용 상태 유지 | 15~25분 | 없음(Storybook 미리보기, 동일 색) | 가능 | Guard PARTIAL, Department Colors Story 1회(다른 Guard 규칙이 hex literal을 지적하는지 확인 필요) |
| 3 | 별도 의사결정 | scripts/guard-theme-analysis.mjs + ai-generation-guard.test.mjs |
ⓐ @hm-design/org-chart/style.css(?url 포함)를 공개 CSS로 인식 ⓑ literal style.setProperty('--hm-…')를 정의로 수집 → F1·F2·F8~F10 해소. 규칙 완화가 아니라 탐지 정확도 개선이지만 Guard 계약 변경이라 승인 필요 |
60~120분 | 제품 영향 없음. 다른 소비 화면 판정이 바뀔 수 있어 회귀 필요 | 가능 | node --test scripts/ai-generation-guard.test.mjs 전체, 기존 Baseline 수량 대조, OrgChart PARTIAL 재실행 |
| 3' | 대안(승인 필요) | 문서 | 3을 하지 않으면 F1·F2·F8~F10을 "Guard 탐지 범위 밖 · 런타임 선언 확인됨" 예외로 기록 | 15분 | — | — | 원본 FAIL 보존 |
- 즉시 수정 대상(BLOCKER): 없음.
- 최소 수정 대상 파일:
expanded-content.ts,department-colors.ts(+ 선택 시 Guard 2개 파일). - 예상 총 수정 시간: 코드 1·2: 20
35분 + 검증 2030분. Guard 확장 3 포함 시 약 1.5~3시간. - 1·2만 적용하면 FAIL은 10 → 5건이 되고 Guard status는 여전히 FAIL이다. Guard PASS에는 3 또는 3'의 결정이 필요하다.
- OrgChart를 검사 대상에서 빼거나 규칙을 완화하는 방안은 제시하지 않는다.
7. 디자인·접근성 구분 (삼안·장헌산업)
- 흰 제목(
#ffffff) on 회사 primary의 일반 텍스트 WCAG 미달 진단은 미해결로 유지한다(이번에 재측정하지 않음 → NOT VERIFIED). - Guard FAIL 10건에 포함되지 않는다. F6·F7은 이 회사들의 제목 색을 바꾸던 이전 코드의 잔재일 뿐이고 현재 렌더에 관여하지 않는다.
- 사용자 승인 디자인 예외다. 접근성 PASS가 아니다.
- 배포 정책상 WCAG 준수가 필수인지는 근거 문서가 없다 → 별도 승인 필요.
- 색 변경 없는 대안(텍스트 그림자, 굵기 증가, 제목 영역 내부 흰 label 등)은 P11 또는 별도 디자인 결정 사항이며 이번에 적용하지 않는다. 회사색·카드 디자인은 변경하지 않았다.
8. 외부 패키지 구조와의 관계
FAIL 10건은 모두 @hm-design/org-chart Core 소스의 CSS 변수 참조에서 나온다. React Wrapper, /hm-dialog Entry, employeePopupAdapter, Optional Peer, HMDesign UI 정적 import, exports, 타입과는 관련이 없다. 기준 Commit에는 P10.2 Wrapper 개선이 없으며, 이번 결과를 개선 코드의 실패로 보지 않는다. Package Graph와 외부 소비자 기준 Guard는 별도 실행하지 않았다(NOT VERIFIED).
9. P10.2와의 충돌 가능성
P10.2 미커밋 변경 파일(AGENTS/CLAUDE, docs, packages/org-chart-react/*, src/org-chart/org-chart-expanded.stories.tsx)과 수정 후보 파일은 겹치지 않는다. 다만 P10.2가 바꾸는 Expanded Story가 Guard graph에 포함되므로, 통합 후 PARTIAL Guard를 1회 다시 실행해야 한다. Guard 확장(3)은 AGENTS·Guard 정책 문서 갱신과 겹칠 수 있다.
10. NOT VERIFIED
- P10 원래 15개 경로 Guard 명령(기록 없음. 3개 파일 subset으로 동일 FAIL 재현)
- dist 선언 확인은 P10 작업본의 기존
packages/org-chart/dist를 읽은 것이다. 이 dist가 5acaf8a에서 빌드되었는지는 확인하지 않았다(Core 소스는 P10.2 미수정) - 원격 Gitea 서버 CI·브랜치 보호, 조직 배포 정책상 Guard 필수 여부
- Runtime / Design Intent / 소비자(React·Vanilla) 기준 Guard graph
- 삼안·장헌산업 대비 재측정
- 수정안 적용 시 다른 Guard 규칙의 반응
11. 작업 제한 준수
제품 코드·Core·React Wrapper·Storybook·Guard 규칙·회사색 수정 없음. P10.2 작업본 파일 수정 없음(읽기만 함). 새 Worktree·브랜치를 만들고 이 보고서와 gitignore 대상 재현 JSON만 추가했다. Commit·Push·Merge·Rebase·Cherry-pick·PR·main Checkout은 진행하지 않았다.