137 lines
10 KiB
Markdown
137 lines
10 KiB
Markdown
# coverage 완전성 게이트 — 설계
|
|
|
|
> 작성: 2026-06-02 · 상태: 합의됨 · 짝 문서: `2026-06-02-branch-spec-assembly-pipeline-design.md`
|
|
|
|
## 1. 배경 / 문제
|
|
|
|
현재 파이프라인에는 **깊이 게이트(`/depth`)는 있지만 완전성 게이트는 없다.**
|
|
|
|
- `/depth`(R1~R4)는 노트에 *적힌* 결정이 충분히 깊고 코딩 가능한지 검사한다.
|
|
- 그러나 *"적어야 할 결정이 다 적혔는가"* 는 어느 축도 보지 않는다. 브랜치의 `In scope` 리스트는 `/branch` 생성 시 사람이 손으로 쓴 것이며, 그 리스트 자체의 완전성은 게이트되지 않는다.
|
|
- 결과: `In scope`가 불완전해도 `/depth`는 통과한다. 실제 사례 — `feature-business-rule-validation-contract`가 "Ready" 판정을 받았지만, ad hoc grep 결과 i18n 메시지 정책 / 입력 정규화 / fail-fast 오류수집 정책 등 표준 검증 관심사가 어느 브랜치에도 결정으로 존재하지 않음이 드러났다.
|
|
|
|
ca-tmpl은 **보편적 백엔드 프로젝트가 갖춰야 할 항목을 빠짐없이 담는 템플릿**이 목적이므로, 완전성(coverage)은 깊이만큼 중요한 축이다.
|
|
|
|
비유: `/depth`는 "네가 푼 문제는 잘 풀었다"를 채점하지만 "3번 문제를 통째로 안 풀었다"는 못 잡는다. `/coverage`가 그 빠진 문제를 잡는다.
|
|
|
|
## 2. 범위
|
|
|
|
**순수 추가 + 최소 수정. depth 게이트의 형제(sibling)로 설계.**
|
|
|
|
| 산출물 | 성격 |
|
|
|---|---|
|
|
| `.claude/commands/coverage.md` | `/coverage` 명령 (브랜치 모드 + 프로젝트 모드) |
|
|
| `.claude/agents/coverage-auditor.md` | 2차 LLM 의미 감사 서브에이전트 (읽기 전용) |
|
|
| `rules/coverage-gate.md` | 판정 규칙 (3단계 심각도 + 명명된 실패 모드) — `branch-depth-gate.md`의 짝 |
|
|
| `wiki/projects/ca-tmpl/coverage-matrix.md` | 프로젝트 전체 현황표 (**자동 생성물**, 손유지 금지) |
|
|
| ~~(린터 확장)~~ → `/coverage` 인라인 | **변경(2026-06-02)**: 공유 린터를 건드리면 기존 노트 대량 파손 → 1차 결정론 검사를 `coverage.md` 인라인(grep, target 한정)으로 구현. 공유 린터 무수정 |
|
|
| (수정) `templates/branch-note-template.md` | `## Coverage` 섹션만 추가(optional 마커). `governing_docs:` 는 **template 에 안 넣음**(§4.1 구현 노트) |
|
|
| (수정) `.claude/commands/branch-spec.md` | `/coverage` 자동 실행 끼우기 |
|
|
|
|
**명시적 비범위:**
|
|
- 외부 taxonomy(OWASP 등)를 기준으로 삼지 않는다 — 기준은 프로젝트 자체의 canonical 문서.
|
|
- `.codex` / `.agents` 병렬 포트는 후속(이번엔 `.claude`만).
|
|
- 기존 브랜치 노트 일괄 마이그레이션(`governing_docs` 소급 부여)은 후속 — 점진 적용.
|
|
|
|
## 3. 확정된 설계 결정
|
|
|
|
| ID | 결정 | 근거 |
|
|
|---|---|---|
|
|
| DD1 | **범위 = 브랜치 레벨 + 프로젝트 레벨 (둘 다, 계층적)** | 브랜치 slice 완전성 + 브랜치 집합 전체의 owner-less 관심사 둘 다 필요 |
|
|
| DD2 | **기준 = 설계 문서 1순위 → 선례 브랜치 → ca-tmpl 코드.** 겹치면 owner 브랜치 위임 | 사용자 방법론: "문서가 제일 먼저 기준, 그걸 ca-tmpl에 구현, 겹치면 owner 위임". 외부 taxonomy 아님 |
|
|
| DD3 | **구조 = 2단계 (얇은 결정론 린터 + LLM coverage-auditor)** | depth 패턴 미러링. 기계로 볼 수 있는 건 1차에서 싸게, 의미 비교는 2차 |
|
|
| DD4 | **판정 = 3단계 심각도 (Blocking / Should-fix / Advisory). Covered = Blocking 0** | depth와 동일. owner 위임 케이스를 Blocking 아닌 Should-fix로 분리 → false block 방지 |
|
|
| DD5 | **접근법 C (하이브리드).** 브랜치→문서 매핑은 frontmatter `governing_docs` 한 줄로 명시, `## Coverage`와 프로젝트 matrix는 **자동 생성**(손유지 금지) | drift 회피(이번 세션 교훈: 손유지 SSOT는 어긋난다 — registry 주석 L580 stale 사례). tag 추론은 엉뚱한 문서를 잡을 위험 → 명시 한 줄로 차단 |
|
|
| DD6 | **끼우는 위치 = `/branch-spec` 맨 끝, `/depth`와 나란히.** 둘 중 하나라도 실패 시 `/branch-spec`으로 루프백 | 두 게이트 대칭. coverage가 찾은 빠진 항목을 채우고 → 그 새 결정을 depth가 다시 깊이 검사 → 둘 다 통과 시 완성 |
|
|
|
|
## 4. 데이터 모델 (가벼움 — 사람이 쓰는 건 한 줄)
|
|
|
|
### 4.1 브랜치 frontmatter `governing_docs:`
|
|
이 브랜치가 구현해야 할 기준 canonical 문서를 명시. tag 추론의 불안정성 제거.
|
|
```yaml
|
|
governing_docs: [wiki/projects/ca-tmpl/api-error-envelope-design]
|
|
```
|
|
- 0개 또는 다수 가능.
|
|
- **구현 노트 (2026-06-02)**: 공유 구조 린터(`wiki_structure_lint.py`)는 `--file` 모드에서 `is_completeness_checkable` 게이트 없이 모든 template fm_key 를 무조건 요구한다. 따라서 `governing_docs` 를 **template frontmatter 에 넣으면 기존 80개 노트가 전부 깨진다** → template 에 추가하지 않음. 대신 **`/coverage` 1차 인라인 검사**가 ca-tmpl 브랜치 한정으로 존재를 요구(`NO_GOVERNING_DOC`). 노트에 *추가 키*로 들어가는 건 린터가 막지 않으므로(required 만 검사, extra 는 허용) per-branch 로 안전하게 부여 가능. 기존 ca-tmpl 노트 backfill 은 점진 마이그레이션(비범위).
|
|
|
|
### 4.2 브랜치 노트 `## Coverage / 관심사 커버리지` 섹션
|
|
coverage-auditor가 **생성**. 손유지 금지.
|
|
|
|
| 관심사 | 상태 | owner | 심각도 | 근거 |
|
|
|--------|------|-------|--------|------|
|
|
| syntax/shape 검증 | covered-here | — | — | D1 |
|
|
| cross-field 검증 | delegated | feature-boundary-validation-mapping | OK | §Audit 링크 |
|
|
| i18n 메시지 정책 | **missing** | (없음) | 🔴 Blocking | governing doc §X 언급, 결정 없음 |
|
|
|
|
- 상태 3종: `covered-here`(이 브랜치가 다룸) / `delegated`(다른 owner) / `missing`(아무도 안 맡음).
|
|
|
|
### 4.3 `wiki/projects/ca-tmpl/coverage-matrix.md`
|
|
프로젝트 모드가 모든 브랜치 `## Coverage`에서 **생성**하는 뷰. `관심사 → owner 브랜치 → status`, owner-less(아무 브랜치도 안 맡은 관심사) 강조. 생성물이라 drift 불가.
|
|
|
|
## 5. 게이트 로직
|
|
|
|
### 5.1 1차 — 결정론 린터 (싸고 빠름)
|
|
사람 판단 불요 항목만:
|
|
- `governing_docs` frontmatter 존재?
|
|
- `## Coverage` 섹션 존재?
|
|
- `governing_docs` 링크가 vault에 실재(깨진 링크 아님)?
|
|
|
|
심각하게 깨졌으면(필드/섹션 누락) 그것부터 고치도록 안내, 2차 보류 — depth 1차와 동일 정책.
|
|
|
|
### 5.2 2차 — coverage-auditor (LLM 의미 감사, 읽기 전용)
|
|
브랜치 모드 입력: 브랜치 노트 경로. 다음 셋을 **실제로 읽고** 비교:
|
|
1. `governing_docs` 문서 — "있어야 할 관심사" 열거.
|
|
2. 선례(완성) 형제 브랜치 — 이미 누가 무엇을 owner인지.
|
|
3. ca-tmpl 코드(`/home/donghyeon/workspace/ca-tmpl/src`, `docs/registries`) — 말로만 있는지 실제 구현인지.
|
|
|
|
→ governing 문서의 각 관심사를 브랜치 In-scope/결정과 대조해 `## Coverage` 표 생성 + 3단계 판정.
|
|
|
|
프로젝트 모드(`--project`): 전체 canonical 문서에서 관심사를 열거하고, 각 브랜치 `## Coverage`와 cross-ref → owner-less 관심사를 Blocking으로 `coverage-matrix.md` 생성.
|
|
|
|
### 5.3 판정 (3단계 심각도)
|
|
| 신호 | 의미 | 트리거 |
|
|
|------|------|--------|
|
|
| 🔴 Blocking (Not-covered) | 진짜 빠짐, 아무 브랜치도 안 맡음 | governing 문서가 요구하는 관심사가 이 브랜치에도 없고 다른 owner도 없음 |
|
|
| 🟡 Should-fix | 다른 브랜치 owner인데 위임 링크 누락 | 관심사를 sibling이 소유하나 본 노트 §Audit/§Coverage에 위임 링크 없음 |
|
|
| ⚪ Advisory | 있으면 좋음 | governing 문서가 권고하나 핵심 아님 |
|
|
|
|
**Covered = Blocking 0건.** Should-fix는 사용자 "감수" 선언 시 통과(리포트 기록) — depth와 동일.
|
|
|
|
### 5.4 명명된 실패 모드 (`rules/coverage-gate.md`)
|
|
- `MISSING_CONCERN` (Blocking): governing 문서 관심사가 어느 브랜치에도 결정으로 없음.
|
|
- `UNLINKED_DELEGATION` (Should-fix): owner sibling 있으나 위임 링크 누락.
|
|
- `NO_GOVERNING_DOC`: `governing_docs` 미지정 → 기준 부재로 판정 불가(1차에서 차단).
|
|
- `STALE_OWNER`: §Coverage가 가리키는 owner 브랜치가 실제로 그 관심사를 안 가짐(코드/노트 대조 불일치).
|
|
|
|
## 6. 통합 — `/branch-spec` 흐름
|
|
|
|
```
|
|
ground truth 읽기 → 결정 추출 → 채움
|
|
→ [depth 검사: 적은 게 깊은가]
|
|
→ [coverage 검사: 빠뜨린 게 있는가] ← 신규
|
|
├─ 둘 다 통과 → 완료 ✅
|
|
└─ depth Not-ready 또는 coverage 🔴 → 다시 branch-spec(보강) → 재검사 (루프)
|
|
```
|
|
|
|
`/coverage`는 독립 명령이며 `/branch-spec`이 끝에서 자동 호출(= `/depth` 호출 방식과 동일).
|
|
|
|
### 6.1 프로젝트 외 브랜치 면제
|
|
`governing_docs` 미지정 + `related_projects`에 ca-tmpl 없는 브랜치(예: keycloak 학습 노트)는 coverage 면제 — 1차 린터가 프로젝트 소속 여부로 판단.
|
|
|
|
## 7. 요구사항 충족 매핑
|
|
|
|
| 사용자 요구 | 충족 |
|
|
|---|---|
|
|
| 깊이 외에 완전성도 검사 | DD1~DD4 — 빠진 관심사 3단계 판정 |
|
|
| 문서를 기준으로 | DD2 — `governing_docs` canonical 문서 1순위 |
|
|
| 선례 브랜치처럼 조사 + 겹치면 owner 위임 | 5.2 — 선례 브랜치 읽기 + `delegated` 상태 |
|
|
| branch-spec의 depth 자동실행 구조처럼 | DD6 — 맨 끝 자동 호출 + 루프백 |
|
|
| 별도 명령 | `.claude/commands/coverage.md` |
|
|
|
|
## 8. 리스크 / 비범위 확인
|
|
|
|
- **drift 리스크**: `## Coverage`·matrix를 손유지하면 또 어긋남 → **자동 생성만**(DD5). 사람이 쓰는 건 `governing_docs` 한 줄뿐.
|
|
- **governing_docs 오지정 리스크**: 사람이 엉뚱한 문서를 적으면 판정 무의미 → 1차 린터가 링크 실재만 확인, 적정성은 2차 auditor가 "이 문서가 이 브랜치 주제와 맞나" 한 줄 코멘트로 surface.
|
|
- **canonical 문서 자체가 불완전하면?** coverage는 "문서 대비" 완전성만 보장. 문서 자체의 완전성은 별도(후속 — 문서 레벨 critic). 이번 범위 밖.
|
|
- **비용**: 프로젝트 모드는 전체 canonical + 전체 브랜치 §Coverage 재독 → 비쌈. 주기적 실행 전제(매 브랜치마다 아님).
|