# Implementation Report: 분석 문서 템플릿 키트

**Plan**: `.claude/plans/doc-template-kit.plan.md` (아카이브: `.claude/PRPs/plans/completed/`)
**Branch**: `feat/doc-template-kit`
**Date**: 2026-08-04

## Summary

`.claude/templates/doc-kit/` 에 정책 문서 템플릿 1종 · IA 문서 템플릿 1종 · config 계약 · lint 1개 ·
채워진 예시 2건 · 결함 fixture 5종 · README 를 확정하고, 상류 문서 6개가 새 정본을 가리키도록 정정했다.
PRD 마일스톤 6개 전부 complete, Open Question 4건 해소.

## Assessment vs Reality

| Metric | Predicted (Plan) | Actual |
|---|---|---|
| Complexity | Medium | Medium — 예상대로 |
| 신규 파일 | 12개 | **13개** (결함 fixture 4 → 5, Codex R1 F1 반영) |
| 상류 편집 | 4건 | **6건** (인덱스 PRD 3종이 Task 6d grep 에서 잡힘) |
| 총 분량 | 약 900줄 | **1,630줄** (lint 613줄이 예상보다 큼 — YAML 파서 + selftest 하네스) |

## Tasks Completed

| # | Task | Status | Notes |
|---|---|---|---|
| 1 | config 계약 + insuniverse fixture | 완료 | `evidence_grades` 를 spec §2 에서 실측 — 아래 편차 1 |
| 2 | `policy-doc.template.md` (M1+M2) | 완료 | 헤더 블록을 `TEMPLATE:` 마커로 — 아래 편차 2 |
| 3 | `ia-doc.template.md` (M3) | 완료 | Task 4 중 역행 1건 — 아래 편차 3 |
| 4 | 예시 2건 (M4) | 완료 | 앵커 34개 실측 검증 |
| 5 | `lint-docs.mjs` + fixture (M5) | 완료 | fixture 5종 (Codex R1 F1 로 1종 추가) |
| 6 | README + 상류 정정 + PRD (M6) | 완료 | 상류 편집 4 → 6건 |

## Validation Results

| Level | Status | Notes |
|---|---|---|
| V1 `--selftest` | PASS | 정상 2건 PASS · 결함 5건이 **지정 규칙명으로** FAIL · BOM+CRLF PASS · 미지원 문법 7종 전부 거부 |
| V2 예시 개별 검사 | PASS | 위반 0 |
| V3 중립성 | PASS | 템플릿 본체에 프로젝트 고유값 0 |
| V4 앵커 실존 | PASS | 34개 전부 파일 존재 + 라인 범위 내 |
| V5 PRD 마일스톤 | PASS | 6/6 complete |
| plan-conflict 검출 | `conflict:false` | 계획 ↔ 구현 간극 없음 |

정적 분석 · 단위 테스트 · 빌드 단계는 해당 없음 — 저장소 루트에 패키지 매니저가 없고,
PRD 가 테스트 프레임워크를 명시적으로 금지한다. `--selftest` 가 유일한 상시 검사다.

### Design Grounding

N/A — 설계 트리거 미발동. impeccable Skill 부재(`skill-missing`)이고 산출물에 렌더링 표면이 없다
(Markdown + 단일 node 스크립트). Phase 3.6 / 3.7 은 no-op.

## Files Changed

| File | Action | Lines |
|---|---|---|
| `.claude/templates/doc-kit/policy-doc.template.md` | CREATED | +107 |
| `.claude/templates/doc-kit/ia-doc.template.md` | CREATED | +95 |
| `.claude/templates/doc-kit/template-config.schema.md` | CREATED | +92 |
| `.claude/templates/doc-kit/lint-docs.mjs` | CREATED | +613 |
| `.claude/templates/doc-kit/README.md` | CREATED | +95 |
| `.claude/templates/doc-kit/examples/template-config.insuniverse.yaml` | CREATED | +36 |
| `.claude/templates/doc-kit/examples/policy-example.md` | CREATED | +130 |
| `.claude/templates/doc-kit/examples/ia-example.md` | CREATED | +224 |
| `.claude/templates/doc-kit/examples/fixtures/bad-*.md` (5) | CREATED | +238 |
| `.claude/prds/doc-template-kit.prd.md` | UPDATED | 마일스톤 6행 + Open Question 4건 해소 + 산출물 표 |
| `.claude/meta/05-final-spec.md` | UPDATED | §4 공통형식 강등 배너 (블록 보존) |
| `.claude/prds/insuniverse-docs-00-protocol.prd.md` | UPDATED | 헤더 정본 분리 + M4 문구 |
| `.claude/prds/insuniverse-policy-docs.prd.md` | UPDATED | 핵심 제약 #7 신설 + 형식 정본 경로 |
| `.claude/prds/insuniverse-docs-{10,11,12}-*.prd.md` | UPDATED | 헤더 정본 분리 (Task 6d 에서 발견) |

## Deviations from Plan

**1. `evidence_grades` 값 집합** — 플랜 §5 예시는 `[S-test, S-roles, S-schema, S-config, A-comment, A-commit]`
이었으나 같은 절이 "`05-final-spec.md` §2 소스 등급을 읽어 확정한다(구현 시 실측)" 라고 지시했다.
§2 표를 1:1 로 옮긴 결과 13종이며 `S-config` 는 §2 에 행이 없다(`RATE_LIMIT_*` 는 "정책 상수" 행 → `S-constant`).
D(task-ID 교집합)·X(`planning/`)는 §2 가 각각 "조인 키로 쓰지 않음"·"참조 금지"로 판정했으므로 제외했다.

**추가 2종 (`S-route` · `S-component`)** — §2 표는 server 정책 추출용이라 화면 근거를 담지 못한다.
IA 예시를 실제로 쓰는 도중 드러난 공백이다. 둘은 서로 독립이며(라우트만 있고 컴포넌트가 없을 수 있고 그 반대도 가능),
`front/src/pages/alimTalk/Step5Page.tsx` 가 그 독립성의 실물 사례다 — 컴포넌트는 있으나 라우트가 없고 본문 전체가 주석 처리됨.
이 독립성 덕분에 두 등급의 동시 충족이 우산 제약 #3(단독 근거 금지)을 만족한다. fixture 주석에 근거를 남겼다.

**2. 템플릿 헤더 주석을 `<!-- TEMPLATE:` 마커로** — 플랜은 헤더에 (a) 제약 준수 판단 (b) lint 실행 명령을
넣으라고만 했다. 일반 HTML 주석으로 두면 복사본에서 프론트매터가 1행에서 시작하지 못해 `frontmatter-parse` 가
깨진다. `TEMPLATE:` 마커로 바꿔 `no-template-comment` 규칙이 삭제를 강제하게 했다.

**3. `ia-doc` 프론트매터에 `limitations:` 추가 (역행)** — 플랜은 `limitations` 를 정책 전용으로 도입했다(R2-F3).
IA 예시 실물 작성 중 `UsedAnalysisPermissionPage` · `ExpiredAccessLinkPage` 처럼 테스트도 주석도 없는 화면의
한계를 기록할 자리가 없었다. 플랜 Task 4b 가 "표현 불가가 나오면 Task 3 템플릿을 고친다(역행 허용)" 를
명시했으므로 그 경로를 따랐다. 두 템플릿이 대칭이 되었다.

**4. `## 정책 (기획)` 코드 심볼 금지의 범위 명시** — `### <id>` 제목이 env 키 이름(`ADMIN_VIEW_TOKEN_ENFORCE`)
이므로 규칙을 문자 그대로 읽으면 제목 자체가 위반이 된다. 금지 대상을 **제목 아래 서술**로 한정한다고
템플릿 주석에 명시했다.

**5. 상류 편집 4 → 6건** — Task 6d grep 이 `10/11/12-index` PRD 헤더의 `> **규약 정본**: … 05-final-spec.md`
단일 선언을 잡았다. 인덱스 PRD 는 주로 YAML/JSONL 을 내지만 Markdown 을 쓸 경우 강등된 §4 형식으로 돌아갈
경로가 열려 있었다. 라벨을 `추출 규약 정본` 으로 바꾸고 `문서 형식 정본` 행을 추가했다(범위·경로 불변).

## Issues Encountered

**selftest 가 자기 예시에서 진짜 위반 1건 검출** — `policy-example.md` 본문의
`` `certify:rl:<식별자>` `` 가 `no-placeholder` 에 걸렸다. 자리표시자 문법과 구별되지 않는 서술이므로
`` `certify:rl:` + 식별자 `` 로 고쳤다. lint 의 오탐이 아니라 예시 쪽 결함이었다.

**BOM+CRLF 테스트 하네스 경로 버그** — 임시 파일을 키트 루트에 쓰는 바람에 문서 기준 상대경로인
`config:` 가 해석되지 않아 `config-resolve` 가 FAIL 했다. 임시 파일을 원본과 같은 디렉터리로 옮겨 해결.
lint 본체가 아니라 selftest 하네스의 버그였다.

## Codex Implement-Codex 게이트

R1 1라운드. HIGH 1건 — 플랜 §5 의 예시 config 가 `statuses:` 흐름형 리스트를 두 줄에 걸쳐 써서
제안된 줄 단위 파서 문법과 모순한다는 지적. 전부 흡수했다:
fixture 를 1행으로 기록 · schema "지원하지 않는 문법" 에 *흐름형 여러 줄 연장* 명시 ·
결함 fixture `bad-yaml-continuation.md` 신설 · selftest 에 BOM+CRLF 정상 경로와 미지원 문법 7종
거부 단언 추가. Codex 최종 판정이 `needs-attention` 이었으므로 receipt 는 `divergent` 로 기록된다
(후속 `/mccp:pr` 에서 PR-Codex 를 건너뛰지 못하게 한다).

## Tests Written

프레임워크 없음(PRD 제약). `lint-docs.mjs --selftest` 가 상시 검사 전체다.

| 검사 | 건수 | 대상 |
|---|---|---|
| 정상 PASS 단언 | 2 | 예시 2건 |
| 결함 FAIL + 규칙명 단언 | 5 | fixture 5종 |
| BOM + CRLF 정상 경로 | 1 | Windows 작성 환경 |
| 미지원 YAML 문법 거부 | 7 | 중첩 맵 · 앵커 · 별칭 · 멀티라인 · 따옴표 키 · 탭 · 흐름형 연장 |

## Next Steps

- [ ] 상류 정정 6건을 **별도 커밋으로 분리** (플랜 §8 — 사용자가 diff 만 보고 판정 가능하게)
- [ ] `/mccp:pr` 또는 `/mccp:code-review`
- [ ] `00-protocol` M4 착수 시 fixture 를 `docs/_meta/template-config.yaml` 로 복사
