140 lines
15 KiB
Markdown
140 lines
15 KiB
Markdown
# HMDesign Guard 정확도 수정 결과 — 2026-10-10
|
||
|
||
RESULT: PARTIAL
|
||
|
||
TARGET: `D:\디자인시스템\hmdesign`
|
||
|
||
범위: Guard 검증 로직·테스트·설명 문서. Runtime: React/Vite. Production과 기존 Storybook Reference를 독립 검사한다. Component/Pattern/Theme/Token/D-01/D-02/대표 Story와 이전 퍼블리셔 통합 보고서는 수정하지 않았다. Git 명령을 실행하지 않았다.
|
||
|
||
## Guard 문제 분석
|
||
|
||
| 항목 | 원인·판정·수정 |
|
||
|---|---|
|
||
| Dashboard Sidebar | 이전 Guard는 import graph의 모든 JSX를 실제 render처럼 취급했다. export entry의 `DashboardScreen mode="compact"` → `compact=true` → `sidebar=undefined`와, 사용되지 않는 Reference JSX initializer를 구분하지 못해 NAV-001 FAIL 및 NAV-005를 냈다. 직접 component 호출·기본/literal props·immutable local 값·반환 JSX/slot을 분석하여 현재 entry에서 배제되는 분기만 제외했다. 실제 Chrome DOM의 Sidebar는 0개다. |
|
||
| Storybook Scope | 기존 Guard는 Production 전용이므로 Story 변경의 SCOPE-001은 검사 범위 불일치였다. 독립 `--profile STORYBOOK`을 추가했다. 설정의 literal stories glob으로 63개 Story module을 발견하고, 각 Story graph에 공통 preview를 연결한다. 다른 lazy Story의 CSS를 연결 증거로 사용하지 않는다. |
|
||
| CSS Intent | 기존 REUSE-003은 위반 확정 FAIL이 아닌 검토용 NOT VERIFIED였다. Primary 80%·Secondary·Legacy·Dashboard Gradient를 바꿀 근거가 없다. 해당 판정을 유지하고, 누락됐던 내부 `tabs-*` slot도 검토 대상으로 포함했다. package 내부 Theme CSS는 기존 소비자 replica 검사에서 제외한다. |
|
||
| Navigation Policy | GNB_ONLY/DASHBOARD_ONLY의 Sidebar 금지와 혼합 Navigation 금지는 유지한다. LNB_ONLY 정상 사용도 유지한다. 실제 선택되는 Reference Sidebar branch는 FAIL, 동적 조건/spread/mutation/opaque callback은 가능한 위반을 NOT VERIFIED로 남긴다. 여러 호출 중 하나라도 확정 위반이면 FAIL이다. 공식 Sidebar를 component prop으로 전달해 렌더하는 경우도 탐지한다. |
|
||
| Production Graph | bootstrap import graph와 공개 package API 경계는 보존한다. Story/helper/reference 소비는 계속 FAIL이다. package Component/Pattern/Theme source는 소비 graph로 강제 포함하지 않는다. 직접 선택한 package CSS는 SCOPE-001 NOT VERIFIED이며 패키지 build/typecheck 및 별도 CSS/실제 렌더 확인으로 구분한다. |
|
||
|
||
### 실제 렌더·조건·Reference 구분
|
||
|
||
- 실제 `<DashboardSidebar>` 또는 금지 `sidebar` slot을 반환하는 literal 경로: FAIL.
|
||
- 조건이 미확정인 Sidebar: NOT VERIFIED. PASS로 숨기지 않는다.
|
||
- 현재 compact literal props로 배제된 분기·반환되지 않는 Reference JSX 값: 현재 Navigation 위반에서만 제외한다. import/export/CSS 검사는 유지한다.
|
||
- Reference라는 주석·파일명·Sidebar 문자열만으로 Production 사용을 허용하지 않는다. 같은 보존 분기를 선택하면 FAIL이다.
|
||
- Storybook Reference의 Navigation API는 mode 미지정 시 NOT APPLICABLE이다. 명시 mode를 주면 기존 정적 금지 규칙을 검사한다. Story별 대표/verification 분류·모든 상태의 혼합 Navigation 의도를 자동 승인하지 않는다. 신규 업무 화면의 Story 등록 금지는 그대로다.
|
||
|
||
## 원인 분류
|
||
|
||
**실제 위반:** 이번 제공된 Production entry에서 확정한 신규 디자인 시스템 위반은 없다. 회귀 fixture의 실제 Sidebar·혼합 Navigation·비공개 import·위조 public slot·Production의 Story 의존은 FAIL을 유지한다.
|
||
|
||
**오탐:** Dashboard compact에서 mount되지 않는 legacy Sidebar branch의 NAV-001. 현재 mode로 빈 slot을 증명할 수 있는데 NAV-005를 내던 분석 한계. Story 변경의 SCOPE-001은 기존 전용 범위 불일치이며 독립 Storybook 검사로 해결했다.
|
||
|
||
**검증 불가:** CSS override의 승인/복제 의도, native control의 합법적 사용 의도, opaque/dynamic render flow, 독립 package source를 소비 Guard로 검사하는 범위, 전 Story/모든 browser/state의 runtime 회귀.
|
||
|
||
전체 Storybook의 `src/patterns/gnb.stories.tsx:406`은 공개 컴포넌트가 없는 내부 `lnb-mobile-nav` wrapper를 사용한다. 기존 [GNB Composition 계약](../patterns/gnb.md#15-gnb-only-sidebar-composition-2026-10-08)에도 있는 Reference이며 소비자 복제로 확정할 수 없다. Storybook에서만 이 종류를 REUSE-001 NOT VERIFIED로 분류한다. 같은 코드의 Production 사용은 FAIL이며, Storybook에서도 공개 component slot을 기본 HTML로 위조하면 FAIL이다. 파일별 허용 목록·무조건 PASS는 추가하지 않았다.
|
||
|
||
## 수정 파일
|
||
|
||
| 파일 | 변경 내용·이유 |
|
||
|---|---|
|
||
| [Guard](../../scripts/ai-generation-guard.mjs) | 독립 Storybook profile/preview 연결·진단 범위, Navigation 분석 연결, 내부 Reference wrapper의 검토 판정, tabs slot intent 인식, 검사 파일 목록. Production 규칙을 삭제하지 않고 근거의 확실성을 구분한다. |
|
||
| [Navigation 분석기](../../scripts/guard-navigation-analysis.mjs) (신규) | 소비 코드를 실행하지 않는 제한된 render-value 분석. immutable literal props/locals만 absent를 증명한다. 미지원 흐름·callback·spread·mutation·alias·비원시 identity에는 불확실성을 유지한다. |
|
||
| [회귀 테스트](../../scripts/ai-generation-guard.test.mjs) | 기존 14개 본문을 그대로 보존하고 22개 test를 추가한다. |
|
||
| [Guard 정책 문서](ai-generation-guard.md) | 두 profile과 Component/Pattern 경계, 조건부 Navigation, Reference wrapper, CSS intent/utility 제한, exit 0 ≠ PASS 설명. |
|
||
| 이 보고서 (신규) | 분석·명령·결과·보존·미검증 근거 기록. 이전 보고서를 덮어쓰지 않는다. |
|
||
|
||
## 추가 테스트
|
||
|
||
- 기존 테스트: 14개, 기존 본문 byte 내용(개행 정규화 대조) 유지, 14/14 PASS.
|
||
- 신규 테스트: 22개. compact/default/literal/alias/barrel props, 실제 Reference 선택, 미확정 조건, 다중 호출, literal ternary/logical, spread·mutation·callback·destructuring·객체 alias, 혼합 Navigation 및 PARTIAL, Storybook discovery·공개 export·CSS entry·lazy CSS 격리, Reference wrapper, 정상 Gradient 파싱, malformed CSS·위조 slot, raw CSS import, package scope, component prop Sidebar 전달을 포함한다.
|
||
- 전체 테스트: 36/36 PASS.
|
||
- 실패 테스트: 0. 개발 중 테스트가 드러낸 누락은 최종 코드에서 수정했다. 성공한 최종 검증은 추가 변경이 없으면 반복하지 않았다.
|
||
|
||
## 최종 검증
|
||
|
||
| 항목 | 결과·실제 실행 근거 |
|
||
|---|---|
|
||
| GUARD_TEST | PASS — `node --test scripts/ai-generation-guard.test.mjs`, 36/36. |
|
||
| GUARD_FULL_SCREEN | NOT VERIFIED — 운영 GNB_ONLY, Dashboard/Recruit DASHBOARD_ONLY 모두 FAIL 0. 각 Navigation·Production 격리·CSS entry·공개 import 그룹은 PASS. 각 11건의 잔여는 REUSE-003 10건 + RENDER-002 1건이다. |
|
||
| GUARD_PARTIAL | NOT VERIFIED — 운영 CSS와 Dashboard composition 각각 RENDER-002 1건. Publisher 두 Story는 독립 profile에서 PASS. package Tabs CSS는 SCOPE-001 1건으로 독립 소비 검사가 아님을 명시한다. |
|
||
| GUARD_STORYBOOK | NOT VERIFIED — 전체 63개 Story module의 graph 검사, FAIL 0. 공개 import·격리 profile·CSS entry 그룹 PASS, Navigation NOT APPLICABLE. 내부 Reference wrapper 1건, CSS intent 16건, native control 19건을 유지한다. Publisher 두 Story PARTIAL은 PASS. |
|
||
| TYPECHECK | PASS — `npm run typecheck`, 사전 Theme/package 검사 및 루트·workspace TypeScript 검사 exit 0. |
|
||
| UI_BUILD | PASS — 위 pretypecheck의 `npm run build:packages`가 UI/Center Graphic build를 수행했다. 동일 package build를 다시 실행하지 않았다. |
|
||
| PRODUCTION_BUILD | PASS — `npm run build --ignore-scripts`; Dashboard 기존 Vite config build + `node scripts/finalize-dashboard-export.mjs`; Recruit 기존 Vite config build. 모두 exit 0. 이미 끝난 사전 package/Theme 검사는 중복하지 않았다. |
|
||
| STORYBOOK_BUILD | PASS — `npm run build-storybook --ignore-scripts`, exit 0, 291개 Story ID 산출물. |
|
||
| TEST | NOT VERIFIED — 일반 `test` script/Component unit runner가 없다. 지원되는 Guard suite는 GUARD_TEST에 별도로 기록한다. |
|
||
| CSS_IMPORTS | PASS — source CSS 78개·import 63건, 미해결 0. `index.css → tailwind.css`, 공개 UI Tailwind/Theme/status entry, compiled UI `@source "./index.js"` 존재, flex/grid/min-w-0/px-0/py-6 생성 및 관련 React 계산값 확인. |
|
||
| EXPORTS | PASS — runtime 공개 import 688건, 누락 0; 공개 export 산출물 16개 모두 존재. source barrel/API는 미변경. |
|
||
|
||
지원되지 않는 전용 Component/Pattern Guard profile, 전체 Story별 runtime/state/포인터 검사와 과거 pixel diff는 NOT VERIFIED다. 존재하지 않는 명령을 통과로 기록하지 않는다. 기존 Tailwind `bg-[var(...)]` 최적화 경고와 production 500kB 초과 chunk 경고는 그대로이며 build 실패가 아니다.
|
||
|
||
### 실제 Guard 명령
|
||
|
||
```sh
|
||
node scripts/ai-generation-guard.mjs --target . --scope FULL_SCREEN --mode GNB_ONLY --result index.html --json
|
||
node scripts/ai-generation-guard.mjs --target . --scope FULL_SCREEN --mode DASHBOARD_ONLY --result src/exports/dashboard/index.html --json
|
||
node scripts/ai-generation-guard.mjs --target . --scope FULL_SCREEN --mode DASHBOARD_ONLY --result src/exports/recruit/index.html --json
|
||
node scripts/ai-generation-guard.mjs --target . --scope PARTIAL --mode GNB_ONLY --files src/index.css,tailwind.css --result index.html --json
|
||
node scripts/ai-generation-guard.mjs --target . --scope PARTIAL --mode DASHBOARD_ONLY --files src/patterns/dashboard-composition.tsx --result src/exports/dashboard/index.html --json
|
||
node scripts/ai-generation-guard.mjs --target . --profile STORYBOOK --scope FULL_SCREEN --json
|
||
node scripts/ai-generation-guard.mjs --target . --profile STORYBOOK --scope PARTIAL --files src/components/tabs.stories.tsx,src/patterns/page-header.stories.tsx --json
|
||
node scripts/ai-generation-guard.mjs --target . --scope PARTIAL --files packages/ui/src/theme/tabs.css --json
|
||
```
|
||
|
||
### 실제 React 확인
|
||
|
||
로컬 Chrome에서 실제 build 산출물을 확인했다. Dashboard/Tabs/PageHeader의 대표 확인 범위이며 전체 291개 Story를 다시 렌더했다는 주장이 아니다.
|
||
|
||
- Dashboard: Sidebar 0개, Header 48px, layout min-width 960px, body flex. Token 기반 20/50/80% gradient 유지. 완료 필터 클릭으로 `완료 업무 12건`과 선택 상태·Table 갱신 확인. 390px에서 document 390px, frame client 390/scroll 960, overflow-x auto. Console error/warn 0.
|
||
- Tabs 1280/390px: Primary `color(srgb 1 1 1 / 0.8) → rgb(245,240,229)`, opacity 1. Secondary White→White. Fill active panel 7개 모두 24px 0 / transparent / border 0 / radius 0. Card 탭 전환 후 입력 초안 보존. document width 1265/375px(세로 scrollbar 제외), 가로 넘침 없음. Console error/warn 0.
|
||
- Legacy Compatibility: 기존 non-fill 2개가 gradient none / White / panel border 1px / padding 16px. surface-only Secondary Fill은 평면 패널 유지.
|
||
- PageHeader 1280/390px: 설명 margin-top 8px, Header margin-bottom 20px, panel 24px 0, Primary alpha .8. `완료 업무` 클릭 시 완료 Table로 전환, 문서 폭 1280/390px.
|
||
- 브라우저 임시 viewport를 복원하고 검증 탭과 loopback 서버를 종료했다. source 화면/API를 바꾸지 않았다.
|
||
|
||
## 보존 확인
|
||
|
||
| 항목 | 결과 |
|
||
|---|---|
|
||
| D-01/D-02 | PASS — Tabs CSS/Story·PageHeader Story source hash 동일. 공식 Tabs source/dist CSS 동일. 실제 위 패널·Gradient·Legacy 렌더 보존. |
|
||
| Component/API | PASS — 기존 Component/Pattern TSX·공개 barrel·package.json·lockfile hash 동일. |
|
||
| Theme/Token | PASS — Theme JSON/계약/CSS source hash 동일, 기존 check:theme-defaults의 71색/73 defaults 일치. |
|
||
| Storybook ID | PASS — Story source/export 미변경, 291개 현재 ID 산출물 및 기존 inventory 288개 ID 모두 보존. |
|
||
| 참고 원본 | PASS — 3개 파일 SHA-256 동일, 읽기 전용 유지. |
|
||
| 기존 파일 | PASS — 시작 source 504개 중 Guard·테스트·Guard 문서 3개만 변경, 나머지 501개 동일. 분석기·이 보고서는 신규다. 이전 통합 보고서/기존 작업을 보존했다. |
|
||
|
||
파일 목록·SHA-256·수정 전 사본은 `_local/guard-accuracy-2026-10-10/`: `_local/guard-accuracy-2026-10-10/` (당시 로컬 보관 증거, Git Clone 미포함)에 보존했다. node_modules·빌드 산출물·tsbuildinfo·기존 _local·Git metadata는 source baseline에서 제외했다. 빌드 산출물은 지원되는 기존 명령으로 재생성했고 source 보존과 구분한다. 해당 경로의 `baseline.json`, `reference-baseline.json`, `before/`, `tests-final.log`, `guard-summary.json`, `guard-*.json`, 각 build log, `static-audit.json`, `browser-evidence.json`, `preservation-final.json`이 이번 증거다. 이전 `_local/publisher-*` 로그/사본은 덮어쓰지 않았다.
|
||
|
||
## 남은 문제
|
||
|
||
- REUSE-003/004와 내부 Reference wrapper는 의도를 정적 코드만으로 확정할 수 없다. 실제 fixture·문서·사용 화면별 검토가 필요하다. 전체 Guard PASS로 표기하지 않았다.
|
||
- RENDER-002는 tool의 브라우저 확인 요구를 나타낸다. 이번 대표 실제 렌더 증거와 원본 JSON 상태를 따로 기록한다. 브라우저 증거를 근거로 JSON을 임의 PASS로 덮어쓰지 않는다.
|
||
- package source의 독립 Guard 범위는 지원하지 않는다. 패키지 typecheck/build/CSS declaration/hash/관련 렌더 검증은 별도 수행했다.
|
||
- 일반 Component unit runner, 전 Story/Props/브라우저/state 회귀, 외부 소비 앱·배포·역사적 pixel diff는 NOT VERIFIED.
|
||
- `.git`이 없는 폴더다. Git status/diff/HEAD 및 미커밋 구분은 NOT VERIFIED이며 파일 baseline으로 기존 작업을 보존했다.
|
||
|
||
## Git
|
||
|
||
```text
|
||
Git Init: NOT EXECUTED
|
||
Git Clone: NOT EXECUTED
|
||
Local Commit: NOT EXECUTED
|
||
Remote Push: NOT EXECUTED
|
||
Git commands / remote changes: NOT EXECUTED
|
||
```
|
||
|
||
## 최종 판단
|
||
|
||
- 기존 Dashboard Guard FAIL은 해결했다. 금지 Sidebar를 실제 선택하는 fixture는 계속 FAIL이다.
|
||
- 실제 위반 탐지 능력은 기존 14개+신규 22개로 검증했다. 미확정 경로를 PASS로 숨기지 않는다.
|
||
- 정상 D-01/D-02·Component/Pattern/Theme/Storybook source를 수정하지 않았고 지원되는 build/typecheck 및 대표 실제 렌더에서 회귀를 발견하지 않았다. 전수 runtime 회귀는 NOT VERIFIED다.
|
||
- 로컬 Git 커밋은 보류한다. Git metadata 부재와 잔여 NOT VERIFIED 검토를 다음 단계에서 별도로 판단해야 한다. 이번에는 Git 작업을 수행하지 않았다.
|
||
|
||
## 작업 시간 (Asia/Seoul)
|
||
|
||
- Started At: 2026-10-10 00:14:14 KST
|
||
- Completed At: 2026-10-10 00:48:42 KST
|
||
- Actual Duration: 34분 28초
|
||
- Estimated Duration: 45–65분
|
||
- Variance: 예상보다 10분 32초–30분 32초 단축
|