feat(stage2): implement S2_20 relief planner

- add one inline deterministic MCP task and sealed planning assets
- reseal S2_00/S2_10 release hashes for the S2_20 handoff
- keep live and legal admission explicitly pending
This commit is contained in:
2026-08-31 14:02:15 +09:00
parent 978e6a6b72
commit daab564e81
151 changed files with 42474 additions and 118 deletions
@@ -192,7 +192,7 @@ Agent:
# literal placeholders in the offline parity mirror and its unit tests. # literal placeholders in the offline parity mirror and its unit tests.
INLINE_USER_HASH = "{{__user_hash__}}" INLINE_USER_HASH = "{{__user_hash__}}"
INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}" INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}"
EXPECTED_STAGE2_RELEASE_SHA256 = "0f21af3ddca538d9b6a5853dac23222c0b632d0e573de371a8de2709e691699d" EXPECTED_STAGE2_RELEASE_SHA256 = "70ef317cc0c557e44619b6cd6b4ad567e02e73271a36a0bbc93b748ae3f34f92"
INLINE_REQUEST_PATH = "stage2_control/s2_00_request.json" INLINE_REQUEST_PATH = "stage2_control/s2_00_request.json"
INLINE_STAGE2_ASSET_ROOT = "Default_Agent/Stage_2_Clean" INLINE_STAGE2_ASSET_ROOT = "Default_Agent/Stage_2_Clean"
INLINE_STAGE2_RELEASE_PATH = ( INLINE_STAGE2_RELEASE_PATH = (
@@ -0,0 +1,65 @@
{
"schema_version": "stage2_corpus_build_receipt.v1",
"receipt_id": "S2-CORPUS-BUILD-PENDING",
"build_status": "PENDING_SOURCE_AND_OPERATOR_BUILD",
"build_executed": false,
"created_at": null,
"collection_contract_status": "PENDING_CORPUS_BUILD",
"collection_schema_ref": "corpus/weaviate_collection.schema.json",
"collection_schema_sha256": "f29b287e99d29dbd6d3008d1ad68e3960f9cc2c72459f04316f0311cd3e9a47d",
"collection_name": null,
"tenant": null,
"snapshot_id": null,
"snapshot_sha256": null,
"source_document_count": 0,
"chunk_count": 0,
"approved_case_type_ids": [],
"components": [
{
"component_id": "CHUNKER",
"status": "PENDING",
"configuration_digest": null,
"evidence_refs": []
},
{
"component_id": "EMBEDDING",
"status": "PENDING",
"configuration_digest": null,
"evidence_refs": []
},
{
"component_id": "RERANKER",
"status": "PENDING",
"configuration_digest": null,
"evidence_refs": []
},
{
"component_id": "INDEX",
"status": "PENDING",
"configuration_digest": null,
"evidence_refs": []
},
{
"component_id": "CROSSWALK",
"status": "PENDING",
"configuration_digest": null,
"evidence_refs": []
}
],
"legal_review_status": "PENDING_KOREAN_LAWYER_REVIEW",
"live_mcp_admission_status": "PENDING_LIVE_MCP_ADMISSION",
"production_eligible": false,
"unresolved_reason_codes": [
"CORPUS_BUILD_NOT_EXECUTED",
"LEGAL_REVIEW_NOT_COMPLETED",
"LIVE_MCP_ADMISSION_NOT_COMPLETED",
"RAW_CORPUS_NOT_PROVIDED"
],
"guards": {
"raw_corpus_runtime_ingest_forbidden": true,
"directory_scan_forbidden": true,
"filter_relaxation_forbidden": true,
"embedded_instruction_execution_forbidden": true,
"unapproved_chunk_use_forbidden": true
}
}
@@ -0,0 +1 @@
{"schema_version":"stage2_corpus_chunk_manifest_header.v1","record_type":"MANIFEST_STATUS","manifest_id":"S2-CORPUS-CHUNK-MANIFEST-PENDING","status":"PENDING_SOURCE_AND_OPERATOR_BUILD","execution_eligible":false,"source_document_count":0,"chunk_count":0,"snapshot_id":null,"snapshot_sha256":null,"unresolved_reason_codes":["RAW_CORPUS_NOT_PROVIDED","HEADING_AWARE_CHUNK_BUILD_NOT_EXECUTED","CHUNK_HASHES_NOT_BOUND","CROSSWALK_NOT_BUILT","KOREAN_LAWYER_REVIEW_NOT_COMPLETED"],"guards":{"placeholder_chunk_row_forbidden":true,"unapproved_chunk_runtime_use_forbidden":true,"embedded_instruction_execution_forbidden":true}}
@@ -0,0 +1,24 @@
{
"schema_version": "stage2_corpus_source_manifest.v1",
"manifest_id": "S2-CORPUS-SOURCE-MANIFEST-PENDING",
"status": "PENDING_SOURCE_AND_LEGAL_REVIEW",
"execution_eligible": false,
"path_base": "corpus/raw",
"source_document_count": 0,
"approved_source_document_count": 0,
"source_rows": [],
"unresolved_reason_codes": [
"RAW_CORPUS_NOT_PROVIDED",
"SOURCE_HASHES_NOT_BOUND",
"CASE_TYPE_SUB_RULE_CROSSWALK_NOT_BUILT",
"AUTHORITY_REVIEW_NOT_COMPLETED",
"KOREAN_LAWYER_REVIEW_NOT_COMPLETED"
],
"guards": {
"placeholder_source_row_forbidden": true,
"unapproved_source_runtime_use_forbidden": true,
"nearest_case_type_fallback_forbidden": true,
"raw_directory_scan_at_runtime_forbidden": true,
"embedded_instruction_execution_forbidden": true
}
}
@@ -0,0 +1,533 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.liti-agent.local/stage2/corpus/weaviate_collection.schema.v1.json",
"title": "Stage 2 requirement-fact Weaviate collection and retrieval contracts",
"description": "Closed metadata, filter, request, response, and build-receipt contracts. It does not assert that a live collection, tenant, credential, snapshot, embedding model, or legal approval exists.",
"schema_version": "stage2_weaviate_collection_contract_bundle.v1",
"oneOf": [
{"$ref": "#/$defs/collection_contract"},
{"$ref": "#/$defs/corpus_object_metadata"},
{"$ref": "#/$defs/hybrid_search_request"},
{"$ref": "#/$defs/hybrid_search_response"},
{"$ref": "#/$defs/corpus_build_receipt"}
],
"$defs": {
"sha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$"
},
"pending_or_sha256": {
"oneOf": [
{"$ref": "#/$defs/sha256"},
{"const": "PENDING_SEQUENTIAL_BIND"}
]
},
"nonempty_string": {
"type": "string",
"minLength": 1
},
"nullable_nonempty_string": {
"oneOf": [
{"$ref": "#/$defs/nonempty_string"},
{"type": "null"}
]
},
"path_ref": {
"type": "string",
"minLength": 1,
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*[\\x00-\\x1f]).+$"
},
"string_set": {
"type": "array",
"items": {"$ref": "#/$defs/nonempty_string"},
"uniqueItems": true
},
"nonempty_string_set": {
"type": "array",
"items": {"$ref": "#/$defs/nonempty_string"},
"minItems": 1,
"uniqueItems": true
},
"date_or_null": {
"oneOf": [
{"type": "string", "format": "date"},
{"type": "null"}
]
},
"collection_contract": {
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"contract_id",
"transport",
"endpoint",
"protocol_version",
"tool_name",
"operation_mode",
"collection_name",
"tenant",
"credential_ref",
"object_metadata_schema_ref",
"filter_schema_ref",
"index_configuration_digest",
"snapshot_id",
"snapshot_sha256",
"status"
],
"properties": {
"schema_version": {"const": "stage2_weaviate_collection_contract.v1"},
"contract_id": {"$ref": "#/$defs/nonempty_string"},
"transport": {"const": "MCP_OVER_HTTP_JSON_RPC"},
"endpoint": {"const": "https://weaviate.eroomai.com/mcp"},
"protocol_version": {"const": "2025-03-26"},
"tool_name": {"const": "search_hybrid"},
"operation_mode": {"const": "READ_ONLY_FILTERED_HYBRID_SEARCH"},
"collection_name": {"$ref": "#/$defs/nullable_nonempty_string"},
"tenant": {"$ref": "#/$defs/nullable_nonempty_string"},
"credential_ref": {"$ref": "#/$defs/nullable_nonempty_string"},
"object_metadata_schema_ref": {
"const": "corpus/weaviate_collection.schema.json#/$defs/corpus_object_metadata"
},
"filter_schema_ref": {
"const": "corpus/weaviate_collection.schema.json#/$defs/search_filter"
},
"index_configuration_digest": {
"oneOf": [
{"$ref": "#/$defs/sha256"},
{"type": "null"}
]
},
"snapshot_id": {"$ref": "#/$defs/nullable_nonempty_string"},
"snapshot_sha256": {
"oneOf": [
{"$ref": "#/$defs/sha256"},
{"type": "null"}
]
},
"status": {
"enum": [
"PENDING_CORPUS_BUILD",
"BUILT_NOT_LIVE_ADMITTED",
"LIVE_CANARY_ADMITTED",
"PRODUCTION_ADMITTED"
]
}
},
"allOf": [
{
"if": {
"properties": {
"status": {"const": "PENDING_CORPUS_BUILD"}
},
"required": ["status"]
},
"then": {
"properties": {
"collection_name": {"type": "null"},
"tenant": {"type": "null"},
"credential_ref": {"type": "null"},
"index_configuration_digest": {"type": "null"},
"snapshot_id": {"type": "null"},
"snapshot_sha256": {"type": "null"}
}
}
}
]
},
"corpus_object_metadata": {
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"document_id",
"document_sha256",
"chunk_id",
"chunk_sha256",
"source_path",
"source_locator",
"case_type_ids",
"sub_rule_ids",
"rule_branch_keys",
"corpus_scope_ids",
"element_set_ids",
"corpus_element_ids",
"doctrine_roles",
"jurisdiction",
"effective_from",
"effective_to",
"authority_ids",
"proposition_ids",
"approval_status",
"legal_reviewer_receipt_ref",
"legal_reviewer_receipt_sha256"
],
"properties": {
"schema_version": {"const": "stage2_requirement_fact_chunk_metadata.v1"},
"document_id": {"$ref": "#/$defs/nonempty_string"},
"document_sha256": {"$ref": "#/$defs/sha256"},
"chunk_id": {"$ref": "#/$defs/nonempty_string"},
"chunk_sha256": {"$ref": "#/$defs/sha256"},
"source_path": {"$ref": "#/$defs/path_ref"},
"source_locator": {"$ref": "#/$defs/nonempty_string"},
"case_type_ids": {"$ref": "#/$defs/nonempty_string_set"},
"sub_rule_ids": {"$ref": "#/$defs/string_set"},
"rule_branch_keys": {"$ref": "#/$defs/string_set"},
"corpus_scope_ids": {"$ref": "#/$defs/nonempty_string_set"},
"element_set_ids": {"$ref": "#/$defs/nonempty_string_set"},
"corpus_element_ids": {"$ref": "#/$defs/nonempty_string_set"},
"doctrine_roles": {
"type": "array",
"items": {
"enum": ["element", "defense", "rebuttal", "burden", "relief_consistency"]
},
"minItems": 1,
"uniqueItems": true
},
"jurisdiction": {"const": "KR"},
"effective_from": {"$ref": "#/$defs/date_or_null"},
"effective_to": {"$ref": "#/$defs/date_or_null"},
"authority_ids": {"$ref": "#/$defs/string_set"},
"proposition_ids": {"$ref": "#/$defs/string_set"},
"approval_status": {
"enum": ["PENDING_LEGAL_REVIEW", "APPROVED", "REJECTED", "WITHDRAWN"]
},
"legal_reviewer_receipt_ref": {
"oneOf": [
{"$ref": "#/$defs/path_ref"},
{"type": "null"}
]
},
"legal_reviewer_receipt_sha256": {
"oneOf": [
{"$ref": "#/$defs/sha256"},
{"type": "null"}
]
}
},
"allOf": [
{
"if": {
"properties": {"approval_status": {"const": "APPROVED"}},
"required": ["approval_status"]
},
"then": {
"properties": {
"legal_reviewer_receipt_ref": {"$ref": "#/$defs/path_ref"},
"legal_reviewer_receipt_sha256": {"$ref": "#/$defs/sha256"}
}
}
}
]
},
"search_filter": {
"type": "object",
"additionalProperties": false,
"required": [
"case_type_id",
"sub_rule_id",
"rule_branch_key",
"corpus_scope_id",
"element_set_id",
"doctrine_role",
"jurisdiction",
"snapshot_id",
"approval_status",
"effective_on"
],
"properties": {
"case_type_id": {"$ref": "#/$defs/nonempty_string"},
"sub_rule_id": {"$ref": "#/$defs/nonempty_string"},
"rule_branch_key": {"$ref": "#/$defs/nonempty_string"},
"corpus_scope_id": {"$ref": "#/$defs/nonempty_string"},
"element_set_id": {"$ref": "#/$defs/nonempty_string"},
"doctrine_role": {
"enum": ["element", "defense", "rebuttal", "burden", "relief_consistency"]
},
"jurisdiction": {"const": "KR"},
"snapshot_id": {"$ref": "#/$defs/nonempty_string"},
"approval_status": {"const": "APPROVED"},
"effective_on": {
"type": "string",
"format": "date"
}
}
},
"hybrid_search_request": {
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"request_id",
"query_plan_id",
"atomic_claim_id",
"collection_name",
"tenant",
"query_text",
"query_sha256",
"filter",
"alpha",
"top_k",
"embedding_configuration_digest",
"reranker_configuration_digest",
"index_configuration_digest",
"snapshot_sha256"
],
"properties": {
"schema_version": {"const": "stage2_weaviate_hybrid_search_request.v1"},
"request_id": {"$ref": "#/$defs/nonempty_string"},
"query_plan_id": {"$ref": "#/$defs/nonempty_string"},
"atomic_claim_id": {"$ref": "#/$defs/nonempty_string"},
"collection_name": {"$ref": "#/$defs/nonempty_string"},
"tenant": {"$ref": "#/$defs/nonempty_string"},
"query_text": {"$ref": "#/$defs/nonempty_string"},
"query_sha256": {"$ref": "#/$defs/sha256"},
"filter": {"$ref": "#/$defs/search_filter"},
"alpha": {"type": "number", "minimum": 0, "maximum": 1},
"top_k": {"type": "integer", "minimum": 1, "maximum": 100},
"embedding_configuration_digest": {"$ref": "#/$defs/sha256"},
"reranker_configuration_digest": {"$ref": "#/$defs/sha256"},
"index_configuration_digest": {"$ref": "#/$defs/sha256"},
"snapshot_sha256": {"$ref": "#/$defs/sha256"}
}
},
"hybrid_hit": {
"type": "object",
"additionalProperties": false,
"required": [
"chunk_id",
"chunk_sha256",
"source_document_id",
"source_document_sha256",
"source_locator",
"pre_rerank_rank",
"hybrid_score",
"post_rerank_rank",
"reranker_score",
"metadata"
],
"properties": {
"chunk_id": {"$ref": "#/$defs/nonempty_string"},
"chunk_sha256": {"$ref": "#/$defs/sha256"},
"source_document_id": {"$ref": "#/$defs/nonempty_string"},
"source_document_sha256": {"$ref": "#/$defs/sha256"},
"source_locator": {"$ref": "#/$defs/nonempty_string"},
"pre_rerank_rank": {"type": "integer", "minimum": 1},
"hybrid_score": {"type": "number"},
"post_rerank_rank": {"type": "integer", "minimum": 1},
"reranker_score": {"type": ["number", "null"]},
"metadata": {"$ref": "#/$defs/corpus_object_metadata"}
}
},
"dropped_hit": {
"type": "object",
"additionalProperties": false,
"required": ["chunk_id", "chunk_sha256", "drop_reason_code"],
"properties": {
"chunk_id": {"$ref": "#/$defs/nonempty_string"},
"chunk_sha256": {"$ref": "#/$defs/sha256"},
"drop_reason_code": {
"enum": [
"FILTER_MISMATCH",
"UNAPPROVED_CHUNK",
"HASH_MISMATCH",
"SNAPSHOT_MISMATCH",
"CROSSWALK_GAP",
"DUPLICATE_CHUNK"
]
}
}
},
"hybrid_search_response": {
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"request_id",
"request_sha256",
"response_status",
"raw_hit_count",
"selected_hits",
"dropped_hits",
"deterministic_order_digest",
"retry_count"
],
"properties": {
"schema_version": {"const": "stage2_weaviate_hybrid_search_response.v1"},
"request_id": {"$ref": "#/$defs/nonempty_string"},
"request_sha256": {"$ref": "#/$defs/sha256"},
"response_status": {
"enum": ["COMPLETE", "NO_HIT", "TECHNICAL_INCOMPLETE"]
},
"raw_hit_count": {"type": "integer", "minimum": 0},
"selected_hits": {
"type": "array",
"items": {"$ref": "#/$defs/hybrid_hit"}
},
"dropped_hits": {
"type": "array",
"items": {"$ref": "#/$defs/dropped_hit"}
},
"deterministic_order_digest": {
"oneOf": [
{"$ref": "#/$defs/sha256"},
{"type": "null"}
]
},
"retry_count": {"type": "integer", "minimum": 0, "maximum": 2}
}
},
"build_component_status": {
"type": "object",
"additionalProperties": false,
"required": ["component_id", "status", "configuration_digest", "evidence_refs"],
"properties": {
"component_id": {
"enum": ["CHUNKER", "EMBEDDING", "RERANKER", "INDEX", "CROSSWALK"]
},
"status": {
"enum": ["PENDING", "BUILT_NOT_ADMITTED", "ADMITTED"]
},
"configuration_digest": {
"oneOf": [
{"$ref": "#/$defs/sha256"},
{"type": "null"}
]
},
"evidence_refs": {"$ref": "#/$defs/string_set"}
}
},
"corpus_build_receipt": {
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"receipt_id",
"build_status",
"build_executed",
"created_at",
"collection_contract_status",
"collection_schema_ref",
"collection_schema_sha256",
"collection_name",
"tenant",
"snapshot_id",
"snapshot_sha256",
"source_document_count",
"chunk_count",
"approved_case_type_ids",
"components",
"legal_review_status",
"live_mcp_admission_status",
"production_eligible",
"unresolved_reason_codes",
"guards"
],
"properties": {
"schema_version": {"const": "stage2_corpus_build_receipt.v1"},
"receipt_id": {"$ref": "#/$defs/nonempty_string"},
"build_status": {
"enum": [
"PENDING_SOURCE_AND_OPERATOR_BUILD",
"BUILT_NOT_LEGALLY_REVIEWED",
"BUILT_NOT_LIVE_ADMITTED",
"ADMITTED"
]
},
"build_executed": {"type": "boolean"},
"created_at": {
"oneOf": [
{"type": "string", "format": "date-time"},
{"type": "null"}
]
},
"collection_contract_status": {
"enum": ["PENDING_CORPUS_BUILD", "BUILT_NOT_LIVE_ADMITTED", "LIVE_CANARY_ADMITTED", "PRODUCTION_ADMITTED"]
},
"collection_schema_ref": {
"const": "corpus/weaviate_collection.schema.json"
},
"collection_schema_sha256": {"$ref": "#/$defs/pending_or_sha256"},
"collection_name": {"$ref": "#/$defs/nullable_nonempty_string"},
"tenant": {"$ref": "#/$defs/nullable_nonempty_string"},
"snapshot_id": {"$ref": "#/$defs/nullable_nonempty_string"},
"snapshot_sha256": {
"oneOf": [
{"$ref": "#/$defs/sha256"},
{"type": "null"}
]
},
"source_document_count": {"type": "integer", "minimum": 0},
"chunk_count": {"type": "integer", "minimum": 0},
"approved_case_type_ids": {"$ref": "#/$defs/string_set"},
"components": {
"type": "array",
"items": {"$ref": "#/$defs/build_component_status"},
"minItems": 5,
"maxItems": 5
},
"legal_review_status": {
"enum": ["PENDING_KOREAN_LAWYER_REVIEW", "APPROVED", "REJECTED"]
},
"live_mcp_admission_status": {
"enum": ["PENDING_LIVE_MCP_ADMISSION", "LIVE_CANARY_ADMITTED", "PRODUCTION_ADMITTED"]
},
"production_eligible": {"type": "boolean"},
"unresolved_reason_codes": {"$ref": "#/$defs/string_set"},
"guards": {
"type": "object",
"additionalProperties": false,
"required": [
"raw_corpus_runtime_ingest_forbidden",
"directory_scan_forbidden",
"filter_relaxation_forbidden",
"embedded_instruction_execution_forbidden",
"unapproved_chunk_use_forbidden"
],
"properties": {
"raw_corpus_runtime_ingest_forbidden": {"const": true},
"directory_scan_forbidden": {"const": true},
"filter_relaxation_forbidden": {"const": true},
"embedded_instruction_execution_forbidden": {"const": true},
"unapproved_chunk_use_forbidden": {"const": true}
}
}
},
"allOf": [
{
"if": {
"properties": {
"build_status": {"const": "PENDING_SOURCE_AND_OPERATOR_BUILD"}
},
"required": ["build_status"]
},
"then": {
"properties": {
"build_executed": {"const": false},
"created_at": {"type": "null"},
"collection_contract_status": {"const": "PENDING_CORPUS_BUILD"},
"collection_name": {"type": "null"},
"tenant": {"type": "null"},
"snapshot_id": {"type": "null"},
"snapshot_sha256": {"type": "null"},
"source_document_count": {"const": 0},
"chunk_count": {"const": 0},
"approved_case_type_ids": {"maxItems": 0},
"legal_review_status": {"const": "PENDING_KOREAN_LAWYER_REVIEW"},
"live_mcp_admission_status": {"const": "PENDING_LIVE_MCP_ADMISSION"},
"production_eligible": {"const": false}
}
}
}
]
}
},
"x-runtime-boundary": {
"mcp_endpoint": "https://weaviate.eroomai.com/mcp",
"mcp_protocol_version": "2025-03-26",
"tool_allowlist": ["search_hybrid"],
"write_operations_allowed": false,
"filter_relaxation_allowed": false,
"live_admission_status": "PENDING_EXTERNAL_EVIDENCE"
}
}
@@ -1,55 +1,58 @@
schema_version: stage2_code_executor_binding.v2 schema_version: stage2_code_executor_binding.v3
binding_id: S2-BINDING-S2_00-CODE-EXECUTOR-V2 binding_id: S2-BINDING-DETERMINISTIC-STAGES-V3
workflow_id: S2_00 stage_bindings:
execution_class: NON-LLM-DETERMINISTIC - stage_id: S2_00
active_runtime_authority: true binding_id: S2-BINDING-S2_00-CODE-EXECUTOR-V2
workflow_id: S2_00
execution_class: NON-LLM-DETERMINISTIC
active_runtime_authority: true
agent_script_ref: agent_script_ref:
asset_id: AGENT-S2_00-INLINE asset_id: AGENT-S2_00-INLINE
path: agent_scripts/Stage_2_S2_00.yml path: agent_scripts/Stage_2_S2_00.yml
sha256: 04877f5459c8a579d793ed34ac936cc366a7e5b1c77a1230c93284036196fabe sha256: 45ca76de0c352745f8111ed036a001d053bdc9b43c1a72292d49d9b5f3bcd2c7
schema_id: liti_agent_yaml.v1 schema_id: liti_agent_yaml.v1
binding_status: BOUND binding_status: BOUND
workflow_contract_ref: workflow_contract_ref:
asset_id: WF-S2_00 asset_id: WF-S2_00
path: workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml path: workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml
sha256: 3d7ceb86b236668c8c372136f1d1b43a5d0a79d3fb05fd1ef4342bb638190f68 sha256: 3d7ceb86b236668c8c372136f1d1b43a5d0a79d3fb05fd1ef4342bb638190f68
schema_id: stage2_workflow_contract.v1.2 schema_id: stage2_workflow_contract.v1.2
binding_status: BOUND binding_status: BOUND
inline_code_receipt_ref: inline_code_receipt_ref:
asset_id: RECEIPT-S2_00-INLINE-CODE asset_id: RECEIPT-S2_00-INLINE-CODE
path: manifest/s2_00_inline_code_receipt.json path: manifest/s2_00_inline_code_receipt.json
sha256: a0839fae2d30091ee3a6d41b96f324a530d0dc569cd23e0b7f6ad6a1445dd130 sha256: 1a0044a0f1e0fec13a5d4870df6147b8c4c671d843d4b634b4249442fdcfdfb8
schema_id: stage2_s2_00_inline_code_receipt.v2 schema_id: stage2_s2_00_inline_code_receipt.v2
binding_status: BOUND binding_status: BOUND
stage2_release_ref: stage2_release_ref:
asset_id: RELEASE-STAGE2-CLEAN asset_id: RELEASE-STAGE2-CLEAN
path: manifest/stage2_release.json path: manifest/stage2_release.json
sha256: 0f21af3ddca538d9b6a5853dac23222c0b632d0e573de371a8de2709e691699d sha256: 70ef317cc0c557e44619b6cd6b4ad567e02e73271a36a0bbc93b748ae3f34f92
schema_id: stage2_release.v2 schema_id: stage2_release.v2
binding_status: BOUND binding_status: BOUND
expected_release_sha256: 0f21af3ddca538d9b6a5853dac23222c0b632d0e573de371a8de2709e691699d expected_release_sha256: 70ef317cc0c557e44619b6cd6b4ad567e02e73271a36a0bbc93b748ae3f34f92
agent_script_sha256: 04877f5459c8a579d793ed34ac936cc366a7e5b1c77a1230c93284036196fabe agent_script_sha256: 45ca76de0c352745f8111ed036a001d053bdc9b43c1a72292d49d9b5f3bcd2c7
canonical_code_sha256: 92f13cf3ac113c68e646fcf3b8d6bf9b8a7f41962eef809af91ebf133d50bc99 canonical_code_sha256: b2c56fde707664903158f7d73073fc4a4913fb21234df455bdf5fe2bd1e5fafa
mcp_server_id: code-executor mcp_server_id: code-executor
tool_name: run_code tool_name: run_code
language: python language: python
network: agent-network network: agent-network
timeout_seconds: 300 timeout_seconds: 300
runtime_image_digest: PENDING_SEQUENTIAL_BIND runtime_image_digest: PENDING_SEQUENTIAL_BIND
runtime_image_status: PENDING_BACKEND_EVIDENCE runtime_image_status: PENDING_BACKEND_EVIDENCE
dependency_lock: dependency_lock:
requirements: "httpx==0.28.1" requirements: "httpx==0.28.1"
requirements_sha256: 5fadf5f6ea5bd1b141ea05745cb52449bdccde939c22e76231e7993c2afc91d0 requirements_sha256: 5fadf5f6ea5bd1b141ea05745cb52449bdccde939c22e76231e7993c2afc91d0
lock_status: LIVE_BACKEND_PENDING lock_status: LIVE_BACKEND_PENDING
localdocs_contract: localdocs_contract:
endpoint: http://mcp-localdocs:8012/mcp endpoint: http://mcp-localdocs:8012/mcp
user_id_template: "{{__user_hash__}}" user_id_template: "{{__user_hash__}}"
workspace_id_template: "{{__workspace_hash__}}" workspace_id_template: "{{__workspace_hash__}}"
@@ -70,18 +73,183 @@ localdocs_contract:
- stage2_runs/by-binding/<run_binding_digest>/<published-artifact-path> - stage2_runs/by-binding/<run_binding_digest>/<published-artifact-path>
write_root_rule: stage2_runs/by-binding/<run_binding_digest>/ write_root_rule: stage2_runs/by-binding/<run_binding_digest>/
egress_profile_id: S2_00_LOCALDOCS_ONLY_V1 external_mcp_contract: null
egress_profile_status: PENDING_LIVE_VERIFICATION egress_profile_id: S2_00_LOCALDOCS_ONLY_V1
egress_profile_status: PENDING_LIVE_VERIFICATION
downstream_handoff_owner: downstream_handoff_owner:
workflow_id: S2_10 workflow_id: S2_10
ownership_scope: DOWNSTREAM_TASK_CONSTRUCTION_BINDING_AND_INVOCATION ownership_scope: DOWNSTREAM_TASK_CONSTRUCTION_BINDING_AND_INVOCATION
agent_path: agent_scripts/Stage_2_S2_10.yml agent_path: agent_scripts/Stage_2_S2_10.yml
s2_10_agent_sha256: 0eed6f354d3539a58cc3953dd3a4eb30bb14ba515e2c90380df5830d404a8513 s2_10_agent_sha256: 0eed6f354d3539a58cc3953dd3a4eb30bb14ba515e2c90380df5830d404a8513
llm_binding_path: deployment/stage2_s2_10_llm_binding.yml llm_binding_path: deployment/stage2_s2_10_llm_binding.yml
s2_10_llm_binding_sha256: b240212634c10017fa3b4d1d71fed7ab82cdb1c2da80d92ece29a6dadfb429f1 s2_10_llm_binding_sha256: 90f23bbe5b0c91374e550e9c841f708f6df51d2692f626e4a05367d4dffd9f95
owner_binding_status: HASH_BOUND_LIVE_ADMISSION_PENDING owner_binding_status: HASH_BOUND_LIVE_ADMISSION_PENDING
s2_00_override_allowed: false s2_00_override_allowed: false
live_admission_status: PENDING_SECRET_BINDING live_admission_status: PENDING_SECRET_BINDING
legacy_fallbacks: []
- stage_id: S2_20
binding_id: S2-BINDING-S2_20-CODE-EXECUTOR-V1
workflow_id: S2_20
execution_class: NON-LLM-DETERMINISTIC
active_runtime_authority: false
agent_script_ref:
asset_id: AGENT-S2_20-INLINE
path: agent_scripts/Stage_2_S2_20.yml
sha256: 4d7642bb8b63dc37fc0ca7808676c816ba43623384b0f745f9f4af17f0f8553b
schema_id: liti_agent_yaml.v1
binding_status: BOUND
workflow_contract_ref:
asset_id: WF-S2_20
path: workflows/S2_20_canonical_relief_plan_reduce.yml
sha256: da56152af502fe432cb2ebaa593a4e389b7f2cd4d0b8f3be29e49717cff0544a
schema_id: stage2_workflow_contract.v1
binding_status: BOUND
inline_code_receipt_ref:
asset_id: RECEIPT-S2_20-INLINE-CODE
path: manifest/s2_20_inline_code_receipt.json
sha256: 3693ce7d99d64458f2dbf80f9535aad55ad1dec22ab95898f3c05b204afb801b
schema_id: stage2_s2_20_inline_code_receipt.v1
binding_status: BOUND
stage2_release_ref:
asset_id: RELEASE-STAGE2-CLEAN
path: manifest/stage2_release.json
sha256: 70ef317cc0c557e44619b6cd6b4ad567e02e73271a36a0bbc93b748ae3f34f92
schema_id: stage2_release.v2
binding_status: BOUND
expected_release_sha256: 70ef317cc0c557e44619b6cd6b4ad567e02e73271a36a0bbc93b748ae3f34f92
agent_script_sha256: 4d7642bb8b63dc37fc0ca7808676c816ba43623384b0f745f9f4af17f0f8553b
canonical_code_sha256: 140a83b71aa1007dd275c91a0aa8c837bd2d72a41136ae5bfa0c007da8dd701e
mcp_server_id: code-executor
tool_name: run_code
language: python
network: agent-network
timeout_seconds: 300
runtime_image_digest: PENDING_SEQUENTIAL_BIND
runtime_image_status: PENDING_BACKEND_EVIDENCE
dependency_lock:
requirements: "httpx==0.28.1"
requirements_sha256: 5fadf5f6ea5bd1b141ea05745cb52449bdccde939c22e76231e7993c2afc91d0
lock_status: LIVE_BACKEND_PENDING
localdocs_contract:
endpoint: http://mcp-localdocs:8012/mcp
user_id_template: "{{__user_hash__}}"
workspace_id_template: "{{__workspace_hash__}}"
tool_allowlist:
- read_binary_doc
- write_binary_file
fixed_request_path: stage2_control/s2_20_request.json
read_path_allowlist:
- stage2_control/s2_20_request.json
- stage2_control/host_cas/<run_binding_digest>/S2_20.json
- Default_Agent/Stage_2_Clean/manifest/stage2_release.json
- Default_Agent/Stage_2_Clean/manifest/module_manifest.json
- Default_Agent/Stage_2_Clean/manifest/s2_10_release.json
- Default_Agent/Stage_2_Clean/manifest/authority_release.json
- Default_Agent/Stage_2_Clean/manifest/case_type_coverage.json
- Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json
- Default_Agent/Stage_2_Clean/manifest/case_type_registry.yml
- Default_Agent/Stage_2_Clean/manifest/case_type_rule_registry.yml
- Default_Agent/Stage_2_Clean/rules/relief/<case_type_id>.md
- Default_Agent/Stage_2_Clean/legal_review/<legal_review_receipt_id>.json
- Default_Agent/Stage_2_Clean/manifest/corpus_release.json
- Default_Agent/Stage_2_Clean/manifest/s2_20_inline_code_receipt.json
- Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml
- Default_Agent/Stage_2_Clean/deployment/stage2_code_executor_binding.yml
- Default_Agent/Stage_2_Clean/deployment/stage2_s2_10_llm_binding.yml
- Default_Agent/Stage_2_Clean/registry/binding/binding_signature_projection.yml
- Default_Agent/Stage_2_Clean/registry/planning/option_disposition_policy.yml
- Default_Agent/Stage_2_Clean/registry/party/party_set_rules.yml
- Default_Agent/Stage_2_Clean/registry/drafting/case_type_relief_rules.yml
- Default_Agent/Stage_2_Clean/registry/drafting/forbidden_relief_rules.yml
- Default_Agent/Stage_2_Clean/registry/drafting/counter_performance_rules.yml
- Default_Agent/Stage_2_Clean/registry/drafting/procedural_declaration_rules.yml
- Default_Agent/Stage_2_Clean/registry/review/review_policy_registry.yml
- Default_Agent/Stage_2_Clean/registry/authority/authority_registry.yml
- Default_Agent/Stage_2_Clean/registry/corpus/requirement_fact_scope.yml
- Default_Agent/Stage_2_Clean/registry/temporal/inheritance_reserved_share.yml
- Default_Agent/Stage_2_Clean/registry/calculations/calculation_activation_registry.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-01_interest_delay.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-02_allocation_setoff_balance.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-03_limitation_deadline.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-04_valuation.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-05_personal_injury.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-06_construction_defect.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-07_lease_use_gain.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-08_inheritance_reserved_share.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-09_wage_severance.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-10_actio_insolvency_value.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-11_distribution_share_division.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-12_insurance.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-13_court_value_cost.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-R1_ip_damage.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-R2_org_liquidation.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-R3_transport_maritime.yml
- Default_Agent/Stage_2_Clean/registry/calculations/CE-R4_financial_instrument.yml
- Default_Agent/Stage_2_Clean/law_values/general_law_values.yml
- Default_Agent/Stage_2_Clean/law_values/court_fee_values.yml
- Default_Agent/Stage_2_Clean/schemas/relief_plan.schema.json
- Default_Agent/Stage_2_Clean/schemas/binding_retrieval.schema.json
- Default_Agent/Stage_2_Clean/schemas/calculation.schema.json
- Default_Agent/Stage_2_Clean/corpus/weaviate_collection.schema.json
- Default_Agent/Stage_2_Clean/schemas/ingress.schema.json
- Default_Agent/Stage_2_Clean/schemas/context.schema.json
- Default_Agent/Stage_2_Clean/schemas/s2_10.schema.json
- Default_Agent/Stage_2_Clean/schemas/review_status.schema.json
- Default_Agent/Stage_2_Clean/schemas/deployment.schema.json
- Default_Agent/Stage_2_Clean/routing/actio_pauliana_route_registry.yml
- Default_Agent/Stage_2_Clean/routing/actio_pauliana_mortgage_route.yml
- Default_Agent/Stage_2_Clean/validators/actio_value_compensation_invariants.yml
- Default_Agent/Stage_2_Clean/renderers/R01_money_payment.yml
- Default_Agent/Stage_2_Clean/renderers/R02_delivery_possession.yml
- Default_Agent/Stage_2_Clean/renderers/R03_declaration_registry.yml
- Default_Agent/Stage_2_Clean/renderers/R04_special_nonmoney_performance.yml
- Default_Agent/Stage_2_Clean/renderers/R05_declaratory.yml
- Default_Agent/Stage_2_Clean/renderers/R06_constitutive_judgment_challenge.yml
- stage2_runs/by-binding/<run_binding_digest>/ingress/ingress_status.json
- stage2_runs/by-binding/<run_binding_digest>/context/case_context.json
- stage2_runs/by-binding/<run_binding_digest>/context/evidence_inventory.json
- stage2_runs/by-binding/<run_binding_digest>/context/object_registry.json
- stage2_runs/by-binding/<run_binding_digest>/context/cluster_plan.json
- stage2_runs/by-binding/<run_binding_digest>/context/party_and_title_context.json
- stage2_runs/by-binding/<run_binding_digest>/context/slot_crosswalk.json
- stage2_runs/by-binding/<run_binding_digest>/context/bundle_plan.json
- stage2_runs/by-binding/<run_binding_digest>/review/issue_ledger.base.json
- stage2_runs/by-binding/<run_binding_digest>/context/cluster_slices/<cluster_id>.json
- stage2_runs/by-binding/<run_binding_digest>/map_s2_10/s2_10_publish_status.json
- stage2_runs/by-binding/<run_binding_digest>/map_s2_10/domain_verdicts/<cluster_id>.json
- stage2_runs/by-binding/<run_binding_digest>/map_s2_10/item_receipts/<cluster_id>.json
- stage2_runs/by-binding/<run_binding_digest>/map_s2_10/issue_patches/<cluster_id>.json
- stage2_runs/by-binding/<run_binding_digest>/map_s2_10/assumption_parts/<cluster_id>.json
- stage2_runs/by-binding/<run_binding_digest>/map_s2_10/usage_parts/<cluster_id>.json
- stage2_runs/by-binding/<run_binding_digest>/map_s2_10/wave_receipts/wave-<zero-based-ordinal>.json
write_root_rule: stage2_runs/by-binding/<run_binding_digest>/
external_mcp_contract:
endpoint: https://weaviate.eroomai.com/mcp
protocol_version: "2025-03-26"
tool_allowlist:
- search_hybrid
collection: PENDING_CORPUS_RELEASE_BIND
tenant: PENDING_CORPUS_RELEASE_BIND
credential_ref: agentbackend://stage2/s2_20/weaviate-readonly
operation_mode: READ_ONLY_EXACT_FILTER
admission_status: PENDING_LIVE_VERIFICATION
egress_profile_id: S2_20_LOCALDOCS_WEAVIATE_READONLY_V1
egress_profile_status: PENDING_LIVE_VERIFICATION
downstream_handoff_owner: null
live_admission_status: PENDING_SECRET_BINDING
legacy_fallbacks: []
legacy_fallbacks: [] legacy_fallbacks: []
@@ -8,7 +8,7 @@ fallback_allowed: false
superseded_by: superseded_by:
asset_id: BINDING-S2_00-CODE-EXECUTOR asset_id: BINDING-S2_00-CODE-EXECUTOR
path: deployment/stage2_code_executor_binding.yml path: deployment/stage2_code_executor_binding.yml
schema_id: stage2_code_executor_binding.v2 schema_id: stage2_code_executor_binding.v3
binding_status: EXTERNAL_TRUST_ROOT_PENDING_LIVE_ADMISSION binding_status: EXTERNAL_TRUST_ROOT_PENDING_LIVE_ADMISSION
retained_legacy_refs: retained_legacy_refs:
- release_ops/stage2_loader.py - release_ops/stage2_loader.py
@@ -51,7 +51,7 @@ prompt_contract:
selected_context_wrapper_sha256: c43c88cad59f2e9c88d944d4997551063e133207398dee0633af53e2bc5bcab6 selected_context_wrapper_sha256: c43c88cad59f2e9c88d944d4997551063e133207398dee0633af53e2bc5bcab6
cluster_payload_wrapper_sha256: aaffb47bb21a975a13075901f3152d7a41b6e1661fa1626f42e678ba8abfdda8 cluster_payload_wrapper_sha256: aaffb47bb21a975a13075901f3152d7a41b6e1661fa1626f42e678ba8abfdda8
projection_receipt_path: manifest/s2_10_inline_prompt_projection_receipt.json projection_receipt_path: manifest/s2_10_inline_prompt_projection_receipt.json
projection_receipt_sha256: c0e388e56f52ee4fef2b825307ef41b204a80dd740cbc8f1562b30c3cd1d3696 projection_receipt_sha256: 4c95f3b3884900d1701f955e109f8927b9c5d818aa5c97623dba567faf7f61e9
canonical_source_paths: canonical_source_paths:
- prompts/P00_system_and_safety_contract.md - prompts/P00_system_and_safety_contract.md
- prompts/P10_legal_resolution_contract.md - prompts/P10_legal_resolution_contract.md
@@ -16,16 +16,16 @@
}, },
"registry_dependency": { "registry_dependency": {
"path": "manifest/case_type_registry.yml", "path": "manifest/case_type_registry.yml",
"sha256": null, "sha256": "6462217f08ced21693e8cfc812182cfc1da593d52e719e5cd11ef30409ffd00e",
"implementation_status": "NOT_IMPLEMENTED", "implementation_status": "STRUCTURAL_REGISTRY_IMPLEMENTED_LEGAL_CONTENT_PENDING",
"catalog_exact_equality_status": "UNVERIFIED" "catalog_exact_equality_status": "OFFLINE_EXACT_137_VERIFIED"
}, },
"summary": { "summary": {
"total_case_type_rows": 137, "total_case_type_rows": 137,
"named_catalog_entries": 134, "named_catalog_entries": 134,
"generic_source_rows": 3, "generic_source_rows": 3,
"implementation_status": "NOT_IMPLEMENTED", "implementation_status": "STRUCTURAL_REGISTRY_IMPLEMENTED_LEGAL_CONTENT_PENDING",
"verification_status": "UNVERIFIED" "verification_status": "OFFLINE_EXACT_137_VERIFIED"
}, },
"coverage_rows": [ "coverage_rows": [
{ {
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
{"authoring":{"path":"Stage_2_S2_00_v.2.yml","sha256":"04877f5459c8a579d793ed34ac936cc366a7e5b1c77a1230c93284036196fabe","size_bytes":367573,"unique_key_parse":"PASS"},"authoring_rewritten":false,"build_kind":"OFFLINE_AUTHORING_PROJECTION","canonical_code":{"ast_status":"PASS","code_sha256":"92f13cf3ac113c68e646fcf3b8d6bf9b8a7f41962eef809af91ebf133d50bc99","code_size_bytes":283196,"compile_status":"PASS","encoding":"UTF-8","external_python_source_ref_count":0,"external_url_count":0,"extraction_transform":"NONE","forbidden_dynamic_call_count":0,"forbidden_import_count":0,"imports":["__future__","argparse","base64","binascii","collections","contextlib","dataclasses","hashlib","httpx","io","itertools","json","math","os","pathlib","re","shutil","stat","sys","tempfile","typing","unicodedata"],"placeholder_count":0,"plaintext_secret_count":0,"yaml_pointer":"/Agent/Stages/0/tasks/0/parameters/code"},"deployment_projection":{"byte_identical_to_authoring":true,"canonical_task_semantics_sha256":"4565b8ea46aac8eab0649e4bff5c17afdc3bc0aaebe77eb6301c3bdede612d0e","path":"Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml","sha256":"04877f5459c8a579d793ed34ac936cc366a7e5b1c77a1230c93284036196fabe","size_bytes":367573},"full_code_mirrors":[{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.py","sha256":"92f13cf3ac113c68e646fcf3b8d6bf9b8a7f41962eef809af91ebf133d50bc99","size_bytes":283196},{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.txt","sha256":"92f13cf3ac113c68e646fcf3b8d6bf9b8a7f41962eef809af91ebf133d50bc99","size_bytes":283196}],"parity_status":"PASS","schema_version":"stage2_s2_00_inline_code_receipt.v2","source_of_truth":"Stage_2_S2_00_v.2.yml","task_contract":{"agent":{"name":"Stage_2_S2_00_v2","version":"1.2.0"},"mcp_servers":{"code-executor":{"type":"streamable-http","url":"https://code-executor.mcp.eroomai.com/mcp"},"localdocs":{"type":"streamable-http","url":"http://mcp-localdocs:8012/mcp"}},"stage":{"name":"S2_00","nexts":[],"prevs":[]},"task":{"code_sha256":"92f13cf3ac113c68e646fcf3b8d6bf9b8a7f41962eef809af91ebf133d50bc99","mcp":"code-executor","parameters":{"language":"python","network":"agent-network","requirements":"httpx==0.28.1","timeout":300},"task_name":"Task_S2_00_deterministic_ingress","tool_name":"run_code"},"task_procedure":{"IN":{"nexts":["Task_S2_00_deterministic_ingress"],"wait_until":[]},"OUT":{"nexts":[],"wait_until":["Task_S2_00_deterministic_ingress"]},"Task_S2_00_deterministic_ingress":{"nexts":["OUT"],"wait_until":["IN"]}}},"workflow_id":"S2_00"} {"authoring":{"path":"Stage_2_S2_00_v.2.yml","sha256":"45ca76de0c352745f8111ed036a001d053bdc9b43c1a72292d49d9b5f3bcd2c7","size_bytes":367573,"unique_key_parse":"PASS"},"authoring_rewritten":false,"build_kind":"OFFLINE_AUTHORING_PROJECTION","canonical_code":{"ast_status":"PASS","code_sha256":"b2c56fde707664903158f7d73073fc4a4913fb21234df455bdf5fe2bd1e5fafa","code_size_bytes":283196,"compile_status":"PASS","encoding":"UTF-8","external_python_source_ref_count":0,"external_url_count":0,"extraction_transform":"NONE","forbidden_dynamic_call_count":0,"forbidden_import_count":0,"imports":["__future__","argparse","base64","binascii","collections","contextlib","dataclasses","hashlib","httpx","io","itertools","json","math","os","pathlib","re","shutil","stat","sys","tempfile","typing","unicodedata"],"placeholder_count":0,"plaintext_secret_count":0,"yaml_pointer":"/Agent/Stages/0/tasks/0/parameters/code"},"deployment_projection":{"byte_identical_to_authoring":true,"canonical_task_semantics_sha256":"6905affae3adfb2e9b4f28c94f039011161c79ea88eebcd70c6cb623c597c0f4","path":"Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml","sha256":"45ca76de0c352745f8111ed036a001d053bdc9b43c1a72292d49d9b5f3bcd2c7","size_bytes":367573},"full_code_mirrors":[{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.py","sha256":"b2c56fde707664903158f7d73073fc4a4913fb21234df455bdf5fe2bd1e5fafa","size_bytes":283196},{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.txt","sha256":"b2c56fde707664903158f7d73073fc4a4913fb21234df455bdf5fe2bd1e5fafa","size_bytes":283196}],"parity_status":"PASS","schema_version":"stage2_s2_00_inline_code_receipt.v2","source_of_truth":"Stage_2_S2_00_v.2.yml","task_contract":{"agent":{"name":"Stage_2_S2_00_v2","version":"1.2.0"},"mcp_servers":{"code-executor":{"type":"streamable-http","url":"https://code-executor.mcp.eroomai.com/mcp"},"localdocs":{"type":"streamable-http","url":"http://mcp-localdocs:8012/mcp"}},"stage":{"name":"S2_00","nexts":[],"prevs":[]},"task":{"code_sha256":"b2c56fde707664903158f7d73073fc4a4913fb21234df455bdf5fe2bd1e5fafa","mcp":"code-executor","parameters":{"language":"python","network":"agent-network","requirements":"httpx==0.28.1","timeout":300},"task_name":"Task_S2_00_deterministic_ingress","tool_name":"run_code"},"task_procedure":{"IN":{"nexts":["Task_S2_00_deterministic_ingress"],"wait_until":[]},"OUT":{"nexts":[],"wait_until":["Task_S2_00_deterministic_ingress"]},"Task_S2_00_deterministic_ingress":{"nexts":["OUT"],"wait_until":["IN"]}}},"workflow_id":"S2_00"}
@@ -1 +1 @@
{"agent_contract":{"agent_name":"Stage_2_S2_10","agent_version":"1.1.0","deterministic_task_count":0,"inline_common_prompt_sha256":"a3f001acfed764b38e34f12d72f13cdbcab59a2e44150dd1d71c5bf8ba1f7099","inline_static_prompt_sha256":"894c30bedaa5f230aed117e81ef4cc06cac832928a1e29cd3ee8804cfd4dba1f","item_tokens":["{{item.selected_legal_context_json}}","{{item.cluster_case_payload_json}}"],"llm_task_count":1,"prompt_roles":["system","system","system","user"],"reduce_task_count":0,"stage_name":"S2_10","task_name":"Task_S2_10_resolve_cluster","tool_task_count":0},"authoring":{"path":"Stage_2_S2_10_v.1.yml","sha256":"0eed6f354d3539a58cc3953dd3a4eb30bb14ba515e2c90380df5830d404a8513","size_bytes":30164},"binding":{"path":"deployment/stage2_s2_10_llm_binding.yml","sha256":"b240212634c10017fa3b4d1d71fed7ab82cdb1c2da80d92ece29a6dadfb429f1"},"child_release":{"path":"manifest/s2_10_release.json","release_digest":"7f6a9ada26c5b11525fd45c3a955fa491cd6e1f66ae491596d1505ba6a749c53","sha256":"b2574efbc61aadf5882b273c18918d62ca3151b95d697bb35e539abd8594698c"},"deployment":{"byte_parity":"PASS","path":"agent_scripts/Stage_2_S2_10.yml","sha256":"0eed6f354d3539a58cc3953dd3a4eb30bb14ba515e2c90380df5830d404a8513","size_bytes":30164},"external_admission_status":"PENDING","inline_prompt_receipt":{"path":"manifest/s2_10_inline_prompt_projection_receipt.json","sha256":"c0e388e56f52ee4fef2b825307ef41b204a80dd740cbc8f1562b30c3cd1d3696","size_bytes":2659},"receipt_digest":"1df0b4482dc5d828593df60d58676ac2a545614b910030589d3c85517043c4ca","receipt_status":"OFFLINE_AGENT_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","schema":{"path":"schemas/s2_10.schema.json","sha256":"5233afde9ddb3c5868b9101816e8b3830a90b1399e3e5e89d9d7c7bf5beacaee","size_bytes":82703},"schema_version":"stage2_s2_10_agent_receipt.v2","workflow":{"path":"workflows/S2_10_domain_relief_resolution_map.yml","sha256":"f0fba48f1760cf4e233d7d698fd19090f96ffb89cabe4b2e2cae9af7c616be0f","size_bytes":15320}} {"agent_contract":{"agent_name":"Stage_2_S2_10","agent_version":"1.1.0","deterministic_task_count":0,"inline_common_prompt_sha256":"a3f001acfed764b38e34f12d72f13cdbcab59a2e44150dd1d71c5bf8ba1f7099","inline_static_prompt_sha256":"894c30bedaa5f230aed117e81ef4cc06cac832928a1e29cd3ee8804cfd4dba1f","item_tokens":["{{item.selected_legal_context_json}}","{{item.cluster_case_payload_json}}"],"llm_task_count":1,"prompt_roles":["system","system","system","user"],"reduce_task_count":0,"stage_name":"S2_10","task_name":"Task_S2_10_resolve_cluster","tool_task_count":0},"authoring":{"path":"Stage_2_S2_10_v.1.yml","sha256":"0eed6f354d3539a58cc3953dd3a4eb30bb14ba515e2c90380df5830d404a8513","size_bytes":30164},"binding":{"path":"deployment/stage2_s2_10_llm_binding.yml","sha256":"90f23bbe5b0c91374e550e9c841f708f6df51d2692f626e4a05367d4dffd9f95"},"child_release":{"path":"manifest/s2_10_release.json","release_digest":"1ad0ab3edd035d7ecafa3d148e9ae5fb7980326e4291a88caffcd04099845f5c","sha256":"284315158756d0391263dc808fcc3fff468b2e721d9d83ce7897b4666571a52f"},"deployment":{"byte_parity":"PASS","path":"agent_scripts/Stage_2_S2_10.yml","sha256":"0eed6f354d3539a58cc3953dd3a4eb30bb14ba515e2c90380df5830d404a8513","size_bytes":30164},"external_admission_status":"PENDING","inline_prompt_receipt":{"path":"manifest/s2_10_inline_prompt_projection_receipt.json","sha256":"4c95f3b3884900d1701f955e109f8927b9c5d818aa5c97623dba567faf7f61e9","size_bytes":2659},"receipt_digest":"7fb1d388ccab3bc281f93850d25515aac5f655f19f6eb29998c98ad1489b12b9","receipt_status":"OFFLINE_AGENT_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","schema":{"path":"schemas/s2_10.schema.json","sha256":"5233afde9ddb3c5868b9101816e8b3830a90b1399e3e5e89d9d7c7bf5beacaee","size_bytes":82703},"schema_version":"stage2_s2_10_agent_receipt.v2","workflow":{"path":"workflows/S2_10_domain_relief_resolution_map.yml","sha256":"f0fba48f1760cf4e233d7d698fd19090f96ffb89cabe4b2e2cae9af7c616be0f","size_bytes":15320}}
@@ -1 +1 @@
{"authoring_agent":{"path":"Stage_2_S2_10_v.1.yml","sha256":"0eed6f354d3539a58cc3953dd3a4eb30bb14ba515e2c90380df5830d404a8513","size_bytes":30164},"builder":{"path":"offline_build/build_s2_10_agent_projection.py","sha256":"f89acf6ddb307515006ed904865c05df1d38051bacb5f13e9f928142f8d72020","size_bytes":56552},"canonicalization_algorithm_id":"S2_10-NFC-LF-RTRIM-CLAUSE-PROJECTION-V1","deployment_agent":{"byte_parity":"PASS","path":"agent_scripts/Stage_2_S2_10.yml","sha256":"0eed6f354d3539a58cc3953dd3a4eb30bb14ba515e2c90380df5830d404a8513","size_bytes":30164},"inline_scalars":[{"raw_scalar_sha256":"a3f001acfed764b38e34f12d72f13cdbcab59a2e44150dd1d71c5bf8ba1f7099","role":"system","size_bytes":7184,"wrapper":"stage_2_common_cache_prefix","yaml_pointer":"/Agent/Stages/0/map_reduce/map/tasks/0/prompts/0/content"},{"raw_scalar_sha256":"894c30bedaa5f230aed117e81ef4cc06cac832928a1e29cd3ee8804cfd4dba1f","role":"system","size_bytes":12261,"wrapper":"s2_10_legal_resolution_static_prompt","yaml_pointer":"/Agent/Stages/0/map_reduce/map/tasks/0/prompts/1/content"}],"message_order":["INLINE_COMMON_SYSTEM","INLINE_STATIC_LEGAL_SYSTEM","SELECTED_CONTEXT_SYSTEM_DATA","CLUSTER_CASE_USER_DATA"],"raw_scalar_hash_algorithm_id":"SHA256-UTF8-PARSED-YAML-SCALAR-V1","receipt_digest":"56975bd356a6a8bcf6a72148be8075991c46511bce2ac18c8a2fd4c969ad425f","receipt_status":"OFFLINE_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","schema_version":"stage2_s2_10_inline_prompt_projection_receipt.v1","source_projections":[{"inline_clause_projection_sha256":"df6e88cf889c739fbfc6829b711c315e4d14ba5dd2a8bb46e1f30ef88b3a7ed5","inline_wrapper":"stage_2_common_cache_prefix","parity":"PASS","source":{"path":"prompts/P00_system_and_safety_contract.md","sha256":"df6e88cf889c739fbfc6829b711c315e4d14ba5dd2a8bb46e1f30ef88b3a7ed5","size_bytes":7124},"source_clause_projection_sha256":"df6e88cf889c739fbfc6829b711c315e4d14ba5dd2a8bb46e1f30ef88b3a7ed5"},{"hybrid_supersession_required":true,"inline_clause_projection_sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","inline_wrapper":"s2_10_legal_resolution_static_prompt","parity":"PASS","source":{"path":"prompts/P10_legal_resolution_contract.md","sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","size_bytes":8712},"source_clause_projection_sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b"}],"validation":{"dynamic_item_tokens":["{{item.selected_legal_context_json}}","{{item.cluster_case_payload_json}}"],"normalized_clause_projection":"PASS","prompt_order":"PASS","static_item_token_count":0,"static_pii_scan":"PASS","wrapper_integrity":"PASS"}} {"authoring_agent":{"path":"Stage_2_S2_10_v.1.yml","sha256":"0eed6f354d3539a58cc3953dd3a4eb30bb14ba515e2c90380df5830d404a8513","size_bytes":30164},"builder":{"path":"offline_build/build_s2_10_agent_projection.py","sha256":"4359364816c8a58eb414bafae8ccf24fc3766dc611d15f1aa09e48c8fedc8f88","size_bytes":61930},"canonicalization_algorithm_id":"S2_10-NFC-LF-RTRIM-CLAUSE-PROJECTION-V1","deployment_agent":{"byte_parity":"PASS","path":"agent_scripts/Stage_2_S2_10.yml","sha256":"0eed6f354d3539a58cc3953dd3a4eb30bb14ba515e2c90380df5830d404a8513","size_bytes":30164},"inline_scalars":[{"raw_scalar_sha256":"a3f001acfed764b38e34f12d72f13cdbcab59a2e44150dd1d71c5bf8ba1f7099","role":"system","size_bytes":7184,"wrapper":"stage_2_common_cache_prefix","yaml_pointer":"/Agent/Stages/0/map_reduce/map/tasks/0/prompts/0/content"},{"raw_scalar_sha256":"894c30bedaa5f230aed117e81ef4cc06cac832928a1e29cd3ee8804cfd4dba1f","role":"system","size_bytes":12261,"wrapper":"s2_10_legal_resolution_static_prompt","yaml_pointer":"/Agent/Stages/0/map_reduce/map/tasks/0/prompts/1/content"}],"message_order":["INLINE_COMMON_SYSTEM","INLINE_STATIC_LEGAL_SYSTEM","SELECTED_CONTEXT_SYSTEM_DATA","CLUSTER_CASE_USER_DATA"],"raw_scalar_hash_algorithm_id":"SHA256-UTF8-PARSED-YAML-SCALAR-V1","receipt_digest":"bfefc18c44815e75dd26a71209e74436e1ec59d858ebeaf704bc6d6e8c97eed9","receipt_status":"OFFLINE_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","schema_version":"stage2_s2_10_inline_prompt_projection_receipt.v1","source_projections":[{"inline_clause_projection_sha256":"df6e88cf889c739fbfc6829b711c315e4d14ba5dd2a8bb46e1f30ef88b3a7ed5","inline_wrapper":"stage_2_common_cache_prefix","parity":"PASS","source":{"path":"prompts/P00_system_and_safety_contract.md","sha256":"df6e88cf889c739fbfc6829b711c315e4d14ba5dd2a8bb46e1f30ef88b3a7ed5","size_bytes":7124},"source_clause_projection_sha256":"df6e88cf889c739fbfc6829b711c315e4d14ba5dd2a8bb46e1f30ef88b3a7ed5"},{"hybrid_supersession_required":true,"inline_clause_projection_sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","inline_wrapper":"s2_10_legal_resolution_static_prompt","parity":"PASS","source":{"path":"prompts/P10_legal_resolution_contract.md","sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","size_bytes":8712},"source_clause_projection_sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b"}],"validation":{"dynamic_item_tokens":["{{item.selected_legal_context_json}}","{{item.cluster_case_payload_json}}"],"normalized_clause_projection":"PASS","prompt_order":"PASS","static_item_token_count":0,"static_pii_scan":"PASS","wrapper_integrity":"PASS"}}
@@ -1 +1 @@
{"binding_sha256":"b240212634c10017fa3b4d1d71fed7ab82cdb1c2da80d92ece29a6dadfb429f1","finding_ids":[],"inline_prompt_projection_sha256":"c0e388e56f52ee4fef2b825307ef41b204a80dd740cbc8f1562b30c3cd1d3696","receipt_digest":"53e1a0c3ba1d944fce9e2dfedb9c99bf4d37bb826add95a040e26ce44a06e8ec","review_id":"S2_10-HYBRID-LEGAL-REVIEW-PENDING","review_scope_digest":"bc5c06f51356ed69a41cd8ffd31ed168efbcecbacd191f9841532a00920e58ef","reviewer_role":"KOREAN_ATTORNEY","s2_10_release_sha256":"b2574efbc61aadf5882b273c18918d62ca3151b95d697bb35e539abd8594698c","schema_version":"stage2_s2_10_legal_review_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null,"status":"PENDING_KOREAN_LAWYER_REVIEW"} {"binding_sha256":"90f23bbe5b0c91374e550e9c841f708f6df51d2692f626e4a05367d4dffd9f95","finding_ids":[],"inline_prompt_projection_sha256":"4c95f3b3884900d1701f955e109f8927b9c5d818aa5c97623dba567faf7f61e9","receipt_digest":"de3f73d055a1c26c976f746911623f81373233dd50cd5781e7fa6ce462b89b96","review_id":"S2_10-HYBRID-LEGAL-REVIEW-PENDING","review_scope_digest":"1b327aba6aa5bdfd81bde57a76bc1d8255c512c88bace0579e2ccc98c300dfc1","reviewer_role":"KOREAN_ATTORNEY","s2_10_release_sha256":"284315158756d0391263dc808fcc3fff468b2e721d9d83ce7897b4666571a52f","schema_version":"stage2_s2_10_legal_review_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null,"status":"PENDING_KOREAN_LAWYER_REVIEW"}
@@ -1 +1 @@
{"benchmark_id":"S2_10-HYBRID-MODEL-BENCHMARK-PENDING","binding_sha256":"b240212634c10017fa3b4d1d71fed7ab82cdb1c2da80d92ece29a6dadfb429f1","cache_telemetry_observed":null,"endpoint":"responses","latency_p95_ms":null,"model":"gpt-5.6-sol","observed_fixture_refs":[],"reasoning_effort":"xhigh","receipt_digest":"acd2043fc18695b61280b099cd388229951ccd59da6dfde024cce58fc8795fdb","s2_10_release_sha256":"b2574efbc61aadf5882b273c18918d62ca3151b95d697bb35e539abd8594698c","schema_pass_rate":null,"schema_version":"stage2_s2_10_model_benchmark_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null,"status":"PENDING_MODEL_BENCHMARK","usage_telemetry_observed":null,"verbosity":"medium"} {"benchmark_id":"S2_10-HYBRID-MODEL-BENCHMARK-PENDING","binding_sha256":"90f23bbe5b0c91374e550e9c841f708f6df51d2692f626e4a05367d4dffd9f95","cache_telemetry_observed":null,"endpoint":"responses","latency_p95_ms":null,"model":"gpt-5.6-sol","observed_fixture_refs":[],"reasoning_effort":"xhigh","receipt_digest":"8d93041ecebb0d68965b40ac1270ecbc94ebed6ed3f8462af52d7a781127b794","s2_10_release_sha256":"284315158756d0391263dc808fcc3fff468b2e721d9d83ce7897b4666571a52f","schema_pass_rate":null,"schema_version":"stage2_s2_10_model_benchmark_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null,"status":"PENDING_MODEL_BENCHMARK","usage_telemetry_observed":null,"verbosity":"medium"}
@@ -1 +1 @@
{"adapter_contract_version":"S2_10_NATIVE_RESULT_ADAPTER_V2","binding_sha256":"b240212634c10017fa3b4d1d71fed7ab82cdb1c2da80d92ece29a6dadfb429f1","capabilities":[{"activation_binding_ref":null,"capability_id":"HOST_ATOMIC_SINGLE_FLIGHT_CAS_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"AGENTBACKEND_MAP_SOURCE_ITEMS_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"AGENTBACKEND_NO_REDUCE_RESULT_ADAPTER_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_STRICT_SCHEMA_AND_REF_VALIDATOR_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_DETERMINISTIC_ID_AND_IMMUTABLE_PERSIST_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_ITEM_RETRY_CONTROLLER_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"}],"overall_status":"PENDING_EXTERNAL_PLATFORM_BINDING","parent_stage2_release_sha256":"0f21af3ddca538d9b6a5853dac23222c0b632d0e573de371a8de2709e691699d","receipt_digest":"b45a1cf57d428bf63159e8de481c0a313a5457dadb667769ccdf290806d41062","receipt_id":"S2_10-HYBRID-PLATFORM-ADAPTER-PENDING","s2_10_release_sha256":"b2574efbc61aadf5882b273c18918d62ca3151b95d697bb35e539abd8594698c","schema_version":"stage2_s2_10_platform_adapter_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null} {"adapter_contract_version":"S2_10_NATIVE_RESULT_ADAPTER_V2","binding_sha256":"90f23bbe5b0c91374e550e9c841f708f6df51d2692f626e4a05367d4dffd9f95","capabilities":[{"activation_binding_ref":null,"capability_id":"HOST_ATOMIC_SINGLE_FLIGHT_CAS_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"AGENTBACKEND_MAP_SOURCE_ITEMS_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"AGENTBACKEND_NO_REDUCE_RESULT_ADAPTER_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_STRICT_SCHEMA_AND_REF_VALIDATOR_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_DETERMINISTIC_ID_AND_IMMUTABLE_PERSIST_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_ITEM_RETRY_CONTROLLER_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"}],"overall_status":"PENDING_EXTERNAL_PLATFORM_BINDING","parent_stage2_release_sha256":"70ef317cc0c557e44619b6cd6b4ad567e02e73271a36a0bbc93b748ae3f34f92","receipt_digest":"d11458da3cd0d5d85f202ec1ee275b95b8dbe34c588e7580bd21fef211fbd050","receipt_id":"S2_10-HYBRID-PLATFORM-ADAPTER-PENDING","s2_10_release_sha256":"284315158756d0391263dc808fcc3fff468b2e721d9d83ce7897b4666571a52f","schema_version":"stage2_s2_10_platform_adapter_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"authoring":{"path":"Stage_2_S2_20.yml","sha256":"4d7642bb8b63dc37fc0ca7808676c816ba43623384b0f745f9f4af17f0f8553b","size_bytes":254364},"canonical_code":{"ast_status":"PASS","code_sha256":"140a83b71aa1007dd275c91a0aa8c837bd2d72a41136ae5bfa0c007da8dd701e","code_size_bytes":199933,"compile_status":"PASS","encoding":"UTF-8","endpoint_literals":["http://mcp-localdocs:8012/mcp","https://weaviate.eroomai.com/mcp"],"expected_parent_stage2_release_sha256":"70ef317cc0c557e44619b6cd6b4ad567e02e73271a36a0bbc93b748ae3f34f92","external_python_source_ref_count":0,"extraction_transform":"NONE","forbidden_dynamic_call_count":0,"forbidden_import_count":0,"imports":["__future__","base64","binascii","concurrent","contextlib","datetime","decimal","hashlib","httpx","io","itertools","json","pathlib","re","sys","typing","unicodedata"],"plaintext_secret_count":0,"yaml_pointer":"/Agent/Stages/0/tasks/0/parameters/code"},"deployment_projection":{"path":"Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml","sha256":"4d7642bb8b63dc37fc0ca7808676c816ba43623384b0f745f9f4af17f0f8553b","size_bytes":254364},"full_code_mirrors":["Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.py","Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.txt"],"parity_status":"PASS","schema_version":"stage2_s2_20_inline_code_receipt.v1","task_contract":{"agent":{"name":"Stage_2_S2_20","version":"1.0.0"},"authoring_rewritten":false,"canonical_task_semantics_sha256":"33367b7091a5d1bebe33c1159f00fa46f8766cee52106491d7d6c7e2c9d472b6","code_mirrors_byte_identical":true,"exactly_one_code_executor_run_code":true,"exactly_one_stage":true,"exactly_one_task":true,"expected_parent_stage2_release_sha256":"70ef317cc0c557e44619b6cd6b4ad567e02e73271a36a0bbc93b748ae3f34f92","internal_dag":"(C20||C21)->C25->C26->(C22||(C27->C28->C29))->C30->C35","mcp_servers":{"code-executor":{"type":"streamable-http","url":"https://code-executor.mcp.eroomai.com/mcp"},"localdocs":{"type":"streamable-http","url":"http://mcp-localdocs:8012/mcp"}},"projection_byte_identical_to_authoring":true,"stage":{"name":"S2_20","nexts":[],"prevs":[],"skip_confirm":true},"task":{"code_sha256":"140a83b71aa1007dd275c91a0aa8c837bd2d72a41136ae5bfa0c007da8dd701e","mcp":"code-executor","parameters":{"language":"python","network":"agent-network","requirements":"httpx==0.28.1","timeout":300},"task_name":"Task_S2_20_deterministic_relief_plan","tool_name":"run_code"},"task_procedure":{"IN":{"nexts":["Task_S2_20_deterministic_relief_plan"],"wait_until":[]},"OUT":{"nexts":[],"wait_until":["Task_S2_20_deterministic_relief_plan"]},"Task_S2_20_deterministic_relief_plan":{"nexts":["OUT"],"wait_until":["IN"]}}},"workflow_id":"S2_20"}
@@ -0,0 +1,117 @@
[
"corpus/build_receipt.json",
"corpus/chunk_manifest.jsonl",
"corpus/source_manifest.json",
"corpus/weaviate_collection.schema.json",
"law_values/court_fee_values.yml",
"law_values/general_law_values.yml",
"manifest/authority_release.json",
"manifest/case_type_coverage.json",
"manifest/case_type_registry.yml",
"manifest/case_type_rule_registry.yml",
"manifest/corpus_release.json",
"manifest/s2_20_parent_member_paths.json",
"migration/actio_assets_receipt.json",
"migration/legacy_asset_disposition.yml",
"offline_build/build_authority_law_value_release.py",
"offline_build/build_authority_law_value_release.txt",
"offline_build/build_corpus_snapshot.py",
"offline_build/build_corpus_snapshot.txt",
"offline_build/build_release_manifests.py",
"offline_build/build_release_manifests.txt",
"offline_build/build_s2_20_inline_projection.py",
"offline_build/build_s2_20_inline_projection.txt",
"offline_build/compile_case_type_registry.py",
"offline_build/compile_case_type_registry.txt",
"offline_build/compile_relief_rule_projection.py",
"offline_build/compile_relief_rule_projection.txt",
"registry/binding/binding_signature_projection.yml",
"registry/calculations/CE-01_interest_delay.yml",
"registry/calculations/CE-02_allocation_setoff_balance.yml",
"registry/calculations/CE-03_limitation_deadline.yml",
"registry/calculations/CE-04_valuation.yml",
"registry/calculations/CE-05_personal_injury.yml",
"registry/calculations/CE-06_construction_defect.yml",
"registry/calculations/CE-07_lease_use_gain.yml",
"registry/calculations/CE-08_inheritance_reserved_share.yml",
"registry/calculations/CE-09_wage_severance.yml",
"registry/calculations/CE-10_actio_insolvency_value.yml",
"registry/calculations/CE-11_distribution_share_division.yml",
"registry/calculations/CE-12_insurance.yml",
"registry/calculations/CE-13_court_value_cost.yml",
"registry/calculations/CE-R1_ip_damage.yml",
"registry/calculations/CE-R2_org_liquidation.yml",
"registry/calculations/CE-R3_transport_maritime.yml",
"registry/calculations/CE-R4_financial_instrument.yml",
"registry/calculations/calculation_activation_registry.yml",
"registry/corpus/requirement_fact_scope.yml",
"registry/drafting/case_type_relief_rules.yml",
"registry/drafting/counter_performance_rules.yml",
"registry/drafting/forbidden_relief_rules.yml",
"registry/drafting/procedural_declaration_rules.yml",
"registry/party/party_set_rules.yml",
"registry/planning/option_disposition_policy.yml",
"registry/regression/finding_fixture_map.yml",
"registry/review/review_policy_registry.yml",
"registry/temporal/inheritance_reserved_share.yml",
"release_ops/canary_rollback.py",
"release_ops/canary_rollback.txt",
"release_ops/release_validator.py",
"release_ops/release_validator.txt",
"renderers/R01_money_payment.yml",
"renderers/R02_delivery_possession.yml",
"renderers/R03_declaration_registry.yml",
"renderers/R04_special_nonmoney_performance.yml",
"renderers/R05_declaratory.yml",
"renderers/R06_constitutive_judgment_challenge.yml",
"routing/actio_pauliana_mortgage_route.yml",
"routing/actio_pauliana_route_registry.yml",
"runtime/authority/authority_preflight.py",
"runtime/authority/authority_preflight.txt",
"runtime/binding_signature_projection.py",
"runtime/binding_signature_projection.txt",
"runtime/c25_case_type_bind.py",
"runtime/c25_case_type_bind.txt",
"runtime/c26_rule_branch_bind.py",
"runtime/c26_rule_branch_bind.txt",
"runtime/c27_query_plan.py",
"runtime/c27_query_plan.txt",
"runtime/c28_weaviate_retrieve.py",
"runtime/c28_weaviate_retrieve.txt",
"runtime/c29_pack_verify.py",
"runtime/c29_pack_verify.txt",
"runtime/calculators/registry_engine.py",
"runtime/calculators/registry_engine.txt",
"schemas/binding_retrieval.schema.json",
"schemas/calculation.schema.json",
"schemas/deployment.schema.json",
"schemas/domain_verdict.schema.json",
"schemas/relief_plan.schema.json",
"tests/fixtures/s2_20/actio_route_cap_matrix.json",
"tests/fixtures/s2_20/calculation_temporal_boundaries.json",
"tests/fixtures/s2_20/case_type_rule_binding_matrix.json",
"tests/fixtures/s2_20/case_type_zero_multi_hash_mutations.json",
"tests/fixtures/s2_20/minimal_supported_portfolio.json",
"tests/fixtures/s2_20/mixed_option_dispositions.json",
"tests/fixtures/s2_20/plan_publish_barrier_failure.json",
"tests/fixtures/s2_20/regression_manifest.json",
"tests/fixtures/s2_20/retrieval_replay_injection.json",
"tests/s2_20/test_agent_and_inline_parity.py",
"tests/s2_20/test_agent_and_inline_parity.txt",
"tests/s2_20/test_calculation_and_reports.py",
"tests/s2_20/test_calculation_and_reports.txt",
"tests/s2_20/test_inline_output_schema.py",
"tests/s2_20/test_inline_output_schema.txt",
"tests/s2_20/test_offline_compilers.py",
"tests/s2_20/test_offline_compilers.txt",
"tests/s2_20/test_option_group_and_binding.py",
"tests/s2_20/test_option_group_and_binding.txt",
"tests/s2_20/test_plan_publish_and_release.py",
"tests/s2_20/test_plan_publish_and_release.txt",
"tests/s2_20/test_regression_manifest_closure.py",
"tests/s2_20/test_regression_manifest_closure.txt",
"tests/s2_20/test_retrieval_and_pack.py",
"tests/s2_20/test_retrieval_and_pack.txt",
"validators/actio_value_compensation_invariants.yml",
"workflows/S2_20_canonical_relief_plan_reduce.yml"
]
@@ -0,0 +1 @@
{"admission_status":"PENDING","backend_capability_receipt_sha256":"PENDING_SEQUENTIAL_BIND","executor_binding_sha256":"d1e16314e81faea5e6a8dd826e81b9ae01e0536923480ba4fb710a4959385a7c","parent_release_sha256":"70ef317cc0c557e44619b6cd6b4ad567e02e73271a36a0bbc93b748ae3f34f92","present_deterministic_stage_ids":["S2_00","S2_20"],"schema_version":"stage2_deterministic_admission_receipt.v1","signature":"PENDING_EXTERNAL_SIGNATURE","signature_verification_status":"PENDING_EXTERNAL_SIGNATURE","signed_payload_sha256":"PENDING_SEQUENTIAL_BIND","stage_receipts":[{"asset_id":"RECEIPT-S2_00-INLINE-CODE","binding_status":"BOUND","path":"manifest/s2_00_inline_code_receipt.json","schema_id":"stage2_s2_00_inline_code_receipt.v2","sha256":"1a0044a0f1e0fec13a5d4870df6147b8c4c671d843d4b634b4249442fdcfdfb8"},{"asset_id":"RECEIPT-S2_20-INLINE-CODE","binding_status":"BOUND","path":"manifest/s2_20_inline_code_receipt.json","schema_id":"stage2_s2_20_inline_code_receipt.v1","sha256":"3693ce7d99d64458f2dbf80f9535aad55ad1dec22ab95898f3c05b204afb801b"}]}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,186 @@
{
"schema_version": "stage2_actio_migration_receipt.v1",
"receipt_id": "S2-ACTIO-MIGRATION-PENDING",
"status": "PENDING_KOREAN_LAWYER_AND_AUTHORITY_REVIEW",
"execution_eligible": false,
"path_base": "Default_Agent/Stage_2_Clean",
"source_root_ref": "../../사해행위취소소송관련기존자산",
"expected_source_count": 10,
"observed_source_count": 10,
"completed_migration_count": 0,
"rows": [
{
"source_asset_id": "ACTIO-MIGRATION-SOURCE-01",
"raw_path": "../../사해행위취소소송관련기존자산/actio_pauliana_calc_v1.txt",
"raw_basename_utf8_hex": "616374696f5f7061756c69616e615f63616c635f76312e747874",
"nfc_display_name": "actio_pauliana_calc_v1.txt",
"raw_sha256": "57dd4a10a982c4b344239f37dcdeab9a388f2dd77ba41bdf89698d2bf8d5ba27",
"byte_length": 22913,
"extracted_propositions": [],
"official_authority_checks": [],
"migration_disposition": null,
"correction_or_drop_reason": "PENDING_PROPOSITION_EXTRACTION_AND_OFFICIAL_AUTHORITY_COMPARISON",
"canonical_targets": [],
"canonical_target_sha256s": [],
"reviewer_id": null,
"review_status": "PENDING_KOREAN_LAWYER_REVIEW"
},
{
"source_asset_id": "ACTIO-MIGRATION-SOURCE-02",
"raw_path": "../../사해행위취소소송관련기존자산/actio_pauliana_calc_v3_mini_v1.json",
"raw_basename_utf8_hex": "616374696f5f7061756c69616e615f63616c635f76335f6d696e695f76312e6a736f6e",
"nfc_display_name": "actio_pauliana_calc_v3_mini_v1.json",
"raw_sha256": "551e0965de9061181beb9a019188fe54ced2b6ef74f979e2cd79eb4edadf1f09",
"byte_length": 11803,
"extracted_propositions": [],
"official_authority_checks": [],
"migration_disposition": null,
"correction_or_drop_reason": "PENDING_PROPOSITION_EXTRACTION_AND_OFFICIAL_AUTHORITY_COMPARISON",
"canonical_targets": [],
"canonical_target_sha256s": [],
"reviewer_id": null,
"review_status": "PENDING_KOREAN_LAWYER_REVIEW"
},
{
"source_asset_id": "ACTIO-MIGRATION-SOURCE-03",
"raw_path": "../../사해행위취소소송관련기존자산/actio_pauliana_case_type_determination.csv",
"raw_basename_utf8_hex": "616374696f5f7061756c69616e615f636173655f747970655f64657465726d696e6174696f6e2e637376",
"nfc_display_name": "actio_pauliana_case_type_determination.csv",
"raw_sha256": "fed50482bff95e8644c912d8e03ccbfe1ea74844a15cf25826fa2d8a681e3786",
"byte_length": 1605,
"extracted_propositions": [],
"official_authority_checks": [],
"migration_disposition": null,
"correction_or_drop_reason": "PENDING_PROPOSITION_EXTRACTION_AND_OFFICIAL_AUTHORITY_COMPARISON",
"canonical_targets": [],
"canonical_target_sha256s": [],
"reviewer_id": null,
"review_status": "PENDING_KOREAN_LAWYER_REVIEW"
},
{
"source_asset_id": "ACTIO-MIGRATION-SOURCE-04",
"raw_path": "../../사해행위취소소송관련기존자산/actio_pauliana_mortgage_actio_calc_both_v1.txt",
"raw_basename_utf8_hex": "616374696f5f7061756c69616e615f6d6f7274676167655f616374696f5f63616c635f626f74685f76312e747874",
"nfc_display_name": "actio_pauliana_mortgage_actio_calc_both_v1.txt",
"raw_sha256": "40405566257145b34c3e539861cf472aa5dc3c73f4f983136da58605eb352e83",
"byte_length": 11138,
"extracted_propositions": [],
"official_authority_checks": [],
"migration_disposition": null,
"correction_or_drop_reason": "PENDING_PROPOSITION_EXTRACTION_AND_OFFICIAL_AUTHORITY_COMPARISON",
"canonical_targets": [],
"canonical_target_sha256s": [],
"reviewer_id": null,
"review_status": "PENDING_KOREAN_LAWYER_REVIEW"
},
{
"source_asset_id": "ACTIO-MIGRATION-SOURCE-05",
"raw_path": "../../사해행위취소소송관련기존자산/actio_pauliana_mortgage_v1.txt",
"raw_basename_utf8_hex": "616374696f5f7061756c69616e615f6d6f7274676167655f76312e747874",
"nfc_display_name": "actio_pauliana_mortgage_v1.txt",
"raw_sha256": "91b8949dfed4bbe8a9553eef0775a39d1967e0c86432e6f8c13f6e8381befdb4",
"byte_length": 21449,
"extracted_propositions": [],
"official_authority_checks": [],
"migration_disposition": null,
"correction_or_drop_reason": "PENDING_PROPOSITION_EXTRACTION_AND_OFFICIAL_AUTHORITY_COMPARISON",
"canonical_targets": [],
"canonical_target_sha256s": [],
"reviewer_id": null,
"review_status": "PENDING_KOREAN_LAWYER_REVIEW"
},
{
"source_asset_id": "ACTIO-MIGRATION-SOURCE-06",
"raw_path": "../../사해행위취소소송관련기존자산/mortgage_fraudulent_act_module_v1_mini_v1.json",
"raw_basename_utf8_hex": "6d6f7274676167655f6672617564756c656e745f6163745f6d6f64756c655f76315f6d696e695f76312e6a736f6e",
"nfc_display_name": "mortgage_fraudulent_act_module_v1_mini_v1.json",
"raw_sha256": "ee5a29a871a82ec09ddf4e7cf5ea31be0e09314a178ba4de716bef427a0c218e",
"byte_length": 12141,
"extracted_propositions": [],
"official_authority_checks": [],
"migration_disposition": null,
"correction_or_drop_reason": "PENDING_PROPOSITION_EXTRACTION_AND_OFFICIAL_AUTHORITY_COMPARISON",
"canonical_targets": [],
"canonical_target_sha256s": [],
"reviewer_id": null,
"review_status": "PENDING_KOREAN_LAWYER_REVIEW"
},
{
"source_asset_id": "ACTIO-MIGRATION-SOURCE-07",
"raw_path": "../../사해행위취소소송관련기존자산/부담부_부동산소유권이전_사해행위_가액배상_모듈.md",
"raw_basename_utf8_hex": "e18487e185aee18483e185a1e186b7e18487e185ae5fe18487e185aee18483e185a9e186bce18489e185a1e186abe18489e185a9e1848be185b2e18480e185afe186abe1848be185b5e1848ce185a5e186ab5fe18489e185a1e18492e185a2e18492e185a2e186bce1848be185b15fe18480e185a1e1848be185a2e186a8e18487e185a2e18489e185a1e186bc5fe18486e185a9e18483e185b2e186af2e6d64",
"nfc_display_name": "부담부_부동산소유권이전_사해행위_가액배상_모듈.md",
"raw_sha256": "424b3d34b30e4c2822d79ab7ec6a3b0645213a743141b72da021365c3f8553ac",
"byte_length": 15743,
"extracted_propositions": [],
"official_authority_checks": [],
"migration_disposition": null,
"correction_or_drop_reason": "PENDING_PROPOSITION_EXTRACTION_AND_OFFICIAL_AUTHORITY_COMPARISON",
"canonical_targets": [],
"canonical_target_sha256s": [],
"reviewer_id": null,
"review_status": "PENDING_KOREAN_LAWYER_REVIEW"
},
{
"source_asset_id": "ACTIO-MIGRATION-SOURCE-08",
"raw_path": "../../사해행위취소소송관련기존자산/사해행위취소_가액배상_최종화게이트_모듈.md",
"raw_basename_utf8_hex": "e18489e185a1e18492e185a2e18492e185a2e186bce1848be185b1e1848ee185b1e18489e185a95fe18480e185a1e1848be185a2e186a8e18487e185a2e18489e185a1e186bc5fe1848ee185ace1848ce185a9e186bce18492e185aae18480e185a6e1848be185b5e18490e185b35fe18486e185a9e18483e185b2e186af2e6d64",
"nfc_display_name": "사해행위취소_가액배상_최종화게이트_모듈.md",
"raw_sha256": "794e7133e3b06d9e38314cc06aad5320faf5269870424e27fcdb2db1dff58478",
"byte_length": 15011,
"extracted_propositions": [],
"official_authority_checks": [],
"migration_disposition": null,
"correction_or_drop_reason": "PENDING_PROPOSITION_EXTRACTION_AND_OFFICIAL_AUTHORITY_COMPARISON",
"canonical_targets": [],
"canonical_target_sha256s": [],
"reviewer_id": null,
"review_status": "PENDING_KOREAN_LAWYER_REVIEW"
},
{
"source_asset_id": "ACTIO-MIGRATION-SOURCE-09",
"raw_path": "../../사해행위취소소송관련기존자산/사해행위취소_피보전채권번들_검증_모듈.md",
"raw_basename_utf8_hex": "e18489e185a1e18492e185a2e18492e185a2e186bce1848be185b1e1848ee185b1e18489e185a95fe18491e185b5e18487e185a9e1848ce185a5e186abe1848ee185a2e18480e185afe186abe18487e185a5e186abe18483e185b3e186af5fe18480e185a5e186b7e1848ce185b3e186bc5fe18486e185a9e18483e185b2e186af2e6d64",
"nfc_display_name": "사해행위취소_피보전채권번들_검증_모듈.md",
"raw_sha256": "7b91276b363c8a99d5c4cb2ce2a5154b7003ee2dc081fa8e4db83dd0e5c0275b",
"byte_length": 13130,
"extracted_propositions": [],
"official_authority_checks": [],
"migration_disposition": null,
"correction_or_drop_reason": "PENDING_PROPOSITION_EXTRACTION_AND_OFFICIAL_AUTHORITY_COMPARISON",
"canonical_targets": [],
"canonical_target_sha256s": [],
"reviewer_id": null,
"review_status": "PENDING_KOREAN_LAWYER_REVIEW"
},
{
"source_asset_id": "ACTIO-MIGRATION-SOURCE-10",
"raw_path": "../../사해행위취소소송관련기존자산/사해행위취소_항변통합_모듈.md",
"raw_basename_utf8_hex": "e18489e185a1e18492e185a2e18492e185a2e186bce1848be185b1e1848ee185b1e18489e185a95fe18492e185a1e186bce18487e185a7e186abe18490e185a9e186bce18492e185a1e186b85fe18486e185a9e18483e185b2e186af2e6d64",
"nfc_display_name": "사해행위취소_항변통합_모듈.md",
"raw_sha256": "be5e43c5b16758ae2f6e02d37d1735bfb871c46ab014bc81f3ae197463a569fc",
"byte_length": 13211,
"extracted_propositions": [],
"official_authority_checks": [],
"migration_disposition": null,
"correction_or_drop_reason": "PENDING_PROPOSITION_EXTRACTION_AND_OFFICIAL_AUTHORITY_COMPARISON",
"canonical_targets": [],
"canonical_target_sha256s": [],
"reviewer_id": null,
"review_status": "PENDING_KOREAN_LAWYER_REVIEW"
}
],
"unresolved_reason_codes": [
"PROPOSITION_EXTRACTION_NOT_COMPLETED",
"OFFICIAL_AUTHORITY_COMPARISON_NOT_COMPLETED",
"CANONICAL_TARGETS_NOT_BOUND",
"KOREAN_LAWYER_REVIEW_NOT_COMPLETED"
],
"guards": {
"legacy_source_runtime_load_forbidden": true,
"legacy_source_fallback_forbidden": true,
"unverified_proposition_migration_forbidden": true,
"source_hash_mutation_forbidden": true,
"pending_receipt_is_not_approval": true
}
}
@@ -0,0 +1,32 @@
{
"schema_version": "stage2_legacy_asset_disposition.v1",
"registry_id": "S2-LEGACY-16-DISPOSITION-PENDING",
"status": "PENDING_SOURCE_DISCOVERY_AND_REVIEW",
"execution_eligible": false,
"audit_is_runtime_dependency": false,
"path_base": "Default_Agent/Stage_2_Clean",
"expected_source_root_ref": "../../../../Default_Agent_updated/Modules_and_New_Rules",
"expected_row_count": 16,
"completed_disposition_count": 0,
"allowed_final_dispositions": ["MIGRATE", "REBUILD", "DROP"],
"rows": [
{"legacy_asset_id":"LEGACY-01","expected_basename_nfc":"금전채권_이행기_시효_지연손해금_작성규칙.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-02","expected_basename_nfc":"상호속용_영업양수인_책임_작성규칙.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-03","expected_basename_nfc":"법정변제충당_담보채무_지분말소_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-04","expected_basename_nfc":"담보권실행경매_공신력_항변_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-05","expected_basename_nfc":"미등기건물_토지사용_부당이득_부진정연대_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-06","expected_basename_nfc":"차임감정표_법률상_기준선택_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-07","expected_basename_nfc":"임대차보증금_부당이득_배제검토_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-08","expected_basename_nfc":"부담부_부동산소유권이전_사해행위_가액배상_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-09","expected_basename_nfc":"사해행위취소_피보전채권번들_검증_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-10","expected_basename_nfc":"사해행위취소_항변통합_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-11","expected_basename_nfc":"사해행위취소_가액배상_최종화게이트_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-12","expected_basename_nfc":"유치권소멸_건물인도_부당이득반환_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-13","expected_basename_nfc":"상속포기_배우자단독상속_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-14","expected_basename_nfc":"통지_도달_법률효과_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-15","expected_basename_nfc":"별지목록_등기부_asset_alias_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"},
{"legacy_asset_id":"LEGACY-16","expected_basename_nfc":"피고답변서_항변추출_모듈.md","source_presence_status":"PENDING_SOURCE_DISCOVERY","raw_path":null,"raw_sha256":null,"disposition":null,"canonical_targets":[],"reason_code":"PENDING_SOURCE_AND_SEMANTIC_REVIEW","review_status":"PENDING"}
],
"unresolved_reason_codes": ["LEGACY_SOURCE_ROOT_NOT_OBSERVED","DISPOSITION_AUDIT_NOT_COMPLETED","CANONICAL_TARGETS_NOT_BOUND","KOREAN_LAWYER_REVIEW_NOT_COMPLETED"],
"guards": {"runtime_load_forbidden":true,"runtime_fallback_forbidden":true,"basename_only_merge_forbidden":true,"pending_row_is_not_disposition":true,"audit_is_non_blocking_until_unique_required_proposition_found":true}
}
@@ -0,0 +1,196 @@
#!/usr/bin/env python3
"""Build or check the offline authority/law-value release inventory.
This program performs local, explicit-path hashing only. It never retrieves
an authority, verifies a legal proposition, signs a release, or promotes a
release beyond the honest ``DEV_UNAVAILABLE`` state.
"""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import re
from typing import Any, Mapping, Sequence
REGISTRY_REF = "registry/authority/authority_registry.yml"
REGISTRY_SCHEMA_VERSION = "stage2.authority_registry.v1"
SCHEMA_VERSION_PATTERN = re.compile(
r'^schema_version:\s*["\']?([^"\'\s#]+)["\']?\s*(?:#.*)?$'
)
class AuthorityReleaseBuildError(ValueError):
"""Raised when an explicit local release input is invalid."""
def _output_bytes(payload: Mapping[str, Any]) -> bytes:
return (json.dumps(payload, ensure_ascii=False, indent=2) + "\n").encode("utf-8")
def _sha256(raw: bytes) -> str:
return hashlib.sha256(raw).hexdigest()
def _contained_file(root: Path, relative_path: str) -> Path:
if not isinstance(relative_path, str) or not relative_path:
raise AuthorityReleaseBuildError("AUTHORITY_ASSET_PATH_INVALID")
root = root.resolve()
target = (root / relative_path).resolve()
if root not in target.parents or not target.is_file():
raise AuthorityReleaseBuildError(f"AUTHORITY_ASSET_UNAVAILABLE:{relative_path}")
return target
def _registry_schema_version(raw: bytes) -> str:
text = raw.decode("utf-8", errors="strict")
for line in text.splitlines():
match = SCHEMA_VERSION_PATTERN.fullmatch(line.strip())
if match:
return match.group(1)
raise AuthorityReleaseBuildError("AUTHORITY_REGISTRY_SCHEMA_VERSION_MISSING")
def _inventory_rows(root: Path, spec: Sequence[Mapping[str, Any]]) -> list[dict[str, Any]]:
rows: list[dict[str, Any]] = []
seen: set[str] = set()
for item in spec:
if not isinstance(item, Mapping):
raise AuthorityReleaseBuildError("AUTHORITY_SPEC_ROW_INVALID")
relative_path = item.get("path")
if not isinstance(relative_path, str) or not relative_path:
raise AuthorityReleaseBuildError("AUTHORITY_SPEC_PATH_INVALID")
if relative_path in seen:
raise AuthorityReleaseBuildError(f"AUTHORITY_SPEC_DUPLICATE_PATH:{relative_path}")
seen.add(relative_path)
target = _contained_file(root, relative_path)
raw = target.read_bytes()
approval_status = item.get("approval_status", "PENDING_LEGAL_CONTENT")
if not isinstance(approval_status, str) or not approval_status:
raise AuthorityReleaseBuildError(
f"AUTHORITY_SPEC_APPROVAL_STATUS_INVALID:{relative_path}"
)
rows.append(
{
"path": relative_path,
"sha256": _sha256(raw),
"size_bytes": len(raw),
"approval_status": approval_status,
}
)
return sorted(rows, key=lambda row: row["path"])
def build_release(root: Path, spec: Sequence[Mapping[str, Any]]) -> dict[str, Any]:
"""Return the current canonical, unsigned pending release shape.
Explicit inventory rows are hashed and recorded as captures, but their
mere presence cannot establish official-source provenance, legal review,
a detached signature, or live admission. The result therefore remains a
non-executable development release.
"""
root = root.resolve()
registry_path = _contained_file(root, REGISTRY_REF)
registry_raw = registry_path.read_bytes()
registry_schema_version = _registry_schema_version(registry_raw)
if registry_schema_version != REGISTRY_SCHEMA_VERSION:
raise AuthorityReleaseBuildError(
f"AUTHORITY_REGISTRY_SCHEMA_VERSION_INVALID:{registry_schema_version}"
)
captures = _inventory_rows(root, spec)
return {
"schema_version": "stage2.authority_release.v1",
"release_id": "AUTHORITY-RELEASE-DEV-UNAVAILABLE",
"status": "DEV_UNAVAILABLE",
"release_class": "DEV_FIXTURE_RELEASE",
"sealed": False,
"signed": False,
"executable": False,
"created_at": None,
"as_of": None,
"registry": {
"path": REGISTRY_REF,
"sha256": _sha256(registry_raw),
"required_status": "VERIFIED",
"schema_version": REGISTRY_SCHEMA_VERSION,
},
"captures": captures,
"law_value_dependencies": [],
"selected_common_authority_ids": [],
"signature": None,
"unresolved": [
"OFFICIAL_AUTHORITY_NOT_CAPTURED",
"AUTHORITY_REGISTRY_NOT_LEGALLY_VERIFIED",
"RELEASE_HASH_SET_NOT_SEALED",
"RELEASE_SIGNATURE_MISSING",
],
"guards": {
"glob_selection_forbidden": True,
"unlisted_capture_ingest_forbidden": True,
"unverified_registry_row_use_forbidden": True,
"production_or_canary_use_forbidden": True,
},
"hash_binding_status": "DEV_HASH_BOUND_UNSIGNED",
}
def write_or_check(output: Path, expected: bytes, *, check: bool) -> int:
"""Write expected bytes, or perform read-only exact-byte drift detection."""
digest = _sha256(expected)
if check:
if not output.is_file():
print(
json.dumps(
{"status": "DRIFT", "reason": "OUTPUT_MISSING", "output": str(output)},
sort_keys=True,
)
)
return 1
actual = output.read_bytes()
if actual != expected:
print(
json.dumps(
{
"status": "DRIFT",
"reason": "OUTPUT_BYTES_MISMATCH",
"actual_sha256": _sha256(actual),
"expected_sha256": digest,
"output": str(output),
},
sort_keys=True,
)
)
return 1
print(json.dumps({"status": "PASS", "output_sha256": digest}, sort_keys=True))
return 0
output.parent.mkdir(parents=True, exist_ok=True)
output.write_bytes(expected)
print(json.dumps({"status": "BUILT", "output_sha256": digest}, sort_keys=True))
return 0
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("root", type=Path)
parser.add_argument("spec", type=Path, help="JSON list of {path, approval_status}")
parser.add_argument("output", type=Path)
parser.add_argument(
"--check",
action="store_true",
help="read-only exact-byte drift check; never creates or modifies output",
)
args = parser.parse_args()
spec = json.loads(args.spec.read_text(encoding="utf-8"))
if not isinstance(spec, list):
raise AuthorityReleaseBuildError("AUTHORITY_SPEC_LIST_REQUIRED")
payload = build_release(args.root, spec)
return write_or_check(args.output, _output_bytes(payload), check=args.check)
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,196 @@
#!/usr/bin/env python3
"""Build or check the offline authority/law-value release inventory.
This program performs local, explicit-path hashing only. It never retrieves
an authority, verifies a legal proposition, signs a release, or promotes a
release beyond the honest ``DEV_UNAVAILABLE`` state.
"""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import re
from typing import Any, Mapping, Sequence
REGISTRY_REF = "registry/authority/authority_registry.yml"
REGISTRY_SCHEMA_VERSION = "stage2.authority_registry.v1"
SCHEMA_VERSION_PATTERN = re.compile(
r'^schema_version:\s*["\']?([^"\'\s#]+)["\']?\s*(?:#.*)?$'
)
class AuthorityReleaseBuildError(ValueError):
"""Raised when an explicit local release input is invalid."""
def _output_bytes(payload: Mapping[str, Any]) -> bytes:
return (json.dumps(payload, ensure_ascii=False, indent=2) + "\n").encode("utf-8")
def _sha256(raw: bytes) -> str:
return hashlib.sha256(raw).hexdigest()
def _contained_file(root: Path, relative_path: str) -> Path:
if not isinstance(relative_path, str) or not relative_path:
raise AuthorityReleaseBuildError("AUTHORITY_ASSET_PATH_INVALID")
root = root.resolve()
target = (root / relative_path).resolve()
if root not in target.parents or not target.is_file():
raise AuthorityReleaseBuildError(f"AUTHORITY_ASSET_UNAVAILABLE:{relative_path}")
return target
def _registry_schema_version(raw: bytes) -> str:
text = raw.decode("utf-8", errors="strict")
for line in text.splitlines():
match = SCHEMA_VERSION_PATTERN.fullmatch(line.strip())
if match:
return match.group(1)
raise AuthorityReleaseBuildError("AUTHORITY_REGISTRY_SCHEMA_VERSION_MISSING")
def _inventory_rows(root: Path, spec: Sequence[Mapping[str, Any]]) -> list[dict[str, Any]]:
rows: list[dict[str, Any]] = []
seen: set[str] = set()
for item in spec:
if not isinstance(item, Mapping):
raise AuthorityReleaseBuildError("AUTHORITY_SPEC_ROW_INVALID")
relative_path = item.get("path")
if not isinstance(relative_path, str) or not relative_path:
raise AuthorityReleaseBuildError("AUTHORITY_SPEC_PATH_INVALID")
if relative_path in seen:
raise AuthorityReleaseBuildError(f"AUTHORITY_SPEC_DUPLICATE_PATH:{relative_path}")
seen.add(relative_path)
target = _contained_file(root, relative_path)
raw = target.read_bytes()
approval_status = item.get("approval_status", "PENDING_LEGAL_CONTENT")
if not isinstance(approval_status, str) or not approval_status:
raise AuthorityReleaseBuildError(
f"AUTHORITY_SPEC_APPROVAL_STATUS_INVALID:{relative_path}"
)
rows.append(
{
"path": relative_path,
"sha256": _sha256(raw),
"size_bytes": len(raw),
"approval_status": approval_status,
}
)
return sorted(rows, key=lambda row: row["path"])
def build_release(root: Path, spec: Sequence[Mapping[str, Any]]) -> dict[str, Any]:
"""Return the current canonical, unsigned pending release shape.
Explicit inventory rows are hashed and recorded as captures, but their
mere presence cannot establish official-source provenance, legal review,
a detached signature, or live admission. The result therefore remains a
non-executable development release.
"""
root = root.resolve()
registry_path = _contained_file(root, REGISTRY_REF)
registry_raw = registry_path.read_bytes()
registry_schema_version = _registry_schema_version(registry_raw)
if registry_schema_version != REGISTRY_SCHEMA_VERSION:
raise AuthorityReleaseBuildError(
f"AUTHORITY_REGISTRY_SCHEMA_VERSION_INVALID:{registry_schema_version}"
)
captures = _inventory_rows(root, spec)
return {
"schema_version": "stage2.authority_release.v1",
"release_id": "AUTHORITY-RELEASE-DEV-UNAVAILABLE",
"status": "DEV_UNAVAILABLE",
"release_class": "DEV_FIXTURE_RELEASE",
"sealed": False,
"signed": False,
"executable": False,
"created_at": None,
"as_of": None,
"registry": {
"path": REGISTRY_REF,
"sha256": _sha256(registry_raw),
"required_status": "VERIFIED",
"schema_version": REGISTRY_SCHEMA_VERSION,
},
"captures": captures,
"law_value_dependencies": [],
"selected_common_authority_ids": [],
"signature": None,
"unresolved": [
"OFFICIAL_AUTHORITY_NOT_CAPTURED",
"AUTHORITY_REGISTRY_NOT_LEGALLY_VERIFIED",
"RELEASE_HASH_SET_NOT_SEALED",
"RELEASE_SIGNATURE_MISSING",
],
"guards": {
"glob_selection_forbidden": True,
"unlisted_capture_ingest_forbidden": True,
"unverified_registry_row_use_forbidden": True,
"production_or_canary_use_forbidden": True,
},
"hash_binding_status": "DEV_HASH_BOUND_UNSIGNED",
}
def write_or_check(output: Path, expected: bytes, *, check: bool) -> int:
"""Write expected bytes, or perform read-only exact-byte drift detection."""
digest = _sha256(expected)
if check:
if not output.is_file():
print(
json.dumps(
{"status": "DRIFT", "reason": "OUTPUT_MISSING", "output": str(output)},
sort_keys=True,
)
)
return 1
actual = output.read_bytes()
if actual != expected:
print(
json.dumps(
{
"status": "DRIFT",
"reason": "OUTPUT_BYTES_MISMATCH",
"actual_sha256": _sha256(actual),
"expected_sha256": digest,
"output": str(output),
},
sort_keys=True,
)
)
return 1
print(json.dumps({"status": "PASS", "output_sha256": digest}, sort_keys=True))
return 0
output.parent.mkdir(parents=True, exist_ok=True)
output.write_bytes(expected)
print(json.dumps({"status": "BUILT", "output_sha256": digest}, sort_keys=True))
return 0
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("root", type=Path)
parser.add_argument("spec", type=Path, help="JSON list of {path, approval_status}")
parser.add_argument("output", type=Path)
parser.add_argument(
"--check",
action="store_true",
help="read-only exact-byte drift check; never creates or modifies output",
)
args = parser.parse_args()
spec = json.loads(args.spec.read_text(encoding="utf-8"))
if not isinstance(spec, list):
raise AuthorityReleaseBuildError("AUTHORITY_SPEC_LIST_REQUIRED")
payload = build_release(args.root, spec)
return write_or_check(args.output, _output_bytes(payload), check=args.check)
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,273 @@
#!/usr/bin/env python3
"""Create a deterministic, schema-conformant corpus build receipt."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import re
from typing import Any
DEPLOYMENT_ROOT = Path(__file__).resolve().parents[1]
COLLECTION_SCHEMA_REF = "corpus/weaviate_collection.schema.json"
HEADING = re.compile(r"^(#{1,6})\s+(.+?)\s*$", re.MULTILINE)
def _canonical(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
def _output_bytes(value: Any) -> bytes:
"""Serialize receipts in the repository's stable reviewable JSON form."""
return (json.dumps(value, ensure_ascii=False, indent=2) + "\n").encode("utf-8")
def _digest(value: Any) -> str:
return hashlib.sha256(_canonical(value)).hexdigest()
def chunks(path: Path) -> list[dict[str, object]]:
raw = path.read_bytes()
text = raw.decode("utf-8", errors="strict")
matches = list(HEADING.finditer(text))
rows: list[dict[str, object]] = []
for index, match in enumerate(matches):
start = match.start()
end = matches[index + 1].start() if index + 1 < len(matches) else len(text)
content = text[start:end]
rows.append(
{
"section_path": match.group(2),
"char_start": start,
"char_end": end,
"chunk_sha256": hashlib.sha256(content.encode("utf-8")).hexdigest(),
}
)
return rows or [
{
"section_path": "ROOT",
"char_start": 0,
"char_end": len(text),
"chunk_sha256": hashlib.sha256(raw).hexdigest(),
}
]
def build_receipt(
raw_root: Path,
*,
deployment_root: Path = DEPLOYMENT_ROOT,
collection_name: str | None = None,
tenant: str | None = None,
) -> dict[str, Any]:
"""Return the exact ``corpus_build_receipt`` schema contract.
Local chunking does not constitute Korean-lawyer approval or live MCP
admission. Accordingly, even a nonempty local build remains ineligible for
production and exposes those missing approvals explicitly.
"""
source_rows: list[dict[str, Any]] = []
chunk_rows: list[dict[str, Any]] = []
for path in sorted(raw_root.glob("CT-*/*.md")):
rel = path.relative_to(raw_root).as_posix()
raw = path.read_bytes()
source_id = "SRC-" + hashlib.sha256(rel.encode("utf-8")).hexdigest()[:24]
source_rows.append(
{
"source_document_id": source_id,
"source_path": rel,
"source_document_sha256": hashlib.sha256(raw).hexdigest(),
}
)
for ordinal, row in enumerate(chunks(path), 1):
chunk_rows.append(
{
"chunk_id": f"{source_id}-CH-{ordinal:04d}",
"source_document_id": source_id,
**row,
}
)
collection_schema_path = deployment_root / COLLECTION_SCHEMA_REF
if not collection_schema_path.is_file():
raise FileNotFoundError(collection_schema_path)
collection_schema_sha256 = hashlib.sha256(collection_schema_path.read_bytes()).hexdigest()
if not source_rows:
return {
"schema_version": "stage2_corpus_build_receipt.v1",
"receipt_id": "S2-CORPUS-BUILD-PENDING",
"build_status": "PENDING_SOURCE_AND_OPERATOR_BUILD",
"build_executed": False,
"created_at": None,
"collection_contract_status": "PENDING_CORPUS_BUILD",
"collection_schema_ref": COLLECTION_SCHEMA_REF,
"collection_schema_sha256": collection_schema_sha256,
"collection_name": None,
"tenant": None,
"snapshot_id": None,
"snapshot_sha256": None,
"source_document_count": 0,
"chunk_count": 0,
"approved_case_type_ids": [],
"components": [
{
"component_id": component_id,
"status": "PENDING",
"configuration_digest": None,
"evidence_refs": [],
}
for component_id in ("CHUNKER", "EMBEDDING", "RERANKER", "INDEX", "CROSSWALK")
],
"legal_review_status": "PENDING_KOREAN_LAWYER_REVIEW",
"live_mcp_admission_status": "PENDING_LIVE_MCP_ADMISSION",
"production_eligible": False,
"unresolved_reason_codes": [
"CORPUS_BUILD_NOT_EXECUTED",
"LEGAL_REVIEW_NOT_COMPLETED",
"LIVE_MCP_ADMISSION_NOT_COMPLETED",
"RAW_CORPUS_NOT_PROVIDED",
],
"guards": {
"raw_corpus_runtime_ingest_forbidden": True,
"directory_scan_forbidden": True,
"filter_relaxation_forbidden": True,
"embedded_instruction_execution_forbidden": True,
"unapproved_chunk_use_forbidden": True,
},
}
snapshot_scope = {"source_rows": source_rows, "chunk_rows": chunk_rows}
snapshot_sha256 = _digest(snapshot_scope)
chunker_digest = _digest(
{"heading_pattern": HEADING.pattern, "fallback_section": "ROOT", "algorithm": "SHA256"}
)
evidence_refs = sorted(row["source_path"] for row in source_rows)
return {
"schema_version": "stage2_corpus_build_receipt.v1",
"receipt_id": f"S2-CORPUS-BUILD-{snapshot_sha256[:24]}",
"build_status": "BUILT_NOT_LEGALLY_REVIEWED",
"build_executed": True,
"created_at": None,
"collection_contract_status": "PENDING_CORPUS_BUILD",
"collection_schema_ref": COLLECTION_SCHEMA_REF,
"collection_schema_sha256": collection_schema_sha256,
"collection_name": collection_name,
"tenant": tenant,
"snapshot_id": f"SNAP-{snapshot_sha256[:24]}",
"snapshot_sha256": snapshot_sha256,
"source_document_count": len(source_rows),
"chunk_count": len(chunk_rows),
"approved_case_type_ids": [],
"components": [
{
"component_id": "CHUNKER",
"status": "BUILT_NOT_ADMITTED",
"configuration_digest": chunker_digest,
"evidence_refs": evidence_refs,
},
*[
{
"component_id": component_id,
"status": "PENDING",
"configuration_digest": None,
"evidence_refs": [],
}
for component_id in ("EMBEDDING", "RERANKER", "INDEX", "CROSSWALK")
],
],
"legal_review_status": "PENDING_KOREAN_LAWYER_REVIEW",
"live_mcp_admission_status": "PENDING_LIVE_MCP_ADMISSION",
"production_eligible": False,
"unresolved_reason_codes": [
"LEGAL_REVIEW_NOT_COMPLETED",
"LIVE_MCP_ADMISSION_NOT_COMPLETED",
"EMBEDDING_NOT_BUILT",
"RERANKER_NOT_BUILT",
"INDEX_NOT_BUILT",
"CROSSWALK_NOT_BUILT",
],
"guards": {
"raw_corpus_runtime_ingest_forbidden": True,
"directory_scan_forbidden": True,
"filter_relaxation_forbidden": True,
"embedded_instruction_execution_forbidden": True,
"unapproved_chunk_use_forbidden": True,
},
}
def write_or_check(output: Path, expected: bytes, *, check: bool) -> int:
"""Write expected bytes, or perform read-only exact-byte drift detection."""
expected_sha256 = hashlib.sha256(expected).hexdigest()
if check:
if not output.is_file():
print(
json.dumps(
{"status": "DRIFT", "reason": "OUTPUT_MISSING", "output": str(output)},
sort_keys=True,
)
)
return 1
actual = output.read_bytes()
if actual != expected:
print(
json.dumps(
{
"status": "DRIFT",
"reason": "OUTPUT_BYTES_MISMATCH",
"actual_sha256": hashlib.sha256(actual).hexdigest(),
"expected_sha256": expected_sha256,
"output": str(output),
},
sort_keys=True,
)
)
return 1
print(
json.dumps(
{"status": "PASS", "output_sha256": expected_sha256}, sort_keys=True
)
)
return 0
output.parent.mkdir(parents=True, exist_ok=True)
output.write_bytes(expected)
print(
json.dumps(
{"status": "BUILT", "output_sha256": expected_sha256}, sort_keys=True
)
)
return 0
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("raw_root", type=Path)
parser.add_argument("output", type=Path)
parser.add_argument("--deployment-root", type=Path, default=DEPLOYMENT_ROOT)
parser.add_argument("--collection-name")
parser.add_argument("--tenant")
parser.add_argument(
"--check",
action="store_true",
help="read-only exact-byte drift check; never creates or modifies output",
)
args = parser.parse_args()
payload = build_receipt(
args.raw_root,
deployment_root=args.deployment_root,
collection_name=args.collection_name,
tenant=args.tenant,
)
return write_or_check(args.output, _output_bytes(payload), check=args.check)
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,273 @@
#!/usr/bin/env python3
"""Create a deterministic, schema-conformant corpus build receipt."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import re
from typing import Any
DEPLOYMENT_ROOT = Path(__file__).resolve().parents[1]
COLLECTION_SCHEMA_REF = "corpus/weaviate_collection.schema.json"
HEADING = re.compile(r"^(#{1,6})\s+(.+?)\s*$", re.MULTILINE)
def _canonical(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
def _output_bytes(value: Any) -> bytes:
"""Serialize receipts in the repository's stable reviewable JSON form."""
return (json.dumps(value, ensure_ascii=False, indent=2) + "\n").encode("utf-8")
def _digest(value: Any) -> str:
return hashlib.sha256(_canonical(value)).hexdigest()
def chunks(path: Path) -> list[dict[str, object]]:
raw = path.read_bytes()
text = raw.decode("utf-8", errors="strict")
matches = list(HEADING.finditer(text))
rows: list[dict[str, object]] = []
for index, match in enumerate(matches):
start = match.start()
end = matches[index + 1].start() if index + 1 < len(matches) else len(text)
content = text[start:end]
rows.append(
{
"section_path": match.group(2),
"char_start": start,
"char_end": end,
"chunk_sha256": hashlib.sha256(content.encode("utf-8")).hexdigest(),
}
)
return rows or [
{
"section_path": "ROOT",
"char_start": 0,
"char_end": len(text),
"chunk_sha256": hashlib.sha256(raw).hexdigest(),
}
]
def build_receipt(
raw_root: Path,
*,
deployment_root: Path = DEPLOYMENT_ROOT,
collection_name: str | None = None,
tenant: str | None = None,
) -> dict[str, Any]:
"""Return the exact ``corpus_build_receipt`` schema contract.
Local chunking does not constitute Korean-lawyer approval or live MCP
admission. Accordingly, even a nonempty local build remains ineligible for
production and exposes those missing approvals explicitly.
"""
source_rows: list[dict[str, Any]] = []
chunk_rows: list[dict[str, Any]] = []
for path in sorted(raw_root.glob("CT-*/*.md")):
rel = path.relative_to(raw_root).as_posix()
raw = path.read_bytes()
source_id = "SRC-" + hashlib.sha256(rel.encode("utf-8")).hexdigest()[:24]
source_rows.append(
{
"source_document_id": source_id,
"source_path": rel,
"source_document_sha256": hashlib.sha256(raw).hexdigest(),
}
)
for ordinal, row in enumerate(chunks(path), 1):
chunk_rows.append(
{
"chunk_id": f"{source_id}-CH-{ordinal:04d}",
"source_document_id": source_id,
**row,
}
)
collection_schema_path = deployment_root / COLLECTION_SCHEMA_REF
if not collection_schema_path.is_file():
raise FileNotFoundError(collection_schema_path)
collection_schema_sha256 = hashlib.sha256(collection_schema_path.read_bytes()).hexdigest()
if not source_rows:
return {
"schema_version": "stage2_corpus_build_receipt.v1",
"receipt_id": "S2-CORPUS-BUILD-PENDING",
"build_status": "PENDING_SOURCE_AND_OPERATOR_BUILD",
"build_executed": False,
"created_at": None,
"collection_contract_status": "PENDING_CORPUS_BUILD",
"collection_schema_ref": COLLECTION_SCHEMA_REF,
"collection_schema_sha256": collection_schema_sha256,
"collection_name": None,
"tenant": None,
"snapshot_id": None,
"snapshot_sha256": None,
"source_document_count": 0,
"chunk_count": 0,
"approved_case_type_ids": [],
"components": [
{
"component_id": component_id,
"status": "PENDING",
"configuration_digest": None,
"evidence_refs": [],
}
for component_id in ("CHUNKER", "EMBEDDING", "RERANKER", "INDEX", "CROSSWALK")
],
"legal_review_status": "PENDING_KOREAN_LAWYER_REVIEW",
"live_mcp_admission_status": "PENDING_LIVE_MCP_ADMISSION",
"production_eligible": False,
"unresolved_reason_codes": [
"CORPUS_BUILD_NOT_EXECUTED",
"LEGAL_REVIEW_NOT_COMPLETED",
"LIVE_MCP_ADMISSION_NOT_COMPLETED",
"RAW_CORPUS_NOT_PROVIDED",
],
"guards": {
"raw_corpus_runtime_ingest_forbidden": True,
"directory_scan_forbidden": True,
"filter_relaxation_forbidden": True,
"embedded_instruction_execution_forbidden": True,
"unapproved_chunk_use_forbidden": True,
},
}
snapshot_scope = {"source_rows": source_rows, "chunk_rows": chunk_rows}
snapshot_sha256 = _digest(snapshot_scope)
chunker_digest = _digest(
{"heading_pattern": HEADING.pattern, "fallback_section": "ROOT", "algorithm": "SHA256"}
)
evidence_refs = sorted(row["source_path"] for row in source_rows)
return {
"schema_version": "stage2_corpus_build_receipt.v1",
"receipt_id": f"S2-CORPUS-BUILD-{snapshot_sha256[:24]}",
"build_status": "BUILT_NOT_LEGALLY_REVIEWED",
"build_executed": True,
"created_at": None,
"collection_contract_status": "PENDING_CORPUS_BUILD",
"collection_schema_ref": COLLECTION_SCHEMA_REF,
"collection_schema_sha256": collection_schema_sha256,
"collection_name": collection_name,
"tenant": tenant,
"snapshot_id": f"SNAP-{snapshot_sha256[:24]}",
"snapshot_sha256": snapshot_sha256,
"source_document_count": len(source_rows),
"chunk_count": len(chunk_rows),
"approved_case_type_ids": [],
"components": [
{
"component_id": "CHUNKER",
"status": "BUILT_NOT_ADMITTED",
"configuration_digest": chunker_digest,
"evidence_refs": evidence_refs,
},
*[
{
"component_id": component_id,
"status": "PENDING",
"configuration_digest": None,
"evidence_refs": [],
}
for component_id in ("EMBEDDING", "RERANKER", "INDEX", "CROSSWALK")
],
],
"legal_review_status": "PENDING_KOREAN_LAWYER_REVIEW",
"live_mcp_admission_status": "PENDING_LIVE_MCP_ADMISSION",
"production_eligible": False,
"unresolved_reason_codes": [
"LEGAL_REVIEW_NOT_COMPLETED",
"LIVE_MCP_ADMISSION_NOT_COMPLETED",
"EMBEDDING_NOT_BUILT",
"RERANKER_NOT_BUILT",
"INDEX_NOT_BUILT",
"CROSSWALK_NOT_BUILT",
],
"guards": {
"raw_corpus_runtime_ingest_forbidden": True,
"directory_scan_forbidden": True,
"filter_relaxation_forbidden": True,
"embedded_instruction_execution_forbidden": True,
"unapproved_chunk_use_forbidden": True,
},
}
def write_or_check(output: Path, expected: bytes, *, check: bool) -> int:
"""Write expected bytes, or perform read-only exact-byte drift detection."""
expected_sha256 = hashlib.sha256(expected).hexdigest()
if check:
if not output.is_file():
print(
json.dumps(
{"status": "DRIFT", "reason": "OUTPUT_MISSING", "output": str(output)},
sort_keys=True,
)
)
return 1
actual = output.read_bytes()
if actual != expected:
print(
json.dumps(
{
"status": "DRIFT",
"reason": "OUTPUT_BYTES_MISMATCH",
"actual_sha256": hashlib.sha256(actual).hexdigest(),
"expected_sha256": expected_sha256,
"output": str(output),
},
sort_keys=True,
)
)
return 1
print(
json.dumps(
{"status": "PASS", "output_sha256": expected_sha256}, sort_keys=True
)
)
return 0
output.parent.mkdir(parents=True, exist_ok=True)
output.write_bytes(expected)
print(
json.dumps(
{"status": "BUILT", "output_sha256": expected_sha256}, sort_keys=True
)
)
return 0
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("raw_root", type=Path)
parser.add_argument("output", type=Path)
parser.add_argument("--deployment-root", type=Path, default=DEPLOYMENT_ROOT)
parser.add_argument("--collection-name")
parser.add_argument("--tenant")
parser.add_argument(
"--check",
action="store_true",
help="read-only exact-byte drift check; never creates or modifies output",
)
args = parser.parse_args()
payload = build_receipt(
args.raw_root,
deployment_root=args.deployment_root,
collection_name=args.collection_name,
tenant=args.tenant,
)
return write_or_check(args.output, _output_bytes(payload), check=args.check)
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,493 @@
#!/usr/bin/env python3
"""Build the canonical Stage-2 module manifest and parent release.
The parent release is deliberately a *raw closure*. Assets that embed the
parent release hash (Agent projections, inline-code mirrors/receipts, the
shared executor binding and detached admission material) are kept outside the
closure so that the release graph cannot become self-referential.
"""
from __future__ import annotations
import argparse
import copy
import hashlib
import json
import os
from pathlib import Path, PurePosixPath
from typing import Any, Iterable
MODULE_MANIFEST_SCHEMA = "stage2_module_manifest.v1"
PARENT_RELEASE_SCHEMA = "stage2_release.v2"
# Downstream-of-parent, detached, and self-referential assets. They may appear
# as an unhashed external trust-root pointer, but never in the parent closure.
FORBIDDEN_PARENT_MEMBERS = frozenset(
{
"manifest/module_manifest.json",
"manifest/stage2_release.json",
"deployment/stage2_code_executor_binding.yml",
"manifest/stage2_deterministic_admission_receipt.json",
"agent_scripts/Stage_2_S2_00.yml",
"runtime/s2_00_ingress.py",
"runtime/s2_00_ingress.txt",
"manifest/s2_00_inline_code_receipt.json",
"agent_scripts/Stage_2_S2_20.yml",
"runtime/s2_20_reduce.py",
"runtime/s2_20_reduce.txt",
"manifest/s2_20_inline_code_receipt.json",
"manifest/s2_10_release.json",
"manifest/s2_10_agent_receipt.json",
"manifest/s2_10_platform_adapter_receipt.json",
"manifest/s2_10_model_benchmark_receipt.json",
"manifest/s2_10_legal_review_receipt.json",
}
)
class ReleaseBuildError(ValueError):
"""Raised when a release input violates the canonical closure contract."""
def _reject_duplicate_pairs(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
result: dict[str, Any] = {}
for key, value in pairs:
if key in result:
raise ReleaseBuildError(f"DUPLICATE_JSON_KEY:{key}")
result[key] = value
return result
def _load_json(path: Path) -> Any:
try:
return json.loads(
path.read_text(encoding="utf-8"),
object_pairs_hook=_reject_duplicate_pairs,
parse_constant=lambda token: (_ for _ in ()).throw(
ReleaseBuildError(f"NON_FINITE_JSON_NUMBER:{token}")
),
)
except UnicodeDecodeError as exc:
raise ReleaseBuildError(f"UTF8_REQUIRED:{path.as_posix()}") from exc
def _canonical_bytes(document: Any) -> bytes:
return (
json.dumps(
document,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
).encode("utf-8")
def _document_digest(document: dict[str, Any], digest_field: str) -> str:
payload = copy.deepcopy(document)
payload.pop(digest_field, None)
return hashlib.sha256(_canonical_bytes(payload)).hexdigest()
def _sha256(raw: bytes) -> str:
return hashlib.sha256(raw).hexdigest()
def _relative_path(value: str) -> str:
if not isinstance(value, str) or not value or "\\" in value:
raise ReleaseBuildError(f"RELATIVE_POSIX_PATH_REQUIRED:{value!r}")
pure = PurePosixPath(value)
if pure.is_absolute() or any(part in {"", ".", ".."} for part in pure.parts):
raise ReleaseBuildError(f"UNSAFE_RELATIVE_PATH:{value}")
normalized = pure.as_posix()
if any(segment in {"v.0", "v.1", "v.2", "v.3"} for segment in pure.parts):
raise ReleaseBuildError(f"LEGACY_STAGE2_DEPENDENCY:{normalized}")
return normalized
def _physical_file(root: Path, relative: str) -> Path:
relative = _relative_path(relative)
root_real = root.resolve(strict=True)
candidate = root / relative
if candidate.is_symlink():
raise ReleaseBuildError(f"MODULE_SYMLINK_FORBIDDEN:{relative}")
try:
resolved = candidate.resolve(strict=True)
except FileNotFoundError as exc:
raise ReleaseBuildError(f"MODULE_PATH_UNAVAILABLE:{relative}") from exc
if root_real not in resolved.parents or not resolved.is_file():
raise ReleaseBuildError(f"MODULE_PATH_UNAVAILABLE:{relative}")
return resolved
def _asset_bytes(root: Path, relative: str) -> bytes:
return _physical_file(root, relative).read_bytes()
def _mirror_for(root: Path, source_path: str) -> tuple[str, bytes] | None:
if not source_path.endswith(".py"):
return None
mirror_path = source_path[:-3] + ".txt"
candidate = root / mirror_path
if not candidate.exists():
raise ReleaseBuildError(f"PYTHON_DOCUMENTATION_MIRROR_MISSING:{source_path}")
source_raw = _asset_bytes(root, source_path)
mirror_raw = _asset_bytes(root, mirror_path)
if source_raw != mirror_raw:
raise ReleaseBuildError(f"PYTHON_DOCUMENTATION_MIRROR_MISMATCH:{source_path}")
return mirror_path, mirror_raw
def _generic_kind(relative: str) -> str:
if relative.startswith("tests/"):
return "TEST"
if relative.startswith("schemas/"):
return "JSON_SCHEMA"
if relative.startswith("workflows/"):
return "WORKFLOW"
if relative.startswith("offline_build/") or relative.startswith("release_ops/"):
return "BUILD_ONLY"
if relative.startswith("runtime/"):
return "RUNTIME_CORE"
if relative.startswith("rules/"):
return "LEGAL_RULE_SOURCE"
if relative.startswith("manifest/"):
return "MANIFEST"
if relative.startswith("registry/"):
return "DECLARATIVE_REGISTRY"
return "S2_20_ASSET"
def _generic_module_row(relative: str) -> dict[str, Any]:
identity = hashlib.sha256(relative.encode("utf-8")).hexdigest()[:16].upper()
return {
"asset_version": "s2_20.1",
"authority_ids": [],
"consumed_schema_ids": [],
"dependency_module_ids": [],
"forbidden_contract_codes": ["LEGACY-STAGE2-V0-V3"],
"implementation_status": "DEV_HASH_BOUND_OFFLINE_ONLY",
"incompatible_module_ids": [],
"inputs": [],
"module_id": f"S2_20-ASSET-{identity}",
"module_kind": _generic_kind(relative),
"outputs": [],
"owner": "Stage_2_S2_20_owner",
"path": relative,
"produced_schema_ids": [],
"schema_version": "stage2_s2_20_generic_asset.v1",
"scope_predicate": "workflow_id == S2_20",
"semantic_review_status": "PENDING_LEGAL_AND_LIVE_ADMISSION",
}
def _refresh_module_row(root: Path, row: dict[str, Any]) -> dict[str, Any]:
refreshed = copy.deepcopy(row)
relative = _relative_path(refreshed.get("path"))
if relative in FORBIDDEN_PARENT_MEMBERS:
raise ReleaseBuildError(f"NON_CYCLIC_PARENT_VIOLATION:{relative}")
raw = _asset_bytes(root, relative)
refreshed["path"] = relative
refreshed["sha256"] = _sha256(raw)
refreshed["size_bytes"] = len(raw)
mirror = _mirror_for(root, relative)
if mirror is not None:
mirror_path, mirror_raw = mirror
refreshed["mirror_path"] = mirror_path
refreshed["mirror_sha256"] = _sha256(mirror_raw)
refreshed["mirror_size_bytes"] = len(mirror_raw)
refreshed["mirror_byte_parity"] = True
return refreshed
def _documentation_mirror(row: dict[str, Any]) -> dict[str, Any] | None:
source = row.get("path")
mirror = row.get("mirror_path")
if not isinstance(source, str) or not isinstance(mirror, str):
return None
return {
"byte_identical": True,
"mirror_path": mirror,
"mirror_sha256": row["mirror_sha256"],
"mirror_size_bytes": row["mirror_size_bytes"],
"runtime_import_allowed": False,
"source_path": source,
"source_sha256": row["sha256"],
"source_size_bytes": row["size_bytes"],
}
def build_module_manifest(
root: Path,
template: dict[str, Any],
explicit_paths: Iterable[str],
) -> dict[str, Any]:
"""Preserve canonical rows, refresh physical bindings and append S2_20 rows."""
if template.get("schema_version") != MODULE_MANIFEST_SCHEMA:
raise ReleaseBuildError("CANONICAL_MODULE_MANIFEST_V1_REQUIRED")
existing = template.get("modules")
if not isinstance(existing, list):
raise ReleaseBuildError("CANONICAL_MODULES_ARRAY_REQUIRED")
normalized_explicit = [_relative_path(value) for value in explicit_paths]
if len(normalized_explicit) != len(set(normalized_explicit)):
raise ReleaseBuildError("PATH_LIST_MUST_BE_UNIQUE_ARRAY")
forbidden = sorted(set(normalized_explicit) & FORBIDDEN_PARENT_MEMBERS)
if forbidden:
raise ReleaseBuildError(f"NON_CYCLIC_PARENT_VIOLATION:{forbidden}")
result = copy.deepcopy(template)
refreshed_rows: list[dict[str, Any]] = []
seen_ids: set[str] = set()
seen_paths: set[str] = set()
for value in existing:
if not isinstance(value, dict):
raise ReleaseBuildError("MODULE_ROW_OBJECT_REQUIRED")
module_id = value.get("module_id")
relative = _relative_path(value.get("path"))
if not isinstance(module_id, str) or not module_id or module_id in seen_ids:
raise ReleaseBuildError(f"MODULE_ID_INVALID_OR_DUPLICATE:{module_id!r}")
if relative in seen_paths:
raise ReleaseBuildError(f"MODULE_PATH_DUPLICATE:{relative}")
seen_ids.add(module_id)
seen_paths.add(relative)
refreshed_rows.append(_refresh_module_row(root, value))
explicit_set = set(normalized_explicit)
for relative in sorted(normalized_explicit):
# A .txt copy is documentation for an explicitly bound .py source, not
# a second executable module row.
if relative.endswith(".txt"):
source = relative[:-4] + ".py"
if source in explicit_set or source in seen_paths:
_mirror_for(root, source)
continue
if relative in seen_paths:
continue
row = _refresh_module_row(root, _generic_module_row(relative))
if row["module_id"] in seen_ids:
raise ReleaseBuildError(f"GENERATED_MODULE_ID_COLLISION:{row['module_id']}")
seen_ids.add(row["module_id"])
seen_paths.add(relative)
refreshed_rows.append(row)
result["modules"] = refreshed_rows
mirrors = [entry for row in refreshed_rows if (entry := _documentation_mirror(row))]
mirror_sources = [str(entry["source_path"]) for entry in mirrors]
if len(mirror_sources) != len(set(mirror_sources)):
raise ReleaseBuildError("DOCUMENTATION_MIRROR_SOURCE_DUPLICATE")
result["documentation_mirrors"] = sorted(
mirrors, key=lambda entry: str(entry["source_path"])
)
summary = result.get("closure_summary")
if not isinstance(summary, dict):
raise ReleaseBuildError("CLOSURE_SUMMARY_REQUIRED")
summary.update(
{
"module_count": len(refreshed_rows),
"documentation_mirror_count": len(mirrors),
"test_module_count": sum(
1 for row in refreshed_rows if row.get("module_kind") == "TEST"
),
"build_tool_module_count": sum(
1 for row in refreshed_rows if row.get("module_kind") == "BUILD_TOOL"
),
"s2_20_generic_module_count": sum(
1
for row in refreshed_rows
if row.get("schema_version") == "stage2_s2_20_generic_asset.v1"
),
"executable_agent_hash_included": False,
"executor_binding_hash_included": False,
"inline_runtime_code_hash_included": False,
"self_hash_included": False,
"stage2_release_hash_included": False,
}
)
result["manifest_digest"] = _document_digest(result, "manifest_digest")
return result
def _refresh_parent_refs(
value: Any,
root: Path,
raw_overrides: dict[str, bytes],
location: str = "$",
) -> None:
if isinstance(value, list):
for index, item in enumerate(value):
_refresh_parent_refs(item, root, raw_overrides, f"{location}/{index}")
return
if not isinstance(value, dict):
return
relative = value.get("path")
if isinstance(relative, str) and relative and "<" not in relative:
try:
relative = _relative_path(relative)
except ReleaseBuildError:
relative = None
if relative == "manifest/module_manifest.json":
raw = raw_overrides.get(relative)
if raw is None:
raise ReleaseBuildError("MODULE_MANIFEST_RAW_OVERRIDE_REQUIRED")
if "sha256" in value:
value["sha256"] = _sha256(raw)
if "size_bytes" in value:
value["size_bytes"] = len(raw)
elif relative in FORBIDDEN_PARENT_MEMBERS:
if "sha256" in value or value.get("binding_status") == "BOUND":
raise ReleaseBuildError(
f"NON_CYCLIC_PARENT_HASH_REFERENCE:{location}:{relative}"
)
elif relative is not None and (relative in raw_overrides or (root / relative).is_file()):
raw = raw_overrides.get(relative)
if raw is None:
raw = _asset_bytes(root, relative)
if "sha256" in value:
value["sha256"] = _sha256(raw)
if "size_bytes" in value:
value["size_bytes"] = len(raw)
for key, item in list(value.items()):
_refresh_parent_refs(item, root, raw_overrides, f"{location}/{key}")
def build_parent_release(
root: Path,
template: dict[str, Any],
module_manifest_raw: bytes,
) -> dict[str, Any]:
"""Refresh safe parent refs and its self digest without changing admission."""
if template.get("schema_version") != PARENT_RELEASE_SCHEMA:
raise ReleaseBuildError("PARENT_STAGE2_RELEASE_V2_REQUIRED")
result = copy.deepcopy(template)
immutable_admission = {
key: copy.deepcopy(result.get(key))
for key in (
"release_class",
"release_status",
"authorization_status",
"signature",
"release_evidence",
)
}
module_ref = result.get("module_manifest_ref")
if not isinstance(module_ref, dict) or module_ref.get("path") != "manifest/module_manifest.json":
raise ReleaseBuildError("PARENT_MODULE_MANIFEST_REF_REQUIRED")
module_ref["sha256"] = _sha256(module_manifest_raw)
if "size_bytes" in module_ref:
module_ref["size_bytes"] = len(module_manifest_raw)
executor_ref = result.get("executor_binding_ref")
if (
not isinstance(executor_ref, dict)
or executor_ref.get("path") != "deployment/stage2_code_executor_binding.yml"
):
raise ReleaseBuildError("PARENT_EXECUTOR_TRUST_ROOT_REF_REQUIRED")
if "sha256" in executor_ref or executor_ref.get("binding_status") == "BOUND":
raise ReleaseBuildError("PARENT_EXECUTOR_TRUST_ROOT_MUST_BE_UNHASHED")
executor_ref["schema_id"] = "stage2_code_executor_binding.v3"
_refresh_parent_refs(
result,
root,
{"manifest/module_manifest.json": module_manifest_raw},
)
bundle = result.get("bundle")
if isinstance(bundle, dict):
agent_ref = bundle.get("s2_10_agent_ref")
binding_ref = bundle.get("s2_10_llm_binding_ref")
if isinstance(agent_ref, dict) and isinstance(agent_ref.get("sha256"), str):
bundle["s2_10_agent_sha256"] = agent_ref["sha256"]
if isinstance(binding_ref, dict) and isinstance(binding_ref.get("sha256"), str):
bundle["s2_10_llm_binding_sha256"] = binding_ref["sha256"]
for key, expected in immutable_admission.items():
if result.get(key) != expected:
raise ReleaseBuildError(f"ADMISSION_STATE_MUTATION_FORBIDDEN:{key}")
result["release_digest"] = _document_digest(result, "release_digest")
return result
def build_release_package(
root: Path,
path_list: list[str],
module_template: dict[str, Any],
parent_template: dict[str, Any],
) -> tuple[dict[str, Any], dict[str, Any]]:
module_manifest = build_module_manifest(root, module_template, path_list)
module_raw = _canonical_bytes(module_manifest)
parent_release = build_parent_release(root, parent_template, module_raw)
return module_manifest, parent_release
def _write_bytes(path: Path, raw: bytes) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
temporary = path.with_name(f".{path.name}.tmp-{os.getpid()}")
temporary.write_bytes(raw)
os.replace(temporary, path)
def main() -> int:
parser = argparse.ArgumentParser(
description="Reseal canonical Stage-2 module and parent release manifests"
)
parser.add_argument("root", type=Path)
parser.add_argument("path_list", type=Path, help="JSON array of relative S2_20 paths")
parser.add_argument("output", type=Path, help="module_manifest.json output")
parser.add_argument(
"--module-template",
type=Path,
help="canonical module manifest template (default: ROOT/manifest/module_manifest.json)",
)
parser.add_argument(
"--parent-template",
type=Path,
help="parent release template (default: ROOT/manifest/stage2_release.json)",
)
parser.add_argument(
"--parent-output",
type=Path,
help="parent release output (default: OUTPUT sibling stage2_release.json)",
)
args = parser.parse_args()
path_list = _load_json(args.path_list)
if not isinstance(path_list, list) or not all(isinstance(row, str) for row in path_list):
raise ReleaseBuildError("PATH_LIST_MUST_BE_STRING_ARRAY")
module_template_path = args.module_template or args.root / "manifest/module_manifest.json"
parent_template_path = args.parent_template or args.root / "manifest/stage2_release.json"
parent_output = args.parent_output or args.output.with_name("stage2_release.json")
module_manifest, parent_release = build_release_package(
args.root,
path_list,
_load_json(module_template_path),
_load_json(parent_template_path),
)
_write_bytes(args.output, _canonical_bytes(module_manifest))
_write_bytes(parent_output, _canonical_bytes(parent_release))
print(
json.dumps(
{
"module_count": len(module_manifest["modules"]),
"module_manifest_output": args.output.as_posix(),
"module_manifest_sha256": _sha256(_canonical_bytes(module_manifest)),
"parent_release_output": parent_output.as_posix(),
"parent_release_sha256": _sha256(_canonical_bytes(parent_release)),
"status": "PASS",
},
sort_keys=True,
separators=(",", ":"),
)
)
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,493 @@
#!/usr/bin/env python3
"""Build the canonical Stage-2 module manifest and parent release.
The parent release is deliberately a *raw closure*. Assets that embed the
parent release hash (Agent projections, inline-code mirrors/receipts, the
shared executor binding and detached admission material) are kept outside the
closure so that the release graph cannot become self-referential.
"""
from __future__ import annotations
import argparse
import copy
import hashlib
import json
import os
from pathlib import Path, PurePosixPath
from typing import Any, Iterable
MODULE_MANIFEST_SCHEMA = "stage2_module_manifest.v1"
PARENT_RELEASE_SCHEMA = "stage2_release.v2"
# Downstream-of-parent, detached, and self-referential assets. They may appear
# as an unhashed external trust-root pointer, but never in the parent closure.
FORBIDDEN_PARENT_MEMBERS = frozenset(
{
"manifest/module_manifest.json",
"manifest/stage2_release.json",
"deployment/stage2_code_executor_binding.yml",
"manifest/stage2_deterministic_admission_receipt.json",
"agent_scripts/Stage_2_S2_00.yml",
"runtime/s2_00_ingress.py",
"runtime/s2_00_ingress.txt",
"manifest/s2_00_inline_code_receipt.json",
"agent_scripts/Stage_2_S2_20.yml",
"runtime/s2_20_reduce.py",
"runtime/s2_20_reduce.txt",
"manifest/s2_20_inline_code_receipt.json",
"manifest/s2_10_release.json",
"manifest/s2_10_agent_receipt.json",
"manifest/s2_10_platform_adapter_receipt.json",
"manifest/s2_10_model_benchmark_receipt.json",
"manifest/s2_10_legal_review_receipt.json",
}
)
class ReleaseBuildError(ValueError):
"""Raised when a release input violates the canonical closure contract."""
def _reject_duplicate_pairs(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
result: dict[str, Any] = {}
for key, value in pairs:
if key in result:
raise ReleaseBuildError(f"DUPLICATE_JSON_KEY:{key}")
result[key] = value
return result
def _load_json(path: Path) -> Any:
try:
return json.loads(
path.read_text(encoding="utf-8"),
object_pairs_hook=_reject_duplicate_pairs,
parse_constant=lambda token: (_ for _ in ()).throw(
ReleaseBuildError(f"NON_FINITE_JSON_NUMBER:{token}")
),
)
except UnicodeDecodeError as exc:
raise ReleaseBuildError(f"UTF8_REQUIRED:{path.as_posix()}") from exc
def _canonical_bytes(document: Any) -> bytes:
return (
json.dumps(
document,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
).encode("utf-8")
def _document_digest(document: dict[str, Any], digest_field: str) -> str:
payload = copy.deepcopy(document)
payload.pop(digest_field, None)
return hashlib.sha256(_canonical_bytes(payload)).hexdigest()
def _sha256(raw: bytes) -> str:
return hashlib.sha256(raw).hexdigest()
def _relative_path(value: str) -> str:
if not isinstance(value, str) or not value or "\\" in value:
raise ReleaseBuildError(f"RELATIVE_POSIX_PATH_REQUIRED:{value!r}")
pure = PurePosixPath(value)
if pure.is_absolute() or any(part in {"", ".", ".."} for part in pure.parts):
raise ReleaseBuildError(f"UNSAFE_RELATIVE_PATH:{value}")
normalized = pure.as_posix()
if any(segment in {"v.0", "v.1", "v.2", "v.3"} for segment in pure.parts):
raise ReleaseBuildError(f"LEGACY_STAGE2_DEPENDENCY:{normalized}")
return normalized
def _physical_file(root: Path, relative: str) -> Path:
relative = _relative_path(relative)
root_real = root.resolve(strict=True)
candidate = root / relative
if candidate.is_symlink():
raise ReleaseBuildError(f"MODULE_SYMLINK_FORBIDDEN:{relative}")
try:
resolved = candidate.resolve(strict=True)
except FileNotFoundError as exc:
raise ReleaseBuildError(f"MODULE_PATH_UNAVAILABLE:{relative}") from exc
if root_real not in resolved.parents or not resolved.is_file():
raise ReleaseBuildError(f"MODULE_PATH_UNAVAILABLE:{relative}")
return resolved
def _asset_bytes(root: Path, relative: str) -> bytes:
return _physical_file(root, relative).read_bytes()
def _mirror_for(root: Path, source_path: str) -> tuple[str, bytes] | None:
if not source_path.endswith(".py"):
return None
mirror_path = source_path[:-3] + ".txt"
candidate = root / mirror_path
if not candidate.exists():
raise ReleaseBuildError(f"PYTHON_DOCUMENTATION_MIRROR_MISSING:{source_path}")
source_raw = _asset_bytes(root, source_path)
mirror_raw = _asset_bytes(root, mirror_path)
if source_raw != mirror_raw:
raise ReleaseBuildError(f"PYTHON_DOCUMENTATION_MIRROR_MISMATCH:{source_path}")
return mirror_path, mirror_raw
def _generic_kind(relative: str) -> str:
if relative.startswith("tests/"):
return "TEST"
if relative.startswith("schemas/"):
return "JSON_SCHEMA"
if relative.startswith("workflows/"):
return "WORKFLOW"
if relative.startswith("offline_build/") or relative.startswith("release_ops/"):
return "BUILD_ONLY"
if relative.startswith("runtime/"):
return "RUNTIME_CORE"
if relative.startswith("rules/"):
return "LEGAL_RULE_SOURCE"
if relative.startswith("manifest/"):
return "MANIFEST"
if relative.startswith("registry/"):
return "DECLARATIVE_REGISTRY"
return "S2_20_ASSET"
def _generic_module_row(relative: str) -> dict[str, Any]:
identity = hashlib.sha256(relative.encode("utf-8")).hexdigest()[:16].upper()
return {
"asset_version": "s2_20.1",
"authority_ids": [],
"consumed_schema_ids": [],
"dependency_module_ids": [],
"forbidden_contract_codes": ["LEGACY-STAGE2-V0-V3"],
"implementation_status": "DEV_HASH_BOUND_OFFLINE_ONLY",
"incompatible_module_ids": [],
"inputs": [],
"module_id": f"S2_20-ASSET-{identity}",
"module_kind": _generic_kind(relative),
"outputs": [],
"owner": "Stage_2_S2_20_owner",
"path": relative,
"produced_schema_ids": [],
"schema_version": "stage2_s2_20_generic_asset.v1",
"scope_predicate": "workflow_id == S2_20",
"semantic_review_status": "PENDING_LEGAL_AND_LIVE_ADMISSION",
}
def _refresh_module_row(root: Path, row: dict[str, Any]) -> dict[str, Any]:
refreshed = copy.deepcopy(row)
relative = _relative_path(refreshed.get("path"))
if relative in FORBIDDEN_PARENT_MEMBERS:
raise ReleaseBuildError(f"NON_CYCLIC_PARENT_VIOLATION:{relative}")
raw = _asset_bytes(root, relative)
refreshed["path"] = relative
refreshed["sha256"] = _sha256(raw)
refreshed["size_bytes"] = len(raw)
mirror = _mirror_for(root, relative)
if mirror is not None:
mirror_path, mirror_raw = mirror
refreshed["mirror_path"] = mirror_path
refreshed["mirror_sha256"] = _sha256(mirror_raw)
refreshed["mirror_size_bytes"] = len(mirror_raw)
refreshed["mirror_byte_parity"] = True
return refreshed
def _documentation_mirror(row: dict[str, Any]) -> dict[str, Any] | None:
source = row.get("path")
mirror = row.get("mirror_path")
if not isinstance(source, str) or not isinstance(mirror, str):
return None
return {
"byte_identical": True,
"mirror_path": mirror,
"mirror_sha256": row["mirror_sha256"],
"mirror_size_bytes": row["mirror_size_bytes"],
"runtime_import_allowed": False,
"source_path": source,
"source_sha256": row["sha256"],
"source_size_bytes": row["size_bytes"],
}
def build_module_manifest(
root: Path,
template: dict[str, Any],
explicit_paths: Iterable[str],
) -> dict[str, Any]:
"""Preserve canonical rows, refresh physical bindings and append S2_20 rows."""
if template.get("schema_version") != MODULE_MANIFEST_SCHEMA:
raise ReleaseBuildError("CANONICAL_MODULE_MANIFEST_V1_REQUIRED")
existing = template.get("modules")
if not isinstance(existing, list):
raise ReleaseBuildError("CANONICAL_MODULES_ARRAY_REQUIRED")
normalized_explicit = [_relative_path(value) for value in explicit_paths]
if len(normalized_explicit) != len(set(normalized_explicit)):
raise ReleaseBuildError("PATH_LIST_MUST_BE_UNIQUE_ARRAY")
forbidden = sorted(set(normalized_explicit) & FORBIDDEN_PARENT_MEMBERS)
if forbidden:
raise ReleaseBuildError(f"NON_CYCLIC_PARENT_VIOLATION:{forbidden}")
result = copy.deepcopy(template)
refreshed_rows: list[dict[str, Any]] = []
seen_ids: set[str] = set()
seen_paths: set[str] = set()
for value in existing:
if not isinstance(value, dict):
raise ReleaseBuildError("MODULE_ROW_OBJECT_REQUIRED")
module_id = value.get("module_id")
relative = _relative_path(value.get("path"))
if not isinstance(module_id, str) or not module_id or module_id in seen_ids:
raise ReleaseBuildError(f"MODULE_ID_INVALID_OR_DUPLICATE:{module_id!r}")
if relative in seen_paths:
raise ReleaseBuildError(f"MODULE_PATH_DUPLICATE:{relative}")
seen_ids.add(module_id)
seen_paths.add(relative)
refreshed_rows.append(_refresh_module_row(root, value))
explicit_set = set(normalized_explicit)
for relative in sorted(normalized_explicit):
# A .txt copy is documentation for an explicitly bound .py source, not
# a second executable module row.
if relative.endswith(".txt"):
source = relative[:-4] + ".py"
if source in explicit_set or source in seen_paths:
_mirror_for(root, source)
continue
if relative in seen_paths:
continue
row = _refresh_module_row(root, _generic_module_row(relative))
if row["module_id"] in seen_ids:
raise ReleaseBuildError(f"GENERATED_MODULE_ID_COLLISION:{row['module_id']}")
seen_ids.add(row["module_id"])
seen_paths.add(relative)
refreshed_rows.append(row)
result["modules"] = refreshed_rows
mirrors = [entry for row in refreshed_rows if (entry := _documentation_mirror(row))]
mirror_sources = [str(entry["source_path"]) for entry in mirrors]
if len(mirror_sources) != len(set(mirror_sources)):
raise ReleaseBuildError("DOCUMENTATION_MIRROR_SOURCE_DUPLICATE")
result["documentation_mirrors"] = sorted(
mirrors, key=lambda entry: str(entry["source_path"])
)
summary = result.get("closure_summary")
if not isinstance(summary, dict):
raise ReleaseBuildError("CLOSURE_SUMMARY_REQUIRED")
summary.update(
{
"module_count": len(refreshed_rows),
"documentation_mirror_count": len(mirrors),
"test_module_count": sum(
1 for row in refreshed_rows if row.get("module_kind") == "TEST"
),
"build_tool_module_count": sum(
1 for row in refreshed_rows if row.get("module_kind") == "BUILD_TOOL"
),
"s2_20_generic_module_count": sum(
1
for row in refreshed_rows
if row.get("schema_version") == "stage2_s2_20_generic_asset.v1"
),
"executable_agent_hash_included": False,
"executor_binding_hash_included": False,
"inline_runtime_code_hash_included": False,
"self_hash_included": False,
"stage2_release_hash_included": False,
}
)
result["manifest_digest"] = _document_digest(result, "manifest_digest")
return result
def _refresh_parent_refs(
value: Any,
root: Path,
raw_overrides: dict[str, bytes],
location: str = "$",
) -> None:
if isinstance(value, list):
for index, item in enumerate(value):
_refresh_parent_refs(item, root, raw_overrides, f"{location}/{index}")
return
if not isinstance(value, dict):
return
relative = value.get("path")
if isinstance(relative, str) and relative and "<" not in relative:
try:
relative = _relative_path(relative)
except ReleaseBuildError:
relative = None
if relative == "manifest/module_manifest.json":
raw = raw_overrides.get(relative)
if raw is None:
raise ReleaseBuildError("MODULE_MANIFEST_RAW_OVERRIDE_REQUIRED")
if "sha256" in value:
value["sha256"] = _sha256(raw)
if "size_bytes" in value:
value["size_bytes"] = len(raw)
elif relative in FORBIDDEN_PARENT_MEMBERS:
if "sha256" in value or value.get("binding_status") == "BOUND":
raise ReleaseBuildError(
f"NON_CYCLIC_PARENT_HASH_REFERENCE:{location}:{relative}"
)
elif relative is not None and (relative in raw_overrides or (root / relative).is_file()):
raw = raw_overrides.get(relative)
if raw is None:
raw = _asset_bytes(root, relative)
if "sha256" in value:
value["sha256"] = _sha256(raw)
if "size_bytes" in value:
value["size_bytes"] = len(raw)
for key, item in list(value.items()):
_refresh_parent_refs(item, root, raw_overrides, f"{location}/{key}")
def build_parent_release(
root: Path,
template: dict[str, Any],
module_manifest_raw: bytes,
) -> dict[str, Any]:
"""Refresh safe parent refs and its self digest without changing admission."""
if template.get("schema_version") != PARENT_RELEASE_SCHEMA:
raise ReleaseBuildError("PARENT_STAGE2_RELEASE_V2_REQUIRED")
result = copy.deepcopy(template)
immutable_admission = {
key: copy.deepcopy(result.get(key))
for key in (
"release_class",
"release_status",
"authorization_status",
"signature",
"release_evidence",
)
}
module_ref = result.get("module_manifest_ref")
if not isinstance(module_ref, dict) or module_ref.get("path") != "manifest/module_manifest.json":
raise ReleaseBuildError("PARENT_MODULE_MANIFEST_REF_REQUIRED")
module_ref["sha256"] = _sha256(module_manifest_raw)
if "size_bytes" in module_ref:
module_ref["size_bytes"] = len(module_manifest_raw)
executor_ref = result.get("executor_binding_ref")
if (
not isinstance(executor_ref, dict)
or executor_ref.get("path") != "deployment/stage2_code_executor_binding.yml"
):
raise ReleaseBuildError("PARENT_EXECUTOR_TRUST_ROOT_REF_REQUIRED")
if "sha256" in executor_ref or executor_ref.get("binding_status") == "BOUND":
raise ReleaseBuildError("PARENT_EXECUTOR_TRUST_ROOT_MUST_BE_UNHASHED")
executor_ref["schema_id"] = "stage2_code_executor_binding.v3"
_refresh_parent_refs(
result,
root,
{"manifest/module_manifest.json": module_manifest_raw},
)
bundle = result.get("bundle")
if isinstance(bundle, dict):
agent_ref = bundle.get("s2_10_agent_ref")
binding_ref = bundle.get("s2_10_llm_binding_ref")
if isinstance(agent_ref, dict) and isinstance(agent_ref.get("sha256"), str):
bundle["s2_10_agent_sha256"] = agent_ref["sha256"]
if isinstance(binding_ref, dict) and isinstance(binding_ref.get("sha256"), str):
bundle["s2_10_llm_binding_sha256"] = binding_ref["sha256"]
for key, expected in immutable_admission.items():
if result.get(key) != expected:
raise ReleaseBuildError(f"ADMISSION_STATE_MUTATION_FORBIDDEN:{key}")
result["release_digest"] = _document_digest(result, "release_digest")
return result
def build_release_package(
root: Path,
path_list: list[str],
module_template: dict[str, Any],
parent_template: dict[str, Any],
) -> tuple[dict[str, Any], dict[str, Any]]:
module_manifest = build_module_manifest(root, module_template, path_list)
module_raw = _canonical_bytes(module_manifest)
parent_release = build_parent_release(root, parent_template, module_raw)
return module_manifest, parent_release
def _write_bytes(path: Path, raw: bytes) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
temporary = path.with_name(f".{path.name}.tmp-{os.getpid()}")
temporary.write_bytes(raw)
os.replace(temporary, path)
def main() -> int:
parser = argparse.ArgumentParser(
description="Reseal canonical Stage-2 module and parent release manifests"
)
parser.add_argument("root", type=Path)
parser.add_argument("path_list", type=Path, help="JSON array of relative S2_20 paths")
parser.add_argument("output", type=Path, help="module_manifest.json output")
parser.add_argument(
"--module-template",
type=Path,
help="canonical module manifest template (default: ROOT/manifest/module_manifest.json)",
)
parser.add_argument(
"--parent-template",
type=Path,
help="parent release template (default: ROOT/manifest/stage2_release.json)",
)
parser.add_argument(
"--parent-output",
type=Path,
help="parent release output (default: OUTPUT sibling stage2_release.json)",
)
args = parser.parse_args()
path_list = _load_json(args.path_list)
if not isinstance(path_list, list) or not all(isinstance(row, str) for row in path_list):
raise ReleaseBuildError("PATH_LIST_MUST_BE_STRING_ARRAY")
module_template_path = args.module_template or args.root / "manifest/module_manifest.json"
parent_template_path = args.parent_template or args.root / "manifest/stage2_release.json"
parent_output = args.parent_output or args.output.with_name("stage2_release.json")
module_manifest, parent_release = build_release_package(
args.root,
path_list,
_load_json(module_template_path),
_load_json(parent_template_path),
)
_write_bytes(args.output, _canonical_bytes(module_manifest))
_write_bytes(parent_output, _canonical_bytes(parent_release))
print(
json.dumps(
{
"module_count": len(module_manifest["modules"]),
"module_manifest_output": args.output.as_posix(),
"module_manifest_sha256": _sha256(_canonical_bytes(module_manifest)),
"parent_release_output": parent_output.as_posix(),
"parent_release_sha256": _sha256(_canonical_bytes(parent_release)),
"status": "PASS",
},
sort_keys=True,
separators=(",", ":"),
)
)
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -33,6 +33,7 @@ PROJECTION_PATH = DEPLOYMENT_ROOT / "agent_scripts" / "Stage_2_S2_00.yml"
MIRROR_PY_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.py" MIRROR_PY_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.py"
MIRROR_TXT_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.txt" MIRROR_TXT_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.txt"
RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_00_inline_code_receipt.json" RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_00_inline_code_receipt.json"
BINDING_PATH = DEPLOYMENT_ROOT / "deployment" / "stage2_code_executor_binding.yml"
EXPECTED_TASK_NAME = "Task_S2_00_deterministic_ingress" EXPECTED_TASK_NAME = "Task_S2_00_deterministic_ingress"
EXPECTED_AGENT_NAME = "Stage_2_S2_00_v2" EXPECTED_AGENT_NAME = "Stage_2_S2_00_v2"
@@ -207,6 +208,66 @@ def load_authoring(path: Path | None = None) -> tuple[bytes, dict[str, Any]]:
return raw, parse_authoring_bytes(raw, source=path.as_posix()) return raw, parse_authoring_bytes(raw, source=path.as_posix())
def select_s2_00_binding(document: Mapping[str, Any]) -> dict[str, Any]:
"""Select the unique S2_00 row from the shared deterministic-stage binding.
The v3 wrapper replaces the former singleton v2 document. This selector
deliberately checks only migration/identity semantics; byte hashes are
resealed after projection generation by the release pipeline.
"""
if document.get("schema_version") != "stage2_code_executor_binding.v3":
raise ProjectionError(
"EXECUTOR_BINDING_SCHEMA_MISMATCH",
repr(document.get("schema_version")),
)
rows = _require_list(document.get("stage_bindings"), "STAGE_BINDINGS_ARRAY_REQUIRED")
stage_ids = [row.get("stage_id") for row in rows if isinstance(row, dict)]
if len(stage_ids) != len(rows) or len(set(stage_ids)) != len(stage_ids):
raise ProjectionError("STAGE_BINDING_ID_NOT_UNIQUE", repr(stage_ids))
matches = [row for row in rows if row.get("stage_id") == "S2_00"]
if len(matches) != 1:
raise ProjectionError("S2_00_BINDING_EXACT_ONE_REQUIRED", str(len(matches)))
row = _require_mapping(matches[0], "S2_00_BINDING_OBJECT_REQUIRED")
expected = {
"workflow_id": "S2_00",
"execution_class": "NON-LLM-DETERMINISTIC",
"mcp_server_id": "code-executor",
"tool_name": "run_code",
"language": "python",
"network": "agent-network",
}
drift = {
key: {"expected": value, "observed": row.get(key)}
for key, value in expected.items()
if row.get(key) != value
}
if row.get("active_runtime_authority") is not True:
drift["active_runtime_authority"] = {
"expected": True,
"observed": row.get("active_runtime_authority"),
}
if row.get("external_mcp_contract") is not None:
drift["external_mcp_contract"] = {
"expected": None,
"observed": row.get("external_mcp_contract"),
}
if drift:
raise ProjectionError(
"S2_00_BINDING_SEMANTICS_DRIFT",
json.dumps(drift, ensure_ascii=False, sort_keys=True),
)
return row
def load_s2_00_binding(path: Path | None = None) -> dict[str, Any]:
path = BINDING_PATH if path is None else path
if not path.is_file() or path.is_symlink():
raise ProjectionError("EXECUTOR_BINDING_UNAVAILABLE", path.as_posix())
wrapper = parse_authoring_bytes(path.read_bytes(), source=path.as_posix())
return select_s2_00_binding(wrapper)
def _require_mapping(value: Any, code: str) -> dict[str, Any]: def _require_mapping(value: Any, code: str) -> dict[str, Any]:
if not isinstance(value, dict): if not isinstance(value, dict):
raise ProjectionError(code, repr(value)[:200]) raise ProjectionError(code, repr(value)[:200])
@@ -738,6 +799,7 @@ def compare_outputs(outputs: Mapping[Path, bytes]) -> list[dict[str, Any]]:
def run(*, check: bool) -> tuple[int, dict[str, Any]]: def run(*, check: bool) -> tuple[int, dict[str, Any]]:
load_s2_00_binding()
before, document = load_authoring() before, document = load_authoring()
outputs, receipt = expected_outputs(before, document) outputs, receipt = expected_outputs(before, document)
if check: if check:
@@ -33,6 +33,7 @@ PROJECTION_PATH = DEPLOYMENT_ROOT / "agent_scripts" / "Stage_2_S2_00.yml"
MIRROR_PY_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.py" MIRROR_PY_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.py"
MIRROR_TXT_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.txt" MIRROR_TXT_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.txt"
RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_00_inline_code_receipt.json" RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_00_inline_code_receipt.json"
BINDING_PATH = DEPLOYMENT_ROOT / "deployment" / "stage2_code_executor_binding.yml"
EXPECTED_TASK_NAME = "Task_S2_00_deterministic_ingress" EXPECTED_TASK_NAME = "Task_S2_00_deterministic_ingress"
EXPECTED_AGENT_NAME = "Stage_2_S2_00_v2" EXPECTED_AGENT_NAME = "Stage_2_S2_00_v2"
@@ -207,6 +208,66 @@ def load_authoring(path: Path | None = None) -> tuple[bytes, dict[str, Any]]:
return raw, parse_authoring_bytes(raw, source=path.as_posix()) return raw, parse_authoring_bytes(raw, source=path.as_posix())
def select_s2_00_binding(document: Mapping[str, Any]) -> dict[str, Any]:
"""Select the unique S2_00 row from the shared deterministic-stage binding.
The v3 wrapper replaces the former singleton v2 document. This selector
deliberately checks only migration/identity semantics; byte hashes are
resealed after projection generation by the release pipeline.
"""
if document.get("schema_version") != "stage2_code_executor_binding.v3":
raise ProjectionError(
"EXECUTOR_BINDING_SCHEMA_MISMATCH",
repr(document.get("schema_version")),
)
rows = _require_list(document.get("stage_bindings"), "STAGE_BINDINGS_ARRAY_REQUIRED")
stage_ids = [row.get("stage_id") for row in rows if isinstance(row, dict)]
if len(stage_ids) != len(rows) or len(set(stage_ids)) != len(stage_ids):
raise ProjectionError("STAGE_BINDING_ID_NOT_UNIQUE", repr(stage_ids))
matches = [row for row in rows if row.get("stage_id") == "S2_00"]
if len(matches) != 1:
raise ProjectionError("S2_00_BINDING_EXACT_ONE_REQUIRED", str(len(matches)))
row = _require_mapping(matches[0], "S2_00_BINDING_OBJECT_REQUIRED")
expected = {
"workflow_id": "S2_00",
"execution_class": "NON-LLM-DETERMINISTIC",
"mcp_server_id": "code-executor",
"tool_name": "run_code",
"language": "python",
"network": "agent-network",
}
drift = {
key: {"expected": value, "observed": row.get(key)}
for key, value in expected.items()
if row.get(key) != value
}
if row.get("active_runtime_authority") is not True:
drift["active_runtime_authority"] = {
"expected": True,
"observed": row.get("active_runtime_authority"),
}
if row.get("external_mcp_contract") is not None:
drift["external_mcp_contract"] = {
"expected": None,
"observed": row.get("external_mcp_contract"),
}
if drift:
raise ProjectionError(
"S2_00_BINDING_SEMANTICS_DRIFT",
json.dumps(drift, ensure_ascii=False, sort_keys=True),
)
return row
def load_s2_00_binding(path: Path | None = None) -> dict[str, Any]:
path = BINDING_PATH if path is None else path
if not path.is_file() or path.is_symlink():
raise ProjectionError("EXECUTOR_BINDING_UNAVAILABLE", path.as_posix())
wrapper = parse_authoring_bytes(path.read_bytes(), source=path.as_posix())
return select_s2_00_binding(wrapper)
def _require_mapping(value: Any, code: str) -> dict[str, Any]: def _require_mapping(value: Any, code: str) -> dict[str, Any]:
if not isinstance(value, dict): if not isinstance(value, dict):
raise ProjectionError(code, repr(value)[:200]) raise ProjectionError(code, repr(value)[:200])
@@ -738,6 +799,7 @@ def compare_outputs(outputs: Mapping[Path, bytes]) -> list[dict[str, Any]]:
def run(*, check: bool) -> tuple[int, dict[str, Any]]: def run(*, check: bool) -> tuple[int, dict[str, Any]]:
load_s2_00_binding()
before, document = load_authoring() before, document = load_authoring()
outputs, receipt = expected_outputs(before, document) outputs, receipt = expected_outputs(before, document)
if check: if check:
@@ -1265,15 +1265,143 @@ def check() -> dict[str, Any]:
} }
def child_only_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]:
"""Reseal only the downstream S2_10 child chain against a frozen parent.
The canonical parent/module builder owns the raw parent closure. This mode
therefore never rewrites ``module_manifest.json``, ``stage2_release.json``,
the Agent projection, prompt receipt, or LLM binding.
"""
authoring_raw = _require_file(AUTHORING_PATH)
if _require_file(PROJECTION_PATH) != authoring_raw:
raise BuildError("S2_10_AGENT_PROJECTION_DRIFT", _logical_path(PROJECTION_PATH))
contract = extract_agent_contract(_load_yaml(authoring_raw, _logical_path(AUTHORING_PATH)))
binding_raw = _require_file(BINDING_PATH)
binding = _load_yaml(binding_raw, _logical_path(BINDING_PATH))
inline_receipt_raw = _require_file(INLINE_RECEIPT_PATH)
parent_raw = _require_file(PARENT_RELEASE_PATH)
child = build_child_release(parent_raw, binding)
child_raw = canonical_json_bytes(child)
outputs = {
CHILD_RELEASE_PATH: child_raw,
AGENT_RECEIPT_PATH: canonical_json_bytes(
build_agent_receipt(authoring_raw, binding_raw, child_raw, contract)
),
PLATFORM_RECEIPT_PATH: canonical_json_bytes(
build_platform_receipt(
parent_raw=parent_raw, binding_raw=binding_raw, child_raw=child_raw
)
),
MODEL_RECEIPT_PATH: canonical_json_bytes(
build_model_receipt(binding_raw=binding_raw, child_raw=child_raw)
),
LEGAL_RECEIPT_PATH: canonical_json_bytes(
build_legal_receipt(
binding_raw=binding_raw,
child_raw=child_raw,
inline_receipt_raw=inline_receipt_raw,
)
),
}
return outputs, {
"child_release_sha256": sha256_bytes(child_raw),
"parent_release_sha256": sha256_bytes(parent_raw),
}
def prerequisite_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]:
"""Build only the parent-owned S2_10 projection prerequisites."""
authoring_raw = _require_file(AUTHORING_PATH)
contract = extract_agent_contract(_load_yaml(authoring_raw, _logical_path(AUTHORING_PATH)))
inline_receipt = build_inline_receipt(authoring_raw, contract)
inline_receipt_raw = canonical_json_bytes(inline_receipt)
binding, producer_material = build_binding(authoring_raw, contract, inline_receipt_raw)
return {
PROJECTION_PATH: authoring_raw,
INLINE_RECEIPT_PATH: inline_receipt_raw,
BINDING_PATH: _yaml_bytes(binding),
}, {
"producer_contract_material": producer_material,
"producer_contract_digest": binding["producer_contract"]["s2_10_producer_contract_digest"],
}
def prerequisites_only(*, verify: bool) -> dict[str, Any]:
outputs, report = prerequisite_outputs()
drift: list[dict[str, Any]] = []
for path, expected in outputs.items():
observed = path.read_bytes() if path.is_file() and not path.is_symlink() else None
if observed != expected:
drift.append(
{
"path": _logical_path(path),
"expected_sha256": sha256_bytes(expected),
"observed_sha256": sha256_bytes(observed) if observed is not None else None,
}
)
if not verify:
_atomic_write(path, expected)
if verify and drift:
raise BuildError("S2_10_PREREQUISITE_DRIFT", json.dumps(drift, ensure_ascii=False))
return {
"status": "S2_10_PREREQUISITE_CHECK_PASS" if verify else "S2_10_PREREQUISITES_REBUILT",
"paths": [_logical_path(path) for path in outputs],
**report,
}
def child_only(*, verify: bool) -> dict[str, Any]:
outputs, report = child_only_outputs()
drift: list[dict[str, Any]] = []
for path, expected in outputs.items():
observed = path.read_bytes() if path.is_file() and not path.is_symlink() else None
if observed != expected:
drift.append(
{
"path": _logical_path(path),
"expected_sha256": sha256_bytes(expected),
"observed_sha256": sha256_bytes(observed) if observed is not None else None,
}
)
if not verify:
_atomic_write(path, expected)
if verify and drift:
raise BuildError("S2_10_CHILD_CHAIN_DRIFT", json.dumps(drift, ensure_ascii=False))
return {
"status": "S2_10_CHILD_CHAIN_CHECK_PASS" if verify else "S2_10_CHILD_CHAIN_RESEALED",
"paths": [_logical_path(path) for path in outputs],
**report,
}
def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace: def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__) parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--check", action="store_true", help="verify without writing") parser.add_argument("--check", action="store_true", help="verify without writing")
parser.add_argument(
"--child-only",
action="store_true",
help="reseal/check only child release and dependent receipts against the frozen parent",
)
parser.add_argument(
"--prerequisites-only",
action="store_true",
help="rebuild/check only Agent projection, inline prompt receipt, and LLM binding",
)
return parser.parse_args(argv) return parser.parse_args(argv)
def main(argv: Sequence[str] | None = None) -> int: def main(argv: Sequence[str] | None = None) -> int:
args = parse_args(argv) args = parse_args(argv)
try: try:
if args.child_only and args.prerequisites_only:
raise BuildError("BUILD_MODE_CONFLICT", "choose only one bounded reseal mode")
if args.child_only:
result = child_only(verify=args.check)
elif args.prerequisites_only:
result = prerequisites_only(verify=args.check)
else:
result = check() if args.check else build() result = check() if args.check else build()
except BuildError as exc: except BuildError as exc:
print(json.dumps({"status": "FAIL", "code": exc.code, "detail": exc.detail}, ensure_ascii=False)) print(json.dumps({"status": "FAIL", "code": exc.code, "detail": exc.detail}, ensure_ascii=False))
@@ -1265,15 +1265,143 @@ def check() -> dict[str, Any]:
} }
def child_only_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]:
"""Reseal only the downstream S2_10 child chain against a frozen parent.
The canonical parent/module builder owns the raw parent closure. This mode
therefore never rewrites ``module_manifest.json``, ``stage2_release.json``,
the Agent projection, prompt receipt, or LLM binding.
"""
authoring_raw = _require_file(AUTHORING_PATH)
if _require_file(PROJECTION_PATH) != authoring_raw:
raise BuildError("S2_10_AGENT_PROJECTION_DRIFT", _logical_path(PROJECTION_PATH))
contract = extract_agent_contract(_load_yaml(authoring_raw, _logical_path(AUTHORING_PATH)))
binding_raw = _require_file(BINDING_PATH)
binding = _load_yaml(binding_raw, _logical_path(BINDING_PATH))
inline_receipt_raw = _require_file(INLINE_RECEIPT_PATH)
parent_raw = _require_file(PARENT_RELEASE_PATH)
child = build_child_release(parent_raw, binding)
child_raw = canonical_json_bytes(child)
outputs = {
CHILD_RELEASE_PATH: child_raw,
AGENT_RECEIPT_PATH: canonical_json_bytes(
build_agent_receipt(authoring_raw, binding_raw, child_raw, contract)
),
PLATFORM_RECEIPT_PATH: canonical_json_bytes(
build_platform_receipt(
parent_raw=parent_raw, binding_raw=binding_raw, child_raw=child_raw
)
),
MODEL_RECEIPT_PATH: canonical_json_bytes(
build_model_receipt(binding_raw=binding_raw, child_raw=child_raw)
),
LEGAL_RECEIPT_PATH: canonical_json_bytes(
build_legal_receipt(
binding_raw=binding_raw,
child_raw=child_raw,
inline_receipt_raw=inline_receipt_raw,
)
),
}
return outputs, {
"child_release_sha256": sha256_bytes(child_raw),
"parent_release_sha256": sha256_bytes(parent_raw),
}
def prerequisite_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]:
"""Build only the parent-owned S2_10 projection prerequisites."""
authoring_raw = _require_file(AUTHORING_PATH)
contract = extract_agent_contract(_load_yaml(authoring_raw, _logical_path(AUTHORING_PATH)))
inline_receipt = build_inline_receipt(authoring_raw, contract)
inline_receipt_raw = canonical_json_bytes(inline_receipt)
binding, producer_material = build_binding(authoring_raw, contract, inline_receipt_raw)
return {
PROJECTION_PATH: authoring_raw,
INLINE_RECEIPT_PATH: inline_receipt_raw,
BINDING_PATH: _yaml_bytes(binding),
}, {
"producer_contract_material": producer_material,
"producer_contract_digest": binding["producer_contract"]["s2_10_producer_contract_digest"],
}
def prerequisites_only(*, verify: bool) -> dict[str, Any]:
outputs, report = prerequisite_outputs()
drift: list[dict[str, Any]] = []
for path, expected in outputs.items():
observed = path.read_bytes() if path.is_file() and not path.is_symlink() else None
if observed != expected:
drift.append(
{
"path": _logical_path(path),
"expected_sha256": sha256_bytes(expected),
"observed_sha256": sha256_bytes(observed) if observed is not None else None,
}
)
if not verify:
_atomic_write(path, expected)
if verify and drift:
raise BuildError("S2_10_PREREQUISITE_DRIFT", json.dumps(drift, ensure_ascii=False))
return {
"status": "S2_10_PREREQUISITE_CHECK_PASS" if verify else "S2_10_PREREQUISITES_REBUILT",
"paths": [_logical_path(path) for path in outputs],
**report,
}
def child_only(*, verify: bool) -> dict[str, Any]:
outputs, report = child_only_outputs()
drift: list[dict[str, Any]] = []
for path, expected in outputs.items():
observed = path.read_bytes() if path.is_file() and not path.is_symlink() else None
if observed != expected:
drift.append(
{
"path": _logical_path(path),
"expected_sha256": sha256_bytes(expected),
"observed_sha256": sha256_bytes(observed) if observed is not None else None,
}
)
if not verify:
_atomic_write(path, expected)
if verify and drift:
raise BuildError("S2_10_CHILD_CHAIN_DRIFT", json.dumps(drift, ensure_ascii=False))
return {
"status": "S2_10_CHILD_CHAIN_CHECK_PASS" if verify else "S2_10_CHILD_CHAIN_RESEALED",
"paths": [_logical_path(path) for path in outputs],
**report,
}
def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace: def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__) parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--check", action="store_true", help="verify without writing") parser.add_argument("--check", action="store_true", help="verify without writing")
parser.add_argument(
"--child-only",
action="store_true",
help="reseal/check only child release and dependent receipts against the frozen parent",
)
parser.add_argument(
"--prerequisites-only",
action="store_true",
help="rebuild/check only Agent projection, inline prompt receipt, and LLM binding",
)
return parser.parse_args(argv) return parser.parse_args(argv)
def main(argv: Sequence[str] | None = None) -> int: def main(argv: Sequence[str] | None = None) -> int:
args = parse_args(argv) args = parse_args(argv)
try: try:
if args.child_only and args.prerequisites_only:
raise BuildError("BUILD_MODE_CONFLICT", "choose only one bounded reseal mode")
if args.child_only:
result = child_only(verify=args.check)
elif args.prerequisites_only:
result = prerequisites_only(verify=args.check)
else:
result = check() if args.check else build() result = check() if args.check else build()
except BuildError as exc: except BuildError as exc:
print(json.dumps({"status": "FAIL", "code": exc.code, "detail": exc.detail}, ensure_ascii=False)) print(json.dumps({"status": "FAIL", "code": exc.code, "detail": exc.detail}, ensure_ascii=False))
@@ -0,0 +1,665 @@
#!/usr/bin/env python3
"""Build/check the S2_20 single-task inline Python projection.
The authoring YAML is the sole editable source. This offline tool rejects
duplicate YAML keys, validates the exact AgentBackend task graph and MCP
``run_code`` contract, compiles and audits parser-returned inline Python, then
projects authoring/code bytes without transformation. It never executes a
matter or imports Stage 2 runtime modules.
"""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
import os
from pathlib import Path
import re
import sys
import tempfile
from typing import Any, Iterable, Mapping
try:
import yaml
except ImportError: # pragma: no cover - incomplete offline build host
yaml = None # type: ignore[assignment]
DEPLOYMENT_ROOT = Path(__file__).resolve().parents[1]
MAIN_WORKING_DIRECTORY = DEPLOYMENT_ROOT.parent.parent
AUTHORING_PATH = MAIN_WORKING_DIRECTORY / "Stage_2_S2_20.yml"
PROJECTION_PATH = DEPLOYMENT_ROOT / "agent_scripts/Stage_2_S2_20.yml"
MIRROR_PY_PATH = DEPLOYMENT_ROOT / "runtime/s2_20_reduce.py"
MIRROR_TXT_PATH = DEPLOYMENT_ROOT / "runtime/s2_20_reduce.txt"
RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest/s2_20_inline_code_receipt.json"
EXPECTED_AGENT_NAME = "Stage_2_S2_20"
EXPECTED_AGENT_VERSION = "1.0.0"
EXPECTED_STAGE_NAME = "S2_20"
EXPECTED_TASK_NAME = "Task_S2_20_deterministic_relief_plan"
EXPECTED_PARAMETERS = {
"language": "python",
"requirements": "httpx==0.28.1",
"network": "agent-network",
"timeout": 300,
}
EXPECTED_LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp"
EXPECTED_CODE_EXECUTOR_URL = "https://code-executor.mcp.eroomai.com/mcp"
EXPECTED_WEAVIATE_URL = "https://weaviate.eroomai.com/mcp"
ALLOWED_CODE_URLS = frozenset({EXPECTED_LOCALDOCS_URL, EXPECTED_WEAVIATE_URL})
ALLOWED_NON_STDLIB_IMPORTS = frozenset({"httpx"})
FORBIDDEN_IMPORT_ROOTS = frozenset(
{"ftplib", "http", "importlib", "smtplib", "socket", "subprocess", "telnetlib", "urllib", "xmlrpc"}
)
FORBIDDEN_CALL_NAMES = frozenset({"__import__", "compile", "eval", "exec", "open"})
FORBIDDEN_ATTRIBUTE_CALLS = frozenset(
{
("os", "popen"),
("os", "system"),
("os", "spawnl"),
("os", "spawnle"),
("os", "spawnlp"),
("os", "spawnlpe"),
("os", "spawnv"),
("os", "spawnve"),
("os", "spawnvp"),
("os", "spawnvpe"),
}
)
MODEL_FIELDS = frozenset({"llm_provider", "llm_model", "llm_reasoning", "llm_verbosity", "prompt"})
REQUIRED_CODE_TOKENS = (
EXPECTED_LOCALDOCS_URL,
EXPECTED_WEAVIATE_URL,
"EXPECTED_STAGE2_RELEASE_SHA256",
"{{__user_hash__}}",
"{{__workspace_hash__}}",
"read_binary_doc",
"write_binary_file",
"plan_publish_status.json",
"build_portfolio",
"build_party_projection",
"calculate_all",
"build_retrieval_branch",
"execute_core",
"publish",
"publish_diagnostic",
)
URL_RE = re.compile(r"https?://[^\s'\"]+")
PYTHON_SOURCE_REF_RE = re.compile(r"(?i)(?:^|[/\\])[^\r\n'\"]+\.py(?:$|[?#])")
PLACEHOLDER_COMMENT_RE = re.compile(
r"(?im)^\s*#\s*(?:TODO|FIXME|TBD|PLACEHOLDER|OMITTED\s+BODY|IMPLEMENT\s+ME)\b"
)
PLAINTEXT_SECRET_RES = (
re.compile(r"(?i)\bAuthorization\s*:\s*Bearer\s+\S+"),
re.compile(r"(?i)\bBearer\s+[A-Za-z0-9+/=_-]{12,}"),
re.compile(
r"(?i)\b(?:MCP_API_KEY|API_KEY|ACCESS_TOKEN|AUTH_TOKEN|CLIENT_SECRET)\s*=\s*['\"][^'\"]+['\"]"
),
)
class ProjectionError(RuntimeError):
"""Controlled build failure with a stable reason code."""
def __init__(self, code: str, detail: str) -> None:
super().__init__(f"{code}: {detail}")
self.code = code
self.detail = detail
if yaml is not None:
class UniqueKeySafeLoader(yaml.SafeLoader):
"""SafeLoader variant that rejects duplicate mapping keys recursively."""
def construct_mapping(self, node: Any, deep: bool = False) -> dict[Any, Any]:
if not isinstance(node, yaml.MappingNode):
raise ProjectionError("YAML_MAPPING_REQUIRED", repr(node)[:200])
self.flatten_mapping(node)
result: dict[Any, Any] = {}
for key_node, value_node in node.value:
key = self.construct_object(key_node, deep=deep)
try:
duplicate = key in result
except TypeError as exc:
raise ProjectionError("YAML_UNHASHABLE_KEY", repr(key)[:200]) from exc
if duplicate:
mark = getattr(key_node, "start_mark", None)
line = mark.line + 1 if mark is not None else "?"
raise ProjectionError("YAML_DUPLICATE_KEY", f"{key!r}@line={line}")
result[key] = self.construct_object(value_node, deep=deep)
return result
else: # pragma: no cover
class UniqueKeySafeLoader: # type: ignore[no-redef]
pass
def sha256_bytes(value: bytes) -> str:
return hashlib.sha256(value).hexdigest()
def canonical_json_bytes(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, allow_nan=False, sort_keys=True, separators=(",", ":"))
+ "\n"
).encode("utf-8")
def _logical_path(path: Path) -> str:
try:
return path.resolve(strict=False).relative_to(MAIN_WORKING_DIRECTORY.resolve(strict=False)).as_posix()
except ValueError:
return path.as_posix()
def _require_mapping(value: Any, code: str) -> dict[str, Any]:
if not isinstance(value, dict):
raise ProjectionError(code, repr(value)[:300])
return value
def _require_list(value: Any, code: str) -> list[Any]:
if not isinstance(value, list):
raise ProjectionError(code, repr(value)[:300])
return value
def parse_authoring_bytes(raw: bytes, *, source: str = "<authoring>") -> dict[str, Any]:
if yaml is None:
raise ProjectionError("PYYAML_REQUIRED", "install PyYAML on offline build host")
try:
text = raw.decode("utf-8")
except UnicodeDecodeError as exc:
raise ProjectionError("AUTHORING_UTF8_REQUIRED", f"{source}: {exc}") from exc
if text.startswith("\ufeff"):
raise ProjectionError("AUTHORING_UTF8_BOM_FORBIDDEN", source)
for pattern in PLAINTEXT_SECRET_RES:
if pattern.search(text):
raise ProjectionError("AUTHORING_PLAINTEXT_SECRET", pattern.pattern)
try:
document = yaml.load(text, Loader=UniqueKeySafeLoader)
except ProjectionError:
raise
except yaml.YAMLError as exc:
raise ProjectionError("AUTHORING_YAML_INVALID", f"{source}: {exc}") from exc
if not isinstance(document, dict):
raise ProjectionError("AUTHORING_ROOT_OBJECT_REQUIRED", source)
return document
def load_authoring(path: Path | None = None) -> tuple[bytes, dict[str, Any]]:
selected = AUTHORING_PATH if path is None else path
if not selected.is_file() or selected.is_symlink():
raise ProjectionError("AUTHORING_YAML_MISSING_OR_SYMLINK", selected.as_posix())
raw = selected.read_bytes()
return raw, parse_authoring_bytes(raw, source=selected.as_posix())
def _find_forbidden_model_fields(value: Any, *, pointer: str = "") -> list[str]:
findings: list[str] = []
if isinstance(value, dict):
for key, child in value.items():
child_pointer = f"{pointer}/{key}"
if key in MODEL_FIELDS:
findings.append(child_pointer)
findings.extend(_find_forbidden_model_fields(child, pointer=child_pointer))
elif isinstance(value, list):
for index, child in enumerate(value):
findings.extend(_find_forbidden_model_fields(child, pointer=f"{pointer}/{index}"))
return findings
def extract_run_code_task(document: Mapping[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]:
agent = _require_mapping(document.get("Agent"), "AGENT_OBJECT_REQUIRED")
if agent.get("name") != EXPECTED_AGENT_NAME or agent.get("version") != EXPECTED_AGENT_VERSION:
raise ProjectionError(
"AGENT_IDENTITY_MISMATCH",
f"expected={EXPECTED_AGENT_NAME}/{EXPECTED_AGENT_VERSION} observed={agent.get('name')}/{agent.get('version')}",
)
forbidden_model_fields = _find_forbidden_model_fields(agent)
if forbidden_model_fields:
raise ProjectionError("LLM_OR_PROMPT_FIELD_FORBIDDEN", repr(forbidden_model_fields))
stages = _require_list(agent.get("Stages"), "STAGES_ARRAY_REQUIRED")
if len(stages) != 1:
raise ProjectionError("EXACTLY_ONE_STAGE_REQUIRED", str(len(stages)))
stage = _require_mapping(stages[0], "STAGE_OBJECT_REQUIRED")
if stage.get("name") != EXPECTED_STAGE_NAME:
raise ProjectionError("S2_20_STAGE_NAME_REQUIRED", repr(stage.get("name")))
if stage.get("skip_confirm") is not True:
raise ProjectionError("S2_20_SKIP_CONFIRM_TRUE_REQUIRED", repr(stage.get("skip_confirm")))
if stage.get("prevs") != [] or stage.get("nexts") != []:
raise ProjectionError("STANDALONE_STAGE_EDGES_MUST_BE_EMPTY", repr(stage))
servers = _require_mapping(
_require_mapping(stage.get("tools"), "TOOLS_OBJECT_REQUIRED").get("mcpServers"),
"MCP_SERVERS_OBJECT_REQUIRED",
)
if set(servers) != {"localdocs", "code-executor"}:
raise ProjectionError("MCP_SERVER_SET_MISMATCH", repr(sorted(servers)))
expected_servers = {
"localdocs": {"type": "streamable-http", "url": EXPECTED_LOCALDOCS_URL},
"code-executor": {"type": "streamable-http", "url": EXPECTED_CODE_EXECUTOR_URL},
}
for name, expected in expected_servers.items():
observed = _require_mapping(servers.get(name), f"{name.upper()}_SERVER_REQUIRED")
if observed != expected:
raise ProjectionError("MCP_SERVER_BINDING_INVALID", f"{name}:{observed!r}")
tasks = _require_list(stage.get("tasks"), "TASKS_ARRAY_REQUIRED")
if len(tasks) != 1:
raise ProjectionError("EXACTLY_ONE_TASK_REQUIRED", str(len(tasks)))
task = _require_mapping(tasks[0], "TASK_OBJECT_REQUIRED")
run_code_tasks = [
value
for candidate_stage in stages
for value in _require_list(
_require_mapping(candidate_stage, "STAGE_OBJECT_REQUIRED").get("tasks"),
"TASKS_ARRAY_REQUIRED",
)
if isinstance(value, dict)
and value.get("mcp") == "code-executor"
and value.get("tool_name") == "run_code"
]
if len(run_code_tasks) != 1:
raise ProjectionError("EXACTLY_ONE_CODE_EXECUTOR_RUN_CODE_REQUIRED", str(len(run_code_tasks)))
if task.get("task_name") != EXPECTED_TASK_NAME:
raise ProjectionError("TASK_NAME_MISMATCH", repr(task.get("task_name")))
if task.get("mcp") != "code-executor" or task.get("tool_name") != "run_code":
raise ProjectionError("RUN_CODE_TASK_BINDING_MISMATCH", repr(task))
parameters = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")
if set(parameters) != set(EXPECTED_PARAMETERS) | {"code"}:
raise ProjectionError("RUN_CODE_PARAMETER_SET_MISMATCH", repr(sorted(parameters)))
for key, expected in EXPECTED_PARAMETERS.items():
if parameters.get(key) != expected:
raise ProjectionError(
"RUN_CODE_PARAMETER_MISMATCH", f"{key}: expected={expected!r} observed={parameters.get(key)!r}"
)
code = parameters.get("code")
if not isinstance(code, str) or not code:
raise ProjectionError("INLINE_CODE_REQUIRED", repr(code)[:200])
if code.endswith(("\n", "\r")):
raise ProjectionError(
"INLINE_CODE_TRAILING_NEWLINE_FORBIDDEN",
"use code: |-; parser-returned code bytes must not be transformed",
)
expected_procedure = {
"IN": {"nexts": [EXPECTED_TASK_NAME], "wait_until": []},
EXPECTED_TASK_NAME: {"nexts": ["OUT"], "wait_until": ["IN"]},
"OUT": {"nexts": [], "wait_until": [EXPECTED_TASK_NAME]},
}
procedure = _require_mapping(stage.get("task_procedure"), "TASK_PROCEDURE_REQUIRED")
if procedure != expected_procedure:
raise ProjectionError("TASK_PROCEDURE_EXACT_IN_TASK_OUT_REQUIRED", repr(procedure)[:800])
description = stage.get("description")
if not isinstance(description, str) or not all(token in description for token in ("C20", "C21", "C25", "C26", "C22", "C27", "C28", "C29", "C30", "C35")):
raise ProjectionError("INTERNAL_DAG_DESCRIPTION_REQUIRED", repr(description))
return stage, task
def extract_code(raw: bytes) -> bytes:
"""Backward-compatible parser-based extraction used by existing tests."""
document = parse_authoring_bytes(raw)
_, task = extract_run_code_task(document)
parameters = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")
return parameters["code"].encode("utf-8")
def _import_root(name: str | None) -> str:
return (name or "").split(".", 1)[0]
def _assigned_names(node: ast.Assign | ast.AnnAssign) -> set[str]:
targets = node.targets if isinstance(node, ast.Assign) else [node.target]
return {target.id for target in targets if isinstance(target, ast.Name)}
def validate_inline_code(code: str) -> dict[str, Any]:
try:
compile(code, "<Stage_2_S2_20.parameters.code>", "exec", dont_inherit=True)
tree = ast.parse(code, filename="<Stage_2_S2_20.parameters.code>", mode="exec")
except (SyntaxError, ValueError, UnicodeError) as exc:
raise ProjectionError("INLINE_CODE_COMPILE_FAILED", str(exc)) from exc
missing_tokens = [token for token in REQUIRED_CODE_TOKENS if token not in code]
if missing_tokens:
raise ProjectionError("INLINE_CODE_REQUIRED_TOKEN_MISSING", repr(missing_tokens))
if PLACEHOLDER_COMMENT_RE.search(code):
raise ProjectionError("INLINE_CODE_PLACEHOLDER_COMMENT", "TODO/FIXME/TBD placeholder")
for pattern in PLAINTEXT_SECRET_RES:
if pattern.search(code):
raise ProjectionError("INLINE_CODE_PLAINTEXT_SECRET", pattern.pattern)
imports: set[str] = set()
import_aliases: dict[str, str] = {}
forbidden_callable_aliases: set[str] = set()
forbidden_nodes: list[str] = []
external_source_refs: set[str] = set()
observed_urls: set[str] = set()
release_constants: list[str] = []
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for alias in node.names:
root = _import_root(alias.name)
imports.add(root)
import_aliases[alias.asname or root] = root
elif isinstance(node, ast.ImportFrom):
root = _import_root(node.module)
imports.add(root)
if node.level:
forbidden_nodes.append(f"relative-import:{node.module or ''}")
for alias in node.names:
local = alias.asname or alias.name
if root == "builtins" and alias.name in FORBIDDEN_CALL_NAMES:
forbidden_callable_aliases.add(local)
if root == "os" and (
("os", alias.name) in FORBIDDEN_ATTRIBUTE_CALLS or alias.name.startswith("exec")
):
forbidden_callable_aliases.add(local)
for node in ast.walk(tree):
if isinstance(node, (ast.Assign, ast.AnnAssign)):
value = node.value
names = _assigned_names(node)
if isinstance(value, ast.Name) and (
value.id in FORBIDDEN_CALL_NAMES or value.id in forbidden_callable_aliases
):
forbidden_callable_aliases.update(names)
if isinstance(value, ast.Attribute) and isinstance(value.value, ast.Name):
module = import_aliases.get(value.value.id, value.value.id)
if (module, value.attr) in FORBIDDEN_ATTRIBUTE_CALLS or (
module == "os" and value.attr.startswith("exec")
):
forbidden_callable_aliases.update(names)
if (
"EXPECTED_STAGE2_RELEASE_SHA256" in names
and isinstance(value, ast.Constant)
and isinstance(value.value, str)
):
release_constants.append(value.value)
elif isinstance(node, ast.Call):
if isinstance(node.func, ast.Name) and (
node.func.id in FORBIDDEN_CALL_NAMES or node.func.id in forbidden_callable_aliases
):
forbidden_nodes.append(f"call:{node.func.id}")
elif isinstance(node.func, ast.Attribute) and isinstance(node.func.value, ast.Name):
module = import_aliases.get(node.func.value.id, node.func.value.id)
if (module, node.func.attr) in FORBIDDEN_ATTRIBUTE_CALLS or (
module == "os" and node.func.attr.startswith("exec")
):
forbidden_nodes.append(f"call:{module}.{node.func.attr}")
elif isinstance(node, ast.Pass):
forbidden_nodes.append("Pass")
elif isinstance(node, ast.Raise):
target = node.exc.func if isinstance(node.exc, ast.Call) else node.exc
if isinstance(target, ast.Name) and target.id == "NotImplementedError":
forbidden_nodes.append("raise:NotImplementedError")
elif isinstance(node, ast.Constant):
if node.value is Ellipsis:
forbidden_nodes.append("Ellipsis")
if isinstance(node.value, str):
observed_urls.update(match.rstrip(".,);]") for match in URL_RE.findall(node.value))
if PYTHON_SOURCE_REF_RE.search(node.value.strip()):
external_source_refs.add(node.value[:200])
imports.discard("")
disallowed_imports = sorted(
value
for value in imports
if value in FORBIDDEN_IMPORT_ROOTS
or (value not in sys.stdlib_module_names and value not in ALLOWED_NON_STDLIB_IMPORTS)
)
if disallowed_imports:
raise ProjectionError("INLINE_CODE_IMPORT_FORBIDDEN", repr(disallowed_imports))
if forbidden_nodes:
raise ProjectionError("INLINE_CODE_DYNAMIC_OR_PLACEHOLDER_FORBIDDEN", repr(forbidden_nodes))
if external_source_refs:
raise ProjectionError("INLINE_CODE_EXTERNAL_PY_SOURCE_REF_FORBIDDEN", repr(sorted(external_source_refs)))
if observed_urls != set(ALLOWED_CODE_URLS):
raise ProjectionError(
"INLINE_CODE_ENDPOINT_LITERAL_SET_MISMATCH",
json.dumps(
{"expected": sorted(ALLOWED_CODE_URLS), "observed": sorted(observed_urls)},
ensure_ascii=False,
sort_keys=True,
),
)
if len(release_constants) != 1 or not re.fullmatch(r"[a-f0-9]{64}", release_constants[0]):
raise ProjectionError("EXPECTED_PARENT_RELEASE_CONSTANT_EXACT_ONE_REQUIRED", repr(release_constants))
code_bytes = code.encode("utf-8")
return {
"yaml_pointer": "/Agent/Stages/0/tasks/0/parameters/code",
"encoding": "UTF-8",
"extraction_transform": "NONE",
"code_sha256": sha256_bytes(code_bytes),
"code_size_bytes": len(code_bytes),
"compile_status": "PASS",
"ast_status": "PASS",
"imports": sorted(imports),
"forbidden_import_count": 0,
"forbidden_dynamic_call_count": 0,
"external_python_source_ref_count": 0,
"plaintext_secret_count": 0,
"endpoint_literals": sorted(observed_urls),
"expected_parent_stage2_release_sha256": release_constants[0],
}
def validate_agent(raw: bytes, code: bytes | None = None) -> dict[str, Any]:
"""Backward-compatible complete validation of authoring and extracted code."""
document = parse_authoring_bytes(raw)
_, task = extract_run_code_task(document)
parsed_code = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")["code"]
parsed_bytes = parsed_code.encode("utf-8")
if code is not None and code != parsed_bytes:
raise ProjectionError("EXTRACTED_CODE_BYTES_DRIFT", sha256_bytes(code))
return validate_inline_code(parsed_code)
def _canonical_task_semantics(
document: Mapping[str, Any], stage: Mapping[str, Any], task: Mapping[str, Any]
) -> dict[str, Any]:
agent = _require_mapping(document.get("Agent"), "AGENT_OBJECT_REQUIRED")
servers = _require_mapping(
_require_mapping(stage.get("tools"), "TOOLS_OBJECT_REQUIRED").get("mcpServers"),
"MCP_SERVERS_OBJECT_REQUIRED",
)
parameters = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")
return {
"agent": {"name": agent.get("name"), "version": agent.get("version")},
"stage": {
"name": stage.get("name"),
"prevs": stage.get("prevs"),
"nexts": stage.get("nexts"),
"skip_confirm": stage.get("skip_confirm"),
},
"mcp_servers": {
name: {"type": value.get("type"), "url": value.get("url")}
for name, value in sorted(servers.items())
if isinstance(value, dict)
},
"task": {
"task_name": task.get("task_name"),
"mcp": task.get("mcp"),
"tool_name": task.get("tool_name"),
"parameters": {key: parameters.get(key) for key in EXPECTED_PARAMETERS},
"code_sha256": sha256_bytes(parameters["code"].encode("utf-8")),
},
"task_procedure": stage.get("task_procedure"),
"internal_dag": "(C20||C21)->C25->C26->(C22||(C27->C28->C29))->C30->C35",
}
def expected_outputs(
authoring_raw: bytes, document: Mapping[str, Any]
) -> tuple[dict[Path, bytes], dict[str, Any]]:
stage, task = extract_run_code_task(document)
parameters = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")
code = parameters["code"]
validation = validate_inline_code(code)
code_bytes = code.encode("utf-8")
semantics = _canonical_task_semantics(document, stage, task)
receipt = {
"schema_version": "stage2_s2_20_inline_code_receipt.v1",
"workflow_id": "S2_20",
"authoring": {
"path": _logical_path(AUTHORING_PATH),
"sha256": sha256_bytes(authoring_raw),
"size_bytes": len(authoring_raw),
},
"deployment_projection": {
"path": _logical_path(PROJECTION_PATH),
"sha256": sha256_bytes(authoring_raw),
"size_bytes": len(authoring_raw),
},
"canonical_code": validation,
"full_code_mirrors": [_logical_path(MIRROR_PY_PATH), _logical_path(MIRROR_TXT_PATH)],
"task_contract": {
**semantics,
"canonical_task_semantics_sha256": sha256_bytes(canonical_json_bytes(semantics)),
"exactly_one_stage": True,
"exactly_one_task": True,
"exactly_one_code_executor_run_code": True,
"authoring_rewritten": False,
"projection_byte_identical_to_authoring": True,
"code_mirrors_byte_identical": True,
"expected_parent_stage2_release_sha256": validation[
"expected_parent_stage2_release_sha256"
],
},
"parity_status": "PASS",
}
outputs = {
PROJECTION_PATH: authoring_raw,
MIRROR_PY_PATH: code_bytes,
MIRROR_TXT_PATH: code_bytes,
RECEIPT_PATH: canonical_json_bytes(receipt),
}
return outputs, receipt
def _assert_output_target(path: Path) -> None:
root = DEPLOYMENT_ROOT.resolve(strict=True)
resolved = path.resolve(strict=False)
try:
resolved.relative_to(root)
except ValueError as exc:
raise ProjectionError("OUTPUT_OUTSIDE_DEPLOYMENT_ROOT", path.as_posix()) from exc
if path.exists() and path.is_symlink():
raise ProjectionError("OUTPUT_SYMLINK_FORBIDDEN", path.as_posix())
def _atomic_write(path: Path, payload: bytes) -> None:
_assert_output_target(path)
path.parent.mkdir(parents=True, exist_ok=True)
temporary_name: str | None = None
try:
with tempfile.NamedTemporaryFile(
mode="wb",
dir=path.parent,
prefix=f".{path.name}.",
suffix=".tmp",
delete=False,
) as handle:
temporary_name = handle.name
handle.write(payload)
handle.flush()
os.fsync(handle.fileno())
os.replace(temporary_name, path)
temporary_name = None
finally:
if temporary_name is not None:
try:
Path(temporary_name).unlink()
except FileNotFoundError:
pass
def compare_outputs(outputs: Mapping[Path, bytes]) -> list[dict[str, Any]]:
mismatches: list[dict[str, Any]] = []
for path, expected in outputs.items():
if not path.is_file():
mismatches.append(
{"path": _logical_path(path), "status": "MISSING", "expected_sha256": sha256_bytes(expected)}
)
continue
observed = path.read_bytes()
if observed != expected:
mismatches.append(
{
"path": _logical_path(path),
"status": "BYTE_MISMATCH",
"expected_sha256": sha256_bytes(expected),
"observed_sha256": sha256_bytes(observed),
}
)
return mismatches
def run(*, check: bool) -> tuple[int, dict[str, Any]]:
before, document = load_authoring()
outputs, receipt = expected_outputs(before, document)
if check:
mismatches = compare_outputs(outputs)
return (
0 if not mismatches else 1,
{
"status": "PARITY_PASS" if not mismatches else "PARITY_DRIFT",
"mode": "CHECK_NO_WRITE",
"authoring_sha256": sha256_bytes(before),
"code_sha256": receipt["canonical_code"]["code_sha256"],
"mismatches": mismatches,
},
)
receipt_payload = outputs[RECEIPT_PATH]
for path, payload in outputs.items():
if path != RECEIPT_PATH:
_atomic_write(path, payload)
if AUTHORING_PATH.read_bytes() != before:
raise ProjectionError("AUTHORING_CHANGED_DURING_BUILD", AUTHORING_PATH.as_posix())
_atomic_write(RECEIPT_PATH, receipt_payload)
if AUTHORING_PATH.read_bytes() != before:
raise ProjectionError("AUTHORING_CHANGED_DURING_RECEIPT_WRITE", AUTHORING_PATH.as_posix())
mismatches = compare_outputs(outputs)
if mismatches:
raise ProjectionError("POST_BUILD_PARITY_FAILED", json.dumps(mismatches, sort_keys=True))
return 0, {
"status": "BUILT_AND_VERIFIED",
"mode": "BUILD",
"authoring_sha256": sha256_bytes(before),
"code_sha256": receipt["canonical_code"]["code_sha256"],
"outputs": [_logical_path(path) for path in outputs],
}
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="Build or verify S2_20 inline Agent projection")
parser.add_argument("--check", action="store_true", help="no-write byte parity check")
return parser
def main(argv: Iterable[str] | None = None) -> int:
args = _parser().parse_args(list(argv) if argv is not None else None)
try:
status, payload = run(check=args.check)
except ProjectionError as exc:
status = 3 if exc.code == "AUTHORING_YAML_MISSING_OR_SYMLINK" else 2
payload = {
"status": "CONTROLLED_MISSING_AUTHORING" if status == 3 else "BUILD_FAILED",
"reason_code": exc.code,
"detail": exc.detail,
"mode": "CHECK_NO_WRITE" if args.check else "BUILD",
}
print(json.dumps(payload, ensure_ascii=False, allow_nan=False, sort_keys=True))
return status
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,665 @@
#!/usr/bin/env python3
"""Build/check the S2_20 single-task inline Python projection.
The authoring YAML is the sole editable source. This offline tool rejects
duplicate YAML keys, validates the exact AgentBackend task graph and MCP
``run_code`` contract, compiles and audits parser-returned inline Python, then
projects authoring/code bytes without transformation. It never executes a
matter or imports Stage 2 runtime modules.
"""
from __future__ import annotations
import argparse
import ast
import hashlib
import json
import os
from pathlib import Path
import re
import sys
import tempfile
from typing import Any, Iterable, Mapping
try:
import yaml
except ImportError: # pragma: no cover - incomplete offline build host
yaml = None # type: ignore[assignment]
DEPLOYMENT_ROOT = Path(__file__).resolve().parents[1]
MAIN_WORKING_DIRECTORY = DEPLOYMENT_ROOT.parent.parent
AUTHORING_PATH = MAIN_WORKING_DIRECTORY / "Stage_2_S2_20.yml"
PROJECTION_PATH = DEPLOYMENT_ROOT / "agent_scripts/Stage_2_S2_20.yml"
MIRROR_PY_PATH = DEPLOYMENT_ROOT / "runtime/s2_20_reduce.py"
MIRROR_TXT_PATH = DEPLOYMENT_ROOT / "runtime/s2_20_reduce.txt"
RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest/s2_20_inline_code_receipt.json"
EXPECTED_AGENT_NAME = "Stage_2_S2_20"
EXPECTED_AGENT_VERSION = "1.0.0"
EXPECTED_STAGE_NAME = "S2_20"
EXPECTED_TASK_NAME = "Task_S2_20_deterministic_relief_plan"
EXPECTED_PARAMETERS = {
"language": "python",
"requirements": "httpx==0.28.1",
"network": "agent-network",
"timeout": 300,
}
EXPECTED_LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp"
EXPECTED_CODE_EXECUTOR_URL = "https://code-executor.mcp.eroomai.com/mcp"
EXPECTED_WEAVIATE_URL = "https://weaviate.eroomai.com/mcp"
ALLOWED_CODE_URLS = frozenset({EXPECTED_LOCALDOCS_URL, EXPECTED_WEAVIATE_URL})
ALLOWED_NON_STDLIB_IMPORTS = frozenset({"httpx"})
FORBIDDEN_IMPORT_ROOTS = frozenset(
{"ftplib", "http", "importlib", "smtplib", "socket", "subprocess", "telnetlib", "urllib", "xmlrpc"}
)
FORBIDDEN_CALL_NAMES = frozenset({"__import__", "compile", "eval", "exec", "open"})
FORBIDDEN_ATTRIBUTE_CALLS = frozenset(
{
("os", "popen"),
("os", "system"),
("os", "spawnl"),
("os", "spawnle"),
("os", "spawnlp"),
("os", "spawnlpe"),
("os", "spawnv"),
("os", "spawnve"),
("os", "spawnvp"),
("os", "spawnvpe"),
}
)
MODEL_FIELDS = frozenset({"llm_provider", "llm_model", "llm_reasoning", "llm_verbosity", "prompt"})
REQUIRED_CODE_TOKENS = (
EXPECTED_LOCALDOCS_URL,
EXPECTED_WEAVIATE_URL,
"EXPECTED_STAGE2_RELEASE_SHA256",
"{{__user_hash__}}",
"{{__workspace_hash__}}",
"read_binary_doc",
"write_binary_file",
"plan_publish_status.json",
"build_portfolio",
"build_party_projection",
"calculate_all",
"build_retrieval_branch",
"execute_core",
"publish",
"publish_diagnostic",
)
URL_RE = re.compile(r"https?://[^\s'\"]+")
PYTHON_SOURCE_REF_RE = re.compile(r"(?i)(?:^|[/\\])[^\r\n'\"]+\.py(?:$|[?#])")
PLACEHOLDER_COMMENT_RE = re.compile(
r"(?im)^\s*#\s*(?:TODO|FIXME|TBD|PLACEHOLDER|OMITTED\s+BODY|IMPLEMENT\s+ME)\b"
)
PLAINTEXT_SECRET_RES = (
re.compile(r"(?i)\bAuthorization\s*:\s*Bearer\s+\S+"),
re.compile(r"(?i)\bBearer\s+[A-Za-z0-9+/=_-]{12,}"),
re.compile(
r"(?i)\b(?:MCP_API_KEY|API_KEY|ACCESS_TOKEN|AUTH_TOKEN|CLIENT_SECRET)\s*=\s*['\"][^'\"]+['\"]"
),
)
class ProjectionError(RuntimeError):
"""Controlled build failure with a stable reason code."""
def __init__(self, code: str, detail: str) -> None:
super().__init__(f"{code}: {detail}")
self.code = code
self.detail = detail
if yaml is not None:
class UniqueKeySafeLoader(yaml.SafeLoader):
"""SafeLoader variant that rejects duplicate mapping keys recursively."""
def construct_mapping(self, node: Any, deep: bool = False) -> dict[Any, Any]:
if not isinstance(node, yaml.MappingNode):
raise ProjectionError("YAML_MAPPING_REQUIRED", repr(node)[:200])
self.flatten_mapping(node)
result: dict[Any, Any] = {}
for key_node, value_node in node.value:
key = self.construct_object(key_node, deep=deep)
try:
duplicate = key in result
except TypeError as exc:
raise ProjectionError("YAML_UNHASHABLE_KEY", repr(key)[:200]) from exc
if duplicate:
mark = getattr(key_node, "start_mark", None)
line = mark.line + 1 if mark is not None else "?"
raise ProjectionError("YAML_DUPLICATE_KEY", f"{key!r}@line={line}")
result[key] = self.construct_object(value_node, deep=deep)
return result
else: # pragma: no cover
class UniqueKeySafeLoader: # type: ignore[no-redef]
pass
def sha256_bytes(value: bytes) -> str:
return hashlib.sha256(value).hexdigest()
def canonical_json_bytes(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, allow_nan=False, sort_keys=True, separators=(",", ":"))
+ "\n"
).encode("utf-8")
def _logical_path(path: Path) -> str:
try:
return path.resolve(strict=False).relative_to(MAIN_WORKING_DIRECTORY.resolve(strict=False)).as_posix()
except ValueError:
return path.as_posix()
def _require_mapping(value: Any, code: str) -> dict[str, Any]:
if not isinstance(value, dict):
raise ProjectionError(code, repr(value)[:300])
return value
def _require_list(value: Any, code: str) -> list[Any]:
if not isinstance(value, list):
raise ProjectionError(code, repr(value)[:300])
return value
def parse_authoring_bytes(raw: bytes, *, source: str = "<authoring>") -> dict[str, Any]:
if yaml is None:
raise ProjectionError("PYYAML_REQUIRED", "install PyYAML on offline build host")
try:
text = raw.decode("utf-8")
except UnicodeDecodeError as exc:
raise ProjectionError("AUTHORING_UTF8_REQUIRED", f"{source}: {exc}") from exc
if text.startswith("\ufeff"):
raise ProjectionError("AUTHORING_UTF8_BOM_FORBIDDEN", source)
for pattern in PLAINTEXT_SECRET_RES:
if pattern.search(text):
raise ProjectionError("AUTHORING_PLAINTEXT_SECRET", pattern.pattern)
try:
document = yaml.load(text, Loader=UniqueKeySafeLoader)
except ProjectionError:
raise
except yaml.YAMLError as exc:
raise ProjectionError("AUTHORING_YAML_INVALID", f"{source}: {exc}") from exc
if not isinstance(document, dict):
raise ProjectionError("AUTHORING_ROOT_OBJECT_REQUIRED", source)
return document
def load_authoring(path: Path | None = None) -> tuple[bytes, dict[str, Any]]:
selected = AUTHORING_PATH if path is None else path
if not selected.is_file() or selected.is_symlink():
raise ProjectionError("AUTHORING_YAML_MISSING_OR_SYMLINK", selected.as_posix())
raw = selected.read_bytes()
return raw, parse_authoring_bytes(raw, source=selected.as_posix())
def _find_forbidden_model_fields(value: Any, *, pointer: str = "") -> list[str]:
findings: list[str] = []
if isinstance(value, dict):
for key, child in value.items():
child_pointer = f"{pointer}/{key}"
if key in MODEL_FIELDS:
findings.append(child_pointer)
findings.extend(_find_forbidden_model_fields(child, pointer=child_pointer))
elif isinstance(value, list):
for index, child in enumerate(value):
findings.extend(_find_forbidden_model_fields(child, pointer=f"{pointer}/{index}"))
return findings
def extract_run_code_task(document: Mapping[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]:
agent = _require_mapping(document.get("Agent"), "AGENT_OBJECT_REQUIRED")
if agent.get("name") != EXPECTED_AGENT_NAME or agent.get("version") != EXPECTED_AGENT_VERSION:
raise ProjectionError(
"AGENT_IDENTITY_MISMATCH",
f"expected={EXPECTED_AGENT_NAME}/{EXPECTED_AGENT_VERSION} observed={agent.get('name')}/{agent.get('version')}",
)
forbidden_model_fields = _find_forbidden_model_fields(agent)
if forbidden_model_fields:
raise ProjectionError("LLM_OR_PROMPT_FIELD_FORBIDDEN", repr(forbidden_model_fields))
stages = _require_list(agent.get("Stages"), "STAGES_ARRAY_REQUIRED")
if len(stages) != 1:
raise ProjectionError("EXACTLY_ONE_STAGE_REQUIRED", str(len(stages)))
stage = _require_mapping(stages[0], "STAGE_OBJECT_REQUIRED")
if stage.get("name") != EXPECTED_STAGE_NAME:
raise ProjectionError("S2_20_STAGE_NAME_REQUIRED", repr(stage.get("name")))
if stage.get("skip_confirm") is not True:
raise ProjectionError("S2_20_SKIP_CONFIRM_TRUE_REQUIRED", repr(stage.get("skip_confirm")))
if stage.get("prevs") != [] or stage.get("nexts") != []:
raise ProjectionError("STANDALONE_STAGE_EDGES_MUST_BE_EMPTY", repr(stage))
servers = _require_mapping(
_require_mapping(stage.get("tools"), "TOOLS_OBJECT_REQUIRED").get("mcpServers"),
"MCP_SERVERS_OBJECT_REQUIRED",
)
if set(servers) != {"localdocs", "code-executor"}:
raise ProjectionError("MCP_SERVER_SET_MISMATCH", repr(sorted(servers)))
expected_servers = {
"localdocs": {"type": "streamable-http", "url": EXPECTED_LOCALDOCS_URL},
"code-executor": {"type": "streamable-http", "url": EXPECTED_CODE_EXECUTOR_URL},
}
for name, expected in expected_servers.items():
observed = _require_mapping(servers.get(name), f"{name.upper()}_SERVER_REQUIRED")
if observed != expected:
raise ProjectionError("MCP_SERVER_BINDING_INVALID", f"{name}:{observed!r}")
tasks = _require_list(stage.get("tasks"), "TASKS_ARRAY_REQUIRED")
if len(tasks) != 1:
raise ProjectionError("EXACTLY_ONE_TASK_REQUIRED", str(len(tasks)))
task = _require_mapping(tasks[0], "TASK_OBJECT_REQUIRED")
run_code_tasks = [
value
for candidate_stage in stages
for value in _require_list(
_require_mapping(candidate_stage, "STAGE_OBJECT_REQUIRED").get("tasks"),
"TASKS_ARRAY_REQUIRED",
)
if isinstance(value, dict)
and value.get("mcp") == "code-executor"
and value.get("tool_name") == "run_code"
]
if len(run_code_tasks) != 1:
raise ProjectionError("EXACTLY_ONE_CODE_EXECUTOR_RUN_CODE_REQUIRED", str(len(run_code_tasks)))
if task.get("task_name") != EXPECTED_TASK_NAME:
raise ProjectionError("TASK_NAME_MISMATCH", repr(task.get("task_name")))
if task.get("mcp") != "code-executor" or task.get("tool_name") != "run_code":
raise ProjectionError("RUN_CODE_TASK_BINDING_MISMATCH", repr(task))
parameters = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")
if set(parameters) != set(EXPECTED_PARAMETERS) | {"code"}:
raise ProjectionError("RUN_CODE_PARAMETER_SET_MISMATCH", repr(sorted(parameters)))
for key, expected in EXPECTED_PARAMETERS.items():
if parameters.get(key) != expected:
raise ProjectionError(
"RUN_CODE_PARAMETER_MISMATCH", f"{key}: expected={expected!r} observed={parameters.get(key)!r}"
)
code = parameters.get("code")
if not isinstance(code, str) or not code:
raise ProjectionError("INLINE_CODE_REQUIRED", repr(code)[:200])
if code.endswith(("\n", "\r")):
raise ProjectionError(
"INLINE_CODE_TRAILING_NEWLINE_FORBIDDEN",
"use code: |-; parser-returned code bytes must not be transformed",
)
expected_procedure = {
"IN": {"nexts": [EXPECTED_TASK_NAME], "wait_until": []},
EXPECTED_TASK_NAME: {"nexts": ["OUT"], "wait_until": ["IN"]},
"OUT": {"nexts": [], "wait_until": [EXPECTED_TASK_NAME]},
}
procedure = _require_mapping(stage.get("task_procedure"), "TASK_PROCEDURE_REQUIRED")
if procedure != expected_procedure:
raise ProjectionError("TASK_PROCEDURE_EXACT_IN_TASK_OUT_REQUIRED", repr(procedure)[:800])
description = stage.get("description")
if not isinstance(description, str) or not all(token in description for token in ("C20", "C21", "C25", "C26", "C22", "C27", "C28", "C29", "C30", "C35")):
raise ProjectionError("INTERNAL_DAG_DESCRIPTION_REQUIRED", repr(description))
return stage, task
def extract_code(raw: bytes) -> bytes:
"""Backward-compatible parser-based extraction used by existing tests."""
document = parse_authoring_bytes(raw)
_, task = extract_run_code_task(document)
parameters = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")
return parameters["code"].encode("utf-8")
def _import_root(name: str | None) -> str:
return (name or "").split(".", 1)[0]
def _assigned_names(node: ast.Assign | ast.AnnAssign) -> set[str]:
targets = node.targets if isinstance(node, ast.Assign) else [node.target]
return {target.id for target in targets if isinstance(target, ast.Name)}
def validate_inline_code(code: str) -> dict[str, Any]:
try:
compile(code, "<Stage_2_S2_20.parameters.code>", "exec", dont_inherit=True)
tree = ast.parse(code, filename="<Stage_2_S2_20.parameters.code>", mode="exec")
except (SyntaxError, ValueError, UnicodeError) as exc:
raise ProjectionError("INLINE_CODE_COMPILE_FAILED", str(exc)) from exc
missing_tokens = [token for token in REQUIRED_CODE_TOKENS if token not in code]
if missing_tokens:
raise ProjectionError("INLINE_CODE_REQUIRED_TOKEN_MISSING", repr(missing_tokens))
if PLACEHOLDER_COMMENT_RE.search(code):
raise ProjectionError("INLINE_CODE_PLACEHOLDER_COMMENT", "TODO/FIXME/TBD placeholder")
for pattern in PLAINTEXT_SECRET_RES:
if pattern.search(code):
raise ProjectionError("INLINE_CODE_PLAINTEXT_SECRET", pattern.pattern)
imports: set[str] = set()
import_aliases: dict[str, str] = {}
forbidden_callable_aliases: set[str] = set()
forbidden_nodes: list[str] = []
external_source_refs: set[str] = set()
observed_urls: set[str] = set()
release_constants: list[str] = []
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for alias in node.names:
root = _import_root(alias.name)
imports.add(root)
import_aliases[alias.asname or root] = root
elif isinstance(node, ast.ImportFrom):
root = _import_root(node.module)
imports.add(root)
if node.level:
forbidden_nodes.append(f"relative-import:{node.module or ''}")
for alias in node.names:
local = alias.asname or alias.name
if root == "builtins" and alias.name in FORBIDDEN_CALL_NAMES:
forbidden_callable_aliases.add(local)
if root == "os" and (
("os", alias.name) in FORBIDDEN_ATTRIBUTE_CALLS or alias.name.startswith("exec")
):
forbidden_callable_aliases.add(local)
for node in ast.walk(tree):
if isinstance(node, (ast.Assign, ast.AnnAssign)):
value = node.value
names = _assigned_names(node)
if isinstance(value, ast.Name) and (
value.id in FORBIDDEN_CALL_NAMES or value.id in forbidden_callable_aliases
):
forbidden_callable_aliases.update(names)
if isinstance(value, ast.Attribute) and isinstance(value.value, ast.Name):
module = import_aliases.get(value.value.id, value.value.id)
if (module, value.attr) in FORBIDDEN_ATTRIBUTE_CALLS or (
module == "os" and value.attr.startswith("exec")
):
forbidden_callable_aliases.update(names)
if (
"EXPECTED_STAGE2_RELEASE_SHA256" in names
and isinstance(value, ast.Constant)
and isinstance(value.value, str)
):
release_constants.append(value.value)
elif isinstance(node, ast.Call):
if isinstance(node.func, ast.Name) and (
node.func.id in FORBIDDEN_CALL_NAMES or node.func.id in forbidden_callable_aliases
):
forbidden_nodes.append(f"call:{node.func.id}")
elif isinstance(node.func, ast.Attribute) and isinstance(node.func.value, ast.Name):
module = import_aliases.get(node.func.value.id, node.func.value.id)
if (module, node.func.attr) in FORBIDDEN_ATTRIBUTE_CALLS or (
module == "os" and node.func.attr.startswith("exec")
):
forbidden_nodes.append(f"call:{module}.{node.func.attr}")
elif isinstance(node, ast.Pass):
forbidden_nodes.append("Pass")
elif isinstance(node, ast.Raise):
target = node.exc.func if isinstance(node.exc, ast.Call) else node.exc
if isinstance(target, ast.Name) and target.id == "NotImplementedError":
forbidden_nodes.append("raise:NotImplementedError")
elif isinstance(node, ast.Constant):
if node.value is Ellipsis:
forbidden_nodes.append("Ellipsis")
if isinstance(node.value, str):
observed_urls.update(match.rstrip(".,);]") for match in URL_RE.findall(node.value))
if PYTHON_SOURCE_REF_RE.search(node.value.strip()):
external_source_refs.add(node.value[:200])
imports.discard("")
disallowed_imports = sorted(
value
for value in imports
if value in FORBIDDEN_IMPORT_ROOTS
or (value not in sys.stdlib_module_names and value not in ALLOWED_NON_STDLIB_IMPORTS)
)
if disallowed_imports:
raise ProjectionError("INLINE_CODE_IMPORT_FORBIDDEN", repr(disallowed_imports))
if forbidden_nodes:
raise ProjectionError("INLINE_CODE_DYNAMIC_OR_PLACEHOLDER_FORBIDDEN", repr(forbidden_nodes))
if external_source_refs:
raise ProjectionError("INLINE_CODE_EXTERNAL_PY_SOURCE_REF_FORBIDDEN", repr(sorted(external_source_refs)))
if observed_urls != set(ALLOWED_CODE_URLS):
raise ProjectionError(
"INLINE_CODE_ENDPOINT_LITERAL_SET_MISMATCH",
json.dumps(
{"expected": sorted(ALLOWED_CODE_URLS), "observed": sorted(observed_urls)},
ensure_ascii=False,
sort_keys=True,
),
)
if len(release_constants) != 1 or not re.fullmatch(r"[a-f0-9]{64}", release_constants[0]):
raise ProjectionError("EXPECTED_PARENT_RELEASE_CONSTANT_EXACT_ONE_REQUIRED", repr(release_constants))
code_bytes = code.encode("utf-8")
return {
"yaml_pointer": "/Agent/Stages/0/tasks/0/parameters/code",
"encoding": "UTF-8",
"extraction_transform": "NONE",
"code_sha256": sha256_bytes(code_bytes),
"code_size_bytes": len(code_bytes),
"compile_status": "PASS",
"ast_status": "PASS",
"imports": sorted(imports),
"forbidden_import_count": 0,
"forbidden_dynamic_call_count": 0,
"external_python_source_ref_count": 0,
"plaintext_secret_count": 0,
"endpoint_literals": sorted(observed_urls),
"expected_parent_stage2_release_sha256": release_constants[0],
}
def validate_agent(raw: bytes, code: bytes | None = None) -> dict[str, Any]:
"""Backward-compatible complete validation of authoring and extracted code."""
document = parse_authoring_bytes(raw)
_, task = extract_run_code_task(document)
parsed_code = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")["code"]
parsed_bytes = parsed_code.encode("utf-8")
if code is not None and code != parsed_bytes:
raise ProjectionError("EXTRACTED_CODE_BYTES_DRIFT", sha256_bytes(code))
return validate_inline_code(parsed_code)
def _canonical_task_semantics(
document: Mapping[str, Any], stage: Mapping[str, Any], task: Mapping[str, Any]
) -> dict[str, Any]:
agent = _require_mapping(document.get("Agent"), "AGENT_OBJECT_REQUIRED")
servers = _require_mapping(
_require_mapping(stage.get("tools"), "TOOLS_OBJECT_REQUIRED").get("mcpServers"),
"MCP_SERVERS_OBJECT_REQUIRED",
)
parameters = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")
return {
"agent": {"name": agent.get("name"), "version": agent.get("version")},
"stage": {
"name": stage.get("name"),
"prevs": stage.get("prevs"),
"nexts": stage.get("nexts"),
"skip_confirm": stage.get("skip_confirm"),
},
"mcp_servers": {
name: {"type": value.get("type"), "url": value.get("url")}
for name, value in sorted(servers.items())
if isinstance(value, dict)
},
"task": {
"task_name": task.get("task_name"),
"mcp": task.get("mcp"),
"tool_name": task.get("tool_name"),
"parameters": {key: parameters.get(key) for key in EXPECTED_PARAMETERS},
"code_sha256": sha256_bytes(parameters["code"].encode("utf-8")),
},
"task_procedure": stage.get("task_procedure"),
"internal_dag": "(C20||C21)->C25->C26->(C22||(C27->C28->C29))->C30->C35",
}
def expected_outputs(
authoring_raw: bytes, document: Mapping[str, Any]
) -> tuple[dict[Path, bytes], dict[str, Any]]:
stage, task = extract_run_code_task(document)
parameters = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")
code = parameters["code"]
validation = validate_inline_code(code)
code_bytes = code.encode("utf-8")
semantics = _canonical_task_semantics(document, stage, task)
receipt = {
"schema_version": "stage2_s2_20_inline_code_receipt.v1",
"workflow_id": "S2_20",
"authoring": {
"path": _logical_path(AUTHORING_PATH),
"sha256": sha256_bytes(authoring_raw),
"size_bytes": len(authoring_raw),
},
"deployment_projection": {
"path": _logical_path(PROJECTION_PATH),
"sha256": sha256_bytes(authoring_raw),
"size_bytes": len(authoring_raw),
},
"canonical_code": validation,
"full_code_mirrors": [_logical_path(MIRROR_PY_PATH), _logical_path(MIRROR_TXT_PATH)],
"task_contract": {
**semantics,
"canonical_task_semantics_sha256": sha256_bytes(canonical_json_bytes(semantics)),
"exactly_one_stage": True,
"exactly_one_task": True,
"exactly_one_code_executor_run_code": True,
"authoring_rewritten": False,
"projection_byte_identical_to_authoring": True,
"code_mirrors_byte_identical": True,
"expected_parent_stage2_release_sha256": validation[
"expected_parent_stage2_release_sha256"
],
},
"parity_status": "PASS",
}
outputs = {
PROJECTION_PATH: authoring_raw,
MIRROR_PY_PATH: code_bytes,
MIRROR_TXT_PATH: code_bytes,
RECEIPT_PATH: canonical_json_bytes(receipt),
}
return outputs, receipt
def _assert_output_target(path: Path) -> None:
root = DEPLOYMENT_ROOT.resolve(strict=True)
resolved = path.resolve(strict=False)
try:
resolved.relative_to(root)
except ValueError as exc:
raise ProjectionError("OUTPUT_OUTSIDE_DEPLOYMENT_ROOT", path.as_posix()) from exc
if path.exists() and path.is_symlink():
raise ProjectionError("OUTPUT_SYMLINK_FORBIDDEN", path.as_posix())
def _atomic_write(path: Path, payload: bytes) -> None:
_assert_output_target(path)
path.parent.mkdir(parents=True, exist_ok=True)
temporary_name: str | None = None
try:
with tempfile.NamedTemporaryFile(
mode="wb",
dir=path.parent,
prefix=f".{path.name}.",
suffix=".tmp",
delete=False,
) as handle:
temporary_name = handle.name
handle.write(payload)
handle.flush()
os.fsync(handle.fileno())
os.replace(temporary_name, path)
temporary_name = None
finally:
if temporary_name is not None:
try:
Path(temporary_name).unlink()
except FileNotFoundError:
pass
def compare_outputs(outputs: Mapping[Path, bytes]) -> list[dict[str, Any]]:
mismatches: list[dict[str, Any]] = []
for path, expected in outputs.items():
if not path.is_file():
mismatches.append(
{"path": _logical_path(path), "status": "MISSING", "expected_sha256": sha256_bytes(expected)}
)
continue
observed = path.read_bytes()
if observed != expected:
mismatches.append(
{
"path": _logical_path(path),
"status": "BYTE_MISMATCH",
"expected_sha256": sha256_bytes(expected),
"observed_sha256": sha256_bytes(observed),
}
)
return mismatches
def run(*, check: bool) -> tuple[int, dict[str, Any]]:
before, document = load_authoring()
outputs, receipt = expected_outputs(before, document)
if check:
mismatches = compare_outputs(outputs)
return (
0 if not mismatches else 1,
{
"status": "PARITY_PASS" if not mismatches else "PARITY_DRIFT",
"mode": "CHECK_NO_WRITE",
"authoring_sha256": sha256_bytes(before),
"code_sha256": receipt["canonical_code"]["code_sha256"],
"mismatches": mismatches,
},
)
receipt_payload = outputs[RECEIPT_PATH]
for path, payload in outputs.items():
if path != RECEIPT_PATH:
_atomic_write(path, payload)
if AUTHORING_PATH.read_bytes() != before:
raise ProjectionError("AUTHORING_CHANGED_DURING_BUILD", AUTHORING_PATH.as_posix())
_atomic_write(RECEIPT_PATH, receipt_payload)
if AUTHORING_PATH.read_bytes() != before:
raise ProjectionError("AUTHORING_CHANGED_DURING_RECEIPT_WRITE", AUTHORING_PATH.as_posix())
mismatches = compare_outputs(outputs)
if mismatches:
raise ProjectionError("POST_BUILD_PARITY_FAILED", json.dumps(mismatches, sort_keys=True))
return 0, {
"status": "BUILT_AND_VERIFIED",
"mode": "BUILD",
"authoring_sha256": sha256_bytes(before),
"code_sha256": receipt["canonical_code"]["code_sha256"],
"outputs": [_logical_path(path) for path in outputs],
}
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="Build or verify S2_20 inline Agent projection")
parser.add_argument("--check", action="store_true", help="no-write byte parity check")
return parser
def main(argv: Iterable[str] | None = None) -> int:
args = _parser().parse_args(list(argv) if argv is not None else None)
try:
status, payload = run(check=args.check)
except ProjectionError as exc:
status = 3 if exc.code == "AUTHORING_YAML_MISSING_OR_SYMLINK" else 2
payload = {
"status": "CONTROLLED_MISSING_AUTHORING" if status == 3 else "BUILD_FAILED",
"reason_code": exc.code,
"detail": exc.detail,
"mode": "CHECK_NO_WRITE" if args.check else "BUILD",
}
print(json.dumps(payload, ensure_ascii=False, allow_nan=False, sort_keys=True))
return status
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,267 @@
#!/usr/bin/env python3
"""Compile ``case_kinds.md`` into the canonical 137-row Stage 2 registry.
This is an offline, deterministic compiler. It reads the three-column source
table, performs only Unicode/whitespace normalization and comma expansion, and
emits legally *unclassified* rows. It must not infer claim capability,
predicates, renderers, or any other legal content.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import os
from pathlib import Path
import tempfile
from typing import Any, Iterable
import unicodedata
EXPECTED_HEADERS = ("소송 대분류", "분쟁 유형", "사건 종류")
EXCLUDED_MAJOR_CATEGORIES = ("가사소송", "가족관계등록", "행정소송")
EXPECTED_ROW_COUNT = 137
DEFAULT_LOGICAL_SOURCE_PATH = "Case_02_Comparison_Research/case_kinds.md"
class CatalogCompileError(ValueError):
"""Controlled source/compile failure with a stable reason code."""
def __init__(self, code: str, detail: str) -> None:
super().__init__(f"{code}: {detail}")
self.code = code
self.detail = detail
def nfc(value: str) -> str:
return unicodedata.normalize("NFC", value.strip())
def sha256_bytes(value: bytes) -> str:
return hashlib.sha256(value).hexdigest()
def canonical_json_bytes(value: Any) -> bytes:
return (
json.dumps(
value,
ensure_ascii=False,
allow_nan=False,
indent=2,
separators=(",", ": "),
)
+ "\n"
).encode("utf-8")
def _markdown_cells(line: str) -> tuple[str, str, str] | None:
stripped = line.strip()
if not (stripped.startswith("|") and stripped.endswith("|")):
return None
cells = tuple(nfc(cell) for cell in stripped[1:-1].split("|"))
if len(cells) != 3:
raise CatalogCompileError("CATALOG_TABLE_COLUMN_COUNT", repr(cells))
return cells # type: ignore[return-value]
def _is_separator_row(cells: tuple[str, str, str]) -> bool:
return all(cell and set(cell) <= {"-", ":"} for cell in cells)
def parse_catalog(path: Path) -> list[dict[str, Any]]:
"""Return the 137 expanded source rows in physical table order."""
try:
text = path.read_text(encoding="utf-8")
except UnicodeDecodeError as exc:
raise CatalogCompileError("CATALOG_UTF8_REQUIRED", str(exc)) from exc
if text.startswith("\ufeff"):
raise CatalogCompileError("CATALOG_UTF8_BOM_FORBIDDEN", path.as_posix())
rows = [cells for line in text.splitlines() if (cells := _markdown_cells(line))]
if len(rows) < 2 or rows[0] != EXPECTED_HEADERS or not _is_separator_row(rows[1]):
raise CatalogCompileError("CATALOG_TABLE_HEADER_MISMATCH", repr(rows[:2]))
expanded: list[dict[str, Any]] = []
source_table_rows = rows[2:]
for table_data_row, (major_category, dispute_type, case_kinds) in enumerate(
source_table_rows, 1
):
if major_category in EXCLUDED_MAJOR_CATEGORIES:
continue
if not major_category:
raise CatalogCompileError(
"CATALOG_MAJOR_CATEGORY_REQUIRED", f"table_data_row={table_data_row}"
)
if case_kinds:
names = [nfc(value) for value in case_kinds.split(",")]
if not all(names):
raise CatalogCompileError(
"CATALOG_EMPTY_EXPANDED_NAME", f"table_data_row={table_data_row}"
)
source_entry_kind = "CATALOG_NAMED_ENTRY"
else:
if not dispute_type:
raise CatalogCompileError(
"CATALOG_GENERIC_SOURCE_LABEL_REQUIRED",
f"table_data_row={table_data_row}",
)
names = [dispute_type]
source_entry_kind = "GENERIC_SOURCE_ROW"
for expanded_item_ordinal, canonical_name in enumerate(names, 1):
if nfc(canonical_name) != canonical_name:
raise CatalogCompileError("CATALOG_NFC_NORMALIZATION_FAILED", canonical_name)
expanded.append(
{
"canonical_name": canonical_name,
"source_ref": {
"table_data_row": table_data_row,
"expanded_item_ordinal": expanded_item_ordinal,
"major_category": major_category,
"dispute_type": dispute_type,
"source_entry_kind": source_entry_kind,
},
}
)
names = [row["canonical_name"] for row in expanded]
if len(expanded) != EXPECTED_ROW_COUNT:
raise CatalogCompileError(
"CASE_TYPE_CATALOG_EXACT_137_REQUIRED", f"observed={len(expanded)}"
)
if len(names) != len(set(names)):
duplicates = sorted({name for name in names if names.count(name) > 1})
raise CatalogCompileError("CASE_TYPE_CANONICAL_NAME_DUPLICATE", repr(duplicates))
return expanded
def compile_rows(
source: Path,
*,
logical_source_path: str = DEFAULT_LOGICAL_SOURCE_PATH,
) -> dict[str, Any]:
raw = source.read_bytes()
parsed = parse_catalog(source)
case_types: list[dict[str, Any]] = []
for ordinal, source_row in enumerate(parsed, 1):
case_type_id = f"CT-{ordinal:03d}"
case_types.append(
{
"catalog_row_id": f"CAT-{ordinal:03d}",
"source_ordinal": ordinal,
"source_label": source_row["canonical_name"],
"case_type_id": case_type_id,
"row_kind": "PENDING_LEGAL_CLASSIFICATION",
"claim_capable_disposition": "PENDING_LEGAL_CONTENT",
"case_type_predicates": [],
"companion_case_type_ids": [],
"legal_classification_status": "PENDING_LEGAL_CLASSIFICATION",
"legal_content_status": "PENDING_LEGAL_CONTENT",
"legal_review_receipt_ref": None,
"legal_review_receipt_sha256": None,
}
)
catalog_row_ids = [row["catalog_row_id"] for row in case_types]
if [row["case_type_id"] for row in case_types] != [
f"CT-{ordinal:03d}" for ordinal in range(1, 138)
]:
raise CatalogCompileError("CASE_TYPE_ID_SEQUENCE_DRIFT", repr(case_types))
return {
"schema_version": "stage2_case_type_registry.v1",
"registry_id": "STAGE2_CASE_TYPE_137_V1",
"catalog_source_ref": logical_source_path,
"catalog_source_sha256": sha256_bytes(raw),
"catalog_row_ids": catalog_row_ids,
"rows": case_types,
"claim_capable_case_type_ids": [],
"pending_legal_classification_case_type_ids": [
row["case_type_id"] for row in case_types
],
"fuzzy_match_allowed": False,
"catch_all_fallback_allowed": False,
"registry_status": "PENDING_LEGAL_CLASSIFICATION",
}
def _atomic_write(path: Path, payload: bytes) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
temporary_name: str | None = None
try:
with tempfile.NamedTemporaryFile(
mode="wb",
dir=path.parent,
prefix=f".{path.name}.",
suffix=".tmp",
delete=False,
) as handle:
temporary_name = handle.name
handle.write(payload)
handle.flush()
os.fsync(handle.fileno())
os.replace(temporary_name, path)
temporary_name = None
finally:
if temporary_name is not None:
try:
Path(temporary_name).unlink()
except FileNotFoundError:
pass
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Compile the canonical 137-kind civil-case catalog"
)
parser.add_argument("source", type=Path)
parser.add_argument("output", type=Path)
parser.add_argument(
"--source-logical-path",
default=DEFAULT_LOGICAL_SOURCE_PATH,
help="version-free path recorded in the emitted registry",
)
parser.add_argument(
"--check",
action="store_true",
help="do not write; require output bytes to equal the deterministic projection",
)
return parser
def main(argv: Iterable[str] | None = None) -> int:
args = _parser().parse_args(list(argv) if argv is not None else None)
try:
payload = canonical_json_bytes(
compile_rows(args.source, logical_source_path=args.source_logical_path)
)
if args.check:
if not args.output.is_file() or args.output.read_bytes() != payload:
raise CatalogCompileError(
"CASE_TYPE_REGISTRY_PARITY_DRIFT", args.output.as_posix()
)
result = {"status": "PARITY_PASS", "sha256": sha256_bytes(payload)}
else:
_atomic_write(args.output, payload)
result = {
"status": "COMPILED",
"row_count": EXPECTED_ROW_COUNT,
"source_sha256": sha256_bytes(args.source.read_bytes()),
"output_sha256": sha256_bytes(payload),
}
except (CatalogCompileError, OSError) as exc:
result = {
"status": "COMPILE_FAILED",
"reason_code": getattr(exc, "code", type(exc).__name__),
"detail": getattr(exc, "detail", str(exc)),
}
print(json.dumps(result, ensure_ascii=False, sort_keys=True))
return 2
print(json.dumps(result, ensure_ascii=False, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,267 @@
#!/usr/bin/env python3
"""Compile ``case_kinds.md`` into the canonical 137-row Stage 2 registry.
This is an offline, deterministic compiler. It reads the three-column source
table, performs only Unicode/whitespace normalization and comma expansion, and
emits legally *unclassified* rows. It must not infer claim capability,
predicates, renderers, or any other legal content.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import os
from pathlib import Path
import tempfile
from typing import Any, Iterable
import unicodedata
EXPECTED_HEADERS = ("소송 대분류", "분쟁 유형", "사건 종류")
EXCLUDED_MAJOR_CATEGORIES = ("가사소송", "가족관계등록", "행정소송")
EXPECTED_ROW_COUNT = 137
DEFAULT_LOGICAL_SOURCE_PATH = "Case_02_Comparison_Research/case_kinds.md"
class CatalogCompileError(ValueError):
"""Controlled source/compile failure with a stable reason code."""
def __init__(self, code: str, detail: str) -> None:
super().__init__(f"{code}: {detail}")
self.code = code
self.detail = detail
def nfc(value: str) -> str:
return unicodedata.normalize("NFC", value.strip())
def sha256_bytes(value: bytes) -> str:
return hashlib.sha256(value).hexdigest()
def canonical_json_bytes(value: Any) -> bytes:
return (
json.dumps(
value,
ensure_ascii=False,
allow_nan=False,
indent=2,
separators=(",", ": "),
)
+ "\n"
).encode("utf-8")
def _markdown_cells(line: str) -> tuple[str, str, str] | None:
stripped = line.strip()
if not (stripped.startswith("|") and stripped.endswith("|")):
return None
cells = tuple(nfc(cell) for cell in stripped[1:-1].split("|"))
if len(cells) != 3:
raise CatalogCompileError("CATALOG_TABLE_COLUMN_COUNT", repr(cells))
return cells # type: ignore[return-value]
def _is_separator_row(cells: tuple[str, str, str]) -> bool:
return all(cell and set(cell) <= {"-", ":"} for cell in cells)
def parse_catalog(path: Path) -> list[dict[str, Any]]:
"""Return the 137 expanded source rows in physical table order."""
try:
text = path.read_text(encoding="utf-8")
except UnicodeDecodeError as exc:
raise CatalogCompileError("CATALOG_UTF8_REQUIRED", str(exc)) from exc
if text.startswith("\ufeff"):
raise CatalogCompileError("CATALOG_UTF8_BOM_FORBIDDEN", path.as_posix())
rows = [cells for line in text.splitlines() if (cells := _markdown_cells(line))]
if len(rows) < 2 or rows[0] != EXPECTED_HEADERS or not _is_separator_row(rows[1]):
raise CatalogCompileError("CATALOG_TABLE_HEADER_MISMATCH", repr(rows[:2]))
expanded: list[dict[str, Any]] = []
source_table_rows = rows[2:]
for table_data_row, (major_category, dispute_type, case_kinds) in enumerate(
source_table_rows, 1
):
if major_category in EXCLUDED_MAJOR_CATEGORIES:
continue
if not major_category:
raise CatalogCompileError(
"CATALOG_MAJOR_CATEGORY_REQUIRED", f"table_data_row={table_data_row}"
)
if case_kinds:
names = [nfc(value) for value in case_kinds.split(",")]
if not all(names):
raise CatalogCompileError(
"CATALOG_EMPTY_EXPANDED_NAME", f"table_data_row={table_data_row}"
)
source_entry_kind = "CATALOG_NAMED_ENTRY"
else:
if not dispute_type:
raise CatalogCompileError(
"CATALOG_GENERIC_SOURCE_LABEL_REQUIRED",
f"table_data_row={table_data_row}",
)
names = [dispute_type]
source_entry_kind = "GENERIC_SOURCE_ROW"
for expanded_item_ordinal, canonical_name in enumerate(names, 1):
if nfc(canonical_name) != canonical_name:
raise CatalogCompileError("CATALOG_NFC_NORMALIZATION_FAILED", canonical_name)
expanded.append(
{
"canonical_name": canonical_name,
"source_ref": {
"table_data_row": table_data_row,
"expanded_item_ordinal": expanded_item_ordinal,
"major_category": major_category,
"dispute_type": dispute_type,
"source_entry_kind": source_entry_kind,
},
}
)
names = [row["canonical_name"] for row in expanded]
if len(expanded) != EXPECTED_ROW_COUNT:
raise CatalogCompileError(
"CASE_TYPE_CATALOG_EXACT_137_REQUIRED", f"observed={len(expanded)}"
)
if len(names) != len(set(names)):
duplicates = sorted({name for name in names if names.count(name) > 1})
raise CatalogCompileError("CASE_TYPE_CANONICAL_NAME_DUPLICATE", repr(duplicates))
return expanded
def compile_rows(
source: Path,
*,
logical_source_path: str = DEFAULT_LOGICAL_SOURCE_PATH,
) -> dict[str, Any]:
raw = source.read_bytes()
parsed = parse_catalog(source)
case_types: list[dict[str, Any]] = []
for ordinal, source_row in enumerate(parsed, 1):
case_type_id = f"CT-{ordinal:03d}"
case_types.append(
{
"catalog_row_id": f"CAT-{ordinal:03d}",
"source_ordinal": ordinal,
"source_label": source_row["canonical_name"],
"case_type_id": case_type_id,
"row_kind": "PENDING_LEGAL_CLASSIFICATION",
"claim_capable_disposition": "PENDING_LEGAL_CONTENT",
"case_type_predicates": [],
"companion_case_type_ids": [],
"legal_classification_status": "PENDING_LEGAL_CLASSIFICATION",
"legal_content_status": "PENDING_LEGAL_CONTENT",
"legal_review_receipt_ref": None,
"legal_review_receipt_sha256": None,
}
)
catalog_row_ids = [row["catalog_row_id"] for row in case_types]
if [row["case_type_id"] for row in case_types] != [
f"CT-{ordinal:03d}" for ordinal in range(1, 138)
]:
raise CatalogCompileError("CASE_TYPE_ID_SEQUENCE_DRIFT", repr(case_types))
return {
"schema_version": "stage2_case_type_registry.v1",
"registry_id": "STAGE2_CASE_TYPE_137_V1",
"catalog_source_ref": logical_source_path,
"catalog_source_sha256": sha256_bytes(raw),
"catalog_row_ids": catalog_row_ids,
"rows": case_types,
"claim_capable_case_type_ids": [],
"pending_legal_classification_case_type_ids": [
row["case_type_id"] for row in case_types
],
"fuzzy_match_allowed": False,
"catch_all_fallback_allowed": False,
"registry_status": "PENDING_LEGAL_CLASSIFICATION",
}
def _atomic_write(path: Path, payload: bytes) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
temporary_name: str | None = None
try:
with tempfile.NamedTemporaryFile(
mode="wb",
dir=path.parent,
prefix=f".{path.name}.",
suffix=".tmp",
delete=False,
) as handle:
temporary_name = handle.name
handle.write(payload)
handle.flush()
os.fsync(handle.fileno())
os.replace(temporary_name, path)
temporary_name = None
finally:
if temporary_name is not None:
try:
Path(temporary_name).unlink()
except FileNotFoundError:
pass
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Compile the canonical 137-kind civil-case catalog"
)
parser.add_argument("source", type=Path)
parser.add_argument("output", type=Path)
parser.add_argument(
"--source-logical-path",
default=DEFAULT_LOGICAL_SOURCE_PATH,
help="version-free path recorded in the emitted registry",
)
parser.add_argument(
"--check",
action="store_true",
help="do not write; require output bytes to equal the deterministic projection",
)
return parser
def main(argv: Iterable[str] | None = None) -> int:
args = _parser().parse_args(list(argv) if argv is not None else None)
try:
payload = canonical_json_bytes(
compile_rows(args.source, logical_source_path=args.source_logical_path)
)
if args.check:
if not args.output.is_file() or args.output.read_bytes() != payload:
raise CatalogCompileError(
"CASE_TYPE_REGISTRY_PARITY_DRIFT", args.output.as_posix()
)
result = {"status": "PARITY_PASS", "sha256": sha256_bytes(payload)}
else:
_atomic_write(args.output, payload)
result = {
"status": "COMPILED",
"row_count": EXPECTED_ROW_COUNT,
"source_sha256": sha256_bytes(args.source.read_bytes()),
"output_sha256": sha256_bytes(payload),
}
except (CatalogCompileError, OSError) as exc:
result = {
"status": "COMPILE_FAILED",
"reason_code": getattr(exc, "code", type(exc).__name__),
"detail": getattr(exc, "detail", str(exc)),
}
print(json.dumps(result, ensure_ascii=False, sort_keys=True))
return 2
print(json.dumps(result, ensure_ascii=False, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,30 @@
{
"schema_version": "stage2_binding_signature_projection_registry.v1",
"registry_id": "S2_20_BINDING_SIGNATURE_PROJECTION_V1",
"source_schema_ref": "schemas/domain_verdict.schema.json#/$defs/normalized_claim_signature",
"source_field_allowlist": [
"legal_basis_family",
"right_holder_refs",
"obligor_refs",
"performance_kind",
"object_refs",
"legal_effect",
"source_occurrence_refs"
],
"target_field_order": [
"claim_family",
"legal_effect",
"performance_kind",
"object_kind",
"party_role_pattern",
"source_obligation_kind",
"remedy_mode",
"registry_action",
"procedural_posture",
"special_statute_tags"
],
"projection_rules": [],
"free_text_fallback_allowed": false,
"fuzzy_matching_allowed": false,
"registry_status": "PENDING_LEGAL_REVIEW"
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-01",
"descriptor_id": "CE-01-INTEREST-DELAY",
"description": "obligation-and-defendant event rate timeline",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-02",
"descriptor_id": "CE-02-ALLOCATION-SETOFF-BALANCE",
"description": "allocation, setoff, and remaining balance",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-03",
"descriptor_id": "CE-03-LIMITATION-DEADLINE",
"description": "limitation, exclusion, filing deadline, and urgency",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-04",
"descriptor_id": "CE-04-VALUATION",
"description": "use gain and object valuation",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-05",
"descriptor_id": "CE-05-PERSONAL-INJURY",
"description": "lost earnings, treatment cost, and comparative fault",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-06",
"descriptor_id": "CE-06-CONSTRUCTION-DEFECT",
"description": "progress payment, extra work, defect repair, and reduction",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-07",
"descriptor_id": "CE-07-LEASE-USE-GAIN",
"description": "lease deductions and use gain",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-08",
"descriptor_id": "CE-08-INHERITANCE-RESERVED-SHARE",
"description": "reserved-share value and temporal remedy branch",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-09",
"descriptor_id": "CE-09-WAGE-SEVERANCE",
"description": "wage, allowance, and severance",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-10",
"descriptor_id": "CE-10-ACTIO-INSOLVENCY-VALUE",
"description": "preserved claim, common security, and beneficiary/transferee caps",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-11",
"descriptor_id": "CE-11-DISTRIBUTION-SHARE-DIVISION",
"description": "distribution, share, and division amount",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-12",
"descriptor_id": "CE-12-INSURANCE",
"description": "insured value, duplicate insurance, and deduction",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-13",
"descriptor_id": "CE-13-COURT-VALUE-COST",
"description": "amount in controversy, filing fee, service cost, joinder, and incidental claim",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-R1",
"descriptor_id": "CE-R1-IP-DAMAGE",
"description": "intellectual-property damage",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-R2",
"descriptor_id": "CE-R2-ORG-LIQUIDATION",
"description": "organization and partnership liquidation/distribution",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-R3",
"descriptor_id": "CE-R3-TRANSPORT-MARITIME",
"description": "transport and maritime damage/liability limit",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,54 @@
{
"schema_version": "stage2.s2_20.calculation_descriptor.v1",
"calculator_id": "CE-R4",
"descriptor_id": "CE-R4-FINANCIAL-INSTRUMENT",
"description": "financial instrument, account, and settlement",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"formula_rows": [],
"operand_contract": {
"required_operands": [],
"optional_operands": [],
"unit_contracts": [],
"missing_operand_policy": "ISSUE_AND_NO_RESULT"
},
"law_value_contract": {
"law_value_refs": [],
"literal_output_affecting_legal_numbers_forbidden": true,
"effective_interval_required": true,
"authority_release_binding_required": true
},
"numeric_contract": {
"decimal_only": true,
"binary_float_forbidden": true,
"rounding_rule_required_per_formula": true,
"explicit_units_required": true
},
"receipt_contract": {
"required_fields": [
"calculation_receipt_id",
"calculator_id",
"formula_id",
"operand_refs",
"units",
"law_value_id",
"effective_interval",
"rounding_rule",
"period_rows",
"missing_operands",
"result_sha256"
]
},
"failure_codes": [
"CALCULATION_DESCRIPTOR_NOT_APPROVED",
"CALCULATION_FORMULA_NOT_AVAILABLE",
"CALCULATION_OPERAND_MISSING",
"CALCULATION_LAW_VALUE_UNRESOLVED",
"CALCULATION_TEMPORAL_GAP",
"CALCULATION_UNIT_MISMATCH"
],
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,168 @@
{
"schema_version": "stage2.s2_20.calculation_activation_registry.v1",
"registry_id": "S2-20-CALCULATION-ACTIVATION",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"state_enum": [
"ACTIVATED",
"NOT_APPLICABLE",
"ACTIVATION_GAP",
"ACTIVATION_CONFLICT"
],
"allowed_predicate_inputs": [
"normalized_claim_signature",
"case_type_id",
"rule_branch_key",
"requested_metric"
],
"allowed_predicate_operators": [
"EQ",
"IN",
"ALL_OF",
"NONE_OF",
"EXISTS"
],
"activation_rows": [],
"activation_row_contract": {
"required_fields": [
"calculator_id",
"requested_metrics",
"equals"
]
},
"calculator_descriptors": [
{
"calculator_id": "CE-01",
"descriptor_path": "registry/calculations/CE-01_interest_delay.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-02",
"descriptor_path": "registry/calculations/CE-02_allocation_setoff_balance.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-03",
"descriptor_path": "registry/calculations/CE-03_limitation_deadline.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-04",
"descriptor_path": "registry/calculations/CE-04_valuation.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-05",
"descriptor_path": "registry/calculations/CE-05_personal_injury.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-06",
"descriptor_path": "registry/calculations/CE-06_construction_defect.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-07",
"descriptor_path": "registry/calculations/CE-07_lease_use_gain.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-08",
"descriptor_path": "registry/calculations/CE-08_inheritance_reserved_share.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-09",
"descriptor_path": "registry/calculations/CE-09_wage_severance.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-10",
"descriptor_path": "registry/calculations/CE-10_actio_insolvency_value.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-11",
"descriptor_path": "registry/calculations/CE-11_distribution_share_division.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-12",
"descriptor_path": "registry/calculations/CE-12_insurance.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-13",
"descriptor_path": "registry/calculations/CE-13_court_value_cost.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-R1",
"descriptor_path": "registry/calculations/CE-R1_ip_damage.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-R2",
"descriptor_path": "registry/calculations/CE-R2_org_liquidation.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-R3",
"descriptor_path": "registry/calculations/CE-R3_transport_maritime.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
},
{
"calculator_id": "CE-R4",
"descriptor_path": "registry/calculations/CE-R4_financial_instrument.yml",
"activation_status": "PENDING_LEGAL_CONTENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false
}
],
"closure": {
"exactly_one_state_per_calculator_required": true,
"activated_requires_nonempty_approved_predicate": true,
"activated_requires_release_selected_descriptor_hash": true,
"activated_requires_receipt": true,
"zero_match_issue_code": "CALCULATION_ACTIVATION_GAP",
"multi_match_issue_code": "CALCULATION_ACTIVATION_CONFLICT",
"model_arithmetic_forbidden": true,
"missing_operand_default_zero_forbidden": true
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,7 @@
{
"schema_version": "stage2_requirement_fact_scope_registry.v1",
"registry_id": "STAGE2_REQUIREMENT_FACT_SCOPE_V1",
"rows": [],
"registry_status": "PENDING_LEGAL_CONTENT",
"fuzzy_fallback_allowed": false
}
@@ -0,0 +1,43 @@
{
"schema_version": "stage2.s2_20.case_type_relief_rules.v1",
"registry_id": "S2-20-CASE-TYPE-RELIEF-RULES",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"source_catalog_registry_path": "manifest/case_type_registry.yml",
"source_rule_registry_path": "manifest/case_type_rule_registry.yml",
"source_catalog_expected_count": 137,
"branch_key_format": "case_type_id::sub_rule_id",
"branch_contract": {
"required_fields": [
"case_type_id",
"sub_rule_id",
"predicate_id",
"structured_relief_slots",
"allowed_renderer_ids",
"markdown_source_path",
"markdown_source_sha256",
"corpus_scope_id",
"element_set_id",
"ce_13_branch_id",
"party_set_rule_id",
"review_policy_id",
"authority_refs",
"review_status"
]
},
"rule_branches": [],
"closure": {
"directory_scan_forbidden": true,
"filename_match_forbidden": true,
"nearest_rule_fallback_forbidden": true,
"generic_wording_fallback_forbidden": true,
"exactly_one_approved_branch_required_for_clean_draft": true,
"zero_match_issue_code": "RELIEF_RULE_BRANCH_ZERO_MATCH",
"multi_match_issue_code": "RELIEF_RULE_BRANCH_MULTI_MATCH",
"source_hash_mismatch_issue_code": "RELIEF_RULE_SOURCE_HASH_MISMATCH"
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,29 @@
{
"schema_version": "stage2.s2_20.drafting_rule_registry.v1",
"registry_id": "S2-20-COUNTER-PERFORMANCE-RULES",
"purpose": "simultaneous or reciprocal performance branches",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"rule_rows": [],
"row_contract": {
"required_fields": [
"rule_id",
"predicate_id",
"effect",
"required_slots",
"renderer_constraints",
"authority_refs",
"review_status"
]
},
"closure": {
"exactly_one_approved_rule_required_when_activated": true,
"zero_match_issue_code": "S2-20-COUNTER-PERFORMANCE-RULES-ZERO-MATCH",
"multi_match_issue_code": "S2-20-COUNTER-PERFORMANCE-RULES-MULTI-MATCH",
"free_text_fallback_forbidden": true
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,29 @@
{
"schema_version": "stage2.s2_20.drafting_rule_registry.v1",
"registry_id": "S2-20-FORBIDDEN-RELIEF-RULES",
"purpose": "prohibited and permitted corrective relief branches",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"rule_rows": [],
"row_contract": {
"required_fields": [
"rule_id",
"predicate_id",
"effect",
"required_slots",
"renderer_constraints",
"authority_refs",
"review_status"
]
},
"closure": {
"exactly_one_approved_rule_required_when_activated": true,
"zero_match_issue_code": "S2-20-FORBIDDEN-RELIEF-RULES-ZERO-MATCH",
"multi_match_issue_code": "S2-20-FORBIDDEN-RELIEF-RULES-MULTI-MATCH",
"free_text_fallback_forbidden": true
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,29 @@
{
"schema_version": "stage2.s2_20.drafting_rule_registry.v1",
"registry_id": "S2-20-PROCEDURAL-DECLARATION-RULES",
"purpose": "service-based procedural declaration branches",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"rule_rows": [],
"row_contract": {
"required_fields": [
"rule_id",
"predicate_id",
"effect",
"required_slots",
"renderer_constraints",
"authority_refs",
"review_status"
]
},
"closure": {
"exactly_one_approved_rule_required_when_activated": true,
"zero_match_issue_code": "S2-20-PROCEDURAL-DECLARATION-RULES-ZERO-MATCH",
"multi_match_issue_code": "S2-20-PROCEDURAL-DECLARATION-RULES-MULTI-MATCH",
"free_text_fallback_forbidden": true
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,8 @@
{
"schema_version": "stage2_party_set_rules.v1",
"registry_id": "S2_20_PARTY_SET_RULES_V1",
"rules": [],
"exactly_one_match_required": true,
"fallback_allowed": false,
"registry_status": "PENDING_LEGAL_CONTENT"
}
@@ -0,0 +1,16 @@
{
"schema_version": "stage2_option_disposition_policy.v1",
"policy_id": "S2_20_OPTION_DISPOSITION_POLICY_V1",
"precedence_order": [
"LEGAL_EXCLUSION",
"CLIENT_NO_SUE",
"PRECONDITION",
"COMPATIBILITY",
"LEGAL_DECISION"
],
"rules": [],
"exhaustive_cross_product_required": true,
"exactly_one_match_required": true,
"hidden_default_allowed": false,
"policy_status": "PENDING_LEGAL_REVIEW"
}
@@ -0,0 +1,32 @@
{
"schema_version": "stage2_finding_fixture_map.v1",
"registry_id": "S2-FINDING-FIXTURE-MAP-PENDING",
"status": "PENDING_SOURCE_FINDING_RECONCILIATION",
"execution_eligible": false,
"runtime_legal_source": false,
"required_fixture_case_ids": [
"S20-F01-SINGLE-OPTION-GROUP",
"S20-F02-MIXED-PORTFOLIO",
"S20-F03-CLIENT-NO-SUE",
"S20-F04-CASE-RULE-EXACTNESS",
"S20-F05-ROW-KIND-BRANCH",
"S20-F06-PARTY-TITLE",
"S20-F07-CE01-INTEREST",
"S20-F08-CE03-LIMITATION",
"S20-F09-CE08-RESERVED-SHARE",
"S20-F10-ACTIO-ROUTE-CAP",
"S20-F11-CE13-COURT-VALUE",
"S20-F12-RETRIEVAL-BOUNDARY",
"S20-F13-CORPUS-INTEGRITY",
"S20-F14-EXHIBIT-LABEL",
"S20-F15-OPTION-SILENT-LOSS",
"S20-F16-PUBLISH-BARRIER",
"S20-F17-LEGACY-PATH"
],
"mapping_rows": [],
"mapped_fixture_case_count": 0,
"required_fixture_case_count": 17,
"source_finding_families": ["discrepancy_report_1..4", "improvement_report_1..4", "improvement_merged", "eval_stage_2_optimal_update_strategy_v.3"],
"unresolved_reason_codes": ["SOURCE_FINDINGS_NOT_EXTRACTED","INVARIANT_MAPPING_NOT_REVIEWED","FIXTURE_CROSSWALK_NOT_SIGNED"],
"guards": {"runtime_routing_use_forbidden":true,"legal_proposition_source_use_forbidden":true,"unmapped_finding_silent_drop_forbidden":true,"pending_map_is_not_coverage_proof":true}
}
@@ -0,0 +1,37 @@
{
"schema_version": "stage2.s2_20.review_policy_registry.v1",
"registry_id": "S2-20-REVIEW-POLICY",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"base_status_enum": [
"CLEAN_DRAFT",
"REVIEW_DRAFT",
"WORKNOTE_ONLY"
],
"trigger_contract": {
"sources": [
"case_type_rule",
"calculation",
"authority",
"corpus",
"party",
"runtime_issue"
],
"exactly_one_policy_result_required": true
},
"policy_rows": [],
"default_unapproved_result": {
"drafting_permission": "WORKNOTE_ONLY",
"issue_code": "REVIEW_POLICY_NOT_APPROVED",
"ready_eligible": false
},
"closure": {
"ready_requires_all_required_receipts": true,
"ready_requires_no_unresolved_blocking_issue": true,
"missing_policy_cannot_upgrade_permission": true
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,31 @@
{
"schema_version": "stage2.s2_20.inheritance_reserved_share_temporal.v1",
"registry_id": "S2-20-INHERITANCE-RESERVED-SHARE-TEMPORAL",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"temporal_basis_field": "inheritance_opening_date",
"branch_rows": [],
"row_contract": {
"required_fields": [
"temporal_rule_id",
"effective_from",
"effective_to",
"remedy_mode",
"renderer_id",
"interest_branch_id",
"authority_refs",
"review_status"
],
"interval_overlap_forbidden": true,
"uncovered_interval_issue_code": "INHERITANCE_RESERVED_SHARE_TEMPORAL_GAP"
},
"closure": {
"missing_date_issue_code": "INHERITANCE_OPENING_DATE_MISSING",
"guessed_effective_date_forbidden": true,
"fallback_to_current_law_forbidden": true
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
"""Produce a non-destructive rollback decision receipt for an admitted canary."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("admission", type=Path)
parser.add_argument("baseline", type=Path)
parser.add_argument("output", type=Path)
args = parser.parse_args()
admission_raw = args.admission.read_bytes()
baseline_raw = args.baseline.read_bytes()
admission = json.loads(admission_raw)
baseline = json.loads(baseline_raw)
rollback = admission.get("canary_status") != "PASS"
payload = {
"schema_version": "stage2.canary_rollback_receipt.v1",
"decision": "ROLLBACK_REQUIRED" if rollback else "KEEP_CANARY",
"admission_sha256": hashlib.sha256(admission_raw).hexdigest(),
"baseline_sha256": hashlib.sha256(baseline_raw).hexdigest(),
"rollback_target_release_sha256": baseline.get("release_sha256") if rollback else None,
"mutation_performed": False,
}
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(json.dumps(payload, sort_keys=True, separators=(",", ":")) + "\n", encoding="utf-8")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
"""Produce a non-destructive rollback decision receipt for an admitted canary."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("admission", type=Path)
parser.add_argument("baseline", type=Path)
parser.add_argument("output", type=Path)
args = parser.parse_args()
admission_raw = args.admission.read_bytes()
baseline_raw = args.baseline.read_bytes()
admission = json.loads(admission_raw)
baseline = json.loads(baseline_raw)
rollback = admission.get("canary_status") != "PASS"
payload = {
"schema_version": "stage2.canary_rollback_receipt.v1",
"decision": "ROLLBACK_REQUIRED" if rollback else "KEEP_CANARY",
"admission_sha256": hashlib.sha256(admission_raw).hexdigest(),
"baseline_sha256": hashlib.sha256(baseline_raw).hexdigest(),
"rollback_target_release_sha256": baseline.get("release_sha256") if rollback else None,
"mutation_performed": False,
}
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(json.dumps(payload, sort_keys=True, separators=(",", ":")) + "\n", encoding="utf-8")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,581 @@
#!/usr/bin/env python3
"""Read-only validator for the canonical Stage-2 raw release closure.
The report separates contract errors from honest pending legal/live evidence.
An offline PASS therefore never means that 137-case legal content, Weaviate,
Code Executor, host CAS or production admission has been approved.
"""
from __future__ import annotations
import argparse
import copy
import hashlib
import json
from pathlib import Path, PurePosixPath
from typing import Any
MODULE_MANIFEST_SCHEMA = "stage2_module_manifest.v1"
PARENT_RELEASE_SCHEMA = "stage2_release.v2"
SHA256_LENGTH = 64
EXPECTED_CASE_TYPE_IDS = tuple(f"CT-{index:03d}" for index in range(1, 138))
EXPECTED_CATALOG_ROW_IDS = tuple(f"CAT-{index:03d}" for index in range(1, 138))
EXPECTED_MANIFEST_DIGEST_CONTRACT = {
"algorithm_id": "STAGE2-MODULE-MANIFEST-DIGEST-V1",
"array_order": "PRESERVE_DECLARED_ORDER",
"canonicalization_algorithm_id": "STAGE2-CANONICAL-JSON-V1",
"digest_algorithm": "sha256",
"digest_scope": "ENTIRE_DOCUMENT_AFTER_REMOVING_TOP_LEVEL_MANIFEST_DIGEST",
"encoding": "UTF-8",
"line_termination": "LF_ONE_TRAILING_NEWLINE",
"non_finite_numbers_allowed": False,
"object_key_order": "SORT_CODEPOINT",
}
EXPECTED_RELEASE_DIGEST_CONTRACT = {
"algorithm_id": "STAGE2-RELEASE-DIGEST-V1",
"array_order": "PRESERVE_DECLARED_ORDER",
"canonicalization_algorithm_id": "STAGE2-CANONICAL-JSON-V1",
"digest_algorithm": "sha256",
"digest_scope": "ENTIRE_DOCUMENT_AFTER_REMOVING_TOP_LEVEL_RELEASE_DIGEST",
"encoding": "UTF-8",
"line_termination": "LF_ONE_TRAILING_NEWLINE",
"non_finite_numbers_allowed": False,
"object_key_order": "SORT_CODEPOINT",
}
FORBIDDEN_PARENT_MEMBERS = frozenset(
{
"manifest/module_manifest.json",
"manifest/stage2_release.json",
"deployment/stage2_code_executor_binding.yml",
"manifest/stage2_deterministic_admission_receipt.json",
"agent_scripts/Stage_2_S2_00.yml",
"runtime/s2_00_ingress.py",
"runtime/s2_00_ingress.txt",
"manifest/s2_00_inline_code_receipt.json",
"agent_scripts/Stage_2_S2_20.yml",
"runtime/s2_20_reduce.py",
"runtime/s2_20_reduce.txt",
"manifest/s2_20_inline_code_receipt.json",
"manifest/s2_10_release.json",
"manifest/s2_10_agent_receipt.json",
"manifest/s2_10_platform_adapter_receipt.json",
"manifest/s2_10_model_benchmark_receipt.json",
"manifest/s2_10_legal_review_receipt.json",
}
)
class ValidationInputError(ValueError):
"""Raised when a validation input cannot be parsed deterministically."""
def _reject_duplicate_pairs(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
result: dict[str, Any] = {}
for key, value in pairs:
if key in result:
raise ValidationInputError(f"DUPLICATE_JSON_KEY:{key}")
result[key] = value
return result
def _load_json(path: Path) -> Any:
try:
return json.loads(
path.read_text(encoding="utf-8"),
object_pairs_hook=_reject_duplicate_pairs,
parse_constant=lambda token: (_ for _ in ()).throw(
ValidationInputError(f"NON_FINITE_JSON_NUMBER:{token}")
),
)
except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc:
raise ValidationInputError(f"JSON_READ_FAILED:{path.as_posix()}:{exc}") from exc
def _canonical_bytes(document: Any) -> bytes:
return (
json.dumps(
document,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
).encode("utf-8")
def _sha256(raw: bytes) -> str:
return hashlib.sha256(raw).hexdigest()
def _document_digest(document: dict[str, Any], digest_field: str) -> str:
payload = copy.deepcopy(document)
payload.pop(digest_field, None)
return _sha256(_canonical_bytes(payload))
def _finding(code: str, path: str, detail: str) -> dict[str, str]:
return {"code": code, "detail": detail, "path": path}
def _is_sha256(value: Any) -> bool:
return (
isinstance(value, str)
and len(value) == SHA256_LENGTH
and all(character in "0123456789abcdef" for character in value)
)
def _contains_contract(value: Any, expected: dict[str, Any]) -> bool:
return isinstance(value, dict) and all(value.get(key) == item for key, item in expected.items())
def _relative_path(value: Any) -> str | None:
if not isinstance(value, str) or not value or "\\" in value:
return None
pure = PurePosixPath(value)
if pure.is_absolute() or any(part in {"", ".", ".."} for part in pure.parts):
return None
return pure.as_posix()
def _legacy_path(relative: str) -> bool:
return any(part in {"v.0", "v.1", "v.2", "v.3"} for part in PurePosixPath(relative).parts)
def _physical(root: Path, relative: str) -> Path | None:
candidate = root / relative
if candidate.is_symlink():
return None
try:
resolved = candidate.resolve(strict=True)
root_real = root.resolve(strict=True)
except FileNotFoundError:
return None
if root_real not in resolved.parents or not resolved.is_file():
return None
return resolved
def _validate_module_manifest(
root: Path,
manifest: dict[str, Any],
) -> tuple[list[dict[str, str]], list[dict[str, str]], dict[str, int]]:
errors: list[dict[str, str]] = []
pending: list[dict[str, str]] = []
if manifest.get("schema_version") != MODULE_MANIFEST_SCHEMA:
errors.append(_finding("MODULE_SCHEMA_VERSION", "$/schema_version", repr(manifest.get("schema_version"))))
declared_digest = manifest.get("manifest_digest")
observed_digest = _document_digest(manifest, "manifest_digest")
if declared_digest != observed_digest:
errors.append(_finding("MANIFEST_DIGEST_MISMATCH", "$/manifest_digest", f"declared={declared_digest};observed={observed_digest}"))
if not _contains_contract(manifest.get("manifest_digest_contract"), EXPECTED_MANIFEST_DIGEST_CONTRACT):
errors.append(_finding("MANIFEST_DIGEST_CONTRACT_INVALID", "$/manifest_digest_contract", repr(manifest.get("manifest_digest_contract"))))
rows = manifest.get("modules")
if not isinstance(rows, list):
return errors + [_finding("MODULES_REQUIRED", "$/modules", "canonical modules array missing")], pending, {"module_count": 0, "mirror_count": 0}
seen_ids: set[str] = set()
seen_paths: set[str] = set()
row_by_path: dict[str, dict[str, Any]] = {}
for index, row in enumerate(rows):
location = f"$/modules/{index}"
if not isinstance(row, dict):
errors.append(_finding("MODULE_ROW_INVALID", location, "object required"))
continue
module_id = row.get("module_id")
if not isinstance(module_id, str) or not module_id or module_id in seen_ids:
errors.append(_finding("MODULE_ID_INVALID_OR_DUPLICATE", f"{location}/module_id", repr(module_id)))
else:
seen_ids.add(module_id)
relative = _relative_path(row.get("path"))
if relative is None or relative in seen_paths:
errors.append(_finding("MODULE_PATH_INVALID_OR_DUPLICATE", f"{location}/path", repr(row.get("path"))))
continue
seen_paths.add(relative)
row_by_path[relative] = row
if relative in FORBIDDEN_PARENT_MEMBERS:
errors.append(_finding("NON_CYCLIC_PARENT_VIOLATION", f"{location}/path", relative))
if _legacy_path(relative):
errors.append(_finding("LEGACY_STAGE2_DEPENDENCY", f"{location}/path", relative))
physical = _physical(root, relative)
if physical is None:
errors.append(_finding("MODULE_MISSING_OR_SYMLINK", f"{location}/path", relative))
continue
raw = physical.read_bytes()
observed = _sha256(raw)
if row.get("sha256") != observed:
errors.append(_finding("MODULE_HASH_MISMATCH", f"{location}/sha256", f"path={relative};observed={observed}"))
if row.get("size_bytes") != len(raw):
errors.append(_finding("MODULE_SIZE_MISMATCH", f"{location}/size_bytes", f"path={relative};observed={len(raw)}"))
if relative.endswith(".py"):
mirror = relative[:-3] + ".txt"
mirror_physical = _physical(root, mirror)
if mirror_physical is None:
errors.append(_finding("PYTHON_DOCUMENTATION_MIRROR_MISSING", location, mirror))
continue
mirror_raw = mirror_physical.read_bytes()
if raw != mirror_raw:
errors.append(_finding("PYTHON_DOCUMENTATION_MIRROR_MISMATCH", location, relative))
expected_fields = {
"mirror_path": mirror,
"mirror_sha256": _sha256(mirror_raw),
"mirror_size_bytes": len(mirror_raw),
"mirror_byte_parity": True,
}
for key, expected in expected_fields.items():
if row.get(key) != expected:
errors.append(_finding("MODULE_MIRROR_BINDING_MISMATCH", f"{location}/{key}", f"expected={expected!r};observed={row.get(key)!r}"))
mirrors = manifest.get("documentation_mirrors")
if not isinstance(mirrors, list):
errors.append(_finding("DOCUMENTATION_MIRRORS_REQUIRED", "$/documentation_mirrors", "array required"))
mirrors = []
seen_sources: set[str] = set()
for index, mirror in enumerate(mirrors):
location = f"$/documentation_mirrors/{index}"
if not isinstance(mirror, dict):
errors.append(_finding("DOCUMENTATION_MIRROR_ROW_INVALID", location, "object required"))
continue
source = _relative_path(mirror.get("source_path"))
target = _relative_path(mirror.get("mirror_path"))
if source is None or target is None or source in seen_sources:
errors.append(_finding("DOCUMENTATION_MIRROR_PATH_INVALID", location, repr(mirror)))
continue
seen_sources.add(source)
if source in FORBIDDEN_PARENT_MEMBERS or target in FORBIDDEN_PARENT_MEMBERS:
errors.append(_finding("NON_CYCLIC_MIRROR_VIOLATION", location, f"{source}->{target}"))
source_physical = _physical(root, source)
target_physical = _physical(root, target)
if source_physical is None or target_physical is None:
errors.append(_finding("DOCUMENTATION_MIRROR_MISSING", location, f"{source}->{target}"))
continue
source_raw = source_physical.read_bytes()
target_raw = target_physical.read_bytes()
expected = {
"source_sha256": _sha256(source_raw),
"source_size_bytes": len(source_raw),
"mirror_sha256": _sha256(target_raw),
"mirror_size_bytes": len(target_raw),
"byte_identical": True,
"runtime_import_allowed": False,
}
if source_raw != target_raw:
errors.append(_finding("DOCUMENTATION_MIRROR_BYTES_DIFFER", location, source))
for key, expected_value in expected.items():
if mirror.get(key) != expected_value:
errors.append(_finding("DOCUMENTATION_MIRROR_METADATA_MISMATCH", f"{location}/{key}", f"expected={expected_value!r};observed={mirror.get(key)!r}"))
row = row_by_path.get(source)
if row is None or row.get("mirror_path") != target:
errors.append(_finding("DOCUMENTATION_MIRROR_MODULE_ORPHAN", location, source))
py_sources = {path for path in row_by_path if path.endswith(".py")}
if seen_sources != py_sources:
errors.append(_finding("DOCUMENTATION_MIRROR_COVERAGE_MISMATCH", "$/documentation_mirrors", f"expected={sorted(py_sources)};observed={sorted(seen_sources)}"))
dependency_graph: dict[str, tuple[str, ...]] = {}
for index, row in enumerate(rows):
if not isinstance(row, dict) or not isinstance(row.get("module_id"), str):
continue
dependencies = row.get("dependency_module_ids", [])
location = f"$/modules/{index}/dependency_module_ids"
if (
not isinstance(dependencies, list)
or not all(isinstance(item, str) and item for item in dependencies)
or len(dependencies) != len(set(dependencies))
):
errors.append(_finding("MODULE_DEPENDENCY_LIST_INVALID", location, repr(dependencies)))
continue
missing = sorted(set(dependencies) - seen_ids)
if missing:
errors.append(_finding("MODULE_DEPENDENCY_MISSING", location, repr(missing)))
if row["module_id"] in dependencies:
errors.append(_finding("MODULE_SELF_DEPENDENCY", location, row["module_id"]))
dependency_graph[row["module_id"]] = tuple(dependencies)
visiting: set[str] = set()
visited: set[str] = set()
def visit(module_id: str, chain: tuple[str, ...]) -> None:
if module_id in visiting:
errors.append(_finding("MODULE_DEPENDENCY_CYCLE", "$/modules", "->".join(chain + (module_id,))))
return
if module_id in visited:
return
visiting.add(module_id)
for dependency in dependency_graph.get(module_id, ()):
if dependency in dependency_graph:
visit(dependency, chain + (module_id,))
visiting.remove(module_id)
visited.add(module_id)
for module_id in sorted(dependency_graph):
visit(module_id, ())
summary = manifest.get("closure_summary")
if not isinstance(summary, dict):
errors.append(_finding("CLOSURE_SUMMARY_REQUIRED", "$/closure_summary", "object required"))
else:
for key, expected in (
("module_count", len(rows)),
("documentation_mirror_count", len(mirrors)),
):
if summary.get(key) != expected:
errors.append(_finding("CLOSURE_SUMMARY_COUNT_MISMATCH", f"$/closure_summary/{key}", f"expected={expected};observed={summary.get(key)}"))
for key in (
"executable_agent_hash_included",
"executor_binding_hash_included",
"inline_runtime_code_hash_included",
"self_hash_included",
"stage2_release_hash_included",
):
if key in summary and summary.get(key) is not False:
errors.append(_finding("NON_CYCLIC_SUMMARY_FLAG_INVALID", f"$/closure_summary/{key}", repr(summary.get(key))))
return errors, pending, {"module_count": len(rows), "mirror_count": len(mirrors)}
def _walk_parent_refs(
root: Path,
value: Any,
errors: list[dict[str, str]],
location: str = "$",
) -> None:
if isinstance(value, list):
for index, item in enumerate(value):
_walk_parent_refs(root, item, errors, f"{location}/{index}")
return
if not isinstance(value, dict):
return
relative = _relative_path(value.get("path"))
if relative is not None and "<" not in relative:
if relative == "manifest/module_manifest.json":
pass
elif relative in FORBIDDEN_PARENT_MEMBERS:
if "sha256" in value or value.get("binding_status") == "BOUND":
errors.append(_finding("NON_CYCLIC_PARENT_HASH_REFERENCE", location, relative))
elif "sha256" in value and _is_sha256(value.get("sha256")):
physical = _physical(root, relative)
if physical is not None:
observed = _sha256(physical.read_bytes())
if value["sha256"] != observed:
errors.append(_finding("PARENT_ASSET_HASH_MISMATCH", f"{location}/sha256", f"path={relative};observed={observed}"))
for key, item in value.items():
_walk_parent_refs(root, item, errors, f"{location}/{key}")
def _validate_parent_release(
root: Path,
release: dict[str, Any],
manifest_raw: bytes,
) -> tuple[list[dict[str, str]], list[dict[str, str]]]:
errors: list[dict[str, str]] = []
pending: list[dict[str, str]] = []
if release.get("schema_version") != PARENT_RELEASE_SCHEMA:
errors.append(_finding("PARENT_RELEASE_SCHEMA_VERSION", "$/schema_version", repr(release.get("schema_version"))))
if not _contains_contract(release.get("release_digest_contract"), EXPECTED_RELEASE_DIGEST_CONTRACT):
errors.append(_finding("PARENT_RELEASE_DIGEST_CONTRACT_INVALID", "$/release_digest_contract", repr(release.get("release_digest_contract"))))
declared = release.get("release_digest")
observed = _document_digest(release, "release_digest")
if declared != observed:
errors.append(_finding("PARENT_RELEASE_DIGEST_MISMATCH", "$/release_digest", f"declared={declared};observed={observed}"))
module_ref = release.get("module_manifest_ref")
if not isinstance(module_ref, dict) or module_ref.get("path") != "manifest/module_manifest.json":
errors.append(_finding("PARENT_MODULE_REF_INVALID", "$/module_manifest_ref", repr(module_ref)))
else:
expected_hash = _sha256(manifest_raw)
if module_ref.get("sha256") != expected_hash:
errors.append(_finding("PARENT_MODULE_REF_HASH_MISMATCH", "$/module_manifest_ref/sha256", f"expected={expected_hash};observed={module_ref.get('sha256')}"))
executor_ref = release.get("executor_binding_ref")
if (
not isinstance(executor_ref, dict)
or executor_ref.get("path") != "deployment/stage2_code_executor_binding.yml"
or executor_ref.get("schema_id") != "stage2_code_executor_binding.v3"
or "sha256" in executor_ref
or executor_ref.get("binding_status") == "BOUND"
):
errors.append(_finding("PARENT_EXECUTOR_TRUST_ROOT_REF_INVALID", "$/executor_binding_ref", repr(executor_ref)))
_walk_parent_refs(root, release, errors)
status = release.get("release_status")
authorization = release.get("authorization_status")
signature = release.get("signature")
if status == "ADMITTED":
if authorization not in {"CANARY_ADMITTED", "PRODUCTION_ADMITTED"}:
errors.append(_finding("ADMITTED_RELEASE_AUTHORIZATION_INVALID", "$/authorization_status", repr(authorization)))
if signature == "PENDING_SEQUENTIAL_BIND" or not isinstance(signature, str) or len(signature) < 32:
errors.append(_finding("ADMITTED_RELEASE_SIGNATURE_INVALID", "$/signature", repr(signature)))
else:
pending.append(_finding("PARENT_RELEASE_NOT_ADMITTED", "$/release_status", str(status)))
return errors, pending
def _nested_pending(value: Any) -> bool:
if isinstance(value, str):
return "PENDING" in value or value in {"UNVERIFIED", "NOT_IMPLEMENTED", "DEV_UNAVAILABLE"}
if isinstance(value, list):
return any(_nested_pending(item) for item in value)
if isinstance(value, dict):
return any(_nested_pending(item) for item in value.values())
return False
def _contains_ready_claim(value: Any) -> bool:
if isinstance(value, str):
return value in {"FULL_137_PRODUCTION_READY", "PRODUCTION_READY", "ADMITTED"}
if isinstance(value, list):
return any(_contains_ready_claim(item) for item in value)
if isinstance(value, dict):
return any(_contains_ready_claim(item) for item in value.values())
return False
def _validate_137_coverage(
root: Path,
case_registry: dict[str, Any],
rule_registry: dict[str, Any],
coverage: dict[str, Any],
) -> tuple[list[dict[str, str]], list[dict[str, str]], dict[str, int]]:
errors: list[dict[str, str]] = []
pending: list[dict[str, str]] = []
case_rows = case_registry.get("rows")
rule_rows = rule_registry.get("rows")
coverage_rows = coverage.get("coverage_rows")
if not isinstance(case_rows, list) or len(case_rows) != 137:
errors.append(_finding("CASE_TYPE_REGISTRY_EXACT_137_REQUIRED", "case_type_registry:/rows", f"observed={len(case_rows) if isinstance(case_rows, list) else 'invalid'}"))
case_rows = []
if not isinstance(rule_rows, list) or len(rule_rows) != 137:
errors.append(_finding("CASE_TYPE_RULE_REGISTRY_EXACT_137_REQUIRED", "case_type_rule_registry:/rows", f"observed={len(rule_rows) if isinstance(rule_rows, list) else 'invalid'}"))
rule_rows = []
if not isinstance(coverage_rows, list) or len(coverage_rows) != 137:
errors.append(_finding("CASE_TYPE_COVERAGE_EXACT_137_REQUIRED", "case_type_coverage:/coverage_rows", f"observed={len(coverage_rows) if isinstance(coverage_rows, list) else 'invalid'}"))
coverage_rows = []
observed_case_ids = tuple(row.get("case_type_id") for row in case_rows if isinstance(row, dict))
observed_catalog_ids = tuple(row.get("catalog_row_id") for row in case_rows if isinstance(row, dict))
declared_catalog_ids = tuple(case_registry.get("catalog_row_ids", ()))
observed_rule_ids = tuple(row.get("case_type_id") for row in rule_rows if isinstance(row, dict))
observed_coverage_ids = tuple(row.get("case_type_id") for row in coverage_rows if isinstance(row, dict))
for code, path, observed, expected in (
("CASE_TYPE_ID_ORDER_MISMATCH", "case_type_registry:/rows", observed_case_ids, EXPECTED_CASE_TYPE_IDS),
("CATALOG_ROW_ID_ORDER_MISMATCH", "case_type_registry:/rows", observed_catalog_ids, EXPECTED_CATALOG_ROW_IDS),
("DECLARED_CATALOG_ROW_ID_ORDER_MISMATCH", "case_type_registry:/catalog_row_ids", declared_catalog_ids, EXPECTED_CATALOG_ROW_IDS),
("RULE_CASE_TYPE_ID_ORDER_MISMATCH", "case_type_rule_registry:/rows", observed_rule_ids, EXPECTED_CASE_TYPE_IDS),
("COVERAGE_CASE_TYPE_ID_ORDER_MISMATCH", "case_type_coverage:/coverage_rows", observed_coverage_ids, EXPECTED_CASE_TYPE_IDS),
):
if observed != expected:
errors.append(_finding(code, path, "exact CT/CAT ordinal sequence required"))
case_path = _physical(root, "manifest/case_type_registry.yml")
if case_path is None:
errors.append(_finding("CASE_TYPE_REGISTRY_PHYSICAL_FILE_REQUIRED", "case_type_registry:$", "manifest/case_type_registry.yml"))
case_raw = _canonical_bytes(case_registry)
else:
case_raw = case_path.read_bytes()
case_ref = rule_registry.get("case_type_registry_ref")
case_hash = rule_registry.get("case_type_registry_sha256")
if case_ref != "manifest/case_type_registry.yml" or case_hash != _sha256(case_raw):
errors.append(_finding("RULE_REGISTRY_CASE_TYPE_REF_MISMATCH", "case_type_rule_registry:/case_type_registry_sha256", f"expected={_sha256(case_raw)};observed={case_hash}"))
coverage_dependency = coverage.get("registry_dependency")
if isinstance(coverage_dependency, dict):
declared = coverage_dependency.get("sha256")
if declared is not None and declared != _sha256(case_raw):
errors.append(_finding("COVERAGE_REGISTRY_HASH_MISMATCH", "case_type_coverage:/registry_dependency/sha256", f"expected={_sha256(case_raw)};observed={declared}"))
else:
errors.append(_finding("COVERAGE_REGISTRY_DEPENDENCY_REQUIRED", "case_type_coverage:/registry_dependency", "object required"))
rule_doc_count = 0
for case_type_id in EXPECTED_CASE_TYPE_IDS:
if _physical(root, f"rules/relief/{case_type_id}.md") is not None:
rule_doc_count += 1
pending_legal = (
rule_doc_count != 137
or _nested_pending(case_registry)
or _nested_pending(rule_registry)
or _nested_pending(coverage)
)
if pending_legal:
if coverage.get("release_eligible") is True or _contains_ready_claim(coverage):
errors.append(_finding("DISHONEST_FULL_137_READY_CLAIM", "case_type_coverage:$", f"rule_document_count={rule_doc_count};pending_contract=true"))
pending.append(_finding("FULL_137_LEGAL_COVERAGE_PENDING", "case_type_coverage:$", f"rule_document_count={rule_doc_count};legal registry/sign-off not fully admitted"))
return errors, pending, {
"case_type_count": len(case_rows),
"case_type_rule_row_count": len(rule_rows),
"coverage_row_count": len(coverage_rows),
"relief_rule_document_count": rule_doc_count,
}
def validate_package(
root: Path,
manifest_path: Path,
release_path: Path,
case_registry_path: Path,
rule_registry_path: Path,
coverage_path: Path,
) -> dict[str, Any]:
manifest = _load_json(manifest_path)
release = _load_json(release_path)
case_registry = _load_json(case_registry_path)
rule_registry = _load_json(rule_registry_path)
coverage = _load_json(coverage_path)
if not all(isinstance(row, dict) for row in (manifest, release, case_registry, rule_registry, coverage)):
raise ValidationInputError("ALL_RELEASE_INPUTS_MUST_BE_OBJECTS")
errors, pending, counts = _validate_module_manifest(root, manifest)
parent_errors, parent_pending = _validate_parent_release(root, release, manifest_path.read_bytes())
coverage_errors, coverage_pending, coverage_counts = _validate_137_coverage(root, case_registry, rule_registry, coverage)
errors.extend(parent_errors)
errors.extend(coverage_errors)
pending.extend(parent_pending)
pending.extend(coverage_pending)
if (
any(row["code"] == "FULL_137_LEGAL_COVERAGE_PENDING" for row in coverage_pending)
and (
release.get("release_class") == "PRODUCTION_RELEASE"
or (isinstance(release.get("bundle"), dict) and release["bundle"].get("mode") == "PRODUCTION")
)
):
errors.append(_finding("PRODUCTION_RELEASE_WITH_PENDING_137_COVERAGE", "stage2_release:$", "full-137 legal/corpus coverage is not admitted"))
counts.update(coverage_counts)
errors = sorted(errors, key=lambda row: (row["code"], row["path"], row["detail"]))
pending = sorted(pending, key=lambda row: (row["code"], row["path"], row["detail"]))
return {
"counts": dict(sorted(counts.items())),
"errors": errors,
"pending": pending,
"schema_version": "stage2_release_validation.v1",
"status": "PASS" if not errors else "FAIL",
}
def validate(root: Path, manifest: dict[str, object]) -> list[str]:
"""Compatibility wrapper for callers that only validate module rows."""
errors, _, _ = _validate_module_manifest(root, manifest)
return [f"{row['code']}:{row['path']}:{row['detail']}" for row in errors]
def main() -> int:
parser = argparse.ArgumentParser(description="Validate canonical Stage-2 raw release closure")
parser.add_argument("root", type=Path)
parser.add_argument("manifest", type=Path, nargs="?")
parser.add_argument("--release", type=Path)
parser.add_argument("--case-registry", type=Path)
parser.add_argument("--rule-registry", type=Path)
parser.add_argument("--coverage", type=Path)
args = parser.parse_args()
report = validate_package(
args.root,
args.manifest or args.root / "manifest/module_manifest.json",
args.release or args.root / "manifest/stage2_release.json",
args.case_registry or args.root / "manifest/case_type_registry.yml",
args.rule_registry or args.root / "manifest/case_type_rule_registry.yml",
args.coverage or args.root / "manifest/case_type_coverage.json",
)
print(json.dumps(report, ensure_ascii=False, sort_keys=True, separators=(",", ":")))
return 0 if report["status"] == "PASS" else 1
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,581 @@
#!/usr/bin/env python3
"""Read-only validator for the canonical Stage-2 raw release closure.
The report separates contract errors from honest pending legal/live evidence.
An offline PASS therefore never means that 137-case legal content, Weaviate,
Code Executor, host CAS or production admission has been approved.
"""
from __future__ import annotations
import argparse
import copy
import hashlib
import json
from pathlib import Path, PurePosixPath
from typing import Any
MODULE_MANIFEST_SCHEMA = "stage2_module_manifest.v1"
PARENT_RELEASE_SCHEMA = "stage2_release.v2"
SHA256_LENGTH = 64
EXPECTED_CASE_TYPE_IDS = tuple(f"CT-{index:03d}" for index in range(1, 138))
EXPECTED_CATALOG_ROW_IDS = tuple(f"CAT-{index:03d}" for index in range(1, 138))
EXPECTED_MANIFEST_DIGEST_CONTRACT = {
"algorithm_id": "STAGE2-MODULE-MANIFEST-DIGEST-V1",
"array_order": "PRESERVE_DECLARED_ORDER",
"canonicalization_algorithm_id": "STAGE2-CANONICAL-JSON-V1",
"digest_algorithm": "sha256",
"digest_scope": "ENTIRE_DOCUMENT_AFTER_REMOVING_TOP_LEVEL_MANIFEST_DIGEST",
"encoding": "UTF-8",
"line_termination": "LF_ONE_TRAILING_NEWLINE",
"non_finite_numbers_allowed": False,
"object_key_order": "SORT_CODEPOINT",
}
EXPECTED_RELEASE_DIGEST_CONTRACT = {
"algorithm_id": "STAGE2-RELEASE-DIGEST-V1",
"array_order": "PRESERVE_DECLARED_ORDER",
"canonicalization_algorithm_id": "STAGE2-CANONICAL-JSON-V1",
"digest_algorithm": "sha256",
"digest_scope": "ENTIRE_DOCUMENT_AFTER_REMOVING_TOP_LEVEL_RELEASE_DIGEST",
"encoding": "UTF-8",
"line_termination": "LF_ONE_TRAILING_NEWLINE",
"non_finite_numbers_allowed": False,
"object_key_order": "SORT_CODEPOINT",
}
FORBIDDEN_PARENT_MEMBERS = frozenset(
{
"manifest/module_manifest.json",
"manifest/stage2_release.json",
"deployment/stage2_code_executor_binding.yml",
"manifest/stage2_deterministic_admission_receipt.json",
"agent_scripts/Stage_2_S2_00.yml",
"runtime/s2_00_ingress.py",
"runtime/s2_00_ingress.txt",
"manifest/s2_00_inline_code_receipt.json",
"agent_scripts/Stage_2_S2_20.yml",
"runtime/s2_20_reduce.py",
"runtime/s2_20_reduce.txt",
"manifest/s2_20_inline_code_receipt.json",
"manifest/s2_10_release.json",
"manifest/s2_10_agent_receipt.json",
"manifest/s2_10_platform_adapter_receipt.json",
"manifest/s2_10_model_benchmark_receipt.json",
"manifest/s2_10_legal_review_receipt.json",
}
)
class ValidationInputError(ValueError):
"""Raised when a validation input cannot be parsed deterministically."""
def _reject_duplicate_pairs(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
result: dict[str, Any] = {}
for key, value in pairs:
if key in result:
raise ValidationInputError(f"DUPLICATE_JSON_KEY:{key}")
result[key] = value
return result
def _load_json(path: Path) -> Any:
try:
return json.loads(
path.read_text(encoding="utf-8"),
object_pairs_hook=_reject_duplicate_pairs,
parse_constant=lambda token: (_ for _ in ()).throw(
ValidationInputError(f"NON_FINITE_JSON_NUMBER:{token}")
),
)
except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc:
raise ValidationInputError(f"JSON_READ_FAILED:{path.as_posix()}:{exc}") from exc
def _canonical_bytes(document: Any) -> bytes:
return (
json.dumps(
document,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
).encode("utf-8")
def _sha256(raw: bytes) -> str:
return hashlib.sha256(raw).hexdigest()
def _document_digest(document: dict[str, Any], digest_field: str) -> str:
payload = copy.deepcopy(document)
payload.pop(digest_field, None)
return _sha256(_canonical_bytes(payload))
def _finding(code: str, path: str, detail: str) -> dict[str, str]:
return {"code": code, "detail": detail, "path": path}
def _is_sha256(value: Any) -> bool:
return (
isinstance(value, str)
and len(value) == SHA256_LENGTH
and all(character in "0123456789abcdef" for character in value)
)
def _contains_contract(value: Any, expected: dict[str, Any]) -> bool:
return isinstance(value, dict) and all(value.get(key) == item for key, item in expected.items())
def _relative_path(value: Any) -> str | None:
if not isinstance(value, str) or not value or "\\" in value:
return None
pure = PurePosixPath(value)
if pure.is_absolute() or any(part in {"", ".", ".."} for part in pure.parts):
return None
return pure.as_posix()
def _legacy_path(relative: str) -> bool:
return any(part in {"v.0", "v.1", "v.2", "v.3"} for part in PurePosixPath(relative).parts)
def _physical(root: Path, relative: str) -> Path | None:
candidate = root / relative
if candidate.is_symlink():
return None
try:
resolved = candidate.resolve(strict=True)
root_real = root.resolve(strict=True)
except FileNotFoundError:
return None
if root_real not in resolved.parents or not resolved.is_file():
return None
return resolved
def _validate_module_manifest(
root: Path,
manifest: dict[str, Any],
) -> tuple[list[dict[str, str]], list[dict[str, str]], dict[str, int]]:
errors: list[dict[str, str]] = []
pending: list[dict[str, str]] = []
if manifest.get("schema_version") != MODULE_MANIFEST_SCHEMA:
errors.append(_finding("MODULE_SCHEMA_VERSION", "$/schema_version", repr(manifest.get("schema_version"))))
declared_digest = manifest.get("manifest_digest")
observed_digest = _document_digest(manifest, "manifest_digest")
if declared_digest != observed_digest:
errors.append(_finding("MANIFEST_DIGEST_MISMATCH", "$/manifest_digest", f"declared={declared_digest};observed={observed_digest}"))
if not _contains_contract(manifest.get("manifest_digest_contract"), EXPECTED_MANIFEST_DIGEST_CONTRACT):
errors.append(_finding("MANIFEST_DIGEST_CONTRACT_INVALID", "$/manifest_digest_contract", repr(manifest.get("manifest_digest_contract"))))
rows = manifest.get("modules")
if not isinstance(rows, list):
return errors + [_finding("MODULES_REQUIRED", "$/modules", "canonical modules array missing")], pending, {"module_count": 0, "mirror_count": 0}
seen_ids: set[str] = set()
seen_paths: set[str] = set()
row_by_path: dict[str, dict[str, Any]] = {}
for index, row in enumerate(rows):
location = f"$/modules/{index}"
if not isinstance(row, dict):
errors.append(_finding("MODULE_ROW_INVALID", location, "object required"))
continue
module_id = row.get("module_id")
if not isinstance(module_id, str) or not module_id or module_id in seen_ids:
errors.append(_finding("MODULE_ID_INVALID_OR_DUPLICATE", f"{location}/module_id", repr(module_id)))
else:
seen_ids.add(module_id)
relative = _relative_path(row.get("path"))
if relative is None or relative in seen_paths:
errors.append(_finding("MODULE_PATH_INVALID_OR_DUPLICATE", f"{location}/path", repr(row.get("path"))))
continue
seen_paths.add(relative)
row_by_path[relative] = row
if relative in FORBIDDEN_PARENT_MEMBERS:
errors.append(_finding("NON_CYCLIC_PARENT_VIOLATION", f"{location}/path", relative))
if _legacy_path(relative):
errors.append(_finding("LEGACY_STAGE2_DEPENDENCY", f"{location}/path", relative))
physical = _physical(root, relative)
if physical is None:
errors.append(_finding("MODULE_MISSING_OR_SYMLINK", f"{location}/path", relative))
continue
raw = physical.read_bytes()
observed = _sha256(raw)
if row.get("sha256") != observed:
errors.append(_finding("MODULE_HASH_MISMATCH", f"{location}/sha256", f"path={relative};observed={observed}"))
if row.get("size_bytes") != len(raw):
errors.append(_finding("MODULE_SIZE_MISMATCH", f"{location}/size_bytes", f"path={relative};observed={len(raw)}"))
if relative.endswith(".py"):
mirror = relative[:-3] + ".txt"
mirror_physical = _physical(root, mirror)
if mirror_physical is None:
errors.append(_finding("PYTHON_DOCUMENTATION_MIRROR_MISSING", location, mirror))
continue
mirror_raw = mirror_physical.read_bytes()
if raw != mirror_raw:
errors.append(_finding("PYTHON_DOCUMENTATION_MIRROR_MISMATCH", location, relative))
expected_fields = {
"mirror_path": mirror,
"mirror_sha256": _sha256(mirror_raw),
"mirror_size_bytes": len(mirror_raw),
"mirror_byte_parity": True,
}
for key, expected in expected_fields.items():
if row.get(key) != expected:
errors.append(_finding("MODULE_MIRROR_BINDING_MISMATCH", f"{location}/{key}", f"expected={expected!r};observed={row.get(key)!r}"))
mirrors = manifest.get("documentation_mirrors")
if not isinstance(mirrors, list):
errors.append(_finding("DOCUMENTATION_MIRRORS_REQUIRED", "$/documentation_mirrors", "array required"))
mirrors = []
seen_sources: set[str] = set()
for index, mirror in enumerate(mirrors):
location = f"$/documentation_mirrors/{index}"
if not isinstance(mirror, dict):
errors.append(_finding("DOCUMENTATION_MIRROR_ROW_INVALID", location, "object required"))
continue
source = _relative_path(mirror.get("source_path"))
target = _relative_path(mirror.get("mirror_path"))
if source is None or target is None or source in seen_sources:
errors.append(_finding("DOCUMENTATION_MIRROR_PATH_INVALID", location, repr(mirror)))
continue
seen_sources.add(source)
if source in FORBIDDEN_PARENT_MEMBERS or target in FORBIDDEN_PARENT_MEMBERS:
errors.append(_finding("NON_CYCLIC_MIRROR_VIOLATION", location, f"{source}->{target}"))
source_physical = _physical(root, source)
target_physical = _physical(root, target)
if source_physical is None or target_physical is None:
errors.append(_finding("DOCUMENTATION_MIRROR_MISSING", location, f"{source}->{target}"))
continue
source_raw = source_physical.read_bytes()
target_raw = target_physical.read_bytes()
expected = {
"source_sha256": _sha256(source_raw),
"source_size_bytes": len(source_raw),
"mirror_sha256": _sha256(target_raw),
"mirror_size_bytes": len(target_raw),
"byte_identical": True,
"runtime_import_allowed": False,
}
if source_raw != target_raw:
errors.append(_finding("DOCUMENTATION_MIRROR_BYTES_DIFFER", location, source))
for key, expected_value in expected.items():
if mirror.get(key) != expected_value:
errors.append(_finding("DOCUMENTATION_MIRROR_METADATA_MISMATCH", f"{location}/{key}", f"expected={expected_value!r};observed={mirror.get(key)!r}"))
row = row_by_path.get(source)
if row is None or row.get("mirror_path") != target:
errors.append(_finding("DOCUMENTATION_MIRROR_MODULE_ORPHAN", location, source))
py_sources = {path for path in row_by_path if path.endswith(".py")}
if seen_sources != py_sources:
errors.append(_finding("DOCUMENTATION_MIRROR_COVERAGE_MISMATCH", "$/documentation_mirrors", f"expected={sorted(py_sources)};observed={sorted(seen_sources)}"))
dependency_graph: dict[str, tuple[str, ...]] = {}
for index, row in enumerate(rows):
if not isinstance(row, dict) or not isinstance(row.get("module_id"), str):
continue
dependencies = row.get("dependency_module_ids", [])
location = f"$/modules/{index}/dependency_module_ids"
if (
not isinstance(dependencies, list)
or not all(isinstance(item, str) and item for item in dependencies)
or len(dependencies) != len(set(dependencies))
):
errors.append(_finding("MODULE_DEPENDENCY_LIST_INVALID", location, repr(dependencies)))
continue
missing = sorted(set(dependencies) - seen_ids)
if missing:
errors.append(_finding("MODULE_DEPENDENCY_MISSING", location, repr(missing)))
if row["module_id"] in dependencies:
errors.append(_finding("MODULE_SELF_DEPENDENCY", location, row["module_id"]))
dependency_graph[row["module_id"]] = tuple(dependencies)
visiting: set[str] = set()
visited: set[str] = set()
def visit(module_id: str, chain: tuple[str, ...]) -> None:
if module_id in visiting:
errors.append(_finding("MODULE_DEPENDENCY_CYCLE", "$/modules", "->".join(chain + (module_id,))))
return
if module_id in visited:
return
visiting.add(module_id)
for dependency in dependency_graph.get(module_id, ()):
if dependency in dependency_graph:
visit(dependency, chain + (module_id,))
visiting.remove(module_id)
visited.add(module_id)
for module_id in sorted(dependency_graph):
visit(module_id, ())
summary = manifest.get("closure_summary")
if not isinstance(summary, dict):
errors.append(_finding("CLOSURE_SUMMARY_REQUIRED", "$/closure_summary", "object required"))
else:
for key, expected in (
("module_count", len(rows)),
("documentation_mirror_count", len(mirrors)),
):
if summary.get(key) != expected:
errors.append(_finding("CLOSURE_SUMMARY_COUNT_MISMATCH", f"$/closure_summary/{key}", f"expected={expected};observed={summary.get(key)}"))
for key in (
"executable_agent_hash_included",
"executor_binding_hash_included",
"inline_runtime_code_hash_included",
"self_hash_included",
"stage2_release_hash_included",
):
if key in summary and summary.get(key) is not False:
errors.append(_finding("NON_CYCLIC_SUMMARY_FLAG_INVALID", f"$/closure_summary/{key}", repr(summary.get(key))))
return errors, pending, {"module_count": len(rows), "mirror_count": len(mirrors)}
def _walk_parent_refs(
root: Path,
value: Any,
errors: list[dict[str, str]],
location: str = "$",
) -> None:
if isinstance(value, list):
for index, item in enumerate(value):
_walk_parent_refs(root, item, errors, f"{location}/{index}")
return
if not isinstance(value, dict):
return
relative = _relative_path(value.get("path"))
if relative is not None and "<" not in relative:
if relative == "manifest/module_manifest.json":
pass
elif relative in FORBIDDEN_PARENT_MEMBERS:
if "sha256" in value or value.get("binding_status") == "BOUND":
errors.append(_finding("NON_CYCLIC_PARENT_HASH_REFERENCE", location, relative))
elif "sha256" in value and _is_sha256(value.get("sha256")):
physical = _physical(root, relative)
if physical is not None:
observed = _sha256(physical.read_bytes())
if value["sha256"] != observed:
errors.append(_finding("PARENT_ASSET_HASH_MISMATCH", f"{location}/sha256", f"path={relative};observed={observed}"))
for key, item in value.items():
_walk_parent_refs(root, item, errors, f"{location}/{key}")
def _validate_parent_release(
root: Path,
release: dict[str, Any],
manifest_raw: bytes,
) -> tuple[list[dict[str, str]], list[dict[str, str]]]:
errors: list[dict[str, str]] = []
pending: list[dict[str, str]] = []
if release.get("schema_version") != PARENT_RELEASE_SCHEMA:
errors.append(_finding("PARENT_RELEASE_SCHEMA_VERSION", "$/schema_version", repr(release.get("schema_version"))))
if not _contains_contract(release.get("release_digest_contract"), EXPECTED_RELEASE_DIGEST_CONTRACT):
errors.append(_finding("PARENT_RELEASE_DIGEST_CONTRACT_INVALID", "$/release_digest_contract", repr(release.get("release_digest_contract"))))
declared = release.get("release_digest")
observed = _document_digest(release, "release_digest")
if declared != observed:
errors.append(_finding("PARENT_RELEASE_DIGEST_MISMATCH", "$/release_digest", f"declared={declared};observed={observed}"))
module_ref = release.get("module_manifest_ref")
if not isinstance(module_ref, dict) or module_ref.get("path") != "manifest/module_manifest.json":
errors.append(_finding("PARENT_MODULE_REF_INVALID", "$/module_manifest_ref", repr(module_ref)))
else:
expected_hash = _sha256(manifest_raw)
if module_ref.get("sha256") != expected_hash:
errors.append(_finding("PARENT_MODULE_REF_HASH_MISMATCH", "$/module_manifest_ref/sha256", f"expected={expected_hash};observed={module_ref.get('sha256')}"))
executor_ref = release.get("executor_binding_ref")
if (
not isinstance(executor_ref, dict)
or executor_ref.get("path") != "deployment/stage2_code_executor_binding.yml"
or executor_ref.get("schema_id") != "stage2_code_executor_binding.v3"
or "sha256" in executor_ref
or executor_ref.get("binding_status") == "BOUND"
):
errors.append(_finding("PARENT_EXECUTOR_TRUST_ROOT_REF_INVALID", "$/executor_binding_ref", repr(executor_ref)))
_walk_parent_refs(root, release, errors)
status = release.get("release_status")
authorization = release.get("authorization_status")
signature = release.get("signature")
if status == "ADMITTED":
if authorization not in {"CANARY_ADMITTED", "PRODUCTION_ADMITTED"}:
errors.append(_finding("ADMITTED_RELEASE_AUTHORIZATION_INVALID", "$/authorization_status", repr(authorization)))
if signature == "PENDING_SEQUENTIAL_BIND" or not isinstance(signature, str) or len(signature) < 32:
errors.append(_finding("ADMITTED_RELEASE_SIGNATURE_INVALID", "$/signature", repr(signature)))
else:
pending.append(_finding("PARENT_RELEASE_NOT_ADMITTED", "$/release_status", str(status)))
return errors, pending
def _nested_pending(value: Any) -> bool:
if isinstance(value, str):
return "PENDING" in value or value in {"UNVERIFIED", "NOT_IMPLEMENTED", "DEV_UNAVAILABLE"}
if isinstance(value, list):
return any(_nested_pending(item) for item in value)
if isinstance(value, dict):
return any(_nested_pending(item) for item in value.values())
return False
def _contains_ready_claim(value: Any) -> bool:
if isinstance(value, str):
return value in {"FULL_137_PRODUCTION_READY", "PRODUCTION_READY", "ADMITTED"}
if isinstance(value, list):
return any(_contains_ready_claim(item) for item in value)
if isinstance(value, dict):
return any(_contains_ready_claim(item) for item in value.values())
return False
def _validate_137_coverage(
root: Path,
case_registry: dict[str, Any],
rule_registry: dict[str, Any],
coverage: dict[str, Any],
) -> tuple[list[dict[str, str]], list[dict[str, str]], dict[str, int]]:
errors: list[dict[str, str]] = []
pending: list[dict[str, str]] = []
case_rows = case_registry.get("rows")
rule_rows = rule_registry.get("rows")
coverage_rows = coverage.get("coverage_rows")
if not isinstance(case_rows, list) or len(case_rows) != 137:
errors.append(_finding("CASE_TYPE_REGISTRY_EXACT_137_REQUIRED", "case_type_registry:/rows", f"observed={len(case_rows) if isinstance(case_rows, list) else 'invalid'}"))
case_rows = []
if not isinstance(rule_rows, list) or len(rule_rows) != 137:
errors.append(_finding("CASE_TYPE_RULE_REGISTRY_EXACT_137_REQUIRED", "case_type_rule_registry:/rows", f"observed={len(rule_rows) if isinstance(rule_rows, list) else 'invalid'}"))
rule_rows = []
if not isinstance(coverage_rows, list) or len(coverage_rows) != 137:
errors.append(_finding("CASE_TYPE_COVERAGE_EXACT_137_REQUIRED", "case_type_coverage:/coverage_rows", f"observed={len(coverage_rows) if isinstance(coverage_rows, list) else 'invalid'}"))
coverage_rows = []
observed_case_ids = tuple(row.get("case_type_id") for row in case_rows if isinstance(row, dict))
observed_catalog_ids = tuple(row.get("catalog_row_id") for row in case_rows if isinstance(row, dict))
declared_catalog_ids = tuple(case_registry.get("catalog_row_ids", ()))
observed_rule_ids = tuple(row.get("case_type_id") for row in rule_rows if isinstance(row, dict))
observed_coverage_ids = tuple(row.get("case_type_id") for row in coverage_rows if isinstance(row, dict))
for code, path, observed, expected in (
("CASE_TYPE_ID_ORDER_MISMATCH", "case_type_registry:/rows", observed_case_ids, EXPECTED_CASE_TYPE_IDS),
("CATALOG_ROW_ID_ORDER_MISMATCH", "case_type_registry:/rows", observed_catalog_ids, EXPECTED_CATALOG_ROW_IDS),
("DECLARED_CATALOG_ROW_ID_ORDER_MISMATCH", "case_type_registry:/catalog_row_ids", declared_catalog_ids, EXPECTED_CATALOG_ROW_IDS),
("RULE_CASE_TYPE_ID_ORDER_MISMATCH", "case_type_rule_registry:/rows", observed_rule_ids, EXPECTED_CASE_TYPE_IDS),
("COVERAGE_CASE_TYPE_ID_ORDER_MISMATCH", "case_type_coverage:/coverage_rows", observed_coverage_ids, EXPECTED_CASE_TYPE_IDS),
):
if observed != expected:
errors.append(_finding(code, path, "exact CT/CAT ordinal sequence required"))
case_path = _physical(root, "manifest/case_type_registry.yml")
if case_path is None:
errors.append(_finding("CASE_TYPE_REGISTRY_PHYSICAL_FILE_REQUIRED", "case_type_registry:$", "manifest/case_type_registry.yml"))
case_raw = _canonical_bytes(case_registry)
else:
case_raw = case_path.read_bytes()
case_ref = rule_registry.get("case_type_registry_ref")
case_hash = rule_registry.get("case_type_registry_sha256")
if case_ref != "manifest/case_type_registry.yml" or case_hash != _sha256(case_raw):
errors.append(_finding("RULE_REGISTRY_CASE_TYPE_REF_MISMATCH", "case_type_rule_registry:/case_type_registry_sha256", f"expected={_sha256(case_raw)};observed={case_hash}"))
coverage_dependency = coverage.get("registry_dependency")
if isinstance(coverage_dependency, dict):
declared = coverage_dependency.get("sha256")
if declared is not None and declared != _sha256(case_raw):
errors.append(_finding("COVERAGE_REGISTRY_HASH_MISMATCH", "case_type_coverage:/registry_dependency/sha256", f"expected={_sha256(case_raw)};observed={declared}"))
else:
errors.append(_finding("COVERAGE_REGISTRY_DEPENDENCY_REQUIRED", "case_type_coverage:/registry_dependency", "object required"))
rule_doc_count = 0
for case_type_id in EXPECTED_CASE_TYPE_IDS:
if _physical(root, f"rules/relief/{case_type_id}.md") is not None:
rule_doc_count += 1
pending_legal = (
rule_doc_count != 137
or _nested_pending(case_registry)
or _nested_pending(rule_registry)
or _nested_pending(coverage)
)
if pending_legal:
if coverage.get("release_eligible") is True or _contains_ready_claim(coverage):
errors.append(_finding("DISHONEST_FULL_137_READY_CLAIM", "case_type_coverage:$", f"rule_document_count={rule_doc_count};pending_contract=true"))
pending.append(_finding("FULL_137_LEGAL_COVERAGE_PENDING", "case_type_coverage:$", f"rule_document_count={rule_doc_count};legal registry/sign-off not fully admitted"))
return errors, pending, {
"case_type_count": len(case_rows),
"case_type_rule_row_count": len(rule_rows),
"coverage_row_count": len(coverage_rows),
"relief_rule_document_count": rule_doc_count,
}
def validate_package(
root: Path,
manifest_path: Path,
release_path: Path,
case_registry_path: Path,
rule_registry_path: Path,
coverage_path: Path,
) -> dict[str, Any]:
manifest = _load_json(manifest_path)
release = _load_json(release_path)
case_registry = _load_json(case_registry_path)
rule_registry = _load_json(rule_registry_path)
coverage = _load_json(coverage_path)
if not all(isinstance(row, dict) for row in (manifest, release, case_registry, rule_registry, coverage)):
raise ValidationInputError("ALL_RELEASE_INPUTS_MUST_BE_OBJECTS")
errors, pending, counts = _validate_module_manifest(root, manifest)
parent_errors, parent_pending = _validate_parent_release(root, release, manifest_path.read_bytes())
coverage_errors, coverage_pending, coverage_counts = _validate_137_coverage(root, case_registry, rule_registry, coverage)
errors.extend(parent_errors)
errors.extend(coverage_errors)
pending.extend(parent_pending)
pending.extend(coverage_pending)
if (
any(row["code"] == "FULL_137_LEGAL_COVERAGE_PENDING" for row in coverage_pending)
and (
release.get("release_class") == "PRODUCTION_RELEASE"
or (isinstance(release.get("bundle"), dict) and release["bundle"].get("mode") == "PRODUCTION")
)
):
errors.append(_finding("PRODUCTION_RELEASE_WITH_PENDING_137_COVERAGE", "stage2_release:$", "full-137 legal/corpus coverage is not admitted"))
counts.update(coverage_counts)
errors = sorted(errors, key=lambda row: (row["code"], row["path"], row["detail"]))
pending = sorted(pending, key=lambda row: (row["code"], row["path"], row["detail"]))
return {
"counts": dict(sorted(counts.items())),
"errors": errors,
"pending": pending,
"schema_version": "stage2_release_validation.v1",
"status": "PASS" if not errors else "FAIL",
}
def validate(root: Path, manifest: dict[str, object]) -> list[str]:
"""Compatibility wrapper for callers that only validate module rows."""
errors, _, _ = _validate_module_manifest(root, manifest)
return [f"{row['code']}:{row['path']}:{row['detail']}" for row in errors]
def main() -> int:
parser = argparse.ArgumentParser(description="Validate canonical Stage-2 raw release closure")
parser.add_argument("root", type=Path)
parser.add_argument("manifest", type=Path, nargs="?")
parser.add_argument("--release", type=Path)
parser.add_argument("--case-registry", type=Path)
parser.add_argument("--rule-registry", type=Path)
parser.add_argument("--coverage", type=Path)
args = parser.parse_args()
report = validate_package(
args.root,
args.manifest or args.root / "manifest/module_manifest.json",
args.release or args.root / "manifest/stage2_release.json",
args.case_registry or args.root / "manifest/case_type_registry.yml",
args.rule_registry or args.root / "manifest/case_type_rule_registry.yml",
args.coverage or args.root / "manifest/case_type_coverage.json",
)
print(json.dumps(report, ensure_ascii=False, sort_keys=True, separators=(",", ":")))
return 0 if report["status"] == "PASS" else 1
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,31 @@
{
"schema_version": "stage2.s2_20.renderer_descriptor.v1",
"renderer_id": "R01",
"renderer_kind": "MONEY_PAYMENT",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"stage2_20_role": "SELECT_AND_SEAL_ONLY",
"stage2_40_role": "CLOSED_RENDER",
"typed_slot_contract": {
"structural_slot_names": [
"amount",
"currency",
"obligor_ref",
"payment_event_ref"
],
"legal_branch_may_add_required_slots_only_after_review": true,
"missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING"
},
"branch_rows": [],
"closure": {
"exactly_one_approved_branch_required": true,
"free_text_template_fallback_forbidden": true,
"renderer_may_not_change_claim_or_facts": true,
"zero_match_issue_code": "RENDERER_BRANCH_ZERO_MATCH",
"multi_match_issue_code": "RENDERER_BRANCH_MULTI_MATCH"
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,30 @@
{
"schema_version": "stage2.s2_20.renderer_descriptor.v1",
"renderer_id": "R02",
"renderer_kind": "DELIVERY_POSSESSION",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"stage2_20_role": "SELECT_AND_SEAL_ONLY",
"stage2_40_role": "CLOSED_RENDER",
"typed_slot_contract": {
"structural_slot_names": [
"object_ref",
"obligor_ref",
"performance_mode"
],
"legal_branch_may_add_required_slots_only_after_review": true,
"missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING"
},
"branch_rows": [],
"closure": {
"exactly_one_approved_branch_required": true,
"free_text_template_fallback_forbidden": true,
"renderer_may_not_change_claim_or_facts": true,
"zero_match_issue_code": "RENDERER_BRANCH_ZERO_MATCH",
"multi_match_issue_code": "RENDERER_BRANCH_MULTI_MATCH"
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,30 @@
{
"schema_version": "stage2.s2_20.renderer_descriptor.v1",
"renderer_id": "R03",
"renderer_kind": "DECLARATION_REGISTRY",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"stage2_20_role": "SELECT_AND_SEAL_ONLY",
"stage2_40_role": "CLOSED_RENDER",
"typed_slot_contract": {
"structural_slot_names": [
"registry_object_ref",
"registry_action",
"obligor_ref"
],
"legal_branch_may_add_required_slots_only_after_review": true,
"missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING"
},
"branch_rows": [],
"closure": {
"exactly_one_approved_branch_required": true,
"free_text_template_fallback_forbidden": true,
"renderer_may_not_change_claim_or_facts": true,
"zero_match_issue_code": "RENDERER_BRANCH_ZERO_MATCH",
"multi_match_issue_code": "RENDERER_BRANCH_MULTI_MATCH"
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,30 @@
{
"schema_version": "stage2.s2_20.renderer_descriptor.v1",
"renderer_id": "R04",
"renderer_kind": "SPECIAL_NONMONEY_PERFORMANCE",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"stage2_20_role": "SELECT_AND_SEAL_ONLY",
"stage2_40_role": "CLOSED_RENDER",
"typed_slot_contract": {
"structural_slot_names": [
"performance_object_ref",
"performance_mode",
"obligor_ref"
],
"legal_branch_may_add_required_slots_only_after_review": true,
"missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING"
},
"branch_rows": [],
"closure": {
"exactly_one_approved_branch_required": true,
"free_text_template_fallback_forbidden": true,
"renderer_may_not_change_claim_or_facts": true,
"zero_match_issue_code": "RENDERER_BRANCH_ZERO_MATCH",
"multi_match_issue_code": "RENDERER_BRANCH_MULTI_MATCH"
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,30 @@
{
"schema_version": "stage2.s2_20.renderer_descriptor.v1",
"renderer_id": "R05",
"renderer_kind": "DECLARATORY",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"stage2_20_role": "SELECT_AND_SEAL_ONLY",
"stage2_40_role": "CLOSED_RENDER",
"typed_slot_contract": {
"structural_slot_names": [
"legal_relation_ref",
"declaration_scope",
"opposing_party_ref"
],
"legal_branch_may_add_required_slots_only_after_review": true,
"missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING"
},
"branch_rows": [],
"closure": {
"exactly_one_approved_branch_required": true,
"free_text_template_fallback_forbidden": true,
"renderer_may_not_change_claim_or_facts": true,
"zero_match_issue_code": "RENDERER_BRANCH_ZERO_MATCH",
"multi_match_issue_code": "RENDERER_BRANCH_MULTI_MATCH"
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,30 @@
{
"schema_version": "stage2.s2_20.renderer_descriptor.v1",
"renderer_id": "R06",
"renderer_kind": "CONSTITUTIVE_JUDGMENT_CHALLENGE",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"stage2_20_role": "SELECT_AND_SEAL_ONLY",
"stage2_40_role": "CLOSED_RENDER",
"typed_slot_contract": {
"structural_slot_names": [
"legal_effect_ref",
"constitutive_method",
"opposing_party_ref"
],
"legal_branch_may_add_required_slots_only_after_review": true,
"missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING"
},
"branch_rows": [],
"closure": {
"exactly_one_approved_branch_required": true,
"free_text_template_fallback_forbidden": true,
"renderer_may_not_change_claim_or_facts": true,
"zero_match_issue_code": "RENDERER_BRANCH_ZERO_MATCH",
"multi_match_issue_code": "RENDERER_BRANCH_MULTI_MATCH"
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,23 @@
{
"schema_version": "stage2.s2_20.actio_pauliana_mortgage_route.v1",
"registry_id": "S2-20-ACTIO-MORTGAGE-ROUTES",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"route_rows": [],
"required_distinctions": [
"ENCUMBERED_TRANSFER",
"FRAUDULENT_MORTGAGE_CREATION",
"MORTGAGE_CANCELLATION",
"DISTRIBUTION_OR_DIVIDEND_EFFECT"
],
"closure": {
"distinction_must_be_authority_backed": true,
"zero_match_issue_code": "ACTIO_MORTGAGE_ROUTE_ZERO_MATCH",
"multi_match_issue_code": "ACTIO_MORTGAGE_ROUTE_MULTI_MATCH",
"value_compensation_guess_forbidden": true
},
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,32 @@
{
"schema_version": "stage2.s2_20.actio_pauliana_route_registry.v1",
"registry_id": "S2-20-ACTIO-PAULIANA-ROUTES",
"status": "PENDING_LEGAL_CONTENT",
"execution_eligible": false,
"required_approved_route_count": 6,
"route_rows": [],
"route_contract": {
"required_fields": [
"route_id",
"predicate_id",
"required_operands",
"defendant_role",
"restoration_recipient_role",
"renderer_id",
"calculation_branch_id",
"authority_refs",
"review_status"
]
},
"closure": {
"exactly_one_approved_route_required": true,
"zero_match_issue_code": "ACTIO_ROUTE_ZERO_MATCH",
"multi_match_issue_code": "ACTIO_ROUTE_MULTI_MATCH",
"generic_actio_fallback_forbidden": true
},
"migration_sources_are_runtime_inputs": false,
"review": {
"required_role": "KOREAN_LAWYER",
"status": "PENDING_KOREAN_LAWYER_REVIEW"
}
}
@@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""Offline authority/law-value release integrity oracle."""
from __future__ import annotations
from datetime import date
import hashlib
from pathlib import Path
from typing import Any, Mapping, Sequence
class AuthorityPreflightError(ValueError):
pass
def verify_authority_rows(
root: Path,
authority_rows: Sequence[Mapping[str, Any]],
as_of: date,
) -> dict[str, Any]:
verified: list[str] = []
pending: list[dict[str, str]] = []
for row in sorted(authority_rows, key=lambda item: str(item.get("authority_id"))):
authority_id = row.get("authority_id")
path = row.get("capture_path")
expected_hash = row.get("capture_sha256")
if not all(isinstance(value, str) and value for value in (authority_id, path, expected_hash)):
raise AuthorityPreflightError("AUTHORITY_ROW_INCOMPLETE")
target = (root / str(path)).resolve()
if root.resolve() not in target.parents or not target.is_file():
pending.append({"authority_id": str(authority_id), "reason": "CAPTURE_UNAVAILABLE"})
continue
if hashlib.sha256(target.read_bytes()).hexdigest() != expected_hash:
pending.append({"authority_id": str(authority_id), "reason": "CAPTURE_HASH_MISMATCH"})
continue
effective_from = date.fromisoformat(str(row["effective_from"]))
effective_to_raw = row.get("effective_to")
effective_to = date.fromisoformat(str(effective_to_raw)) if effective_to_raw else None
if as_of < effective_from or (effective_to is not None and as_of > effective_to):
pending.append({"authority_id": str(authority_id), "reason": "OUTSIDE_EFFECTIVE_INTERVAL"})
continue
if row.get("approval_status") != "APPROVED":
pending.append({"authority_id": str(authority_id), "reason": "LEGAL_APPROVAL_PENDING"})
continue
verified.append(str(authority_id))
return {
"status": "PASS" if not pending else "PENDING",
"verified_authority_ids": verified,
"pending_rows": pending,
}
@@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""Offline authority/law-value release integrity oracle."""
from __future__ import annotations
from datetime import date
import hashlib
from pathlib import Path
from typing import Any, Mapping, Sequence
class AuthorityPreflightError(ValueError):
pass
def verify_authority_rows(
root: Path,
authority_rows: Sequence[Mapping[str, Any]],
as_of: date,
) -> dict[str, Any]:
verified: list[str] = []
pending: list[dict[str, str]] = []
for row in sorted(authority_rows, key=lambda item: str(item.get("authority_id"))):
authority_id = row.get("authority_id")
path = row.get("capture_path")
expected_hash = row.get("capture_sha256")
if not all(isinstance(value, str) and value for value in (authority_id, path, expected_hash)):
raise AuthorityPreflightError("AUTHORITY_ROW_INCOMPLETE")
target = (root / str(path)).resolve()
if root.resolve() not in target.parents or not target.is_file():
pending.append({"authority_id": str(authority_id), "reason": "CAPTURE_UNAVAILABLE"})
continue
if hashlib.sha256(target.read_bytes()).hexdigest() != expected_hash:
pending.append({"authority_id": str(authority_id), "reason": "CAPTURE_HASH_MISMATCH"})
continue
effective_from = date.fromisoformat(str(row["effective_from"]))
effective_to_raw = row.get("effective_to")
effective_to = date.fromisoformat(str(effective_to_raw)) if effective_to_raw else None
if as_of < effective_from or (effective_to is not None and as_of > effective_to):
pending.append({"authority_id": str(authority_id), "reason": "OUTSIDE_EFFECTIVE_INTERVAL"})
continue
if row.get("approval_status") != "APPROVED":
pending.append({"authority_id": str(authority_id), "reason": "LEGAL_APPROVAL_PENDING"})
continue
verified.append(str(authority_id))
return {
"status": "PASS" if not pending else "PENDING",
"verified_authority_ids": verified,
"pending_rows": pending,
}
@@ -0,0 +1,157 @@
#!/usr/bin/env python3
"""Deterministic S2_10 -> C25 signature projection pure core.
The module is an offline oracle. Runtime delivery copies these functions into
the single S2_20 YAML ``run_code`` body; a case run must not import this file.
"""
from __future__ import annotations
import hashlib
import json
from typing import Any, Mapping, Sequence
SOURCE_FIELDS = frozenset(
{
"vocabulary_version",
"legal_basis_family",
"right_holder_refs",
"obligor_refs",
"performance_kind",
"object_refs",
"legal_effect",
"source_occurrence_refs",
}
)
TARGET_FIELDS = (
"claim_family",
"legal_effect",
"performance_kind",
"object_kind",
"party_role_pattern",
"source_obligation_kind",
"remedy_mode",
"registry_action",
"procedural_posture",
"special_statute_tags",
)
ALLOWED_SOURCE_ROOTS = frozenset({"signature", "c20", "c21", "remedy"})
class ProjectionError(ValueError):
"""Closed projection contract violation."""
def canonical_json_bytes(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False)
+ "\n"
).encode("utf-8")
def _dig(root: Mapping[str, Any], path: str) -> Any:
parts = path.split(".")
if not parts or parts[0] not in ALLOWED_SOURCE_ROOTS:
raise ProjectionError(f"SOURCE_PATH_NOT_ALLOWED:{path}")
current: Any = root
for part in parts:
if not isinstance(current, Mapping) or part not in current:
return None
current = current[part]
return current
def _stable_values(value: Any) -> list[str]:
if value is None:
return []
raw = value if isinstance(value, list) else [value]
if not all(isinstance(item, str) and item for item in raw):
raise ProjectionError("NON_TOKEN_SOURCE_VALUE")
return sorted(set(raw))
def project_signature(
source_signature: Mapping[str, Any],
c20_projection: Mapping[str, Any],
c21_projection: Mapping[str, Any],
remedy_context: Mapping[str, Any],
projection_registry: Mapping[str, Any],
) -> dict[str, Any]:
"""Apply release-bound mappings; never infer from labels or free text."""
unknown_source = sorted(set(source_signature) - SOURCE_FIELDS)
if unknown_source:
raise ProjectionError(f"UNEXPECTED_S2_10_SIGNATURE_FIELDS:{unknown_source}")
missing_source = sorted(SOURCE_FIELDS - set(source_signature))
if missing_source:
raise ProjectionError(f"MISSING_S2_10_SIGNATURE_FIELDS:{missing_source}")
if source_signature.get("vocabulary_version") != "stage2.claim_signature_vocab.v1":
raise ProjectionError("UNSUPPORTED_SOURCE_VOCABULARY")
rules = projection_registry.get("projection_rules")
if not isinstance(rules, list):
raise ProjectionError("PROJECTION_RULES_REQUIRED")
if projection_registry.get("registry_status") != "APPROVED":
rules = []
by_target: dict[str, Mapping[str, Any]] = {}
for rule in rules:
if not isinstance(rule, Mapping):
raise ProjectionError("PROJECTION_ROW_NOT_OBJECT")
target = rule.get("target_field")
if target not in TARGET_FIELDS or target in by_target:
raise ProjectionError(f"TARGET_FIELD_INVALID_OR_DUPLICATE:{target}")
by_target[str(target)] = rule
if rules and set(by_target) != set(TARGET_FIELDS):
raise ProjectionError("TARGET_FIELD_COVERAGE_MISMATCH")
source_values: Mapping[str, Any] = {
**source_signature,
"c20_remedy_projection": remedy_context.get("remedy_mode"),
"c20_dependency_projection": c20_projection.get("dependency_kind"),
"c21_party_projection": c21_projection.get("party_role_pattern"),
"c21_object_projection": c21_projection.get("object_kind"),
}
target: dict[str, Any] = {}
provenance: list[dict[str, Any]] = []
for field in TARGET_FIELDS:
rule = by_target.get(field)
if rule is None:
value = [] if field == "special_statute_tags" else "UNKNOWN"
paths: list[str] = []
distinct: list[str] = []
else:
paths = rule.get("source_fields")
allowed = rule.get("allowed_output_values")
operator = rule.get("derivation_operator")
if not isinstance(paths, list) or not paths or not isinstance(allowed, list):
raise ProjectionError(f"INVALID_PROJECTION_RULE:{field}")
candidates = [token for path in paths for token in _stable_values(source_values.get(path))]
distinct = sorted({token for token in candidates if token in allowed})
if operator in {"DIRECT_COPY", "CLOSED_LOOKUP"}:
value = distinct[0] if len(distinct) == 1 else "UNKNOWN"
elif operator in {"SET_INTERSECTION", "SET_UNION"} and field == "special_statute_tags":
value = distinct
else:
value = [] if field == "special_statute_tags" else "UNKNOWN"
target[field] = value
provenance.append(
{
"target_field": field,
"value": value,
"source_paths": sorted(paths),
"status": "DERIVED" if value not in ("UNKNOWN", []) else "UNKNOWN",
}
)
payload = {
"schema_version": "stage2.binding_target_signature.v1",
"source_vocabulary_version": source_signature["vocabulary_version"],
"target_vocabulary_version": projection_registry.get(
"target_vocabulary_version", "stage2.case_type_signature_vocab.v1"
),
"signature": target,
"provenance": provenance,
}
payload["signature_sha256"] = hashlib.sha256(canonical_json_bytes(target)).hexdigest()
return payload
@@ -0,0 +1,157 @@
#!/usr/bin/env python3
"""Deterministic S2_10 -> C25 signature projection pure core.
The module is an offline oracle. Runtime delivery copies these functions into
the single S2_20 YAML ``run_code`` body; a case run must not import this file.
"""
from __future__ import annotations
import hashlib
import json
from typing import Any, Mapping, Sequence
SOURCE_FIELDS = frozenset(
{
"vocabulary_version",
"legal_basis_family",
"right_holder_refs",
"obligor_refs",
"performance_kind",
"object_refs",
"legal_effect",
"source_occurrence_refs",
}
)
TARGET_FIELDS = (
"claim_family",
"legal_effect",
"performance_kind",
"object_kind",
"party_role_pattern",
"source_obligation_kind",
"remedy_mode",
"registry_action",
"procedural_posture",
"special_statute_tags",
)
ALLOWED_SOURCE_ROOTS = frozenset({"signature", "c20", "c21", "remedy"})
class ProjectionError(ValueError):
"""Closed projection contract violation."""
def canonical_json_bytes(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False)
+ "\n"
).encode("utf-8")
def _dig(root: Mapping[str, Any], path: str) -> Any:
parts = path.split(".")
if not parts or parts[0] not in ALLOWED_SOURCE_ROOTS:
raise ProjectionError(f"SOURCE_PATH_NOT_ALLOWED:{path}")
current: Any = root
for part in parts:
if not isinstance(current, Mapping) or part not in current:
return None
current = current[part]
return current
def _stable_values(value: Any) -> list[str]:
if value is None:
return []
raw = value if isinstance(value, list) else [value]
if not all(isinstance(item, str) and item for item in raw):
raise ProjectionError("NON_TOKEN_SOURCE_VALUE")
return sorted(set(raw))
def project_signature(
source_signature: Mapping[str, Any],
c20_projection: Mapping[str, Any],
c21_projection: Mapping[str, Any],
remedy_context: Mapping[str, Any],
projection_registry: Mapping[str, Any],
) -> dict[str, Any]:
"""Apply release-bound mappings; never infer from labels or free text."""
unknown_source = sorted(set(source_signature) - SOURCE_FIELDS)
if unknown_source:
raise ProjectionError(f"UNEXPECTED_S2_10_SIGNATURE_FIELDS:{unknown_source}")
missing_source = sorted(SOURCE_FIELDS - set(source_signature))
if missing_source:
raise ProjectionError(f"MISSING_S2_10_SIGNATURE_FIELDS:{missing_source}")
if source_signature.get("vocabulary_version") != "stage2.claim_signature_vocab.v1":
raise ProjectionError("UNSUPPORTED_SOURCE_VOCABULARY")
rules = projection_registry.get("projection_rules")
if not isinstance(rules, list):
raise ProjectionError("PROJECTION_RULES_REQUIRED")
if projection_registry.get("registry_status") != "APPROVED":
rules = []
by_target: dict[str, Mapping[str, Any]] = {}
for rule in rules:
if not isinstance(rule, Mapping):
raise ProjectionError("PROJECTION_ROW_NOT_OBJECT")
target = rule.get("target_field")
if target not in TARGET_FIELDS or target in by_target:
raise ProjectionError(f"TARGET_FIELD_INVALID_OR_DUPLICATE:{target}")
by_target[str(target)] = rule
if rules and set(by_target) != set(TARGET_FIELDS):
raise ProjectionError("TARGET_FIELD_COVERAGE_MISMATCH")
source_values: Mapping[str, Any] = {
**source_signature,
"c20_remedy_projection": remedy_context.get("remedy_mode"),
"c20_dependency_projection": c20_projection.get("dependency_kind"),
"c21_party_projection": c21_projection.get("party_role_pattern"),
"c21_object_projection": c21_projection.get("object_kind"),
}
target: dict[str, Any] = {}
provenance: list[dict[str, Any]] = []
for field in TARGET_FIELDS:
rule = by_target.get(field)
if rule is None:
value = [] if field == "special_statute_tags" else "UNKNOWN"
paths: list[str] = []
distinct: list[str] = []
else:
paths = rule.get("source_fields")
allowed = rule.get("allowed_output_values")
operator = rule.get("derivation_operator")
if not isinstance(paths, list) or not paths or not isinstance(allowed, list):
raise ProjectionError(f"INVALID_PROJECTION_RULE:{field}")
candidates = [token for path in paths for token in _stable_values(source_values.get(path))]
distinct = sorted({token for token in candidates if token in allowed})
if operator in {"DIRECT_COPY", "CLOSED_LOOKUP"}:
value = distinct[0] if len(distinct) == 1 else "UNKNOWN"
elif operator in {"SET_INTERSECTION", "SET_UNION"} and field == "special_statute_tags":
value = distinct
else:
value = [] if field == "special_statute_tags" else "UNKNOWN"
target[field] = value
provenance.append(
{
"target_field": field,
"value": value,
"source_paths": sorted(paths),
"status": "DERIVED" if value not in ("UNKNOWN", []) else "UNKNOWN",
}
)
payload = {
"schema_version": "stage2.binding_target_signature.v1",
"source_vocabulary_version": source_signature["vocabulary_version"],
"target_vocabulary_version": projection_registry.get(
"target_vocabulary_version", "stage2.case_type_signature_vocab.v1"
),
"signature": target,
"provenance": provenance,
}
payload["signature_sha256"] = hashlib.sha256(canonical_json_bytes(target)).hexdigest()
return payload
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""Closed-predicate C25 case-type binding pure core."""
from __future__ import annotations
from typing import Any, Mapping, Sequence
ALLOWED_OPERATORS = frozenset({"EQ", "IN", "ALL_OF", "NONE_OF", "EXISTS"})
ELIGIBLE_ROW_KINDS = frozenset({"CLAIM", "GENERIC"})
class BindingError(ValueError):
pass
def evaluate_predicate(signature: Mapping[str, Any], clauses: Sequence[Mapping[str, Any]]) -> bool:
for clause in clauses:
field = clause.get("field")
operator = clause.get("operator")
expected = clause.get("value")
if not isinstance(field, str) or operator not in ALLOWED_OPERATORS:
raise BindingError("INVALID_PREDICATE_CLAUSE")
actual = signature.get(field, "UNKNOWN")
if operator == "EQ":
passed = actual == expected
elif operator == "IN":
passed = isinstance(expected, list) and actual in expected
elif operator == "ALL_OF":
passed = isinstance(actual, list) and isinstance(expected, list) and set(expected) <= set(actual)
elif operator == "NONE_OF":
passed = isinstance(actual, list) and isinstance(expected, list) and set(expected).isdisjoint(actual)
else:
passed = (actual not in (None, "UNKNOWN", [])) is bool(expected)
if not passed:
return False
return True
def bind_case_type(signature: Mapping[str, Any], registry_rows: Sequence[Mapping[str, Any]]) -> dict[str, Any]:
matches: list[dict[str, str]] = []
seen_ids: set[str] = set()
for row in registry_rows:
case_type_id = row.get("case_type_id")
if not isinstance(case_type_id, str):
raise BindingError("REGISTRY_ID_REQUIRED")
if case_type_id in seen_ids:
raise BindingError("DUPLICATE_CASE_TYPE_ID")
seen_ids.add(case_type_id)
row_kind = row.get("row_kind")
if row_kind not in ELIGIBLE_ROW_KINDS:
continue
if (
row.get("claim_capable_disposition") != "CLAIM_CAPABLE"
or row.get("legal_classification_status") != "APPROVED"
or row.get("legal_content_status") != "APPROVED"
):
continue
predicates = row.get("case_type_predicates")
if not isinstance(predicates, list) or len(predicates) != 1:
continue
predicate = predicates[0]
if (
not isinstance(predicate, Mapping)
or predicate.get("legal_review_status") != "APPROVED"
or not isinstance(predicate.get("predicate_id"), str)
or not isinstance(predicate.get("clauses"), list)
):
continue
predicate_id = str(predicate["predicate_id"])
if evaluate_predicate(signature, predicate["clauses"]):
matches.append({"case_type_id": case_type_id, "matched_case_type_predicate_id": predicate_id})
matches.sort(key=lambda item: (item["case_type_id"], item["matched_case_type_predicate_id"]))
if len(matches) == 1:
return {"binding_status": "BOUND", **matches[0], "binding_issue_codes": []}
return {
"binding_status": "UNRESOLVED" if not matches else "CONFLICT",
"matched_case_type_id": None,
"matched_case_type_predicate_id": None,
"candidate_matches": matches,
"binding_issue_codes": [
"CASE_TYPE_BINDING_ZERO_MATCH" if not matches else "CASE_TYPE_BINDING_MULTI_MATCH"
],
}
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""Closed-predicate C25 case-type binding pure core."""
from __future__ import annotations
from typing import Any, Mapping, Sequence
ALLOWED_OPERATORS = frozenset({"EQ", "IN", "ALL_OF", "NONE_OF", "EXISTS"})
ELIGIBLE_ROW_KINDS = frozenset({"CLAIM", "GENERIC"})
class BindingError(ValueError):
pass
def evaluate_predicate(signature: Mapping[str, Any], clauses: Sequence[Mapping[str, Any]]) -> bool:
for clause in clauses:
field = clause.get("field")
operator = clause.get("operator")
expected = clause.get("value")
if not isinstance(field, str) or operator not in ALLOWED_OPERATORS:
raise BindingError("INVALID_PREDICATE_CLAUSE")
actual = signature.get(field, "UNKNOWN")
if operator == "EQ":
passed = actual == expected
elif operator == "IN":
passed = isinstance(expected, list) and actual in expected
elif operator == "ALL_OF":
passed = isinstance(actual, list) and isinstance(expected, list) and set(expected) <= set(actual)
elif operator == "NONE_OF":
passed = isinstance(actual, list) and isinstance(expected, list) and set(expected).isdisjoint(actual)
else:
passed = (actual not in (None, "UNKNOWN", [])) is bool(expected)
if not passed:
return False
return True
def bind_case_type(signature: Mapping[str, Any], registry_rows: Sequence[Mapping[str, Any]]) -> dict[str, Any]:
matches: list[dict[str, str]] = []
seen_ids: set[str] = set()
for row in registry_rows:
case_type_id = row.get("case_type_id")
if not isinstance(case_type_id, str):
raise BindingError("REGISTRY_ID_REQUIRED")
if case_type_id in seen_ids:
raise BindingError("DUPLICATE_CASE_TYPE_ID")
seen_ids.add(case_type_id)
row_kind = row.get("row_kind")
if row_kind not in ELIGIBLE_ROW_KINDS:
continue
if (
row.get("claim_capable_disposition") != "CLAIM_CAPABLE"
or row.get("legal_classification_status") != "APPROVED"
or row.get("legal_content_status") != "APPROVED"
):
continue
predicates = row.get("case_type_predicates")
if not isinstance(predicates, list) or len(predicates) != 1:
continue
predicate = predicates[0]
if (
not isinstance(predicate, Mapping)
or predicate.get("legal_review_status") != "APPROVED"
or not isinstance(predicate.get("predicate_id"), str)
or not isinstance(predicate.get("clauses"), list)
):
continue
predicate_id = str(predicate["predicate_id"])
if evaluate_predicate(signature, predicate["clauses"]):
matches.append({"case_type_id": case_type_id, "matched_case_type_predicate_id": predicate_id})
matches.sort(key=lambda item: (item["case_type_id"], item["matched_case_type_predicate_id"]))
if len(matches) == 1:
return {"binding_status": "BOUND", **matches[0], "binding_issue_codes": []}
return {
"binding_status": "UNRESOLVED" if not matches else "CONFLICT",
"matched_case_type_id": None,
"matched_case_type_predicate_id": None,
"candidate_matches": matches,
"binding_issue_codes": [
"CASE_TYPE_BINDING_ZERO_MATCH" if not matches else "CASE_TYPE_BINDING_MULTI_MATCH"
],
}
@@ -0,0 +1,123 @@
#!/usr/bin/env python3
"""C26 exact sub-rule/renderer/party/corpus binding pure core."""
from __future__ import annotations
from typing import Any, Mapping, Sequence
class RuleBindingError(ValueError):
pass
def _evaluate(signature: Mapping[str, Any], clauses: Sequence[Mapping[str, Any]]) -> bool:
allowed = {"EQ", "IN", "ALL_OF", "NONE_OF", "EXISTS"}
for clause in clauses:
field = clause.get("field")
op = clause.get("operator")
expected = clause.get("value")
if not isinstance(field, str) or op not in allowed:
raise RuleBindingError("INVALID_SUB_RULE_PREDICATE")
actual = signature.get(field, "UNKNOWN")
if op == "EQ":
ok = actual == expected
elif op == "IN":
ok = isinstance(expected, list) and actual in expected
elif op == "ALL_OF":
ok = isinstance(actual, list) and isinstance(expected, list) and set(expected) <= set(actual)
elif op == "NONE_OF":
ok = isinstance(actual, list) and isinstance(expected, list) and set(expected).isdisjoint(actual)
else:
ok = (actual not in (None, "UNKNOWN", [])) is bool(expected)
if not ok:
return False
return True
def bind_rule_branch(
signature: Mapping[str, Any],
case_binding: Mapping[str, Any],
rule_rows: Sequence[Mapping[str, Any]],
asset_hashes: Mapping[str, str],
) -> dict[str, Any]:
if case_binding.get("binding_status") != "BOUND":
return {
"binding_status": "UNRESOLVED",
"binding_issue_codes": ["QUERY_NOT_RUN_UNRESOLVED_BINDING"],
}
case_type_id = case_binding.get("case_type_id") or case_binding.get("matched_case_type_id")
candidates: list[Mapping[str, Any]] = []
for row in rule_rows:
if row.get("case_type_id") != case_type_id:
continue
if (
row.get("claim_capable_disposition") != "CLAIM_CAPABLE"
or row.get("legal_classification_status") != "APPROVED"
or row.get("legal_content_status") != "APPROVED"
):
continue
branches = row.get("rule_branches")
if not isinstance(branches, list):
raise RuleBindingError("RULE_BRANCHES_ARRAY_REQUIRED")
for branch in branches:
if not isinstance(branch, Mapping) or branch.get("legal_content_status") != "APPROVED":
continue
predicates = branch.get("sub_rule_predicates")
if not isinstance(predicates, list) or len(predicates) != 1:
continue
predicate = predicates[0]
if (
isinstance(predicate, Mapping)
and predicate.get("legal_review_status") == "APPROVED"
and isinstance(predicate.get("clauses"), list)
and _evaluate(signature, predicate["clauses"])
):
candidates.append(branch)
candidates.sort(key=lambda row: str(row.get("sub_rule_id")))
if len(candidates) != 1:
return {
"binding_status": "UNRESOLVED" if not candidates else "CONFLICT",
"binding_issue_codes": [
"SUB_RULE_BINDING_ZERO_MATCH" if not candidates else "SUB_RULE_BINDING_MULTI_MATCH"
],
"candidate_sub_rule_ids": [row.get("sub_rule_id") for row in candidates],
}
row = candidates[0]
required_fields = (
"sub_rule_id", "rule_branch_key", "markdown_source_path",
"markdown_source_sha256", "renderer_ids", "corpus_scope_id",
"element_set_id", "party_set_rule_id", "ce13_branch_id",
)
missing = [name for name in required_fields if row.get(name) in (None, "", [])]
markdown_path = row.get("markdown_source_path")
markdown_hash = row.get("markdown_source_sha256")
hash_mismatch = (
isinstance(markdown_path, str)
and markdown_path in asset_hashes
and asset_hashes[markdown_path] != markdown_hash
)
if missing or hash_mismatch:
return {
"binding_status": "CONFLICT",
"binding_issue_codes": sorted(
({"RULE_BRANCH_MISSING"} if missing else set())
| ({"RULE_HASH_MISMATCH"} if hash_mismatch else set())
),
"missing_refs": sorted(missing),
"hash_mismatches": ["markdown_source_sha256"] if hash_mismatch else [],
}
sub_rule_id = row.get("sub_rule_id")
predicates = row.get("sub_rule_predicates", [])
return {
"binding_status": "BOUND",
"case_type_id": case_type_id,
"sub_rule_id": sub_rule_id,
"rule_branch_key": row.get("rule_branch_key"),
"matched_sub_rule_predicate_id": predicates[0].get("predicate_id"),
"renderer_ids": list(row.get("renderer_ids", [])),
"party_set_rule_id": row.get("party_set_rule_id"),
"corpus_scope_id": row.get("corpus_scope_id"),
"element_set_id": row.get("element_set_id"),
"ce13_branch_id": row.get("ce13_branch_id"),
"binding_issue_codes": [],
}
@@ -0,0 +1,123 @@
#!/usr/bin/env python3
"""C26 exact sub-rule/renderer/party/corpus binding pure core."""
from __future__ import annotations
from typing import Any, Mapping, Sequence
class RuleBindingError(ValueError):
pass
def _evaluate(signature: Mapping[str, Any], clauses: Sequence[Mapping[str, Any]]) -> bool:
allowed = {"EQ", "IN", "ALL_OF", "NONE_OF", "EXISTS"}
for clause in clauses:
field = clause.get("field")
op = clause.get("operator")
expected = clause.get("value")
if not isinstance(field, str) or op not in allowed:
raise RuleBindingError("INVALID_SUB_RULE_PREDICATE")
actual = signature.get(field, "UNKNOWN")
if op == "EQ":
ok = actual == expected
elif op == "IN":
ok = isinstance(expected, list) and actual in expected
elif op == "ALL_OF":
ok = isinstance(actual, list) and isinstance(expected, list) and set(expected) <= set(actual)
elif op == "NONE_OF":
ok = isinstance(actual, list) and isinstance(expected, list) and set(expected).isdisjoint(actual)
else:
ok = (actual not in (None, "UNKNOWN", [])) is bool(expected)
if not ok:
return False
return True
def bind_rule_branch(
signature: Mapping[str, Any],
case_binding: Mapping[str, Any],
rule_rows: Sequence[Mapping[str, Any]],
asset_hashes: Mapping[str, str],
) -> dict[str, Any]:
if case_binding.get("binding_status") != "BOUND":
return {
"binding_status": "UNRESOLVED",
"binding_issue_codes": ["QUERY_NOT_RUN_UNRESOLVED_BINDING"],
}
case_type_id = case_binding.get("case_type_id") or case_binding.get("matched_case_type_id")
candidates: list[Mapping[str, Any]] = []
for row in rule_rows:
if row.get("case_type_id") != case_type_id:
continue
if (
row.get("claim_capable_disposition") != "CLAIM_CAPABLE"
or row.get("legal_classification_status") != "APPROVED"
or row.get("legal_content_status") != "APPROVED"
):
continue
branches = row.get("rule_branches")
if not isinstance(branches, list):
raise RuleBindingError("RULE_BRANCHES_ARRAY_REQUIRED")
for branch in branches:
if not isinstance(branch, Mapping) or branch.get("legal_content_status") != "APPROVED":
continue
predicates = branch.get("sub_rule_predicates")
if not isinstance(predicates, list) or len(predicates) != 1:
continue
predicate = predicates[0]
if (
isinstance(predicate, Mapping)
and predicate.get("legal_review_status") == "APPROVED"
and isinstance(predicate.get("clauses"), list)
and _evaluate(signature, predicate["clauses"])
):
candidates.append(branch)
candidates.sort(key=lambda row: str(row.get("sub_rule_id")))
if len(candidates) != 1:
return {
"binding_status": "UNRESOLVED" if not candidates else "CONFLICT",
"binding_issue_codes": [
"SUB_RULE_BINDING_ZERO_MATCH" if not candidates else "SUB_RULE_BINDING_MULTI_MATCH"
],
"candidate_sub_rule_ids": [row.get("sub_rule_id") for row in candidates],
}
row = candidates[0]
required_fields = (
"sub_rule_id", "rule_branch_key", "markdown_source_path",
"markdown_source_sha256", "renderer_ids", "corpus_scope_id",
"element_set_id", "party_set_rule_id", "ce13_branch_id",
)
missing = [name for name in required_fields if row.get(name) in (None, "", [])]
markdown_path = row.get("markdown_source_path")
markdown_hash = row.get("markdown_source_sha256")
hash_mismatch = (
isinstance(markdown_path, str)
and markdown_path in asset_hashes
and asset_hashes[markdown_path] != markdown_hash
)
if missing or hash_mismatch:
return {
"binding_status": "CONFLICT",
"binding_issue_codes": sorted(
({"RULE_BRANCH_MISSING"} if missing else set())
| ({"RULE_HASH_MISMATCH"} if hash_mismatch else set())
),
"missing_refs": sorted(missing),
"hash_mismatches": ["markdown_source_sha256"] if hash_mismatch else [],
}
sub_rule_id = row.get("sub_rule_id")
predicates = row.get("sub_rule_predicates", [])
return {
"binding_status": "BOUND",
"case_type_id": case_type_id,
"sub_rule_id": sub_rule_id,
"rule_branch_key": row.get("rule_branch_key"),
"matched_sub_rule_predicate_id": predicates[0].get("predicate_id"),
"renderer_ids": list(row.get("renderer_ids", [])),
"party_set_rule_id": row.get("party_set_rule_id"),
"corpus_scope_id": row.get("corpus_scope_id"),
"element_set_id": row.get("element_set_id"),
"ce13_branch_id": row.get("ce13_branch_id"),
"binding_issue_codes": [],
}
@@ -0,0 +1,166 @@
#!/usr/bin/env python3
"""Build schema-conformant, release-bound C27 requirement-fact query plans."""
from __future__ import annotations
import hashlib
import json
from typing import Any, Mapping, Sequence
ROLES = ("element", "defense", "rebuttal", "burden", "relief_consistency")
SHA256_KEYS = (
"embedding_configuration_digest",
"reranker_configuration_digest",
"index_configuration_digest",
)
class QueryPlanError(ValueError):
"""Controlled C27 contract failure."""
def _digest(value: Any) -> str:
raw = (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
return hashlib.sha256(raw).hexdigest()
def _nonempty(value: Any, code: str) -> str:
if not isinstance(value, str) or not value:
raise QueryPlanError(code)
return value
def _sha256(value: Any, code: str) -> str:
text = _nonempty(value, code)
if len(text) != 64 or any(character not in "0123456789abcdef" for character in text):
raise QueryPlanError(code)
return text
def _bound(binding: Mapping[str, Any]) -> bool:
return (
binding.get("case_type_binding_status") == "BOUND"
and binding.get("sub_rule_binding_status") == "BOUND"
and binding.get("legal_content_status") == "APPROVED"
)
def build_query_plan(
atomic_claim_id: str,
binding: Mapping[str, Any],
scope: Mapping[str, Any],
role_element_ids: Mapping[str, Sequence[str]],
*,
run_binding_digest: str,
effective_on: str,
) -> dict[str, Any]:
"""Return the exact ``query_plan`` contract from binding_retrieval.schema.
An unresolved binding produces a valid empty plan. It never manufactures a
case type or rule ID merely to populate a query row.
"""
atomic_claim_id = _nonempty(atomic_claim_id, "ATOMIC_CLAIM_ID_REQUIRED")
run_binding_digest = _sha256(run_binding_digest, "RUN_BINDING_DIGEST_INVALID")
if not _bound(binding):
core = {
"schema_version": "stage2_requirement_fact_query_plan.v1",
"run_binding_digest": run_binding_digest,
"atomic_claim_id": atomic_claim_id,
"rows": [],
}
return {**core, "query_plan_sha256": _digest(core)}
case_type_id = _nonempty(binding.get("case_type_id"), "CASE_TYPE_ID_REQUIRED")
sub_rule_id = _nonempty(binding.get("sub_rule_id"), "SUB_RULE_ID_REQUIRED")
rule_branch_key = _nonempty(binding.get("rule_branch_key"), "RULE_BRANCH_KEY_REQUIRED")
corpus_scope_id = _nonempty(binding.get("corpus_scope_id"), "CORPUS_SCOPE_ID_REQUIRED")
element_set_id = _nonempty(binding.get("element_set_id"), "ELEMENT_SET_ID_REQUIRED")
if rule_branch_key != f"{case_type_id}::{sub_rule_id}":
raise QueryPlanError("RULE_BRANCH_KEY_MISMATCH")
if scope.get("corpus_scope_id") not in {None, corpus_scope_id}:
raise QueryPlanError("CORPUS_SCOPE_BINDING_MISMATCH")
if scope.get("element_set_id") not in {None, element_set_id}:
raise QueryPlanError("ELEMENT_SET_BINDING_MISMATCH")
snapshot_id = _nonempty(scope.get("snapshot_id"), "SNAPSHOT_ID_REQUIRED")
effective_on = _nonempty(effective_on, "EFFECTIVE_ON_REQUIRED")
query_contract = scope.get("query_contract")
if not isinstance(query_contract, Mapping):
raise QueryPlanError("QUERY_CONTRACT_REQUIRED")
alpha = query_contract.get("alpha")
top_k = query_contract.get("top_k")
if not isinstance(alpha, (int, float)) or isinstance(alpha, bool) or not 0 <= alpha <= 1:
raise QueryPlanError("QUERY_ALPHA_INVALID")
if not isinstance(top_k, int) or isinstance(top_k, bool) or not 1 <= top_k <= 100:
raise QueryPlanError("QUERY_TOP_K_INVALID")
configuration_digests = {
key: _sha256(query_contract.get(key), f"{key.upper()}_INVALID") for key in SHA256_KEYS
}
allowed_elements = scope.get("corpus_element_ids", [])
if not isinstance(allowed_elements, list) or not all(
isinstance(item, str) and item for item in allowed_elements
):
raise QueryPlanError("CORPUS_ELEMENT_IDS_INVALID")
allowed_set = set(allowed_elements)
rows: list[dict[str, Any]] = []
for role in ROLES:
raw_ids = role_element_ids.get(role, ())
if not isinstance(raw_ids, Sequence) or isinstance(raw_ids, (str, bytes)):
raise QueryPlanError("ROLE_ELEMENT_IDS_INVALID")
element_ids = sorted(set(raw_ids))
if not all(isinstance(item, str) and item for item in element_ids):
raise QueryPlanError("ROLE_ELEMENT_IDS_INVALID")
if allowed_set and not set(element_ids).issubset(allowed_set):
raise QueryPlanError("ROLE_ELEMENT_OUTSIDE_APPROVED_SCOPE")
query_text = " ".join([case_type_id, sub_rule_id, role, *element_ids])
query_text_sha256 = _digest(query_text)
query_identity = {
"atomic_claim_id": atomic_claim_id,
"rule_branch_key": rule_branch_key,
"doctrine_role": role,
"query_sha256": query_text_sha256,
}
row = {
"query_id": f"Q-{_digest(query_identity)[:24]}",
"atomic_claim_id": atomic_claim_id,
"case_type_id": case_type_id,
"sub_rule_id": sub_rule_id,
"rule_branch_key": rule_branch_key,
"corpus_scope_id": corpus_scope_id,
"element_set_id": element_set_id,
"doctrine_role": role,
"query_status": "READY",
"query_text": query_text,
"query_sha256": query_text_sha256,
"filter": {
"case_type_id": case_type_id,
"sub_rule_id": sub_rule_id,
"rule_branch_key": rule_branch_key,
"corpus_scope_id": corpus_scope_id,
"element_set_id": element_set_id,
"doctrine_role": role,
"jurisdiction": "KR",
"snapshot_id": snapshot_id,
"approval_status": "APPROVED",
"effective_on": effective_on,
},
"alpha": float(alpha),
"top_k": top_k,
**configuration_digests,
"expected_corpus_element_ids": element_ids,
"issue_codes": [],
}
rows.append(row)
core = {
"schema_version": "stage2_requirement_fact_query_plan.v1",
"run_binding_digest": run_binding_digest,
"atomic_claim_id": atomic_claim_id,
"rows": rows,
}
return {**core, "query_plan_sha256": _digest(core)}
@@ -0,0 +1,166 @@
#!/usr/bin/env python3
"""Build schema-conformant, release-bound C27 requirement-fact query plans."""
from __future__ import annotations
import hashlib
import json
from typing import Any, Mapping, Sequence
ROLES = ("element", "defense", "rebuttal", "burden", "relief_consistency")
SHA256_KEYS = (
"embedding_configuration_digest",
"reranker_configuration_digest",
"index_configuration_digest",
)
class QueryPlanError(ValueError):
"""Controlled C27 contract failure."""
def _digest(value: Any) -> str:
raw = (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
return hashlib.sha256(raw).hexdigest()
def _nonempty(value: Any, code: str) -> str:
if not isinstance(value, str) or not value:
raise QueryPlanError(code)
return value
def _sha256(value: Any, code: str) -> str:
text = _nonempty(value, code)
if len(text) != 64 or any(character not in "0123456789abcdef" for character in text):
raise QueryPlanError(code)
return text
def _bound(binding: Mapping[str, Any]) -> bool:
return (
binding.get("case_type_binding_status") == "BOUND"
and binding.get("sub_rule_binding_status") == "BOUND"
and binding.get("legal_content_status") == "APPROVED"
)
def build_query_plan(
atomic_claim_id: str,
binding: Mapping[str, Any],
scope: Mapping[str, Any],
role_element_ids: Mapping[str, Sequence[str]],
*,
run_binding_digest: str,
effective_on: str,
) -> dict[str, Any]:
"""Return the exact ``query_plan`` contract from binding_retrieval.schema.
An unresolved binding produces a valid empty plan. It never manufactures a
case type or rule ID merely to populate a query row.
"""
atomic_claim_id = _nonempty(atomic_claim_id, "ATOMIC_CLAIM_ID_REQUIRED")
run_binding_digest = _sha256(run_binding_digest, "RUN_BINDING_DIGEST_INVALID")
if not _bound(binding):
core = {
"schema_version": "stage2_requirement_fact_query_plan.v1",
"run_binding_digest": run_binding_digest,
"atomic_claim_id": atomic_claim_id,
"rows": [],
}
return {**core, "query_plan_sha256": _digest(core)}
case_type_id = _nonempty(binding.get("case_type_id"), "CASE_TYPE_ID_REQUIRED")
sub_rule_id = _nonempty(binding.get("sub_rule_id"), "SUB_RULE_ID_REQUIRED")
rule_branch_key = _nonempty(binding.get("rule_branch_key"), "RULE_BRANCH_KEY_REQUIRED")
corpus_scope_id = _nonempty(binding.get("corpus_scope_id"), "CORPUS_SCOPE_ID_REQUIRED")
element_set_id = _nonempty(binding.get("element_set_id"), "ELEMENT_SET_ID_REQUIRED")
if rule_branch_key != f"{case_type_id}::{sub_rule_id}":
raise QueryPlanError("RULE_BRANCH_KEY_MISMATCH")
if scope.get("corpus_scope_id") not in {None, corpus_scope_id}:
raise QueryPlanError("CORPUS_SCOPE_BINDING_MISMATCH")
if scope.get("element_set_id") not in {None, element_set_id}:
raise QueryPlanError("ELEMENT_SET_BINDING_MISMATCH")
snapshot_id = _nonempty(scope.get("snapshot_id"), "SNAPSHOT_ID_REQUIRED")
effective_on = _nonempty(effective_on, "EFFECTIVE_ON_REQUIRED")
query_contract = scope.get("query_contract")
if not isinstance(query_contract, Mapping):
raise QueryPlanError("QUERY_CONTRACT_REQUIRED")
alpha = query_contract.get("alpha")
top_k = query_contract.get("top_k")
if not isinstance(alpha, (int, float)) or isinstance(alpha, bool) or not 0 <= alpha <= 1:
raise QueryPlanError("QUERY_ALPHA_INVALID")
if not isinstance(top_k, int) or isinstance(top_k, bool) or not 1 <= top_k <= 100:
raise QueryPlanError("QUERY_TOP_K_INVALID")
configuration_digests = {
key: _sha256(query_contract.get(key), f"{key.upper()}_INVALID") for key in SHA256_KEYS
}
allowed_elements = scope.get("corpus_element_ids", [])
if not isinstance(allowed_elements, list) or not all(
isinstance(item, str) and item for item in allowed_elements
):
raise QueryPlanError("CORPUS_ELEMENT_IDS_INVALID")
allowed_set = set(allowed_elements)
rows: list[dict[str, Any]] = []
for role in ROLES:
raw_ids = role_element_ids.get(role, ())
if not isinstance(raw_ids, Sequence) or isinstance(raw_ids, (str, bytes)):
raise QueryPlanError("ROLE_ELEMENT_IDS_INVALID")
element_ids = sorted(set(raw_ids))
if not all(isinstance(item, str) and item for item in element_ids):
raise QueryPlanError("ROLE_ELEMENT_IDS_INVALID")
if allowed_set and not set(element_ids).issubset(allowed_set):
raise QueryPlanError("ROLE_ELEMENT_OUTSIDE_APPROVED_SCOPE")
query_text = " ".join([case_type_id, sub_rule_id, role, *element_ids])
query_text_sha256 = _digest(query_text)
query_identity = {
"atomic_claim_id": atomic_claim_id,
"rule_branch_key": rule_branch_key,
"doctrine_role": role,
"query_sha256": query_text_sha256,
}
row = {
"query_id": f"Q-{_digest(query_identity)[:24]}",
"atomic_claim_id": atomic_claim_id,
"case_type_id": case_type_id,
"sub_rule_id": sub_rule_id,
"rule_branch_key": rule_branch_key,
"corpus_scope_id": corpus_scope_id,
"element_set_id": element_set_id,
"doctrine_role": role,
"query_status": "READY",
"query_text": query_text,
"query_sha256": query_text_sha256,
"filter": {
"case_type_id": case_type_id,
"sub_rule_id": sub_rule_id,
"rule_branch_key": rule_branch_key,
"corpus_scope_id": corpus_scope_id,
"element_set_id": element_set_id,
"doctrine_role": role,
"jurisdiction": "KR",
"snapshot_id": snapshot_id,
"approval_status": "APPROVED",
"effective_on": effective_on,
},
"alpha": float(alpha),
"top_k": top_k,
**configuration_digests,
"expected_corpus_element_ids": element_ids,
"issue_codes": [],
}
rows.append(row)
core = {
"schema_version": "stage2_requirement_fact_query_plan.v1",
"run_binding_digest": run_binding_digest,
"atomic_claim_id": atomic_claim_id,
"rows": rows,
}
return {**core, "query_plan_sha256": _digest(core)}
@@ -0,0 +1,298 @@
#!/usr/bin/env python3
"""C28 exact-filter retrieval and canonical result/receipt normalization."""
from __future__ import annotations
import hashlib
import json
from typing import Any, Callable, Mapping, Sequence
class RetrievalError(RuntimeError):
"""Controlled C28 transport or contract failure."""
RESPONSE_KEYS = frozenset(
{
"schema_version", "request_id", "request_sha256", "response_status",
"raw_hit_count", "selected_hits", "dropped_hits", "deterministic_order_digest",
"retry_count",
}
)
HIT_KEYS = frozenset(
{
"chunk_id", "chunk_sha256", "source_document_id", "source_document_sha256",
"source_locator", "pre_rerank_rank", "hybrid_score", "post_rerank_rank",
"reranker_score", "metadata",
}
)
METADATA_KEYS = frozenset(
{
"schema_version", "document_id", "document_sha256", "chunk_id", "chunk_sha256",
"source_path", "source_locator", "case_type_ids", "sub_rule_ids",
"rule_branch_keys", "corpus_scope_ids", "element_set_ids", "corpus_element_ids",
"doctrine_roles", "jurisdiction", "effective_from", "effective_to", "authority_ids",
"proposition_ids", "approval_status", "legal_reviewer_receipt_ref",
"legal_reviewer_receipt_sha256",
}
)
DROP_KEYS = frozenset({"chunk_id", "chunk_sha256", "drop_reason_code"})
DROP_REASONS = frozenset(
{"FILTER_MISMATCH", "UNAPPROVED_CHUNK", "HASH_MISMATCH", "SNAPSHOT_MISMATCH", "CROSSWALK_GAP", "DUPLICATE_CHUNK"}
)
def _canonical(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
def _digest(value: Any) -> str:
return hashlib.sha256(_canonical(value)).hexdigest()
def _nonempty(value: Any, code: str) -> str:
if not isinstance(value, str) or not value:
raise RetrievalError(code)
return value
def build_request(query_row: Mapping[str, Any], collection: Mapping[str, Any]) -> dict[str, Any]:
"""Build the exact Weaviate ``hybrid_search_request`` contract."""
if query_row.get("query_status") != "READY":
raise RetrievalError("QUERY_ROW_NOT_READY")
filter_value = query_row.get("filter")
if not isinstance(filter_value, Mapping):
raise RetrievalError("QUERY_FILTER_REQUIRED")
request_seed = {
"query_id": query_row.get("query_id"),
"query_sha256": query_row.get("query_sha256"),
"snapshot_sha256": collection.get("snapshot_sha256"),
}
return {
"schema_version": "stage2_weaviate_hybrid_search_request.v1",
"request_id": f"REQ-{_digest(request_seed)[:24]}",
"query_plan_id": _nonempty(query_row.get("query_id"), "QUERY_ID_REQUIRED"),
"atomic_claim_id": _nonempty(
query_row.get("atomic_claim_id"), "ATOMIC_CLAIM_ID_REQUIRED"
),
"collection_name": _nonempty(
collection.get("collection_name"), "COLLECTION_NAME_REQUIRED"
),
"tenant": _nonempty(collection.get("tenant"), "TENANT_REQUIRED"),
"query_text": _nonempty(query_row.get("query_text"), "QUERY_TEXT_REQUIRED"),
"query_sha256": _nonempty(query_row.get("query_sha256"), "QUERY_SHA256_REQUIRED"),
"filter": dict(filter_value),
"alpha": query_row.get("alpha"),
"top_k": query_row.get("top_k"),
"embedding_configuration_digest": query_row.get("embedding_configuration_digest"),
"reranker_configuration_digest": query_row.get("reranker_configuration_digest"),
"index_configuration_digest": query_row.get("index_configuration_digest"),
"snapshot_sha256": _nonempty(
collection.get("snapshot_sha256"), "SNAPSHOT_SHA256_REQUIRED"
),
}
def _drop(hit: Mapping[str, Any], reason: str) -> dict[str, Any]:
return {
"chunk_id": _nonempty(hit.get("chunk_id"), "HIT_CHUNK_ID_REQUIRED"),
"chunk_sha256": _nonempty(hit.get("chunk_sha256"), "HIT_CHUNK_SHA256_REQUIRED"),
"drop_reason_code": reason,
}
def _hit_filter_mismatch(hit: Mapping[str, Any], filter_value: Mapping[str, Any]) -> str | None:
if set(hit) != HIT_KEYS:
raise RetrievalError("RETRIEVAL_HIT_KEYS_INVALID")
metadata = hit.get("metadata")
if not isinstance(metadata, Mapping):
raise RetrievalError("RETRIEVAL_HIT_METADATA_INVALID")
if set(metadata) != METADATA_KEYS:
raise RetrievalError("RETRIEVAL_HIT_METADATA_KEYS_INVALID")
if metadata.get("approval_status") != "APPROVED":
return "UNAPPROVED_CHUNK"
scalar_to_set = {
"case_type_id": "case_type_ids",
"sub_rule_id": "sub_rule_ids",
"rule_branch_key": "rule_branch_keys",
"corpus_scope_id": "corpus_scope_ids",
"element_set_id": "element_set_ids",
"doctrine_role": "doctrine_roles",
}
for filter_key, metadata_key in scalar_to_set.items():
values = metadata.get(metadata_key)
if not isinstance(values, list) or filter_value.get(filter_key) not in values:
return "FILTER_MISMATCH"
if metadata.get("jurisdiction") != "KR":
return "FILTER_MISMATCH"
if hit.get("chunk_sha256") != metadata.get("chunk_sha256"):
return "HASH_MISMATCH"
return None
def _receipt(
*,
query_plan: Mapping[str, Any],
query_row: Mapping[str, Any],
request: Mapping[str, Any],
response: Mapping[str, Any],
collection: Mapping[str, Any],
credential_ref: str,
) -> dict[str, Any]:
configuration = {
key: query_row.get(key)
for key in (
"alpha",
"top_k",
"embedding_configuration_digest",
"reranker_configuration_digest",
"index_configuration_digest",
)
}
core = {
"schema_version": "stage2_requirement_fact_retrieval_receipt.v1",
"run_binding_digest": query_plan["run_binding_digest"],
"atomic_claim_id": query_plan["atomic_claim_id"],
"query_plan_sha256": query_plan["query_plan_sha256"],
"request_sha256": _digest(request),
"response_sha256": _digest(response),
"transport": "MCP_OVER_HTTP_JSON_RPC",
"endpoint": "https://weaviate.eroomai.com/mcp",
"tool_name": "search_hybrid",
"collection_name": collection["collection_name"],
"tenant": collection["tenant"],
"snapshot_sha256": collection["snapshot_sha256"],
"filter_sha256": _digest(query_row["filter"]),
"configuration_digest": _digest(configuration),
"attempt_count": int(response.get("retry_count", 0)) + 1,
"replay_status": "NOT_REQUESTED",
"read_only_verified": True,
"credential_ref": _nonempty(credential_ref, "CREDENTIAL_REF_REQUIRED"),
"credential_material_persisted": False,
}
return {**core, "receipt_sha256": _digest(core)}
def retrieve_exact(
query_plan: Mapping[str, Any],
collection: Mapping[str, Any],
search_hybrid: Callable[[Mapping[str, Any]], Mapping[str, Any]],
*,
credential_ref: str,
) -> tuple[dict[str, Any], list[dict[str, Any]]]:
"""Execute READY rows without fallback and return canonical result + receipts."""
rows = query_plan.get("rows")
if not isinstance(rows, Sequence) or isinstance(rows, (str, bytes)):
raise RetrievalError("QUERY_PLAN_ROWS_INVALID")
selected: list[dict[str, Any]] = []
dropped: list[dict[str, Any]] = []
receipts: list[dict[str, Any]] = []
issue_codes: set[str] = set()
technical_incomplete = False
for query_row in rows:
if not isinstance(query_row, Mapping) or query_row.get("query_status") != "READY":
raise RetrievalError("QUERY_PLAN_READY_ROW_REQUIRED")
request = build_request(query_row, collection)
request_sha256 = _digest(request)
response = search_hybrid(request)
if not isinstance(response, Mapping) or response.get("request_sha256") != request_sha256:
raise RetrievalError("RETRIEVAL_REQUEST_ECHO_MISMATCH")
if set(response) != RESPONSE_KEYS:
raise RetrievalError("RETRIEVAL_RESPONSE_KEYS_INVALID")
if response.get("schema_version") != "stage2_weaviate_hybrid_search_response.v1":
raise RetrievalError("RETRIEVAL_RESPONSE_SCHEMA_MISMATCH")
if response.get("request_id") != request["request_id"]:
raise RetrievalError("RETRIEVAL_REQUEST_ID_ECHO_MISMATCH")
retry_count = response.get("retry_count")
if not isinstance(retry_count, int) or isinstance(retry_count, bool) or not 0 <= retry_count <= 2:
raise RetrievalError("RETRIEVAL_RETRY_COUNT_INVALID")
response_status = response.get("response_status")
if response_status not in {"COMPLETE", "NO_HIT", "TECHNICAL_INCOMPLETE"}:
raise RetrievalError("RETRIEVAL_RESPONSE_STATUS_INVALID")
if response_status == "TECHNICAL_INCOMPLETE":
technical_incomplete = True
issue_codes.add("RETRIEVAL_TECHNICAL_INCOMPLETE")
raw_hits = response.get("selected_hits")
raw_drops = response.get("dropped_hits")
if not isinstance(raw_hits, list) or not isinstance(raw_drops, list):
raise RetrievalError("RETRIEVAL_RESPONSE_ROWS_INVALID")
for hit in raw_hits:
if not isinstance(hit, Mapping):
raise RetrievalError("RETRIEVAL_HIT_INVALID")
reason = _hit_filter_mismatch(hit, query_row["filter"])
if reason is None:
selected.append(dict(hit))
else:
dropped.append(_drop(hit, reason))
issue_codes.add(reason)
for row in raw_drops:
if (
not isinstance(row, Mapping)
or set(row) != DROP_KEYS
or row.get("drop_reason_code") not in DROP_REASONS
):
raise RetrievalError("DROPPED_HIT_INVALID")
dropped.append(dict(row))
receipts.append(
_receipt(
query_plan=query_plan,
query_row=query_row,
request=request,
response=response,
collection=collection,
credential_ref=credential_ref,
)
)
unique: dict[str, dict[str, Any]] = {}
for hit in sorted(
selected,
key=lambda value: (
int(value.get("post_rerank_rank", 2**31 - 1)),
-float(value.get("reranker_score") or value.get("hybrid_score") or 0),
str(value.get("chunk_id", "")),
),
):
chunk_id = _nonempty(hit.get("chunk_id"), "HIT_CHUNK_ID_REQUIRED")
if chunk_id in unique:
dropped.append(_drop(hit, "DUPLICATE_CHUNK"))
issue_codes.add("DUPLICATE_CHUNK")
else:
unique[chunk_id] = hit
selected_hits = list(unique.values())
result_status = (
"NOT_RUN_UNRESOLVED_BINDING"
if not rows
else "TECHNICAL_INCOMPLETE"
if technical_incomplete
else "COMPLETE"
if selected_hits
else "NO_HIT"
)
if not rows:
issue_codes.add("QUERY_NOT_RUN_UNRESOLVED_BINDING")
core = {
"schema_version": "stage2_requirement_fact_retrieval_result.v1",
"run_binding_digest": query_plan["run_binding_digest"],
"atomic_claim_id": query_plan["atomic_claim_id"],
"query_plan_sha256": query_plan["query_plan_sha256"],
"snapshot_id": _nonempty(collection.get("snapshot_id"), "SNAPSHOT_ID_REQUIRED"),
"snapshot_sha256": _nonempty(
collection.get("snapshot_sha256"), "SNAPSHOT_SHA256_REQUIRED"
),
"result_status": result_status,
"selected_hits": selected_hits,
"dropped_hits": sorted(
dropped,
key=lambda value: (
str(value.get("chunk_id", "")),
str(value.get("drop_reason_code", "")),
),
),
"issue_codes": sorted(issue_codes),
}
return {**core, "result_sha256": _digest(core)}, receipts
@@ -0,0 +1,298 @@
#!/usr/bin/env python3
"""C28 exact-filter retrieval and canonical result/receipt normalization."""
from __future__ import annotations
import hashlib
import json
from typing import Any, Callable, Mapping, Sequence
class RetrievalError(RuntimeError):
"""Controlled C28 transport or contract failure."""
RESPONSE_KEYS = frozenset(
{
"schema_version", "request_id", "request_sha256", "response_status",
"raw_hit_count", "selected_hits", "dropped_hits", "deterministic_order_digest",
"retry_count",
}
)
HIT_KEYS = frozenset(
{
"chunk_id", "chunk_sha256", "source_document_id", "source_document_sha256",
"source_locator", "pre_rerank_rank", "hybrid_score", "post_rerank_rank",
"reranker_score", "metadata",
}
)
METADATA_KEYS = frozenset(
{
"schema_version", "document_id", "document_sha256", "chunk_id", "chunk_sha256",
"source_path", "source_locator", "case_type_ids", "sub_rule_ids",
"rule_branch_keys", "corpus_scope_ids", "element_set_ids", "corpus_element_ids",
"doctrine_roles", "jurisdiction", "effective_from", "effective_to", "authority_ids",
"proposition_ids", "approval_status", "legal_reviewer_receipt_ref",
"legal_reviewer_receipt_sha256",
}
)
DROP_KEYS = frozenset({"chunk_id", "chunk_sha256", "drop_reason_code"})
DROP_REASONS = frozenset(
{"FILTER_MISMATCH", "UNAPPROVED_CHUNK", "HASH_MISMATCH", "SNAPSHOT_MISMATCH", "CROSSWALK_GAP", "DUPLICATE_CHUNK"}
)
def _canonical(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
def _digest(value: Any) -> str:
return hashlib.sha256(_canonical(value)).hexdigest()
def _nonempty(value: Any, code: str) -> str:
if not isinstance(value, str) or not value:
raise RetrievalError(code)
return value
def build_request(query_row: Mapping[str, Any], collection: Mapping[str, Any]) -> dict[str, Any]:
"""Build the exact Weaviate ``hybrid_search_request`` contract."""
if query_row.get("query_status") != "READY":
raise RetrievalError("QUERY_ROW_NOT_READY")
filter_value = query_row.get("filter")
if not isinstance(filter_value, Mapping):
raise RetrievalError("QUERY_FILTER_REQUIRED")
request_seed = {
"query_id": query_row.get("query_id"),
"query_sha256": query_row.get("query_sha256"),
"snapshot_sha256": collection.get("snapshot_sha256"),
}
return {
"schema_version": "stage2_weaviate_hybrid_search_request.v1",
"request_id": f"REQ-{_digest(request_seed)[:24]}",
"query_plan_id": _nonempty(query_row.get("query_id"), "QUERY_ID_REQUIRED"),
"atomic_claim_id": _nonempty(
query_row.get("atomic_claim_id"), "ATOMIC_CLAIM_ID_REQUIRED"
),
"collection_name": _nonempty(
collection.get("collection_name"), "COLLECTION_NAME_REQUIRED"
),
"tenant": _nonempty(collection.get("tenant"), "TENANT_REQUIRED"),
"query_text": _nonempty(query_row.get("query_text"), "QUERY_TEXT_REQUIRED"),
"query_sha256": _nonempty(query_row.get("query_sha256"), "QUERY_SHA256_REQUIRED"),
"filter": dict(filter_value),
"alpha": query_row.get("alpha"),
"top_k": query_row.get("top_k"),
"embedding_configuration_digest": query_row.get("embedding_configuration_digest"),
"reranker_configuration_digest": query_row.get("reranker_configuration_digest"),
"index_configuration_digest": query_row.get("index_configuration_digest"),
"snapshot_sha256": _nonempty(
collection.get("snapshot_sha256"), "SNAPSHOT_SHA256_REQUIRED"
),
}
def _drop(hit: Mapping[str, Any], reason: str) -> dict[str, Any]:
return {
"chunk_id": _nonempty(hit.get("chunk_id"), "HIT_CHUNK_ID_REQUIRED"),
"chunk_sha256": _nonempty(hit.get("chunk_sha256"), "HIT_CHUNK_SHA256_REQUIRED"),
"drop_reason_code": reason,
}
def _hit_filter_mismatch(hit: Mapping[str, Any], filter_value: Mapping[str, Any]) -> str | None:
if set(hit) != HIT_KEYS:
raise RetrievalError("RETRIEVAL_HIT_KEYS_INVALID")
metadata = hit.get("metadata")
if not isinstance(metadata, Mapping):
raise RetrievalError("RETRIEVAL_HIT_METADATA_INVALID")
if set(metadata) != METADATA_KEYS:
raise RetrievalError("RETRIEVAL_HIT_METADATA_KEYS_INVALID")
if metadata.get("approval_status") != "APPROVED":
return "UNAPPROVED_CHUNK"
scalar_to_set = {
"case_type_id": "case_type_ids",
"sub_rule_id": "sub_rule_ids",
"rule_branch_key": "rule_branch_keys",
"corpus_scope_id": "corpus_scope_ids",
"element_set_id": "element_set_ids",
"doctrine_role": "doctrine_roles",
}
for filter_key, metadata_key in scalar_to_set.items():
values = metadata.get(metadata_key)
if not isinstance(values, list) or filter_value.get(filter_key) not in values:
return "FILTER_MISMATCH"
if metadata.get("jurisdiction") != "KR":
return "FILTER_MISMATCH"
if hit.get("chunk_sha256") != metadata.get("chunk_sha256"):
return "HASH_MISMATCH"
return None
def _receipt(
*,
query_plan: Mapping[str, Any],
query_row: Mapping[str, Any],
request: Mapping[str, Any],
response: Mapping[str, Any],
collection: Mapping[str, Any],
credential_ref: str,
) -> dict[str, Any]:
configuration = {
key: query_row.get(key)
for key in (
"alpha",
"top_k",
"embedding_configuration_digest",
"reranker_configuration_digest",
"index_configuration_digest",
)
}
core = {
"schema_version": "stage2_requirement_fact_retrieval_receipt.v1",
"run_binding_digest": query_plan["run_binding_digest"],
"atomic_claim_id": query_plan["atomic_claim_id"],
"query_plan_sha256": query_plan["query_plan_sha256"],
"request_sha256": _digest(request),
"response_sha256": _digest(response),
"transport": "MCP_OVER_HTTP_JSON_RPC",
"endpoint": "https://weaviate.eroomai.com/mcp",
"tool_name": "search_hybrid",
"collection_name": collection["collection_name"],
"tenant": collection["tenant"],
"snapshot_sha256": collection["snapshot_sha256"],
"filter_sha256": _digest(query_row["filter"]),
"configuration_digest": _digest(configuration),
"attempt_count": int(response.get("retry_count", 0)) + 1,
"replay_status": "NOT_REQUESTED",
"read_only_verified": True,
"credential_ref": _nonempty(credential_ref, "CREDENTIAL_REF_REQUIRED"),
"credential_material_persisted": False,
}
return {**core, "receipt_sha256": _digest(core)}
def retrieve_exact(
query_plan: Mapping[str, Any],
collection: Mapping[str, Any],
search_hybrid: Callable[[Mapping[str, Any]], Mapping[str, Any]],
*,
credential_ref: str,
) -> tuple[dict[str, Any], list[dict[str, Any]]]:
"""Execute READY rows without fallback and return canonical result + receipts."""
rows = query_plan.get("rows")
if not isinstance(rows, Sequence) or isinstance(rows, (str, bytes)):
raise RetrievalError("QUERY_PLAN_ROWS_INVALID")
selected: list[dict[str, Any]] = []
dropped: list[dict[str, Any]] = []
receipts: list[dict[str, Any]] = []
issue_codes: set[str] = set()
technical_incomplete = False
for query_row in rows:
if not isinstance(query_row, Mapping) or query_row.get("query_status") != "READY":
raise RetrievalError("QUERY_PLAN_READY_ROW_REQUIRED")
request = build_request(query_row, collection)
request_sha256 = _digest(request)
response = search_hybrid(request)
if not isinstance(response, Mapping) or response.get("request_sha256") != request_sha256:
raise RetrievalError("RETRIEVAL_REQUEST_ECHO_MISMATCH")
if set(response) != RESPONSE_KEYS:
raise RetrievalError("RETRIEVAL_RESPONSE_KEYS_INVALID")
if response.get("schema_version") != "stage2_weaviate_hybrid_search_response.v1":
raise RetrievalError("RETRIEVAL_RESPONSE_SCHEMA_MISMATCH")
if response.get("request_id") != request["request_id"]:
raise RetrievalError("RETRIEVAL_REQUEST_ID_ECHO_MISMATCH")
retry_count = response.get("retry_count")
if not isinstance(retry_count, int) or isinstance(retry_count, bool) or not 0 <= retry_count <= 2:
raise RetrievalError("RETRIEVAL_RETRY_COUNT_INVALID")
response_status = response.get("response_status")
if response_status not in {"COMPLETE", "NO_HIT", "TECHNICAL_INCOMPLETE"}:
raise RetrievalError("RETRIEVAL_RESPONSE_STATUS_INVALID")
if response_status == "TECHNICAL_INCOMPLETE":
technical_incomplete = True
issue_codes.add("RETRIEVAL_TECHNICAL_INCOMPLETE")
raw_hits = response.get("selected_hits")
raw_drops = response.get("dropped_hits")
if not isinstance(raw_hits, list) or not isinstance(raw_drops, list):
raise RetrievalError("RETRIEVAL_RESPONSE_ROWS_INVALID")
for hit in raw_hits:
if not isinstance(hit, Mapping):
raise RetrievalError("RETRIEVAL_HIT_INVALID")
reason = _hit_filter_mismatch(hit, query_row["filter"])
if reason is None:
selected.append(dict(hit))
else:
dropped.append(_drop(hit, reason))
issue_codes.add(reason)
for row in raw_drops:
if (
not isinstance(row, Mapping)
or set(row) != DROP_KEYS
or row.get("drop_reason_code") not in DROP_REASONS
):
raise RetrievalError("DROPPED_HIT_INVALID")
dropped.append(dict(row))
receipts.append(
_receipt(
query_plan=query_plan,
query_row=query_row,
request=request,
response=response,
collection=collection,
credential_ref=credential_ref,
)
)
unique: dict[str, dict[str, Any]] = {}
for hit in sorted(
selected,
key=lambda value: (
int(value.get("post_rerank_rank", 2**31 - 1)),
-float(value.get("reranker_score") or value.get("hybrid_score") or 0),
str(value.get("chunk_id", "")),
),
):
chunk_id = _nonempty(hit.get("chunk_id"), "HIT_CHUNK_ID_REQUIRED")
if chunk_id in unique:
dropped.append(_drop(hit, "DUPLICATE_CHUNK"))
issue_codes.add("DUPLICATE_CHUNK")
else:
unique[chunk_id] = hit
selected_hits = list(unique.values())
result_status = (
"NOT_RUN_UNRESOLVED_BINDING"
if not rows
else "TECHNICAL_INCOMPLETE"
if technical_incomplete
else "COMPLETE"
if selected_hits
else "NO_HIT"
)
if not rows:
issue_codes.add("QUERY_NOT_RUN_UNRESOLVED_BINDING")
core = {
"schema_version": "stage2_requirement_fact_retrieval_result.v1",
"run_binding_digest": query_plan["run_binding_digest"],
"atomic_claim_id": query_plan["atomic_claim_id"],
"query_plan_sha256": query_plan["query_plan_sha256"],
"snapshot_id": _nonempty(collection.get("snapshot_id"), "SNAPSHOT_ID_REQUIRED"),
"snapshot_sha256": _nonempty(
collection.get("snapshot_sha256"), "SNAPSHOT_SHA256_REQUIRED"
),
"result_status": result_status,
"selected_hits": selected_hits,
"dropped_hits": sorted(
dropped,
key=lambda value: (
str(value.get("chunk_id", "")),
str(value.get("drop_reason_code", "")),
),
),
"issue_codes": sorted(issue_codes),
}
return {**core, "result_sha256": _digest(core)}, receipts
@@ -0,0 +1,137 @@
#!/usr/bin/env python3
"""C29 retrieval provenance and Stage-1-slot crosswalk verifier."""
from __future__ import annotations
import hashlib
import json
from typing import Any, Mapping, Sequence
class PackError(ValueError):
"""Controlled C29 contract failure."""
def _digest(value: Any) -> str:
raw = (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
return hashlib.sha256(raw).hexdigest()
def _sha256(value: Any, code: str) -> str:
if (
not isinstance(value, str)
or len(value) != 64
or any(character not in "0123456789abcdef" for character in value)
):
raise PackError(code)
return value
def verify_pack(
binding: Mapping[str, Any],
retrieval_result: Mapping[str, Any],
corpus_release: Mapping[str, Any],
crosswalk_rows: Sequence[Mapping[str, Any]],
*,
claim_group_id: str,
retrieval_receipt_refs: Sequence[Mapping[str, Any]],
) -> dict[str, Any]:
"""Return the exact ``requirement_fact_pack`` schema contract."""
run_binding_digest = retrieval_result.get("run_binding_digest")
atomic_claim_id = retrieval_result.get("atomic_claim_id")
run_binding_digest = _sha256(run_binding_digest, "RUN_BINDING_DIGEST_INVALID")
if not isinstance(atomic_claim_id, str) or not atomic_claim_id:
raise PackError("ATOMIC_CLAIM_ID_REQUIRED")
expected_snapshot = corpus_release.get("snapshot_id")
expected_snapshot_hash = corpus_release.get("snapshot_sha256")
if (
retrieval_result.get("snapshot_id") != expected_snapshot
or retrieval_result.get("snapshot_sha256") != expected_snapshot_hash
):
raise PackError("RETRIEVAL_RESULT_SNAPSHOT_MISMATCH")
corpus_release_sha256 = _sha256(
corpus_release.get("corpus_release_sha256"), "CORPUS_RELEASE_SHA256_INVALID"
)
expected_snapshot_hash = _sha256(expected_snapshot_hash, "SNAPSHOT_SHA256_INVALID")
crosswalk = {
(row.get("corpus_element_id"), row.get("doctrine_role")): row
for row in crosswalk_rows
if isinstance(row, Mapping)
}
items: list[dict[str, Any]] = []
unmapped: set[str] = set()
conflicting: set[str] = set()
issue_codes: set[str] = set(retrieval_result.get("issue_codes", []))
for hit in retrieval_result.get("selected_hits", []):
if not isinstance(hit, Mapping):
raise PackError("RETRIEVAL_HIT_INVALID")
metadata = hit.get("metadata")
if not isinstance(metadata, Mapping):
raise PackError("RETRIEVAL_HIT_METADATA_REQUIRED")
chunk_id = hit.get("chunk_id")
if not isinstance(chunk_id, str) or not chunk_id:
raise PackError("CHUNK_ID_REQUIRED")
mismatch = (
binding.get("case_type_id") not in metadata.get("case_type_ids", [])
or binding.get("sub_rule_id") not in metadata.get("sub_rule_ids", [])
or binding.get("rule_branch_key") not in metadata.get("rule_branch_keys", [])
)
if mismatch:
conflicting.add(chunk_id)
issue_codes.add("RETRIEVAL_BINDING_MISMATCH")
continue
for corpus_element_id in sorted(set(metadata.get("corpus_element_ids", []))):
for doctrine_role in sorted(set(metadata.get("doctrine_roles", []))):
row = crosswalk.get((corpus_element_id, doctrine_role))
if row is None or row.get("mapping_status") in {None, "UNMAPPED"}:
unmapped.add(chunk_id)
issue_codes.add("SLOT_CROSSWALK_MISSING")
continue
if row.get("mapping_status") == "CONFLICT":
conflicting.add(chunk_id)
issue_codes.add("SLOT_CROSSWALK_CONFLICT")
continue
items.append(
{
"corpus_element_id": corpus_element_id,
"doctrine_role": doctrine_role,
"chunk_id": chunk_id,
"chunk_sha256": hit["chunk_sha256"],
"source_document_id": hit["source_document_id"],
"source_document_sha256": hit["source_document_sha256"],
"source_locator": hit["source_locator"],
"authority_ids": sorted(set(metadata.get("authority_ids", []))),
"proposition_ids": sorted(set(metadata.get("proposition_ids", []))),
"stage1_slot_refs": sorted(set(row.get("stage1_slot_refs", []))),
"mapping_status": row["mapping_status"],
"fact_creation_allowed": False,
"legal_decision_override_allowed": False,
}
)
items.sort(
key=lambda item: (
item["corpus_element_id"],
item["doctrine_role"],
item["chunk_id"],
)
)
core = {
"schema_version": "stage2_requirement_fact_pack.v1",
"run_binding_digest": run_binding_digest,
"claim_group_id": claim_group_id,
"atomic_claim_ids": [atomic_claim_id],
"corpus_release_sha256": corpus_release_sha256,
"snapshot_id": expected_snapshot,
"snapshot_sha256": expected_snapshot_hash,
"retrieval_receipt_refs": [dict(row) for row in retrieval_receipt_refs],
"items": items,
"unmapped_chunk_ids": sorted(unmapped),
"conflicting_chunk_ids": sorted(conflicting),
"authority_class": "CAUSE_AND_ELEMENT_CHECK",
"issue_codes": sorted(issue_codes),
}
return {**core, "pack_sha256": _digest(core)}
@@ -0,0 +1,137 @@
#!/usr/bin/env python3
"""C29 retrieval provenance and Stage-1-slot crosswalk verifier."""
from __future__ import annotations
import hashlib
import json
from typing import Any, Mapping, Sequence
class PackError(ValueError):
"""Controlled C29 contract failure."""
def _digest(value: Any) -> str:
raw = (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
return hashlib.sha256(raw).hexdigest()
def _sha256(value: Any, code: str) -> str:
if (
not isinstance(value, str)
or len(value) != 64
or any(character not in "0123456789abcdef" for character in value)
):
raise PackError(code)
return value
def verify_pack(
binding: Mapping[str, Any],
retrieval_result: Mapping[str, Any],
corpus_release: Mapping[str, Any],
crosswalk_rows: Sequence[Mapping[str, Any]],
*,
claim_group_id: str,
retrieval_receipt_refs: Sequence[Mapping[str, Any]],
) -> dict[str, Any]:
"""Return the exact ``requirement_fact_pack`` schema contract."""
run_binding_digest = retrieval_result.get("run_binding_digest")
atomic_claim_id = retrieval_result.get("atomic_claim_id")
run_binding_digest = _sha256(run_binding_digest, "RUN_BINDING_DIGEST_INVALID")
if not isinstance(atomic_claim_id, str) or not atomic_claim_id:
raise PackError("ATOMIC_CLAIM_ID_REQUIRED")
expected_snapshot = corpus_release.get("snapshot_id")
expected_snapshot_hash = corpus_release.get("snapshot_sha256")
if (
retrieval_result.get("snapshot_id") != expected_snapshot
or retrieval_result.get("snapshot_sha256") != expected_snapshot_hash
):
raise PackError("RETRIEVAL_RESULT_SNAPSHOT_MISMATCH")
corpus_release_sha256 = _sha256(
corpus_release.get("corpus_release_sha256"), "CORPUS_RELEASE_SHA256_INVALID"
)
expected_snapshot_hash = _sha256(expected_snapshot_hash, "SNAPSHOT_SHA256_INVALID")
crosswalk = {
(row.get("corpus_element_id"), row.get("doctrine_role")): row
for row in crosswalk_rows
if isinstance(row, Mapping)
}
items: list[dict[str, Any]] = []
unmapped: set[str] = set()
conflicting: set[str] = set()
issue_codes: set[str] = set(retrieval_result.get("issue_codes", []))
for hit in retrieval_result.get("selected_hits", []):
if not isinstance(hit, Mapping):
raise PackError("RETRIEVAL_HIT_INVALID")
metadata = hit.get("metadata")
if not isinstance(metadata, Mapping):
raise PackError("RETRIEVAL_HIT_METADATA_REQUIRED")
chunk_id = hit.get("chunk_id")
if not isinstance(chunk_id, str) or not chunk_id:
raise PackError("CHUNK_ID_REQUIRED")
mismatch = (
binding.get("case_type_id") not in metadata.get("case_type_ids", [])
or binding.get("sub_rule_id") not in metadata.get("sub_rule_ids", [])
or binding.get("rule_branch_key") not in metadata.get("rule_branch_keys", [])
)
if mismatch:
conflicting.add(chunk_id)
issue_codes.add("RETRIEVAL_BINDING_MISMATCH")
continue
for corpus_element_id in sorted(set(metadata.get("corpus_element_ids", []))):
for doctrine_role in sorted(set(metadata.get("doctrine_roles", []))):
row = crosswalk.get((corpus_element_id, doctrine_role))
if row is None or row.get("mapping_status") in {None, "UNMAPPED"}:
unmapped.add(chunk_id)
issue_codes.add("SLOT_CROSSWALK_MISSING")
continue
if row.get("mapping_status") == "CONFLICT":
conflicting.add(chunk_id)
issue_codes.add("SLOT_CROSSWALK_CONFLICT")
continue
items.append(
{
"corpus_element_id": corpus_element_id,
"doctrine_role": doctrine_role,
"chunk_id": chunk_id,
"chunk_sha256": hit["chunk_sha256"],
"source_document_id": hit["source_document_id"],
"source_document_sha256": hit["source_document_sha256"],
"source_locator": hit["source_locator"],
"authority_ids": sorted(set(metadata.get("authority_ids", []))),
"proposition_ids": sorted(set(metadata.get("proposition_ids", []))),
"stage1_slot_refs": sorted(set(row.get("stage1_slot_refs", []))),
"mapping_status": row["mapping_status"],
"fact_creation_allowed": False,
"legal_decision_override_allowed": False,
}
)
items.sort(
key=lambda item: (
item["corpus_element_id"],
item["doctrine_role"],
item["chunk_id"],
)
)
core = {
"schema_version": "stage2_requirement_fact_pack.v1",
"run_binding_digest": run_binding_digest,
"claim_group_id": claim_group_id,
"atomic_claim_ids": [atomic_claim_id],
"corpus_release_sha256": corpus_release_sha256,
"snapshot_id": expected_snapshot,
"snapshot_sha256": expected_snapshot_hash,
"retrieval_receipt_refs": [dict(row) for row in retrieval_receipt_refs],
"items": items,
"unmapped_chunk_ids": sorted(unmapped),
"conflicting_chunk_ids": sorted(conflicting),
"authority_class": "CAUSE_AND_ELEMENT_CHECK",
"issue_codes": sorted(issue_codes),
}
return {**core, "pack_sha256": _digest(core)}
@@ -0,0 +1,286 @@
#!/usr/bin/env python3
"""Safe Decimal interpreter that emits canonical S2_20 calculation receipts."""
from __future__ import annotations
from decimal import Decimal, InvalidOperation, ROUND_DOWN, ROUND_HALF_UP, ROUND_UP
import hashlib
import json
import re
from typing import Any, Mapping, Sequence
OPERATORS = frozenset({"ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "MIN", "MAX"})
ROUNDING_MODES = {
"ROUND_HALF_UP": ROUND_HALF_UP,
"ROUND_DOWN": ROUND_DOWN,
"ROUND_UP": ROUND_UP,
"TRUNCATE": ROUND_DOWN,
}
CALCULATOR_ID = re.compile(r"^CE-(?:0[1-9]|1[0-3]|R[1-4])$")
SHA256 = re.compile(r"^[a-f0-9]{64}$")
class CalculationError(ValueError):
"""Controlled calculator contract failure."""
def _decimal(value: Any) -> Decimal:
try:
return Decimal(str(value))
except (InvalidOperation, ValueError) as exc:
raise CalculationError("INVALID_DECIMAL_OPERAND") from exc
def _canonical(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
def _digest(value: Any) -> str:
return hashlib.sha256(_canonical(value)).hexdigest()
def _sha256(value: Any, code: str) -> str:
if not isinstance(value, str) or SHA256.fullmatch(value) is None:
raise CalculationError(code)
return value
def activate_calculators(
signature: Mapping[str, Any],
requested_metrics: Sequence[str],
activation_rows: Sequence[Mapping[str, Any]],
) -> list[dict[str, Any]]:
"""Evaluate the closed activation registry without a default branch."""
rows: list[dict[str, Any]] = []
for rule in sorted(
activation_rows,
key=lambda row: (str(row.get("calculator_id")), str(row.get("activation_row_id"))),
):
calculator_id = rule.get("calculator_id")
allowed_metrics = rule.get("requested_metrics", [])
predicates = rule.get("equals", {})
if (
not isinstance(calculator_id, str)
or CALCULATOR_ID.fullmatch(calculator_id) is None
or not isinstance(allowed_metrics, list)
or not isinstance(predicates, Mapping)
or not predicates
):
raise CalculationError("INVALID_ACTIVATION_ROW")
metric_match = bool(set(requested_metrics) & set(allowed_metrics))
predicate_match = all(signature.get(key, "UNKNOWN") == value for key, value in predicates.items())
rows.append(
{
"calculator_id": calculator_id,
"activation_row_id": rule.get("activation_row_id"),
"activation_status": "ACTIVATED" if metric_match and predicate_match else "NOT_APPLICABLE",
}
)
return rows
def _operand_row(operand_id: str, supplied: Any, unit_id: str, currency: str | None) -> dict[str, Any]:
if supplied is None:
return {
"operand_id": operand_id,
"source_ref": f"OPERAND:{operand_id}",
"status": "MISSING",
"value_type": "DECIMAL",
"value": None,
"unit_id": unit_id,
"currency": currency,
"value_sha256": None,
}
if isinstance(supplied, Mapping):
status = supplied.get("status", "PRESENT")
value = supplied.get("value")
source_ref = supplied.get("source_ref", f"OPERAND:{operand_id}")
value_type = supplied.get("value_type", "DECIMAL")
row_unit = supplied.get("unit_id", unit_id)
row_currency = supplied.get("currency", currency)
else:
status = "PRESENT"
value = supplied
source_ref = f"OPERAND:{operand_id}"
value_type = "DECIMAL"
row_unit = unit_id
row_currency = currency
if status not in {"PRESENT", "MISSING", "CONFLICT"}:
raise CalculationError("OPERAND_STATUS_INVALID")
if status != "PRESENT":
value = None
normalized = format(_decimal(value), "f") if status == "PRESENT" and value_type == "DECIMAL" else value
return {
"operand_id": operand_id,
"source_ref": str(source_ref),
"status": status,
"value_type": value_type,
"value": normalized,
"unit_id": row_unit,
"currency": row_currency,
"value_sha256": _digest(normalized) if status == "PRESENT" else None,
}
def _law_value_uses(
law_value_ids: Sequence[str], law_values: Mapping[str, Mapping[str, Any]]
) -> tuple[list[dict[str, Any]], list[str]]:
rows: list[dict[str, Any]] = []
missing: list[str] = []
for law_value_id in law_value_ids:
source = law_values.get(law_value_id)
if not isinstance(source, Mapping) or source.get("approval_status") != "APPROVED":
missing.append(law_value_id)
continue
rows.append(
{
"law_value_id": law_value_id,
"authority_id": source["authority_id"],
"authority_release_sha256": _sha256(
source.get("authority_release_sha256"), "AUTHORITY_RELEASE_SHA256_INVALID"
),
"law_value_release_sha256": _sha256(
source.get("law_value_release_sha256"), "LAW_VALUE_RELEASE_SHA256_INVALID"
),
"effective_interval": dict(source["effective_interval"]),
"value": format(_decimal(source["value"]), "f"),
"unit_id": source["unit_id"],
"approval_status": "APPROVED",
}
)
return rows, missing
def execute_formula(
calculator: Mapping[str, Any],
operands: Mapping[str, Any],
law_values: Mapping[str, Mapping[str, Any]],
*,
run_binding_digest: str,
atomic_claim_id: str,
claim_group_id: str,
activation_row_id: str,
descriptor_sha256: str,
) -> dict[str, Any]:
"""Execute one admitted formula and emit every required receipt field."""
run_binding_digest = _sha256(run_binding_digest, "RUN_BINDING_DIGEST_INVALID")
descriptor_sha256 = _sha256(descriptor_sha256, "DESCRIPTOR_SHA256_INVALID")
calculator_id = calculator.get("calculator_id")
if not isinstance(calculator_id, str) or CALCULATOR_ID.fullmatch(calculator_id) is None:
raise CalculationError("CALCULATOR_ID_INVALID")
formula_id = calculator.get("formula_id")
if not isinstance(formula_id, str) or not formula_id:
raise CalculationError("FORMULA_ID_REQUIRED")
required = calculator.get("input_operand_ids", calculator.get("required_operands", []))
if not isinstance(required, list) or not required or not all(
isinstance(item, str) and item for item in required
):
raise CalculationError("FORMULA_OPERANDS_INVALID")
output_metric_id = calculator.get("output_metric_id")
output_unit_id = calculator.get("output_unit_id", calculator.get("unit"))
if not isinstance(output_metric_id, str) or not output_metric_id:
raise CalculationError("OUTPUT_METRIC_ID_REQUIRED")
if not isinstance(output_unit_id, str) or not output_unit_id:
raise CalculationError("OUTPUT_UNIT_ID_REQUIRED")
currency = calculator.get("currency")
rounding_rule = calculator.get("rounding_rule")
effective_interval = calculator.get("effective_interval")
if not isinstance(rounding_rule, Mapping) or rounding_rule.get("mode") not in ROUNDING_MODES:
raise CalculationError("ROUNDING_RULE_INVALID")
if not isinstance(effective_interval, Mapping):
raise CalculationError("EFFECTIVE_INTERVAL_REQUIRED")
formula_scope = {key: value for key, value in calculator.items() if key != "formula_sha256"}
formula_sha256 = calculator.get("formula_sha256") or _digest(formula_scope)
formula_sha256 = _sha256(formula_sha256, "FORMULA_SHA256_INVALID")
operand_rows = [
_operand_row(operand_id, operands.get(operand_id), output_unit_id, currency)
for operand_id in required
]
missing = sorted(
row["operand_id"] for row in operand_rows if row["status"] != "PRESENT"
)
law_value_ids = calculator.get("law_value_ids", [])
if not isinstance(law_value_ids, list):
raise CalculationError("LAW_VALUE_IDS_INVALID")
law_value_uses, missing_law_values = _law_value_uses(law_value_ids, law_values)
issue_codes: list[str] = []
calculation_status = "CALCULATED"
if missing:
calculation_status = "MISSING_OPERAND"
issue_codes.append("CALCULATION_OPERAND_MISSING")
elif missing_law_values:
calculation_status = "LAW_VALUE_GAP"
issue_codes.extend(f"CALCULATION_LAW_VALUE_UNRESOLVED:{item}" for item in missing_law_values)
result: dict[str, Any] | None = None
result_sha256: str | None = None
if calculation_status == "CALCULATED":
operator = calculator.get("operator")
if operator not in OPERATORS:
raise CalculationError("UNSUPPORTED_FORMULA_OPERATOR")
values = [_decimal(operands[name]["value"] if isinstance(operands[name], Mapping) else operands[name]) for name in required]
if operator == "ADD":
computed = sum(values, Decimal("0"))
elif operator == "SUBTRACT":
computed = values[0] - sum(values[1:], Decimal("0"))
elif operator == "MULTIPLY":
computed = Decimal("1")
for value in values:
computed *= value
elif operator == "DIVIDE":
if len(values) != 2 or values[1] == 0:
raise CalculationError("INVALID_DIVISION")
computed = values[0] / values[1]
elif operator == "MIN":
computed = min(values)
else:
computed = max(values)
quantum = _decimal(rounding_rule["quantum"])
rounded = format(computed.quantize(quantum, rounding=ROUNDING_MODES[rounding_rule["mode"]]), "f")
result = {
"metric_id": output_metric_id,
"value": rounded,
"unit_id": output_unit_id,
"currency": currency,
}
result_sha256 = _digest(result)
identity = {
"run_binding_digest": run_binding_digest,
"atomic_claim_id": atomic_claim_id,
"claim_group_id": claim_group_id,
"calculator_id": calculator_id,
"formula_id": formula_id,
}
core = {
"schema_version": "stage2.calculation_receipt.v1",
"calculation_receipt_id": f"CR-{_digest(identity)[:24]}",
"run_binding_digest": run_binding_digest,
"atomic_claim_id": atomic_claim_id,
"claim_group_id": claim_group_id,
"calculator_id": calculator_id,
"activation_status": "ACTIVATED",
"calculation_status": calculation_status,
"activation_row_id": activation_row_id,
"descriptor_sha256": descriptor_sha256,
"formula_id": formula_id,
"formula_sha256": formula_sha256,
"operand_rows": operand_rows,
"operand_refs": sorted(required),
"units": sorted({row["unit_id"] for row in operand_rows if row["unit_id"]}),
"law_value_uses": law_value_uses,
"effective_interval": dict(effective_interval),
"rounding_rule": dict(rounding_rule),
"period_rows": [],
"missing_operands": missing,
"result": result,
"result_sha256": result_sha256,
"issue_codes": sorted(issue_codes),
}
return {**core, "receipt_sha256": _digest(core)}
@@ -0,0 +1,286 @@
#!/usr/bin/env python3
"""Safe Decimal interpreter that emits canonical S2_20 calculation receipts."""
from __future__ import annotations
from decimal import Decimal, InvalidOperation, ROUND_DOWN, ROUND_HALF_UP, ROUND_UP
import hashlib
import json
import re
from typing import Any, Mapping, Sequence
OPERATORS = frozenset({"ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "MIN", "MAX"})
ROUNDING_MODES = {
"ROUND_HALF_UP": ROUND_HALF_UP,
"ROUND_DOWN": ROUND_DOWN,
"ROUND_UP": ROUND_UP,
"TRUNCATE": ROUND_DOWN,
}
CALCULATOR_ID = re.compile(r"^CE-(?:0[1-9]|1[0-3]|R[1-4])$")
SHA256 = re.compile(r"^[a-f0-9]{64}$")
class CalculationError(ValueError):
"""Controlled calculator contract failure."""
def _decimal(value: Any) -> Decimal:
try:
return Decimal(str(value))
except (InvalidOperation, ValueError) as exc:
raise CalculationError("INVALID_DECIMAL_OPERAND") from exc
def _canonical(value: Any) -> bytes:
return (
json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n"
).encode("utf-8")
def _digest(value: Any) -> str:
return hashlib.sha256(_canonical(value)).hexdigest()
def _sha256(value: Any, code: str) -> str:
if not isinstance(value, str) or SHA256.fullmatch(value) is None:
raise CalculationError(code)
return value
def activate_calculators(
signature: Mapping[str, Any],
requested_metrics: Sequence[str],
activation_rows: Sequence[Mapping[str, Any]],
) -> list[dict[str, Any]]:
"""Evaluate the closed activation registry without a default branch."""
rows: list[dict[str, Any]] = []
for rule in sorted(
activation_rows,
key=lambda row: (str(row.get("calculator_id")), str(row.get("activation_row_id"))),
):
calculator_id = rule.get("calculator_id")
allowed_metrics = rule.get("requested_metrics", [])
predicates = rule.get("equals", {})
if (
not isinstance(calculator_id, str)
or CALCULATOR_ID.fullmatch(calculator_id) is None
or not isinstance(allowed_metrics, list)
or not isinstance(predicates, Mapping)
or not predicates
):
raise CalculationError("INVALID_ACTIVATION_ROW")
metric_match = bool(set(requested_metrics) & set(allowed_metrics))
predicate_match = all(signature.get(key, "UNKNOWN") == value for key, value in predicates.items())
rows.append(
{
"calculator_id": calculator_id,
"activation_row_id": rule.get("activation_row_id"),
"activation_status": "ACTIVATED" if metric_match and predicate_match else "NOT_APPLICABLE",
}
)
return rows
def _operand_row(operand_id: str, supplied: Any, unit_id: str, currency: str | None) -> dict[str, Any]:
if supplied is None:
return {
"operand_id": operand_id,
"source_ref": f"OPERAND:{operand_id}",
"status": "MISSING",
"value_type": "DECIMAL",
"value": None,
"unit_id": unit_id,
"currency": currency,
"value_sha256": None,
}
if isinstance(supplied, Mapping):
status = supplied.get("status", "PRESENT")
value = supplied.get("value")
source_ref = supplied.get("source_ref", f"OPERAND:{operand_id}")
value_type = supplied.get("value_type", "DECIMAL")
row_unit = supplied.get("unit_id", unit_id)
row_currency = supplied.get("currency", currency)
else:
status = "PRESENT"
value = supplied
source_ref = f"OPERAND:{operand_id}"
value_type = "DECIMAL"
row_unit = unit_id
row_currency = currency
if status not in {"PRESENT", "MISSING", "CONFLICT"}:
raise CalculationError("OPERAND_STATUS_INVALID")
if status != "PRESENT":
value = None
normalized = format(_decimal(value), "f") if status == "PRESENT" and value_type == "DECIMAL" else value
return {
"operand_id": operand_id,
"source_ref": str(source_ref),
"status": status,
"value_type": value_type,
"value": normalized,
"unit_id": row_unit,
"currency": row_currency,
"value_sha256": _digest(normalized) if status == "PRESENT" else None,
}
def _law_value_uses(
law_value_ids: Sequence[str], law_values: Mapping[str, Mapping[str, Any]]
) -> tuple[list[dict[str, Any]], list[str]]:
rows: list[dict[str, Any]] = []
missing: list[str] = []
for law_value_id in law_value_ids:
source = law_values.get(law_value_id)
if not isinstance(source, Mapping) or source.get("approval_status") != "APPROVED":
missing.append(law_value_id)
continue
rows.append(
{
"law_value_id": law_value_id,
"authority_id": source["authority_id"],
"authority_release_sha256": _sha256(
source.get("authority_release_sha256"), "AUTHORITY_RELEASE_SHA256_INVALID"
),
"law_value_release_sha256": _sha256(
source.get("law_value_release_sha256"), "LAW_VALUE_RELEASE_SHA256_INVALID"
),
"effective_interval": dict(source["effective_interval"]),
"value": format(_decimal(source["value"]), "f"),
"unit_id": source["unit_id"],
"approval_status": "APPROVED",
}
)
return rows, missing
def execute_formula(
calculator: Mapping[str, Any],
operands: Mapping[str, Any],
law_values: Mapping[str, Mapping[str, Any]],
*,
run_binding_digest: str,
atomic_claim_id: str,
claim_group_id: str,
activation_row_id: str,
descriptor_sha256: str,
) -> dict[str, Any]:
"""Execute one admitted formula and emit every required receipt field."""
run_binding_digest = _sha256(run_binding_digest, "RUN_BINDING_DIGEST_INVALID")
descriptor_sha256 = _sha256(descriptor_sha256, "DESCRIPTOR_SHA256_INVALID")
calculator_id = calculator.get("calculator_id")
if not isinstance(calculator_id, str) or CALCULATOR_ID.fullmatch(calculator_id) is None:
raise CalculationError("CALCULATOR_ID_INVALID")
formula_id = calculator.get("formula_id")
if not isinstance(formula_id, str) or not formula_id:
raise CalculationError("FORMULA_ID_REQUIRED")
required = calculator.get("input_operand_ids", calculator.get("required_operands", []))
if not isinstance(required, list) or not required or not all(
isinstance(item, str) and item for item in required
):
raise CalculationError("FORMULA_OPERANDS_INVALID")
output_metric_id = calculator.get("output_metric_id")
output_unit_id = calculator.get("output_unit_id", calculator.get("unit"))
if not isinstance(output_metric_id, str) or not output_metric_id:
raise CalculationError("OUTPUT_METRIC_ID_REQUIRED")
if not isinstance(output_unit_id, str) or not output_unit_id:
raise CalculationError("OUTPUT_UNIT_ID_REQUIRED")
currency = calculator.get("currency")
rounding_rule = calculator.get("rounding_rule")
effective_interval = calculator.get("effective_interval")
if not isinstance(rounding_rule, Mapping) or rounding_rule.get("mode") not in ROUNDING_MODES:
raise CalculationError("ROUNDING_RULE_INVALID")
if not isinstance(effective_interval, Mapping):
raise CalculationError("EFFECTIVE_INTERVAL_REQUIRED")
formula_scope = {key: value for key, value in calculator.items() if key != "formula_sha256"}
formula_sha256 = calculator.get("formula_sha256") or _digest(formula_scope)
formula_sha256 = _sha256(formula_sha256, "FORMULA_SHA256_INVALID")
operand_rows = [
_operand_row(operand_id, operands.get(operand_id), output_unit_id, currency)
for operand_id in required
]
missing = sorted(
row["operand_id"] for row in operand_rows if row["status"] != "PRESENT"
)
law_value_ids = calculator.get("law_value_ids", [])
if not isinstance(law_value_ids, list):
raise CalculationError("LAW_VALUE_IDS_INVALID")
law_value_uses, missing_law_values = _law_value_uses(law_value_ids, law_values)
issue_codes: list[str] = []
calculation_status = "CALCULATED"
if missing:
calculation_status = "MISSING_OPERAND"
issue_codes.append("CALCULATION_OPERAND_MISSING")
elif missing_law_values:
calculation_status = "LAW_VALUE_GAP"
issue_codes.extend(f"CALCULATION_LAW_VALUE_UNRESOLVED:{item}" for item in missing_law_values)
result: dict[str, Any] | None = None
result_sha256: str | None = None
if calculation_status == "CALCULATED":
operator = calculator.get("operator")
if operator not in OPERATORS:
raise CalculationError("UNSUPPORTED_FORMULA_OPERATOR")
values = [_decimal(operands[name]["value"] if isinstance(operands[name], Mapping) else operands[name]) for name in required]
if operator == "ADD":
computed = sum(values, Decimal("0"))
elif operator == "SUBTRACT":
computed = values[0] - sum(values[1:], Decimal("0"))
elif operator == "MULTIPLY":
computed = Decimal("1")
for value in values:
computed *= value
elif operator == "DIVIDE":
if len(values) != 2 or values[1] == 0:
raise CalculationError("INVALID_DIVISION")
computed = values[0] / values[1]
elif operator == "MIN":
computed = min(values)
else:
computed = max(values)
quantum = _decimal(rounding_rule["quantum"])
rounded = format(computed.quantize(quantum, rounding=ROUNDING_MODES[rounding_rule["mode"]]), "f")
result = {
"metric_id": output_metric_id,
"value": rounded,
"unit_id": output_unit_id,
"currency": currency,
}
result_sha256 = _digest(result)
identity = {
"run_binding_digest": run_binding_digest,
"atomic_claim_id": atomic_claim_id,
"claim_group_id": claim_group_id,
"calculator_id": calculator_id,
"formula_id": formula_id,
}
core = {
"schema_version": "stage2.calculation_receipt.v1",
"calculation_receipt_id": f"CR-{_digest(identity)[:24]}",
"run_binding_digest": run_binding_digest,
"atomic_claim_id": atomic_claim_id,
"claim_group_id": claim_group_id,
"calculator_id": calculator_id,
"activation_status": "ACTIVATED",
"calculation_status": calculation_status,
"activation_row_id": activation_row_id,
"descriptor_sha256": descriptor_sha256,
"formula_id": formula_id,
"formula_sha256": formula_sha256,
"operand_rows": operand_rows,
"operand_refs": sorted(required),
"units": sorted({row["unit_id"] for row in operand_rows if row["unit_id"]}),
"law_value_uses": law_value_uses,
"effective_interval": dict(effective_interval),
"rounding_rule": dict(rounding_rule),
"period_rows": [],
"missing_operands": missing,
"result": result,
"result_sha256": result_sha256,
"issue_codes": sorted(issue_codes),
}
return {**core, "receipt_sha256": _digest(core)}
@@ -149,7 +149,7 @@ _RAW_VALUE_UNSET = object()
# literal placeholders in the offline parity mirror and its unit tests. # literal placeholders in the offline parity mirror and its unit tests.
INLINE_USER_HASH = "{{__user_hash__}}" INLINE_USER_HASH = "{{__user_hash__}}"
INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}" INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}"
EXPECTED_STAGE2_RELEASE_SHA256 = "0f21af3ddca538d9b6a5853dac23222c0b632d0e573de371a8de2709e691699d" EXPECTED_STAGE2_RELEASE_SHA256 = "70ef317cc0c557e44619b6cd6b4ad567e02e73271a36a0bbc93b748ae3f34f92"
INLINE_REQUEST_PATH = "stage2_control/s2_00_request.json" INLINE_REQUEST_PATH = "stage2_control/s2_00_request.json"
INLINE_STAGE2_ASSET_ROOT = "Default_Agent/Stage_2_Clean" INLINE_STAGE2_ASSET_ROOT = "Default_Agent/Stage_2_Clean"
INLINE_STAGE2_RELEASE_PATH = ( INLINE_STAGE2_RELEASE_PATH = (

Some files were not shown because too many files have changed in this diff Show More