Files
llm-wiki/docs/superpowers/specs/2026-06-01-branch-depth-gate-design.md

160 lines
13 KiB
Markdown

# Design: branch-depth-gate — 브랜치 노트 구현 착수 깊이 게이트
- 날짜: 2026-06-01
- 대상: `rules/`, `.claude/agents/`, `.claude/commands/`, `templates/branch-note-template.md`
- 부모 SSOT: 본 게이트는 *방법론 규칙*이므로 `rules/` 층에 속한다. 프로젝트 내용(`raw/project-notes/ca-skeleton-operational-contract.md`)이 아니다.
- 목적: branch-note 가 **"코딩 착수해도 되묻지 않을 만큼 깊은가"** 를 착수 *전에* 판정하는 read-only 게이트를 도입. 현재의 "착수 → 의구심 → 되돌아가 4~5회 재작업" 루프를 "착수 전 1회 가이드 루프"로 압축한다.
---
## 0. 문제 (P2)
`raw/branch-notes/` 에 80개의 `feature-*` 노트가 있다. 사용자는 한 브랜치를 실제 구현하기 전에 평균 4~5회 노트를 다듬어야 "의구심 없이" 개발에 들어갈 수 있다. 재작업을 유발하는 의구심은 네 축 **전부**에서 발생한다(사용자 확인):
1. **조사 깊이 부족** — 공식문서/기술블로그 조사가 질문에 실제론 답하지 못함(존재만 확인, 메커니즘 미확인).
2. **결정 조건 누락** — "A vs B"는 적혀 있으나 "언제 A, 언제 B"의 선택 기준이 없음.
3. **구체 detail 미정** — 명명·경로·메커니즘·테스트명이 비어 구현 중 임의 결정 발생.
4. **엣지·실패·의존 미열거** — 정상 경로만 있고 실패/엣지/다른 계약 의존이 빠짐.
근본 원인 (둘):
1. branch-note-template 의 `## 구현 가이드`*목표*("구현자가 되묻지 않을 수준")는 정의하지만, **그 수준에 도달했는지 알려주는 게이트가 없다.** 그래서 미달 상태로 착수 → 반복 재작업.
2. 조사가 **코퍼스-주도(bottom-up)** 다 — 주제 정하고 문서를 넓게 모은 뒤 합성. 그래서 "이 결정이 의존하는 질문"이 안 닫힌 채 착수 → 코딩 중 그 질문에 부딪힘 → 되돌아가 조사. 조사는 **결정-주도(top-down)** 여야 한다: 내려야 할 결정·미지수를 먼저 나열하고 각각을 닫을 때까지 조사. 조사 완료 = 모든 결정이 닫힘 = 착수 가능. (R1 의 설계 기반.)
## 1. 목표 / 성공 기준
- **성공 지표**: branch-note 1개가 착수 전 `/depth` 게이트를 통과(Blocking 0)하면, 구현 중 노트로 되돌아가는 횟수가 현격히 줄어든다(4~5회 → 1회 사전 루프).
- **수용 기준(회귀 테스트)**: 기존 브랜치 2~3개로 보정. 얕은 초기 브랜치는 `Not ready`, 여러 번 다듬어 실제 구현에 쓴 브랜치(예: `feature-boundary-validation-mapping-contract`)는 `Ready` 에 근접해야 게이트가 보정된 것.
## 2. Non-goals (명시적 비목표)
- 본 게이트는 **"전체 계약"이 아니다.** 전체 계약은 `raw/project-notes/ca-skeleton-operational-contract.md`.
- **`feature-implementation-readiness-scorecard` 를 대체/포함하지 않는다.** 그것은 *스켈레톤 전체가 도메인을 받을 준비*를 보는 거시 게이트(15 area, raw 내용). 본 게이트는 *브랜치 노트 1개의 깊이*를 보는 미시 게이트(rules 방법론). 두 게이트는 **다른 층·다른 범위로 공존**한다.
- 감사기는 **브랜치 노트를 편집하지 않는다.** 자동 조사·자동 채움(접근법 B)은 기본 동작이 아니라 옵트인 안내만.
- P1(계약 충돌 거버넌스)·P3(백틱/링크 깨짐 린트)·P4(raw→concept 승격 기준)는 별도 사이클. 단 §7의 연결점 참조.
## 3. 층위 정리 (명명 혼동 해소)
```
[rules/] ← HOW (방법론·프로세스 SSOT)
linking-rules.md, naming-conventions.md, tag-taxonomy.md,
evidence-first-research.md, reporting-standards.md,
advisory-depth.md, diagram-standards.md
+ branch-depth-gate.md ← ★ 신규. "브랜치 노트가 코딩할 만큼 깊은가" 판정 기준
[raw/project-notes/] ← WHAT (프로젝트 내용 SSOT)
ca-skeleton-operational-contract.md ← 전체 계약 (모든 branch 의 Parent)
[raw/branch-notes/] ← 전체 계약의 조각 (내용, 80개)
feature-contract-registry-governance = 계약 토큰 레지스트리
feature-implementation-readiness-scorecard = 스켈레톤 adoption 거시 게이트
feature-boundary-validation-mapping-contract = 경계 계약
...
```
명명 통일: 룰 SSOT `rules/branch-depth-gate.md` · 감사기 `branch-depth-auditor` · 커맨드 `/depth`. ("readiness" 단어를 배제해 scorecard 와 충돌 제거.)
설계 모티프: im-not-ai 의 검증된 3요소 — **기준 SSOT(taxonomy) + 탐지/감사(detector·reviewer) + 등급 판정** — 을 위키 문법으로 옮긴 것. `branch-depth-gate.md`↔taxonomy, `branch-depth-auditor`↔detector, Ready/Not-ready↔grade.
---
## 4. 컴포넌트 1 — `rules/branch-depth-gate.md` (기준 SSOT, 설계의 심장)
"구현 착수 가능"을 4축 × Blocking 규칙으로 명문화한다.
> 축 라벨은 `R1~R4` 를 쓴다. branch-note 의 Decision Evidence Map 이 `D1`, `D2` 를 *Decision ID* 로 쓰므로, 축을 `D*` 로 두면 충돌·모호해진다.
| 축 | Pass 조건 | Blocking (= Not ready) 트리거 |
|---|---|---|
| **R1. 조사 깊이** | 각 Decision 의 Supporting Claim 이 클레임 깊이 사다리(§4.1) 기준을 충족 — 의존 메커니즘에 L1+, 분기 조건에 L2+ | 결정의 근거 claim 이 순수 L0(존재만)뿐. how/when 부재 |
| **R2. 결정 조건** | 각 Decision 이 "어떤 조건일 때 A, 아니면 B"의 선택 기준을 명시 | `검토한 대안` 은 있는데 *언제 그 대안을 고르는지* 기준이 없음 |
| **R3. 구체 detail** | `## 구현 가이드` 의 각 in-scope 항목이 명명·경로·메커니즘·API/테스트명을 구체화 **또는** `UNSUPPORTED_IMPL_DECISION` 라벨 + trade-off 한 줄 | in-scope 항목인데 구현 detail 도 없고 UNSUPPORTED 라벨도 없음 |
| **R4. 엣지·실패·의존** | 실패/엣지 경로 열거 + 다른 contract 의존을 *대상 브랜치 + 그 Decision ID* 로 링크 | 정상 경로만 있음 / 다른 계약 의존이 암시되는데 링크 안 됨 |
**판정 규칙** (위키가 이미 쓰는 binary 프레이밍 계승):
- 심각도 3단계: `Blocking`(Not ready) · `Should-fix`(권고) · `Advisory`(참고).
- **Ready = Blocking 0건.** Should-fix 가 남아도 사용자가 "감수" 선언 시 착수 가능(리포트에 기록).
- 모든 finding 은 `심각도 · 위치(섹션/행) · 예상 의구심("구현 중 여기서 ___를 되묻게 됨") · 채울 방법` 4종 세트로 근거화. 근거 없는 지적 금지(claim 철학과 동일).
이 룰북은 `rules/` 의 8번째 규칙이며, 다른 규칙처럼 *명명된 실패 모드 + 자동 검사 가능* 형태로 작성한다.
### 4.1 R1 조사 깊이 — 결정-주도 + 클레임 깊이 사다리
깊이의 단위는 **코퍼스(문서 개수)가 아니라 결정별 종결**이다. 얕은 문서 10개 < 결정을 닫는 문서 1개. 개수는 허영 지표.
**클레임 깊이 사다리** — 각 Supporting Claim 이 답하는 수준:
| 레벨 | 답하는 것 | 판정 |
|---|---|---|
| **L0 존재** | "X 가 있다 / 권장한다" | 단독이면 불충분 |
| **L1 메커니즘** | 어떻게 동작 / 언제 발생 | 메커니즘 의존 결정의 최소선 |
| **L2 조건·경계** | 언제 적용/제외, 실패 시 어떻게 | 분기 조건 있는 결정의 최소선 |
| **L3 검증** | 확인 방법·수치·반례 | 가산점 |
**R1 Pass**: 각 Decision 의 근거 claim 이 — 그 결정이 *의존하는 메커니즘*에 L1 이상, 그 결정이 *분기하는 조건*에 L2 이상 도달. 순수 L0 만 = Blocking.
**출처 타입 적정성** (개수 기준 대체 — 위키의 claim-strength 개념 재사용):
- 스펙/표준이 정의한 동작 → `official-standard` / `official-vendor-doc` **1개로 충분**.
- "대기업은 보통 이렇게 한다"는 *운영 패턴 추론* → 회사 블로그 1개는 claim-gate 철학상 "공식" 불가. 그 결정의 근거로 삼으려면 **독립 사례 2개+** 또는 official 1개 병행.
즉 게이트가 묻는 것은 "몇 개 조사했나"가 아니라 **"내 결정 N개가 각각 적정 출처 타입의 L1+ claim 으로 닫혔나"**.
## 5. 컴포넌트 2 — `branch-depth-auditor` 에이전트 (read-only)
- **입력**: 브랜치 노트 경로 1개.
- **읽는 것**: ① `rules/branch-depth-gate.md` ② 대상 브랜치 노트 ③ 그 노트가 링크한 raw 소스(Sources 표 + Decision Evidence Map 의 Supporting Claims 가 가리키는 `raw/.../*.md#Cn`). — 소스를 실제로 열어 **R1(조사 깊이)** 을 판정하는 게 핵심. 링크만 있고 내용이 얕으면 잡아낸다.
- **처리**: R1~R4 각 축을 적대적으로 훑어 finding 생성.
- **출력**: 갭 리포트 + 판정(`Ready` / `Not ready (Blocking N건)`). **편집 일절 안 함. 판정을 브랜치 노트에도 박지 않음.**
- **도구**: Read·Glob·Grep 만(쓰기 도구 미보유 → 구조적 read-only 보장). 위키의 `wiki-adversarial-reviewer` 와 같은 read-only 리뷰어 계열.
- **리포트 형식**: 가능하면 `rules/reporting-standards.md` 의 보조 형식을 따르되, COMPLETE verdict 보고서가 아니므로 claim-gate hook 의 `*-report.md` 강제 대상이 아니다.
## 6. 컴포넌트 3 — `/depth <branch>` 커맨드 + 루프
1. 인자 검증 → `raw/branch-notes/<branch>.md` 경로 해석(없으면 안내 후 종료).
2. `branch-depth-auditor` 디스패치.
3. 리포트를 **인라인 출력**(기본). 파일로 남기려면 옵션 — 단 claim-gate hook 이 `raw/`·`wiki/`·`docs/` 쓰기를 검사하므로 **브랜치 노트에 쓰지 않고** 게이트 비대상 경로 또는 인라인으로만. read-only 불변식 유지.
4. **루프**: 사람(또는 후속 AI)이 갭을 채움 → `/depth` 재실행 → Blocking 0 = Ready → 개발 착수.
## 7. 컴포넌트 4 — 템플릿 캡처 칸 추가 (얇은 상류 예방, 접근법 C)
`templates/branch-note-template.md` 에 최소 추가(기존 80개는 미변경, 신규부터 적용):
- **Decision Evidence Map 에 `선택 조건` 열 추가** → R2(언제 A, 언제 대안)를 작성 시점에 강제.
- **`## 엣지·실패·의존` 미니 섹션** 추가(또는 구현 가이드 내 고정 라인) → R4 를 작성 시점에 유도.
- 그 이상 비대화 금지(YAGNI). 게이트가 본체, 템플릿은 보조.
## 8. 접근법 B 온램프 (옵트인만)
리포트가 R1 "조사 얕음" 갭을 낼 때, 한 줄 안내만 출력: *"이 갭은 `wiki-decision-researcher` 로 심화 권장."* 감사기는 절대 자동 조사·편집하지 않는다 — 사용자가 원할 때만 직접 호출. (위키의 "사람이 결정하게" 철학 보존.)
## 9. 엣지 처리
- 브랜치 파일 없음 → 에러 후 종료.
- 필수 섹션 결손 → 그 자체가 finding.
- 소스 위키링크가 백틱에 싸여 깨짐(`` `[[...]]` ``) → finding 으로 표면화. 깨진 링크 = 근거 추적 불가 = R1 Blocking 후보. (**P3 와 자연 연결점.**)
- Supporting Claim 의 `#Cn` 앵커가 대상 raw 에 실재하지 않음 → R1 finding.
## 10. 검증 / 수용 기준
- 회귀 보정: 얕은 초기 브랜치 1개(`Not ready` 기대) + 다듬어진 브랜치 1개(`feature-boundary-validation-mapping-contract`, `Ready` 근접 기대)로 게이트 판정이 직관과 일치하는지 확인.
- 자체점검: 각 finding 이 4종 세트(심각도·위치·의구심·방법)를 갖췄는지.
- 회귀: 룰북의 4축(R1~R4)이 §0 의 4개 의구심과 1:1 매핑 유지.
## 11. 다른 고통(P1·P3·P4)과의 연결점
- **P1(계약 충돌)**: R4(다른 계약 의존 링크)가 부분적으로 닿음. 본격 거버넌스는 `feature-contract-registry-governance` 라인의 별도 사이클.
- **P3(백틱/링크)**: §9 에서 본 게이트가 백틱 래핑 링크를 finding 으로 *표면화*는 하지만, P3 의 본체는 **별도 사이클**(P2 구현 완료 후 착수)로 확정. 기존 `wiki-link-verifier`(LLM·수동)는 *타깃 부재* broken link 만 잡고 코드블록은 스킵하므로, **타깃은 멀쩡한데 `` `[[...]]` `` 백틱에 싸여 옵시디언이 렌더링 안 하는** 경우는 미커버 — 진짜 빈틈. 결정론적 버그라 LLM 이 아니라 **py 스크립트가 정답**이며, `wiki_claim_gate.py` 처럼 **PostToolUse hook 으로 걸어 매 저장마다 자동 검출**(수동 수정 제거)하는 것을 권장. 1차 범위는 백틱 래핑 1종에 집중(인라인 코드 내 `[[]]`, `![[]]` 임베드, `#heading` 앵커 부재 등은 확장 여지로만 남김 — YAGNI). 위키에 *옵시디언 문법 검증*이라는 관점 자체가 현재 부재함을 기록.
- **P4(raw→concept 승격 기준)**: 별도 사이클. 단 본 게이트의 "근거화된 판정" 패턴은 P4 의 승격 루브릭에 재사용 가능.
## 12. 산출물 요약
| 파일 | 종류 | 신규/변경 |
|---|---|---|
| `rules/branch-depth-gate.md` | 기준 SSOT | 신규 |
| `.claude/agents/branch-depth-auditor.md` | 에이전트 정의 | 신규 |
| `.claude/commands/depth.md` | 커맨드 정의 | 신규 |
| `templates/branch-note-template.md` | 템플릿 | 변경(선택 조건 열 + 엣지·실패·의존 섹션) |
| (선택) `AGENTS.md` / `CLAUDE.md` | 멀티 CLI 진입점 | 신규 게이트 1줄 등재 여부는 구현 단계 결정 |