9.5 KiB
문서 간 모순·위임 동기화를 검사하고 수거합니다. (계약: rules/consistency-contract.md — Single-Owner + Reference-Only)
대상: {{arguments}} (지정 안 하면 raw/branch-notes/ + raw/project-notes/ 전수)
작업 절차 — 결정론 선행 (LLM 수기 재연 금지)
-
결정론 검사기 (필수 1단계)
python3 .claude/hooks/wiki_consistency_check.py --all--impact <slug>가 주어지면 대신python3 .claude/hooks/wiki_consistency_check.py --impact <slug>(해당 노트의 결정을 참조하는 문서 역추적).--all은.claude/hooks/wiki_graph_contract_check.py의 v2 structured graph 검사를 이미 병합한다. 디버깅은 독립 CLIpython3 .claude/hooks/wiki_graph_contract_check.py --all로 재현한다.- 신규 validation output 8종:
AMBIGUOUS_WIKILINK(동명 basename은 full path 필수) + graphMISSING_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의<!-- GENERATED: children:start -->…<!-- GENERATED: children:end -->블록은 reverse view로만 대조하며,MISSING_EXPECTED_EDGE는 batch/post-sync에서만 판정한다. - marker/table 없는 legacy 문서는 strict failure가 아닌
LEGACY_GRAPH_CONTRACTmigration warning + skip으로 보존한다. - findings 를 그대로 흡수:
DANGLING_DECISION_REF/DANGLING_SECTION_REF/DUAL_OWNERSHIP→ CRITICAL,BARE_DECISION_REF/BARE_OWNER_REF→ WARN. - 이 검사들을 LLM 이 수기로 재연하지 않는다 — 검사기 출력이 결정론 SSOT.
-
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_sha256drift 가 두 프로젝트 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 으로 세지 말 것.
-
팩킷 준비 (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.
-
명시 참조 엣지 의미 대조 —
wiki-consistency-auditordispatch- 입력: 1단계 검사기 출력 + 팩킷 파일 경로(
/tmp/sync-packets.md) + 대조할 참조 엣지 목록 (엣지 = citing 문서 / owner 문서 / D-id·§-id + 양 노트 경로). - 기본 슬라이스: DANGLING / DUAL_OWNERSHIP 관련 엣지 + 사용자가 지정한 대상 경로의 엣지. 전수 대조는 엣지 수를 먼저 보고하고 사용자 확인 후에만.
- 엣지 >20개면 슬라이스로 분할해 병렬 dispatch.
- 출력: 엣지별
CONSISTENT/STALE_SUMMARY/CONTRADICTION/RESTATED_FOREIGN_DECISIONverdict (+ wiki-verdict/wiki-stats 블록).
- 입력: 1단계 검사기 출력 + 팩킷 파일 경로(
-
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이다.
-
fix-plan 표 —
/lint --fix-plan과 동일 규율 (위험도·승인 필요·패치 범위):Finding 필요한 수정 대상 파일:line 위험 승인 필요? 패치 범위 <실패 모드 + 한 줄><무엇을 어떻게 바꾸는가>path:linelow / 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 위험 — 묶음 승인 제안 가능.
- owner-우선 해소 원칙 (
-
승인된 항목만 Edit
- 재진술 수거 시 기존 본문 의미 보존 — 세부 내용을 owner 로 이관했는지, 중복이라 삭제했는지 fix-plan 에 명시한 대로만.
- high 위험(본문 의미 변경·hub 갱신)은 절대 묶음 적용 금지 — 개별 승인.
- 적용 중 owner D-row 를 건드리면 PostToolUse 훅(
wiki_consistency_check.py --post)이 역참조 충격을 비차단 알림 — 같은 세션에서 반영.
-
재검사 + 로그 + 요약
-
적용 후
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:
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 <proof-request.json> --repo-root . --output <report-dir>/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 불일치면 완료 판정을 차단한다.