문서 간 모순·위임 동기화를 검사하고 수거합니다. (계약: `rules/consistency-contract.md` — Single-Owner + Reference-Only) **대상:** {{arguments}} (지정 안 하면 `raw/branch-notes/` + `raw/project-notes/` 전수) ## 작업 절차 — 결정론 선행 (LLM 수기 재연 금지) 1. **결정론 검사기 (필수 1단계)** ``` python3 .claude/hooks/wiki_consistency_check.py --all ``` `--impact ` 가 주어지면 대신 `python3 .claude/hooks/wiki_consistency_check.py --impact ` (해당 노트의 결정을 참조하는 문서 역추적). - `--all`은 `.claude/hooks/wiki_graph_contract_check.py`의 v2 structured graph 검사를 이미 병합한다. 디버깅은 독립 CLI `python3 .claude/hooks/wiki_graph_contract_check.py --all`로 재현한다. - 신규 validation output 8종: `AMBIGUOUS_WIKILINK`(동명 basename은 full path 필수) + graph `MISSING_PROJECT_BINDING` / `MISSING_INHERITED_DECISION` / `STALE_INHERITANCE_REVISION` / `CONFLICTS_WITH_PROJECT_DECISION` / `UNDECLARED_OVERRIDE` / `MISSING_EXPECTED_EDGE` / `DUPLICATE_DECISION_OWNER`. Link ambiguity는 structure lint, graph 7종은 consistency `--all`이 각각 수거한다. - Parent edge는 child의 structured `project` / `parent_branch` 또는 `Branch Contract Packet`이 canonical이다. Hub의 ``…`` 블록은 reverse view로만 대조하며, `MISSING_EXPECTED_EDGE`는 batch/post-sync에서만 판정한다. - marker/table 없는 legacy 문서는 strict failure가 아닌 `LEGACY_GRAPH_CONTRACT` migration warning + skip으로 보존한다. - findings 를 그대로 흡수: `DANGLING_DECISION_REF` / `DANGLING_SECTION_REF` / `DUAL_OWNERSHIP` → **CRITICAL**, `BARE_DECISION_REF` / `BARE_OWNER_REF` → **WARN**. - 이 검사들을 LLM 이 수기로 재연하지 않는다 — 검사기 출력이 결정론 SSOT. 2. **typed contract 검사** ``` python3 harness/runtime/typed_contract_check.py --root . ``` owner/revision/import/delegation/projection findings를 별도 `typed findings`로 수거한다. 실패해도 의미 결과로 덮어쓰지 않으며 explicit blocking으로 통합한다. 2-b. **투영 drift · 레이아웃 · MOC · branch postflight (필수 — 위 두 검사가 보지 못하는 축)** ``` python3 harness/runtime/contract_projection.py --check --root . python3 harness/runtime/layout_check.py --root . python3 harness/runtime/moc_indexer.py --check for f in raw/branch-notes/*.md; do python3 harness/runtime/branch_contract_check.py "$f" --postflight --root . done ``` > **이 검사들이 `/sync` 에 없던 동안 무슨 일이 있었나** (2026-07-21~22 실측): > `branch_contract_check` 는 vault cutover 이후 심링크를 resolve 한 경로로 위치를 판정해 > **모든 branch 를 거부**했고(status=ERROR), 아무도 그것을 돌리지 않아 `contract_packet_sha256` > drift 가 두 프로젝트 **82건** 쌓이는 동안 sweep 은 계속 `findings 0` 을 반환했다. > `contract_projection --check` 는 셀 정규화 버그로 깨진 코드스팬 15곳을 들고 있었고, > `moc_indexer --check` 는 hub reverse-view 3건이 낡은 상태였다. > 즉 "consistency + typed 통과 = 깨끗하다"는 성립하지 않는다 — 축들이 서로를 못 본다. > > 비용은 전부 합쳐 ~6.5초다(2026-07-22 실측: consistency 0.56s · typed 0.29s · > projection 0.40s · layout 1.41s · structure lint 2.32s). 느려서 뺄 이유가 없다. - `contract_projection` / `moc_indexer` 가 `DRIFT` 면 **수기로 고치지 말고** `--write` 로 재생성한다. 생성기가 SSOT 이므로 수기 수정은 다음 재생성에서 되돌아온다. - `layout_check` 의 `MIGRATION_LEGACY_EXTRA` / `INVALID_COMPATIBILITY_SYMLINK` 는 호환 심링크가 실파일로 대체됐다는 신호다(writer 가 정본 대신 링크를 덮어쓴 경우). 정본과 링크가 갈라진 split-brain 이므로 CRITICAL. - postflight 는 `GENERATED_REGION_DRIFT` / `CONFLICTS_WITH_PROJECT_DECISION` / `STALE_INHERITANCE_REVISION` / `INHERITED_DECISION_MISMATCH` 를 branch 단위로 판정한다. `status: ERROR` 는 "통과"가 아니라 **검사가 실행조차 못 했다**는 뜻이니 findings 0 으로 세지 말 것. 3. **팩킷 준비 (T0 결정론 발췌 — 0토큰, `rules/extraction-tiering.md`)** ``` python3 .claude/hooks/wiki_consistency_check.py --packets [slug] > /tmp/sync-packets.md ``` 참조 엣지 양쪽(citing ±2줄 / owner D-row)의 맥락을 결정론 추출. auditor 는 corpus 대신 이 팩킷 파일을 **1차 입력**으로 소비한다 — 판결이 모호한 엣지만 원문 해당 라인을 Read. 4. **명시 참조 엣지 의미 대조 — `wiki-consistency-auditor` dispatch** - 입력: 1단계 검사기 출력 + **팩킷 파일 경로**(`/tmp/sync-packets.md`) + **대조할 참조 엣지 목록** (엣지 = citing 문서 / owner 문서 / D-id·§-id + 양 노트 경로). - 기본 슬라이스: DANGLING / DUAL_OWNERSHIP 관련 엣지 + 사용자가 지정한 대상 경로의 엣지. **전수 대조는 엣지 수를 먼저 보고하고 사용자 확인 후에만.** - 엣지 **>20개면 슬라이스로 분할해 병렬 dispatch**. - 출력: 엣지별 `CONSISTENT` / `STALE_SUMMARY` / `CONTRADICTION` / `RESTATED_FOREIGN_DECISION` verdict (+ wiki-verdict/wiki-stats 블록). 5. **local/hub semantic certificate 수거 + impact audit** - `semantic_certificate.py --root . --check`로 stale/missing certificate를 수거한다. - project 변경은 full `hub`, branch 변경은 `local + typed graph direct impact`로 `wiki-semantic-coherence-auditor`를 실행한다. direct impact는 imported owner/consumer, 직접 dependency, delegation 상대이며 sibling 전체는 포함하지 않는다. - `semantic_surface_extractor.py` → assertion → `semantic_candidate_builder.py` → verdict → proof → `semantic_audit.py validate` 순서를 지키고, `typed findings`, `edge-semantic findings`, `local-semantic findings`, `hub-semantic findings`를 서로 섞지 않고 집계한다. - hub `AMBIGUOUS_AUTHORITY`, 모든 `CONTRADICTION`, `RESTATEMENT_DRIFT`, hub dropped candidate는 fix 전까지 blocking이다. 6. **fix-plan 표** — `/lint --fix-plan` 과 동일 규율 (위험도·승인 필요·패치 범위): | Finding | 필요한 수정 | 대상 파일:line | 위험 | 승인 필요? | 패치 범위 | |---|---|---|---|---|---| | `<실패 모드 + 한 줄>` | `<무엇을 어떻게 바꾸는가>` | `path:line` | low / med / high | yes / no | `<몇 줄 / 어느 섹션>` | - **owner-우선 해소 원칙** (`rules/consistency-contract.md` §충돌 해소): 위임한 쪽(참조자)이 요약을 갱신한다. owner 본문을 참조자에 맞춰 고치지 않는다. - `RESTATED_FOREIGN_DECISION` → **"참조 + 1줄 요약으로 교체" 제안** (세부 내용은 owner 로 이관 또는 삭제를 명시). - **hub(project-note) vs branch 충돌은 항상 개별 승인** — 자동 적용 금지. 보통 branch 가 더 최신·구체 → "project-note 갱신 제안" 형태가 기본이나, 판정은 사용자 몫. - `BARE_DECISION_REF` / `BARE_OWNER_REF` 수정(wikilink 화)은 low 위험 — 묶음 승인 제안 가능. 7. **승인된 항목만 Edit** - 재진술 수거 시 **기존 본문 의미 보존** — 세부 내용을 owner 로 이관했는지, 중복이라 삭제했는지 fix-plan 에 명시한 대로만. - high 위험(본문 의미 변경·hub 갱신)은 절대 묶음 적용 금지 — 개별 승인. - 적용 중 owner D-row 를 건드리면 PostToolUse 훅(`wiki_consistency_check.py --post`)이 역참조 충격을 비차단 알림 — 같은 세션에서 반영. 8. **재검사 + 로그 + 요약** - 적용 후 `python3 .claude/hooks/wiki_consistency_check.py --all` 재실행. **루프 천장 2회** — 2회 후 잔여 findings 는 보고 후 종료 (다음 `/sync` 로 이월). - `wiki/log.md` 한 줄: `YYYY-MM-DD HH:mm /sync — <대상> → findings n (CRITICAL c / WARN w), 적용 a / 보류 b` - 최종 요약 funnel: ```wiki-stats agent: sync found: <검출 findings 수> processed: <적용 + 보류 수> dropped: <제외 수 + 사유> ``` ## 규칙 - **무단 자동 수정 금지.** fix-plan 의 *승인된 항목만* 적용하며 사용자 확인 없이 본문을 바꾸지 않는다. - `/lint` 와의 경계: 단일 문서 품질(과장/stale/canonical 우회)은 `/lint`, **cross-doc 모순·위임 동기화는 `/sync`** — 서로 중복 검사하지 않는다. - 검사기가 침묵하는 귀속 모호 케이스(인용자 자신의 DEM 에 있는 D-id)는 Layer 2 의미 대조가 판정한다 — 결정론 출력만으로 "깨끗하다" 단정 금지. ## Proof Artifact Contract (HARD) finding/인용 draft는 exact UTF-8 quote 전부를 포함한 `proof-request/v1` JSON으로 조립한다. controller는 `python3 harness/runtime/proof_runner.py --repo-root . --output /proof-manifest.json`을 실행한다. exit 0, `schema_version: proof-runner-result/v1`, `status: PASS`, manifest `schema_version: proof-manifest/v1` 확인 전에는 workflow 완료를 선언하지 않는다. 보고서에는 `manifest_path`, `manifest_sha256`, `proof_count`, `pass_count`, `fail_count`를 기록한다. 실패 proof와 라인 정정은 전부, PASS proof는 대표 1~3개만 펼치고 나머지는 manifest를 참조한다. `fail_count != 0` 또는 count 불일치면 완료 판정을 차단한다.