name: review-adr description: docs/adr/ 의 작성된 ADR 문서 검증이 필요할 때 발동 — "ADR 리뷰", "ADR 검토", "설계 문서 리뷰", "아키텍처 리뷰", "review ADR", "architecture review", "design review", "ADR 위험 평가" 요청 시. 코드 리뷰/PR 리뷰에는 사용하지 않는다. user-invocable: true
Review ADR: 아키텍처 결정 문서 검증
ADR 문서의 구조적 완결성, 코드 정합성, 위험 커버리지를 검증합니다. 이슈를 "out of scope"로 스킵하지 않습니다. 발견된 모든 문제를 보고합니다.
🛡️ Anti-Hallucination 5대 규칙 (CRITICAL)
2026-04-20 추가 — 과거 리뷰 세션에서 ADR 본문과 불일치하는 판정이 반복됐다. 원인은 (a) subagent SendMessage 이어받기 시 원문 컨텍스트 손실, (b) Phase 4 템플릿 slot-fill 완성 편향, (c) reviewer 의 일반 prior 를 특정 ADR 에 투영. 아래 5대 규칙은 이를 차단한다.
- 증거 없으면 판정 없음 — 모든 구조/코드/위험 판정은
file:line또는 정확한 섹션 인용 1개 이상 필수. 증거 미제시 판정은 자동UNVERIFIED분류. - "이슈 0건" 정당 — Phase 4 에 HIGH/MEDIUM/LOW 이슈가 없으면
이슈 없음 — 승인 가능으로 보고. 결함을 만들어내려 하지 않는다. "reviewer 가 결함을 찾지 못하면 부실하다" 는 편향 금지. - 템플릿 slot 강제 금지 — Phase 4 테이블의 모든 행을 채울 필요 없음. 해당하지 않는 slot 은 생략 가능 (
N/A - 해당 섹션 없음명시). - 원문 단 1회 재확인 의무 — Phase 4 보고 직전, 각 판정의 인용 라인 번호를 원문에서 재확인. 기억이나 summary 에서 인용 금지.
- Subagent 1-shot 원칙 — review-adr 을 subagent 에 위임 시, 중간 중단 후 SendMessage 이어받기 금지. agent context 가 autocompact 되면 원문 손실 → hallucination 필연. 중단되었다면 main 이 직접 재수행 또는 새 agent 1-shot.
사전 준비 (Setup)
Read docs/adr/README.md → 전체 ADR 현황 파악
Read {대상 ADR 본문} → 100% 전체 읽기 (절삭 금지)
Read {대상 ADR breakdown} (있으면) → 구현 상세 확인
Read .claude/rules/adr-writing.md → 템플릿 체크리스트 (동적 seed 포함)
Read .claude/rules/measurement-validity.md → Gate 수치의 leakage 8-패턴 + 착수 전 5-질문 (Phase 3-H 판정 기준)
증거 캐시 시작: 이 시점부터 file:line 또는 ADR:line_range 형태로 인용할 것만을 판정 근거로 사용. 기억/추측은 근거 아님.
Phase 1: 구조 검증 (Risk-First 템플릿 대조)
필수 섹션 체크리스트 (adr-writing.md 의 7개 + 동적 seed)
| 섹션 | 확인 기준 | 증거 형식 |
| ----------------------- | --------------------------------------------------------------------------- | ----------------- |
| Context | 측정 가능한 hard constraint 1개 이상 | ADR:line N |
| Alternatives Considered | 최소 2개 대안 + 각 대안에 4축 위험 평가 | ADR:line N-M |
| Risk Threshold Check | 테이블 + HIGH+ 루프 판정 | ADR:line N |
| Decision | Alternatives 뒤, 위험 수용 근거 + 기각 사유 | ADR:line N |
| 구현 상세 분리 | 구현 상세가 design 파일에 있는가 (포인터만 본문에) | ADR:line N 링크 |
| Risks | Decision 뒤 / Gates 앞, ID/위험/심각도/대응 표 (또는 "잔존 HIGH 위험 없음") | ADR:line N |
| Gates | Gate 테이블 또는 "잔존 HIGH 위험 없음" 명시 | ADR:line N |
adr-writing.md 동적 seed 확인 — 해당 seed 가 활성화되어 있으면 (예: 2026-04-20 반복 패턴 선차단 — 현행 seed 항목, 개수 미고정, adr-writing.md 참조) 추가 검증. 비활성화되었으면 스킵.
4축 위험 평가
각 대안에 기술/성능/유지보수/마이그레이션 4축이 모두 평가됐는지 확인. 누락 축은 missing axis: <축> 으로 기록.
구조 검증 판정 규칙
- 섹션 존재하고 내용이 adr-writing.md 요구 충족 →
PASS + 품질(HIGH/MED/LOW) - 섹션 존재하지만 내용 부실 →
PARTIAL+ 부실 부분 인용 - 섹션 없음 →
FAIL+ ADR 의 어느 line 범위에 있어야 하는지 명시
reviewer prior 투영 금지: "일반적으로 Gate 가 약하다" 는 전제로 PASS 를 FAIL 로 내리지 않는다. 실제 본문 line 확인 후 판정.
Phase 2: 코드 검증 (주장 vs 실제)
ADR에서 언급된 파일, 인터페이스, 함수, 상수, 라인 번호를 실제 코드에서 확인합니다. 주장만 읽고 PASS 처리하지 않습니다. 증거 없는 VERIFIED 판정 금지.
검증 절차
# 1. ADR에서 언급된 파일 경로 추출 → Glob 으로 존재 확인
Glob {언급된 파일 패턴}
# 2. 언급된 함수/인터페이스/상수 → Grep 으로 line 번호 확인
Grep "{함수명|인터페이스명}" --type=ts -n
# 3. "현재 ~를 사용 중" 주장 → 실제 사용 패턴 Grep
Grep "{주장된 패턴}" <경로>
# 4. 라인 번호 인용된 경우 → 해당 line ±5 Read 로 맥락 확증
Read {파일} offset:N-5 limit:10
검증 결과 분류 (3택 중 하나)
| 분류 | 의미 | 필수 인용 |
| -------------- | -------------------------------------------------------------- | ----------- |
| VERIFIED | 코드/라인에서 확인됨, 주장과 일치 | file:line |
| UNVERIFIED | 코드에서 발견되지 않음 OR 확인 시도 실패 OR 인용 라인과 불일치 | 시도한 경로 |
| PARTIAL | 일부만 확인, 누락 범위 구체 명시 | 확인된 부분 |
"주장 수 ≠ 판정 수" — 모든 주장을 검증할 필요 없음. 핵심 주장 (decision 근거, gate 조건, hard constraint) 우선. 주변 서술은 skip 가능.
Phase 3: 위험 스트레스 테스트
나열된 위험 검증
ADR의 각 Risk 항목에 대해 codebase에서 구체적 증거를 grep합니다.
# 위험이 실제로 존재하는가? 관련 코드 패턴 검색
Grep "{위험 관련 키워드}" --type=ts -n -C 3
누락 위험 탐색 (composition 프로젝트 특화)
ADR에 명시되지 않은 잠재 위험을 능동적으로 조사:
| 위험 영역 | 탐색 방법 |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 렌더링 파리티 | CSS↔Skia 경로 양쪽에서 변경 영향 grep |
| 성능 절벽 | O(n) 순회, WASM 반복 호출, 불필요한 리렌더 패턴 |
| 마이그레이션 깨짐 | 영향받는 파일 수 grep, import 체인 추적 |
| 레이아웃 부작용 | layoutVersion 5-심볼 2계층 체인 점검 — A(트리거): LAYOUT_AFFECTING_PROP_KEYS (layoutInvalidation.ts, props) / NON_LAYOUT_PROPS_UPDATE (elementUpdate.ts, style blacklist) / INHERITED_LAYOUT_PROPS_UPDATE · B(캐시 시그니처, layoutCache.ts): LAYOUT_STYLE_KEYS (style) / LAYOUT_PROP_KEYS (props). A·B 는 AND, 축별 배열 상이 |
| 상태 동기화 | Zustand → Preview postMessage 누락 가능성 |
| SSOT 체인 | @sync 주석, consumer-to-consumer 참조 금지 |
대안 위험 레벨 검토
- 모든 대안이 HIGH → 대안 추가 필요 플래그
- LOW/MEDIUM 대안이 있는데 선택하지 않았다면 → Decision 근거 재검토
"누락 위험 없음" 정당 사유
위 영역에서 실제 증거를 찾지 못하면 "누락 위험 0건" 으로 보고. 억지로 위험을 만들어내지 않는다.
Phase 3-H: 근본 반론 (hate) — root 1개 + first nail (2026-08-28, 병합 순서 ④)
Phase 3 이 "나열된 위험이 실재하는가" 를 보는 것과 달리, 3-H 는 계획 전체를 무너뜨리고 싶은 사람이 먼저 공격할 자리 를 찾는다. 체크리스트가 아니라 root 하나 + first nail 하나 를 돌려준다 (paperthin hate 의 composition 재구현).
- load-bearing 가정 을 적는다 — Decision 이 서 있으려면 반드시 참이어야 하는 것 (보통 1~3개). ADR 이 명시하지 않은 암묵 가정을 우선한다.
- 공격 축 (해당하는 것만):
- load-bearing 사실이 거짓 — Context 의 "현재 X 다" 서술이 코드와 다름 (Phase 2 UNVERIFIED 와 연결)
- confabulation — 사후 설명을 근거로 취급 (리뷰 round 1 의 결론을 그대로 승계한 문장 포함)
- analogy ≠ isomorphism — 외부 참조 (OpenPencil / RSP / Figma 관례) 의 구조가 composition 에도 성립한다고 가정 — 참조 쪽에 있고 이쪽에 없는 전제 (두 번째 host, 다른 SSOT) 를 찾는다
- 측정 leakage — Gate 통과 수치의 oracle 이
measurement-validity.md§2 8-패턴에 해당 → 그 Gate 는 통과 불가능하거나 vacuous - 소비 경로 부재 — "기구현 인프라 활성화" 를 근거로 쓰는데 3-grep (import/caller · flag 실배선 · factory 경유) 미통과
- 조건부 편익 — 편익이 ADR 스스로 선택적이라 선언한 후속 (별도 ADR / 조건부 Gate) 에만 실현되는데 비용은 지금 전부 지불
- 발견을 root 하나 로 접는다 — 그것이 무너지면 나머지 반론이 무의미해지는 것. 목록 반환 금지.
- first nail — root 가정을 가장 싸게 반증할 검사 (시간/비용/표본). 반드시 그 가정 위에 세워진 프로그램보다 싸야 한다. 이미 Gate 에 같은 검사가 있으면 "G{n} 이 커버" 로 종결.
- 판정 매핑: first nail 이 어느 Gate 에도 없고 root 가 Decision 을 무너뜨리는 성질이면 이슈 (심각도 = root 가 죽이는 것의 크기; 카테고리
evidence-missing/alternative-strawman/other). Gate 가 이미 커버하면 이슈 아님 — 보고에 "hate: G{n} 커버" 1줄.
규칙: 공격만 한다 — 개선안은 다른 reflex. root 는 진짜 load-bearing 이어야 한다 (그것 없이도 계획이 서면 root 가 아니다). first nail 이 프로그램보다 비싸면 nail 이 아니다. 전제 확정 종결 계약 (CLAUDE.md §전제·관점) 과의 관계: 이미 승인된 round 가 있는 ADR 에서 3-H 가 전제 수준 root 를 찾으면 기록하되 재질문하지 않는다 — 이슈는 다음 착수 조건 (Phase 0 / 기준선 갱신) 으로 deferred 하고, 재개는 사용자 재제기·scope 변경·의존 반전 증거 3경로뿐.
Phase 3-P: 렌즈 대조 (prism) — 조건부 (2026-08-28)
실행 조건: HIGH 위험 ≥ 1 또는 breakdown phase ≥ 3 인 ADR 만 (복수 렌즈는 opt-in 비용 — 수렴이 자동 증명으로 둔갑하면 안 된다). 조건 미달이면 "prism: 해당 없음" 1줄.
- ADR 을 끝까지 읽은 뒤 서로 다른 failure mode 하나당 렌즈 하나 를 이 ADR 에 맞춰 새로 고른다 (2~5개) — 예: 정합성/SSOT · 비용/성능 · 측정 무결성 · 되돌림/rollout · 사용자 적대 시나리오. 같은 failure mode 를 공유하는 두 렌즈는 하나다 ("보안 리뷰어" 와 "시니어 보안 리뷰어" 는 렌즈 하나).
- 렌즈마다 한 줄 판정 (pass / fail / unclear) + load-bearing 이유 하나. 목록을 내는 렌즈는 hedging 이다.
- 판정을 묶는다: 전원 일치 / 다른 이유로 일치 / 불일치.
- 불일치가 있으면 그것을 일치 또는 owner 가 있는 깔끔한 분기로 바꿀 질문 하나 를 낸다 — 이 질문이 산출물이다. 평균 내지 않는다.
- 전원 일치면 공유 판정 + 2개 이상 렌즈에서 load-bearing 이었던 이유만 보고. 불일치를 만들어내지 않는다 — 없으면 없다고 쓰고 끝.
Phase 3.5: Pre-Report Evidence Freeze (CRITICAL)
Phase 4 보고 직전 필수 단계. 지금까지 수집한 판정 중 file:line 인용이 있는 것만 최종 보고에 포함시킨다. 인용 없는 판정은 Phase 4 에서 제외하거나 UNVERIFIED 로 다운그레이드.
# 체크포인트 (mental check):
1. 각 VERIFIED 판정에 file:line 있는가?
2. 각 FAIL 판정에 ADR 의 line 인용 있는가?
3. 모든 "누락 위험 발견" 항목에 grep 결과 있는가?
4. Phase 2 에서 UNVERIFIED 분류된 항목을 Phase 4 에서 FAIL 로 승격하지 않았는가?
증거 부족 시 대응: 해당 판정을 삭제하거나 UNVERIFIED - evidence missing 으로 표기. 무증거 단정 금지. Phase 3-H 의 root / 3-P 의 렌즈 이유도 같은 규칙 — ADR:line 또는 file:line 인용 없는 root 는 보고에서 제외.
Phase 4: 결과 보고
형식 (slot 전부 채울 필요 없음)
## ADR 리뷰 결과: ADR-NNN {제목}
### 구조 검증
| 섹션 | 판정 | 품질 | 인용 |
| ----------------------------------- | ----------------- | ------------ | ------------ |
| Context | PASS/PARTIAL/FAIL | HIGH/MED/LOW | `ADR:line N` |
| Alternatives (2개+) | PASS/PARTIAL/FAIL | HIGH/MED/LOW | `ADR:line N` |
| 4축 위험 평가 | PASS/PARTIAL/FAIL | HIGH/MED/LOW | `ADR:line N` |
| Risk Threshold Check | PASS/PARTIAL/FAIL | HIGH/MED/LOW | `ADR:line N` |
| Decision 위험 수용 근거 | PASS/PARTIAL/FAIL | HIGH/MED/LOW | `ADR:line N` |
| Risks (Decision 뒤/Gates 앞, ID 표) | PASS/PARTIAL/FAIL | HIGH/MED/LOW | `ADR:line N` |
| Gates | PASS/PARTIAL/FAIL | HIGH/MED/LOW | `ADR:line N` |
### 코드 검증 (핵심 주장만)
| 주장 | 판정 | 근거 |
| -------- | --------------------------- | --------------------- |
| "{주장}" | VERIFIED/UNVERIFIED/PARTIAL | `file:line` 또는 시도 |
### 위험 평가
| 위험 | 증거 | 심각도 | 상태 |
| ---------------- | ----------- | ------------ | -------- |
| {ADR 나열 위험} | `file:line` | HIGH/MED/LOW | 기재됨 |
| {탐색 발견 위험} | `grep 결과` | HIGH/MED/LOW | **누락** |
**또는** `누락 위험 없음` — 탐색 결과 추가 위험 미발견.
### 근본 반론 (hate)
- **load-bearing 가정**: {Decision 이 서기 위해 참이어야 하는 것} (`ADR:line`)
- **root**: {그것이 무너지면 나머지가 무의미해지는 반론 1개} — 공격 축: {사실 거짓 / confabulation / analogy≠isomorphism / 측정 leakage #n / 소비 경로 / 조건부 편익}
- **first nail**: {가장 싼 반증 검사} — 비용 {시간/표본} vs 프로그램 {Phase 수/Gate 수}
- **판정**: G{n} 커버 / 이슈 #{id} ({severity}, deferred → {착수 조건})
### 렌즈 대조 (prism) — 조건부
| 렌즈 (failure mode) | 판정 | load-bearing 이유 |
| ------------------- | ----------------- | ----------------- |
| {정합성/SSOT} | pass/fail/unclear | {이유 1개} |
| {비용/성능} | pass/fail/unclear | {이유 1개} |
- **수렴**: {전원 일치 / 다른 이유로 일치 / 불일치 — 어느 렌즈끼리}
- **해결 질문 1**: {불일치를 가르는 질문} 또는 `불일치 없음`
### 종합 판정
- **구조**: PASS/PARTIAL/FAIL ({FAIL 섹션 있으면 목록})
- **코드 정합**: N/M VERIFIED (검증 시도 수)
- **누락 위험**: N건 (HIGH X / MED Y / LOW Z) 또는 `0건`
- **권고**:
- **HIGH**: {필수 수정 이슈} 또는 `없음`
- **MEDIUM**: {권장 수정} 또는 `없음`
- **LOW**: {선택적 개선} 또는 `없음`
- **결론**: 승인 가능 / 수정 후 재리뷰 / 재설계 필요
"이슈 0건 권고" 예시
ADR 이 건전하면 아래와 같이 보고:
### 종합 판정
- 구조: PASS (7/7 섹션 HIGH 품질)
- 코드 정합: 8/8 VERIFIED
- 누락 위험: 0건
- 권고:
- HIGH: 없음
- MEDIUM: 없음
- LOW: 없음
- 결론: **승인 가능**
Phase 4.5: Layer 0 영속화 (자동 저장)
Phase 4 의 마크다운 결과를 출력한 후, 아래 JSON payload 를 stdin 으로 writer 에 전달하여 docs/adr/reviews/NNN.md 에 저장합니다. Fail-soft — writer 실패해도 Phase 4 사용자 출력은 영향 받지 않습니다.
호출 방법
cat <<'EOF' | node .claude/scripts/adr-review/writer.mjs
{
"adr": <ADR번호>,
"title": "<ADR 제목>",
"reviewer": "claude",
"source": "live",
"issues": [
{
"severity": "CRITICAL | HIGH | MEDIUM | LOW",
"category": "<.claude/scripts/adr-review/ 9-taxonomy>",
"summary": "<한 줄 요약>",
"evidence": "<파일:line>",
"root_cause": "<...>",
"outcome": "<기록 시점 실제 상태: pending | fixed | deferred | rejected>"
}
],
"bodyMd": "<Phase 4 마크다운 본문>",
"hate": { "assumption": "<load-bearing 가정>", "root": "<반론 1개>", "axis": "<공격 축>", "first_nail": "<가장 싼 반증>", "verdict": "<G{n} 커버 | issue:{id}>" },
"prism": { "lenses": [ { "lens": "<failure mode>", "verdict": "pass|fail|unclear", "reason": "<이유 1개>" } ], "convergence": "<일치|다른 이유로 일치|불일치>", "question": "<해결 질문 1 | 없음>" }
}
EOF
issues 가 빈 배열([])이어도 정상 — Layer 0 에 "이슈 없음 승인" 기록으로 저장. hate / prism 은 선택 필드 (3-P 미실행이면 prism 생략) — writer 가 round frontmatter 에 그대로 보존한다.
Outcome 종결 의무 (2026-07-11 — 종결 계약 연계, CRITICAL)
outcome은 기록 시점의 실제 상태를 반영한다 — 기본값pending을 기계적으로 넣지 않는다. 리뷰 중 이미 해소를 확인한 이슈는fixed+addressed_in(commit/round 참조) 로 기록.- 종합 판정이 "승인 가능" 인 round 는
pending잔존 금지 — 각 이슈를fixed/deferred/rejected중 하나로 종결한다. 이전 round 의pending이슈도 해소 여부를 확인해 해당 round frontmatter 의outcome을 직접 갱신한다 (round 본문은 append-only 보존, frontmatter outcome 필드만 상태 갱신 대상). - Why: execute-adr auto 모드와 전제 확정 종결 계약 (CLAUDE.md §전제·관점 의문 처리) 이 최신 round 의 outcome 을 기계 판독한다.
pending잔존 = 실질 승인 ADR 이 미확정으로 판정되어 착수 시점 재질문 루프 재발 (2026-07-11 진단: 912=7 / 913=10 pending 잔존 실측 — 본문 프로즈는 "승인 가능" 인데 frontmatter 는 미종결).
출력 처리
- 성공:
→ saved to docs/adr/reviews/NNN.md (round N)한 줄을 Phase 4 결과 끝에 추가. exit 0. - Malformed 복구:
→ saved (malformed recovery) to NNN.{ts}.md한 줄 추가. exit 1 무시 (data preserved). - Fatal (required 필드 누락, IO 실패):
writer: <error>warning 만 출력. Phase 1~4 정상 완료.
스키마 / taxonomy
- Schema SSOT: docs/adr/reviews/README.md
- Design rationale: docs/reference/schemas/ADR_REVIEW_LAYER0.md
- Validator:
node .claude/scripts/adr-review/validate.mjs
이슈 처리 원칙
- HIGH/MEDIUM 이슈는 "범위 외" 로 스킵하지 않는다 — 단, 증거 있는 이슈만 해당
- 코드 검증 없이 ADR 주장을 사실로 수용하지 않는다 — 동시에 근거 없이 부정하지도 않는다
- UNVERIFIED 항목은 반드시 보고하고, ADR 수정 또는 코드 구현 필요 여부를 명시한다
- 위험이 발견됐지만 ADR 에 없으면 "누락 위험" 으로 분류하고 grep 증거를 첨부
- "이슈 없음" 은 정당한 결론 — 건전한 ADR 을 "결함 있는 것처럼" 보고하지 않는다
Subagent 운영 가이드 (재발 방지)
본 skill 을 subagent 에 위임할 때의 안전 원칙:
1-shot 완결 원칙
subagent 를 dispatch 했다면 처음부터 Phase 4.5 까지 한 번에 수행. 중간에 "일단 여기까지 보고" 지시 금지.
중단 발생 시
subagent 가 Phase 2/3 중간에 응답을 멈추고 새 turn 을 요구하면:
| 상황 | 권장 조치 | | ---------------------- | ----------------------------------------------------- | | Main 이 동일 리뷰 가능 | main 이 직접 재수행 (가장 빠르고 신뢰 높음) | | Main 컨텍스트 포화 | 새 agent 1-shot dispatch (SendMessage 이어받기 X) | | 결과 일부 이미 유효 | 증거 인용 있는 판정만 채택, 나머지는 main 이 보충 |
SendMessage 금지 사유
Subagent 의 context 는 autocompact 되면 원문 세부가 압축된다. SendMessage 로 "최종 보고만 제출" 요청 시 압축된 기억에 의존 → Phase 4 템플릿 slot fill 압박과 결합하여 hallucination 가능성 HIGH.
확증 역할 분리
Subagent 리뷰 결과는 가설 (hint) 로 취급. Main 은 확증자 (verifier) 로 file:line 인용을 원문에서 cross-check. 이 역할 분리가 reviewer 개별 신뢰도보다 안전.
Evals
Positive (이 스킬을 실행해야 하는 경우)
- "이 ADR 리뷰해줘" → ✅
- "설계 문서 검토 부탁" → ✅
- "ADR-051 위험 평가가 맞는지 확인해봐" → ✅
- "아키텍처 결정 문서 리뷰" → ✅
- "review ADR" → ✅
Negative (이 스킬을 실행하면 안 되는 경우)
- "코드 리뷰해줘" → ❌ (코드 리뷰 → reviewer 에이전트)
- "README 수정해줘" → ❌ (문서 편집)
- "ADR 새로 작성해줘" → ❌ (작성 → create-adr 스킬 (
/create-adr)) - "PR 리뷰해줘" → ❌ (PR → reviewer 에이전트)
API Documentation Generator
Documentation
Automatically generates OpenAPI/Swagger API documentation.
Technical Writer
Documentation
Writes clear technical documentation following top style guides.
CodeTour Guided Walkthroughs
Documentation
Create .tour files for step-by-step code walkthroughs, tailored to personas like onboarding, PR review, RCA, and feature explanation.