Files
llm-wiki/harness/source/skills/sync.md
T

9.5 KiB

문서 간 모순·위임 동기화를 검사하고 수거합니다. (계약: 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 <slug> 가 주어지면 대신 python3 .claude/hooks/wiki_consistency_check.py --impact <slug> (해당 노트의 결정을 참조하는 문서 역추적).

    • --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의 <!-- GENERATED: children:start --><!-- GENERATED: children:end --> 블록은 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_OWNERSHIPCRITICAL, BARE_DECISION_REF / BARE_OWNER_REFWARN.
    • 이 검사들을 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_indexerDRIFT수기로 고치지 말고 --write 로 재생성한다. 생성기가 SSOT 이므로 수기 수정은 다음 재생성에서 되돌아온다.
  • layout_checkMIGRATION_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 으로 세지 말 것.
  1. 팩킷 준비 (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.

  2. 명시 참조 엣지 의미 대조 — 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 블록).
  3. local/hub semantic certificate 수거 + impact audit

    • semantic_certificate.py --root . --check로 stale/missing certificate를 수거한다.
    • project 변경은 full hub, branch 변경은 local + typed graph direct impactwiki-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이다.
  4. 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 위험 — 묶음 승인 제안 가능.
  5. 승인된 항목만 Edit

    • 재진술 수거 시 기존 본문 의미 보존 — 세부 내용을 owner 로 이관했는지, 중복이라 삭제했는지 fix-plan 에 명시한 대로만.
    • high 위험(본문 의미 변경·hub 갱신)은 절대 묶음 적용 금지 — 개별 승인.
    • 적용 중 owner D-row 를 건드리면 PostToolUse 훅(wiki_consistency_check.py --post)이 역참조 충격을 비차단 알림 — 같은 세션에서 반영.
  6. 재검사 + 로그 + 요약

    • 적용 후 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 불일치면 완료 판정을 차단한다.