11 KiB
P1 구조적 품질 복구 — 설계/실행 스펙
status: approved supersedes: (none) follows: 2026-07-10-p0-execution-integrity-design.md applies-to-version: company-haness @ fix/p0-execution-integrity date: 2026-07-10
배경 / 범위
P0(실행 무결성) 완료 후, 리뷰의 P1(#7–16, 구조적 품질) 10건을 적용한다. P1은 P0보다 파일이 얽혀
있고(여러 항목이 gen_agents.py·validate_report.py·guard_tools.py·commands·test_enforcement.py에 수렴),
3건(#7 wave/cascade 통합, #13 SSOT YAML 실행화, #14 acceptance-event 모델)은 아키텍처를 재구성하는 큰 작업이다.
따라서 한 번의 대량 병렬이 아니라 **트랜치(tranche)**로 나눠 실행한다.
공유 규칙 (모든 P1 work-package)
.claude/tests/test_enforcement.py는 편집 금지(공유 충돌점). 각 package는 자기 테스트를 새 파일(test_p1_<topic>.py)에 쓴다. 기존 assertion이 깨지면 정확히 어느 케이스가 왜 깨지는지 + 새 기대값을 보고만 하고, 오케스트레이터가 리뷰 단계에서 한 곳에서 반영한다.- CLAUDE.md/README.md 편집 금지. 트랜치 종료 시 오케스트레이터가 정직성 반영.
- git commit/branch 금지. workspace 필요 시
ORGOS_WORKSPACE=_sandbox. - P0 계약(report-header·evidence receipt·workspace 강제·context_package·70 agents)을 깨지 않는다. 끝에
doctor+ 전체 suite green 유지.
트랜치 맵
Tranche 1 (병렬-안전, 파일 소유 배타) — 지금
| WP | 결함 | 쓰는 파일(배타) |
|---|---|---|
| P1-A | #12 lens vs 전문성 | .claude/hooks/lens_cap.py, org-os/00-role-registry/lens-registry.yaml, .claude/tests/test_p1_lens.py(신규) |
| P1-B | #15 /consult 분기 + 렌더 열화표시 | .claude/commands/consult.md, .claude/hooks/render_consult.py, .claude/hooks/consult_exhibits.py, .claude/tests/test_p1_consult.py(신규) |
| P1-C | #16 디자인 파이프라인 discovery+검증 | .claude/commands/design-system.md, .claude/hooks/preview_ui.py, org-os/06-agent-work/design-brief-spec.yaml, .claude/tests/test_p1_design.py(신규) |
| P1-D | #10 audit Write + #9 primary-artifacts | .claude/hooks/gen_agents.py, org-os/00-role-registry/tool-permission-matrix.yaml, org-os/06-agent-work/context-package-spec.yaml, .claude/hooks/validate_report.py, .claude/schemas/, .claude/tests/test_p1_artifacts.py(신규), 생성물 .claude/agents/*.md |
주의: P1-A는 role-profiles.yaml을 편집하지 않는다(gen_agents가 읽음) — 서브스페셜티 축은 lens-registry.yaml에 둔다. P1-D만 gen_agents.py/validate_report.py/schemas를 만진다.
Tranche 2 (순차 — Tranche 1 이후)
| WP | 결함 | 소유 파일 | 의존 |
|---|---|---|---|
| P1-E | #11 guard default-deny 경계 | .claude/hooks/guard_tools.py, .claude/settings.json(permissions.deny/allow) |
tool-permission-matrix(P1-D 확정 후 read) |
| P1-F | #8 구현 루프 | .claude/commands/build.md, org-os/00-role-registry/role-working-methods.yaml(eng), .claude/skills/build-loop/(신규) |
gen_agents(P1-D) 후 재생성 |
| P1-G | #14 acceptance-event 모델 | new_report.py, .claude/hooks/acceptance_log.py(신규), report schema, completion-record status |
schema(P1-D) 후 |
Tranche 3 (아키텍처 — 설계 결정 후)
- #7 wave↔cascade 실행모델 통합: commands 전체 + collaboration-map/state-transition-rules/execution-policy. 비파괴 버전(두 흐름 유지하되 workflow-id/state 어휘 통일 + cascade=preset 문서화 + 리뷰가 짚은 모순 제거: README "항상 ceo-intake" vs 중간시작, collaboration-map에 GROUND 추가, divergent /decide의 결정 생성, anchoring)로 스코프.
- #13 SSOT YAML 실행화: template-driven validator/renderer, state-transition 검사기, scorecard 계산기 중 최고가치 1–2개만 우선. (전부는 별도 대공사.)
→ Tranche 3는 트랜치 1–2 종료 후, 오케스트레이터가 스코프/설계를 사용자에게 제시하고 진행.
Tranche 1 상세
P1-A — lens diversity ≠ domain coverage (#12)
현상: lens_cap.role_lenses()가 role별이 아니라 family lens를 모든 멤버에 복사 → 아키텍트 7명 모두 LENS-TECH로 간주 → standard tier에서 1명만 남고 나머지 전문분야가 삭제됨.
처방: lens 다양성과 domain/sub-specialty 커버리지를 별도 축으로. 같은 lens라도 서로 다른 sub-specialty role은 중복이 아니다(application vs system architecture, PM vs TPO, product vs platform design).
lens-registry.yaml에 sub-specialty 축 정책(같은 lens 내 distinct sub-specialty 허용 상한: light≤2, standard≤3, heavy=무제한 등 — 리뷰 취지에 맞게 선택) + 필요한 role→sub-specialty 매핑을 둔다(role-profiles는 건드리지 않음).lens_cap.py: "같은 lens 워커 2+ → 위반"을 "같은 lens AND 같은/미분화 sub-specialty → 위반; distinct sub-specialty는 tier 상한까지 허용"으로 교체. 진짜 중복(동일 role·미분화)만 잡고 전문분야 삭제를 멈춘다.- 기존
test_enforcement.py의 lens_cap 3케이스가 바뀔 수 있음 → 새 기대값을 보고만 하고test_p1_lens.py에 신규 케이스(아키텍트 7명 standard에서 통과, 동일 role 2회는 여전히 위반 등) 작성. 수용: 아키텍처 fan-out(7 distinct roles)이 standard에서 부당하게 1명으로 깎이지 않음; 진짜 중복은 여전히 차단.
P1-B — /consult 문서-컨설팅 분기 실제화 + 렌더 열화표시 (#15, +#16의 D2/Mermaid 부분)
현상: consult.md가 문서 컨설팅이면 FAM-DOC-CONSULT를 고른다고 설명만 하고, 실제 FRAME/ANALYZE/SYNTHESIZE 절차는 비즈니스 5분과로 하드코딩. 또 render_consult가 D2/Mermaid 렌더 실패 시 코드 텍스트를 넣은 SVG로 대체하면서 성공 처리(열화 은폐). 처방:
- consult.md: engagement 유형(business vs doc-consulting)에 따라
lead/workers/output-contract를 데이터로 분기. 문서 컨설팅이면 doc-lead + doc-writer/ia/visual/edu가 실제 FRAME/ANALYZE/SYNTHESIZE 각 단계에 배선되게(설명이 아니라 절차). 두 경로가 대칭이 되도록. render_consult.py(+필요 시consult_exhibits.py): D2/Mermaid(또는 exhibit) 렌더 실패 시 fallback-SVG를 쓰되 결과에 degraded 표시(파일명/메타/stderr 경고 + 비영점 신호 or 리포트 플래그)로 "성공"으로 위장하지 않는다.test_p1_consult.py: 문서-컨설팅 분기가 doc-family를 실제로 선택하는지(커맨드 파싱/구조 검증 수준) + 렌더 열화가 감지되는지.- 기존
test_enforcement.py의 render_consult 케이스가 깨지면 새 기대값 보고. 수용: 문서 리뷰 요청에서 writer/IA/visual/edu가 빠지지 않음; 렌더 열화가 조용히 성공으로 처리되지 않음.
P1-C — 디자인 파이프라인 discovery-first + 실질 검증 (#16)
현상: design-system.md가 React+CSS+Vite를 전사 고정으로 못박고 기존 stack/컴포넌트/브랜드/데이터밀도를 조사하지 않음. preview_ui.py는 build+PNG 존재만 확인(접근성/키보드/대비/반응형/상태/인터랙션/비주얼회귀/콘텐츠밀도/기존 시스템 정합 미검증). 처방:
- design-system.md: discovery → reuse/adapt/create 판단을 먼저. 기존 시스템 조사 단계 추가. 고정 Vite 경로는
greenfield-reactpreset으로 격하(기본이 아니라 옵션). 기존 프로젝트면 그 stack/토큰/컴포넌트를 우선 재사용. - preview_ui.py: 최소한 대비(contrast)·반응형 viewport(복수 width)·상태(loading/empty/error/overflow)·키보드 포커스 가시성 중 실현 가능한 자동 체크를 추가하고, build 실패/degraded를 성공으로 처리하지 않는다. 스크린샷 존재=품질 아님을 코드/문서로 명확히.
test_p1_design.py: preset framing·discovery 단계 존재, preview_ui의 신규 체크·fail-loud.- 기존
test_enforcement.py의 design-system/preview_ui 케이스가 깨지면 새 기대값 보고. 수용: 기존 프로젝트에서 stack 강제하지 않음; preview가 build/PNG 존재만으로 통과시키지 않음.
P1-D — audit-agent Write 권한 + primary-artifacts 분리 (#10, #9)
현상(#10): gen_agents의 TOOLS가 audit family(아키텍처/보안/QA/Legal/VPEng 13개)에 Read/Grep/Glob/Bash/WebFetch/WebSearch만 줘서 보고서를 쓰라면서 Write가 없음 → Bash redirection 우회(보고서 불변 guard 우회) 위험. 반대로 GTM/OPS엔 불필요한 Edit/Bash. tool-permission-matrix.yaml·frontmatter·guard가 서로 다른 정본.
현상(#9): 생성 worker가 산출물을 report 하나로 제한 → RFC/데이터모델/threat-model/API계약/실제코드 대신 보고서 안 몇 줄로 대체됨.
처방:
tool-permission-matrix.yaml을 tools의 단일 정본으로 삼고,gen_agents의 TOOLS 매핑을 거기서 파생(또는 정합). audit agent에Write부여(자기 보고서/설계 산출물 작성용) — 단 보고서 불변 guard는 유지(새 파일만). 불필요한 Edit/Bash 정리.primary-artifacts[]를completion-report와 분리: context-packageexpected-output과 report schema에primary-artifacts:[{path, kind, sha?, verification}]를 두고, 보고서는 실물의 경로·검증·리스크를 담는 envelope임을 gen_agents 본문 계약에 명시(“보고서 안 요약으로 실물을 대체하지 말 것”). build/design/spec 유형은 실물 아티팩트를 요구.validate_report.py: 해당 report-type이면primary-artifacts가 존재하고 각 path가 실존(가능하면 receipt/hash와 연계)하는지 검사(P0 receipt 로직과 정합, 시그니처 C3 유지)..claude/schemas/: primary-artifacts 필드 추가(공통/유형별).test_p1_artifacts.py: audit agent가 Write 보유, primary-artifacts 누락 시 build-type 차단, 경로 실존 검사.- gen_agents 개수 계약(70)·기존 본문 검증을 깨지 않게(라우터/워커/lead 구조 유지). 기존
test_enforcement.py의 gen_agents/tool 관련 케이스가 깨지면 새 기대값 보고. 수용: audit agent가 Bash 우회 없이 Write로 보고서·설계 산출; 실물 아티팩트가 report와 분리되어 요구·검증됨; tools 정본 일원화.
트랜치 종료 처리(오케스트레이터)
- 각 package 결과 리뷰(자기신고 아님 — 직접 재현).
- 깨진
test_enforcement.pyassertion을 보고된 새 기대값으로 한 곳에서 반영 + 전체 suite 재실행. doctor+ gen_agents --check(70) + lint_refs + 전체 테스트 green 유지.- CLAUDE.md/README 정직성 반영(트랜치별 변경 요약).
- settings.json 복원(P1 종료 시).