Files
company-haness/docs/superpowers/specs/2026-07-13-p2-design-direction-design.md

29 KiB
Raw Permalink Blame History

P2 — Design Direction 스테이지 설계

§1. 문제 (리뷰 2번째 핵심결함)

현재 /design-system 파이프라인은 design-brief 세우기 → tokens → components → screens → preview바로 들어간다. design-brief의 reference cluster가 탐색 없이 단번에 확정되고, 그 순간 시각 방향이 고착된다. 빠진 것:

  1. 방향 발산 부재 — 2~3개의 서로 다른 시각 방향을 실물로 세워 비교하는 단계가 없다. LLM은 단일 brief를 generic 평균("modern/clean")으로 채운다(design-craft 근거: vague prototyping = generic, NNGroup).
  2. 비평 게이트 부재 — generic·미분화 산출을 되돌리는 critique 루프가 없다. preview_ui는 기술 품질(렌더됨·대비·포커스)만 보고 방향의 독창성/일관성은 보지 않는다.
  3. 조기고착 방지 선행조건 부재 — "방향 승인 전 시스템 고착 금지"가 /design-system 진입에 강제되지 않는다.
  4. FAM-DESIGN에 리드 부재 — FAM-CONSULTING(CONSULT-EM)·FAM-DOC-CONSULT(DOC-LEAD)와 달리 FAM-DESIGN에는 발산을 프레이밍하고 수렴을 종합하는 lead-role-id가 없다.
  5. 입력 brief 자체가 조기고착의 원천 — reference cluster·색·typography·layout·token·visual metaphor가 이미 박힌 design brief를 발산의 입력으로 주면 "방향이 정해진 뒤 발산하는" 모순이 된다. 따라서 발산 이전 입력(direction-input-brief)과 승인 이후 시스템 입력(design-system-brief)을 분리해야 한다(§3).

cascade의 design 스테이지는 역할 관점 fan-out(PRD/RFC/data-model/threat-model)이라 시각 방향 발산은 그 안에 없다.

§2. 결정 요약

확정 문장: design-direction은 제품 cascade에 종속된 별도 named child plan이다. UI-bearing standard/heavy 작업에서 강제되며, 독립 발산·단일 방향 수렴·coded prototype·비평 재작업 루프를 state machine으로 보장한다. 승인 결과는 부모 workflow, 제품 결정, direction-input-brief hash에 바인딩되고 /design-system의 선행조건으로 사용된다.

접근법 A(별도 named plan, venture-bootstrap과 동형)를 택한 이유: 리뷰의 결함(탐색 없이 조기고착)을 구조로 막으려면 발산→수렴→비평이 강제 스테이지여야 한다. 게이트+커맨드만(C안)은 P1의 핵심 교훈("prose가 아니라 hook 강제")을 위반하고, cascade design 스테이지 내부 삽입(B안)은 단일 스테이지를 오염시키고 non-UI cascade에 죽은 하위단계를 남긴다.

정제 6종(사용자 승인): ①부모 workflow 바인딩(§3) ②namespaced 스테이지(§4) ③critique 실패 역전이(§4) ④divergence 3안 동일 대표화면 coded slice(§11) ⑤평균금지 스키마 강제(§6) ⑥/design-system 게이트 tier 한정+바인딩+staleness(§7).

4 구조수정(사용자 지시, 구현 계획 전 필수):

  • S1. brief 입력/출력 분리 — direction-input-brief(발산 이전) vs design-system-brief(승인 이후). 바인딩·staleness 앵커는 direction-input-brief-sha256(§3).
  • S2. approved-direction을 terminal로 — 스테이지별 산출물 재명명: decision→selected-direction, prototype→winner-prototype, critique→design-review, approved(terminal)→approved-direction. critique 통과 전엔 승인 아티팩트가 존재하지 않는다(§4/§5).
  • S3. 리뷰 패널(자기승인 차단) — critique는 다관점 패널이 평가, DES-DIRECTOR는 종합만. producer는 자기 방향의 필수 reviewer 불가(§5/§8/§9).
  • S4. 방향 독립성 격리 강제 — 3안은 각자 다른 producer-run-id + context-package로 격리 생산, 형제 산출물 must-read 금지(§9/§11).

§15 열린항목 결정: ①/design 자동 spawn + /design-direction 수동 유지(dedup) ②guard_tools 특수보호 없음(불변 report만) ③preview_ui --url-path 미확장(별도 갤러리 패키지) ④secondary-influence-id 제거→adopted-elements 원자 예외 최대1(§6).

§3. child-plan 바인딩 + brief 분리 (정제 ① + 구조수정 S1)

design-direction은 venture-bootstrap 같은 독립 lifecycle이 아니다. 특정 제품 결정에서 파생되는 자식 workflow다.

brief 분리 (S1) — 조기고착 재발 방지

direction-input-brief  →  design-direction  →  approved-direction  →  design-system-brief  →  design-system
  • direction-input-brief(발산 이전 입력): 제품 목표 · 핵심 사용자 · 핵심 작업 · 정보 밀도 · 필수 접근성 · 브랜드 제약 · 피해야 할 클리셰 · 대표 화면 요구 · 기술·플랫폼 제약.
    • 포함 금지(넣으면 lint Hard Fail): 최종 reference cluster · 확정 색상 팔레트 · 확정 typography · 확정 layout grammar · 확정 token · 선택된 visual metaphor. (이게 있으면 발산 전에 방향이 고착됨.)
  • design-system-brief(승인 이후, 기존 design-brief-spec.yaml의 design-brief 역할): 입력 = direction-input-brief-ref + approved-direction-ref/sha256. reference cluster·색·typography·token은 여기서 승인된 방향으로부터 확정(발명 아님). design-brief-spec.yamlbrief-phase: system-ready와 approved-direction 인용 필드를 추가.

바인딩 메타 (child 원장 state/<wf>/workflow.yaml)

plan: design-direction
parent-workflow-id: product-cascade-001    # 필수 — 부모 제품 cascade wf-id
product-decision-id: PD-001                # 필수 — 부모 decide 산출(ExecutiveDecisionPacket) id
company-context-ref: org-os/01-company/company-context.yaml
direction-input-brief-ref: <path>          # 발산 입력(design-brief 아님)
direction-input-brief-sha256: <hash>       # staleness 앵커 (§7)
  • 바인딩이 없으면 한 제품 방향을 다른 제품/오래된 brief에 재사용할 수 있다 — P1의 company↔product seam과 동형.
  • state_engine.py init--parent-workflow, --product-decision, --direction-input-brief 인자. 미지정 시 design-direction init 거부(BlockedReport). parent wf-id는 실존 원장, product-decision-id는 부모 원장의 accepted decision-packet과 대조.

부모 원장의 child 등록 (dedup 근거, §10)

child-workflows:
  design-direction:
    workflow-id: product-001-direction-01
    input-brief-sha256: ...
    status: running | approved | stale

§4. 스테이지 그래프 (정제 ②③ + 구조수정 S2)

스테이지 (전역 그래프 충돌 방지 위해 전부 접두어)

design-direction-intake
design-direction-discovery
design-direction-divergence
design-direction-decision
design-direction-prototype
design-direction-critique
design-direction-finalize
design-direction-approved      # terminal

unified-stage-graph에 위 8개 추가(venture-bootstrap 스테이지 추가와 동형). intake도 일반 cascade intake와 구분. critique pass 직후 바로 approved로 가지 않고 finalize를 하나 더 거친다 — approved-direction 불변 report 작성과 부모 원장 등록(§10)이라는, critique 자체와는 다른 책임을 별도 stage로 분리해 "패널 통과"와 "최종 확정·부모 바인딩"을 섞지 않기 위함이다.

스테이지별 산출물 이름 (S2 — 의미와 상태 일치)

스테이지 산출 아티팩트
divergence direction-set(3안, 각 격리 생산)
decision selected-direction(1안 선택 + rejected + locked-invariants, 사람 선택)
prototype winner-prototype(승자 핵심흐름 coded)
critique design-review-panel(다관점 verdict + 종합)
finalize approved-direction(불변 report — 위 전부를 hash로 묶음) + 부모 원장 design-direction-approval 등록
approved(terminal) (신규 아티팩트 없음 — finalize 산출물의 유효성·해시·바인딩이 8점 검증을 통과했음을 표시하는 종료 상태)

critique 통과 에는 approved-direction이 존재하지 않는다(finalize에서 비로소 작성된다). selected-direction은 "선택"이지 "승인"이 아니다.

전이 (선형 아님 — critique 실패 역전이 포함, 전부 allowed-by: [OPS-ORCH])

intake      → discovery      : parent-binding-present
discovery   → divergence     : direction-input-brief-valid          (S1 포함금지 통과)
divergence  → decision       : directions-diverged                  (§9 독립성 6검사)
decision    → prototype      : selected-direction-accepted          (1안 선택 + 사람 acceptance)
prototype   → critique       : winner-prototype-present
critique    → prototype      : critique-revision-requested          (역전이: minor revision)
critique    → divergence     : concept-rejection-recorded           (역전이: concept flaw)
critique    → finalize       : direction-critique-passed            (패널 pass + winner preview_ui receipt)
finalize    → approved       : approved-direction-valid + approval-receipt-bound
                                + parent-approval-link-recorded      (report 확정+hash 일치 + acceptance receipt 바인딩 + 부모 원장 등록)

전이 9종(순방향 7 + 역전이 2).

        ┌──────────────── concept-rejection-recorded ───────────────┐
        ↓                                                           │
  -divergence → -decision → -prototype → -critique ── pass ──→ -finalize → -approved
                              ↑              │
                              └── minor rev ─┘

§5. 아티팩트/스키마 (4종)

계약 파일: org-os/06-agent-work/design-direction-spec.yaml(4 아티팩트 함께 정의) + JSON Schema(validator 소비).

(a) direction-set (-divergence 산출)

direction-set:
  representative-screen:              # 3안이 공유하는 동일 대표 화면 (비교 가능성 핵심)
    id: SCREEN-CORE-TASK
    kind: first-entry | core-task | signature-moment    # 버튼/카드 갤러리 금지
    description: ...
  directions:
    - id: DIR-001
      producer-role-id: DES-VISUAL
      producer-run-id: RUN-001        # 격리 생산 증거 (S4)
      context-package-id: PKG-001
      concept-artifact: ...
      reference-cluster:              # 6집중, 각 '나르는 신호'(형용사 금지)
        - { name: ..., signal: ..., why-relevant: ... }
      visual-thesis: ...
      layout-grammar: ...
      interaction-grammar: ...
      typography-token-direction: ...
      coded-slice: <path>             # representative-screen 구현 경량 slice
      render-manifest: <ref>          # 갤러리 렌더 receipt 참조

(b) selected-direction (-decision 산출 — 사람 선택, 아직 승인 아님)

selected-direction:
  selected-direction-id: DIR-002      # 정확히 1개
  rejected-directions:                # 모든 비선택에 reason 필수
    - { id: DIR-001, reason: ... }
    - { id: DIR-003, reason: ... }
  locked-invariants: [...]            # 최소 3개
  flexible-elements: [...]
  adopted-elements:                   # optional, 최대 1개 (§6 — 원자 예외, secondary 대체)
    - from-direction-id: DIR-001
      element-id: typography-scale
      description: "본문 크기 비율만 채택"
      rationale: "고밀도 데이터 화면 판독성 우수"
      affected-invariants: []
  parent-workflow-id: ...
  product-decision-id: ...
  direction-input-brief-sha256: ...
  selection-acceptance-receipt: ...   # 사람 선택 acceptance

(c) design-review-panel (-critique 산출 — 다관점, S3)

design-review-panel:
  target-prototype: <path>
  preview-receipt: <ref>              # winner 프로토타입 실제 렌더 preview_ui receipt
  reviews:
    - { reviewer-role-id: DES-PROD,        reviewer-run-id: ..., lens: product-fit,      verdict: pass, report-ref: ..., report-sha256: ... }
    - { reviewer-role-id: UX-RESEARCHER,   reviewer-run-id: ..., lens: usability,        verdict: ..., ... }
    - { reviewer-role-id: DES-VISUAL,      reviewer-run-id: ..., lens: distinctiveness,  verdict: ..., ... }   # producer-run-id와 상이해야
    - { reviewer-role-id: DES-PLATFORM,    reviewer-run-id: ..., lens: systematizability, verdict: ..., ... }
    - { reviewer-role-id: GTM-PMM,         reviewer-run-id: ..., lens: market-memorability, verdict: ..., ... }
    - { reviewer-role-id: ENG-FE,          reviewer-run-id: ..., lens: implementability,  verdict: ..., ... }
  synthesis:
    role-id: DES-DIRECTOR
    verdict: pass | minor-revision | concept-flaw
    unresolved-dissent: []

distinctiveness/generic-risk 판정 기준(reference-signal-fidelity, generic-adjective-risk="modern/clean"이면 weak, layout-information-hierarchy, token-consistency)은 각 reviewer가 관찰+근거로 기록(자기채점 금지). synthesis.verdict가 §4 역전이 구동.

(d) approved-direction (-finalize 산출 — 불변 report, S2)

-critique pass 직후의 -finalize stage에서 작성된다(terminal인 -approved가 만드는 것이 아니다 — -approved는 이 report의 유효성·hash·acceptance receipt·부모 원장 등록이 전부 확인된 뒤 도달하는 종료 상태). 경로: <workspace>/completion-records/<child-workflow-id>/approved-direction-<timestamp>.report.yaml(불변 report, guard 특수보호 불요).

approved-direction:
  selected-direction-ref: ...
  selected-direction-sha256: ...
  final-prototype-ref: ...
  final-prototype-sha256: ...
  critique-report-refs: [...]
  critique-pass-receipt: ...
  locked-invariants: [...]
  approved-at: ...
  parent-workflow-id: ...
  product-decision-id: ...
  direction-input-brief-sha256: ...

부모 원장엔 파일 복사 없이 hash-bound 참조만:

design-direction-approval:
  report-ref: ...
  report-sha256: ...
  child-workflow-id: ...

JSON Schema

.claude/schemas/에 selected-direction·design-review-panel·approved-direction schema. (direction-set는 lint가 검사.)

§6. 평균 금지 = 스키마 강제 (정제 ⑤ + secondary 제거)

hook은 시각적 독창성은 판정 못 하나 "선택 대신 평균내는 구조적 실패"는 차단한다. lint_design_direction.py(=lint_company_context.py 형제)의 Hard Fail:

  • selected-direction-id 정확히 1개(0·복수 = Hard Fail), direction-set 실존 id.
  • 모든 비선택(rejected)에 reason 필수(빈 사유 = Hard Fail).
  • locked-invariants ≥ 3.
  • rejected {selected} = direction-set 모든 id(누락·유령 id = Hard Fail).
  • secondary-influence-id 필드가 있으면 Hard Fail(제거됨 — 평균의 뒷문).
  • adopted-elements: 최대 1개. element-id 필수, rationale 필수. selected의 locked-invariants를 침범하면 Hard Fail. "분위기/감성/스타일" 같은 포괄 표현이면 Hard Fail(원자적 element-id만 허용).

Warning: reference-cluster가 형용사만("modern/clean/minimal/sleek") → generic-risk 경고. direction-input-brief에 §3 포함금지 항목이 있으면 Hard Fail(발산 전 고착 방지).

§7. /design-system 게이트 (정제 ⑥ + 구조수정 gate)

tier 어휘 정합: 사용자 "standard/high" = 하네스 standard/heavy(governance-tiers High: heavy).

UI-bearing 판정 (proxy 아님 — 명시 필드 우선)

부모 decision-brief(ceo-intake 산출)에 명시 필드:

deliverable-profile:
  ui-bearing: true
  ui-kind: product | admin | internal-tool
  governance-tier: standard

판정 우선순위: ① decision-brief ui-bearing 명시값 → ② 산출물 타입/요구에서 파생 → ③ FAM-ENG-FRONTEND 포함 여부(fallback). 누락 + standard/heavy + UI 가능성 있으면 warning 또는 fail-closed(안전측).

게이트

UI-bearing && tier ∈ {standard, heavy} → design-direction-approved 필수 → 없으면 Hard Fail(BlockedReport)
UI-bearing && tier = light             → Warning + 기존 승인 방향 있으면 반드시 상속
non-UI                                  → N/A (child plan 생성 안 함)

direction-approved는 boolean 아님 — 바인딩 검사

state_engine._has_direction_approval(wf)(= _has_preview_receipt 형제)가 부모 원장의 design-direction-approval 참조를 따라가 확인:

  1. approved-direction 불변 report 존재(completion-records 경로)
  2. schema/validator(lint_design_direction) 통과
  3. acceptance receipt 존재(acceptance_log accepted, report-sha256 바인딩 — P1 hash 바인딩 재사용)
  4. report hash 일치(receipt report-sha256 == 실제 파일 hash — 수정 시 mismatch)
  5. parent-workflow-id 일치
  6. product-decision-id 일치(부모 accepted decision-packet)
  7. direction-input-brief-sha256 일치
  8. critique pass receipt 존재(design-review-panel synthesis=pass + winner preview_ui receipt)

staleness (자동 무효화)

current direction-input-brief-sha256 (실측) != approved.direction-input-brief-sha256 → 승인 무효

매 평가 시 현재 direction-input-brief 파일 hash 재계산 대조(P1 company-context-lint live 평가와 동형). product-decision supersede 시도 무효.

§8. 역할 신설 + 리뷰 패널 (구조수정 S3)

  • DES-DIRECTOR: FAM-DESIGN lead-role-id(synthesis-lead). 발산 프레이밍(discovery→direction-input-brief 정련) + 3안 원본 종합 수렴(decision) + critique 종합(단독 평가자 아님). CONSULT-EM/DOC-LEAD 동형.
  • DES-VISUAL: FAM-DESIGN fan-out 워커. 방향별 아트디렉션(각 방향 격리 생산, §11).

리뷰 패널(critique 평가자 — DES-DIRECTOR는 종합만):

lens 역할
제품 흐름·핵심 작업 (product-fit) DES-PROD
사용성·인지부하 (usability) UX-RESEARCHER
시각적 독창성·일관성 (distinctiveness) DES-VISUAL(생산 안 한 별도 run)
시스템화 가능성 (systematizability) DES-PLATFORM
시장 전달·기억성 (market-memorability) GTM-PMM
구현 손실·기술 가능성 (implementability) ENG-FE(FAM-ENG-FRONTEND)
최종 종합 DES-DIRECTOR

패널 pass 조건(구조화): 필수 reviewer lens 전부 존재 · producer-run-id ≠ 각 reviewer-run-id(생산자가 자기 방향 필수 reviewer 불가) · critical blocker 없음 · 각 review report hash 검증 · DES-DIRECTOR synthesis 존재.

변경 파일: roles.yaml(+2), role-profiles.yaml, role-working-methods.yaml(design-craft 근거 embed), capability-families.yaml(FAM-DESIGN member-role-ids += [DES-DIRECTOR, DES-VISUAL], lead-role-id: DES-DIRECTOR) → gen_agents.py 재생성. roles 73→75, family 28·lens 12 불변.

§9. 강제기 / predicate

state_engine.py (신설)

  • predicate: parent-binding-present, direction-input-brief-valid, directions-diverged, selected-direction-accepted, winner-prototype-present, critique-revision-requested, concept-rejection-recorded, direction-critique-passed, direction-approved(복합 §7).
  • helper:
    • _directions_diverged(wf)S4 독립성 6검사: ① direction ≥ 3 ② producer-run-id 전부 상이 ③ context-package-id 전부 상이 ④ 각 worker의 must-read에 형제 direction 산출물 없음 ⑤ 동일 representative-screen ⑥ 각 coded-slice + render-manifest 존재.
    • _selected_direction_ok(wf)(lint 통과 + 평균금지 + adopted-elements 규칙).
    • _critique_panel_ok(wf)(§8 패널 pass 조건 — producer≠reviewer run-id 포함).
    • _has_direction_approval(wf)(§7 8검사 + staleness).
    • _current_input_brief_sha(ref).
  • _PROTECTED_FACTS에 신규 fact 키 전부 추가(자기신고 차단 — P1 동일).
  • CLI: state_engine.py check-direction-approved --workflow WF(advisory 조회, /design-system·/design 진입이 호출).

lint_design_direction.py (신설)

lint_file(path, kind) -> (hard_fails, warnings). §6(selected-direction 평균금지) + direction-input-brief 포함금지(§3) + direction-set 구조 강제. run_all·doctor 배선.

collaboration-map.yaml (수정)

design-to-build-contractdirection-gate 추가(design-system-gate 형제):

direction-gate:
  requires: design-direction-approved
  enforced-by: state_engine._has_direction_approval
  applies-to: [FAM-ENG-FRONTEND]
  hard-if: tier in [standard, heavy]   # light: warning + 상속

must-read-designs(FAM-ENG-FRONTEND)에 approved-direction을 선행으로 추가(design-system preview receipt와 함께).

guard_tools.py — 변경 없음 (§15 결정 ②)

approved-direction은 기존 immutable report 경로에 생성, 부모 원장엔 hash-bound reference만. 별도 mutable canonical 파일을 두지 않으므로 특수 직접쓰기 보호 불요. 일반 report immutability로 충분.

§10. 커맨드

/design (수정 — 자동 spawn + dedup, §15 결정 ①)

UI-bearing && tier ∈ {standard, heavy} 판정(§7 우선순위) → 유효 child 없으면 자동 init/spawn → /design-direction 절차 실행 → child approved까지 부모 design 전이 대기. dedup(중복 생성 방지): (parent-workflow-id + product-decision-id + direction-input-brief-sha256)로 기존 child 검색 —

  • 일치 & running → resume
  • 일치 & approved → 재사용
  • hash 상이 → stale 처리 후 신규 child 생성 사용자가 /design을 돌렸는데 나중에 /design-system에서 갑자기 막히지 않도록, 방향 탐색이 필요한 순간(/design)에 child를 자동 시작.

/design-direction (신설 — 수동 진입점 유지)

용도: 독립 실행 · 중단 후 resume · critique 실패 후 재진입 · stale 승인 재생성 · child 복구/디버깅. 인자 --parent-workflow --product-decision --direction-input-brief. 각 스테이지 종료 시 state_engine transition, 산출 시 record + acceptance_log append accepted(P1 deadlock 교훈 — 커맨드 본문에 명시).

/design-review (신설)

critique 패널 실행(§8). 프로토타입 대상 다관점 verdict 산출. -critique에서 호출되거나 임의 프로토타입에 독립 실행.

/design-system (수정)

진입 선행조건에 check-direction-approved. UI+standard/heavy면 승인 없을 시 BlockedReport, light면 경고+상속. 입력 brief = design-system-brief(approved-direction 인용, §3).

§11. divergence 충실도 + 독립성 (정제 ④ + 구조수정 S4 + Q2)

  • 각 방향 = concept artifact · reference cluster(6집중) · visual thesis · layout/interaction grammar · typography/token direction · signature interaction · 대표 화면 1개 경량 coded slice.
  • 대표 화면 = 첫 진입 / 핵심 작업 / signature moment 중 하나. 버튼·카드 수준 금지. 3안 모두 동일 대표 화면(representative-screen.id 공유, lint 강제).
  • 독립 생산(S4): 3안은 각자 다른 producer-run-id + context-package-id로 격리 실행. 각 worker의 must-read에 형제 direction 산출물 금지(한 에이전트가 A/B/C를 한 번에 쓰면 표면만 다른 동일 사고 — _directions_diverged가 거부).
  • 비교 렌더(§15 결정 ③): 3 slice를 별도 Vite 갤러리 패키지의 root(ComparisonGallery)로 묶어 기존 preview_ui.py로 root 1회 렌더 → 3-way PNG(receipt). --url-path 확장 없이 최단·재현성. _directions_diverged가 이 render-manifest 요구.
design-direction-preview/
  src/{DirectionA,DirectionB,DirectionC,ComparisonGallery}.jsx
  App.jsx   # ComparisonGallery를 root에서 렌더
  • 수렴 후 -prototype: 승자 방향 핵심 사용자 흐름 전체 coded → -critique(preview_ui + design-review-panel). 통과 후에야 /design-system이 그 방향으로 재사용 토큰+컴포넌트 확장.

§12. 하네스 정합성 영향

  • 카운트: roles 73→75(실측). family 28·lens 12 불변. FAM-DESIGN lead-role-id 획득 → gen_agents가 DES-DIRECTOR synthesis-lead + DES-VISUAL 워커 생성. 갱신할 구체 단언:
    • test_enforcement.py:722 role-working-methods covers 73 roles75.
    • FAM-DESIGN member-role-ids 카운트 단언(있으면) 3→5.
    • gen_agents agent 총수 단언(doctor·test 있으면) 신규 2 반영.
  • gen_agents.py 재생성 필수. .claude/agents/*.md는 생성물 — 수기편집 금지.
  • doctor.py: check_design_direction_wiring 신설 — 스키마 존재, lint 배선, DES-* 등록, 커맨드→에이전트 참조 무결성.
  • execution-plans.yaml: design-direction plan(§4 스테이지 + 바인딩). state-transition-rules.yaml: 전이 8종 + condition-catalog.
  • design-brief-spec.yaml: brief-phase: pre-direction | system-ready + approved-direction 인용 필드 추가(design-system-brief가 승인 방향 소비).
  • 기존 불변식 유지: report immutability, evidence 등급, 권한(외부 side-effect 기본금지; npm/chrome 로컬빌드 허용), design-brief 없이 컴포넌트 생성 금지.

§13. 테스트 (test_design_direction.py 신설, standalone check() 규약)

기본 8종: ①평균금지 negative(selected 0/2개, rejected reason 누락, locked<3) ②평균금지 positive ③staleness(input-brief sha 불일치→승인 무효) ④바인딩 검사(parent/product-decision 불일치, critique·preview receipt 없음) ⑤게이트 tier 분기(UI+standard 승인없음→Hard Fail; UI+light→Warning; non-UI→N/A) ⑥critique 역전이(minor-revision→prototype, concept-flaw→divergence, pass→approved) ⑦directions-diverged(3안 미만·대표화면 불일치·render-manifest 없음→거부) ⑧바인딩 부재 init 거부.

추가 11종(구조수정 검증): 9. 동일 producer-run-id가 3안 생산 → divergence 거부. 10. DES-VISUAL producer가 자기 방향 필수 reviewer → critique 거부. 11. selected-direction만 있고 최종 approved-direction 없음 → /design-system 거부. 12. critique 전 생성된 approval artifact → 승인으로 불인정. 13. direction-input-brief hash 변경 → child·approval 모두 stale. 14. /design 재실행 시 같은 binding child 중복 spawn 안 하고 resume. 15. 승인 immutable report 수정 → hash mismatch로 게이트 거부. 16. secondary-influence-id가 스키마에 들어오면 거부. 17. adopted-elements 허용량 초과·locked-invariant 침범 → 거부. 18. ui-bearing=true + standard/heavy인데 child 없음 → /design 자동 생성. 19. ui-bearing=false → child plan 생성 안 함.

§14. 비목표 (YAGNI)

  • 시각적 독창성 자동 정량 판정(hook이 미적 채점) — hook은 구조적 평균금지·바인딩·격리·렌더 receipt만 강제, 미적 판단은 패널/사람.
  • 3안 각각 풀 프로토타입 — divergence는 동일 대표화면 slice만, 풀은 승자만.
  • preview_ui --url-path 다중 route 순회 — 별도 갤러리 패키지로 대체(실제 요구 생기면 후속).
  • Figma MCP·비주얼 회귀 스냅샷 diff — 후속.
  • 제품 cascade 밖(마케팅 사이트 등) 적용 — 우선 제품 child로 검증 후.

§15. 열린항목 — 결정 완료

  1. 자동 spawn + 수동 유지: /design이 UI+standard/heavy에서 child 자동 init/spawn(dedup), /design-direction은 독립·resume·재진입·재생성·복구용 수동 진입점 유지(§10).
  2. guard_tools 특수보호 없음: approved-direction은 immutable report 경로에 생성, 부모 원장엔 hash-bound reference만. mutable canonical 파일 없음 → 일반 report immutability로 충분(§9).
  3. preview_ui 미확장: 비교 갤러리를 별도 Vite 패키지 root로, 기존 preview_ui root 1회 렌더(§11).
  4. secondary-influence-id 제거: 평균의 뒷문. 대신 원자적 adopted-elements 최대 1개(element-id+rationale 필수, locked-invariant 침범·포괄표현 금지, §6).

§16. 구현 체크리스트

  • design-direction-spec.yaml(direction-set/selected-direction/design-review-panel/approved-direction + direction-input-brief) + 3 JSON Schema
  • design-brief-spec.yaml에 brief-phase + approved-direction 인용(design-system-brief 분리)
  • roles/role-profiles/role-working-methods/capability-families에 DES-DIRECTOR(lead)+DES-VISUAL → gen_agents 재생성
  • execution-plans.yaml design-direction plan(namespaced 스테이지 + 바인딩)
  • state-transition-rules.yaml 전이 8종(역전이 2) + condition-catalog
  • state_engine.py predicate/helper(독립성 6검사·패널·8검사·staleness)/_PROTECTED_FACTS/CLI + init 바인딩 인자
  • lint_design_direction.py(평균금지·포함금지 Hard Fail) + run_all/doctor 배선
  • collaboration-map.yaml direction-gate + must-read
  • /design(자동 spawn+dedup) · /design-direction · /design-review · /design-system 선행조건
  • test_design_direction.py(19종) + 카운트 단언 갱신(test_enforcement:722 →75) + doctor check
  • 전체 green(run_all) + doctor OK