15 KiB
title, source_type, status, confidence, tags, last_reviewed
| title | source_type | status | confidence | tags | last_reviewed | |||||
|---|---|---|---|---|---|---|---|---|---|---|
| LLM Wiki 하네스 설계 감사 — deep-research 기준 33파일 × 8원칙 | llm-generated | draft | medium |
|
2026-06-06 |
하네스 설계 감사 보고서 (read-only)
⚠️ 시점 스냅샷 (2026-06-06 감사 당시): 본 보고서는 구현 전 상태를 기술한다. 이후 Spec A 가 G1·G5·G6 을, Spec B 가 G3·G7 을 해소했다. 특히 §3 G1("
--hook이 항상 exit 0")·G6("claim_gate 테스트 0개")는 현재 코드에서 더 이상 사실이 아니다(--hookfix-up 시 exit 2,test_wiki_claim_gate.py존재). 우선순위 판단 시 docs/superpowers/README의 Spec A/B = DONE 상태를 함께 보라. 남은 미해소: G2(Spec D, 보류), G4(Spec C, 진행 예정).
기준선: Claude Code 내장 deep-research Workflow 스크립트 (CLI 바이너리에서 추출, 350행 — /tmp/deep_research_script.js).
대상: .claude/ 하네스 33파일 (agents 10 · commands 22 · hooks 3 · settings 2 · skill 1 — 일부는 commands에 포함, 실제 채점 파일 33개).
방법: 5개 read-only 감사 에이전트를 병렬 dispatch, 동일한 8원칙 루브릭 + 고정 output-spec 적용 → 본 문서로 합성. 파일 변경 없음.
메타: 이 감사 자체가 deep-research 패턴(fan-out readers → 고정 schema → synthesize)으로 수행됨. dogfooding.
§0. deep-research가 "잘 설계된 하네스"인 8가지 이유 (루브릭)
| # | 원칙 | deep-research 구현 | 한 줄 정의 |
|---|---|---|---|
| P1 | 강제된 output-spec | agent() 마다 JSON schema (required/enum/minItems), tool-layer 검증 + 모델 재시도 |
구조화 출력이 경계에서 검증되는가, 산문 희망인가 |
| P2 | 결정론적 오케스트레이션 | pipeline()/[barrier]가 JS 코드, 각 barrier에 왜 막는지 주석 |
fan-out/순서가 코드인가 controller-LLM 판단인가 |
| P3 | 적대적 정족수 검증 | 3표/claim, ≥2 refute면 kill, "불확실하면 refuted=true", 기권≠통과 | 독립 회의론자 + 기계적 kill 임계값 vs 단일심사/자문 |
| P4 | 우아한 저하 + funnel stats | 모든 early-return이 유효한 PARTIAL 리포트 + stats funnel |
부분결과 경로 + 깔때기 통계를 내는가 |
| P5 | 무삭제 보장 | budgetDropped[]/dupes[] 추적·노출, 캡이 보임 |
캡/탈락/스킵을 명시 보고하는가 silent인가 |
| P6 | 증거 + grep 자가검증 | claim마다 verbatim 인용 | 원문 인용 + grep 검증 |
| P7 | 최소권한 + 단일직무 | 작은 단일목적 에이전트 | scoped tools:, 하나의 일 |
| P8 | 명명된 상수 | MAX_FETCH, VOTES_PER_CLAIM 상단 |
임계값이 한 곳에 명명 vs 산문에 흩어진 매직넘버 |
채점: MATCH / PARTIAL / GAP / N-A.
§1. 33파일 × 8원칙 매트릭스
1-A. agents (10) — 대부분 GATE(read-only judge) + 3 WORKER + 1 ORCHESTRATOR
| File | P1 | P2 | P3 | P4 | P5 | P6 | P7 | P8 |
|---|---|---|---|---|---|---|---|---|
| branch-depth-auditor | PARTIAL | N-A | PARTIAL no quorum | GAP | N-A | MATCH | MATCH | MATCH |
| coverage-auditor | PARTIAL | PARTIAL | GAP single judge | GAP | N-A | MATCH | PARTIAL | MATCH |
| project-readiness-auditor | PARTIAL | N-A | PARTIAL no vote | GAP | N-A | MATCH | MATCH | MATCH |
| wiki-adversarial-reviewer | MATCH | N-A | PARTIAL no N-vote/default-refute | PARTIAL | N-A | MATCH | MATCH | PARTIAL |
| wiki-decision-researcher | PARTIAL | PARTIAL | N-A | PARTIAL | PARTIAL | MATCH | MATCH | PARTIAL |
| wiki-diagram-reviewer | MATCH | N-A | MATCH measured+HARD-STOP | GAP | MATCH | MATCH | MATCH | MATCH |
| wiki-doc-author | MATCH | N-A | N-A | PARTIAL | GAP | PARTIAL | MATCH | PARTIAL |
| wiki-link-verifier | MATCH | N-A | N-A | PARTIAL | MATCH | MATCH | MATCH | PARTIAL |
| wiki-research-lane | MATCH | N-A | PARTIAL | MATCH | PARTIAL | MATCH | MATCH | MATCH |
| wiki-source-summarizer | MATCH | N-A | N-A | PARTIAL | PARTIAL | MATCH | MATCH | MATCH |
1-B. capture commands (5) — 2 ORCHESTRATOR + 3 SCAFFOLD
| File | P1 | P2 | P3 | P4 | P5 | P6 | P7 | P8 |
|---|---|---|---|---|---|---|---|---|
| daily | N-A | N-A | N-A | PARTIAL | N-A | N-A | MATCH | N-A |
| branch | PARTIAL | N-A | GAP | PARTIAL | N-A | PARTIAL | MATCH | N-A |
| branch-spec | PARTIAL | PARTIAL prose-advisory | PARTIAL LLM-judge | PARTIAL | MATCH | PARTIAL | MATCH | GAP |
| project | PARTIAL | N-A | N-A | PARTIAL | N-A | N-A | MATCH | N-A |
| project-spec | PARTIAL | PARTIAL prose loop | PARTIAL LLM-judge | PARTIAL | MATCH | PARTIAL | MATCH | GAP |
1-C. transform/quality commands (7) — 2 TRANSFORM + 3 GATE + 1 QUERY + 1 MIGRATION
| File | P1 | P2 | P3 | P4 | P5 | P6 | P7 | P8 |
|---|---|---|---|---|---|---|---|---|
| ingest | GAP | N-A | N-A | GAP | PARTIAL | MATCH | MATCH | N-A |
| tag | GAP | N-A | N-A | GAP | N-A | N-A | MATCH | N-A |
| lint | PARTIAL | PARTIAL (post-hoc) | PARTIAL advisory | PARTIAL | MATCH | PARTIAL | MATCH | PARTIAL |
| query | GAP | N-A | PARTIAL | N-A | N-A | MATCH | MATCH | N-A |
| depth | PARTIAL | MATCH linter→LLM gate | PARTIAL single auditor | PARTIAL | N-A | N-A | MATCH | PARTIAL |
| coverage | PARTIAL | MATCH gate ordering | PARTIAL single auditor | PARTIAL | N-A | N-A | MATCH | PARTIAL |
| migrate-claims | PARTIAL | MATCH Phase0-4 interlock | PARTIAL default-UNSUPPORTED | MATCH | MATCH | MATCH | MATCH | PARTIAL |
1-D. output + invest commands (10) — 4 DERIVE + RESEARCH/LEDGER/PLAN/REVIEW
| File | P1 | P2 | P3 | P4 | P5 | P6 | P7 | P8 |
|---|---|---|---|---|---|---|---|---|
| projectize | PARTIAL | N-A | N-A | GAP | N-A | PARTIAL | MATCH | GAP |
| interviewize | PARTIAL | PARTIAL gate steps | N-A | GAP | N-A | PARTIAL | MATCH | GAP |
| blogify | MATCH | PARTIAL gate steps | N-A | GAP | N-A | PARTIAL | MATCH | GAP |
| explain | PARTIAL | N-A | N-A | GAP | N-A | PARTIAL | MATCH | N-A |
| invest-daily | PARTIAL | N-A (delegates DR) | N-A | GAP | GAP | PARTIAL no grep | MATCH | GAP |
| invest-decide | PARTIAL | PARTIAL gate steps | PARTIAL soft-block | GAP | N-A | GAP no grep | MATCH | GAP |
| invest-ingest | PARTIAL | PARTIAL | PARTIAL REJECT-excl | GAP | N-A | PARTIAL | MATCH | N-A |
| invest-plan | PARTIAL | PARTIAL | N-A | GAP | N-A | PARTIAL | MATCH | PARTIAL |
| invest-research | PARTIAL | N-A (delegates DR) | PARTIAL no quorum | GAP | N-A | MATCH self-grep | MATCH | N-A |
| invest-review | PARTIAL | PARTIAL | N-A | GAP | N-A | GAP no grep | MATCH | PARTIAL |
1-E. infra: hooks + settings + skill (6) — 결정론 backbone
| File | P1 | P2 | P3 | P4 | P5 | P6 | P7 | P8 |
|---|---|---|---|---|---|---|---|---|
| wiki_structure_lint.py | PARTIAL | PARTIAL post-hoc, exit0 항상 | N-A | MATCH fail_by_type | PARTIAL hook[:10] | PARTIAL | MATCH | MATCH templates SSOT |
| wiki_claim_gate.py | MATCH | MATCH PreToolUse exit-2 | PARTIAL keyword block | PARTIAL | GAP | PARTIAL | MATCH | GAP inline 하드코딩 |
| test_wiki_structure_lint.py | PARTIAL | MATCH | N-A | PARTIAL | PARTIAL | PARTIAL | MATCH | PARTIAL |
| settings.json | PARTIAL | PARTIAL Post=after-fact | N-A | N-A | N-A | N-A | MATCH | N-A |
| settings.local.json | N-A | N-A | N-A | N-A | N-A | N-A | GAP blanket Bash | N-A |
| wiki-workflow/SKILL.md | PARTIAL | GAP advisory dispatch | PARTIAL | PARTIAL | N-A | MATCH | MATCH | PARTIAL re-list |
§2. 강점 — deep-research 수준 이상 (건드리지 말 것)
- P6 증거 규율이 최강. self-grep verbatim 검증이
wiki-source-summarizer·wiki-research-lane·wiki-diagram-reviewer·/migrate-claims·invest-research에서 기계적으로 명세됨(grep -nF/sed -n). deep-research보다 강함. - P7 최소권한·단일직무가 깨끗. 9/10 에이전트가 scoped
tools:+ "Shortcut Trap" 반-합리화 가드. (유일 예외:settings.local.jsonblanketBash.) - 결정론 layer가 존재. deep-research에는 없는
wiki_structure_lint.py(582행, 이진 PASS/FAIL) +wiki_claim_gate.py(exit-2 block) — 문서-쓰기 경계 게이트. - 두 개의 "골드 표준형" 파일이 이미 존재 → 내부 템플릿으로 승격 가능:
wiki-diagram-reviewer.md— P1·P3·P5·P8 동시 MATCH. 측정된 카운트 + HARD-STOP→0 + 명명 상수(≤10/≤8/≤1/≥95). 다른 judge 에이전트의 본보기./migrate-claims.md— P2·P4 MATCH. Phase0-4 hard interlock(Phase2는 Phase1 미완 시 BLOCKED), default-refute(UNSUPPORTED_DECISION), >10파일→슬라이스, COMPLETE/PARTIAL/BLOCKED verdict. 다른 오케스트레이터의 본보기.
§3. 횡단 체계적 갭 (deep-research가 더 체계적인 지점) — 영향순
G1 — 결정론 backbone이 실제로 막지 않는다 ⭐ 가장 구체적·고위험
wiki_structure_lint.py의 --hook 모드는 findings가 있어도 항상 sys.exit(0) (line 531) → 풍부한 린터가 경고 프린터일 뿐 게이트가 아님. 게다가 PostToolUse라 사후. 유일한 실제 차단은 wiki_claim_gate.py(PreToolUse + SubagentStop)인데 5개 path-prefix만 커버 → wiki/projects, 모든 invest-*, 파생 wiki/interview|portfolio|blog, raw/errors는 쓰기-시점 강제 전혀 없음. (블라스트: H / 레버리지: H)
G2 — 오케스트레이션이 산문-자문이지 코드가 아니다
branch-spec·project-spec은 fan-out/barrier를 번호 매긴 LLM 지시("통과 시 dispatch", "8c 루프백 반복")로 표현. 비순응 controller가 단계를 건너뛰어도 탐지 가능한 위반이 없음. deep-research의 [barrier](코드)와 대비. (단 /depth·/coverage·/migrate-claims은 P2 MATCH — 이미 깔끔한 linter→LLM 순서.) (블라스트: H / 레버리지: H, 단 Workflow는 Claude 전용)
G3 — 검증에 verdict 라벨은 있으나 정족수/kill 기계장치가 없다
모든 judge가 단일 패스(adversarial-reviewer, depth/coverage/readiness auditor, invest-research KEEP/REJECT). N-vote·default-refute·기권≠통과 없음. 역설: wiki-adversarial-reviewer의 INSUFFICIENT_CONTEXT는 불확실성을 PASS 쪽으로 — deep-research(불확실→refute)의 정반대. invest-decide는 규칙 위반을 soft-flag(설계상 사용자 주권이나 P3 PARTIAL). (블라스트: M / 레버리지: H)
G4 — funnel stats가 거의 어디에도 없다
wiki_structure_lint.py의 fail_by_type/fail_by_rule만 유일. 어떤 judge·command도 deep-research funnel(후보→처리→탈락→확정)을 안 냄. /ingest가 promotable 항목을 silent 누락했는지 알 수 없음; coverage-auditor가 관심사를 몇 개 열거했는지 보이지 않음. (블라스트: M / 레버리지: M)
G5 — P8 SSOT 분열(split-brain)
structure_lint은 templates/에서 매핑을 도출(강함). 그러나 claim_gate는 섹션명·컬럼을 inline 하드코딩, SKILL.md는 source_type를 재나열 → 택소노미 사본 3개, drift 위험. 임계값(90/30/14일, cap 6, ≥5 findings, ≥95)도 산문에 분산. (블라스트: M / 레버리지: M)
G6 — 차단 훅에 테스트가 없다
유일한 exit-2 차단기 claim_gate.py는 유닛 테스트 0개; 비차단 린터는 잘 테스트됨. 고-블라스트 컴포넌트가 덜 테스트됨(비대칭). (블라스트: M / 레버리지: L)
G7 — 에이전트 출력은 어디에서도 schema 검증되지 않는다
모든 에이전트가 산문("첫 글자 # + 고정 Output 블록 + STOP 체크리스트")을 반환, 희망으로 검증. deep-research의 초능력(tool-layer JSON schema + 재시도)이 부재. 단 — 이건 Claude Code가 Agent 호출에 schema를 강제하는 native 수단이 없어서(현재 Workflow의 agent({schema})만 가능) 부분적으로 플랫폼 제약. (블라스트: M / 레버리지: M)
§4. 우선순위 (레버리지 × 블라스트, 낮은 아키텍처 위험 우선)
| 순위 | 항목 | 갭 | 레버리지 | 블라스트 | 아키텍처 위험 | 3-플랫폼? |
|---|---|---|---|---|---|---|
| 1 | structure_lint --hook 차단화(CRITICAL/WARN 티어) + claim_gate 커버리지 확장 + SSOT 중앙화 |
G1·G5 | H | H | 낮음(기존 강화) | ✅ 공유 hook |
| 2 | judge 5종에 return-schema 강제 + adversarial-reviewer에 N-vote/default-refute/기권≠통과 | G3·G7 | H | M | 낮음 | ✅ |
| 3 | reporting-standards에 funnel-stats 계약 + ingest/coverage/depth/decision-researcher 출력에 stats 블록 | G4 | M | M | 낮음 | ✅ |
| 4 | claim_gate 유닛 테스트 + diagram-reviewer/migrate-claims를 "골드형 템플릿"으로 문서화 | G6 | M | L | 낮음 | ✅ |
| 5 | invest-daily/decide 강화: 숫자당 grep self-verify, 규칙 위반 hard-block 옵션 | G3·부분 | M | M | 낮음 | Claude 전용 |
| 6 | branch-spec/project-spec를 결정론 Workflow 스크립트로 변환 | G2 | H | H | 높음 | ❌ Claude 전용 |
6번이 "딥 재아키텍처"(앞서 보류). 1~4번이 기존 아키텍처를 deep-research 메커니즘으로 경화하는 안전한 길.
§5. spec 분할 권고 (각각 자체 spec→plan 사이클)
- Spec A — "결정론 backbone을 진짜 게이트로" ⭐ 첫 슬라이스 후보. (순위 1)
wiki_structure_lint.py --hook: CRITICAL(broken-link/missing-required-section)에 exit-2, WARN은 exit-0 유지 → 사후 경고를 사전 차단으로.wiki_claim_gate.py: path-prefix 커버리지를wiki/projects·invest-*·파생 산출물로 확장.- SSOT 중앙화: 섹션명·컬럼·source_type 매핑을 단일 모듈로(두 훅 + SKILL이 소비).
--hookfindings 잘림([:10]) 시 "N more suppressed" 명시(무삭제).- 왜 먼저: 다른 모든 spec이 "backbone이 막는다"를 전제. 위험 최저, 블라스트 최고(비차단-린터는 사실상 잠재 결함).
- Spec B — "judge 에이전트 schema + quorum" (순위 2): depth/coverage/readiness/adversarial/diagram에 return-schema; adversarial-reviewer·게이트에 선택적 N-vote + default-refute + 기권≠통과. P1+P3 동시 상승.
- Spec C — "funnel stats + 무삭제 계약" (순위 3): reporting-standards + 핵심 명령 출력에 stats 블록.
- Spec D (보류, 딥) — "branch-spec/project-spec 결정론 오케스트레이션" (순위 6): Workflow 변환, Claude 전용, 최고 레버리지·최고 위험. 사용자 명시 opt-in 필요.
§6. claim traceability 검사 (감사 메타)
본 감사는 5개 슬라이스 매트릭스에서 파일별 evidence(file:line)를 근거로 했고, 미적용 원칙은 N-A(이유)로 분리했다. 임의 보강 없이 갭은 GAP으로, 단정 불가는 PARTIAL로 표기했다. 이 보고서는 변경을 가하지 않는 read-only 산출물이며, 다음 단계는 사용자가 §5의 첫 슬라이스(Spec A)를 승인할 때 spec→plan으로 진행한다.
상태: draft (검토 전). 외부 파생 금지.