Files
company-haness/docs/superpowers/specs/2026-07-11-cascade-design-integration-and-orchestrator-design.md
T

69 lines
7.9 KiB
Markdown

# Cascade 디자인 통합 + End-to-End 오케스트레이터 설계
- 날짜: 2026-07-11
- 상태: **구현 완료** — state_engine `next`+`_has_preview_receipt`, `/design` UI-bearing 분기, `/run-cascade`, collaboration-map `design-system-gate`, 테스트 `test_p2_cascade_design.py`(19)·`test_p2_orchestrator.py`(34). run_all 17/17 green.
- 근거 리뷰: "훅을 고치면 *안전한* 하네스가 될 뿐, 품질엔 (3)cascade에 통합된 디자인, (4)end-to-end 오케스트레이터, (5)골든태스크 실증이 더 필요하다."
- 선행: P0 신뢰경계 하드닝(커밋 51d101d). 이 설계는 그 위에서 **품질** 층을 얹는다.
- 실증(항목5) 결과: `benchmark/BENCHMARK.md` — low 난이도 code-bugfix(GT-01·GT-R2)에서 plain==harness(둘 다 만점). 하네스 lift는 *단순 과제*가 아니라 **모호·다관점·교차 작업**(design/decision/feature)에서 나온다는 가설을 강화. 이 설계(3·4)는 바로 그 경로를 실물로 만든다.
## 문제 (코드로 확인된 사실)
### 항목 3 — 디자인이 cascade 밖에 있다
- `/design`(DESIGN stage)은 설계 **문서**만 fan-out한다(`fam-architecture-tech`·`fam-design`·`fam-data`·`fam-security`). `fam-design`은 "UX/UI·디자인시스템"을 개념적으로 다루고 design-brief를 채우지만, **코드 디자인 시스템 파이프라인**(discovery→tokens.css→components→screens→`preview_ui` 렌더·품질게이트)을 돌리지 않는다.
- `/design-system`은 그 렌더 산출물을 만드는 **독립 커맨드**로, cascade에서 호출되지 않는다.
- `collaboration-map.yaml``design-to-build-contract``FAM-ENG-FRONTEND`의 must-read-designs로 **`design-system`**을 이미 요구한다(Accepted 전 프론트 BUILD 금지). 그런데 그 `design-system` 산출물을 **생산·게이팅하는 cascade stage가 없다** → 계약과 생산의 미스매치. 결과: 프론트 기능이 *설계문서 → spec → build*로 흐르는 동안 **실제 렌더된 화면**(상태 loading/empty/error/overflow·반응형·대비·포커스)을 한 번도 검증하지 않을 수 있다("docs는 있는데 pixels는 없다").
### 항목 4 — 상위 end-to-end 오케스트레이터가 없다
- `/ceo-intake`·`/ground`·`/decide`·`/design`·`/spec`·`/build`가 전부 **사람이 수동 호출**하는 개별 커맨드다. `state_engine`이 stage 순서를 강제하지만(예: 설계 Accepted 없으면 `/build` 거부), **다음 커맨드를 반드시 호출하게 만드는 것은 없다** — 사람이 `/design` 후 멈추고 하네스 밖에서 코딩해버릴 수 있다. 전 과정을 일관되게 걷고 사람 결정 지점에서만 멈추는 단일 진입점이 없다.
## 설계
### 항목 3 — 디자인 파이프라인의 **조건부** cascade 통합
**원칙: 조건부 게이팅.** 모든 cascade가 UI를 만들지 않는다. 백엔드/인프라/데이터/의사결정 워크플로에 design-system을 강제하면 과설계다. UI를 만드는 워크플로에서만 렌더 게이트를 요구한다.
1. **UI-bearing 술어.** 워크플로가 UI-bearing = 그 BUILD 계획에 `FAM-ENG-FRONTEND`가 포함(사용자 대면 UI). 이는 `design-to-build-contract`가 이미 인코딩한 것(FAM-ENG-FRONTEND→design-system)과 동치다. DECIDE에서 `ExecutiveDecisionPacket``ui-bearing: true|false`를 명시하거나, 계획된 build family에서 파생한다.
2. **UI-bearing이면 DESIGN이 렌더 산출물을 생산.** `/design``fam-design` 분기는 design-system 서브파이프라인(=`/design-system` 절차: discovery→design-brief→tokens/components/screens→`preview_ui` 게이트)을 돌리고 **`design-type: design-system` 산출물**을 낸다. 그 **acceptance는 통과한 `preview_ui` receipt(E4/E5)**를 요구한다 — 산문 문서가 아니라 렌더 증거(#root 비어있지 않음·WCAG 대비 ok·포커스 가시·반응형 스냅샷).
3. **state_engine 강제.** `design-system` 산출물의 acceptance가 must-read-designs-accepted에 카운트되려면 evidence-ledger에 **preview_ui receipt(E4/E5)**가 결속돼야 한다 — 렌더된 적 없는 design-system을 "Accepted"로 위장 불가. non-UI 워크플로는 FAM-ENG-FRONTEND 매핑이 적용 안 되므로 design-system 불요(과차단 없음).
4. **기계를 새로 만들지 않고 배선.**
- `/design` 커맨드: "UI-bearing이면 design-system 서브파이프라인이 DESIGN의 일부 — preview_ui로 게이팅된 `design-system` 산출물을 낸다. `/design-system` 절차를 따른다" 조건부 섹션 추가.
- `collaboration-map.yaml`: `design-system`(FAM-ENG-FRONTEND)이 preview_ui 게이트(E4/E5)를 요구함을 명시.
- `state_engine.py`: `design-system` design-type의 accepted 카운트에 preview_ui receipt 결속 요건 추가(없으면 must-read 충족으로 안 침).
- `/design-system`은 독립 호출도 유지(하위호환) — `/design`이 UI 서브파이프라인으로 참조.
**비목표:** 백엔드/인프라/의사결정 워크플로에 design-system 강제 금지. 모든 cascade에 `/design-system` 필수화 금지.
### 항목 4 — 얇은 오케스트레이터 `/run-cascade`
**원칙: 기존 state graph 위의 얇은 드라이버.** 평행 엔진을 새로 만들지 않고 `state_engine`을 재사용한다. **사람 게이트에서 멈추는 것이 존재 이유** — 절대 자동 승인/자동 완주하지 않는다.
1. **`state_engine.py next --workflow <wf>`** — 신규 결정론적 서브커맨드. 반환:
- `current-stage`, `next-stage`(execution-plans cascade 그래프에서),
- `guard`: next-stage 진입 게이트 결과(pass / block + 사유) — 기존 `can_transition` 재사용,
- `human-gate: true|false` + `what` + `approver` — governance-tiers human-gate + DRAI decider=human + DECIDE(go/no-go) + release에서 파생,
- `command`: next-stage에 대응하는 커맨드(`/ground`·`/decide`·`/design`·`/spec`·`/build`·…)와 spawn할 families.
2. **`/run-cascade` 커맨드** = Orchestrator가 따르는 얇은 루프:
- `state_engine.py next` 호출.
- `guard`가 block → 미충족 선행조건을 담은 **BlockedReport** + **정지**.
- `human-gate` → decision-needed 보고(BLUF: 무슨 결정·승인자·근거) + **정지**(진행 금지). 사람이 승인(acceptance_log/signoff)한 뒤 `/run-cascade` 재호출로 재개.
- 아니면 → 해당 stage 커맨드 절차를 따른다(그 stage의 families만 fan-out) → 산출물 → `transition`으로 전진 → 루프.
- `released`에서 종료.
3. **불변식(반드시):**
- state_engine guard/transition 재사용 — 평행 엔진 금지.
- 사람 게이트 자동 승인 금지(멈추는 것이 목적).
- 각 stage는 여전히 자기 context-package spawn 게이트·validator·token/lens 게이트를 통과.
- resumable: `next`가 현재 state를 읽으므로, 사람 승인 후 재호출하면 멈춘 지점부터 계속(mid-start).
**정지 지점(사람 게이트):** DECIDE(go/no-go)·tier=heavy plan-signoff·Release acceptance(DRAI decider=human)·guard가 block하는 모든 stage.
## 테스트 계획
- `test_p2_cascade_design.py`(신규): (a) UI-bearing 워크플로에서 design-system 없이 spec→build guard가 block, (b) preview_ui receipt 없는 design-system accepted는 must-read 충족으로 안 침, (c) non-UI 워크플로는 design-system 불요로 통과.
- `test_p2_orchestrator.py`(신규): (a) `state_engine.py next`가 current/next/guard/human-gate/command를 정확히 반환, (b) DECIDE·release에서 human-gate=true, (c) guard block 시 next가 block 사유 노출, (d) 재호출 resumable.
- 회귀: `run_all.py`(doctor+lint_refs+모든 test_*) 그린 유지, `gen_agents.py --check` 정합.
## 롤아웃
1. 항목5 벤치마크 실증(완료 — BENCHMARK.md).
2. state_engine `next` + preview_ui-gated design-system 강제(코어).
3. `/run-cascade`·`/design` 커맨드 배선(프롬프트 층).
4. 테스트 + doctor/lint_refs/run_all 그린 + 커밋.