Files
document-haness/skills/technical-doc-flow/references/artifact-contracts.md
T

20 KiB

산출물 계약

아래 파일명과 순서를 그대로 사용한다. 같은 번호는 paired 또는 parallel 작업을 뜻한다. final.md에 번호가 없는 것과 finalization 뒤 09_final_report.json을 만드는 것은 의도된 구조다.

목차

  • 정본 산출물과 경로별 필수 여부
  • JSON 필드와 schema
  • 소유권, 실행 순서, staleness
  • 오류 처리와 통과 조건

정본 산출물

artifact owner 목적
00_run.json orchestrator run identity, route, input·계약·규칙 hash, stage status, omission
01_input.md orchestrator 사용자 source document와 instruction의 immutable normalized copy
01_sources.json orchestrator/intake evidence curation에 제공할 source registry와 locator
02_reader_contract.json logic architect audience, prerequisite, reader question, outcome
03_evidence_map.json evidence curator claim, evidence link, support limit, status
04_logic_map.json logic architect document kind, section dependency, reasoning role, closure
05_term_ledger.json logic architect canonical term, alias, first-use, protected identifier
07_draft.md drafter review 가능한 초안
08_logic_review.json logic reviewer 독립 logic/evidence/fidelity review
08_reader_review.json reader reviewer 독립 reader/terminology/cognitive-load review
08_lint.json deterministic validator mechanical/schema validation
final.md finalizer 요청한 출력으로 변환할 publishable Markdown source
09_final_report.json deterministic verifier 실행/문서 verdict, lint·review 요약, fidelity, limitation, omission, 상태

대체 파일명을 만들거나 두 독립 review를 한 파일로 합치지 않는다. 번호를 다른 용도로 재사용하지 않는다.

경로별 필수 여부

artifact Light Standard Deep
00_run.json 필수 필수 필수
01_input.md 필수 필수 필수
01_sources.json 필수; source 0건 허용 필수 필수
02_reader_contract.json 필수 필수 필수
03_evidence_map.json 생략 가능 필수 필수
04_logic_map.json 필수 필수 필수
05_term_ledger.json 필수 필수 필수
07_draft.md 필수 필수 필수
08_logic_review.json 생략 가능 필수 필수
08_reader_review.json 생략 가능 필수 필수
08_lint.json 필수 필수 필수
final.md 성공한 write/revise run에 필수 성공한 write/revise run에 필수 성공한 write/revise run에 필수
09_final_report.json 필수 필수 필수

optional stage를 생략하면 artifact를 만들지 않고 검증 전에 정본 {skill_dir}/scripts/update_run.py --omit로 생략 사실과 이유를 기록한다. 00_run.json을 직접 편집하지 않는다. verifier는 이 목록을 09_final_report.json.summary.omissions에 복사한다. 빈 파일을 완료 증거처럼 만들지 않는다. review-only mode는 final.md를 만들지 않고 그 이유도 omission으로 기록한다.

각 생략 파일은 정본 파일명 하나만 담은 별도 항목이어야 한다.

python3 {skill_dir}/scripts/update_run.py \
  --run-dir {run_dir} \
  --omit 03_evidence_map.json "light 경로이며 별도 근거 큐레이션이 필요하지 않다." \
  --omit 08_logic_review.json "light write 경로에서 독립 논리 리뷰를 생략했다." \
  --omit 08_reader_review.json "light write 경로에서 독립 독자 리뷰를 생략했다."

omission-only 호출은 status를 유지한다. 마지막 status 전이와 같은 원자 쓰기로 처리하려면 같은 명령에 --status--reason을 함께 준다. 여러 파일을 "08_logic_review.json, 08_reader_review.json"처럼 한 문자열로 합치지 않는다. 필수 artifact, 이미 존재하는 artifact, 계약에 없는 이름도 omission으로 선언하지 않는다. CLI가 이 오류와 중복을 즉시 거절한다.

나중에 생략했던 artifact를 만들기로 결정했다면 artifact 파일을 만들기 전에 기존 선언을 철회한다. --unomit은 반복할 수 있고 --omit 또는 --status와 같은 원자 호출에 넣을 수 있다. unknown 또는 아직 선언하지 않은 artifact를 철회하면 실패한다.

python3 {skill_dir}/scripts/update_run.py \
  --run-dir {run_dir} \
  --unomit 08_logic_review.json

필수 의미 필드

schema가 선언하지 않은 common envelope를 임의로 추가하지 않는다. run identity, route, stage state, content hash는 00_run.json에서 관리하고 다른 JSON은 자기 schema만 따른다. 00_run.json.contract_sha256, rules_version, rules_sha256은 초기화에 사용한 정본 runtime contract와 quality-rules의 정확한 byte hash·의미 버전이다. route_metrics는 brief·draft·모든 UTF-8 source를 합친 total_chars, total_headings, 외부 source_count를 기록한다. 정상 lint report도 같은 rules version/hash를 기록한다.

  • 02_reader_contract.json: schema_version, document_kind, primary_audience, purpose, reader_question, reader_outcome, prerequisites, assumed_known, must_explain, non_goals
  • 03_evidence_map.json: schema_version, claims; 각 claim은 id, statement, status, load_bearing, source_ids, source_locations, does_not_support. source_locations{source_id, locator}source_ids와 정확히 같은 ID 집합을 가리키며 사실형 상태에는 하나 이상 필요하다. status는 source_backed | observed | measured | derived | recommended | assumption
  • 04_logic_map.json: schema_version, title, document_kind, core_claim, sections, closure; 각 section은 id, heading, role, depends_on, reader_state_before, question, answer_plain, claim_ids, new_terms, transition_to, reader_state_after. 선택 필드는 required_markers, proves, does_not_prove
  • 05_term_ledger.json: schema_version, assumed_known, budgets, terms; 각 term은 id, canonical, plain_definition, why_needed, aliases, first_section, first_use. first_use에는 정식 용어가 들어가고 그 문구와 정식 용어가 주석이 아닌 실제 본문에 있어야 한다. 선택 필드는 english, abbreviation, protected
  • 08_logic_review.json, 08_reader_review.json: schema_version, 정확한 review_type, document, inputs, verdict, findings. document.path는 현재 07_draft.md, document.sha256는 그 파일의 lowercase SHA-256이다. inputs는 현재 01_input, 01_sources, 02_reader_contract, optional 03_evidence_map, 04_logic_map, 05_term_ledger의 byte hash를 고정하며 없는 optional만 null이다.

reader reviewer에게 전달되는 01_sources.json과 optional 03_evidence_map.json은 이 provenance hash를 계산하기 위한 입력일 뿐이다. reader reviewer는 registry, claim, 실제 source 내용을 열어 독자 이해도 판정에 사용하지 않는다.

array는 empty가 실제 의미상 유효할 때만 비울 수 있다. required work가 없다는 뜻으로 null, TBD, ?, plausible placeholder를 넣지 않는다.

Schema mapping

JSON artifact는 {skill_dir}/schemas/ 아래 대응 schema로 검증한다.

artifact schema
00_run.json run.schema.json
01_sources.json sources.schema.json
02_reader_contract.json reader-contract.schema.json
03_evidence_map.json evidence-map.schema.json
04_logic_map.json logic-map.schema.json
05_term_ledger.json term-ledger.schema.json
08_logic_review.json review.schema.json with review_type: logic
08_reader_review.json review.schema.json with review_type: reader
08_lint.json lint-report.schema.json
09_final_report.json final-report.schema.json

Markdown artifact는 JSON Schema 대신 UTF-8, balanced fence, link, heading, placeholder, hash를 structural lint로 검사한다.

소유권과 불변성

agent는 자기 artifact만 쓴다. upstream defect를 읽는 쪽에서 고치지 않는다.

  • 01_input.md는 intake 뒤 immutable이다. 사용자 입력이 바뀌면 새 hash로 downstream을 무효화한다.
  • 01_sources.json, 03_evidence_map.json, 04_logic_map.json, 05_term_ledger.json은 read-only contract다. 결함은 owner에게 반환한다.
  • reviewer는 자기 08_*_review.json만 쓰고 07_draft.md나 상대 review를 수정하지 않는다.
  • finalizer는 확정된 07_draft.md를 byte-identical final.md로 복사한다. draft, map, lint, review를 고치지 않는다.
  • deterministic verifier만 09_final_report.json을 쓴다.

runtime이 지원하면 temporary file을 검증한 뒤 target으로 교체해 atomic write한다. 일부만 쓰인 canonical artifact를 남기지 않는다. lint/verifier는 입력 경로 alias나 다른 도구의 기존 파일을 report output으로 덮어쓰지 않는다. 처음 만드는 report는 대상 이름이 비어 있을 때만 원자적으로 게시하고, 같은 도구의 기존 report를 갱신할 때는 사전 검사한 파일의 장치·식별자·크기·시간·내용 hash가 그대로인지 게시 직전에 다시 확인한다. 다만 운영체제가 “기존 파일이 그대로일 때만 교체”를 하나의 연산으로 제공하지 않으므로, 비협조적인 다른 프로세스가 마지막 재검사와 기존 report 교체 사이에 끼어드는 아주 짧은 경쟁까지 증명해 막지는 못한다. verifier는 canonical 09_final_report.json만 쓴다.

실행 순서

00_run + 01_input + 01_sources
  -> 03_evidence_map                       (light에서만 생략 가능)
  -> 02_reader_contract + 04_logic_map + 05_term_ledger
  -> write/revise: 07_draft
       -> 08_logic_review || 08_reader_review (서로 독립; light에서만 생략 가능)
       -> pass reviews -> finalizer -> final -> 08_lint -> 09_final_report
  -> review: immutable 07_draft
       -> 08_logic_review || 08_reader_review -> review-target 08_lint
       -> 09_final_report                  (final 없음)

reader contract는 evidence curation과 일부 병행할 수 있지만 factual answer를 unverified source에 묶지 않는다. standard와 deep의 계획은 required evidence artifact가 유효할 때 닫는다. 두 review는 같은 draft와 upstream hash 묶음을 독립적으로 읽는다. reader reviewer는 sources/evidence bytes를 provenance hash에만 사용한다. write/revise의 review가 revise이면 Phase 3에서 새 draft를 만들고 두 독립 review를 모두 다시 실행하며, hold_for_review이면 blocker를 먼저 해결한다. finalizer는 적용되는 review가 모두 pass일 때만 현재 draft를 그대로 게시한다. light에서 두 review를 생략한 경우에는 drafter 자체 점검 뒤 동일본을 게시한다. lint 오류나 고칠 finding이 있으면 final을 패치하지 않고 draft 단계로 되돌아간다. 마지막 verifier가 09_final_report.json을 만든다.

상태 전이 checkpoint

init_run.py가 만든 상태는 initialized다. 각 checkpoint의 정본 산출물을 모두 쓰고 schema/hash를 확인한 다음에만 {skill_dir}/scripts/update_run.py를 호출한다. 00_run.json을 직접 편집하거나 미래 단계의 상태를 먼저 기록하지 않는다.

update_run.py도 이 완료 증거를 다시 검사한다. 단계 파일은 비어 있지 않은 일반 파일이어야 하며 symbolic link는 거절한다. 입력/source registry와 외부 source는 초기 hash에 묶고 JSON은 해당 schema를 통과해야 한다. draft는 UTF-8과 Markdown 구조를 검사한다. review checkpoint는 현재 07_draft.md와 upstream 파일 hash를 기록한 두 review만 허용하고, write/revise에서는 두 verdict가 모두 pass, review mode에서는 pass | revise여야 한다. review mode의 lint와 final checkpoint의 lint는 현재 입력으로 다시 실행한 canonical 결과와 같아야 한다. revise baseline도 초기 원본 hash에 묶으며, final checkpoint는 final.md07_draft.md의 실제 byte도 비교한다. 따라서 파일 이름만 미리 만들거나 오래된 pass report를 재사용해 상태만 앞당길 수 없다.

checkpoint 적용 경로 현재 → 다음 상태 완료 증거
evidence standard/deep 전체 initialized → evidence_ready 유효한 03_evidence_map.json
plan light 전체 initialized → planned 유효하고 상호 참조가 맞는 02, 04, 05
plan standard/deep 전체 evidence_ready → planned 유효하고 evidence와 상호 참조가 맞는 02, 04, 05
draft write/revise 전체 planned → drafted 유효한 07_draft.md
reviews standard/deep write/revise drafted → reviewed 같은 현재 draft hash를 검토한 두 pass review
reviews light write/revise, 두 review를 수행한 경우만 drafted → reviewed 같은 현재 draft hash를 검토한 두 pass review
final gate light write/revise, 두 review를 생략한 경우 drafted → finalized 07_draft.md와 byte-identical한 final.md, 통과한 08_lint.json, 완성된 omission 기록
final gate standard/deep write/revise 또는 두 review를 수행한 light reviewed → finalized review 대상과 byte-identical한 final.md, 통과한 08_lint.json, 완성된 omission 기록
review gate review 전체 planned → reviewed `pass
verification write/revise 전체 finalized → verified 통과한 verify_run.py가 자동 기록

review mode는 init_run.py가 원본을 immutable 07_draft.md로 만들기 때문에 drafted, finalized, verified를 거치지 않는다. light write/revise에서 두 독립 리뷰를 생략하면 reviewed도 거치지 않는다.

호출 형식은 항상 다음과 같다. {status}{reason}에는 위 checkpoint의 실제 다음 상태와 완료 증거를 넣는다.

python3 {skill_dir}/scripts/update_run.py \
  --run-dir {run_dir} \
  --status {status} \
  --reason "{validated artifacts and checkpoint}"

verifier를 호출하기 직전 status는 write/revise에서 정확히 finalized, review에서 정확히 reviewed여야 한다. write/revise의 verified는 verifier만 기록하며 일반 상태 CLI는 이 전이를 거절한다. 상태 변경과 verifier는 kernel이 프로세스 종료 때 해제하는 run-wide lock을 공유한다. verifier는 검증 파일 snapshot을 상태 전이 전후로 다시 비교하고 동시 변경을 발견하면 hold_for_review로 끝낸다.

hold_for_review, failed, incomplete는 기록이 끝난 terminal 상태다. 한 terminal 상태에서 다른 상태로 바꾸는 전이는 허용하지 않는다. 재개가 필요하면 기존 history를 고쳐 쓰지 말고 blocker 해결 사실과 새 입력을 반영한 새 run을 시작한다.

Staleness와 부분 재실행

artifact를 소비하기 전에 다음을 확인한다.

  1. 00_run.json에서 run identity, route, recorded hash를 읽는다.
  2. 선언된 input hash를 다시 계산하거나 조회한다.
  3. 규칙 version뿐 아니라 rules_sha256, 문서·계약·review 대상 hash가 다르면 artifact를 stale로 거절한다.
  4. 가장 이른 invalid owner부터 다시 실행한다. final output만 패치하지 않는다.

reviewer는 자신이 검토한 exact draft와 upstream artifact hash 묶음을 기록한다. finalizer는 다른 draft나 바뀐 evidence/reader/logic/term 계약에 review가 적용된다고 주장하지 않는다. final lint의 --draft-baseline 변경률 상한은 0이고 verifier는 final/draft byte hash를 직접 비교한다. 차이가 있으면 final candidate를 버리고 Phase 3의 새 draft부터 시작해 적용되는 두 독립 review를 다시 만든다. post-final review 파일을 추가하지 않는다.

오류 처리

  • evidence, 사용자 결정, upstream redesign이 필요하면 hold_for_review로 둔다.
  • invalid required input, required tool 부재, unrecoverable execution error는 failed로 둔다.
  • 실행 중단이나 일부 artifact만 만들어진 상태는 incomplete로 두고 마지막 완전한 stage를 기록한다.
  • 00_run.json.error는 non-terminal 상태에서 null이고, hold_for_review | failed | incomplete에서는 stage, code, message, affected_artifact, retryable, safe_next_action을 가진 객체다. 마지막 history 항목에도 같은 error snapshot을 기록한다.
  • pipeline 진행을 위해 required artifact를 만들어 내지 않는다.
  • hard gate가 열려 있으면 publishable final.md로 보고하지 않는다.
  • 같은 error 자동 재시도는 한 번만 하고 이후 사람 검토로 넘긴다.

터미널 상태를 수동 기록할 때는 가능한 한 구조화 필드를 명시한다.

python3 {skill_dir}/scripts/update_run.py \
  --run-dir {run_dir} \
  --status hold_for_review \
  --reason "required source is unavailable" \
  --error-stage evidence \
  --error-code SOURCE_UNAVAILABLE \
  --error-message "필수 source를 읽을 수 없습니다." \
  --error-affected-artifact 03_evidence_map.json \
  --error-not-retryable \
  --error-safe-next-action "source 접근 권한을 확인한 뒤 evidence 단계부터 재실행한다."

기존 호출처럼 --reason만 주면 CLI는 마지막 유효 status를 stage로, terminal status 기반 code와 reason을 message로 사용한다. affected artifact는 모른다고 null로 두고 자동 재시도는 안전하지 않다고 retryable: false로 기록한다. 이 기본값은 정보가 없는데 성공 가능성을 추측하지 않기 위한 하위 호환 경로다.

계약 통과 조건

다음을 모두 만족해야 한다.

  • canonical filename과 route별 required artifact가 맞다.
  • optional omission이 이유와 함께 기록됐다.
  • JSON schema와 mode별 lint 계약을 통과한다. write/revise는 lint pass가 필요하고, review는 진단 결과인 pass | fail을 허용하되 input/schema 오류는 허용하지 않는다.
  • write/revise lint는 현재 07_draft.md--draft-baseline으로 사용하고 final과 exact hash가 같아야 한다. revise는 원본 draft --baseline도 필요하고, review는 --draft-baseline을 사용하지 않는다. deep은 --fail-on warning을 사용한다.
  • ownership과 review independence를 지켰다.
  • consumer가 current hash artifact를 읽었다.
  • write/revise는 09_final_report.json.verdictdocument_verdict가 모두 pass다.
  • review는 실행 verdictpass이며 문서 document_verdict는 진단 결과인 pass | revise다.

09_final_report.json 의미

최상위 verdict는 하네스 실행이 계약대로 끝났는지, document_verdict는 대상 문서가 게시 가능한지 또는 수정이 필요한지를 나타낸다. review mode에서 결함을 찾아 document_verdict: revise를 반환한 것은 성공적인 진단 실행일 수 있다.

summary는 verifier가 결정적으로 확인한 required artifact, omission, 최종 status와 다음 요약을 담는다.

  • lint verdict, rules version과 SHA-256, 대상 hash, findings에서 재계산한 error/warning/info 수, 최초 등장 순서대로 중복 제거한 rule ID, fidelity, linter limitation
  • review별 verdict, 대상 hash, severity별 finding 수, finding ID

현재 계약은 별도 근거가 없는 품질 점수, finding fixed/disposition, waiver 승인을 만들지 않는다. 세부 finding 본문은 원본 08_*_review.json, lint finding은 08_lint.json을 정본으로 유지한다. schema가 맞아도 현재 target/rules hash와 다른 stale 진단은 summary와 document_verdict에서 제외한다.