15 KiB
/branch 로 만든 빈 브랜치 노트를 되묻지 않을 수준으로 채우는 오케스트레이터입니다.
source claim 에서 결정 후보·대안 비교를 도출하고, 근거 없는 결정은 먼저 자동조사한 뒤 그래도 없으면 UNSUPPORTED_DECISION 으로 라벨링하고, 끝에 /depth 로 깊이를 검증합니다.
브랜치 이름: {{arguments}}
참조 (작업 시 정독)
rules/subagent-input-contracts.md— 본 명령 + dispatch 할 agent 들의 입력 계약rules/branch-depth-gate.md— 끝에 적용할 깊이 판정 4축(R1~R4)rules/coverage-gate.md— 끝에 적용할 완전성 판정(빠진 관심사 3단계). depth 의 짝rules/consistency-contract.md— project decision 상속, revision pin, override 선언 규칙templates/branch-note-template.md— 채울 대상 구조(특히## 결정-근거 매핑,## 구현 가이드)CLAUDE.md§11, §15 — 근거 없는 결정 금지, 근거 기반 구현 명세
ca-tmpl 구현·계약 ground truth (필수 — §2 에서 읽음, 읽기 전용)
이 wiki 의 branch-note 는 별도 레포 /home/donghyeon/workspace/ca-tmpl 의 설계·계약 rationale 층이다 (ca-tmpl CLAUDE.md HARD-STOP #8: 구현 종료 시 이 wiki 의 branch-note 갱신 의무 — 코드↔노트 양방향 결합). 명세를 추측이 아니라 실제 구현·계약에 정합시키려면 다음을 본다:
/home/donghyeon/workspace/ca-tmpl/CLAUDE.md+AGENTS.md+ 해당src/<module>/CLAUDE.md— 아키텍처 HARD-STOP, module map, 레이어 규칙./home/donghyeon/workspace/ca-tmpl/docs/registries/*.yaml— 계약 값의 SSOT:error-codes.yaml(category enum·code·owner_branch·owner_layer·client_safe),env-keys.yaml,headers.yaml,metrics.yaml,mdc-keys.yaml,capabilities.yaml,secrets-classification.yaml. 각 row 의owner_branch:가 그 계약을 정한 branch-note 를 가리킨다./home/donghyeon/workspace/ca-tmpl/docs/runbooks/*.md— 운영 시나리오(장애 대응). retryable/category 정책의 운영측 근거./home/donghyeon/workspace/ca-tmpl/src/<module>/— 무엇이 실제 구현됐는지의 최종 SSOT. registry 주석조차 drift 가능(예:error-codes.yamlL580 의 stalePERSISTENCE) → enum/클래스 실체는src/shared-contract/src/main/java/dev/caskeleton/shared/error/Category.java같은 코드가 authoritative. module:domain-core·application-core·adapter-web·adapter-persistence·adapter-outbound·shared-contract·sample-portfolio·app-bootstrap.- 완수한 sibling branch-notes (
raw/branch-notes/feature-*.md중 구현 완료분) — registryowner_branch로 발견. 앞선 결정·구조·계약을 알아야 일관성을 깨지 않는다.
작업 절차
-
전제 확인
-
인자 비면 브랜치 이름 요청(종료).
.md·prefix 누락은 관대히 보정(rules/naming-conventions.md§2.1). -
raw/branch-notes/<slug>.md가 없으면 생성하지 말고/branch <slug>먼저 실행하도록 안내(종료). 채움은 본 명령, 생성은/branch. -
노트의
## Parent가 비어 있으면NEEDS_CONTEXT. -
결정론 contract preflight (필수): 편집 전에 다음 명령을 실행한다.
python3 harness/runtime/branch_contract_check.py --preflight --root . raw/branch-notes/<slug>.md -
exit code가 0이고 JSON의
schema_version이branch-contract-check-result/v1,status가PASS일 때만 계속한다.MISSING_PROJECT_BINDING,MISSING_INHERITED_DECISION,STALE_INHERITANCE_REVISION,UNDECLARED_OVERRIDE,CONFLICTS_WITH_PROJECT_DECISION,GENERATED_REGION_DRIFT등 실패는 그대로 보고하고 직접 보정하지 않는다. -
preflight가 확인하는 project/Work Item/decision/dependency/revision/packet hash를 LLM이 다시 파싱하거나 독자 판정하지 않는다.
-
-
구현·계약 현황 확인 (ca-tmpl ground truth — 필수, 추측 방지)
- 위 §참조의 ca-tmpl 자료를 읽기 전용으로 확인. 순서: 아키텍처 진입점(
CLAUDE.md/AGENTS.md+ 건드리는 레이어의src/<module>/CLAUDE.md) → 결정이 건드리는docs/registries/*.yaml→ 관련docs/runbooks/→src/<module>/grep. - 계약 값은 invent 금지 — 결정이 error code / category / env key / header / metric / capability / secret 을 건드리면 registry 의 기존 값을 재사용. 없으면 "신규 제안"임을 명시. registry row 의
owner_branch로 그 계약을 정한 sibling branch-note 를 찾아 정합 확인. actually-implemented주장은 코드로 확인 — 클래스/메커니즘이 "구현됐다"고 적기 전src/를 grep. 노트의 자기 보고만으로 FACT 화 금지. 코드에 없으면documented-only/planned로 표기.- drift 발견 시 surface — branch-note 의 명칭/매핑이 registry 또는 코드 enum 과 어긋나면(예: stale category 명)
## Audit & Findings에CATEGORY_DRIFT등으로 기록. 사용자 작성 결정 영역이면 자동 rewrite 말고 정합 권고만. - ca-tmpl 경로 부재 시
NO_GROUND_TRUTH라벨 + registry/노트 근거로만 진행하고 그 한계를 §8 에서 보고.
- 위 §참조의 ca-tmpl 자료를 읽기 전용으로 확인. 순서: 아키텍처 진입점(
-
Sources 수집
- 노트의
## 근거표 + 인자로 받은 추가 URL 을 합친다. - URL 이면
wiki-source-summarizerdispatch (source_type + parent + 정당화 결정 한 줄 전달 — 입력 계약 §wiki-source-summarizer). 결과 raw 의 Claim ID 를 수집.
- 노트의
-
결정 후보 추출
- 수집한 source Claim 과 노트의
## TODO·## 결정 사항, 그리고 §2 에서 본 ca-tmpl 구현·계약 현황에서 내려야 할 결정과 각 결정의 대안을 도출. - 각 후보를
Decision ID(D1, D2 …)로 부여. - project decision 상세를 branch 에 복제하지 않는다. 브랜치 계약 패킷은 pinned pointer + project 1줄 요약 + branch application 만 유지하고, 새 상세는 branch-local D-row 가 소유한다.
- 수집한 source Claim 과 노트의
-
자동조사 (bounded — DD4)
- Supporting Claim 이 없는 결정마다
wiki-decision-researcherdispatch (decision_topic + parent_branch + constraints + N — 입력 계약 §wiki-decision-researcher). 공식문서 + 대기업 블로그를 webfetch 로 조사해 대안 비교 + Claim 생성. - bound: 회당 최대 6개 결정. 초과분은 채우지 말고
deferred목록으로 보고(절대 silent 절단 금지). 사용자가 재실행하거나 수동 조사. - 조사는 개수가 아니라 근거 — 회사 블로그 1개로 "공식" 승격 금지(
rules/branch-depth-gate.md출처 타입 적정성).
- Supporting Claim 이 없는 결정마다
-
라벨링
- 조사 후에도 근거가 없는 결정은 추측 금지.
Decision Evidence Map에UNSUPPORTED_DECISION+ trade-off 한 줄로 남긴다. - 구현 가이드의 근거 없는 detail 은
UNSUPPORTED_IMPL_DECISION라벨(CLAUDE.md §15.5 R2).
- 조사 후에도 근거가 없는 결정은 추측 금지.
-
격리 candidate 채움 (기존 표 포맷 유지)
- 실제 target bytes는 유지하고 repo와 같은 layout의
<run-root>에 candidate를 작성한다. 이 단계의 Edit와 agent 입력은 staged candidate만 대상으로 한다. <!-- GENERATED: branch-contract:start -->와<!-- GENERATED: branch-contract:end -->사이 전체는 runtime 소유다. marker 자체와 내부 bytes를 수정하지 않는다. 편집은 marker 밖의 editable section으로 한정한다.## 결정-근거 매핑표를 채운다: Decision / 선택 조건(언제 이 결정/언제 대안) / Supporting Claims(raw/<slug>.md#C1) / Evidence Strength / Open Risk.## 구현 가이드는 in-scope 항목을 명명·경로·메커니즘으로 구체화하거나UNSUPPORTED_IMPL_DECISION라벨(CLAUDE.md §15.5 3-rule). §2 에서 확인한 실제 클래스/패키지/registry 값을 anchor 로 쓰되, 코드로 확인 안 된 것은planned로 표기.- 템플릿 섹션 순서 정합 (린터 미검사 — 필수 수기 확인):
wiki_structure_lint.py는 섹션 존재만 검사하고 순서·중복은 검사하지 않는다(린트 PASS ≠ 템플릿 정합). pre-template 노트(템플릿 도입 전 작성분)는 섹션 순서가 템플릿과 다를 수 있으므로, 채운 뒤grep '^## ' <노트>와templates/branch-note-template.md의##순서를 대조해 템플릿 순서로 재배치한다. 템플릿에 없는 노트 고유 섹션(예:## 테스트 계약,## Secret Source Defaults,## Work Item Contract)은 삭제 금지 — 가장 관련된 템플릿 섹션 바로 옆에 슬롯한다(검증성 섹션 →## 검증해야 할 주장앞, 결정 테이블 →## 결정-근거 매핑앞, 근거 보강 →## 근거뒤). - 파일 편집은 직접 Edit 하거나 대규모(전면 재배치 포함)면
wiki-doc-author(mode=migrate)에 위임. 기존 사용자 작성 본문 verbatim 보존.
- 실제 target bytes는 유지하고 repo와 같은 layout의
-
결정론 postflight + semantic certificate + 깊이·완전성 + 원자 commit (맨 끝)
-
(8a) contract postflight — 다음 명령을 실행하고 exit code 0, schema
branch-contract-check-result/v1, statusPASS를 요구한다.python3 harness/runtime/branch_contract_check.py --postflight --root . raw/branch-notes/<slug>.md --candidate <run-root>/raw/branch-notes/<slug>.mdGENERATED_REGION_DRIFT를 포함한 실패가 하나라도 있으면 즉시 중단한다. generated 영역을 수동 복구하거나 다시 쓰지 않는다. -
(8b) typed + local/direct-impact semantic audit — parent project의 current hub certificate를 먼저 확인한다. staged root에서
typed_contract_check.py→semantic_surface_extractor.py→wiki-semantic-coherence-auditorassertion phase →semantic_candidate_builder.py→ verdict phase → proof manifest →semantic_audit.py validate순서로 실행한다. impact set은 typed graph가 계산한 imported owner/consumer, 직접 dependency branch, delegation 상대만 포함하며 sibling 전수 비교는 금지한다. -
(8c) semantic certificate — 모든
CONTRADICTION, hubAMBIGUOUS_AUTHORITY,RESTATEMENT_DRIFT, explicit blocking이 0이고 pair coverage가 완전해야 한다. 미검증 negative finding은 dropped로 분류하며 hub dropped는 PASS 불가다. -
(8d) /depth + /coverage — staged candidate에 대해 structure/depth와 coverage를 실행한다. depth
Ready와 coverageCovered를 모두 요구한다. -
(8e) 공통 quality gate — staged candidate와 generated projection/MOC/current semantic certificate를
quality_gate.py로 검사한다. semantic 의미 판단은 quality gate가 재현하지 않고 certificate hash·coverage·verdict만 검증한다. -
(8f) 원자 commit —
document-commit/v1에 candidate/proof와 semantic audit request/result의 run-namespace hash를 넣는다.document_commit.py --dry-run --semantic-run-root <run-root>의plan_sha256을 그대로--apply --expected-plan-sha256에 전달해 target·projection·MOC·certificate를 한 번에 반영한다. -
(8g) 루프백 — 천장 2회 (project-spec §10 과 동일 규율) — depth
Not ready, coverageNot-covered, semantic/quality FAIL이면 §3~§7의 staged candidate만 보강하고 8a~8f를 다시 실행한다. 실제 target에는 실패 bytes를 남기지 않는다. -
coverage 가 찾은 missing 관심사는 §3 결정 후보로 편입 → §5 자동조사 대상이 됨(깊이·완전성이 한 루프에서 수렴).
-
-
요약 보고 (DD5 — 짧게, 상세는 노트에)
-
사람이 5초에 읽을 요약만:
채운 결정 N / UNSUPPORTED K / 조사한 결정 M / deferred D / drift D' / depth: Ready|Not ready / coverage: Covered|Not-covered (missing X). -
통과 못하면 무엇을 더 채워야 하는지 한 줄씩(depth·coverage finding 인용). 상세는 노트 본문에.
-
funnel 계측 (no-silent-truncation — Stop 훅이 균형 검증): 요약 끝에 기계 파싱용 블록을 방출한다.
found = processed + dropped균형 필수:agent: branch-spec found: <대상 결정 총수 = 채움 + UNSUPPORTED + deferred> processed: <채운 결정 + UNSUPPORTED_DECISION 라벨 수> dropped: <deferred 수> dropped_reason: <deferred 사유 (bound 6 초과 등), 0 이면 행 생략 가능>
-
규칙
- 추측해서 FACT 로 채우지 않는다. 근거 없으면 자동조사 → 실패 시
UNSUPPORTED_*라벨(CLAUDE.md §11). - 계약 값을 지어내지 않는다. error code / category enum / env key / header / metric 등은
ca-tmpl/docs/registries/*.yaml+ 코드 enum(예:shared/error/Category.java)이 SSOT. registry 에 없으면 "신규 제안"으로만 표기, 기존 값처럼 단정 금지. actually-implemented는src/grep 으로만 확정. 다른 노트의 자기 보고(note→note 전이)는 근거가 아니다. 코드 미확인 항목은documented-only/planned.- 기존 본문 보존 — 채움은 빈 셀/skeleton 에만. 사용자가 쓴 결정·메모를 덮어쓰지 않는다.
- generated 계약 영역은 수정 금지 —
<!-- GENERATED: branch-contract:start/end -->내부는 runtime만 쓴다.GENERATED_REGION_DRIFT는 자동 수정 대상이 아니라 즉시 중단 조건이다. - 템플릿 순서·중복은 린터가 안 잡는다 — 채움 후
##헤더 순서를templates/branch-note-template.md와 대조해 템플릿 순서로 정렬(§7). 노트 고유 섹션은 관련 템플릿 섹션 옆에 보존(삭제 금지). pre-template 노트일수록 이 단계가 필수다. - 자동조사는 bounded — §4 의 6개 한도. 초과는
deferred명시(UNBOUNDED_RESEARCH실패 모드 방지). deferred 는 §9 의wiki-statsfunnel 에 계측된다(silent 절단 불가). - 루프 천장 2회 — §8c. 2회 초과 미통과는 실패가 아니라 정상 종료 경로 (잔여 finding 보고 후 다음 세션 재개).
- agent 경계 고정 — source 조사/작성 agent에 더해
wiki-semantic-coherence-auditor는 assertion·verdict 의미 판단에만 dispatch한다. Python validator나 certificate 발급을 agent가 흉내내지 않는다. - 검증은 /depth + /coverage 에 위임 — 본 명령은 채움에 집중. 깊이(
/depth)·완전성(/coverage) 판정 로직을 중복 구현하지 않는다. 두 게이트가 모두 통과해야 완성. wiki/log.md기록 안 함(브랜치 작업은 빈번, 로그 노이즈) —/branch·/depth와 동일 정책.
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 불일치면 완료 판정을 차단한다.