docs(stage2): analyze five deployed YAML workflows

This commit is contained in:
2026-09-09 14:05:15 +09:00
parent f4aece497a
commit 112be9ed57
7 changed files with 1742 additions and 0 deletions
@@ -16,6 +16,16 @@
- 하위 에이전트(subagents)를 사용하여 핵심 테마와 교훈을 식별하고 MEMORY.md에 섹션으로 저장하라. - 하위 에이전트(subagents)를 사용하여 핵심 테마와 교훈을 식별하고 MEMORY.md에 섹션으로 저장하라.
- 향후 세션 시작 시 MEMORY.md의 이전 섹션을 참조하라. - 향후 세션 시작 시 MEMORY.md의 이전 섹션을 참조하라.
## 2026-09-09 — Stage 2 배포 YAML 5종 전문 분석과 단계 간 계약 차이 기록
한 줄 요약: 배포 YAML 00/10/20/30/40 총 16,100행을 독립 병렬 분담해 전문 분석하고 각 분석서에 정확히 2회 검증·증분수정을 수행했으며, “구현/봉인/과거 offline PASS”와 “현재 의미 인계·live 실행·법률 승인”을 구별해야 한다는 교훈을 확인했다.
- 산출물: 본 폴더 `Stage_2_00_Analysis_v1.md`, `Stage_2_10_Analysis_v1.md`, `Stage_2_20_Analysis_v1.md`, `Stage_2_30_Analysis_v1.md`, `Stage_2_40_Analysis_v1.md`. DAG, 세부 작업·목적, exact IO/producer-consumer, 배포 assets 및 `.py/.txt`, 외부 adapter 책임, 소스 행·SHA와 구현 한계를 포함한다. 실행계획/검증 추적은 root `plans/stage2-five-yaml-analysis.md`에 기록했다.
- 독립 분석/검증: 00·20·40을 병렬 sub-agent, 10을 main이 동시에 분석하고 가용 슬롯에서 30 분석을 이어 수행했다. 각 문서 1차 교차 검증 후 main 수정, 2차 검증 후 증분수정/확정으로 종료했다(00: analysis20→main, 10: analysis00→main, 20: main→analysis00, 30: analysis20→main, 40: analysis20→main). 추가 기능·실행자산 변경은 하지 않았다.
- 중요한 인계 한계: 00의 signal-family adapter 명칭 불일치·축약 fact/빈 slot·signal/review slice 미편입, 10의 output echo 자기 payload hash 전달 공백·native adapter 미결·단일-wave oracle 범위, 20의 missing operand/descriptor 자기참조 raw hash·특칙 미소비·빈 gap/filing/P32 및 permission 미반영, 30의 producer digest drift·row pointer 금지·owner singleton과 전체 group equality·전체 plan context 포함, 40의 상류와 V05/V12/V17 필드 차이·V16 빈 집합 PASS·문서 정렬 및 S2_30 P31/S30 hash 대상 불일치를 각 분석서에 근거와 함께 남겼다. 이는 법률 오류를 새로 판정하거나 해당 결함을 수정한 작업이 아니다.
- 실행단위 교훈: 의미상 5단계이나 배포 task template/family는 S2_30 비법률 planner를 포함해 6개다. 00/20/40의 inline Python mirror와 10/30의 offline adapter oracle을 live runtime 구현과 혼동하지 않는다. FAILED_NO_BARRIER나 planner stdout 존재 역시 실제 파일 부재/실행 성공의 보증이 아니다.
- 마감 정적 확인: 분석서 5개 총 1,664행, 로컬 링크 87개 유효, UTF-8/종결 LF/fence 및 각 2회 검증표 확인, 분석대상 YAML SHA 변화 없음, 00/20/30-helper/40 inline↔`.py`↔`.txt` 4쌍 byte parity 확인. 기존 240개 회귀시험 재실행, live MCP/LLM/Weaviate/E2E, 법률가 검수, 재봉인·commit은 수행하지 않았다. 현재 분석은 추후 구현 보완의 근거이지 production readiness 증명서가 아니다.
## 2026-09-01 — S2_40 deterministic 최종검증·render·review·commit package offline 구현 ## 2026-09-01 — S2_40 deterministic 최종검증·render·review·commit package offline 구현
한 줄 요약: S2_30의 group-parallel immutable part를 무손실 reduce하고 closed render·V01∼V18·review freeze/resume·비순환 seal·content-addressed commit을 수행하는 exactly-one MCP Code Executor S2_40을 구현해 전체 240개 회귀시험과 release 재현성을 통과했으며, live·법률 admission은 증거가 없어 의도적으로 대기 상태로 유지했다. 한 줄 요약: S2_30의 group-parallel immutable part를 무손실 reduce하고 closed render·V01∼V18·review freeze/resume·비순환 seal·content-addressed commit을 수행하는 exactly-one MCP Code Executor S2_40을 구현해 전체 240개 회귀시험과 release 재현성을 통과했으며, live·법률 admission은 증거가 없어 의도적으로 대기 상태로 유지했다.
@@ -0,0 +1,438 @@
# Stage 2_00 작업분석서
## 0. 분석 범위와 결론
분석 기준일은 2026-09-09이다. 분석 정본은 [배포 Stage_2_S2_00.yml](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml) **1–6,248행 전체**, SHA-256 `94c2744d71d222cfb5cc1b2a0d33a6cda20079439823de431eef378a2fa5c943`이다. 이 문서에서 `Y:번호`는 이 배포 YAML의 행번호이며, 각 절의 링크와 함께 읽는다. 실제 구현을 우선하고 [S2_00_SOW_v.2.md](S2_00_SOW_v.2.md), [S2_00_assets_v.2.md](S2_00_assets_v.2.md), [workflow 계약](Default_Agent/Stage_2_Clean/workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml), [parent release](Default_Agent/Stage_2_Clean/manifest/stage2_release.json)는 의도·배포계약과의 대조에 사용했다. JSON이 한 행으로 저장된 release는 행번호 대신 JSON Pointer로 특정한다.
S2_00은 **Stage 1 자료를 받아 후속 법률판단에 사용할 입력을 구성하는 단일 deterministic ingress task**다. Stage 1의 사실·증거·구조·signal·review를 검사하고, context·claim-neutral cluster·slice·S2_10용 structured-context handoff를 만든다. 청구권의 성립, 청구취지, 청구원인 문안을 LLM으로 판단하지 않는다. C00·C05·C10·C15는 한 Python 호출 안의 논리적 구성요소이며 네 개 Agent task가 아니다. `Agent.Stages[0].prevs`와 `nexts`는 모두 빈 배열이므로 전체 Stage 2 연결은 YAML 내부 stage edge가 아니라 **출력 barrier의 route와 외부 orchestrator**로 성립한다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:1–43, 6018–6103, 6230–6248.
다만 현재 코드와 배포계약만으로 “Stage 1 자료가 충분히 보존된 실행 가능한 S2_10 입력이 완성된다”고 단정할 수 없다. 현재 release는 `DEV_FIXTURE_RELEASE / DRAFT_NOT_EXECUTABLE`, bundle은 `STRUCTURAL_FIXTURE`, selected context는 빈 배열이다. 또한 source-family adapter 불일치, provenance pointer 불일치, 일부 자료의 slice 미편입 및 core와 MCP 진입경로의 실패처리 차이가 존재한다. 이들은 §8에 실제 구현의 제한으로 별도 기재했다. MEMORY의 240/240 등은 이전 작업 기록이며 본 분석에서 새로 실행한 시험 결과가 아니다.
### 0.1 경로 기호
| 기호 | 정확한 의미 |
|---|---|
| `M/` | `Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/` |
| `R/` | `M/Default_Agent/Stage_2_Clean/` |
| `W/` | localdocs가 user/workspace session에 결속한 논리 workspace root. 로컬 저장소 절대경로와 동일하다고 가정하지 않음 |
| `U/` | request의 `stage1_run_root_ref`가 지정한 `W/` 아래 Stage 1 사건 run root |
| `D/` | request의 `stage1_deployment_root_ref`가 지정한 Stage 1 고정 배포 root |
| `O/` | `W/stage2_runs/by-binding/<run_binding_digest>/` |
| `T/` | Code Executor에서 `TemporaryDirectory(prefix="liti-s2-00-")`로 만드는 임시 root |
`W/Default_Agent/Stage_2_Clean`가 live 자산 root다. 저장소의 `R/`는 그 배포 패키지의 로컬 위치다. request가 임의 output root나 release path를 전달할 수는 없다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:194–205, 5548–5591, 5957–5959.
## 1. 전체 작업 DAG
```text
외부 AgentBackend
user/workspace hash 치환 + Code Executor 실행환경/인증 결속
|
v
Agent IN -> Task_S2_00_deterministic_ingress -> Agent OUT
정확히 1 x code-executor.run_code
Python / httpx==0.28.1 / agent-network / 300s
|
v
run_inline_mcp
-> localdocs initialize / session / notifications/initialized
-> 고정 request + pin-bound parent release 읽기
-> exact input closure 1차 읽기 / expected hash 대조
-> 같은 remote path 전부 2차 읽기 / bytes equality
-> T/{stage1_run,stage1_deployment,stage2_asset} hydration
|
v
execute_ingress
C00: release/source schema·producer·identity·seal 검사
signal ALL 전개 / 두 SG-01 semantic projection 비교
|
v
C05: P1~P4 review occurrence 정규화
BO-fact / LES / evidence-event / signal / review 보존검사
|
v
run binding·schema-bound artifact header 구성
|
v
C10: case context / evidence inventory / object registry
party-title context / slot crosswalk 구성
|
v
C15: explicit membership·relation -> hard-join cluster
candidate edge -> SCC -> scheduling waves
bounded immutable slice -> structured-context cohort
cohort invariant -> executable/residual 분할 -> route
|
+--> TO_S2_10 또는 TO_S2_10_WITH_ISSUES
| 정상 11 + E개 JSON (E=최종 executable cluster 수)
|
+--> TO_S2_40_STATUS_ONLY
diagnostic 정확히 5개 JSON (context 미발행)
|
v
원본 local snapshot 재검사 -> output schema 검증
-> T/core_output 임시 tree 전체 write/fsync/rename
|
v
_inline_output_files: exact artifact set/hash 재검사
|
v
_inline_publish_remote
기존 barrier 있음 -> 동일 bytes 전수 확인 -> IDEMPOTENT_SUCCESS
기존 barrier 없음 -> non-status 파일 쓰기·read-back
-> ingress_status 마지막 쓰기·read-back
|
v
stdout 단일 JSON inner receipt + exit 0
|
외부 orchestrator가 barrier 재검증
+--> S2_10 ready-wave dispatch item 구성·호출
+--> S2_40 status-only entry 호출
통제 불가능한 ingress/transport/schema 등 예외
-> stdout ok:false / FAILED_NO_BARRIER / exit 2
-> partial output/barrier의 물리적 부재는 보장하지 않음
(저장 이후 read-back/close 실패도 같은 label; 저장상태 재확인 필요)
```
위 도식의 C00–C15는 작업 책임을 묶은 것이다. `execute_ingress`는 마지막에 manifest/intake/issue/status를 조립해 일괄 발행하므로 C00 또는 C10 진입 직후 해당 파일이 이미 외부에 저장되는 것은 아니다. 로컬 `os.rename`과 원격 `STATUS_LAST_LOGICAL_COMMIT`은 서로 다른 보장이다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:4015–4108, 4801–5243, 5896–6103.
## 2. IO 구조
### 2.1 외부 제어 입력과 Stage 1 사건 입력
모든 아래 파일은 JSON이다. 이 표의 producer는 현 parent release `/stage1_sources`에 선언된 expected producer이며, 실제 Stage 1 사건 실행 사실을 확인했다는 의미가 아니다. raw source는 strict UTF-8, duplicate JSON key 및 NaN/Infinity 거부, 기본 파일당 32 MiB/run 256 MiB/depth 96/items 1,000,000 제한을 적용한다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:83–87, 211–227, 299–329, 1084–1392.
| 입력 exact path | producer/공급자 | C00 이후의 사용 |
|---|---|---|
| `W/stage2_control/s2_00_request.json` | 외부 orchestrator | 정확히 `schema_version, workflow_id, request_id, attempt_id, stage1_run_root_ref, stage1_deployment_root_ref` 6필드 검증 |
| `W/Default_Agent/Stage_2_Clean/manifest/stage2_release.json` | offline release builder | build-time raw SHA pin, source 계약·schema·배포 closure·bundle 계약 |
| `U/evidence_indexed.json` | `Task_B1_quality_gate_evidence_indexed` | evidence ID·fact/event 연결, evidence inventory, cluster/slice |
| `U/evidence_event_candidates.json` | `Task_B2_quality_gate_event_candidates` | event ID·disposition·evidence 연결, cluster/slice |
| `U/client_goal.json` | `Task_A_client_goal` | 입력 검증·case context 최상위 source ref. 목표 본문 projection은 현 구현에 없음 |
| `U/routing/domain_screening.json` | `Task_A0_domain_screener_02` | routing shape·P1 digest guard |
| `U/routing/domain_activation_manifest.json` | `Task_D0_domain_activation_gate` | active/expected domain, signal SG-01과 17필드 대조 |
| `U/quality_gates/B1_evidence_indexed_gate.json` | `Task_B12_gate_audit_finalizer` | P1 digest 재검증 및 source 상태 |
| `U/quality_gates/B2_event_candidates_gate.json` | `Task_B12_gate_audit_finalizer` | P1 digest 및 event disposition count 대조 |
| `U/quality_gates/stage1_part1_soft_gate_handoff.json` | `Task_B2_SHA256_soft_gate_handoff_writer` | flat review 항목, 7-key digest guard |
| `U/BO.json` | `Task_C_BO_F0_final_bo_compiler_gate_writer` | identity backbone, BO–fact multiset, party/object occurrence, cluster |
| `U/signals/signal_manifest.json` | `Task_C_BO_S0_signal_bundle_writer` | `downstream_read_sets.stage2 == ["ALL"]`, files 순서·hash·kind·count, transaction |
| `U/quality_gates/stage1_part2_review_handoff.json` | `Task_C_BO_F0_final_bo_compiler_gate_writer` | flat review 정규화 |
| `U/legal_effect_structures.json` | `Task_C_LE_L2_final_structure_index_writer` | LES–BO join, domain/type/reverse index, cluster/slice |
| `U/quality_gates/stage1_part3_review_handoff.json` | `Task_C_LE_L2_final_structure_index_writer` | wrapped review 정규화·count |
| `U/Fact_Ledger_base.json` | `Task_C_FL_F2_final_fact_ledger_gate_and_writer` | identity backbone, fact sequence, domain_effects/calculation_requests, context·cluster |
| `U/stage1_tmp/fact_ledger/fact_ledger_writer_report.json` | `Task_C_FL_F2_final_fact_ledger_gate_and_writer` | row count·domain effect count·operand readiness count·ledger raw hash 대조 |
| `U/quality_gates/stage1_part4_review_handoff.json` | `Task_C_FL_F2_final_fact_ledger_gate_and_writer` | wrapped review 정규화·count |
| `U/signals/<signal_manifest.files[i].path>` | signal compiler, alias `PA-SG-COMPILER-001` | 유일한 manifest-expanded 가변 input family. `signals/` 중복 prefix 금지 |
Stage 1의 16개 고정 입력과 signal family를 구분한다. manifest row의 `canonical`·`domain_signal`은 의미 입력, `compatibility_view`는 파일 무결성만 검사하는 입력이다. signal ID 하나로 deduplicate하지 않고 `(transaction, file_path, record_ordinal, signal_id)` 발생 단위를 보존한다. `USED/UNUSED/UNMAPPED` 판정은 source의 명시적 ID/ref 존재 여부에 따른다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:1420–1591, 1612–1669.
조건부 추가 입력은 release `/dependency_locks/stage1/contract_manifest_ref`가 지정한 `D/<path>`와 `/completion_seal_ref`가 지정한 `U/<path>`다. 현재는 contract path가 null이고 completion ref도 없다. 따라서 새 Stage 1 completion 파일의 상시 생성을 요구하는 구조로 해석하지 않는다. core resolver는 release-bound `path_overrides`만 인정하지만 실제 inline hydration는 먼저 release의 원래 fixed path를 읽으므로 relocation 실행 호환성에는 §8의 제한이 있다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:791–820, 4141–4161, 5700–5720, 6162–6183.
### 2.2 출력 파일과 소비자
모든 persisted 출력은 canonical UTF-8 JSON이며 S2_00이 단독 writer다. `E`는 **최종 executable cluster 수**이다. 정상 branch는 아래 공통 4개 + context 7개 + slice E개, 즉 **11 + E개**다. diagnostic branch는 공통 4개 + technical diagnostic 1개, 정확히 5개다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:172–186, 5109–5243.
| 출력 경로 | branch | 내용 및 직접/후속 소비 |
|---|---|---|
| `O/ingress/stage1_input_manifest.json` | 공통 | fixed/signal/deployment source rows, parse/schema/seal/identity, hydration receipt·snapshot/input digest; orchestrator 및 S2_20/S2_40 추적 검증 |
| `O/ingress/intake_report.json` | 공통 | source count, compact conservation checks, compact review receipt, scope summary·issue codes; S2_40/검토자 |
| `O/review/issue_ledger.base.json` | 공통 | technical issue 및 unmapped review issue, 발생 수·conservation 상태; S2_20 reduce 및 S2_40 |
| `O/ingress/ingress_status.json` | 공통·최종 write | run binding, route, executable/residual ID, exact non-status artifact hash 목록과 barrier digest; downstream 허가 진입점 |
| `O/context/case_context.json` | 정상 | fact ID와 BO/LES/evidence/event/calculation/law-version/signal 참조 및 source refs; orchestrator context 공급 |
| `O/context/evidence_inventory.json` | 정상 | evidence–event–fact ID 연결과 provenance; 후속 plan/drafting trace |
| `O/context/object_registry.json` | 정상 | BO에서 추출한 object occurrence/canonical ID·표시 label·lineage |
| `O/context/party_and_title_context.json` | 정상 | party occurrence, title/defendant_role/liability/client_instruction/recovery_information 분리 |
| `O/context/slot_crosswalk.json` | 정상 | domain config element/opposing/defense 슬롯의 미평가 skeleton; fact/evidence 값은 현 구현에서 빈 배열 |
| `O/context/cluster_plan.json` | 정상 | cluster member/edge, SCC ID, scheduling waves, executable/residual 분할, slice/cohort 연결 |
| `O/context/cluster_slices/<cluster_id>.json` | 정상·최종 executable만 | bounded immutable content projections 및 source digest; orchestrator가 S2_10 동적 item을 만드는 재료 |
| `O/context/bundle_plan.json` | 정상 | ordered legal-context refs/hash, cluster slice refs/hash, cohort membership, opaque S2_10 Agent/binding digest, embedded context receipt |
| `O/ingress/technical_diagnostic.json` | diagnostic만 | `minimum_coherent_package_possible:false`, reason/source refs, `context_published:false`; S2_40 status-only |
`context_materialization_receipt`, `run_binding_receipt`, `hydration_stability_receipt`, `output_barrier`는 위 파일 안의 **embedded object**이며 별도 고정 파일이 아니다. `selected_legal_context_json`과 `cluster_case_payload_json`은 S2_00 output file이 아니라 **외부 orchestrator가 생성할 S2_10 item의 문자열 필드**다.
stdout에는 `stage2_s2_00_inner_receipt.v1` 한 객체만 출력한다. 성공은 `ok:true`, `SUCCEEDED` 또는 `DIAGNOSTIC_PUBLISHED`, route/run/hash와 `logical_publish_receipt`를 담는다. 예외는 `ok:false`, `FAILED_NO_BARRIER`, error와 exit 2다. stdout receipt를 `control/run_status.json`이나 최종 소송문안으로 오인하면 안 된다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:6018–6103.
## 3. 작업용 자산과 정확한 배포 위치
### 3.1 실행·검증·설계 자산의 구별
| 정확한 위치 | 포맷 | 역할과 실제 읽기 경계 |
|---|---|---|
| `R/agent_scripts/Stage_2_S2_00.yml` | YAML | AgentBackend가 실행할 정본. 단일 task의 `parameters.code`가 실행 source |
| `M/Stage_2_S2_00_v.2.yml` | YAML | authoring source. runtime에서 따로 읽지 않음 |
| `R/runtime/s2_00_ingress.py` 및 `R/runtime/s2_00_ingress.txt` | Python/동일 bytes TXT | inline source mirror 및 offline test oracle. YAML이 import하거나 호출하는 외부 실행파일이 아님 |
| `R/workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml` | YAML | declarative C00–C15/IO/route 계약. `tasks: []`, 자체 실행하지 않으며 inline code가 이 파일을 parse하지 않음 |
| `R/manifest/stage2_release.json` | JSON | raw pin 기준, exact upstream/direct/schema/bundle 폐쇄집합. live hydration 직접 읽음 |
| `R/manifest/module_manifest.json` | JSON | release가 hash 결속. inline은 여기서 S2_00 schema 3개를 선택·읽음; 모든 module을 실행하는 것은 아님 |
| `R/schemas/ingress.schema.json` | JSON Schema | manifest/intake/status/diagnostic 출력 검증 및 request/receipt 계약 |
| `R/schemas/context.schema.json` | JSON Schema | 7 context 산출물과 cluster slice/bundle 검증 |
| `R/schemas/review_status.schema.json` | JSON Schema | base issue ledger 검증 |
| `R/schemas/deployment.schema.json` | JSON Schema | offline binding/receipt 검증 계약. inline 3-schema loader 대상 아님 |
| `R/deployment/stage2_code_executor_binding.yml` | YAML | 외부 backend의 executor·egress·auth·release/Agent binding. inline 자체가 직접 load/서명검증하지 않음 |
| `R/manifest/s2_00_inline_code_receipt.json` | JSON | authoring/projection/code/mirror hash·AST/compile 증거. offline 생성 |
| `R/registry/cache/prompt_cache_policy.yml` | YAML | S2_00 context cohort와 S2_10 prompt cache 소유권 규칙. inline 직접 읽기 없음 |
| `R/offline_build/build_s2_00_inline_projection.py` 및 `R/offline_build/build_s2_00_inline_projection.txt` | Python/TXT | authoring→deployment YAML/runtime mirrors/inline receipt 생성·check. 사건 run 작업 아님 |
| `R/deployment/stage2_loader_binding.yml` | YAML | superseded loader audit pointer, active 호출/fallback 없음 |
| `R/release_ops/stage2_loader.py` 및 `R/release_ops/stage2_loader.txt` | Python/TXT | 과거 loader 보존본. S2_00 live 실행 dependency가 아님 |
| `R/manifest/stage2_deterministic_admission_receipt.json` | JSON | 후속 구현과 공유하는 detached admission 증거. S2_00 inline에서 직접 검증하지 않으므로 외부 admission 책임과 구분 |
[근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:8–15, 194–208, 637–645, 5721–5753; [자산 inventory](S2_00_assets_v.2.md) §1.2·§3·§7; [workflow 계약](Default_Agent/Stage_2_Clean/workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml) `orchestration_contract`.
### 3.2 Stage 1 고정 배포 closure 55개
각 경로는 `D/` 기준이며 모두 JSON이다. source-of-truth는 [parent release](Default_Agent/Stage_2_Clean/manifest/stage2_release.json) `/dependency_locks/stage1/concrete_paths`이다. 전체 Stage 1 YAML/runtime를 import하는 것이 아니라 **열거된 55개 source 계약 파일만** raw hash로 결속해 읽는다. `expected_concrete_path_count=55`이며 선언 개수·중복 경로·hash·strict JSON을 검사한다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:4164–4242, 5670–5698.
| lock ID 범위 | exact path 또는 닫힌 전개 규칙 | 개수·사용 |
|---|---|---|
| `S1-DEPLOY-001` | `D/runtime_manifest.json` | 1, 상류 배포 계약 snapshot |
| `002` | `D/domains/_registry_index.json` | 1, P1 seventh digest 및 domain lineage |
| `003` | `D/signals/signal_registry.v2.json` | 1, canonical/compatibility/schema lineage 대조 |
| `004–025` | `D/domains/E-00/domain_config.json`부터 `D/domains/E-21/domain_config.json`까지 정수 00–21 전부 | 22, element/opposing/defense 슬롯 |
| `026–029` | `D/domains/EC-00/domain_config.json`, `D/domains/X1/domain_config.json`, `D/domains/X2/domain_config.json`, `D/domains/X3/domain_config.json` | 4, 공통·crosscut config |
| `030–038` | `D/platform/schemas/` 아래 `client_goal_domain_profiles.schema.json`, `domain_fanout_plan.schema.json`, `domain_seed_output.schema.v3.json`, `domain_slice.schema.v2.json`, `fact_exception_pack.schema.json`, `fact_ledger_base.schema.json`, `fact_ledger_candidate_bundle.schema.json`, `legal_effect_structures.schema.json`, `structure_seed_bundle.schema.json` | 9, upstream schema closure |
| `039–040` | `D/signals/_common/evidence_slot_status.schema.json`, `D/signals/_common/signal_item.schema.json` | 2, signal 공통 schema |
| `041–055` | `D/signals/schemas/` 아래 다음 15개 | 15, activation·signal schema closure |
`D/signals/schemas/`의 정확한 basename 15개는 다음과 같다.
```text
domain_activation_manifest.schema.json
procedural_posture_relief_signals.schema.json
party_capacity_standing_signals.schema.json
governing_law_version_signals.schema.json
legal_relation_lifecycle_signals.schema.json
timeline_notice_condition_signals.schema.json
asset_right_state_signals.schema.json
liability_causation_damage_signals.schema.json
defense_exception_signals.schema.json
evidence_proof_conflict_signals.schema.json
calculation_requirements.schema.json
remedy_enforcement_signals.schema.json
legal_effect_routes.schema.json
domain_signal_envelope.schema.v2.json
signal_manifest.schema.json
```
위 path에 `v2/v3`가 포함되어도 이는 Stage 1 schema 버전이다. 금지된 과거 Stage 2 `v.0–v.3` YAML runtime dependency와는 다르다.
### 3.3 Stage 2 direct closure 49개
현재 [parent release](Default_Agent/Stage_2_Clean/manifest/stage2_release.json) `/dependency_locks/stage2_direct`에는 아래 **49개**가 있다. inline hydration는 이 목록 전부를 읽고 raw hash 검증한다. selected context의 의미적 선택은 `/bundle/selected_context_refs`에 별도로 기록되며 현재 빈 배열이다. 따라서 “활성 profile만 원격 읽는다”와 “읽은 모든 profile을 LLM에게 준다”는 설명 모두 실제 코드와 다르다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:3283–3475, 5741–5753.
| path prefix | exact basename | 개수·역할 |
|---|---|---|
| `R/agent_scripts/` | `Stage_2_S2_10.yml` | 1, 후속 Agent opaque bytes/hash |
| `R/deployment/` | `stage2_s2_10_llm_binding.yml` | 1, 후속 모델 설정을 S2_00이 변경하지 않고 hash 결속 |
| `R/registry/authority/` | `authority_registry.yml` | 1, authority registry snapshot |
| `R/manifest/` | `authority_release.json` | 1, authority release snapshot |
| `R/registry/substantive/` | 아래 목록 A | 22, substantive profile 배포본 |
| `R/profiles/crosscut/` | 아래 목록 B | 5, 공통 profile |
| `R/profiles/special_law/` | 아래 목록 C | 13, special-law profile |
| `R/profiles/overlays/` | 아래 목록 D | 5, ACTIO profile overlay |
```text
A — R/registry/substantive/
EC-00_contract_general.yml
E-01_juristic_act_validity.yml
E-02_contract_money_claim.yml
E-03_parties_liability_succession.yml
E-04_unjust_enrichment.yml
E-05_tort_general.yml
E-06_professional_liability.yml
E-07_construction_defect.yml
E-08_lease_deposit.yml
E-09_registry_transfer_claims.yml
E-10_secured_registry.yml
E-11_possession_vindication.yml
E-12_co_ownership_boundary.yml
E-13_creditor_preservation.yml
E-14_execution_linked_claims.yml
E-15_succession_family_property.yml
E-16_negotiable_instruments.yml
E-17_labor_wage_claims.yml
E-18_org_resolution_status.yml
E-19_insurance_claims.yml
E-20_ip_claims.yml
E-21_media_personality_rights.yml
B — R/profiles/crosscut/
E-00_residual_unrouted.yml
X1_notice_lifecycle.yml
X2_asset_identity_lineage.yml
X3_procedure_standing_relief.yml
X4_response_admission_defense.yml
C — R/profiles/special_law/
SL-AUTO_motor_vehicle.yml
SL-INDUSTRIAL_ACCIDENT.yml
SL-PRODUCT_LIABILITY.yml
SL-RESIDENTIAL_LEASE.yml
SL-COMMERCIAL_LEASE.yml
SL-LABOR.yml
SL-STATE_LIABILITY.yml
SL-IP-PATENT.yml
SL-IP-COPYRIGHT.yml
SL-IP-OTHER.yml
SL-MEDIA.yml
SL-TRANSPORT_MARITIME.yml
SL-CONSUMER_CONTRACT.yml
D — R/profiles/overlays/
ACTIO-MORTGAGE.yml
ACTIO-MORTGAGE-CREATION.yml
ACTIO-ENCUMBERED-TRANSFER.yml
ACTIO-PRESERVED-CLAIM-BUNDLE.yml
ACTIO-DEFENSE-MAP.yml
```
`R/law_values/general_law_values.yml`, `R/law_values/court_fee_values.yml`, `R/manifest/case_type_coverage.json`, `R/manifest/corpus_release.json`는 inventory 또는 release의 다른 영역에 등장하지만 현재 위 direct hydration 목록에 없다. 이 파일들을 S2_00이 무조건 읽는다고 기술하지 않는다. P00/P10 Markdown도 S2_00 직접 읽기 대상이 아니다.
### 3.4 offline 시험 자산
`R/tests/s2_00/`의 아래 **7개 Python과 7개 TXT mirror**가 존재한다. 테스트는 실행 알고리즘 검증용이며 live Agent의 추가 task가 아니다.
| `.py` exact basename | `.txt` exact basename | 검증 역할 |
|---|---|---|
| `test_resolver_source_lock.py` | `test_resolver_source_lock.txt` | input resolver·source closure·경로 정책 |
| `test_schema_hash_and_signals.py` | `test_schema_hash_and_signals.txt` | schema/hash·signal ALL·SG-01 |
| `test_conservation.py` | `test_conservation.txt` | BO/fact/LES/review 등 보존식 |
| `test_canonical_ids.py` | `test_canonical_ids.txt` | ID 결정성·표시 정규화·collision |
| `test_cluster_bundle_compile.py` | `test_cluster_bundle_compile.txt` | cluster/SCC/slice/bundle 계약 |
| `test_failure_and_atomic_publish.py` | `test_failure_and_atomic_publish.txt` | failure·retry·local publication |
| `test_inline_code_parity.py` | `test_inline_code_parity.txt` | Agent/inline/mirror parity·MCP 계약 |
관련 fixture 위치는 `R/tests/fixtures/regression_manifest.json`, `R/tests/fixtures/cases/*.json`, `R/tests/fixtures/mutations/*.json`이다. 별표는 문서상 family 표기이며 runtime directory scan 지시가 아니다. hybrid 변경 fixture는 `selected_legal_context_hash_drift.json`, `selected_legal_context_pii.json`, `s2_10_agent_binding_hash_drift.json`이며 모두 mutations 폴더 아래다. inventory의 과거 10 case + 50 mutation/69 PASS 수치는 역사 기록으로 취급한다.
## 4. 세부 작업별 이름·내용·목적
| 논리 소작업 | 구현 함수·행 | 작업 내용 | 목적/후행 의존 |
|---|---|---|---|
| MCP 세션·제어 입력 확정 | `_InlineLocaldocs`, `_inline_validate_request`, Y:5404–5591 | initialize protocol `2025-03-26`, session-ID 고정, 6필드 request | 다른 workspace/source로 흐르는 것을 방지하고 closure 읽기 시작 |
| exact closure hydration | `_inline_release_materialization_plan`, `_inline_hydrate`, Y:5602–5893 | request/release/fixed/signal/deployment/schema/direct asset 2회 읽기, bytes/hash 비교, temp 저장 | core가 동일 bounded snapshot을 사용하도록 제공 |
| C00 source 계약 검증 | `validate_ingress_contracts`, Y:1084–1392 | exact source set/path, strict JSON, schema/adapter, producer/alias, raw seal, run/transaction | available/with-issues/unavailable source row 작성 |
| C00 signal ALL·activation 검증 | `expand_stage2_signal_all`, `bind_signal_occurrences`, `verify_activation_projection`, Y:1420–1726 | semantic/integrity 파일 분할, occurrence 유지, raw hash와 SG-01 canonical 의미 분리 | signal 중복·소실·다른 activation 혼입 탐지 |
| C00 분산 seal 검사 | `verify_cross_artifact_seals`, Y:1740–1782 | P1 7-key guard, P2 flat/P3/P4 wrapper, v8 ledger extension | 상류 PASS 문자열을 그대로 신뢰하지 않음 |
| C05 review 정규화 | `normalize_review_items`, Y:1897–2065 | release mapping으로 5 partition 분리, upstream review ID 보존 또는 발생 ID mint | unknown status도 UNMAPPED로 남겨 검토 보존 |
| C05 보존검사 | `check_conservation`, Y:2068–2436 | 아래 §4.1의 독립 checks | downstream 판단 전에 자료 연결의 손실·중복 검출 |
| C10 provenance·ID | `_source_ref`, `mint_stage2_id`, `mint_context_occurrence_id`, Y:1785–1872·2439–2460 | raw hash와 logical pointer/lineage, namespace/version-separated deterministic ID | 파생값 출처 추적, 표시이름 기준 동일인 병합 금지 |
| C10 case·evidence context | `build_case_context`, `build_evidence_inventory`, Y:2523–2685 | fact/evidence/event/LES/calculation ref inventory | 후속 자료의 공통 연결축 |
| C10 object·party context | `build_object_registry`, `build_party_and_title_context`, Y:2701–2779 | BO의 닫힌 key 후보를 occurrence로 추출 | 권리객체·당사자 identity/title/role의 분리 |
| C10 slot skeleton | `build_slot_crosswalk`, Y:2782–2831 | config의 ELEMENT/OPPOSING_FACT/DEFENSE 슬롯 열거 | S2_10 이후 판단할 요건 슬롯 목록 제공; 현 구현은 실제 슬롯 충족판정 안 함 |
| C15 입력 membership | `_cluster_inputs`, Y:4339–4527 | BO/FACT/LES/EVIDENCE/EVENT member와 explicit relation 생성 | 추측 없이 hard join 가능한 자료 연결 준비 |
| C15 cluster·SCC·wave | `compile_cluster_plan`, `_tarjan_scc`, Y:2834–3129 | union-find hard join, 후보 edge, SCC condensation/topological waves | 독립 cluster 병렬 판단 및 선행관계 유지 |
| C15 slice | `compile_cluster_slices`, Y:3132–3269 | kind별 bounded projections, source hash·content hash·slice digest | raw Stage 1 재읽기 없이 사용할 최소 단위 준비; 실제 보존 제한은 §8 |
| C15 bundle/cohort | `compile_bundle_plan`, `validate_bundle_release_cohorts`, Y:3283–3906 | selected refs 정렬/hash, opaque Agent/binding, membership/slice receipt 재계산 | S2_10 동적 item 생성 계약 제공 |
| route·issue·manifest 조립 | `_route`, `_build_issue_ledger`, `execute_ingress`, Y:4681–5243 | final executable 집합, source/snapshot/report/status 조립 | 다음 stage와 diagnostic 처리의 근거를 하나의 barrier에 결속 |
| 로컬 schema·원자적 tree | `_validate_output_artifact`, `publish_atomically`, Y:648–682·4015–4108 | release-local schema 검사 후 fsync·rename | temp 결과를 완결 tree로 확정 |
| 원격 status-last 발행 | `_inline_output_files`, `_inline_verify_existing_remote`, `_inline_publish_remote`, Y:5896–6008 | exact set/hash, 동일 결과 재사용 또는 파일별 write/read-back 후 status last | partial tree의 downstream 소비 방지 |
| 단일 실행 receipt | `run_inline_mcp`, Y:6018–6103 | stdout 격리·JSON 한 객체·exit 0/2 | AgentBackend가 성공과 실패를 기계적으로 판독 |
### 4.1 C05 검사 세부 목록
`check_conservation`은 `BO_FACT_MULTISET`, `FACT_ID_SEQUENCE`, `CURRENT_V8_LEDGER_EXTENSIONS`, `LES_BO_JOIN`, `LES_DECLARED_ACTUAL_COUNT`, `LES_REVERSE_INDEX`, `EVIDENCE_REFERENCE_CONSERVATION`, `EVENT_REFERENCE_CONSERVATION`, `EVENT_DISPOSITION_CONSERVATION`, `FACT_LEDGER_WRITER_REPORT_CONNECTION`, `SIGNAL_FILE_ROW_CONSERVATION`, `SIGNAL_RECORD_OCCURRENCE_CONSERVATION`, `REVIEW_OCCURRENCE_CONSERVATION`을 구성한다. BO와 source_bo_id의 Counter 동일성, fact 배열의 `F-001..F-N` 순서·유일성, LES attach/reverse index, 참조 universe, writer-report 실측 재계산을 구별한다. 비교 자료가 없는 일부 검사에는 `UNEVALUABLE`이 가능하며 이를 PASS와 동일시하지 않는다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:2068–2436.
### 4.2 cluster·slice·bundle의 서로 다른 의미
cluster는 청구권 또는 claim group의 확정값이 아니다. 같은 BO, LES의 source BO, 같은 evidence/event ref, 명시 사건관계만 hard join한다. `claim_precondition`, `accessory_of`, `incompatible_with`, `EXPLICIT_DEPENDENCY`는 candidate edge로 유지한다. domain config의 지식상속 `depends_on`을 소송상의 선후관계로 바꾸지 않는다. SCC는 candidate graph의 순환을 축약해 scheduling wave를 만든다. 원래 cluster edges와 SCC membership을 함께 출력하여 후속 LLM의 재판단 여지를 남긴다.
slice는 cluster별 content/ref snapshot이다. projection당 최대 262,144 UTF-8 bytes, slice content 합계 최대 2,097,152 bytes이며 넘으면 잘라내지 않고 exception을 발생시킨다. 모든 projection은 source ID에 결속된 하나의 raw source hash를 요구한다. `slice_digest`는 그 필드를 넣기 전 body의 canonical digest, bundle의 `member_slices[].sha256`는 digest 필드까지 포함한 최종 slice body의 canonical digest다. 두 hash를 같은 값으로 취급하면 안 된다.
cohort는 현재 compiler에서 동일 release-selected context를 쓰는 valid slice 전체를 묶는다. cluster별 profile을 별도로 법률추론하여 골라주는 알고리즘이 아니다. missing slice는 별도의 non-executable cohort로 보존한다. selected context 허용 kind는 `ACTIVE_PROFILE`, `APPROVED_COMMON_AUTHORITY`, `LAW_VALUE_TOKEN`, `AUTHORITY_PROPOSITION`; 여기의 법률 context에 주민번호·이메일·한국 휴대전화 패턴이 있으면 PII 오류를 남긴다. 이 제한을 사건별 dynamic payload의 PII 전면 금지로 확대 해석하지 않는다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:2877–3279, 3283–3906.
## 5. upstream–downstream 자료 의존
| 연결 | 연결 이유 | 방식과 구체 자료 |
|---|---|---|
| Stage 1 Part 1 → C00/C05 | 증거·event·goal·domain 활성화 근거 확보 | 8 fixed inputs와 P1 guard. evidence/event는 사실 증명 관계로, goal은 현재 source provenance로 보존 |
| Stage 1 Part 2 → C00/C05/C10/C15 | BO identity와 signal universe 확보 | BO multiset·party/object occurrence·signal ALL·P2 review. signal duplicate occurrence를 전역 ID 하나로 합치지 않음 |
| Stage 1 Part 3 → C00/C05/C15 | 법률효과 구조의 source BO lineage 확보 | LES structure/member·candidate 관계 및 P3 review. S2_00은 실체법 결론을 확정하지 않음 |
| Stage 1 Part 4 → C05/C10/C15 | 최종 fact identity와 domain/calculation 구조 확보 | ledger 배열·writer report·P4 review; fact ID를 새 순번으로 재발급하지 않음 |
| Stage 1 deployment → source 검증/slot | 자료 형식과 config의 실제 producer 계약 고정 | release의 55개 path/hash closure·schema/adapters |
| S2_00 → 외부 orchestrator → S2_10 | 명시적 자료 결합 단위별 법률판단 | status/barrier 검증, nonempty executable IDs, bundle/slice hashes, ready wave를 canonical item으로 변환. S2_10 호출은 이 YAML 밖 |
| S2_00 → S2_20 | 상류 identity/issue/provenance를 판결·계산·group reduce와 연결 | manifest/intake/base issue/context를 후속 sealed reference로 검증. S2_00의 cluster와 S2_20의 claim group을 동의어로 사용하지 않음 |
| S2_00 → S2_40 status-only | 법률판단 입력이 성립하지 않는 run의 상태 보존 | 정확히 status·technical_diagnostic·manifest·intake·base issue 5개. 청구취지·청구원인 생성을 우회 |
| S2_00 → S2_40 정상 검증 | 최종 문안이 원래 자료·run에 연결되는지 대조 | S2_00 barrier/manifest/source digest를 상류 검증 기준으로 사용. 최종 상태 writer는 S2_40 |
[근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:211–227, 4801–5243; [SOW](S2_00_SOW_v.2.md) §8.3; [S2_10 Agent](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_10.yml), [S2_40 Agent](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml)는 후단 소비 명세의 위치이며 해당 전체 분석은 각각의 별도 작업분석서를 참조한다.
## 6. 결정성·발행·실패의 의미
`input_set_digest`는 fixed snapshot과 signal/deployment closure의 logical ID/path/raw hash로 계산한다. `run_binding_digest`는 `input_set_digest + parent release raw hash + ALGORITHM_SEMANTIC_DIGEST + release_class`의 canonical JSON digest다. `run_id=S2RUN-<digest>`, output root는 `by-binding/<digest>`로 파생한다. algorithm digest는 `ALGORITHM_VERSION` 문자열에 namespace를 붙여 해시한 의미 버전 digest이며 **Python 전체 source hash와는 다르다**. actual source hash는 projection/receipt 체계가 별도로 관리한다. attempt ID는 canonical binding에 포함되지 않는다. request ID와 user/workspace hash는 receipt에 보존되지만 binding formula에는 포함되지 않는다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:79–82, 4544–4612.
로컬 publish는 전 출력 schema 검사 → non-status write/fsync → status에 exact artifact list/digest 삽입 → status write/fsync → staging directory rename 순서다. 원격은 localdocs `write_binary_file(overwrite:true)`와 매 파일 read-back을 사용하고 barrier를 마지막에 쓴다. 원격 directory rename·OS fsync·단일 transaction이 보장된다는 뜻은 아니다. 기존 remote barrier가 있으면 run binding과 **status 전체 bytes** 및 모든 artifact bytes까지 동일해야 idempotent success다. 다른 request ID가 같은 input binding을 공유하면 status bytes가 달라질 수 있으므로 “input이 같으면 request ID와 무관하게 무조건 재사용”이라고 쓰지 않는다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:4015–4108, 5934–6008.
| 실제 조건 | 구현 결과 |
|---|---|
| core identity backbone unavailable 또는 닫힌 diagnostic issue code 관측 | `TO_S2_40_STATUS_ONLY` |
| cluster 없음 또는 executable cohort cluster 없음 | `TO_S2_40_STATUS_ONLY` |
| coherent executable cohort 있음 + issue 있음 | `TO_S2_10_WITH_ISSUES` |
| coherent executable cohort 있음 + issue 없음 | `TO_S2_10` |
| hydration/transport/예외 등 core 정상 조립 이전 또는 도중 fatal 오류 | `FAILED_NO_BARRIER`, exit 2. diagnostic 5파일 자동 발행이 아님 |
| `release_class=DEV_FIXTURE_RELEASE`로 `execute_ingress` 진입 | `DEV_FIXTURE_REAL_RUN_FORBIDDEN`; STRUCTURAL_FIXTURE는 별개 bundle mode |
core diagnostic code 집합은 `RELEASE_SOURCE_CONTRACT_MISSING`, `RELEASE_SOURCE_PATH_MISMATCH`, `RAW_HASH_MISMATCH`, `SCHEMA_HASH_MISMATCH`, `SCHEMA_ID_MISMATCH`, `RUN_IDENTITY_CONFLICT`, `TRANSACTION_IDENTITY_CONFLICT`, `BO_FACT_CONSERVATION_FAILED`, `FACT_ID_CONSERVATION_FAILED`, `CURRENT_V8_LEDGER_EXTENSION_MISSING`다. 모든 ERROR를 동일하게 전역 차단하지 않으며 모든 exception을 status-only로 회복하지도 않는다. [근거: 배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml), Y:4770–4830, 6087–6103.
`FAILED_NO_BARRIER`는 반환 label이지 실제 barrier가 없다는 확인 결과가 아니다. Y:5989의 status write 뒤 5990의 read-back 실패, 또는 publish 성공 후 Y:6084–6086의 localdocs.close 실패도 generic catch에서 이 label을 반환한다. 이미 쓴 non-status 파일과 barrier를 rollback하지 않으므로 외부 실행 관리자는 실제 상태/hash를 재확인해야 한다.
## 7. 전체 Stage 2에서의 책임 경계
S2_00은 사건명 137종 중 한 개를 법적으로 확정하거나 청구권 signature·rule branch·청구취지 규칙을 선택하지 않는다. profile/context reference와 cluster는 다음 판단을 위한 자료 구조다. S2_10이 법률판단, S2_20이 plan/group 및 rule/retrieval 연결, S2_30이 문안 공동작성, S2_40이 최종 검증·발행을 맡는 전략의 첫 단계다. 다만 이 코드에서 그 다음 Agent를 직접 호출하지 않는다.
MCP authentication/secret injection, Code Executor 실행 이미지, workspace 격리, 네트워크 allowlist 실제 강제, signed live admission, S2_10 wave orchestration와 CAS·native adapter는 외부 시스템 책임이다. YAML metadata에 적힌 상태는 그 기능의 실행 증거가 아니다. S2_00이 실제로 직접 검증하는 것은 release pin 및 그 일부 transitive closure이고, 공유 executor binding·detached admission receipt의 서명검증은 이 inline code에서 발견되지 않는다. LLM model/effort/cache key는 S2_10 소유이며 S2_00은 Agent/binding의 opaque digest만 인계한다.
## 8. 현 구현의 제한·설계와의 불일치
이 절은 수정 제안서나 법률평가가 아니라 **분석 결과를 과장하지 않기 위한 구현 관찰**이다. 코드·자산은 본 작업에서 수정하지 않았다.
| ID | 직접 확인한 구현 | 분석상 의미와 근거 |
|---|---|---|
| 00-L1 | current parent `release_class=DEV_FIXTURE_RELEASE`, `release_status=DRAFT_NOT_EXECUTABLE`; bundle `mode=STRUCTURAL_FIXTURE`, `selected_context_refs=[]`, hybrid status가 `HYBRID_RELEASE_BOUND` 아님 | 실제 case run은 DEV guard로 거절된다. class만 바꾸어도 executable handoff가 되는 것은 아님. Y:4817–4818·3360–3362 및 release `/bundle` |
| 00-L2 | release signal family adapter는 `S2A-SIGNAL-ALL-V1`; code는 `S2A-SIGNAL-PAYLOAD-FAMILY-V1` 요구 | 현 source contract를 그대로 검증하면 `SIGNAL_PAYLOAD_FAMILY_CONTRACT_MISMATCH`. 상위 DEV guard 해소와 별개로 남는 계약 불일치. Y:1136–1145, release `/stage1_sources`의 해당 row |
| 00-L3 | MCP hydration가 16 fixed input 전부 `first_read`로 필수 읽기; core `_load_case_snapshots`는 missing을 row로 남길 수 있음 | missing client_goal 등도 실제 MCP 경로에서는 먼저 `FAILED_NO_BARRIER`가 될 수 있다. SOW의 partial recovery를 core 단위 동작과 live 경로로 나누어 설명해야 함. Y:4111–4138·5635–5654 |
| 00-L4 | case fact provenance가 `/rows/{i}`, cluster fact는 `/facts/{i}`, BO는 `/business_objects/{i}`, LES는 `/structures/{i}`를 사용 | current v8 raw 배열/`structure_records`에 대한 실제 RFC 6901 pointer와 맞지 않을 수 있다. raw hash가 있어도 정확한 source dereference를 보증하지 않음. Y:2595·4380–4394·4450–4460, release source adapters |
| 00-L5 | `build_case_context` facts는 ID/ref 중심이며 fact 본문·domain_effects 내용·calculation operand를 복제하지 않음. `client_goal`도 최상위 source ref만 존재 | FACT projection은 이 축약 context를 사용하므로 substantive 사실내용이 실제로 충분히 인계되는지 추가 보완이 필요하다. `raw_stage1_reread_required:false` 표기만으로 무손실 인계를 입증할 수 없음. Y:2523–2630·3137–3140 |
| 00-L6 | `_cluster_inputs`는 BO/FACT/LES/EVIDENCE/EVENT만 멤버화. signal/review/profile source map은 준비하되 해당 member를 만들지 않음 | slice의 `signal_occurrence_projections`, `review_item_projections`, `profile_projections`는 이 진입경로에서 비어 있을 수 있다. BO는 member이지만 `projection_arrays`에 BO 자체 배열도 없다. Y:3200–3208·4339–4527·5019–5051 |
| 00-L7 | EVENT/LES projection source로 raw row를 공급하지만 materializer는 source ID에 결속된 `source_refs[].raw_value_sha256` 하나를 요구 | raw row에 그 provenance가 없는 경우 `SLICE_PROJECTION_PROVENANCE_MISSING`; raw source가 존재한다고 slice가 자동 완성되는 것은 아님. Y:3167–3186·5006–5026 |
| 00-L8 | slot crosswalk의 모든 fact/evidence array는 빈 값, status `UNEVALUABLE`; fact의 party/object/review key도 빈 배열 | SOW의 요건-사실-증거·당사자 연결은 구현된 완전 crosswalk가 아니라 일부 skeleton이다. Y:2580–2595·2810–2820 |
| 00-L9 | normalized review 모든 occurrence는 메모리에서 유지되나 issue ledger는 기존 technical issue와 `UNMAPPED` review만 행으로 저장; intake는 count/key compact receipt | mapped CONDITIONAL/UNRESOLVED 원문·범위·blocking 정보가 그대로 persisted output에 들어간다고 설명하면 부정확하다. 00-L6와 결합하면 후단 review 보존에 공백 가능. Y:4657–4767·5109–5132 |
| 00-L10 | direct closure 49개 전부 remote read. selected ref 목록은 release-global이며 cluster별 선택 로직 없음 | SOW의 최소 선택 context 원칙과 실제 hydration 비용/선택 책임을 구별해야 함. 선택 안 된 profile을 LLM에게 전달한다는 뜻은 아님. Y:3380 이후·5741–5753 |
| 00-L11 | selected context 검사는 path/raw hash/NFC+LF text hash/순서/PII 중심. semantic schema·authority 유효시점·scope 판정은 직접 수행하지 않음 | SOW에서 말한 schema/scope/temporal closure 전체를 C15가 현재 검증한다고 쓰지 않음. Y:3380–3500 |
| 00-L12 | `_cluster_inputs`의 후보 relation target fact가 없으면 `continue`; 초기 member 기술상태는 모두 AVAILABLE | dangling 후보관계와 source unavailable이 항상 residual cluster/issue로 보존된다는 보장이 없다. Y:4356–4371·4510–4526 |
| 00-L13 | workflow에 retry policy 3회가 있으나 inline client `_post`에 retry loop가 없음; dormant CLI `main`은 hydration receipt 없이 execute 호출 | transient retry는 외부 책임/설계 선언과 구현을 구별. `main(argv)`를 실행 정본으로 오인하면 안 되며 실제 `__main__`은 `run_inline_mcp()`. Y:5437–5443·6186–6231 |
| 00-L14 | contract manifest path override는 core resolver에 있지만 hydration는 contract manifest를 읽기 전에 고정 source paths를 읽음 | 현재 exact default-path 실행과 relocation 지원을 동일한 완성도로 평가하지 않음. Y:791–820·5635–5654·5700–5709 |
따라서 이 분석은 구현된 함수·IO·hash 계약을 확인한 문서이며, real Stage 1→S2_10 E2E 성공이나 137종 법률적 완결성을 인증하지 않는다. 코드 hash가 역사적 memory hash와 다른 점은 이후 재봉인 이력에 따른 가능성이 있으므로, 본 문서는 처음에 기록한 **현재 배포 bytes**를 기준으로 한다.
## 9. 함수·클래스 전수 연결 부록
주요 함수만 골라 전체 작업을 놓치지 않도록 top-level 정의를 구성요소별로 묶었다. 괄호 안 숫자는 배포 YAML 정의 시작행이다. `_InlineLocaldocs` 및 다른 클래스의 method, 함수 내부 helper는 해당 owner 아래 포함된다.
| 구성요소 | 정의 이름·행 및 역할 |
|---|---|
| 오류·snapshot·JSON | `IngressError(230)`, `Snapshot(256)`, `_reject_constant(268)`, `_pairs_without_duplicates(272)`, `_walk_json_limits(281)`, `load_json_strict(299)`, `canonical_json_bytes(331)`, `canonical_digest(358)` — typed 오류, 단일 source snapshot, strict parse/결정적 직렬화 |
| 자체 schema validator | `_SchemaViolation(362)`, `_json_equal(366)`, `_schema_pointer(373)`, `_schema_type_matches(390)`, `_validate_schema_node(402)`, `_schema_branch_matches(616)`, `_load_output_schemas(637)`, `_validate_output_artifact(648)` — release-local `$ref`, required/type/branch/array/number/string 검사. 완전한 범용 JSON Schema 엔진이라고 주장하지 않음 |
| 경로·source | `_safe_relative_path(685)`, `_assert_no_symlink_components(696)`, `open_bounded_snapshot(708)`, `resolve_stage1_sources(791)`, `load_release_lock(823)`, `_issue(839)`, `_shape_required(859)`, `_json_pointer_value(865)` — 경로 containment/FD snapshot/계약 resolver |
| C00 adapter/identity | `_release_stage1_source_rows(882)`, `_adapter_decision(890)`, `_closed_adapter_shape_errors(897)`, `_schema_document_index(952)`, `_source_hash_index(965)`, `_source_producer_index(993)`, `_producer_value(1030)`, `_producer_matches(1058)`, `_identity_ref(1075)`, `validate_ingress_contracts(1084)` |
| signal | `_records_from_signal_document(1395)`, `_record_signal_id(1407)`, `expand_stage2_signal_all(1420)`, `_collect_values_for_keys(1594)`, `bind_signal_occurrences(1612)`, `_activation_payload(1672)`, `verify_activation_projection(1680)`, `_array_rows(1729)` |
| C00 seal/C05 | `verify_cross_artifact_seals(1740)`, `_extract_review_arrays(1875)`, `normalize_review_items(1897)`, `check_conservation(2068)` — `_extract_review_arrays`는 현재 main call chain에서 쓰지 않는 helper |
| ID/provenance | `mint_stage2_id(1785)`, `mint_context_occurrence_id(1817)`, `_source_ref(2439)`, `_dedupe_source_refs(2463)`, `_coerce_source_ref(2468)`, `_artifact_header(2485)`, `_derivation(2508)` |
| C10 | `build_case_context(2523)`, `build_evidence_inventory(2633)`, `_candidate_values(2688)`, `build_object_registry(2701)`, `build_party_and_title_context(2734)`, `build_slot_crosswalk(2782)` |
| C15 | `_tarjan_scc(2834)`, `compile_cluster_plan(2877)`, `compile_cluster_slices(3132)`, `_scan_pii(3278)`, `compile_bundle_plan(3283)`, `validate_bundle_release_cohorts(3703)` |
| 로컬 발행 | `_write_fsynced(3909)`, `_fsync_directory(3925)`, `_published_tree_matches(3936)`, `_output_schema_id(4005)`, `publish_atomically(4015)` |
| closure·binding | `_load_case_snapshots(4111)`, `_load_bound_completion_seal(4141)`, `_load_stage1_deployment_closure(4164)`, `_signal_source_contract_rows(4245)`, `_snapshot_state_digest(4298)`, `_verify_snapshot_state(4314)`, `_cluster_inputs(4339)`, `_run_binding_digest(4530)`, `_input_set_digest(4544)`, `_make_run_binding_receipt(4559)`, `canonical_run_id(4604)` — 실제 binding 경로는 `_make_run_binding_receipt`; `_run_binding_digest`는 별도 helper |
| report·core | `_compact_conservation_checks(4615)`, `_compact_review_receipt(4657)`, `_build_issue_ledger(4681)`, `_route(4770)`, `execute_ingress(4801)`, `_execute_structural_fixture(5246)` — fixture 함수는 실제 Agent main에서 호출하지 않으며 `published:false` 반환 |
| MCP parse/transport | `_inline_sha256(5279)`, `_inline_relative_path(5285)`, `_inline_join(5299)`, `_inline_parse_mcp_payload(5305)`, `_inline_tool_text(5361)`, `_inline_binary_envelope(5381)`, `_InlineLocaldocs(5404)` — 클래스 method `__init__`, `close`, `_post`, `initialize`, `call`, `read_binary`, `read_binary_optional`, `write_binary_verified` |
| MCP lifecycle | `_inline_validate_request(5548)`, `_inline_bound_ref(5594)`, `_inline_release_materialization_plan(5602)`, `_inline_hydrate(5756)`, `_inline_output_files(5896)`, `_inline_verify_existing_remote(5934)`, `_inline_publish_remote(5957)`, `_inline_context_is_bound(6011)`, `run_inline_mcp(6018)` — `_inline_context_is_bound`는 main 호출경로에서 직접 호출하지 않음 |
| dormant CLI·공통 manifest | `_FixedArgvParser(6106)`, `_parser(6111)`, `_project_root_from_runtime(6127)`, `_resolve_contained_ref(6134)`, `_load_bound_contract_manifest(6162)`, `main(6186)` — contract loader는 inline에서도 사용; CLI entry 함수는 실제 `__main__` 대상 아님 |
## 10. 검증 기록
초안은 배포 YAML 1–6,248행을 분할해 빠짐없이 읽고 function inventory, source/release path 목록, workflow·SOW의 해당 구간을 교차 확인하여 작성했다. source SHA-256을 기록했으며 실행 YAML·runtime·release 자산을 수정하거나 live MCP를 호출하지 않았다.
| 회차 | 검증자·범위 | 발견사항 및 증분 수정 |
|---|---|---|
| 1차 | 독립 analysis20: 분석서 전문, closure/materialization·C00–C15·route·remote publish·직접 release 자산 대조 | FAILED_NO_BARRIER의 실제 파일 부재 보장으로 읽히는 서술 교정; DEV_FIXTURE_RELEASE와 bundle STRUCTURAL_FIXTURE 구별. main agent 반영 |
| 2차 | main agent: 수정본 전문, execute_ingress guard·projection 구성·cohort 분할·remote writer/receipt 예외 및 현 release 직접 대조 | 1차 수정 반영 확인. 55/49 closure 및 현재 DEV release 실측 재확인. 실패 label과 물리적 저장상태의 구별을 유지하며 추가 중요 서술 오류는 발견하지 않음 |
검증-수정은 총 2회로 종료했다. 2차에는 추가 내용 수정이 불필요하여 검증 기록만 확정했다. 확인된 코드·계약 한계는 그대로 남아 있고 이번 분석서 작성으로 해결되었다고 주장하지 않는다.
@@ -0,0 +1,217 @@
# Stage 2_10 작업분석서
## 1. 분석 기준과 결론
분석 기준일: 2026-09-09. 정본은 [배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_10.yml) 1–447행이다. SHA-256: `122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272`. 전문을 두 연속 구간으로 읽고 workflow·binding·schema 및 adapter oracle을 대조했다. 이하 `R/`는 `Default_Agent/Stage_2_Clean/`, `B/`는 사건별 `stage2_runs/by-binding/<run_binding_digest>/`를 뜻한다. `R/`는 고정 배포 파일, `B/`는 실행 중 생기는 JSON 산출물이며 서로 다른 경로 공간이다.
S2_10은 **ready dependency wave 하나에 속한 cluster마다 법률판단 JSON을 산출하는 단일 LLM task의 map 단계**다. 청구권·구제수단의 후보와 그 관계를 판단하지만 사건종류·청구군 확정·금액 계산·청구취지/청구원인 문안 작성은 하지 않는다. 검증·영구 ID 생성·불변 저장·재시도는 YAML 안의 추가 Python task가 아니라 외부 AgentBackend adapter의 책임이다. 따라서 YAML 파일이 존재한다는 사실과 전체 실행환경이 구현·승인되어 있다는 사실은 다르다.
현재 binding은 `PENDING_EXTERNAL_PLATFORM_BINDING`, native adapter의 `implementation_ref`, `handler_version`, `handler_sha256`, `activation_binding`은 null이다. 이 문서는 정적 구현/계약 분석이며 실제 모델 호출·MCP 실행·변호사 검수 또는 법률적 무오류를 인증하지 않는다. SOW와 assets의 과거 외부 완성 prompt 구조 또는 초기 STUB 서술보다 현행 배포 파일을 우선한다.
## 2. 전체 작업 DAG와 책임 경계
```text
S2_00: ingress_status + cluster_plan + cluster_slices + bundle_plan
|
v
[외부 orchestrator] 선행 cluster 완료 확인 -> ready wave 선택
+ release-selected 법리/authority/context
+ 앞 wave의 필요한 verdict만 선택
-> host atomic single-flight CAS / lock receipt
-> stage2_control/s2_10_wave_dispatch.json {items:[...]}
|
localdocs.read_docs / source.mcp.key=[items]
v
+------------------- S2_10 YAML ------------------------+
| map(max_concurrency=8) |
| Task_S2_10_resolve_cluster × ready cluster |
| inline P00 -> inline P10 -> selected context |
| -> cluster case payload |
| GPT-5.6 Sol / xhigh / medium / responses |
| 출력: raw model_output.v2 JSON 한 객체 |
| reduce: [] / Python task: 0 / LLM tool call: 0 |
+-----------------------------------------------------+
|
v
[외부 native adapter] schema/echo/ref/review 검증
-> local refs 검증 -> 영구 ID mint -> 관계 endpoint 재작성
-> canonical verdict 검증 -> immutable write -> read-back
-> cluster별 verdict/issue/assumption/usage/receipt
|
+------------+------------------------+
| |
유효 결과 기술적 부적합
| 1차: 실패 cluster만 1회 재시도
| 2차: TECHNICAL_INCOMPLETE
| / S2_20 차단
v
wave receipt / 다음 ready wave 재호출
|
최종 wave 완료 + terminal failure 없음
v
s2_10_publish_status.json 마지막 게시 -> S2_20
```
실제 Agent의 `prevs: []`, `nexts: []`는 standalone 호출 선언이다(YAML 55–56행). 참조 workflow의 `prevs: [S2_00]`, `nexts: [S2_20]`는 전체 단계 계약이다. 이를 YAML 내부에 이미 단계 간 호출 코드가 있다고 해석하면 안 된다. source read는 map 입력 공급이며 LLM이 자유롭게 문서를 검색하는 tool 권한이 아니다.
## 3. 실제 실행 단위와 prompt 구성
| 구분 | 실제 선언/자료 | 목적·동작 |
|---|---|---|
| Agent/stage | `Stage_2_S2_10` / `S2_10`, Agent version `1.1.0` | 단일 ready wave 실행(YAML 1–56행) |
| map source | `localdocs`, `http://mcp-localdocs:8012/mcp`, `read_docs` | 고정 dispatch 경로의 `items` 배열을 분배(58–75행) |
| 유일 task | `Task_S2_10_resolve_cluster` | cluster별 법리·청구 후보 판단(76–447행) |
| 모델 | `openai / gpt-5.6-sol / xhigh / medium / responses`, `preflight: false` | 설정은 선언값이며 실제 사용 증명은 model receipt 필요(83–88행) |
| system 1 | inline `stage_2_common_cache_prefix` | 공통 안전규칙·근거·금지행위(92–207행) |
| system 2 | inline `s2_10_legal_resolution_static_prompt` | 법률판단 절차 및 v2 직렬화 우선규칙(210–427행) |
| system 3 | `{{item.selected_legal_context_json}}` | 선택된 법리·authority 자료를 명령이 아닌 데이터로 전달(428–436행) |
| user | `{{item.cluster_case_payload_json}}` | 사건별 사실·증거·선행판단·허용 참조·재시도 정보를 전달(437–445행) |
| reducer | 빈 배열 | 전체 종합/불변 저장은 이 YAML reducer가 아니라 외부 adapter 소관(447행) |
P00/P10 Markdown은 작성·배포 때 대조하는 원천이며 매 사건에서 runtime import하는 prompt 파일이 아니다. 동적 item에도 완성된 prompt 문자열을 넣지 않는다. 정적 system 두 개 → 법리 context → 사건 payload 순서로 같은 앞부분을 유지하는 cache-friendly 구조다. binding digest는 무결성·분류용 값이지 API가 cache hit를 보장하는 증표가 아니다. 현행 계약은 미문서화된 cache 파라미터를 만들지 않고, cache hit를 법률판단 성공조건으로 삼지 않는다. 이 설명은 로컬 계약에 대한 분석으로서 최신 외부 API 지원 여부를 검증한 것이 아니다.
## 4. 법률판단 내부 소작업
아래는 별도 Agent task가 아니라 한 번의 LLM 추론에서 수행하도록 지시한 논리적 소작업이다(YAML 237–250행, 318–368행).
| 순서/명칭 | 작업 내역 | 목적 및 연결 |
|---|---|---|
| 1 occurrence 확인 | fact/evidence/party/object/LES/signal/slot/review 참조를 확인 | cluster source와 결론의 추적성 확보 |
| 2 법률관계 후보 검토 | 활성 profile별 규범 문제와 사실을 구분 | profile 선택을 청구권 성립 확정으로 오인하지 않음 |
| 3 청구 후보 식별 | 후보·주위/예비·누적·부수·선결 관계 구분 | S2_20이 검토할 선택지 집합 제공 |
| 4 요건 충족 검토 | 지지 사실, 반대 사실, 미상 요소를 분리 | 증거 없는 요건을 자동 충족하지 않음 |
| 5 항변·재항변 검토 | 방어 논점 및 주장·입증 책임 정보 기록 | 원고 유리 자료만 남기는 편향 방지 |
| 6 법적 근거 결속 | 적용 시점에 맞는 released authority refs 사용 | profile/corpus 설명을 판례·법률 자체로 승격하지 않음 |
| 7 구제수단 후보 | 이행·확인·형성 등 후보를 판단 | 문안/renderer 확정은 후속 단계로 유보 |
| 8 양립·중복 회복 | 서로 양립 불가/누적/선결 관계를 참조로 표시 | 후속 claim group 구성 시 이중 회복 방지 자료 |
| 9 기간·긴급성 | 시효·제척·긴급 논점을 식별하되 계산하지 않음 | 금액·기산일·이율 확정 권한과 분리 |
| 10 미해결·가정 보존 | unresolved_review_keys/assumptions/self_check 출력 | 불확실성을 기술 장애로 혼동하거나 삭제하지 않음 |
각 판단은 `SUPPORTED / CONDITIONAL / UNRESOLVED / EXCLUDED`로 구별한다. 원고의 소제기 보류 지시는 법률상 청구 불성립과 다르므로 `DEFERRED_BY_CLIENT_INSTRUCTION` 및 지시 근거로 보존한다. P00의 atom provenance 표는 Stage 2 공통 기준이며 그 표의 금액·서식·절차 선언 전부를 S2_10이 생성한다는 뜻은 아니다.
### 4.1 출력 직렬화 우선순위
YAML 270–314행의 종전 논리 예시(`claim_options`, `claim_option_id` 등)를 실제 JSON schema로 사용하면 잘못이다. 369–426행의 `serialization_supersession`이 이를 명시적으로 대체한다. 실제 raw 출력은 fence 없는 `stage2_s2_10_model_output.v2` JSON 한 객체이며 최상위는 다음 9개다.
`schema_version`, `input_echo`, `domain_resolutions`, `claim_option_candidates`, `candidate_relations`, `unresolved_review_keys`, `assumptions`, `cluster_forbidden_outputs`, `self_check`.
후보는 cluster 내 유일 `option_local_ref`로 표현한다. LLM은 영구 `claim_option_id`, `claim_group_id`, `case_type_id`, `sub_rule_id`, 최종 문안·금액·이율·기간·증거번호·READY·저장경로·usage를 만들지 않는다. adapter가 cluster ID, 정규화 청구 signature, 정렬된 source occurrences, producer-contract digest를 이용해 `CO-` 영구 ID를 생성하고 두 번째 pass에서 local relation endpoint를 재작성한다. 양 pass 사이의 부분 게시를 허용하지 않는다.
실제 typed 세부 결과는 [s2_10 schema](Default_Agent/Stage_2_Clean/schemas/s2_10.schema.json)의 `$defs`로 다음처럼 연결된다.
| 결과 구조 | 핵심 field와 소작업 연결 |
|---|---|
| `domain_resolution` | domain_local_ref, decision, fact/evidence/authority refs, review_keys, missing_inputs, reason_codes, typed_provenance: 법률관계별 근거·상태 |
| `normalized_claim_signature` | vocabulary_version, legal_basis_family, right_holder_refs, obligor_refs, performance_kind, object_refs, legal_effect, source_occurrence_refs의 8키: 후보 정규화·후속 deterministic ID 및 S2_20 투영 |
| `claim_option_candidate` | option_local_ref/signature/relation/decision, client_disposition/client_instruction_refs, authority_refs, element_statuses/defense_statuses/remedy_candidates, incompatible_local_refs/precondition_local_refs, same_underlying_recovery_key, limitation, impact_scope/risk_level, forbidden_outputs, review_resolutions/typed_provenance/missing_inputs/review_flags |
| `candidate_relation` | from_option_local_ref, to_option_local_ref, relation, basis_refs, authority_refs: 후보 간 관계를 문자열 사건명 대신 참조로 전달 |
| `limitation` (`limitation_assessment`) | urgency (`NONE_IDENTIFIED/POTENTIAL/URGENT/UNRESOLVED`), basis_refs, authority_refs, unresolved_reason_codes; 실제 기간·기산일 계산 결과로 해석하지 않음 |
`risk_level`은 현 schema에서 `UNASSESSED` 고정이다. 따라서 prompt의 위험 검토를 승소확률이나 수치 위험등급 산출로 설명하면 안 된다. canonical verdict는 `stage2_s2_10_domain_verdict.v1`, `producer_id: S2_10`, `canonical_status: CANONICAL_VALIDATED`이며 raw의 `claim_option_candidates`를 영구 ID가 붙은 `claim_options`로 바꾸고 raw-model hash·verdict self hash·producer-contract digest·run/wave/cluster identity를 추가한다. 법률적 결론은 adapter가 재판단하지 않는다.
review 보존은 단순 배열 복사보다 엄격하다. `input_ref_allowlist.review_keys`의 모든 key는 후보 `review_resolutions` 또는 최상위 `unresolved_review_keys`에 **정확히 한 번** 나타나야 한다(validator 690–710행). RESOLVED review는 근거 fact/evidence/authority 참조가 필요하고, 후보가 CONDITIONAL/UNRESOLVED이면 missing_inputs 또는 review_flags가 필요하다. 누락·중복·허용집합 밖 참조는 유효 법률판단 결과로 게시하지 않는다.
## 5. IO 파일 및 자료 사용 계약
### 5.1 입력
| 파일/위치 | 포맷 | 생산자 → 소비자 | 사용 방식 |
|---|---|---|---|
| `stage2_control/s2_10_wave_dispatch.json` | JSON `wave_dispatch.v2`, `items` | 외부 orchestrator → map source | YAML이 직접 읽는 유일 runtime 문서 |
| `stage2_control/s2_10_wave_dispatch.lock.json` | JSON lock receipt | host/orchestrator → admission checker | 동시 실행 증빙; JSON 파일 자체는 원자적 lock primitive 아님 |
| `B/ingress/ingress_status.json` | JSON | S2_00 → orchestrator | `TO_S2_10` 또는 `TO_S2_10_WITH_ISSUES` route 확인 |
| `B/context/cluster_plan.json` | JSON | S2_00 → orchestrator | ready dependency wave 및 cluster 집합 |
| `B/context/cluster_slices/<exact-cluster-id>.json` | JSON | S2_00 → orchestrator | 해당 cluster의 사실·증거·slot 등 occurrence |
| `B/context/bundle_plan.json` | JSON | S2_00 → orchestrator | 선택 context/cohort 구성·참조 결속 |
| `B/map_s2_10/domain_verdicts/<exact-predecessor-id>.json` | JSON | 선행 wave adapter → orchestrator | 필요한 선행 결론만 축약·선택 |
| `B/map_s2_10/wave_receipts/wave-<zero-padded-ordinal>.json` | JSON | adapter → orchestrator | 선행 완료 검증; 임의 directory scan 금지 |
| release-selected exact profile/authority/law-value 파일 | YAML/JSON/Markdown 등 release에 기록된 포맷 | 배포 release → orchestrator | 승인·선택된 부분을 context JSON으로 materialize; 전량 주입 아님 |
`stage2_control/`은 고정 control namespace이고 canonical B/ 출력 루트와 구별된다. 위 간접 자료들을 S2_10 LLM이 다시 read_docs하거나 원시 Stage 1 파일·137종 catalog·청구취지 rulebook·Weaviate corpus를 직접 검색하는 흐름은 아니다. 사건종류와 rulebook binding은 S2_20, frozen 자료 기반 문안 작성은 S2_30 책임이다.
dispatch item에는 metadata 및 `input_ref_allowlist`와 함께 두 canonical JSON 문자열이 들어간다. canonical JSON은 UTF-8, 정렬된 object key, 지정된 array 순서, compact whitespace, trailing LF 없음, NaN/Infinity 금지다. 선택 context는 재사용 가능한 법리자료이고 case payload는 사건별 occurrence·선행판단·retry 정보다. payload의 `input_echo`는 자기 자신의 hash를 제외한 19개이고, raw output echo는 아래 20개를 요구한다.
선택 자산의 정확한 파일 결속은 `selected_legal_context.ordered_sources[]`의 `source_path/source_sha256`에 있으며 `context_ref_id/context_kind/order_index`를 함께 갖는다. context_kind는 ACTIVE_PROFILE, APPROVED_COMMON_AUTHORITY, LAW_VALUE_TOKEN, AUTHORITY_PROPOSITION의 네 종류다. 따라서 보고서의 “release-selected source”는 임의 폴더 검색이나 추정 filename이 아니라 해당 실행의 봉인된 exact path 집합을 뜻한다.
`request_id`, `run_binding_digest`, `wave_ordinal`, `attempt_no`, `cluster_id`, `bundle_cohort_id`, `cluster_slice_sha256`, `input_set_digest`, `parent_stage2_release_sha256`, `s2_10_release_sha256`, `s2_10_agent_sha256`, `s2_10_llm_binding_sha256`, `prompt_contract_version`, `raw_model_output_schema_sha256`, `s2_10_producer_contract_digest`, `inline_common_prompt_sha256`, `inline_static_prompt_sha256`, `selected_legal_context_sha256`, `cluster_case_payload_sha256`, `s2_10_cache_binding_digest`.
### 5.2 출력
다음은 [workflow](Default_Agent/Stage_2_Clean/workflows/S2_10_domain_relief_resolution_map.yml)의 `output_contract`가 정한 **외부 adapter 산출물**이다. raw 모델 응답은 API 결과이지 YAML이 직접 쓰는 파일이 아니다. 모든 아래 상대경로 앞에는 B/가 붙는다.
| 출력 경로 | 포맷 | 목적/하류 소비 |
|---|---|---|
| `map_s2_10/domain_verdicts/<cluster_id>.json` | canonical verdict JSON | 다음 wave와 S2_20의 법률판단 입력 |
| `map_s2_10/issue_patches/<cluster_id>.json` | JSON | 미해결 issue occurrence 보존 |
| `map_s2_10/assumption_parts/<cluster_id>.json` | JSON | 가정 보존, 후속 통합 |
| `map_s2_10/usage_parts/<cluster_id>.json` | JSON | backend metadata 기반 사용량; LLM 자가 보고 금지 |
| `map_s2_10/item_receipts/<cluster_id>.json` | JSON | 검증·mint·불변 저장 결과 증빙 |
| `map_s2_10/repair_request_parts/<cluster_id>.json` | JSON | 실패 cluster의 제한 재시도 요청 |
| `map_s2_10/technical_failure_parts/<cluster_id>.json` | JSON | 최종 기술적 실패; 무효 raw publish 금지 |
| `map_s2_10/wave_receipts/wave-<zero-padded-ordinal>/attempt-<n>.json` | JSON | 시도별 검증 기록(n=1,2) |
| `map_s2_10/wave_receipts/wave-<zero-padded-ordinal>.json` | JSON | 한 번만 쓰는 terminal wave 완료 기록 |
| `map_s2_10/s2_10_publish_status.json` | JSON | 마지막에 기록하는 S2_20 소비 허가/중단 상태 |
동일 기존 bytes는 idempotent success, 다른 bytes는 immutable conflict이며 덮어쓰지 않는다. 실패 cluster만 최대 두 번째 시도로 보정하고 성공 cluster 결과는 보존한다. 마지막 시도까지 실패하면 `STOP_TECHNICAL_INCOMPLETE`; 법률적으로 `UNRESOLVED`인 유효 verdict와 기술적으로 schema를 위반한 결과는 다른 상태다. S2_10은 최종 `control/run_status.json`을 쓰지 않는다.
## 6. 작업용 고정 자산: 정확한 배포 경로와 역할
아래 경로는 모두 main working directory 기준이며 `R/` 축약을 확장하면 정확한 배포 경로가 된다. 동적 context는 선택된 release refs로 결정되므로 모든 법리자산을 고정 필수 입력으로 열거하지 않는다.
| 고정 자산 | 역할/실행 경계 |
|---|---|
| `R/agent_scripts/Stage_2_S2_10.yml` | 실행 YAML 정본 projection |
| `Stage_2_S2_10_v.1.yml` | main의 authoring 원본; runtime 검색 대상 아님 |
| `R/workflows/S2_10_domain_relief_resolution_map.yml` | task·IO·cache·adapter·retry 계약 |
| `R/schemas/s2_10.schema.json` | dispatch/내부 data/raw output/canonical verdict/receipt 구조 |
| `R/deployment/stage2_s2_10_llm_binding.yml` | 모델·prompt·Agent hash·외부 capability 결속 |
| `R/manifest/module_manifest.json` | 배포 module identity/hash |
| `R/manifest/stage2_release.json` | parent release 및 선택자산 closure |
| `R/manifest/s2_10_release.json` | parent에 결속된 child release |
| `R/manifest/s2_10_agent_receipt.json` | authoring/projection·계약 검증 기록 |
| `R/manifest/s2_10_inline_prompt_projection_receipt.json` | 정적 prompt scalar·source·projection hash 기록 |
| `R/manifest/s2_10_platform_adapter_receipt.json` | 외부 native adapter admission 증빙 |
| `R/manifest/s2_10_model_benchmark_receipt.json` | 모델 실측·admission 증빙 |
| `R/manifest/s2_10_legal_review_receipt.json` | 법률검수 증빙; 파일 존재만으로 승인 아님 |
| `R/prompts/P00_system_and_safety_contract.md` | 공통 정적 조항 작성·projection 검토 원천 |
| `R/prompts/P10_legal_resolution_contract.md` | 법률판단 정적 조항 작성·projection 검토 원천 |
| `R/offline_build/build_s2_10_agent_projection.py` 및 동일 stem `.txt` | offline 생성·투영·봉인 도구/복제 문서 |
| `R/offline_build/validate_s2_10_contract.py` 및 동일 stem `.txt` | strict schema/ref/mint/retry/admission oracle; live adapter 구현과 다름 |
| `R/tests/s2_10/test_agent_contract.py` 및 `.txt` | Agent 구조 회귀시험/복제 |
| `R/tests/s2_10/test_wave_dispatch.py` 및 `.txt` | wave·dispatch·source 검사 |
| `R/tests/s2_10/test_domain_verdict_contract.py` 및 `.txt` | raw→canonical verdict 계약 검사 |
| `R/tests/s2_10/test_prompt_cache_and_boundaries.py` 및 `.txt` | hybrid prompt·cache 경계 검사 |
| `R/tests/s2_10/test_release_adapter_retry.py` 및 `.txt` | release·외부 adapter·retry 검사 |
S2_10 runtime Python 자산 수는 **0**이다. 위 `.py/.txt` 7쌍을 S2_10 LLM task가 import/execute한다고 해석하면 안 된다. `.txt`는 해당 Python의 복제 저장 파일이며 별도 실행 엔진이 아니다.
fixture 배포 폴더는 `R/tests/fixtures/s2_10/`이며 현재 파일은 다음 11개다: `single_wave_dispatch.json`, `multi_wave_plan.json`, `valid_model_output.json`, `invalid_reference_output.json`, `invalid_forbidden_output.json`, `invalid_preassembled_prompt_item.json`, `cache_prefix_drift.json`, `s2_00_c15_handoff_compatibility.json`, `actio_overlay_matrix.json`, `technical_failure.json`, `regression_manifest.json`. 관련 음성 mutation은 `R/tests/fixtures/mutations/s2_10_raw_stage1_reread.json`, `R/tests/fixtures/mutations/s2_10_agent_binding_hash_drift.json`이다. 이들은 실제 사건 입력이나 실법리 검수 완료 자료가 아니다.
## 7. upstream/downstream 결속과 실패 처리
1. **S2_00 → S2_10:** 검증·정규화된 source occurrences와 cluster dependency를 받아 사건 의미를 판단한다. 상류 bundle은 static prompt bytes를 공급하지 않는다. S2_10 agent/producer-contract/cache 결속은 외부 orchestrator가 현재 child release에 맞춰 구성한다.
2. **S2_10 wave → 다음 wave:** 완료된 선행 verdict와 receipt에 한해서 좁게 전달한다. max_concurrency 8은 wave 안의 병렬도이며 선행 의존성을 무시하고 모든 cluster를 한꺼번에 호출하라는 뜻이 아니다.
3. **S2_10 → S2_20:** 법률판단 후보·관계·유보가 주된 의미 입력이다. 정확한 참조·영구 ID가 붙은 canonical verdict를 publish barrier 뒤에 소비한다. 사건종류 mapping, rule selection, 계산, group 확정은 S2_20으로 넘긴다.
4. **S2_10 → S2_40:** issue·assumption·backend usage를 parts로 남겨 최종 통합에서 손실하지 않도록 한다. S2_10이 final draft나 final status를 우회 작성하지 않는다.
호출 전 host atomic CAS, map source items binding, no-reduce result adapter, strict schema/ref validator, deterministic ID+immutable persistence, item retry controller라는 6개 capability를 요구한다. JSON lock receipt만으로 동시 실행 방지를 증명하지 않는다. 기술 gate가 충족되어도 model/legal admission이 없으면 production은 차단되며, 별도로 허용·release-bound된 canary만 예외 계약이다. 현재 binding의 미결 항목을 canary가 자동 해결하지 않는다.
## 8. 구현과 계약 사이의 확인사항·잔여 한계
| 항목 | 원문 근거 | 분석 판단 |
|---|---|---|
| P10 안에 종전 출력 예시 공존 | YAML 270–314 대 369–426행 | v2 supersession을 적용해야 함; 종전 예시를 그대로 실행 출력으로 설명하지 않음 |
| 외부 adapter 구현 미결 | binding `native_result_adapter.implementation_ref: null` 등 | YAML만으로 CAS·불변 저장·retry까지 완결되었다고 할 수 없음 |
| input echo 전달의 가시성 공백 | YAML 428–445행은 JSON data 2개만 삽입; validator `_validate_cluster_payload`는 자기 hash 제외, `validate_model_output`은 20개 exact echo 요구 | `cluster_case_payload_sha256`은 dispatch top-level에 있으나 payload의 echo에는 없음. 별도 metadata 전달이 없다면 모델이 해당 hash를 그대로 복사할 근거가 prompt에 보이지 않음. live adapter가 보완한다고 추정하지 않고 인계 미해결 사항으로 기록 |
| schema 지시와 실제 주입은 다름 | YAML 403–426행은 closed schema를 따르라고 지시하나 schema 전체를 메시지로 inline하지 않음 | backend structured-output/schema 전달의 실효성은 외부 결속 증거 필요. offline oracle의 존재가 LLM 응답 준수를 보장하지 않음 |
| multi-wave 집계 구현 증거 범위 | offline validator `validate_receipt_state_bundle` 1123–1126행은 global 집합을 단일 wave 집합과 같게 하고 terminal wave hash도 하나로 제한 | §2의 모든 wave 완료 후 global 게시는 workflow 계약이다. 이 단일-wave oracle이 여러 wave를 종합하는 live global publisher 구현을 증명하지는 않음 |
| profile와 법적 authority의 구별 | P00/P10 및 workflow legal boundary | 법리자산 선택 자체가 법률 정확성·사실 충족의 증명이 아님 |
## 9. 검증·수정 이력
| 회차 | 검증자·범위 | 발견사항 및 증분 수정 |
|---|---|---|
| 1차 | 독립 analysis00: 배포 YAML 전문·workflow IO·binding·schema/oracle 대조 | nested typed 결과와 8-key signature, review exact-once 보존, multi-wave oracle의 증거 범위 보완. main agent 반영 |
| 2차 | main agent: 수정본과 schema의 nested output/echo/source-path 정의, adapter validator 및 상류-하류 인계 재대조 | limitation의 정확한 4개 field, UNASSESSED 고정 risk, canonical verdict 변환, 선택자산 exact source_path 결속을 보완. 1차 지적 3건 반영 확인 |
검증-수정은 총 2회로 종료했다. 구현 파일은 이 분석 작업에서 변경하지 않았다. 외부 adapter·multi-wave·echo 전달에 관한 미해결 계약은 문서 수정으로 해소되었다고 주장하지 않는다.
@@ -0,0 +1,399 @@
# Stage 2_20 작업분석서
분석 기준일: 2026-09-09. 분석 대상은 [배포 Stage_2_S2_20.yml](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml) 전문 3,979행이며, 원본 SHA-256은 `3c4e6a7404f5b6a6b2403824c3cd9e71db566d4f2865bd4de3e6fd9d07824bd6`이다. 이하 `Y:행번호`는 이 배포본의 실제 줄을 지칭한다. 파일명·component 명칭만으로 기능을 추정하지 않고 inline Python 실행 경로를 기준으로 분석했다. SOW·inventory는 설계 및 이력의 보조 근거다.
## 1. 결론과 분석 범위
S2_20은 S2_00의 사실·증거 context와 S2_10의 확정 형식 DomainVerdict를 읽어, 청구권 후보의 처분·원자적 청구·청구그룹·사건종류 및 규칙 결속·계산 및 검색 결과를 동결된 ReliefPlan으로 정리하는 **단일 deterministic MCP Code Executor task**다. S2_10의 법률판단을 새로 수행하지 않고, S2_30이 사용할 그룹별 작성자료와 작성허용 수준을 생산한다. 실제 Agent DAG는 `IN → Task_S2_20_deterministic_relief_plan → OUT`이며 C20∼C35는 이 task 안의 함수·자료구성 단계다. [Y:1–45, 3966–3979](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L1)
다만 현 배포본을 완성된 법률·계산 엔진으로 읽으면 안 된다. admitted formula/법률자료 및 live binding의 부재 외에도, 계산 operand는 현재 코드에서 모두 `MISSING`, 소가·인지 등 filing metrics는 빈 배열, 요건-사실-증거 gap은 그룹마다 고정된 미해결 1행, P32 공통 authority 참조는 빈 배열로 생성된다. 특칙 자산을 읽었다는 사실과 그 법리를 실제 적용한다는 사실도 다르다. 이 차이는 §8에 구체적으로 기록한다.
분석은 코드·문서의 정적 확인이다. MEMORY의 과거 240개 회귀시험 통과 기록을 이번 분석에서 새로 실행한 결과로 주장하지 않는다. live Code Executor·Weaviate·Stage 1→Stage 2 E2E·법률가 승인 여부도 이번 분석의 검증 대상이 아니다.
실행 parameter는 `language: python`, `requirements: httpx==0.28.1`, `network: agent-network`, `timeout: 300`이다. MCP endpoint는 `https://code-executor.mcp.eroomai.com/mcp`, 문서 IO endpoint는 `http://mcp-localdocs:8012/mcp`이다(Y:24–44). 외부 `.py` 호출이 아니라 YAML 안의 완전한 `parameters.code`가 실행 대상이다.
## 2. 작업 DAG와 책임 경계
### 2.1 Stage 2 전체에서의 위치
```text
S2_00 정규화/보존검사/context/cluster slice
| ingress barrier, context files, bundle/cluster plan, base issues
+--------------------+
v
S2_10 cluster 법률판단 → canonical verdict + item/issue/assumption/usage parts
+ 모든 wave receipt + global publish status
|
v
S2_20 [본 분석 대상]
frozen plan + groups + rule/fact packs + S30 slices
plan_publish_status.json을 마지막에 저장
|
consumer_authorized=true / TO_S2_30
v
S2_30 group별 청구취지/청구원인 공동작성 → S2_40 최종검증/조립/저장
```
S2_20 YAML의 `prevs`·`nexts`는 모두 빈 배열이다. 따라서 이 파일 자체가 S2_10 또는 S2_30 Agent를 직접 실행하는 것은 아니다. 외부 orchestrator가 선행 완료를 확인하고 request를 만들며, 후행은 S2_20 barrier가 허가한 자료만 소비한다. [Y:21–23, 3789–3831](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L21)
### 2.2 단일 task 내부 실제 흐름
```text
AgentBackend: user/workspace 치환 + run request + host CAS/admission 제공
|
v
run(): localdocs initialize → validate_request()
|
v
hydrate(): fixed seed 2회 read
→ parent/request/binding/host CAS/detached admission/schema 검증
→ exact registry/cluster/wave로 dynamic path 확장
→ fixed+dynamic 전체 2회 read → S2_00/S2_10 인계자료 검증
|
v
+-----------------------------+--------------------------------+
| C20 build_portfolio() | C21 build_party_projection() |
| option partition/atomic/CG | 사실상 party/object identity |
+-----------------------------+--------------------------------+
ThreadPoolExecutor(max_workers=2) join
|
v
project_signature() → C25 bind_case() → C26 bind_rule()+FK 검증
|
+-------------------------------+-----------------------------------+
| C22 calculate_all() | C27 query plan |
| 17 CE activation/receipt | → C28 filtered Weaviate search |
| | → C29 crosswalk/pack item 구성 |
+-------------------------------+-----------------------------------+
ThreadPoolExecutor(max_workers=2) join
|
v
C30: group/permission/issues/party report/exhibit/option conservation
|
v
C35: canonical plan + artifact_payloads()
rule/fact pack, group slice, P31/P32, 계산·검색·gap 자료
|
v
publish(): payload 전체 schema 검증 → 경로순 immutable write + read-back
→ plan_publish_status.json LAST → stdout JSON execution receipt
|
+ 성공: PLAN_COMPLETE 또는 PLAN_COMPLETE_WITH_REVIEW → TO_S2_30
+ 오류, trust 미검증: plan write 없이 실패 stdout receipt
+ 오류, trust 검증 후: technical_diagnostic + 실패 barrier 저장 시도
→ STOP_TECHNICAL_INCOMPLETE
```
내부 병렬화는 두 곳뿐이다. C27·C28·C29는 하나의 `build_retrieval_branch()`에서 순차 실행되며, 검색 query도 순차 loop다. 각 C 번호가 독립 Agent task 또는 별도 `.py` invocation이라는 뜻은 아니다. 코드 출처: [Y:1670–1780](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L1670), [Y:3902–3965](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L3902). 선언형 대응은 [workflow](Default_Agent/Stage_2_Clean/workflows/S2_20_canonical_relief_plan_reduce.yml)다.
## 3. IO 경로 및 포맷
경로 표기 기준은 다음과 같다. `R/`와 `O/`는 축약 표기이며 실제 파일명에 이 문자를 넣지 않는다.
```text
M = Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/
R = M/Default_Agent/Stage_2_Clean/ [고정 배포 root]
O = stage2_runs/by-binding/<run_binding_digest>/ [localdocs 사건 runtime root]
P = O/plan/
CL = CL-<24자리 hex>; AC = AC-<24자리 hex>; CG = CG-<24자리 hex>
CR = CR-<24자리 hex>; wave = wave-<4자리 0-padding ordinal>
```
고정 배포 파일의 localdocs 이름은 `Default_Agent/Stage_2_Clean/...`이고, `M`은 실제 저장소 위치를 설명하는 접두어다. `O`는 저장소에 사전 생성된 고정 자산이 아니다. 모든 사건 JSON 출력은 UTF-8·key sort·compact separator·마지막 LF의 canonical bytes이며, raw file hash와 자기 hash 필드를 제외한 object digest는 구별해야 한다. [Y:74–94, 124–177](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L74)
### 3.1 제어 입력
| 경로 / 포맷 | 생산자 | 소비·목적 |
|---|---|---|
| `stage2_control/s2_20_request.json` / JSON | 외부 orchestrator | 고정 진입파일. request/attempt/run·identity·출력 root·기대 parent/S2_10/status/Agent/binding hash·CAS/admission ref 18개 closed key 검증 |
| `stage2_control/host_cas/<run_binding_digest>/S2_20.json` / JSON | host CAS backend | 정확한 run에 대한 `S2_20:<digest>` single writer 획득 증거 |
| `R/manifest/stage2_deterministic_admission_receipt.json` / JSON | release/backend 승인 담당 | CANARY/PRODUCTION admission·parent/binding/inline receipt·backend capability·서명 검증상태 결속 |
| `R/deployment/stage2_code_executor_binding.yml` / YAML | release builder/operator | S2_20 execution row의 endpoint/image/network/timeout/live authority와 정확한 해시를 검사 |
`outer_execution_receipt_target_ref`는 `O/control/s2_20_outer_execution_receipt.json`으로 제한하지만 **inline 코드가 이 경로에 파일을 직접 쓰지는 않는다**. inline은 stdout 한 개 JSON만 출력하고, 외부 Code Executor/AgentBackend가 outer receipt를 저장해야 한다. [Y:338–385, 2025–2235, 3902–3965](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L338)
### 3.2 사건 입력
| 경로 / 모두 JSON | 생산자 | S2_20 사용 방식 |
|---|---|---|
| `O/ingress/ingress_status.json` | S2_00 | NORMAL branch, TO_S2_10(_WITH_ISSUES), written-last/readback, run/output root와 artifact set 검증 |
| `O/context/case_context.json` | S2_00 | canonical context header·run/input/release/schema 결속 검증; 현재 core에서 전체 내용을 계산 operand로 전환하지 않음 |
| `O/context/evidence_inventory.json` | S2_00 | evidence_id 유일성 확인, 정렬 후 갑호증 번호 부여 |
| `O/context/object_registry.json` | S2_00 | C21 객체 context ID·identity unresolved 확인 |
| `O/context/party_and_title_context.json` | S2_00 | party context ID·identity unresolved·party_title/defendant_role token |
| `O/context/slot_crosswalk.json` | S2_00 | schema/header/integrity 검증·인계; 실제 C29는 corpus registry의 crosswalk row 사용 |
| `O/context/cluster_plan.json` | S2_00 | executable cluster 집합의 유일한 동적 입력 열거 기준 |
| `O/context/bundle_plan.json` | S2_00 | cohort/member slice/ordered context/materialization receipt/Agent hash/wave 순서 검증 |
| `O/review/issue_ledger.base.json` | S2_00 | raw hash 및 issue ID를 plan ledger에 연결·보존 |
| `O/context/cluster_slices/<CL>.json` | S2_00 | 각 verdict의 slice hash·immutable/header 검증 |
| `O/map_s2_10/s2_10_publish_status.json` | S2_10 외부 publish adapter | COMPLETE/TO_S2_20·완전한 cluster 집합·terminal wave hash·terminal technical failure 없음 확인 |
| `O/map_s2_10/domain_verdicts/<CL>.json` | S2_10 결과 adapter | claim_options와 signature·relation·client instruction·요건/항변/구제후보·typed provenance의 원천 |
| `O/map_s2_10/item_receipts/<CL>.json` | S2_10 결과 adapter | verdict/part digest·request/wave/attempt·readback/persistence 상태 연결 |
| `O/map_s2_10/issue_patches/<CL>.json` | S2_10 결과 adapter | schema/self hash/item header 검증 후 inputs에 보관. 현재 plan ledger에 patch 내용을 merge하지 않음 |
| `O/map_s2_10/assumption_parts/<CL>.json` | S2_10 결과 adapter | verdict assumptions와 exact equality, part/header 검증; plan에 별도 assumptions reduce는 없음 |
| `O/map_s2_10/usage_parts/<CL>.json` | S2_10 결과 adapter | schema/self hash/header 검증. S2_20 비용은 LLM usage로 생성하지 않음 |
| `O/map_s2_10/wave_receipts/wave-<ordinal:04d>.json` | S2_10 wave adapter | 0부터 연속 wave, 각 expected cluster·최종 wave route·전역 receipt hash의 closure 검증 |
cluster별 6개 family와 wave 경로는 directory scan 없이 cluster/bundle 자료에서 계산한다. seed 고정파일 집합 2회, 확장된 전체집합 2회를 읽으므로 고정파일은 통상 네 번 읽는다. 다만 두 번째 read cycle의 fixed bytes가 첫 seed cycle의 bytes와 동일한지에 대한 전역 비교는 별도 수행하지 않는다(§8). [Y:2318–2760, 2762–3022](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L2318)
### 3.3 정상 출력
| `P/` 아래 경로 / 모두 JSON | producer component | 핵심 내용·후행 소비 |
|---|---|---|
| `canonical_relief_plan.json` | C35 | option disposition, atomic/group/dependency, 4분할, report refs, ledger ref, plan_content_digest. S2_30 불변 작성계획·S2_40 기준 |
| `claim_groups.json` | C30 | 그룹·그룹 간 dependency와 document_digest |
| `case_type_bindings.json` | C26 | signature·projection/predicate ID·case/sub-rule/FK 및 bound/unresolved/conflict 분할 |
| `issue_ledger.plan.json` | C30 | base raw hash·보존 base issue ID·신규 plan issues |
| `calculation_report.json` | C22 | receipt paths/hashes·activation state counts·missing operand/issue 요약 |
| `filing_metrics.json` | C22 | 현 구현 rows=[], source_ce13_receipt_ids=[], REVIEW_REQUIRED |
| `exhibit_register.json` | C30 | evidence_id 정렬에 따른 갑 제N호증·register digest |
| `option_conservation_report.json` | C20 | 전체 option의 상호배타 selected/alternative/excluded/deferred 보존식 |
| `party_completeness_report.json` | C30 | group별 required/present/missing role·identity conflict·review 상태 |
| `calculation_receipts/<CR>.json` | C22 | active atomic claim × registry calculator별 activation 및 계산상태·formula/operand/law-value/result hash |
| `query_plans/<AC>.json` | C27 | role별 정확한 검색범위 및 query/config hash. 미결이면 빈 rows도 보존 |
| `retrieval_results/<AC>.json` | C28 | COMPLETE/NO_HIT/NOT_RUN_UNRESOLVED_BINDING·선택/탈락 hit·snapshot/hash |
| `retrieval_receipts/<AC>.json` | C28 | 실제 검색이 수행된 AC만 request/response/filter/config digest·endpoint·retry count 기록 |
| `rule_context_packs/<CG>.json` | C26 | binding row·structured rule/Markdown/renderer/party/CE13/review path+hash+pointer. `RELIEF_ONLY` |
| `requirement_fact_packs/<CG>.json` | C29 | corpus source/locator/authority/proposition/element/Stage1 slot 참조와 unmapped/conflict 목록. `CAUSE_AND_ELEMENT_CHECK` |
| `element_evidence_gap/<CG>.json` | C30 | 현 구현은 UNRESOLVED/GAP 1행, gap_count=1 |
| `group_slices/<CG>.json` | C35 | frozen plan raw hash·그룹·pack/gap/calculation ref·drafting_permission; S2_30 S30 자료 |
| `prompt_segments/<CG>/P31_rule_and_pack.json` | C35 | rule/fact/gap pack의 순서 있는 참조 3개; 완성 prompt 문자열 아님 |
| `prompt_segments/<CG>/P32_common_authority.json` | C35 | 공통 authority segment 봉투; 현 ordered_asset_refs=[] |
| `plan_publish_status.json` | publish | 전체 artifact path/schema/raw hash/size/producer·그룹 권한 분할·Agent/code/parent/S2_10 hash, LAST 소비허가 barrier |
모든 `artifact_payloads()` 산출물에는 해당 JSON Schema `$defs`가 명시되며 `publish()`가 저장 전 payload 집합 전체를 검증한다. barrier 자체는 payload 집합 외부에서 나중에 만들어 저장한다. [Y:3172–3378, 3774–3831](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L3172)
모든 option이 excluded/deferred이면 active AC/CG가 0개이고 group/atomic별 family 없이 고정 plan artifact 9개와 마지막 barrier만 생성할 수 있다. `any(empty)`가 false이므로 이 경우에도 `PLAN_COMPLETE / TO_S2_30 / consumer_authorized=true`가 가능하다. schema도 빈 group/atomic 집합을 허용한다. 따라서 이 상태는 “적어도 한 청구그룹이 작성 준비됨”과 동의어가 아니며, 후속 S2_30의 nonempty cohort 요구와 함께 점검해야 한다(Y:843–845, 3217–3227, 3803–3807).
### 3.4 실패 출력과 저장 소유권
외부 trust 검증 후의 실패는 `P/technical_diagnostic.json`과 `P/plan_publish_status.json`을 생성하려고 시도한다. partial-write 오류는 이미 성공한 artifact row를 diagnostic barrier에 보존하고 `consumer_authorized=false`로 둔다. trust 검증 전 또는 diagnostic 저장마저 실패하면 정상 barrier를 만들지 못한 stdout 실패 receipt만 남을 수 있다. `publish_diagnostic()`의 `failure_component`는 PUBLISH_PARTIAL_WRITE만 `PUBLISH`, 나머지는 모두 `PREFLIGHT`로 분류하므로 실제 C22/C28 중간 오류도 이 라벨로 나타날 수 있다. [Y:3834–3965](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L3834)
`write_immutable()`은 기존 파일이 같은 bytes면 재사용하고 다르면 `IMMUTABLE_CONFLICT`다. 새 파일은 overwrite=false로 쓰고 즉시 read-back 비교한다. 하나의 run root에 내용이 바뀐 plan을 덮어쓰는 기능은 없으며 외부 실행 관리자가 새 실행 식별과 경로 계약을 처리해야 한다. 단순히 `attempt_id`만 바꿔도 `P` 경로가 달라지는 것은 아니다. [Y:323–336, 352–385](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L323)
## 4. 작업용 고정 assets와 정확한 배포 위치
### 4.1 실제 runtime에서 읽는 고정 파일
아래 모든 경로는 `R/` 기준이다. `.yml` 확장자라도 registry/descriptor는 `load_json()`으로 해석하므로 **현재 runtime이 요구하는 실제 내용 포맷은 strict JSON subset of YAML**이다. 자유로운 YAML scalar·anchor 등으로 다시 작성하면 같은 확장자여도 실행되지 않는다. shared executor binding만 별도 bounded YAML text parser로 읽는다. [Y:2762–2824, 3023–3165](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L2762)
| 경로 | 내용/실제 사용 |
|---|---|
| `agent_scripts/Stage_2_S2_20.yml` | 자기 배포 Agent raw hash 대조 |
| `deployment/stage2_code_executor_binding.yml` | 승인된 실행환경·S2_20 row 대조 |
| `manifest/stage2_release.json` | inline 및 request의 기대 raw hash·self digest |
| `manifest/module_manifest.json` | parent에 봉인된 직접 자산 path/hash membership |
| `manifest/s2_10_release.json` | 상류 child·producer digest·Agent/binding/schema seals |
| `manifest/s2_20_inline_code_receipt.json` | admitted inline code hash·receipt 연결 |
| `manifest/stage2_deterministic_admission_receipt.json` | detached backend/live admission |
| `manifest/authority_release.json` | authority admission flag |
| `manifest/case_type_coverage.json` | release-bound raw membership 검증; 137종 법률내용 승인 그 자체를 증명하지 않음 |
| `manifest/corpus_release.json` | collection/tenant/snapshot/config/availability 및 검색 승인 |
| `manifest/case_type_registry.yml` | 137개 case ID와 승인 predicate |
| `manifest/case_type_rule_registry.yml` | 같은 137 ID와 sub-rule branch/FK·source refs |
| `registry/binding/binding_signature_projection.yml` | 7개 의미 source field + vocabulary marker/C20/C21에서 10 target field 투영 |
| `registry/planning/option_disposition_policy.yml` | option 분할 정책 |
| `registry/party/party_set_rules.yml` | required role tokens 및 party rule |
| `registry/drafting/case_type_relief_rules.yml` | structured relief branch 승인/FK |
| `registry/review/review_policy_registry.yml` | branch의 review policy FK |
| `registry/authority/authority_registry.yml` | release membership 확인; core에서 세부 authority row 적용 없음 |
| `registry/corpus/requirement_fact_scope.yml` | exact corpus scope와 slot crosswalk |
| `registry/calculations/calculation_activation_registry.yml` | 17 CE descriptor 경로 및 activation row |
| `law_values/general_law_values.yml` | 검증된 일반 법정수치 후보 |
| `law_values/court_fee_values.yml` | 검증된 소가·인지 관련 law-value 후보 |
| `registry/temporal/inheritance_reserved_share.yml` | 특칙 envelope 검증·보관 |
| `registry/drafting/forbidden_relief_rules.yml` | 특칙 envelope 검증·보관 |
| `registry/drafting/counter_performance_rules.yml` | 특칙 envelope 검증·보관 |
| `registry/drafting/procedural_declaration_rules.yml` | 특칙 envelope 검증·보관 |
| `routing/actio_pauliana_route_registry.yml` | 특칙 envelope 검증·보관 |
| `routing/actio_pauliana_mortgage_route.yml` | 특칙 envelope 검증·보관 |
| `validators/actio_value_compensation_invariants.yml` | 특칙 envelope 검증·보관 |
schema 파일 9개는 `schemas/relief_plan.schema.json`, `schemas/binding_retrieval.schema.json`, `schemas/calculation.schema.json`, `corpus/weaviate_collection.schema.json`, `schemas/ingress.schema.json`, `schemas/context.schema.json`, `schemas/s2_10.schema.json`, `schemas/review_status.schema.json`, `schemas/deployment.schema.json`이다. 외부 `$ref`는 허용된 corpus/review/relief 정의만 메모리에서 병합해 닫는다. [Y:3381–3543](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L3381)
renderer 6개는 아래와 같다. S2_20은 descriptor를 검사하고 참조를 결속하며 실제 Markdown render는 하지 않는다.
| `R/renderers/` 파일 | 의미 |
|---|---|
| `R01_money_payment.yml` | 금전지급 |
| `R02_delivery_possession.yml` | 인도·점유 |
| `R03_declaration_registry.yml` | 등기·의사표시 |
| `R04_special_nonmoney_performance.yml` | 특별 비금전 이행 |
| `R05_declaratory.yml` | 확인 |
| `R06_constitutive_judgment_challenge.yml` | 형성·불복 |
계산 descriptor는 activation registry가 정확한 경로로 열거하며 실물 배포 경로는 다음 17개다. 이름에 해당하는 모든 법률 계산이 완성되었다는 뜻은 아니다.
| `R/registry/calculations/` 파일 | 의도된 계산 분야 |
|---|---|
| `CE-01_interest_delay.yml` | 이자·지연손해금 |
| `CE-02_allocation_setoff_balance.yml` | 충당·상계·잔액 |
| `CE-03_limitation_deadline.yml` | 시효·기간 |
| `CE-04_valuation.yml` | 평가·가치 |
| `CE-05_personal_injury.yml` | 인적 손해 |
| `CE-06_construction_defect.yml` | 공사·하자 |
| `CE-07_lease_use_gain.yml` | 임대차·사용이익 |
| `CE-08_inheritance_reserved_share.yml` | 유류분 |
| `CE-09_wage_severance.yml` | 임금·퇴직금 |
| `CE-10_actio_insolvency_value.yml` | 사해행위·무자력·가액 |
| `CE-11_distribution_share_division.yml` | 배당·지분·분할 |
| `CE-12_insurance.yml` | 보험 |
| `CE-13_court_value_cost.yml` | 소가·소송비용 |
| `CE-R1_ip_damage.yml` | 지식재산 |
| `CE-R2_org_liquidation.yml` | 조직 청산 |
| `CE-R3_transport_maritime.yml` | 운송·해상 |
| `CE-R4_financial_instrument.yml` | 금융상품 |
추가 동적 **고정자산 선택** family는 `R/rules/relief/CT-<3자리>.md` 및 `R/legal_review/<legal_review_receipt_id>.json`이다. case/party/corpus registry의 review ref 및 rule registry 각 branch의 Markdown/review ref를 열거해 읽고 module hash membership을 요구한다. 현재 사건의 최종 선택 branch만 읽는 lazy-load라고 단정할 수 없다. `hydrate()`는 case binding 전에 registry 전체가 참조하는 이 파일들을 열거한다. [Y:2927–2971](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L2927)
### 4.2 runtime으로 import하지 않는 Python·mirror 및 build 자료
아래 `이름.py`와 `이름.txt`는 각각 별도 물리 파일이다. full inline mirror 한 쌍 외 pure-core oracle은 독립 source이므로 그 기능을 곧바로 inline 기능으로 간주하지 않는다. 특히 C29 oracle과 inline의 검증 범위는 같지 않다(§8).
| 정확한 `.py` 경로 / 대응 `.txt` 경로 (`R/` 기준) | 역할 |
|---|---|
| `runtime/s2_20_reduce.py` / `runtime/s2_20_reduce.txt` | authoring inline 전체 byte mirror·offline 검사 |
| `runtime/binding_signature_projection.py` / `runtime/binding_signature_projection.txt` | signature projection oracle |
| `runtime/c25_case_type_bind.py` / `runtime/c25_case_type_bind.txt` | case predicate oracle |
| `runtime/c26_rule_branch_bind.py` / `runtime/c26_rule_branch_bind.txt` | sub-rule/FK oracle |
| `runtime/c27_query_plan.py` / `runtime/c27_query_plan.txt` | query plan oracle |
| `runtime/c28_weaviate_retrieve.py` / `runtime/c28_weaviate_retrieve.txt` | retrieval oracle |
| `runtime/c29_pack_verify.py` / `runtime/c29_pack_verify.txt` | provenance/crosswalk oracle |
| `runtime/calculators/registry_engine.py` / `runtime/calculators/registry_engine.txt` | 계산 oracle |
| `runtime/authority/authority_preflight.py` / `runtime/authority/authority_preflight.txt` | authority preflight oracle |
| `offline_build/build_s2_20_inline_projection.py` / `offline_build/build_s2_20_inline_projection.txt` | authoring→배포 YAML·inline mirror·receipt 투영/검사 |
| `offline_build/compile_case_type_registry.py` / `offline_build/compile_case_type_registry.txt` | case catalog compile |
| `offline_build/compile_relief_rule_projection.py` / `offline_build/compile_relief_rule_projection.txt` | Markdown→structured rule projection |
| `offline_build/build_authority_law_value_release.py` / `offline_build/build_authority_law_value_release.txt` | authority/law value release |
| `offline_build/build_corpus_snapshot.py` / `offline_build/build_corpus_snapshot.txt` | corpus snapshot build |
| `offline_build/build_release_manifests.py` / `offline_build/build_release_manifests.txt` | parent/module release 조립 |
| `release_ops/release_validator.py` / `release_ops/release_validator.txt` | release closure 검증 |
| `release_ops/canary_rollback.py` / `release_ops/canary_rollback.txt` | canary/rollback 운영 검증 |
`R/workflows/S2_20_canonical_relief_plan_reduce.yml`은 선언 계약으로 builder/validator가 사용하며 runtime의 fixed read 목록에는 없다. `R/schemas/domain_verdict.schema.json`은 S2_10 정의를 가리키는 facade이고 S2_20 inline은 직접 `schemas/s2_10.schema.json`을 읽는다. `R/manifest/s2_20_parent_member_paths.json`은 parent closure의 build allowlist다. 전략/SOW/assets 및 root `case_kinds.md` 역시 runtime read 대상이 아니다. 근거: [assets §1](S2_20_assets.md), 배포 YAML hydrate의 closed 목록.
### 4.3 시험자료
`R/tests/s2_20/`의 다음 이름 각각에 `.py`와 `.txt`가 존재한다: `test_agent_and_inline_parity`, `test_option_group_and_binding`, `test_calculation_and_reports`, `test_retrieval_and_pack`, `test_plan_publish_and_release`, `test_inline_output_schema`, `test_offline_compilers`, `test_regression_manifest_closure`. 예를 들어 첫 쌍은 `R/tests/s2_20/test_agent_and_inline_parity.py`와 `R/tests/s2_20/test_agent_and_inline_parity.txt`다. 이들은 사건 task가 호출하지 않는 offline 시험자산이다.
fixture는 `R/tests/fixtures/s2_20/` 아래 `minimal_supported_portfolio.json`, `mixed_option_dispositions.json`, `case_type_rule_binding_matrix.json`, `case_type_zero_multi_hash_mutations.json`, `calculation_temporal_boundaries.json`, `actio_route_cap_matrix.json`, `retrieval_replay_injection.json`, `plan_publish_barrier_failure.json`, `regression_manifest.json`이다. 상위 `R/tests/fixtures/regression_manifest.json`은 공유 회귀목록이다. 파일 존재와 시험항목 이름은 실제 production 법률 coverage의 증거로 쓰지 않는다.
## 5. 내부 소작업: 이름·내용·목적
| 소작업 / 실제 구현 위치 | 작업 내용 | 목적·연결 |
|---|---|---|
| Bootstrap `run`, `McpClient` (Y:248,3902) | identity 치환 검증, localdocs initialize, JSON-RPC/SSE, session 헤더, stdout 격리 | 한 Code Executor 호출로 신뢰 가능한 binary IO 유지 |
| Request/Trust/Hydration (Y:352,2025,2147,2762) | 18-key request, raw hash/schema, binding row·CAS·admission·상류 완료 검증, 제한된 exact 파일 열거 | 다른 사건·다른 release·중간 산출물 혼입 방지 |
| C20 `option_disposition`, `build_portfolio` (Y:405,821) | 승인 policy의 exact row 또는 미승인 fallback에 따라 4분할. active option에 AC/CG 생성. same recovery key로 CG를 공유 | 청구후보 보존과 후속 공동작성 단위 구성 |
| C21 `build_party_projection`, `claim_c21_projection` (Y:934,986) | party/object ID·불명확성·role token; right holder/obligor 수와 identified object set projection | 법률상 당사자 판단 전에 사실상 identity 정보를 결속 |
| Signature projection `project_signature` (Y:444) | 승인된 target별 rule로 DIRECT_COPY/CLOSED_LOOKUP/SET_UNION/SET_INTERSECTION. 미도출 UNKNOWN | 사건명·임의 자연어 없이 C25가 읽을 typed vocabulary 확보 |
| C25 `bind_case` (Y:587) | 승인 CLAIM/GENERIC·CLAIM_CAPABLE row의 단일 predicate exact match | 137종 중 원자청구의 drafting/retrieval case ID 선택 |
| C26 `bind_rule`, `validate_rule_foreign_keys` (Y:615,651) | 단일 승인 branch; Markdown/review hash, structured rule, renderer, party, corpus, CE13, review FK 검사 | 잘못된 문서·branch를 선택하거나 누락된 rule로 clean drafting 하지 않게 함 |
| C22 `calculate_all` (Y:1010) | AC별 17 CE activation·descriptor/formula 선택·Decimal 연산 틀·law-value·missing operand receipt | 계산 근거와 계산불능 사유를 기록. 현 숫자 operand 통로는 미구현 |
| C27 `build_retrieval_branch` 앞부분 (Y:1353) | bound case/sub-rule/corpus scope 및 role/element ID를 canonical query로 생성 | 검색이 case binding을 역으로 변경하지 못하도록 범위 고정 |
| C28 같은 함수 검색부 (Y:1496) | read-only `search_hybrid`, 고정 filter, 최초 호출 포함 최대 3회 시도(재시도 최대 2회), 정렬/중복제거/탈락사유/receipt | 승인 corpus에서 필요한 정보를 제한적으로 조회·추적. receipt attempt_count는 query별 시도수의 최댓값이며 총 retry 수가 아님 |
| C29 같은 함수 pack부 (Y:1618) | hit element→registry crosswalk·Stage1 slot ref 연결, unmapped/conflict 목록 구성 | source·요건 ref를 S2_30 보조자료로 전달; 사건 사실 창작 금지 |
| C30 `execute_core` 후반 + `artifact_payloads` (Y:1782–2016,3172) | group set·permission·issues·party report·exhibit·conservation, calculation 요약·gap/filing 봉투 | 작성자료 정리 및 검토 필요성 가시화 |
| C35 같은 함수들의 plan/slice/segment 구성 (Y:1957,3300) | plan hash, frozen group slice, P31/P32 ref, producer별 artifact bytes | S2_30이 수정할 수 없는 명시적 작성 입력 생성 |
| Schema validation `build_schema_documents`, `_schema_errors` (Y:3381,3584) | local `$ref` closure, 지원 JSON Schema keyword 검사 | malformed payload를 정상 output으로 저장하지 않기 위한 형식검사 |
| Publish `publish`, `publish_diagnostic` (Y:3774,3834) | schema 검증→immutable write→readback→barrier-last; 실패시 partial row 보존 | 자료 존재와 후행 소비허가를 분리 |
함수와 component의 관계는 1:1이 아니다. C30·C35의 상당 부분은 `execute_core()`와 `artifact_payloads()`에 분산되어 있고, C27∼C29는 하나의 함수다. 함수 호출 단위와 파일의 `producer_component` 라벨도 같은 개념이 아니다.
## 6. upstream/downstream dependency의 실제 의미
### 6.1 S2_00 → S2_20
S2_00은 실제 사건 사실·증거·party/object ID와 cluster 단위를 제공한다. S2_20은 `ingress_status.output_barrier.artifacts`에 소비하는 context·slice raw hash가 모두 포함되는지 검사하고, 각 artifact header의 run_id/input_set_digest/release_digest/schema hash를 대조한다. 이 덕분에 S2_10 verdict가 가리키는 slice와 S2_20이 보는 사건 context가 같은 사건 snapshot에 연결된다. S2_00 status-only route는 S2_20 경로가 아니며 NORMAL/executable cluster를 요구한다. [Y:2350–2468](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L2350)
### 6.2 S2_10 → S2_20
S2_10 claim option은 법률판단의 원본이다. S2_20은 COMPLETE global barrier·정확한 executable cluster 집합·모든 wave 완료와 producer contract digest를 확인한 뒤 option을 정리한다. excluded/deferred도 conservation report에 남기고 selected/alternative만 AC 및 CG를 만든다. CG ID는 `same_underlying_recovery_key`가 있으면 그 키, 없으면 option ID에서 deterministic 생성한다. active option 간 INCOMPATIBLE/PRECONDITION 관계만 그룹 간 edge로 별도 만든다. 상류의 모든 의미관계를 새로 법률 판단하는 graph solver는 아니다. [Y:821–931, 2580–2758](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L821)
### 6.3 C25/C26 → C22 및 C27/C28/C29
case/sub-rule의 exact binding은 동일 사건종류 문서 안에서 원자규칙을 찾는 키이며, CE activation과 corpus 검색범위를 함께 제한한다. 검색 hit를 이용해 case ID를 다시 선택하지 않는다. C26은 Markdown 본문을 자유롭게 해석하는 대신 source raw hash 및 structured branch/FK를 확인한다. 검색 결과와 규칙문서는 Stage1 사실의 추가 원천이나 S2_10 verdict 변경권한을 갖지 않는다. P31은 `RELIEF_ONLY` rule pack과 `CAUSE_AND_ELEMENT_CHECK` fact pack을 별개 권한으로 함께 참조한다. [Y:651–818, 1353–1460, 3250–3370](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L651)
### 6.4 S2_20 → S2_30 → S2_40
S2_30이 사용할 핵심 묶음은 `group_slices/<CG>.json` + P31/P32 segment + 그들이 정확한 raw hash로 가리키는 packs/calculation/gap 자료다. frozen plan은 group slice에서 다시 hash로 결속된다. 전체 집합의 completeness와 작성권한은 `plan_publish_status.json`의 artifact_rows/group partitions로 전달한다. `TO_S2_30`은 그룹 중 일부가 REVIEW_DRAFT/WORKNOTE_ONLY여도 가능하며 법률 문제를 자동 소거하지 않는다. `consumer_authorized=true`는 자료소비 권한이지 법원제출 승인이나 실제 corpus/live 승인 증명이 아니다. S2_40이 나중에 상류 자료와 작성 결과를 재검증할 수 있도록 producer·source·hash가 남는다. [Y:3320–3376, 3789–3831](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L3320)
## 7. 상태·failure·외부 책임
| 상황 | 실제 결과 |
|---|---|
| 정확한 case/rule binding·관련 registry/authority/retrieval/calculation 조건 충족 | group `CLEAN_DRAFT` 후보. §8의 permission 누락 때문에 법률 완전성 보증으로 해석 금지 |
| permission issue 존재, 해당 group legal decision에 UNRESOLVED 포함 | `WORKNOTE_ONLY` |
| permission issue 존재, UNRESOLVED 없음 | `REVIEW_DRAFT` |
| 모든 group CLEAN_DRAFT | `PLAN_COMPLETE`, `TO_S2_30`, consumer_authorized=true |
| 하나 이상 group이 review/worknote | `PLAN_COMPLETE_WITH_REVIEW`, `TO_S2_30`, consumer_authorized=true |
| trust 검증 전 실패 | plan/diagnostic write 금지, stdout ok=false, exit 2 |
| trust 검증 후 오류 | diagnostic·TECHNICAL_INCOMPLETE barrier 저장 시도, STOP_TECHNICAL_INCOMPLETE |
| 기존 동일 경로 동일 bytes | idempotent 재사용 |
| 기존 동일 경로 다른 bytes 또는 readback 불일치 | immutable conflict/partial write; 정상 소비허가 불가 |
외부 책임은 identity 치환, shared binding의 live 승인·image pin·egress, run-bound CAS 발급, backend 서명검증 및 capability, request 생성, 실제 Weaviate collection/tenant/credential 연결, outer receipt 영속화, 다음 Agent 호출이다. inline이 서명을 암호학적으로 직접 검증하는 것은 아니며 `BACKEND_VERIFIED` 상태·signed material digest·capability linkage를 신뢰계약으로 검사한다. [Y:2080–2235](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml#L2080)
현재 [corpus_release.json](Default_Agent/Stage_2_Clean/manifest/corpus_release.json)은 `DEV_UNAVAILABLE`, available/sealed/signed=false이며 collection/snapshot이 null이다. 따라서 검색 구현의 존재만으로 live retrieval이 가능하다고 판단할 수 없다. 법률자료 승인과 실행환경 admission은 별개 층이다.
## 8. 설계와 실제 구현의 차이·중요한 한계
아래는 분석상 발견사항이며 실행자산 변경 제안의 자동 승인이나 이번 작업에서의 수정 사실이 아니다.
| 항목 | 소스에서 확인한 실제 동작 | 분석상 의미 |
|---|---|---|
| C20 관계 완결성 | build_portfolio는 active option 간 INCOMPATIBLE/PRECONDITION만 group edge로 만들며 대상 group이 없거나 같으면 건너뜀. `duplicate_recovery_issue_refs=[]` 고정 | [SOW §6.1](S2_20_SOW.md#L440)의 cycle/dangling/recovery cap/frontier 전부 구현으로 읽을 수 없음 |
| 미승인 disposition policy | 명시적 fallback if 분기를 사용하고 DISPOSITION_POLICY_NOT_ADMITTED를 reason으로 남김 | SOW의 승인 exhaustive table only 요구와 차이. 결과는 clean permission에서 차단하지만 partition 자체는 생성 |
| C21 title/role | title_chain_refs=[]; role token은 전체 party context에서 모음 | 완전한 title chain·group별 당사자 적격 판단이 아니며 전체 사건 role이 group completeness에 사용됨 |
| C22 계산 | required operand마다 status=MISSING/value=null 생성; law values는 receipt에 붙이나 산술 연산 inputs는 operand_rows뿐 | typed numeric handoff 미구현. CE별 실제 기간/3-cap/소가 계산이 모두 된 상태가 아님 |
| C22 descriptor 자기참조 hash | Y:1194–1200은 descriptor 내부 descriptor_sha256을 descriptor_hashes 값과 같게 요구하고 Y:3136–3142는 그 값을 descriptor 전체 raw bytes hash로 계산 | 자기 hash 필드를 제외하지 않는 고정점 요구다. 현 pending 자산 승인과 operand 보완만으로 계산 실행이 완성된다고 설명할 수 없음 |
| 특칙 7종 | `_validate_special_legal_asset`로 envelope 확인 후 `assets.special_legal_assets`에 저장; execute_core에서 해당 rows 미소비 | ACTIO·유류분·반대급부·절차적 의사표시·금지문안 특칙을 실제 적용했다고 표현 불가 |
| group 슬롯 | amount_slots/period_slots/counter_performance_refs/procedural_declaration_refs는 빈 배열로 시작해 채우지 않음 | frozen plan의 해당 실질정보는 현재 빈 상태 |
| filing metrics | rows=[], source_ce13_receipt_ids=[], REVIEW_REQUIRED 고정 | 소가/인지/송달비 계산결과를 실제 집계하는 단계 미완성 |
| gap 분석 | group마다 corpus_element_id=UNRESOLVED, coverage_status=GAP, gap_count=1 고정 | slot_crosswalk/요건·항변·증거를 전수 대조한 실제 gap 계산이 아님 |
| P32 | ordered_asset_refs=[] | 공통 authority 본문/참조를 여기서 materialize하지 않음 |
| C29 inline/oracle 차이 | inline은 element ID만으로 crosswalk dictionary 구성, CONFLICT도 목록에 기록하면서 pack item에 포함. 별도 `c29_pack_verify.py`는 (element,role) 키와 conflict 제외 정책 | pure-core oracle 시험만으로 inline 동일 행동 보증 불가 |
| 검색 source 검증 | inline은 승인·case/sub-rule/scope/element-set/role/jurisdiction 및 metadata hash 문자열 일치를 확인. 실제 chunk 본문을 받거나 다시 hash하지 않고 source locator/authority IDs를 투영 | SOW가 요구한 원문 hash·snapshot·temporal 의미·authority 전부의 검증과는 차이. `replay_status=NOT_REQUESTED`이며 replay 비교 실행 없음 |
| permission 재검사 | permission은 binding, activation GAP/CONFLICT, result_status COMPLETE, registry/authority flag 기준. MISSING_OPERAND·party report missing role·고정 gap·unmapped/conflict 자체를 후행 재반영하지 않음 | CLEAN_DRAFT를 “모든 계산/당사자/요건 gap 해소”로 해석하면 과장 |
| legal decision과 permission | Y:1861–1868은 permission_codes가 없으면 legal_decisions에 UNRESOLVED가 있어도 먼저 CLEAN_DRAFT 선택 | 법적 유보 자체가 CLEAN_DRAFT를 무조건 막는다고 설명할 수 없음. 앞 단계에서 해당 option이 active로 남는 조건과 함께 해석해야 함 |
| ledger 보존 | base issue IDs/raw hash 및 신규 plan issues를 생성하지만 S2_10 issue_patches/assumption/usage는 검증·보관 후 core merge 없음 | “S2_20이 모든 상류 issue를 완전히 reduce했다”는 설명 불가; S2_40의 별도 보존검사와 구별 |
| TOCTOU 범위 | 각 read_stable 두 읽기 비교는 있으나 seed→all_raw 세대간 동일성 비교는 없음. release/registry 신뢰검사의 일부는 seed로 하고 core assets는 all_raw로 사용 | “전체 hydration 내내 단일 snapshot 불변을 완전 보증”으로 표현 불가 |
| 출력 schema 검증 범위 | payloads 전체 검증 후 저장. 정상 barrier·diagnostic·실패 barrier·stdout receipt에는 validate_artifact_payload 호출 없음 | “모든 생성 JSON을 저장 전에 schema 검증한다”는 설명은 S2_20에 맞지 않음 |
| 실패 barrier의 schema 충돌 | `publish_diagnostic`(Y:3834–3898)은 partial artifact rows 뒤에 diagnostic row를 추가하나 `schemas/relief_plan.schema.json` L712–734의 TECHNICAL_INCOMPLETE 분기는 artifact_rows를 정확히 1개 diagnostic으로 제한 | partial write가 발생한 경우 생성 실패 barrier가 선언 schema를 위반할 수 있음. 실패 기록이 항상 schema-valid라는 해석은 배제 |
행 근거: C20 Y:405–441/821–931, C21 Y:934–1007, 계산 Y:1145–1299, 특칙 Y:3058–3125, 빈 슬롯 및 permission Y:1782–1868, ledger Y:1894–1903, filing/gap/P32 Y:3210–3372, retrieval Y:1520–1666, hydration Y:2824–3022, publish Y:3774–3965. 모두 [배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml)에서 직접 확인한 범위다. C29 비교는 [별도 oracle](Default_Agent/Stage_2_Clean/runtime/c29_pack_verify.py)을 직접 대조했다.
## 9. 전문 읽기 및 검증 기록
배포 YAML은 1–250, 251–700, 701–1150, 1151–1600, 1601–2050, 2051–2500, 2501–2950, 2951–3400, 3401–3979행으로 나누어 전문을 읽었다. 이어 top-level/class/nested function 목록을 검색해 §5와 아래 부록의 누락 여부를 대조했고 workflow·SOW component 계약·asset inventory·corpus 상태 및 C29 oracle을 보조 확인했다. runtime 코드·자산·release는 변경하지 않았다.
| 회차 | 검증자·검증 내용 | 발견사항 및 증분 수정 |
|---|---|---|
| 1차 | main agent: 본문 전문·실제 task 설정·execute_core/계산/실패 publisher/schema 및 상하류 IO 대조 | 실행 parameter 누락 보완; permission의 법적 UNRESOLVED 우선순위 명시; partial-write 실패 barrier와 schema의 maxItems=1 충돌 추가 |
| 2차 | 독립 analysis00: 수정본 전문, C20/C21/C22/C27–29/C30/C35·hydration·publisher/schema·자산 대조 | 1차 수정 확인. descriptor 자기참조 hash, 최초 포함 3회 시도/attempt_count 의미, zero-group 정상 게시 경계 추가. main agent 반영 |
검증-수정은 총 2회로 종료했다. 검증은 분석서의 기술적 설명을 대상으로 하며 원본 실행자산을 수정하거나 live 성공을 입증하지 않는다.
## 부록 A. 함수 전체와 component 대응
중첩 함수는 소유 함수와 함께 표기했다. 실제 클래스 메서드까지 포함해 실행 지원 기능이 분석에서 빠지지 않도록 한다.
| 묶음 | 함수/메서드 및 시작행 |
|---|---|
| 오류/정규화/JSON/path/hash/ID | `S220Error.__init__` 98, `as_dict` 104; `nfc` 111; `no_duplicates` 115; `load_json` 124; `canonical_bytes` 141; `digest` 148; `safe_path` 153; `join_path` 164; `require_hex` 168; `stable_id` 174 |
| MCP transport/binary IO | `_parse_mcp_payload` 179; `_tool_text` 212; `_binary_from_text` 226; `McpClient.__init__` 249, `close` 261, `_post` 266, `initialize` 279, `call` 299, `read_binary` 311, `read_optional` 315, `write_immutable` 323 |
| request/hydration/상류 검증 | `validate_request` 352; `read_stable` 388; `_require_mapping` 2019; `_verify_binding_text` 2025; `_admission_signed_material` 2139; `_verify_external_trust` 2147; `_require_object_self_hash` 2238; `_validate_loaded_value` 2249; `_sealed_child_asset_hash` 2268; `_validate_special_legal_asset` 2282; `validate_upstream_handoff` 2318 (`loaded` 2330); `hydrate` 2762 |
| C20/C21/C25/C26 | `option_disposition` 405; `project_signature` 444; `eval_predicate` 556; `eval_closed_predicate` 576; `bind_case` 587; `bind_rule` 615; `_source_ref` 647; `validate_rule_foreign_keys` 651; `build_portfolio` 821; `build_party_projection` 934; `claim_c21_projection` 986 |
| C22 | `calculate_all` 1010; 내부 `decimal_value` 1070, `claim_metrics` 1076, `row_matches` 1090, `empty_receipt` 1115, `operand_row` 1145 |
| C27/C28/C29 | `call_with_transient_retry` 1304; `canonicalize_retrieval_hits` 1322; `build_retrieval_branch` 1353 |
| 내부 DAG/C30/C35 | `execute_core` 1670; `_artifact_ref` 3168; `artifact_payloads` 3172 (내부 `merged_rule_refs`) |
| schema closure | `build_schema_documents` 3381; 내부 `rewrite_external_refs` 3453, `merge_namespaced_external_defs` 3466, 그 내부 `rewrite_source_local_refs`, `rewrite_target_external_refs` |
| schema 검사 | `_schema_pointer` 3546; `_schema_type_matches` 3562; `_schema_identity` 3580; `_schema_errors` 3584; `validate_artifact_payload` 3753 |
| writer/종료 | `publish` 3774; `publish_diagnostic` 3834; `run` 3902; `__main__` guard 3964; `task_procedure` 3966 |
## 부록 B. 근거 우선순위
1. 실행 사실: [배포 YAML](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml) inline 코드와 closed task graph.
2. 형식/연결: [ReliefPlan schema](Default_Agent/Stage_2_Clean/schemas/relief_plan.schema.json), [binding/retrieval schema](Default_Agent/Stage_2_Clean/schemas/binding_retrieval.schema.json), [calculation schema](Default_Agent/Stage_2_Clean/schemas/calculation.schema.json), [deployment schema](Default_Agent/Stage_2_Clean/schemas/deployment.schema.json), [workflow](Default_Agent/Stage_2_Clean/workflows/S2_20_canonical_relief_plan_reduce.yml).
3. 설계 의도: [S2_20_SOW.md](S2_20_SOW.md), [S2_20_assets.md](S2_20_assets.md), [v5-1 전략](stage_2_optimal_update_strategy_v.5-1.md).
4. 과거 구현·검증의 맥락: [MEMORY.md](MEMORY.md). 현재 실행 검증 증거를 대신하지 않는다.
@@ -0,0 +1,270 @@
# Stage 2_30 작업분석서
## 1. 분석 대상과 결론
S2_30은 S2_20이 확정한 claim group별 청구취지와 청구원인을 **같은 LLM context에서 공동작성**하는 단계다. 동결된 청구권·당사자·rule branch·계산 결과를 바꾸지 않고 raw typed atom을 반환한다. 실행 YAML은 입력을 실제로 읽어 결속하는 deterministic planner 1개와 group별 wildcard LLM task family 1개를 가진다. 영구 atom ID·불변 파일 저장·retry·publish barrier는 YAML의 LLM이나 planner가 수행하지 않으며 외부 native result adapter가 담당해야 한다.
| 항목 | 2026-09-09 확인값 |
|---|---|
| 분석 실행본 | [Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_30.yml](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_30.yml) |
| 줄수 / SHA-256 | 1,851행 / `d0804526941207395c9b64a314b124ff8e919c6852e828d829dc45a9feb3ccdd` |
| Agent / stage / version | `Stage_2_S2_30` / `S2_30` / `1.0.0` |
| task templates | `Task_S2_30_dispatch_planner` + `Task_S2_30_draft_group_*` |
| planner 실행 설정 | `code-executor.run_code`, Python, `httpx==0.28.1`, `agent-network`, timeout 300초; endpoint `https://code-executor.mcp.eroomai.com/mcp` |
| 모델 설정 | `openai / gpt-5.6-sol / xhigh / medium / responses`, `preflight:false`, `max_concurrency:8` |
| parent raw hash 상수 | `9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53` |
| 구현/실행 상태 선언 | offline 구현; `BLOCKED_PENDING_PLATFORM_MODEL_LEGAL_AND_SOURCE_ADMISSION` |
배포 YAML 1–500, 501–1000, 1001–1450, 1451–1851행을 연속으로 전문 읽고 실제 workflow/binding/schema·SOW/assets를 대조했다. 아래 `Y:L숫자`는 이 배포 YAML 행번호다. source hash는 과거 MEMORY의 S2_30 초기 구현 hash와 다르므로 현재 파일의 값을 기준으로 한다. 과거 시험 PASS를 이번 분석의 실행 결과로 재사용하지 않는다.
`M = Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/`, `R = M/Default_Agent/Stage_2_Clean/`, `O = stage2_runs/by-binding/<run_binding_digest>/`로 표기한다. `O`는 Localdocs의 사건별 동적 논리경로이며 저장소 고정 파일 경로가 아니다.
## 2. 전체 DAG와 단위 구분
```text
S2_20 plan_publish_status + frozen plan/P32/P31/group slices
|
v
outer orchestrator: group dispatch + CAS + mode admission
|
v
IN -> Task_S2_30_dispatch_planner [고정 Python; 단일 Code Executor]
identity/MCP -> parent/module/child/Agent/schema/prompt hash
-> batch/admission -> S2_20 barrier + source materialization
-> owner/follower receipt -> stdout {dynamic_fanout:[items...]}
|
v
Task_S2_30_draft_group_* [GPT-5.6 Sol; 최대 8 instance 병렬]
+--- group A: P00 -> P30 -> P32 -> P31 -> S30 -> raw JSON
+--- group B: P00 -> P30 -> P32 -> P31 -> S30 -> raw JSON
+--- group N: P00 -> P30 -> P32 -> P31 -> S30 -> raw JSON
|
v
OUT: all wildcard task 완료 대기
아래는 추가 YAML task가 아니라 외부 adapter의 필수 책임
raw JSON -> schema/input echo/provenance/coverage 검증
-> group-local atom ref -> deterministic permanent ID 2-pass 치환
-> immutable draft/issue/worknote/usage parts + read-back
-> receipt-free artifact_manifest core
-> item/cohort receipts -> s2_30_publish_status LAST
| |
모두 성공 실패 group만 1회 retry
| |
TO_S2_40 2차 실패: terminal stop
```
전체 Stage 2의 의미상 backbone은 S2_00→10→20→30→40의 5단계이고 법률 LLM 단계는 S2_10/S2_30 두 개다. 그러나 **배포 Agent task template/family 기준으로는 S2_30 planner가 추가되어 총 6개**이며 S2_30 wildcard의 실제 instance 수는 group 수에 따라 변한다. 이것을 “법률판단 단계가 6개” 또는 “S2_30에 LLM task 두 개”로 해석하면 안 된다. S2_30 `prevs/nexts=[]`는 외부 호출이 없는 뜻이 아니라 이 YAML 안에 타 Stage가 없다는 뜻이다. S2_20/S2_40 연결은 barrier/outer adapter 계약에 존재한다. (Y:L1–54, L1455–1465, L1833–1851; [SOW §0](S2_30_SOW.md))
owner-first 계획은 한 cohort의 첫 group 성공을 확인한 후 follower들을 실행하여 공통 prefix cache를 재사용하는 것이다. 이 단계의 설계와 현재 batch/group equality 구현 사이 차이는 §8에 별도로 명시한다.
## 3. 입력 파일·포맷·사용 방식
### 3.1 control / 배포 신뢰 입력
| 정확 경로 / 형식 | 생산·소유 주체 | 소비 내용 |
|---|---|---|
| `stage2_control/s2_30_group_dispatch.json` / JSON | outer orchestrator | closed batch 20-key; run/cohort/attempt/mode/phase, S2_20 barrier ref, 배포/prompt/schema hashes, expected groups, mode gate, items, batch digest |
| `stage2_control/s2_30_canary_authorization.json` / JSON | trusted admission owner | SUBSET_CANARY만 exact authorization path/hash·scope·issuer·기간·서명 attestation 검증 |
| `R/manifest/stage2_release.json`, `R/manifest/module_manifest.json` / JSON | release builder | inline parent raw hash와 self digest, module manifest hash/self digest |
| `R/manifest/s2_30_release.json` / JSON | child release builder | parent 연결과 sealed assets index |
| `R/agent_scripts/Stage_2_S2_30.yml`, `R/deployment/stage2_s2_30_llm_binding.yml` / YAML | authoring/projection/binding owner | child sealed hash와 dispatch hash 비교 |
| `R/schemas/draft_atoms.schema.json` / JSON Schema | schema owner | batch/materialized item/selected value 및 raw/canonical part 계약 |
| `R/manifest/s2_30_inline_prompt_projection_receipt.json`, `s2_30_inline_code_receipt.json` / JSON (`manifest/` 아래) | projection builder | 실제 prompt scalar P00/P30 hash 및 Agent/code 봉인 |
| `R/manifest/s2_30_platform_adapter_receipt.json`, `s2_30_model_benchmark_receipt.json`, `s2_30_legal_review_receipt.json` / JSON (`manifest/` 아래) | platform/model/legal admission owner | SUBSET_CANARY는 platform receipt; PRODUCTION은 세 종류 전부 exact admitted schema/status/effect/evidence/signature 확인 |
| `R/agent_scripts/Stage_2_S2_20.yml`, `R/runtime/s2_20_reduce.py` / YAML/Python text | S2_20 배포 owner | barrier에 기록된 S2_20 Agent/code hash와 실제 bytes를 대조. Python을 실행/import하는 것은 아님 |
| `O/map_s2_30/cohort_receipts/<cohort_id>/attempt-<1 또는 2>.json` / JSON | 외부 cache-owner coordinator | FOLLOWER_BATCH의 owner-completion receipt. owner 성공·P32/cohort material digest·release/model tuple 확인 |
planner는 `read_binary_doc`이 아니라 **Localdocs `read_docs`**로 text를 읽는다. one-document JSON envelope 및 정확 요청 경로를 표기한 제한적 trailing metadata를 처리한 후 text UTF-8 bytes의 hash를 검증한다. 단일 문서 상한은 32 MiB 수치의 문자열 길이 검사이고 fanout 상한은 64 MiB 수치의 최종 encoded payload 길이 검사다. byte-preserving binary API를 호출한다고 설명하면 안 된다. (Y:L116–119, L137–193, L294–327, L1429–1436)
### 3.2 S2_20 및 관련 상류 자료
다음 `O/` 상대경로는 dispatch exact refs와 S2_20 barrier에 의해 결정된다. source contract는 `source_kind/path/sha256/schema_ref/json_pointer` 5개 키를 가진다. `source_kind`는 자유로운 파일 검색키가 아니라 경로·schema를 고정하는 selector다.
위 5키는 정규화된 ref의 모양이다. `normalize_ref`는 최소 path/sha256/schema_ref를 요구하고 빠진 source_kind는 inherited/default kind, json_pointer는 빈 문자열로 채운다. 이후 직접 source의 kind별 closed 계약 검사가 별도로 적용된다(Y:L1035–1108).
| source_kind | `O/` 아래 파일 / 형식 | 쓰임 |
|---|---|---|
| `S2_20_PUBLISH_STATUS` | `plan/plan_publish_status.json` / JSON | consumer_authorized·TO_S2_30, run/parent/S2_20 Agent/code, artifact-set/self hash, exact plan source index |
| `P32_AUTHORITY_PACK` | `plan/prompt_segments/<claim_group_id>/P32_common_authority.json` / JSON | 공통 authority의 ordered_asset_refs. wrapper의 group metadata는 receipt에 남기되 P32 prompt에서는 제외 |
| `P31_RULE_PACK` | `plan/prompt_segments/<claim_group_id>/P31_rule_and_pack.json` / JSON | group별 renderer/rule/requirement/calculation/exhibit data와 ordered refs |
| `S30_GROUP_SLICE` | `plan/group_slices/<claim_group_id>.json` / JSON | frozen group/input contract의 중심 |
| `CANONICAL_RELIEF_PLAN` | `plan/canonical_relief_plan.json` / JSON | source-plan hash, run, option-disposition→S2_10 verdict 연결 |
| `S2_10_PART` | `map_s2_10/domain_verdicts/<cluster_id>.json` / JSON | 관련 법률판단 verdict. 선택 option의 source verdict raw hash 집합 일치 |
| `S2_00_CLUSTER_SLICE` | `context/cluster_slices/<cluster_id>.json` / JSON | group의 ID projection과 관련 cluster 사실·증거 자료 |
| `NORMALIZED_FACT_SOURCE` | `context/case_context.json` / JSON | normalized fact context. 의도상 `/facts/<index>` 선택; 현행 pointer 제한 문제는 §8 |
| `NORMALIZED_EVIDENCE_SOURCE` | `context/evidence_inventory.json` / JSON | normalized evidence. 의도상 `/items/<index>` 선택; 현행 pointer 제한 문제는 §8 |
| inherited ordered refs | 위 P32/P31/S30 selected object의 `ordered_asset_refs[]`가 지정한 `plan/` 하위 exact path / JSON | 재귀적 materialization. plan artifact index의 같은 path/hash/schema를 요구하고 원 배열 순서 유지 |
schema ref는 `schemas/relief_plan.schema.json#/$defs/...`, `schemas/s2_10.schema.json#/$defs/canonical_domain_verdict`, `schemas/context.schema.json#/$defs/...`로 고정되어 있다. 이것들은 실행 시 선택값을 검증하는 추가 schema read를 일으킨다. runtime schema path를 actual `R/schemas/`로 결속하는 플랫폼 경로 의미도 중요하다. code의 `validate_selected`는 전달된 `schema_path`를 그대로 `read_docs`에 넘긴다. (Y:L521–567, L1050–1118)
`materialize`는 자료 내용을 법률적으로 요약하지 않는다. exact hash JSON을 읽어 selected value와 provenance receipt를 구성한다. `plan/` source는 barrier index membership가 필수이고, 다른 run의 `stage2_runs/by-binding/...`는 거부한다. 같은 path/pointer/schema ref 반복은 선언 bytes가 같으면 중복 read를 생략하고 다르면 거부한다. source의 embedded claim_group_id가 현재 group과 다르면 거부한다. reference allowlist의 각 값이 materialized source에서 추출한 ID/ref 집합에 포함되는지도 확인한다. (Y:L1141–1403)
다만 canonical plan은 현재 전체 객체가 S30에 들어간다. 최상위 claim_group_id가 없는 전체 plan은 위 embedded-group 검사에 걸리지 않으며 다른 group/option의 ID도 추출 참조집합에 포함될 수 있다. “현재 group만의 자료·allowlist”라는 의미적 제한이 planner에서 완전히 강제되는 것은 아니다(§8.9).
### 3.3 planner에서 LLM으로 전달하는 item
| item field | 포맷 / 의미 | 소비 |
|---|---|---|
| `p32_common_authority_json` | 종결 LF 없는 canonical JSON 문자열, `{sources:[...]}` | 세 번째 system data block; cohort 내 같은 bytes 필요 |
| `p31_rule_and_pack_json` | `{claim_group_id,sources:[...]}`의 canonical JSON 문자열 | 네 번째 system data block; exact group rule/pack |
| `s30_group_slice_json` | `{claim_group_id,input_contract,sources:[...]}` canonical JSON 문자열 | user block의 `s30_group_slice` object 값 |
| `compile_mode`, `s30_group_slice_sha256` | mode / 실제 materialized S30 JSON 문자열의 raw hash | user envelope transport binding 및 raw output input_echo |
| `request_id`, `run_binding_digest`, `cohort_id`, `attempt_no`, `dispatch_phase`, `stable_ordinal`, `drafting_permission`, `source_plan_sha256` | closed execution/group metadata | 외부 native adapter의 결과 연결·검증 |
| P32/P31 hash, `source_materialization_receipts`, `materialized_reference_values` 및 hash, `s30_source_refs`, `reference_allowlist` | 검증된 source receipt/data | input echo·provenance 검증·감사 |
planner stdout은 `{"dynamic_fanout":[...]}` 하나이며 item은 파일로 저장하지 않는다. 영구 group/atom ID를 만들지 않는다. P32/P31/S30는 runtime prompt 지시문이 아니라 데이터이고, P00/P30는 YAML에 직접 들어 있는 static literal이다. (Y:L1335–1395, L1429–1438, L1812–1831)
## 4. LLM 내부 소작업과 prompt 계층
| 순서 / prompt | 실제 source | 역할 |
|---|---|---|
| 1 system / P00 | `<stage_2_common_cache_prefix>` inline literal | Stage 2 공통 출처·사실 창작 금지·injection 방어·provenance·불확실성 |
| 2 system / P30 | `<s2_30_joint_drafting_static_prompt>` inline literal | claim-group 공동작성·frozen plan·atom/coverage/permission 계약 |
| 3 system data / P32 | `{{item.p32_common_authority_json}}` | 승인 공통 authority data |
| 4 system data / P31 | `{{item.p31_rule_and_pack_json}}` | frozen renderer/rule/요건사실·계산/증거표시 자료 |
| 5 user data / S30 | 3-key envelope: materialized S30, mode, S30 hash | 현재 group 사실·증거·선행 verdict/input contract |
공통 static prefix를 앞에 두고 공통 authority→group rule→사건 자료 순으로 변화가 많은 부분을 뒤로 둔다. follower owner receipt가 결속하는 코드의 `cohort_material_digest`는 parent/child/Agent/binding/P00/P30/P32/model/effort/verbosity/endpoint다. S30·request/group/attempt는 이 tuple에 없고 P31 역시 이 함수의 tuple에 직접 들어 있지 않다. provider cache hit, cache retention, token 절감량을 YAML 구조만으로 보장할 수 없으며 실제 telemetry는 별도다. (Y:L891–919; [SOW §4](S2_30_SOW.md))
LLM task는 `preflight:false`여도 planner admission·barrier 검사를 생략하지 않는다. 이 flag는 LLM task의 설정이고 실제 앞선 deterministic planner가 preflight 역할을 수행한다. max_concurrency 8은 wildcard instances 상한이며 planner 내부를 8개로 병렬 실행한다는 뜻이 아니다. (Y:L1455–1465)
| 내부 소작업 | 내용 / 목적 | YAML locator |
|---|---|---|
| input echo | group/option/atomic IDs, permission, source-plan/P32/P31/S30 hash 보존 | L1627–1634 |
| frozen slot 보존 | party/object/performance/recipient/liability/counter-performance 및 계산 token 유지 | L1614–1625, L1635 |
| 청구취지 atom 작성 | P31 exact renderer/rule 범위 내 `relief_*`; 최종 번호·cost/provisional literal 확정 금지 | L1636, L1664 |
| 요건-사실-증거 연결 | requirement element마다 fact/evidence/authority, 누락/반대 ref 연결 | L1637 |
| 청구원인 공동작성 | `cause_parties→cause_facts→cause_law→cause_conclusion`; relief와 동일 급부/당사자/계산 기초 | L1638 |
| 절차상 선언 | actor authority/service event/status/도달 후 기간/효과조건; 예정 송달 PLANNED 보존 | L1639, L1706–1720 |
| 불리한 사실·항변 | expected adverse-fact 집합 보존; 실제 상대방 서면 없으면 ANTICIPATED_DEFENSE; 권한 없는 선제 공개 대신 worknote | L1722–1730 |
| atomic coverage | atomic claim별 relief/cause local ref exact partition, frozen alignment signature 복사 | L1774–1781, L1799–1807 |
| self-check | 새 ID/사실/숫자/READY/commit 없음, source·permission·coverage 준수 후 JSON 하나 | L1641, L1796–1810 |
이 표의 소작업은 P30가 하나의 LLM 호출 안에서 지시하는 사고·작성 순서이며 YAML의 별도 task entry가 아니다. self_check boolean은 모델 자기보고이고 native adapter의 deterministic 검증을 대체하지 않는다.
## 5. raw output과 영구 파일의 차이
LLM 반환 schema는 `draft_atoms.schema.json#/$defs/raw_joint_draft_output`이며 `schema_version=stage2_s2_30_raw_joint_draft_output.v1`이다. raw JSON에는 group/mode/permission/input_echo, atoms, atomic_claim_coverage, adverse_fact_rows, review_flags, missing_inputs, self_check가 들어간다. 각 atom은 group-local `atom_local_ref`, upstream claim_option/atomic IDs, closed output_section, typed text_or_slots, source_plan hash, provenance, disposition과 optional counter_performance/procedural declaration을 갖는다. 영구 `atom_id`는 LLM이 만들 수 없다. (Y:L1668–1704, L1758–1793)
| group permission | 허용 atom disposition |
|---|---|
| CLEAN_DRAFT | CLEAN, REVIEW, WORKNOTE_ONLY |
| REVIEW_DRAFT | REVIEW, WORKNOTE_ONLY |
| WORKNOTE_ONLY | WORKNOTE_ONLY |
output section은 `relief_main`, `relief_cost`, `relief_provisional_execution`, `cause_parties`, `cause_facts`, `cause_law`, `cause_conclusion`, `procedural_declaration`, `worknote_only`의 9개다. 법률명제는 released authority에, 사건사실은 fact/evidence에, 계산값은 calculation receipt/law-value에 연결해야 하며 corpus chunk가 authority나 사실을 대체하지 않는다. counter-performance는 독립 top-level atom type이 아니라 관련 relief_main/cause_conclusion의 같은 subobject다. (Y:L1643–1720)
아래 파일은 **외부 native adapter의 산출 계약**이다. 현행 YAML planner는 Localdocs write를 호출하지 않고 LLM도 raw JSON만 반환하므로, 아래 파일 생성 전체를 “inline Python이 구현했다”고 설명할 수 없다. [binding](Default_Agent/Stage_2_Clean/deployment/stage2_s2_30_llm_binding.yml)의 native handler는 `implementation_ref/version/sha256=null`이며 live fixture evidence도 빈 배열이다.
| `O/` 상대 출력 / 포맷 | 생산 내용·조건 | downstream 소비 |
|---|---|---|
| `map_s2_30/draft_parts/<claim_group_id>.json` / JSON | 검증·영구 ID 치환된 canonical atoms와 coverage/source-plan/provenance | S2_40 C40/C45 |
| `map_s2_30/issue_patches/<claim_group_id>.json` / JSON | review flags/missing/adverse rows | S2_40 final issue ledger |
| `map_s2_30/worknote_parts/<claim_group_id>.json` / JSON | worknote atom IDs와 provenance | S2_40 attorney worknotes |
| `map_s2_30/usage_parts/<claim_group_id>.json` / JSON | 모델 usage·원본 part provenance | S2_40 usage projection |
| `map_s2_30/artifact_manifest.json` / JSON | 각 successful group의 정확히 4 part family, path/raw hash/schema; receipt-free self-hashed core | S2_40의 유일 part index |
| `map_s2_30/item_receipts/<claim_group_id>.json` / JSON | 검증·불변저장/read-back 및 manifest-core 결속 | coordinator·S2_40 |
| `map_s2_30/cohort_receipts/<cohort_id>/attempt-<n>.json` / JSON | cohort 완료·manifest-core/provenance; owner-completion 용도 schema도 별도 존재 | follower planner / global coordinator / S2_40 |
| `map_s2_30/repair_request_parts/<claim_group_id>.json` / JSON | 실패 group의 한 번 추가 시도 요청 | retry controller |
| `map_s2_30/technical_failure_parts/<claim_group_id>.json` / JSON | 두 번째 실패 등 terminal 기술상태 | global coordinator |
| `map_s2_30/s2_30_publish_status.json` / JSON | manifest raw hash/path/schema·ordered item/cohort receipts·expected/published/failure group set; 마지막 저장 | 모두 성공이면 S2_40 TO_S2_40; 실패면 STOP_TECHNICAL_INCOMPLETE |
성공 저장 순서는 4 part wrapper → receipt-free manifest core → item receipts → cohort receipts → publish status LAST다. manifest에 receipt hash를 다시 포함하지 않아 `manifest↔receipt` 순환을 피한다. 동일 path·동일 bytes는 idempotent로, 다르면 immutable conflict로 처리하는 계약이며 physical atomicity는 host CAS와 실제 backend 증거가 필요하다. ([workflow L300–390](Default_Agent/Stage_2_Clean/workflows/S2_30_claim_group_draft_map.yml), [SOW §7](S2_30_SOW.md))
## 6. 고정 assets와 배포 경로
### 6.1 실행·prompt·계약
| `R/` 기준 정확 경로 | 역할 / runtime 소비 구분 |
|---|---|
| `agent_scripts/Stage_2_S2_30.yml` | 현재 배포 실행본. `M/Stage_2_S2_30.yml` authoring projection |
| `workflows/S2_30_claim_group_draft_map.yml` | 선언형 IO·native-adapter·barrier 계약. 별도 executable Agent로 호출하지 않음 |
| `prompts/P00_system_and_safety_contract.md`, `prompts/P30_joint_drafting_contract.md` | static literal의 authoring/review source. YAML prompt는 inline이므로 runtime 외부 prompt read 0 |
| `schemas/draft_atoms.schema.json` | dispatch/materialized/raw/canonical/part/receipt/status schema |
| `schemas/relief_plan.schema.json`, `schemas/context.schema.json`, `schemas/s2_10.schema.json` | source_kind별 selected-value 및 상류 schema |
| `schemas/deployment.schema.json` | binding/receipt/embedded-helper 계약; release/build/외부 adapter용 |
| `registry/cache/prompt_cache_policy.yml` | shared cache 정책. inline planner의 실제 tuple과 비교 필요 |
| `deployment/stage2_s2_30_llm_binding.yml` | model/prompt/planner/native adapter와 producer digest |
| `deployment/stage2_code_executor_binding.yml`, `manifest/stage2_deterministic_admission_receipt.json` | S2_30 전체를 deterministic으로 분류하지 않고 embedded planner execution unit만 shared admission에 결속. planner 자체가 이 두 파일을 고정 read하는 코드는 없음 |
| `manifest/s2_30_release.json`, `manifest/s2_30_parent_member_paths.json` | child seal / parent-independent source allowlist |
| `manifest/s2_30_inline_prompt_projection_receipt.json`, `manifest/s2_30_inline_code_receipt.json`, `manifest/s2_30_agent_receipt.json` | projection/parity/task/DAG/release 증적 |
| `manifest/s2_30_platform_adapter_receipt.json`, `manifest/s2_30_model_benchmark_receipt.json`, `manifest/s2_30_legal_review_receipt.json` | live/model/legal admission 증적; 현재 PENDING |
| `manifest/stage2_release.json`, `manifest/module_manifest.json` | 공유 release 신뢰 anchor |
### 6.2 Python 및 `.txt` 물리 파일
| 정확한 `R/` 상대 파일 pair | 역할 |
|---|---|
| `runtime/s2_30_dispatch_planner.py` / `runtime/s2_30_dispatch_planner.txt` | inline planner의 byte parity mirror; runtime import 아님 |
| `offline_build/build_s2_30_agent_projection.py` / `offline_build/build_s2_30_agent_projection.txt` | authoring→Agent/planner/prompt/binding/receipt/child projection·reseal |
| `offline_build/validate_s2_30_contract.py` / `offline_build/validate_s2_30_contract.txt` | native result adapter의 offline 검증·ID rewrite·write/retry 판정 oracle. live handler로 자동 배포되지 않음 |
| `tests/s2_30/test_agent_contract.py` / `tests/s2_30/test_agent_contract.txt` | Agent/DAG/parity 검사 |
| `tests/s2_30/test_dispatch_materialization.py` / `tests/s2_30/test_dispatch_materialization.txt` | dispatch/materialization/mode/owner 검사 |
| `tests/s2_30/test_draft_atom_contract.py` / `tests/s2_30/test_draft_atom_contract.txt` | atom/provenance/coverage/adverse 검사 |
| `tests/s2_30/test_prompt_cache_and_boundaries.py` / `tests/s2_30/test_prompt_cache_and_boundaries.txt` | P00/P30 cache prefix/data 경계 검사 |
| `tests/s2_30/test_release_adapter_retry.py` / `tests/s2_30/test_release_adapter_retry.txt` | release/native adapter/retry/barrier oracle 검사 |
shared reseal에는 `offline_build/build_release_manifests.py/.txt`, `release_ops/release_validator.py/.txt`, 앞 단계 projection builders가 관계되지만 사건별 LLM runtime이 이들을 실행하지 않는다. source `.py`와 `.txt`는 각각 별도 물리 파일이고 executable code의 정본은 YAML inline scalar다.
전용 fixture는 `R/tests/fixtures/s2_30/`에 `owner_singleton_dispatch.json`, `follower_batch_dispatch.json`, `valid_joint_draft_output.json`, `invalid_forbidden_output.json`, `invalid_reference_output.json`, `invalid_preassembled_prompt_item.json`, `cache_prefix_drift.json`, `counter_performance_and_declaration.json`, `adverse_fact_worknote_policy.json`, `rule_requirement_admission_gap.json`, `context_reference_envelope.json`, `technical_failure.json`, `partial_write_publish_barrier.json`, `regression_manifest.json`의 14개다. 공유 `R/tests/fixtures/regression_manifest.json`이 상위 closure다. 과거 assets 문서의 신규 44/공유 44 수량은 생성 작업 범위이고 현재 runtime 필수 read 파일 수가 아니다. ([assets §1](S2_30_assets.md))
## 7. upstream/downstream 연결 이유와 실패 분기
S2_20→S2_30 연결은 **무엇을 청구할지의 확정**과 **어떻게 함께 표현할지의 작성**을 분리한다. plan barrier가 전체 계획의 소비를 허가하고, P31이 exact drafting rule·요건사실 pack을, P32가 공통 authority를, S30가 실제 사건자료·관련 S2_10 판단을 전달한다. normalized fact/evidence refs는 Stage 1 raw 파일을 다시 탐색하지 않고 S2_00의 정규화·출처 보존을 재사용하기 위해 존재한다.
S2_30→S2_40 연결은 문안 후보를 검증 가능한 typed atom으로 전달하기 위한 것이다. native adapter가 raw→permanent ID/immutable wrapper로 변환한 뒤 manifest와 publish barrier를 발행해야 S2_40이 exact group×4 part를 읽을 수 있다. YAML `OUT` 도달만으로 이 manifest/barrier가 생성되거나 최종 package가 완성되는 것은 아니다.
| 상황 | 현재 경계 / 결과 |
|---|---|
| try 안의 identity, parent/hash/schema/source/batch 오류 | planner stderr JSON `{code,detail}`, exit 2. 빈 dynamic_fanout 성공을 반환하지 않음. finally close 예외는 이 봉투 바깥(§8.10) |
| STRUCTURAL_FIXTURE | `require_admission`에서 model call 금지; 합성 원자 자료를 live LLM에 보내지 않음 |
| SUBSET_CANARY | admitted platform receipt + exact signed canary authorization + source/mode gates 필요 |
| PRODUCTION | platform/model/legal exact admitted receipt + mode source gates 필요 |
| cache owner/follower 오류 | owner singleton cardinality/receipt/hash/P32 tuple 조건에서 planner 실패 |
| raw output 불량 | 외부 adapter가 reject, 실패 group만 추가 1회 retry; 2차 실패 terminal |
| 모든 group 불변저장/read-back 완료 | 외부 coordinator의 publish barrier 후 S2_40 |
mode gate와 receipt 검사는 외부 신뢰 증거를 소비하는 작업이다. planner는 독립 암호키 검증 엔진이 아니라 trusted-platform attestation status·scope/digest·issuer·기간을 검사한다. S2_30 metadata의 10개 native capability와 offline oracle 존재만으로 실제 AgentBackend implementation을 증명할 수 없다. (Y:L627–714, L943–1032, L1406–1448)
## 8. 현재 코드와 설계·상류/하류 계약의 확인된 차이
아래는 static source를 대조한 분석 finding이며 실행 코드를 변경한 결과가 아니다. 특히 “offline 구현 완료” metadata와 “live 경로 전체가 현재 일치한다”를 구분해야 한다.
1. **producer-contract digest 불일치.** Y:L95의 상수는 `337fd978acb335e89ef3ee859bf2333403858b370cbc5466d601317ba027fe4a`인데 실제 [binding](Default_Agent/Stage_2_Clean/deployment/stage2_s2_30_llm_binding.yml)의 `producer_contract.s2_30_producer_contract_digest`는 `b0d7e781e8a59ebd9e9ed8db6d04973640b2a127440f32b7bff605103cbc23e0`이다. batch가 binding의 값을 따르면 Y:L773에서 `PRODUCER_CONTRACT_DIGEST_MISMATCH`로 중단한다. hash 봉인 자체와 의미 상수 동기화는 다른 검증축이다.
2. **normalized fact/evidence JSON Pointer 충돌.** SOW §3.3은 case_context `/facts/*`, evidence_inventory `/items/*` 선택을 설명하지만 Y:L1107은 모든 직접 source의 pointer를 빈 문자열로 강제한다. 그런데 해당 source kind의 schema는 전체 context가 아닌 `fact_context_row`/`evidence_row`다. 정상 root 문서에서 row를 선택하려는 ref는 pointer 조건으로 거부되고 root를 row schema로 검사하는 것도 맞지 않는다. (Y:L1075–1087, L1090–1108)
3. **owner singleton과 전체 barrier group equality 충돌.** owner phase는 item 1개를 요구하는데 `materialize` 마지막 Y:L1398–1400은 barrier의 전체 `group_ids`와 현재 item group list를 동일하게 요구한다. barrier가 복수 group을 가진 정상 run이면 owner batch가 이 검사를 통과할 수 없다. follower/retry subset도 전체 집합 equality와 별도 조정이 필요하다. “owner-first multi-group 실행이 현재 완전히 연결됨”이라고 볼 수 없다. (Y:L843–848, L1398–1400)
4. **S2_40과 P31/S30 hash 단위 차이.** S2_30 planner의 P31/S30 echo는 새로 materialize한 JSON 문자열 hash다(Y:L1335–1382). S2_40은 nonfixture에서 group slice 원파일 hash를 S30 echo와, `rule_context_pack_ref` 원파일 hash를 P31 echo와 비교한다([S2_40 YAML L1580–1593](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml)). 현 정의대로라면 wrapper/materialized payload와 원파일이 다르므로 정상 raw-hash 전달을 그대로 성공으로 볼 수 없다. transport materialization hash와 frozen-source raw hash를 별도 필드로 해석할 필요가 있다.
5. **확장 native capability contract의 drift.** [workflow L300–315](Default_Agent/Stage_2_Clean/workflows/S2_30_claim_group_draft_map.yml)는 `S2_30_TYPED_PART_WRAPPER_PERSIST_V1`, `S2_30_RECEIPT_FREE_PART_MANIFEST_CORE_V1`, `S2_30_ORDERED_RECEIPT_INDEX_V1`까지 13개 capability를 요구한다. 배포 YAML L98–109와 binding은 기존 10개만 열거한다. planner는 그 10개 exact list를 검사하므로 후단 manifest/part-wrapper 추가 capability의 live admission까지 확인하는 것은 아니다.
6. **cache contract의 직접 material 차이.** SOW §4는 renderer/rule/Markdown/corpus/schema/producer까지 포함한 ordered tuple을 설명하지만 `verify_cache_owner_receipt`의 실제 cohort material에는 P31/rule/corpus/schema/producer가 독립 field로 없고 parent/child/Agent/binding 등을 통해 일부 전이 결속된다. 정확한 cache cohort를 설명할 때 직접 tuple과 전이 결속을 구분해야 한다. (Y:L891–906)
7. **duplicate lane 구분 및 schema 경로를 주의해야 한다.** `load_one`의 seen key는 path/pointer/schema이고 저장 비교는 ref object뿐이다. lane/transitive 값은 key가 아니어서 동일 ref가 다른 lane에 다시 등장하면 처음만 남는다. 또한 직접 source 계약의 짧은 `schemas/...` ref는 `validate_selected`가 `Default_Agent/Stage_2_Clean/`를 자동 접두하지 않는다. 올바른 materialization에는 이러한 실제 path·lane 의미가 맞는 배포/dispatch가 필요하다. (Y:L528–539, L1235–1239)
8. **에러·저장 책임은 외부에 있다.** SOW overview의 “stdout closed stop result”와 달리 실제 planner 실패는 stderr JSON+exit 2다. retry/immutable writer/manifest/상태 barrier 구현은 이 YAML 안에 없고 binding handler도 null이다. 별도 offline validator의 `adapt_model_output`, `evaluate_immutable_write`, `evaluate_retry`, `validate_handoff_chain`은 검증 oracle이며 실행 native adapter 그 자체가 아니다. (Y:L1437–1448; [validator](Default_Agent/Stage_2_Clean/offline_build/validate_s2_30_contract.py))
9. **group-local context 격리는 완전하지 않다.** CANONICAL_RELIEF_PLAN은 root pointer로 읽으며 현재 S2_20 생산 plan에는 전체 claim_groups/option_dispositions가 있다. Y:L1252–1258, L1272–1284는 이를 S30 sources에 통째로 넣고 L1328–1334는 그 전체에서 추출한 refs도 derived 집합에 합친다. L1246의 embedded group check는 최상위 claim_group_id가 있는 경우에만 적용된다. 따라서 다른 group 정보·ID가 포함될 수 있으며 P30의 현재 group 한정 지시와 planner의 실제 자료 범위를 구별해야 한다. group-local 축약·검증이 다른 곳에서 완성되었다는 증거는 이번 분석에서 확인하지 않았다.
10. **session close 예외는 closed error 처리 밖이다.** L1431에서 fanout을 stdout으로 출력한 뒤 finally의 client.close(L1445–1448)가 실패하면 이미 fanout이 출력된 상태에서 비정형 traceback/nonzero 종료가 가능하다. host는 stdout에 dynamic_fanout이 있다는 것만으로 planner 성공을 판정하면 안 된다. §7의 stderr JSON+exit2는 try/catch가 처리한 오류에 한정된다.
11. **상류 zero-group 완료 경로와 nonempty dispatch 요구가 다르다.** S2_20은 모든 option이 excluded/deferred이면 group 0개에서도 PLAN_COMPLETE/TO_S2_30를 낼 수 있지만, 본 planner의 `validate_batch`는 items의 nonempty list를 요구한다(Y:L840–842). 현 YAML에는 빈 group run을 성공적으로 건너뛰어 S2_40에 연결하는 branch가 없다. 이 경로는 외부 설계가 해결했다고 추정하지 않고 연결상 미결로 남긴다.
## 9. 함수 및 내부 책임 색인
| 책임 | 실제 함수/클래스 시작행 |
|---|---|
| error / parse | `PlannerError` 121 (`__init__` 122), `reject_duplicates` 128, `parse_one` 137, `parse_read_docs_envelope` 156 |
| canonical/hash/path | `canonical_bytes` 195, `digest` 202, `require_hex` 207, `safe_path` 213 |
| MCP client | `mcp_payload` 222, `LocalDocs` 253 (`__init__`254, `close`263, `post`266, `initialize`277, `read_text`294) |
| pointer/schema | `resolve_pointer`330, `schema_pointer`347, `type_matches`355, `parse_rfc3339`367, `validate_schema_node`381, `validate_selected`521 |
| exact reads | `read_ref`542, `read_hashed_untyped`570, `read_fixed_json`579 |
| release / admission | `verify_top_level_digest`587, `sealed_asset_index`595, `assert_sealed_actual`610, `verify_signed_attestation`627, `verify_external_receipt`655, `verify_fixed_contract`717 |
| batch / cache / mode | `validate_batch`818, `verify_cache_owner_receipt`856, `require_admission`943 |
| source materialization | `normalize_ref`1035, `validate_source_contract`1090, `canonical_run_path`1111, `ref_strings`1121, `materialize`1141 (nested `load_one`) |
| outer inline sequence | `run`1406 → `__main__`1452 |
| LLM task | `Task_S2_30_draft_group_*`1455; P00/P30/P32/P31/S30 prompt blocks 1467–1831; task_procedure 1833–1851 |
## 10. 검증 범위
배포 YAML 전행·현재 SHA/줄수, 함수·path 및 실제 workflow/binding/receipts를 직접 확인했다. 본 분석서는 구현 설명과 설계상의 외부 책임을 분리하고 §8의 모순을 숨기지 않는다. LLM 추론의 정확성, provider cache 효율, live platform admission, 137종 법률 content의 승인 및 Stage 1→S2_40 E2E 성공을 새로 검증하거나 주장하지 않는다.
| 회차 | 검증자·범위 | 발견사항 및 증분 수정 |
|---|---|---|
| 1차 | 독립 analysis20: YAML 1–1851 전문·분석서 전문·binding/schema 및 20/40 인계 대조 | 전체 canonical plan의 타 group 자료/참조 포함, finally close 예외의 closed error 바깥 경계 추가. main agent 반영 |
| 2차 | main agent: 수정본 전문, batch/source 정규화·materialization·prompt/LLM 설정·producer digest·40 hash 소비 및 20 empty-group 생산 대조 | 1차 group-local/close 경계 반영 확인. planner parameter·ref 기본값 설명 및 zero-group 상류→nonempty dispatch 불일치 추가 |
검증-수정은 총 2회로 종료했다. 실행자산·release·model 설정은 변경하지 않았다. 문서에서 드러낸 인계계약 오류와 live 승인 미결이 해소되었다는 의미는 아니다.
@@ -0,0 +1,340 @@
# Stage 2_40 작업분석서
## 1. 분석 대상과 결론
S2_40은 S2_30의 청구취지·청구원인 작성 결과를 모아 고정 규칙으로 검증·조립하고, 검토용 후보를 동결한 다음 외부 검토와 배포 승인 조건을 확인하여 최종 package를 저장하는 **단일 deterministic finalizer**다. LLM 법률판단·새 청구권 식별·문장 재작성은 수행하지 않는다. 상류의 모든 단계와 연결되지만 주 경로는 S2_30 완료 barrier에서, 진단 전용 경로는 S2_00의 `TO_S2_40_STATUS_ONLY`에서 시작한다.
분석 기준일은 2026-09-09다. 배포 YAML **1–3,575행 전체**를 연속 구간으로 읽고, 선언형 workflow·SOW·assets 및 관련 배포 자산을 대조했다. 실행 사실과 설계상의 요구사항을 구분한다. 이번 분석은 live MCP 실행·법률적 타당성 인증·전체 테스트 재실행이 아니다. 과거 MEMORY의 240 PASS는 과거 구현 기록이다.
| 항목 | 확인 내용 |
|---|---|
| 직접 분석한 실행본 | [Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml](Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml) |
| 줄수 / SHA-256 | 3,575행 / `5cbe2ac9aa73d95a5fa4e6cf71d7d8f0ad83aa05536f573c13e42505ef5d46f7` |
| Agent / version | `Stage_2_S2_40` / `1.0.0` |
| 실제 Stage / task | `S2_40` / `Task_S2_40_deterministic_finalizer` 각각 1개 |
| 실행 방식 | `code-executor.run_code`; Python; `httpx==0.28.1`; `agent-network`; 300초 |
| 고정 parent raw SHA-256 | `9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53` |
| 상태 선언 | `IMPLEMENTED_OFFLINE_VERIFIED_LIVE_AND_LEGAL_ADMISSION_PENDING` |
| 근거 locator | 배포 YAML L1–142, L3484–3575 |
이하 모든 `Y:L숫자`는 위 배포 YAML의 실제 행을 뜻한다. `M`은 이 분석서가 저장된 `Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/`, `R`은 `M/Default_Agent/Stage_2_Clean/`이다. runtime의 Localdocs 논리경로 `Default_Agent/Stage_2_Clean/`와 로컬 저장소의 `R`을 구분한다. 사건별 root는 `O = stage2_runs/by-binding/<run_binding_digest>/`, 후보 root는 `C = O/candidates/by-content-digest/<candidate_content_digest>/`다. 이 동적 경로는 고정 자산 파일이 아니다.
## 2. 전체 DAG와 실행 단위
```text
AgentBackend / outer orchestrator
identity 치환 + request 작성 + host CAS lease + detached admission
|
v
IN -> Task_S2_40_deterministic_finalizer [단 1회 run_code] -> OUT
|
+-- strict request + release/Agent/binding/receipt preflight
| 실패: stdout error receipt, run-root write 없음
|
+-- TO_S2_40_STATUS_ONLY + FREEZE
| S2_00 진단 파일 exact 5개 + output barrier 4개 대조
| -> run_status LAST: DIAGNOSTIC_ONLY / STOP_TECHNICAL_INCOMPLETE
|
+-- TO_S2_40
|
+-- FREEZE
| S2_00/S2_10/S2_20/S2_30 barrier·manifest 검증
| -> 상류 exact artifact hydrate
| -> C40 reduce: atom/issue/assumption/worknote/usage
| -> C45 renderer·typed slot 전개 + 재전개 바이트 비교
| -> C46 V01~V18 + 3축 상태 + 법률자산 gate
| -> C47 candidate digest -> C/ immutable 저장
| -> receipt type별 review request 0/N개
|
+-- RESUME
이전 WAIT run_status + C/ 파일 + review request
-> source-preimage/candidate/review digest 완전 재계산
-> 상류 재검색·재작성 없이 frozen candidate 재사용
|
v
외부 review receipt canonical/schema/scope/trust 검사
|
+-- 유효 CONTENT_CHANGE_REQUIRED -> SUPERSEDED
| -> earliest owner S2_00/10/20/30 재시작 route
+-- 승인/PRODUCTION/V18개/gates 미충족 -> WAIT
+-- 모두 충족 -> C48 commit_intent
-> final/ exact bytes + read-back
-> commit_result + read-back
-> COMMITTED
|
v
immutable status_event -> control/run_status.json LAST
|
v
stdout execution receipt JSON 1개
[outer receipt 저장은 외부 adapter]
preflight 이후 예외 -> diagnostic/failure-<digest>.json
-> status_event -> run_status LAST -> stdout 오류 receipt
```
실제 YAML의 `prevs: []`, `nexts: []`는 이 Agent 문서 내부에 다른 Stage가 없다는 뜻이다. S2_00/S2_30으로부터의 호출은 YAML 내부 DAG edge가 아니라 request·상류 barrier·outer orchestrator 계약으로 연결된다. `task_procedure`는 `IN → Task_S2_40_deterministic_finalizer → OUT`이며 C40/C45/C46/C47/C48은 별도 Agent task나 Python 모듈 호출이 아니다. 실제 코드에서는 `reduce_and_render`가 C40과 C45를 한 함수에 결합한다. 선언형 workflow의 component 명칭과 실행 함수의 1:1 대응을 가정하면 안 된다. (Y:L15–43, L1838, L3444–3456, L3562–3575; [workflow](Default_Agent/Stage_2_Clean/workflows/S2_40_final_review_render_and_commit.yml))
## 3. 입력 파일과 연결 계약
### 3.1 호출·기술 신뢰 입력
| 입력 경로 / 형식 | 작성·관리 주체 | S2_40 사용 목적 / 소비 함수 |
|---|---|---|
| `stage2_control/s2_40_request.json` / JSON | outer orchestrator | closed 27-key request. run/identity/route/mode/transition·상류 및 배포 hash·CAS·review receipt refs를 지정. `validate_request` |
| `stage2_control/host_cas/<run_binding_digest>/S2_40/<candidate_attempt_id>/<FREEZE 또는 RESUME>.json` / JSON | host CAS owner | 같은 run·attempt·transition·previous-status에 대한 `ACQUIRED` lease, 유효시간·attestation을 확인. `preflight` |
| request의 `detached_admission_receipt_ref` / JSON; 통상 `Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json` | release/platform owner | parent/executor/stage receipt·signed payload·backend capability 결속. path는 request 지정이며 코드가 통상 경로 한 개로 강제하지 않음 |
| `R/manifest/stage2_release.json`, `R/manifest/module_manifest.json` / JSON | release builder | 고정 parent raw hash, self digest, module membership의 시작점 |
| `R/agent_scripts/Stage_2_S2_40.yml` / YAML, `R/deployment/stage2_code_executor_binding.yml` / YAML, `R/manifest/s2_40_inline_code_receipt.json` / JSON | projection/release builder | 실행 Agent와 receipt·binding의 exact raw hash 및 parent 결속 |
request의 `stage2_run_root_ref`는 임의 폴더가 아니라 run digest에서 도출되는 `O`와 같아야 한다. normal FREEZE는 candidate digest·previous status·review receipt를 받지 않으며, RESUME는 candidate digest와 previous-status hash가 필수다. status-only는 `compile_mode=null`, FREEZE, S2_10/20/30 hash null, review refs 빈 배열이다. review refs는 최대 64개·중복 금지다. preflight에서 mode가 PRODUCTION이면 production admission, 그 외는 canary 또는 production admission을 요구한다. 따라서 status-only도 무승인 실행 우회로가 아니다. (Y:L458–539, L743–837)
외부 `review_receipt_refs[]`는 request가 지정한 exact safe relative path를 읽으며 특정 `O/review/receipts/` 폴더나 `.json` suffix로 강제하지 않는다. 파일의 내용·schema·candidate/subject·서명 attestation을 검증한다. 반면 S2_40 자신이 생성하는 review request는 §4.2의 고정 family다.
### 3.2 normal FREEZE: 상류 단계별 파일
다음은 모두 `O/` 상대경로의 JSON이다. `cluster_id`, `claim_group_id`는 앞 단계에서 동결된 ID이며 scan/glob로 발견하지 않는다.
| 생산자 | 입력 경로 / family | 필수 연결과 사용 |
|---|---|---|
| S2_00 | `ingress/ingress_status.json` | request raw hash와 비교. NORMAL barrier, run/input/parent, executable cluster 집합을 제공 |
| S2_00 | `ingress/stage1_input_manifest.json`, `ingress/intake_report.json` | ingress barrier가 명시한 input snapshot·intake 자료 |
| S2_00 | `context/case_context.json`, `context/evidence_inventory.json`, `context/object_registry.json`, `context/party_and_title_context.json`, `context/slot_crosswalk.json` | 사실·증거·객체·당사자/권원·slot 연결; exact path/schema/hash를 다시 확인 |
| S2_00 | `context/cluster_plan.json`, `context/bundle_plan.json`, `context/cluster_slices/<cluster_id>.json` | executable cluster 및 cohort/dependency-wave/slice 집합. S2_10 verdict 누락·다른 slice 소비 여부 검사 |
| S2_00 | `review/issue_ledger.base.json` | 전체 issue 원집합. S2_20의 `preserved_base_issue_ids` 및 base hash와 대조 |
| S2_10 native result adapter | `map_s2_10/s2_10_publish_status.json` | COMPLETE/TO_S2_20/status-last 및 terminal wave receipt 집합 |
| S2_10 native result adapter | `map_s2_10/domain_verdicts/<cluster_id>.json`, `item_receipts/<cluster_id>.json`, `issue_patches/<cluster_id>.json`, `assumption_parts/<cluster_id>.json`, `usage_parts/<cluster_id>.json` (뒤 4개도 `map_s2_10/` 아래) | verdict/self-hash와 item·sidecar link, cluster/slice/wave/attempt/producer 계약 확인; issue·assumption·usage를 최종 보존 |
| S2_10 native result adapter | `map_s2_10/wave_receipts/wave-<ordinal:04d>.json` | wave 순번은 0부터 연속. 각 WAVE_COMPLETE, 마지막 TO_S2_20, expected/valid cluster exact set |
| S2_20 | `plan/plan_publish_status.json` | request·S2_10 barrier hash와 연결. `consumer_authorized=true`, TO_S2_30, non-TECHNICAL_INCOMPLETE. 전체 `artifact_rows`를 순서·중복·set digest로 확인 |
| S2_20 | `plan_publish_status.artifact_rows[].path`가 열거한 모든 JSON | `read_plan_artifacts`가 각 raw hash/byte size/schema를 검증. canonical plan, group slice, issue ledger, exhibit 및 pack/receipt 등이 이에 포함됨 |
| S2_20 | `plan/canonical_relief_plan.json`, `plan/issue_ledger.plan.json`, `plan/exhibit_register.json`, `plan/group_slices/<claim_group_id>.json` | 코드가 직접 lookup하는 필수 핵심 파일. atom의 claim/option/group/source-plan 연결, base issue 보존, 호증, renderer/rule/calculation refs를 제공 |
| S2_30 native result adapter | `map_s2_30/s2_30_publish_status.json`, `map_s2_30/artifact_manifest.json` | S2_30_COMPLETE/TO_S2_40/status-last. expected/published group과 S2_20 group set 일치, terminal failure 빈 배열, manifest raw hash/self hash |
| S2_30 native result adapter | `map_s2_30/draft_parts/<claim_group_id>.json`, `issue_patches/<claim_group_id>.json`, `usage_parts/<claim_group_id>.json`, `worknote_parts/<claim_group_id>.json` (모두 `map_s2_30/` 아래) | manifest에 정확히 group×4 family. atom과 issue/usage/worknote 분리 입력; 각 part self-hash·raw hash·schema·group provenance 일치 |
| S2_30 native result adapter | `s2_30_publish_status.ordered_item_receipts[].path`, `.ordered_cohort_receipts[].path` | barrier가 명시한 exact path만 읽는다. receipt self-hash·manifest-core·common/group provenance와 item의 group 집합을 대조 |
S2_00 normal non-status 입력은 **10개 고정 파일 + executable cluster별 slice**다. `ingress_status` 자체는 이 10개 바깥의 barrier다. S2_10은 cluster별 5개 + wave별 1개 + global barrier다. S2_30의 네 part family는 group별 정확히 하나이고 item/cohort receipt는 별도다. S2_10/20/30 technical failure를 S2_40 status-only로 임의 전환하지 않는다. (Y:L924–990, L1086–1276, L1297–1700)
S2_30 common provenance는 compile mode, parent, S2_30 child/Agent/binding, P00/P30, producer-contract digest를 묶고 group provenance는 P31/P32/S30 hash까지 더한다. non-STRUCTURAL_FIXTURE에서는 S2_20 group-slice raw hash와 S30 echo, rule-pack raw hash와 P31 echo를 대조한다. fixture mode에만 이 두 echo equality 예외가 있다. 코드가 검증하는 것은 provenance 객체·hash의 연결이며, S2_30의 법률판단을 새로 수행하지 않는다. (Y:L124–142, L1279–1295, L1519–1606)
### 3.3 S2_20 frozen refs로 선택되는 추가 입력
| ref 출발점 | 해석 경로 / 형식 | 쓰임 |
|---|---|---|
| group slice `rule_context_pack_ref` | `plan/` artifact row에 있으면 그 frozen bytes; 아니면 `R/` 아래 exact path / JSON | 해당 group의 binding rows, renderer, structured rule, review policy 등 |
| rule pack `renderer_refs[]` | 위와 동일; `R/renderers/*.yml`도 코드에서는 JSON object로 읽음 | renderer ID·branch·literal/slot 전개 |
| rule pack `structured_relief_rule_refs[]`, `review_policy_refs[]`, `ce13_branch_refs[]` | manifest-bound plan ref 또는 `R/` exact path / JSON 호환 YAML 또는 JSON | legal gate·review policy·frozen source snapshot |
| group slice `calculation_receipt_refs[]` | frozen plan ref 또는 `R/` exact path / JSON | receipt ID·operand digest·missing law value·계산상태 대조. S2_40은 계산을 재실행하지 않음 |
| plan artifacts 중 `schema_version=stage2_requirement_fact_pack.v1` | barrier가 열거한 JSON | corpus release·slot crosswalk·injection isolation 및 legal gate |
| `R/manifest/authority_release.json`, `case_type_coverage.json`, `case_type_registry.yml`, `case_type_rule_registry.yml` | release-member raw hash/size를 확인한 JSON object | authority 승인 및 CT-001∼137/CAT-001∼137의 full-release 조건 |
`resolve_frozen_ref`는 상대경로에 `plan/`를 붙여 plan row 존재 여부를 먼저 확인하고, 없으면 `ASSET_ROOT`로 해석한다. 이미 `Default_Agent/Stage_2_Clean/`로 시작하면 그대로 쓴다. code는 모든 이런 `.yml`을 YAML parser로 해석하지 않고 `load_json`으로 읽으므로 해당 자산은 **JSON 문법으로 저장된 YAML 호환 파일**이어야 한다. 상류 pack의 raw hash가 주 검증축이며 추가 frozen ref를 읽을 때마다 module membership를 직접 재확인하는 함수는 아니다. (Y:L553–587, L1378–1396, L1565–1628)
### 3.4 status-only / RESUME 전용 입력
| 분기 | 입력 | 처리 |
|---|---|---|
| status-only | `O/ingress/ingress_status.json`, `O/ingress/technical_diagnostic.json`, `O/ingress/stage1_input_manifest.json`, `O/ingress/intake_report.json`, `O/review/issue_ledger.base.json` | 사건 입력 exact 5개. status 내 barrier에는 나머지 4개 exact set. run/input/producer/reason conservation 재검증. schemas·release·CAS 등의 고정/통제 입력은 별도이므로 전체 read 횟수가 5회라는 뜻은 아님 |
| RESUME | `O/control/run_status.json`, `C/candidate_package_manifest.json`, `C/candidate_content_digest.json`, manifest의 모든 candidate artifact, 보조 validation/worknote/packet/subject JSON | 이전 phase가 AWAITING_EXTERNAL_REVIEW여야 함. run/attempt/mode/parent/upstream hashes 동일, canonical bytes, 크기/hash, schema, 후보 digest 전체 재계산 |
| RESUME | `O/review/review_requests/<request_id>.json`, request `review_receipt_refs[]`의 exact path | frozen review subject에서 request ID/core를 다시 도출. 외부 receipt만 새로 검증하며 상류를 재조회·재render하지 않음 |
## 4. 출력 파일과 생산·소비 관계
### 4.1 FREEZE candidate
아래 고정 basename은 `C/` 아래 immutable 파일이다. JSON은 UTF-8, key sort, compact separators, LF 종결의 canonical JSON이고 Markdown은 NFC/LF 및 단일 종결 LF로 정규화한다. 작성 직후 read-back한다. (Y:L187–205, L422–437, L2575–2893)
| 후보 파일 / 형식 | 생산 내용 | 소비자 / 목적 |
|---|---|---|
| `issue_ledger.final.json` / JSON | S2_00 base + S2_20 plan issues + S2_10 issues + S2_30 flags/missing/adverse rows | 변호사·RESUME·최종 package; 보존 hash |
| `assumption_ledger.json` / JSON | S2_10 가정과 출처·scope | 검토자·RESUME |
| `llm_usage_projection.json` / JSON | S2_10/S2_30 usage part별 source stage/scope/hash/payload | telemetry·감사; **JSONL이 아님** |
| `attorney_worknotes.core.json`, `attorney_worknotes.json` / JSON | 전자는 digest 이전 worknote core, 후자는 candidate digest를 포함한 envelope | 후보 봉인·검토 |
| `render_diagnostic.json` / JSON | render error/absence 및 재render equality | 검토·진단 |
| `review_policy_core.json`, `review_request_basis.json` / JSON | 승인 policy·trigger·required receipt type·scope/finding/role/release 기반 | review subject 및 RESUME request 재도출 |
| `upstream_dependency_snapshot.json`, `ordered_source_snapshot_preimage.json`, `frozen_source_rows.json` / JSON | parent/barrier hash, 순서 있는 전체 source hash preimage, frozen source ref/hash 목록 | 재현성·RESUME digest 재계산 |
| `legal_gate_snapshot.json` / JSON | 10개 legal readiness gate | 같은 후보의 RESUME/final readiness |
| `claim_relief.md`, `claim_cause.md`, `pleading_draft.md` / Markdown | approved renderer·완전한 render + mode가 SUBSET_CANARY/PRODUCTION일 때만 생성 | 변호사 검토 및 최종 조립. STRUCTURAL_FIXTURE에서는 미생성 |
| `candidate_package_manifest.json`, `candidate_content_digest.json` / JSON | 전자는 pre-review artifacts/dep snapshot, 후자는 manifest/문서/ledger/validation/source digest의 비순환 envelope | 내용주소 후보 ID·RESUME 검증 |
| `validation_core.json`, `validation_envelope.json` / JSON | V01∼V18·기술상태 및 review subject 연결 | 검토자·final status |
| `lawyer_review_packet.json`, `review_subject.json` / JSON | 검토 문서/finding/scope와 request-core binding | 외부 reviewer 및 receipt 검증 |
후보는 기본 JSON 18개, clean render 허용 시 Markdown 3개를 더한다. `candidate_package_manifest.artifacts`가 나열하는 것은 이 중 **pre-review JSON 11개와 조건부 Markdown 3개**다. manifest/digest/envelope 등 모든 후보 파일을 manifest에 넣는 방식은 순환 hash를 만들므로 보조 파일은 별도 digest chain으로 검증한다. `review_policy_result`는 이 시점의 메모리 객체이며 `C/review_policy_result.json`을 쓰지 않는다; 후보에는 `review_policy_core.json`이 저장된다. (Y:L2690–2741, L2845–2880)
### 4.2 후보 바깥 출력과 final commit
| 경로 / 형식 | 작성 조건·순서 | 소비 주체 |
|---|---|---|
| `O/review/review_requests/<RR40-id>.json` / JSON | policy receipt type별 0/N개. candidate·review subject 이후 immutable 기록 | 외부 자격 검토자 / RESUME |
| `O/commit/commit_intent.json` / JSON | production readiness 전부 충족 시, final write **전** expected artifact bytes/hash를 고정 | C48·감사 |
| `O/final/<basename>` / JSON/Markdown | 위 pre-review JSON 11개 및 Markdown 3개 + candidate manifest/digest, attorney_worknotes, lawyer_review_packet, `stage2_final_validation_report.json`, `review_policy_result.json`, `stage2_package.json` | 후속 filing/export validator·변호사 |
| `O/commit/stage2_commit_result.json` / JSON | final 파일 전부 write/read-back 후. intent hash·artifact set digest·실제 rows·conflict/missing=0 | 마지막 run_status 및 후속 소비자 |
| `O/control/status_events/<event_digest>.json` / JSON | normal WAIT/SUPERSEDED/COMMITTED 또는 post-preflight failure의 immutable transition event | 상태 이력. 자체로 final 소비 허가는 아님 |
| `O/control/run_status.json` / JSON | status-event/commit read-back 다음 마지막 write. 유일 latest/CAS 예외 | 후속 소비의 최종 barrier |
| `O/diagnostic/failure-<diagnostic_digest>.json` / JSON | preflight 성공 후 기술 예외 | 장애 조사. 이어 failure run_status 시도 |
| stdout / JSON | `run()`의 execution receipt 하나. success exit 0, exception exit 2 | outer adapter |
| `O/control/s2_40_outer_execution_receipt.json` / JSON | request에 target이 있으나 **inline은 직접 저장하지 않음** | outer adapter가 execution 결과를 저장해야 하는 외부 책임 |
final set은 조건이 충족된 정상 경로에서 JSON 18개 + Markdown 3개다. `stage2_package.artifacts`에는 자기 자신을 제외한 final files를 넣고, commit intent/result에는 `stage2_package.json`까지 포함하여 자기 hash 순환을 피한다. `validation_envelope.json`·`review_subject.json`은 candidate 쪽 파일이며 final로 복사되지 않는다. final package는 `filing_permission=NOT_GRANTED`, `filing_decision_receipt_sha256=null`을 명시한다. READY는 법원 제출 완료나 자동 제출 허가가 아니다. (Y:L3075–3180)
status-only는 candidate/final/status-event를 생성하지 않고 `run_status`만 쓴다. 여기의 `validation_report_sha256`에는 별도 validation-report 파일의 raw hash 대신 exact-five 검사 snapshot digest가 들어간다. 이 필드를 모든 route에서 동일한 report-file pointer로 해석하면 안 된다. (Y:L1059–1076)
## 5. 고정 실행 자산과 offline 자산
### 5.1 runtime 직접 읽는 고정 파일
| `R/` 기준 정확 배포 위치 | 역할 / 실제 읽기 |
|---|---|
| `agent_scripts/Stage_2_S2_40.yml` | 배포 실행본; AgentBackend가 실행하고 preflight도 raw hash 검증 |
| `manifest/stage2_release.json`, `manifest/module_manifest.json` | parent/module self digest와 exact member raw hash·size |
| `deployment/stage2_code_executor_binding.yml`, `manifest/s2_40_inline_code_receipt.json` | executor·Agent·parent·projection 결속. binding은 코드에서 full YAML schema parse 대신 필수 literal 포함 여부를 검사 |
| `schemas/ingress.schema.json`, `schemas/context.schema.json`, `schemas/domain_verdict.schema.json`, `schemas/s2_10.schema.json` | Stage 1 정규화→S2_10 입력과 verdict/sidecar/schema refs |
| `schemas/relief_plan.schema.json`, `schemas/binding_retrieval.schema.json`, `schemas/calculation.schema.json` | S2_20 plan·rule/corpus/calculation |
| `schemas/draft_atoms.schema.json` | S2_30 atom/part/manifest/barrier |
| `schemas/package.schema.json`, `schemas/review_status.schema.json`, `schemas/deployment.schema.json` | candidate/review/status/request·execution/commit 출력 |
| `manifest/authority_release.json`, `manifest/case_type_coverage.json`, `manifest/case_type_registry.yml`, `manifest/case_type_rule_registry.yml` | normal FREEZE의 release/legal eligibility; RESUME는 frozen legal snapshot 재사용 |
| `manifest/stage2_deterministic_admission_receipt.json` | 통상 request에 지정되는 detached admission. 파일 존재와 유효 승인 여부는 별개 |
schema 11개를 release-bound JSON store로 읽으며 자체 `schema_errors`는 필요한 JSON Schema keyword의 부분집합 구현이다. 범용 외부 JSON Schema 엔진을 import하지 않는다. schema self-description과 실제 지원 keyword를 구분해야 한다. (Y:L87–100, L631–740)
### 5.2 selected frozen ref로 읽는 자산 / 상류 전이 의존성
| `R/` 기준 경로 | 역할과 범위 |
|---|---|
| `renderers/R01_money_payment.yml`, `R02_delivery_possession.yml`, `R03_declaration_registry.yml`, `R04_special_nonmoney_performance.yml`, `R05_declaratory.yml`, `R06_constitutive_judgment_challenge.yml` | 모두 `renderers/` 아래. 전체 일괄 import가 아니라 pack이 지정한 renderer만 사용 |
| `registry/review/review_policy_registry.yml` | `registry_id=S2-20-REVIEW-POLICY`로 selected frozen assets에서 찾음. 승인 여부·base type·trigger·required receipt 계산 |
| `registry/drafting/case_type_relief_rules.yml` | structured relief-rule refs에 들어온 경우 사용; status/execution eligibility와 frozen hash |
| `registry/calculations/`, `law_values/`, `manifest/corpus_release.json`, `registry/drafting/forbidden_relief_rules.yml`, `counter_performance_rules.yml`, `procedural_declaration_rules.yml`, `routing/`, `validators/actio_value_compensation_invariants.yml` | SOW/assets에 제시된 관련 상류 자산이다. **S2_40 코드가 모두 직접 고정 read하는 목록은 아님**. 계산 receipt·plan pack·frozen refs·상류 검증을 통한 전이 의존성을 구분해야 함 |
| `rules/relief/<case_type_id>.md` | 법률가 승인용 원천 문서 family. S2_40이 137개 Markdown을 직접 scan/read하여 법률판단하지 않음 |
| `workflows/S2_40_final_review_render_and_commit.yml` | 배포 선언 계약. preflight는 module ID `WF-S2_40`의 canonical path membership를 확인하나 실행 code를 이 파일에서 읽어오지 않음 |
### 5.3 Python / `.txt` mirror / build·test 자산
아래 pair 표기의 `.py`와 `.txt`는 **서로 다른 두 물리 파일**이다. runtime task는 YAML scalar의 inline Python을 실행하며 아래 파일을 import하지 않는다.
| 정확한 `R/` 상대경로 | 역할 |
|---|---|
| `runtime/s2_40_commit.py`, `runtime/s2_40_commit.txt` | 전체 inline code mirror·parity 대상 |
| `runtime/c45_document_assembler.py`, `runtime/c45_document_assembler.txt` | 조립·reduce용 pure offline oracle; inline과 자동으로 같은 구현이라는 보장은 없음 |
| `runtime/rendering/closed_renderer.py`, `runtime/rendering/closed_renderer.txt` | closed renderer offline oracle |
| `runtime/validation/invariant_runner.py`, `runtime/validation/invariant_runner.txt` | V01∼V18 offline oracle |
| `offline_build/build_s2_40_inline_projection.py`, `offline_build/build_s2_40_inline_projection.txt` | authoring→배포 YAML/전체 mirror/inline receipt 추출·검증 |
| `offline_build/build_release_manifests.py`, `offline_build/build_release_manifests.txt` | cumulative module/parent 봉인 |
| `release_ops/release_validator.py`, `release_ops/release_validator.txt` | release closure 검증; 사건 runtime 아님 |
| `manifest/s2_40_parent_member_paths.json` | parent-independent source allowlist. parent hash를 내장한 Agent/full mirror/receipt를 parent closure에 넣어 순환시키지 않음 |
| `schemas/migration_regression.schema.json`, `registry/regression/finding_fixture_map.yml`, `tests/fixtures/regression_manifest.json` | 회귀시험 schema·finding/V-code·공유 fixture 봉인 |
| `tests/s2_40/test_agent_and_inline_parity.py`, `.txt` | Agent/inline/parity 계약 시험 |
| `tests/s2_40/test_c40_reduce_and_conservation.py`, `.txt` | part set·보존 시험 |
| `tests/s2_40/test_c45_closed_render.py`, `.txt` | closed render 시험 |
| `tests/s2_40/test_v01_v18.py`, `.txt` | invariant/state 시험 |
| `tests/s2_40/test_review_state_machine.py`, `.txt` | review freeze/resume/supersede 시험 |
| `tests/s2_40/test_commit_barrier_and_idempotence.py`, `.txt` | commit/read-back/idempotence 시험 |
| `tests/s2_40/test_release_closure.py`, `.txt` | 누적 release closure 시험 |
마지막 7행의 `.txt`는 각 행의 `.py` basename을 그대로 유지한 `tests/s2_40/<동일 basename>.txt`다. 전용 fixture 위치는 `R/tests/fixtures/s2_40/`이며 basename은 다음 16개다: `valid_full_candidate_and_commit.json`, `valid_status_only_diagnostic.json`, `part_set_missing_duplicate_or_cross_group.json`, `renderer_ast_slot_branch_mutations.json`, `relief_cause_crossmatch_mutations.json`, `v01_v18_invariant_matrix.json`, `cost_provisional_execution_numbering.json`, `exhibit_object_party_title_completeness.json`, `review_policy_state_aggregation.json`, `review_receipt_missing_or_invalid.json`, `review_receipt_approve_resume.json`, `review_receipt_content_change_supersede.json`, `partial_write_readback_barrier.json`, `same_binding_idempotence_and_commit_conflict.json`, `candidate_digest_noncycle.json`, `regression_manifest.json`. fixture 이름 자체가 live 기능 검증 완료의 증거는 아니다. ([assets §1](S2_40_assets.md), [offline assembler](Default_Agent/Stage_2_Clean/runtime/c45_document_assembler.py))
## 6. 소작업의 내용·목적과 V01∼V18 실제 의미
| component / 실제 함수 | 작업 내용 | 연결 이유 / 목적 | YAML locator |
|---|---|---|---|
| bootstrap / `run`, `validate_request`, `preflight` | identity 치환 확인·MCP initialize·request·parent/binding/admission/CAS 검증 | 현재 호출의 신뢰·저장 권한과 대상 run을 확정 | L477, L743, L3484 |
| input hydration / `hydrate_normal` | 상류 barrier와 모든 지정 artifact/schema/hash/provenance 수집 | 완료하지 않은 producer·부분 output·다른 run 혼입 거부 | L1399–1698 |
| C40 / `reduce_and_render` 전반 | stable ID atom union, base/plan/S2_10/S2_30 issue 변환·보존, worknote atom 연결, assumption/usage projection | 병렬 결과의 완료 순서에 의존하지 않는 single reducer. 충돌은 last-write-wins 금지 | L1838–1977 |
| C45 / `slot_values`, `select_renderer_branch`, `render_segments`, `reduce_and_render` 후반 | exact branch와 승인·typed slot을 검사해 두 방식으로 문자열 전개·바이트 비교; relief/cause 정렬·문서화 | LLM 자유문을 정형 청구취지로 그대로 확정하지 않음. cause의 REVIEW_TEXT_WITH_SLOTS draft_text는 조건부 사용 | L1748–1835, L1978–2062 |
| C46 / `invariant_results`, `aggregate_validation` | 18개 결과·finding·scope·technical 상태 계산 | 기계적 정합성과 평가불가를 명시 | L2065–2272, L2370–2382 |
| C47 / `legal_gate_snapshot`, `resolve_review_policy_contract`, `candidate_material`, `publish_candidate` | legal readiness·policy 계산, candidate→review subject/request 비순환 봉인, immutable candidate 저장 | 검토 대상 바이트를 고정한 상태에서 외부 승인 받기 | L2275–2367, L2385–2893 |
| C47 resume / `hydrate_frozen_candidate`, `verify_frozen_candidate_digest_chain`, `validate_review_receipts` | frozen dependency/digest·request 재도출, 검토자/서명 attestation/기간/scope 대조 | 다른 후보 승인서 재사용과 검토 중 문안 변경 방지 | L2896–3008, L3197–3441 |
| C48 / `final_status`, `write_terminal_status` | earliest-owner restart 또는 WAIT 또는 commit; intent→파일→result→event→status | 최종 파일의 존재만으로 소비 허가하지 않고 barrier로 확정 | L845–921, L3011–3194 |
| diagnostic / `status_only`, `publish_post_preflight_failure` | S2_00 exact-five 또는 preflight 후 예외의 진단·종결상태 보존 | 최소 coherent package가 없는 run과 기술장애를 명확히 분리 | L993–1076, L3459–3481 |
아래 표는 SOW의 이상적 검증명을 반복하지 않고 **현행 `invariant_results`의 실제 predicate**를 요약한다. 값은 `PASS|FAIL|UNEVALUABLE`; V01/V02의 비PASS는 INCOMPLETE, 나머지의 비PASS는 REVIEW_REQUIRED로 집계된다. (Y:L2065–2272)
| ID | 실제 관찰값 |
|---|---|
| V01 | input closure row의 유일 경로, 필수 5개 barrier/manifest 존재, schema/hash/producer/version 일치 |
| V02 | atom nonempty/group 집합·atom occurrence, issue/assumption/usage occurrence count 및 worknote ID·cluster 보존 |
| V03 | slot row의 `slot_id`, `namespace_owner`, `domain_id` 존재; slot 없음은 UNEVALUABLE |
| V04 | REBUTTAL provenance의 opposing_fact/rebuttal/evidence/polarity/presentation 필드 존재; 해당 row 없음은 UNEVALUABLE |
| V05 | group의 dependency_wave_id 존재와 relation_consistency_status PASS |
| V06 | atom의 각 atomic claim에 BOUND case-type/sub-rule binding row 정확히 하나 |
| V07 | calculation-token의 receipt ID·operand digest·missing_law_values 없음; token 없음은 UNEVALUABLE |
| V08 | recovery_object_id가 있는 atom의 `(recovery_object_id,recovery_scope)` 중복 없음; 없음은 UNEVALUABLE |
| V09 | atom source-plan hash·claim/group·source claim-option 및 binding row 개수 일치 |
| V10 | render errors/absences 없음, 생성 relief/cause row에 section/text 존재 |
| V11 | relief/cause의 claim + party/object/amount/period/calculation/counter-performance hash signature 집합 일치 |
| V12 | requirement-fact pack의 corpus hash 존재·slot_crosswalk PASS·injection isolation PASS에 `all(...) or None` 적용 |
| V13 | LEGAL_PROPOSITION provenance의 authority/locator·temporal PASS·negative treatment CLEAR; 없음은 UNEVALUABLE |
| V14 | 상류 객체에 downstream digest key가 없고 frozen source row가 정렬됨 |
| V15 | atom provenance 존재 및 provenance row의 source_ref/source_refs 존재 |
| V16 | group option_partition의 selected/alternative/excluded/deferred 합집합이 option IDs와 같고 중복 없음. 두 필드가 없으면 빈 집합 비교로 PASS할 수 있음(§8.10) |
| V17 | exhibit rows의 party/object/exhibit/title 필드 존재; 비어 있으면 UNEVALUABLE |
| V18 | render error면 FAIL, absence면 UNEVALUABLE, 그 외 실제 render row 존재 + 재render equality |
`invariant_result`의 `source_refs` 인자는 존재하지만 현재 18개 호출은 대부분 별도 인자를 전달하지 않아 result의 source_refs가 빈 배열이다. reason code와 algorithm ID는 남으나 각 finding의 상세 source locator를 자동 산출하는 구현이라고 설명할 수 없다. (Y:L2065–2077, L2252–2272)
## 7. review·commit 상태와 책임 경계
candidate digest는 dependency snapshot·candidate manifest·문서 hash·worknote core·issue/assumption ledger·validation core·ordered source digest를 입력으로 만든다. review subject는 candidate digest와 request-core bindings·packet/envelope-core hash를 사용하고, receipt는 이 subject에 결속된다. **receipt hash가 candidate digest에 역으로 들어가지 않는다.** RESUME는 persisted ordered-source preimage와 candidate 자료를 재계산하므로 현재 상류를 다시 읽어 새 후보를 만드는 과정이 아니다. (Y:L2743–2823, L3197–3262)
외부 receipt 승인에는 exact receipt type/request/candidate/subject/finding/scope, KOREAN_LAWYER/QUALIFIED_KOREAN_LAWYER, 허용 issuer/key/algorithm, 외부 검증 attestation, 미폐기·유효시간, signed-material digest가 필요하다. required type마다 정확히 하나의 유효 APPROVE_AS_IS가 있어야 한다. duplicate/unsolicited/invalid receipt는 승인에 쓰지 않는다. 유효 CONTENT_CHANGE_REQUIRED만 이전 단계로 되돌리는 원인이 된다. S2_40은 암호 서명 자체를 검증하는 외부 어댑터를 대신하지 않는다. (Y:L2896–3008)
| 관찰 상태 | S2_40 결과 | 후속 책임 |
|---|---|---|
| 입력 trust/preflight 실패 | stdout error; case files 작성 전 종료 | outer adapter가 실패 실행 기록 |
| S2_00 exact-five | DIAGNOSTIC_ONLY / STOP_TECHNICAL_INCOMPLETE, NOT_PRODUCED/NOT_ASSESSED | Stage 1/ingress 보완 |
| 승인 누락·무효, non-production, V 비PASS, gate 미충족 | AWAITING_EXTERNAL_REVIEW / WAIT_EXTERNAL_REVIEW | candidate 유지·필요 자산 승인/검토. receipt 하나로 미승인 legal release를 치유하지 못함 |
| 유효 CONTENT_CHANGE_REQUIRED | SUPERSEDED / RESTART_FROM_S2_00·10·20·30 중 earliest owner | 외부 orchestrator가 새 run/attempt 및 상류 재실행을 설계; S2_40은 in-place 수정 안 함 |
| PRODUCTION + V18개 PASS + 문서 존재 + 10 gates 모두 true + review-policy ready | final 저장 후 COMMITTED / PACKAGE_COMMITTED; READY_FOR_LAWYER_FILING_DECISION | 변호사의 별도 filing decision 및 후속 filing/export validator |
| preflight 이후 예외 | failure diagnostic 및 DIAGNOSTIC_ONLY barrier 시도; stdout ok=false/exit 2 | partial artifact를 committed package로 소비하지 않음 |
10 gates는 `binding`, `authority`, `renderer_branch`, `rule_sub_rule`, `review_policy`, `case_type_coverage_137`, `corpus`, `law_value`, `calculator`, `required_receipts`다. full-137 gate는 CT/CAT 순서·catalog mapping·row legal approval·7개 downstream coverage·Markdown count 137·제외 catalog 없음·registry hash 결속을 함께 요구한다. `required_receipts`만 receipt validation 결과로 나중에 갱신된다. (Y:L2385–2512, L3011–3074)
## 8. 설계 의도와 현재 구현의 차이·분석상 주의점
다음은 코드 수정 권고를 실행한 결과가 아니라 정적 분석에서 확인한 경계다. 본 작업에서 실행 자산은 변경하지 않았다.
1. **SOW/assets의 초기 상태 표시는 최신 실행 상태가 아니다.** [S2_40_assets.md](S2_40_assets.md) 서두는 STUB/FULL_NOT_IMPLEMENTED라고 쓰지만 배포 YAML에는 전체 코드가 있고 metadata는 offline 구현 상태다. 실제 [detached admission](Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json)은 PENDING이므로 live 실행 승인까지 완료했다고 볼 수 없다.
2. **소송문안 순서 검증은 SOW보다 좁다.** SOW §6.2의 본안→비용→가집행·청구원인 section 순서와 달리 inline은 `(group, atomic_claim, output_section, atom)` 문자열 순서로 정렬한다. 같은 group/claim이면 `relief_cost`가 `relief_main`보다 앞선다. V10은 텍스트·section 존재와 render 오류만 검사하므로 문서 순서·가집행 허용식 전체를 실제로 판정하지 않는다. offline assembler의 `RELATION_ORDER`, `CAUSE_SECTION_ORDER`가 inline에 동일 구현되었다고 전제하면 안 된다. (Y:L2035–2047, L2212–2214; [SOW §6.2](S2_40_SOW.md), [oracle](Default_Agent/Stage_2_Clean/runtime/c45_document_assembler.py))
3. **재render의 독립성 범위가 제한적이다.** 두 문자열 생성은 같은 descriptor segments와 slots의 복사본에서 이루어진다. frozen plan/calculator로 별도 AST를 재구축하는 독립 legal renderer까지 구현한 것은 아니다. segment의 escape 속성은 closed key shape 확인에 쓰이지만 escape 값에 따른 실제 escaping 분기는 없다. (Y:L1785–1835)
4. **V09/V11은 주장 내용의 독립 사실검증이 아니다.** V09는 source-plan/claim/group/option 연결을 보며 모든 typed slot 값을 원 plan과 일일이 대조하지 않는다. V11의 비교에 쓰이는 party/amount 등은 relief/cause 양쪽 모두 같은 group contract에서 복사한 값이므로 잘못된 출력 문장 숫자까지 독립 탐지한다고 볼 수 없다. (Y:L2007–2034, L2190–2225)
5. **V12의 빈 집합과 N/A 처리가 중요하다.** `all(...) or None` 때문에 requirement pack이 0개면 `all([])=True`로 V12 PASS가 가능하고, 하나라도 조건 불충족이면 FAIL 대신 UNEVALUABLE이 된다. 별도의 corpus legal gate는 `bool(requirement_packs)`를 요구하여 빈 corpus의 production 승격을 막는다. V03/04/07/08/13/17 등은 해당 자료가 없어도 N/A PASS가 아닌 UNEVALUABLE이므로, 적용할 이유가 없는 사건에서도 all-18-PASS 조건을 충족하지 못할 수 있다. (Y:L2160–2269, L2506, L3025–3044)
6. **서명·CAS는 외부 신뢰 전제가 남는다.** 코드의 latest write는 read/check/write/read-back이며 물리적 atomic CAS 구현이 아니다. host lease와 외부 crypto attestation이 진짜임을 보장하는 backend가 필요하다. YAML만 읽어 live 동시성 안전·전자서명 검증 완료라고 주장할 수 없다. (Y:L439–457, L794–836, L2938–2966)
7. **모든 output에 schema 검증이 적용되는 것은 아니다.** 정상 candidate/review/commit/status/outer execution receipt에는 명시 검사가 많지만 `publish_post_preflight_failure`의 technical diagnostic은 별도 `validate_schema_instance` 없이 저장한다. 또한 `run_status.outer_execution_receipt_sha256`는 null이며 stdout receipt 출력은 barrier 저장 뒤에 실행된다. outer artifact 저장/상호 결속은 별도 플랫폼 책임이다. (Y:L908–915, L3459–3481, L3548–3557)
8. **review 보존과 원본 문안 보존을 구분해야 한다.** 후보에 atom 원본 전체를 복사하는 파일은 없다. clean render 불가 시 3종 Markdown도 만들지 않으며 worknote 대상으로 연결된 atom만 worknote text로 투영한다. 원래 draft atom은 `O/map_s2_30/draft_parts/`에 남고 hash chain으로 결속된다. “모든 상류 문장이 candidate 본문에 복사된다”는 설명은 부정확하다. (Y:L1923–1940, L2038–2062, L2575–2893)
9. **일부 invariant 입력은 현 S2_20 생산 schema와 다르다.** S2_20 group 생성부에는 `dependency_wave_id`, `relation_consistency_status`가 없지만 V05는 이를 요구한다. requirement-fact pack에는 `slot_crosswalk_status`, `injection_isolation_status`가 없지만 V12는 둘의 PASS를 요구한다. exhibit register row는 `evidence_ref/source_key/existing_label/assigned_label/assignment_status`인데 V17은 다른 party/object/exhibit/title 필드를 요구한다. 따라서 정상적인 nonempty 상류 group/pack/exhibit라도 V05 FAIL, V12 UNEVALUABLE, V17 FAIL로 이어질 수 있다. 단순 live admission 대기와는 별개의 생산자-소비자 의미계약 불일치다. (S2_20 YAML L1782–1820, L1930–1942, L3260–3298; 본 YAML L2168–2173, L2225, L2250; `schemas/binding_retrieval.schema.json`의 requirement_fact_pack 정의)
10. **V16은 빈 집합의 자명한 일치로 PASS할 수 있다.** 현재 코드는 group에 `claim_option_ids/option_ids`가 없으면 `[]`, `option_partition`이 없으면 `{}`로 읽는다. `{}`도 dict이므로 평가가능으로 처리하고 빈 합집합과 빈 ID 집합이 같아 PASS할 수 있다. S2_20의 실제 option 분할은 canonical plan 최상위에 있고 group에는 위 필드들이 없다. 따라서 현 V16을 상류 보존식의 실질적 독립 검증 완료로 해석하면 안 된다. (Y:L2101–2114, L2240–2249)
11. **S2_30→S2_40 인계 hash의 대상이 다르다.** 현재 S2_30 planner L1333–1370은 P31을 `{claim_group_id,sources}`, S30을 `{claim_group_id,input_contract,sources}`로 재조립하고 trailing LF 없는 JSON 문자열을 hash한다. S2_40 L1580–1592는 non-STRUCTURAL_FIXTURE에서 그 echo를 원 S2_20 group-slice/rule-pack raw 파일 hash와 비교한다. 서로 다른 객체·byte 범위를 같은 hash로 요구하는 연결이므로 정상적인 조립 결과에도 `S220_S230_GROUP_SLICE_HASH` 또는 `S220_S230_RULE_PACK_HASH` 오류가 발생할 수 있다. fixture 예외 통과를 nonfixture 호환성 증거로 확대하지 않는다. 상세 상류 생성 경로는 [S2_30 분석서](Stage_2_30_Analysis_v1.md) 참조.
## 9. 함수 누락 점검용 색인
다음 표는 코드의 함수·클래스 helper를 실제 책임에 연결한다. 이는 Agent subtask 수를 늘리지 않는다.
| 책임 | 함수/클래스 및 시작행 |
|---|---|
| error | `S240Error` 144 (`__init__` 145, `as_dict` 151) |
| 정규화·JSON·hash | `nfc` 158, `no_duplicates` 162, `load_json` 171, `canonical_bytes` 187, `canonical_markdown` 194, `digest` 203 |
| scalar/path/ID | `require_hex` 208, `require_ident` 214, `require_text` 220, `safe_path` 226, `join_path` 237, `stable_id` 241, `utc_now` 245, `require_object` 249, `require_list` 255 |
| MCP wire | `_parse_mcp_payload` 261, `_tool_text` 313, `_binary_from_text` 327 |
| MCP client | `McpClient` 349 (`__init__` 350, `close` 362, `_post` 365, `initialize` 378, `call` 398, `read_binary` 410, `read_optional` 414, `write_immutable` 422, `write_latest` 439) |
| request/release | `validate_request` 477, `read_bound_json` 542, `read_release_bound_jsons` 553, `preflight` 743, `require_self_hash` 1079 |
| schema | `json_pointer` 589, `resolve_schema_ref` 607, `schema_errors` 631 (nested `type_ok`), `validate_schema_instance` 734, `load_output_schema_store` 840 |
| status/diagnostic | `write_terminal_status` 845, `ingress_schema_ref` 924, `hydrate_ingress_barrier_artifacts` 945, `status_only` 993 |
| S2_10 hydration | `hydrate_s210_artifacts` 1086 (nested `stable_json` 1142) |
| S2_20/30 hydration | `validate_handoff_provenance` 1279, `common_provenance` 1293, `artifact_rows` 1297, `plan_artifact_rows` 1333, `read_plan_artifacts` 1357, `resolve_frozen_ref` 1378, `hydrate_normal` 1399 |
| reduce/render | `flatten` 1701, `unique_sorted` 1717, `provenance_source_refs` 1733, `slot_values` 1748, `select_renderer_branch` 1768, `render_segments` 1785 (nested `render_a` 1800), `reduce_and_render` 1838 |
| invariant | `invariant_result` 2065, `invariant_results` 2080 (nested `relation_signature` 2215, `contains_downstream_key` 2227), `aggregate_validation` 2370 |
| review/digest/gates | `review_request_basis` 2275, `review_subject` 2312, `legal_gate_snapshot` 2385, `resolve_review_policy_contract` 2515, `candidate_material` 2575, `publish_candidate` 2845, `validate_review_receipts` 2896 |
| commit/resume | `final_status` 3011, `verify_frozen_candidate_digest_chain` 3197 (nested `payload_json` 3206), `hydrate_frozen_candidate` 3265 (nested `canonical_bound_json` 3271, `auxiliary_json` 3349) |
| main orchestration | `normal_route` 3444, `publish_post_preflight_failure` 3459, `run` 3484; `__main__` 3560 |
`utc_now` 등 정의된 helper가 모든 실행 경로에서 호출되는 것은 아니다. JSON 크기 상한 32 MiB, 일반 입력 합계 256 MiB, S2_30 manifest row 20,000, schema recursion 160, review ref 64 같은 bounded guard가 있으나 전체 네트워크 response·모든 ref를 동일한 합산 guard로 감싼 구현으로 확대 해석하지 않는다. (Y:L101–110, L631–645, L1297–1301, L1504–1517)
## 10. 근거와 검증 범위
핵심 source 우선순위는 배포 YAML > 실제 deployment/schema/registry 파일 > 선언형 workflow > SOW/assets > MEMORY 역사 기록이다. YAML 전문은 1–500, 501–1000, 1001–1500, 1501–2000, 2001–2500, 2501–3000, 3001–3575의 누락 없는 연속 범위로 읽었다. source hash·줄수와 함수 locator를 실측하고, 자산 존재를 파일 목록으로 확인했다. live run, 현행 대한민국 법률 원문 검증, E2E, 기존 240개 회귀시험 재실행은 이번 문서분석 범위에 포함하지 않는다.
| 회차 | 검증자·범위 | 발견사항 및 증분 수정 |
|---|---|---|
| 1차 | 독립 analysis20: 본문 전체, 40 입력·V predicate·candidate/final 및 20 생산/schema 대조 | V05/V12/V17 생산-소비 필드 불일치, V16 빈 집합 PASS, review receipt 경로 경계 보강. main agent가 반영 |
| 2차 | main agent: 수정본 전문, 실제 V01–V18 predicate, final payload 구성, S2_30 hash 생성부와 S2_40 소비부 대조 | 1차 필드 불일치·빈 집합 PASS 반영 확인. nonfixture S2_30→40 hash 대상 불일치 추가; candidate/final 수량 및 기술·법률 승인 경계 유지 |
검증-수정은 총 2회로 종료했다. 이 결과는 분석서 설명의 정적 정확성 점검이며 기록한 실행계약 결함이 해소되었다는 뜻이 아니다.
@@ -0,0 +1,68 @@
# Stage 2 배포 YAML 5종 분석
## Objective
2026-09-09 실물 배포 YAML 00/10/20/30/40 전문을 분석하여 작업·IO·고정 자산·단계 간 연결을 추적 가능한 한국어 문서로 작성한다.
## Deliverables
`YAML_Prompts/2. Stage_2/Stage_2_{00,10,20,30,40}_Analysis_v1.md`, 해당 폴더 MEMORY.md 요약 및 검증 기록.
## Scope and Non-Scope
배포 YAML·인라인 코드·참조 자산의 기술적 분석. 실행 자산 수정, 재봉인, 실제 사건 실행, 새 법률 판단, 커밋은 범위 밖이다.
## Known Inputs
Stage 2 MEMORY, v.5-1 전략, 단계별 SOW/assets, `Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_*.yml`와 직접 참조 schema/workflow/binding/runtime mirror.
## Material Assumptions
구현 설명의 정본은 현재 배포 YAML이다. 전략·SOW는 의도/히스토리 자료이고 불일치를 숨기지 않는다. 가용 동시 agent 슬롯 3개로 5개 독립 분석을 순차 배정하되 가능한 작업을 중첩한다.
## Questions That Could Change the Outcome
없음. 기존 offline PASS와 현재 live admission 상태는 구별한다.
## Workstreams and Dependencies
5개 독립 전문 읽기·분석 → 교차 문서 및 원문 검증 1회·수정 → 검증 2회·수정 → 문서 형식·경로 확인 → MEMORY.
## Source and Tool Plan
로컬 파일 전문을 분할 읽고 hash/행번호를 기록한다. 검색은 위치 확인용이다. apply_patch로 문서를 작성하며 실행 자산은 읽기 전용으로 유지한다.
## Validation Plan
각 문서 두 차례 검증. 1차는 누락·IO·task/component·경로, 2차는 수정 반영·단계 연결·실제 코드와 계약 차이. 검증표에 발견사항·교정·한계를 기록한다. 실행 테스트는 새 코드 변경이 없으므로 재실행을 완료 근거로 요구하지 않는다.
## Approval Boundaries
요청된 로컬 문서 생성·MEMORY 기록만 수행.
## Progress
- [x] MEMORY 및 규칙 확인
- [x] 5개 YAML 전문 분석 및 초안
- [x] 1차 검증·수정
- [x] 2차 검증·수정
- [x] 최종 문서 및 MEMORY 확인
## Decision Log
| Date/Stage | Decision | Basis | Consequence |
|---|---|---|---|
| 2026-09-09 | 소작업을 Agent task, 인라인 component, 외부 adapter 책임으로 구분 | 배포 YAML의 실제 task 구조 | 개념적 5단계와 실행 task 수의 혼동 방지 |
## Evidence Ledger
| Claim/Issue | Source or Test | Status | Notes |
|---|---|---|---|
| 분석 대상 | 배포 YAML 5개 총 16,100행 | 확인 | 6,248 / 447 / 3,979 / 1,851 / 3,575행 |
| 분석서 및 경로 마감 | 5개 총 1,664행, local links 87개, UTF-8/LF/fence | 확인 | 2026-09-09 read-only 구조 검사 오류 0 |
| source 보존 | source SHA 5개 불변, inline/py/txt 4쌍 | 확인 | 00/20/30-helper/40 parity true; live 실행 검증 아님 |
## Review Ledger
| 분석서 | 1차 검증 → main 수정 | 2차 검증 → main 수정/확정 |
|---|---|---|
| 00 | analysis20: failure label과 실제 barrier 존재 구분, release-class 용어 | main: 전문·guard·projection/cohort·remote publish·55/49 closure 대조, 추가 내용수정 불필요 |
| 10 | analysis00: nested typed output/review exact-once/multi-wave oracle | main: limitation·risk 고정·canonical verdict·exact selected-source path 보완 |
| 20 | main: task parameters/legal decision permission/partial-write schema | analysis00: descriptor self-hash/3 attempts/zero-group 보완 |
| 30 | analysis20: 전체 plan의 group 범위·close exception | main: planner parameters/ref defaults/zero-group downstream 보완 |
| 40 | analysis20: V05/V12/V17 producer field mismatch/V16 empty PASS/review receipt path | main: 30→40 P31/S30 hash 범위 불일치 보완 |
각 문서의 의미 검증-수정은 위 2회로 종료했다. 마지막 link/encoding/hash/parity 검사는 산출물의 기계적 마감 확인이며 추가 의미 검증회차나 실행시험이 아니다.
## Risks and Failure Modes
SOW 의도를 코드 실행 사실로 기술, dynamic path를 실제 존재 파일로 오인, mirror를 runtime import로 오인, historical PASS를 live 실행으로 오인.
## Results and Residual Uncertainty
5종 분석서 및 단계별 정확히 2회 검증·수정과 Stage 2 MEMORY 요약 완료. source와 실제 producer/consumer의 필드·hash 의미 차이, placeholder 자료 처리, 외부 adapter 미결을 분석서에 보존했다. 실행자산·release·기존 무관 변경은 수정하지 않았고 commit하지 않았다. 모델/법률 정확성, live 실행/E2E는 검증하지 않았다.