feat(stage2): run S2_00 through inline MCP

Replace the unresolved host-loader invocation with one hash-bound Code Executor task so deterministic ingress has a concrete Agent execution path.\n\nBREAKING CHANGE: S2_00 no longer invokes stage2_loader.py. The legacy loader binding is reference-only and cannot authorize or provide fallback.
This commit is contained in:
2026-08-30 16:37:43 +09:00
parent 388a6c0179
commit 1b7d2d3a09
30 changed files with 21903 additions and 711 deletions
@@ -0,0 +1,89 @@
schema_version: stage2_code_executor_binding.v1
binding_id: S2-BINDING-S2_00-CODE-EXECUTOR-V1
workflow_id: S2_00
execution_class: NON-LLM-DETERMINISTIC
active_runtime_authority: true
agent_script_ref:
asset_id: AGENT-S2_00-INLINE
path: agent_scripts/Stage_2_S2_00.yml
sha256: 2e0bf36786a64d74070f8cc97dfde05e9d17c7d7bef3a5b1e60aecdb0accc71d
schema_id: liti_agent_yaml.v1
binding_status: BOUND
workflow_contract_ref:
asset_id: WF-S2_00
path: workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml
sha256: 74f8844963952ca853286662e46ab4c7b24c5785faf521c0557548778c446cea
schema_id: stage2_workflow_contract.v1.1
binding_status: BOUND
inline_code_receipt_ref:
asset_id: RECEIPT-S2_00-INLINE-CODE
path: manifest/s2_00_inline_code_receipt.json
sha256: ce82890b543315f1dc8a0793c68e35c19e6975e56f90c97715136462a1b72ecb
schema_id: stage2_s2_00_inline_code_receipt.v1
binding_status: BOUND
stage2_release_ref:
asset_id: RELEASE-STAGE2-CLEAN
path: manifest/stage2_release.json
sha256: 5c892cce3e686dea27c249b1585f86e44b60eb2cda074740d0d8c391095655e2
schema_id: stage2_release.v1
binding_status: BOUND
expected_release_sha256: 5c892cce3e686dea27c249b1585f86e44b60eb2cda074740d0d8c391095655e2
agent_script_sha256: 2e0bf36786a64d74070f8cc97dfde05e9d17c7d7bef3a5b1e60aecdb0accc71d
canonical_code_sha256: 269d775690beb806a1e922b71909448b1f11a10f344e6a2d064295bf80ae1c10
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_00_request.json
read_path_allowlist:
- stage2_control/s2_00_request.json
- Default_Agent/Stage_2_Clean/manifest/stage2_release.json
- Default_Agent/Stage_2_Clean/manifest/module_manifest.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/review_status.schema.json
- Default_Agent/Stage_2_Clean/<release-bound-stage2-direct-path>
- <stage1_run_root_ref>/<release-bound-stage1-source-path>
- <stage1_deployment_root_ref>/<release-bound-stage1-dependency-path>
- stage2_runs/by-binding/<run_binding_digest>/<published-artifact-path>
write_root_rule: stage2_runs/by-binding/<run_binding_digest>/
egress_profile_id: S2_00_LOCALDOCS_ONLY_V1
egress_profile_status: PENDING_LIVE_VERIFICATION
downstream_llm_candidate_bindings:
- workflow_id: S2_10
provider: openai
model: gpt-5.6-sol
reasoning_effort: ultra
binding_status: CANDIDATE_PENDING_BENCHMARK_AND_LEGAL_REVIEW
runtime_activation_allowed: false
required_admission_evidence:
- PHASE4_REPRESENTATIVE_BENCHMARK_PASS
- KOREAN_LAWYER_BLIND_REVIEW_PASS
- SIGNED_RELEASE_BINDING
live_admission_status: PENDING_SECRET_BINDING
legacy_fallbacks: []
@@ -1,119 +1,18 @@
{ schema_version: stage2_loader_binding.reference.v1
"schema_version": "stage2_loader_binding.v1", binding_id: S2-BINDING-S2_00-V1
"binding_id": "S2-BINDING-S2_00-V1", workflow_id: S2_00
"workflow_id": "S2_00", disposition: REFERENCE_ONLY_SUPERSEDED_FOR_S2_00
"execution_class": "NON-LLM-DETERMINISTIC", active_runtime_authority: false
"workflow_ref": { invocation_allowed: false
"asset_id": "WF-S2_00", fallback_allowed: false
"path": "workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml", superseded_by:
"sha256": "f554db71899dbe21009628275cdcea763bfa654ca5537c1f03605a5381ef417b", asset_id: BINDING-S2_00-CODE-EXECUTOR
"schema_id": "stage2_workflow_contract.v1", path: deployment/stage2_code_executor_binding.yml
"binding_status": "BOUND" schema_id: stage2_code_executor_binding.v1
}, binding_status: EXTERNAL_TRUST_ROOT_PENDING_LIVE_ADMISSION
"loader_ref": { retained_legacy_refs:
"asset_id": "LOADER-STAGE2", - release_ops/stage2_loader.py
"path": "release_ops/stage2_loader.py", - release_ops/stage2_loader.txt
"sha256": "bd961b79117240bfb2985fa71e84d24cabfd66fb4eabd55b03f80d6ce11698d2", - runtime/s2_00_ingress.py
"schema_id": null, - runtime/s2_00_ingress.txt
"binding_status": "BOUND" reason_code: O-06_SUPERSEDED_NOT_APPLICABLE_BY_DIRECT_MCP_CODE_EXECUTOR
},
"runtime_ref": {
"asset_id": "RUNTIME-S2_00",
"path": "runtime/s2_00_ingress.py",
"sha256": "3abbc90b23b9ab7893addffc30302c36483d256e105712508f7f5e901a5f9f2e",
"schema_id": null,
"binding_status": "BOUND"
},
"schema_refs": [
{
"asset_id": "SCHEMA-INGRESS",
"path": "schemas/ingress.schema.json",
"sha256": "b0d77e9833ec498e1c633cea7c7dca0ab8e171e30e18dc27bf6774f3975559a6",
"schema_id": "https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json",
"binding_status": "BOUND"
},
{
"asset_id": "SCHEMA-CONTEXT",
"path": "schemas/context.schema.json",
"sha256": "378a7b4e0b8bc3315deb83bd58d2f20db830b82e22c685224b4f02c80f6923b9",
"schema_id": "https://schemas.liti-agent.local/stage2/s2_00/context.schema.v1.json",
"binding_status": "BOUND"
},
{
"asset_id": "SCHEMA-DEPLOYMENT",
"path": "schemas/deployment.schema.json",
"sha256": "9ca010e4c1e42ea6150fc1caa8ec33b4b98224d1b947e1e51925b0766325c73f",
"schema_id": "https://schemas.liti-agent.local/stage2/shared/deployment.schema.v1.json",
"binding_status": "BOUND"
},
{
"asset_id": "SCHEMA-REVIEW-STATUS",
"path": "schemas/review_status.schema.json",
"sha256": "edcdd127e648c6b045abb852146a63f19936d300a350023b8987700afa05fde7",
"schema_id": "https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json",
"binding_status": "BOUND"
}
],
"module_manifest_ref": {
"asset_id": "MANIFEST-MODULE",
"path": "manifest/module_manifest.json",
"sha256": "PENDING_SEQUENTIAL_BIND",
"schema_id": "stage2_module_manifest.v1",
"binding_status": "PENDING_SEQUENTIAL_BIND"
},
"stage2_release_ref": {
"asset_id": "MANIFEST-STAGE2-RELEASE",
"path": "manifest/stage2_release.json",
"sha256": "PENDING_SEQUENTIAL_BIND",
"schema_id": "stage2_release.v1",
"binding_status": "PENDING_SEQUENTIAL_BIND"
},
"fixed_argv_contract": {
"executable_source": "sys.executable",
"runtime_entrypoint": "runtime/s2_00_ingress.py",
"allowed_flags": [
"--workflow-id",
"--release-ref",
"--run-id",
"--attempt-id",
"--user-context-sha256",
"--workspace-context-sha256",
"--stage1-run-root-ref",
"--stage1-deployment-root-ref"
],
"positional_argument_count": 0,
"shell": false,
"arbitrary_command_allowed": false,
"arbitrary_path_allowed": false
},
"workspace_root_policy": {
"authoring_root_source": "loader_file_parent_parent",
"resolved_root_must_equal_loader_parent": true,
"symlink_escape_allowed": false,
"runtime_output_root_argument_allowed": false,
"user_workspace_hashes_required": true
},
"authorization_policy": {
"skip_confirm_owned_by_host": true,
"loader_bypass_allowed": false,
"canary_production_signed_admission_required": true
},
"downstream_llm_candidate_bindings": [
{
"workflow_id": "S2_10",
"provider": "openai",
"model": "gpt-5.6-sol",
"reasoning_effort": "ultra",
"binding_status": "CANDIDATE_PENDING_BENCHMARK_AND_LEGAL_REVIEW",
"runtime_activation_allowed": false,
"required_admission_evidence": [
"PHASE4_REPRESENTATIVE_BENCHMARK_PASS",
"KOREAN_LAWYER_BLIND_REVIEW_PASS",
"SIGNED_RELEASE_BINDING"
]
}
],
"invocation_status": "OPEN_EXTERNAL_BACKEND",
"legacy_fallbacks": [],
"external_network_access_allowed": false
}
@@ -1,9 +1,9 @@
{ {
"schema_version": "stage2_module_manifest.v1", "schema_version": "stage2_module_manifest.v1",
"manifest_id": "STAGE2-CLEAN-S2_00-SHARED-DRAFT-V1", "manifest_id": "STAGE2-CLEAN-S2_00-SHARED-DRAFT-V1-INLINE",
"manifest_scope": "S2_00_AND_SHARED_HANDOFF_DRAFT", "manifest_scope": "S2_00_AND_SHARED_HANDOFF_DRAFT",
"manifest_status": "DEV_HASH_BOUND_PENDING_CROSS_AUDIT", "manifest_status": "DEV_HASH_BOUND_INLINE_PENDING_LIVE_ADMISSION",
"manifest_digest": "7aa491d3e053e8dba9325b0ed06ea1c9e5e9a9f3c82f4b4340a04bd8b8c944ba", "manifest_digest": "de7a70dae9773a8c3b348c6cd8861f858ce10d9438c66b8ce209a3c34ce8deda",
"manifest_digest_contract": { "manifest_digest_contract": {
"algorithm_id": "STAGE2-MODULE-MANIFEST-DIGEST-V1", "algorithm_id": "STAGE2-MODULE-MANIFEST-DIGEST-V1",
"digest_algorithm": "sha256", "digest_algorithm": "sha256",
@@ -24,7 +24,7 @@
}, },
{ {
"code": "LEGACY-STAGE2-LOADER", "code": "LEGACY-STAGE2-LOADER",
"meaning": "Only the canonical Stage_2_Clean loader and binding may cross the host trust boundary.", "meaning": "The historical host loader and loader binding are reference-only and cannot authorize, execute, or provide fallback for S2_00.",
"legacy_runtime_dependency_allowed": false "legacy_runtime_dependency_allowed": false
}, },
{ {
@@ -62,7 +62,6 @@
"produced_schema_ids": [], "produced_schema_ids": [],
"authority_ids": [], "authority_ids": [],
"dependency_module_ids": [ "dependency_module_ids": [
"RUNTIME-S2_00",
"SCHEMA-INGRESS", "SCHEMA-INGRESS",
"SCHEMA-CONTEXT", "SCHEMA-CONTEXT",
"SCHEMA-REVIEW-STATUS" "SCHEMA-REVIEW-STATUS"
@@ -72,10 +71,10 @@
"LEGACY-STAGE2-V0-V3" "LEGACY-STAGE2-V0-V3"
], ],
"path": "workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml", "path": "workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml",
"sha256": "f554db71899dbe21009628275cdcea763bfa654ca5537c1f03605a5381ef417b", "sha256": "74f8844963952ca853286662e46ab4c7b24c5785faf521c0557548778c446cea",
"schema_version": "stage2_workflow_contract.v1", "schema_version": "stage2_workflow_contract.v1",
"asset_version": "s2_00.1", "asset_version": "s2_00.1.1",
"implementation_status": "DEV_HASH_BOUND", "implementation_status": "IMPLEMENTED_DECLARATIVE_CONTRACT",
"semantic_review_status": "PENDING_CROSS_AUDIT", "semantic_review_status": "PENDING_CROSS_AUDIT",
"owner": "Stage_2_workflow_maintainer", "owner": "Stage_2_workflow_maintainer",
"inputs": [ "inputs": [
@@ -87,48 +86,6 @@
"S2_00-DIAGNOSTIC-BRANCH" "S2_00-DIAGNOSTIC-BRANCH"
] ]
}, },
{
"module_id": "RUNTIME-S2_00",
"module_kind": "FIXED_RUNTIME",
"scope_predicate": "workflow_id == S2_00",
"consumed_schema_ids": [
"https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json",
"https://schemas.liti-agent.local/stage2/s2_00/context.schema.v1.json",
"https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json"
],
"produced_schema_ids": [
"stage2_s2_00_stage1_input_manifest.v1",
"stage2_s2_00_intake_report.v1",
"stage2_s2_00_ingress_status.v1",
"stage2_s2_00_context.v1",
"stage2_issue_ledger_base.v1"
],
"authority_ids": [],
"dependency_module_ids": [
"SCHEMA-INGRESS",
"SCHEMA-CONTEXT",
"SCHEMA-REVIEW-STATUS"
],
"incompatible_module_ids": [],
"forbidden_contract_codes": [
"LEGACY-STAGE2-V0-V3"
],
"path": "runtime/s2_00_ingress.py",
"sha256": "3abbc90b23b9ab7893addffc30302c36483d256e105712508f7f5e901a5f9f2e",
"schema_version": "fixed_python_runtime.v1",
"asset_version": "s2_00.runtime.1",
"implementation_status": "DEV_HASH_BOUND",
"semantic_review_status": "PENDING_CROSS_AUDIT",
"owner": "Stage_2_runtime_maintainer",
"inputs": [
"STAGE1-ALLOWLIST-V1",
"STAGE2-RELEASE-V1"
],
"outputs": [
"S2_00-NORMAL-BRANCH",
"S2_00-DIAGNOSTIC-BRANCH"
]
},
{ {
"module_id": "SCHEMA-INGRESS", "module_id": "SCHEMA-INGRESS",
"module_kind": "JSON_SCHEMA", "module_kind": "JSON_SCHEMA",
@@ -141,9 +98,9 @@
"dependency_module_ids": [], "dependency_module_ids": [],
"incompatible_module_ids": [], "incompatible_module_ids": [],
"path": "schemas/ingress.schema.json", "path": "schemas/ingress.schema.json",
"sha256": "b0d77e9833ec498e1c633cea7c7dca0ab8e171e30e18dc27bf6774f3975559a6", "sha256": "8fd7b76015b7d7dfbbe056e08999dda7ea8e1012bb16cec50634b08f7ea97302",
"schema_version": "stage2_s2_00_ingress.v1", "schema_version": "stage2_s2_00_ingress.v1",
"asset_version": "s2_00.schema.1", "asset_version": "s2_00.schema.1.1",
"implementation_status": "DEV_HASH_BOUND", "implementation_status": "DEV_HASH_BOUND",
"semantic_review_status": "PENDING_CROSS_AUDIT", "semantic_review_status": "PENDING_CROSS_AUDIT",
"owner": "Stage_2_schema_owner", "owner": "Stage_2_schema_owner",
@@ -191,9 +148,9 @@
"dependency_module_ids": [], "dependency_module_ids": [],
"incompatible_module_ids": [], "incompatible_module_ids": [],
"path": "schemas/deployment.schema.json", "path": "schemas/deployment.schema.json",
"sha256": "9ca010e4c1e42ea6150fc1caa8ec33b4b98224d1b947e1e51925b0766325c73f", "sha256": "361f894e9ef91957b9c0613e88d0a31c2fb65ec40c8a0c1da46df006b3eca460",
"schema_version": "stage2_deployment.v1", "schema_version": "stage2_deployment.v1",
"asset_version": "stage2.shared.1", "asset_version": "stage2.shared.1.1",
"implementation_status": "DEV_HASH_BOUND", "implementation_status": "DEV_HASH_BOUND",
"semantic_review_status": "PENDING_CROSS_AUDIT", "semantic_review_status": "PENDING_CROSS_AUDIT",
"owner": "Stage_2_deployment_schema_owner", "owner": "Stage_2_deployment_schema_owner",
@@ -225,73 +182,6 @@
"REVIEW-STATUS-SCHEMA-DEFS" "REVIEW-STATUS-SCHEMA-DEFS"
] ]
}, },
{
"module_id": "LOADER-STAGE2",
"module_kind": "HOST_TRUST_BOUNDARY",
"scope_predicate": "workflow_id == S2_00",
"consumed_schema_ids": [
"https://schemas.liti-agent.local/stage2/shared/deployment.schema.v1.json"
],
"produced_schema_ids": [
"stage2_loader_receipt.v1"
],
"authority_ids": [],
"dependency_module_ids": [
"BINDING-S2_00",
"RUNTIME-S2_00",
"SCHEMA-DEPLOYMENT"
],
"incompatible_module_ids": [],
"forbidden_contract_codes": [
"LEGACY-STAGE2-LOADER"
],
"path": "release_ops/stage2_loader.py",
"sha256": "bd961b79117240bfb2985fa71e84d24cabfd66fb4eabd55b03f80d6ce11698d2",
"schema_version": "stage2_loader.v1",
"asset_version": "stage2.loader.1",
"implementation_status": "DEV_HASH_BOUND",
"semantic_review_status": "PENDING_CROSS_AUDIT",
"owner": "Stage_2_loader_owner",
"inputs": [
"STAGE2-RELEASE-V1",
"BINDING-S2_00"
],
"outputs": [
"STAGE2-LOADER-RECEIPT"
]
},
{
"module_id": "BINDING-S2_00",
"module_kind": "DEPLOYMENT_BINDING",
"scope_predicate": "workflow_id == S2_00",
"consumed_schema_ids": [
"https://schemas.liti-agent.local/stage2/shared/deployment.schema.v1.json"
],
"produced_schema_ids": [],
"authority_ids": [],
"dependency_module_ids": [
"WF-S2_00",
"RUNTIME-S2_00",
"SCHEMA-DEPLOYMENT"
],
"incompatible_module_ids": [],
"forbidden_contract_codes": [
"LEGACY-STAGE2-LOADER"
],
"path": "deployment/stage2_loader_binding.yml",
"sha256": "d740f73274f39c5196c48e2bd3760ccd2347eadf8c59938fbe84a9f56ccb16f1",
"schema_version": "stage2_loader_binding.v1",
"asset_version": "stage2.binding.1",
"implementation_status": "DEV_HASH_BOUND_WITH_RELEASE_ORACLE_REFS_DEFERRED",
"semantic_review_status": "PENDING_CROSS_AUDIT",
"owner": "Stage_2_loader_owner",
"inputs": [
"STAGE2-RELEASE-V1"
],
"outputs": [
"FIXED-ARGV-BINDING"
]
},
{ {
"module_id": "CACHE-POLICY-STATIC-PREFIX", "module_id": "CACHE-POLICY-STATIC-PREFIX",
"module_kind": "CACHE_POLICY", "module_kind": "CACHE_POLICY",
@@ -302,8 +192,7 @@
"dependency_module_ids": [ "dependency_module_ids": [
"P00", "P00",
"P10", "P10",
"SCHEMA-CONTEXT", "SCHEMA-CONTEXT"
"BINDING-S2_00"
], ],
"incompatible_module_ids": [], "incompatible_module_ids": [],
"path": "registry/cache/prompt_cache_policy.yml", "path": "registry/cache/prompt_cache_policy.yml",
@@ -334,9 +223,9 @@
"dependency_module_ids": [], "dependency_module_ids": [],
"incompatible_module_ids": [], "incompatible_module_ids": [],
"path": "tests/fixtures/regression_manifest.json", "path": "tests/fixtures/regression_manifest.json",
"sha256": "7dc2b23309537f3f71dac0774f86cf918fed82fcbbc89b2f38399488e31f8043", "sha256": "d367ad04364c3881bfdc48ac1b4ccf36c2a5a68b213d7e95d8874d17887aad40",
"schema_version": "stage2_s2_00_regression_manifest.v1", "schema_version": "stage2_s2_00_regression_manifest.v1",
"asset_version": "s2_00.test.1", "asset_version": "s2_00.test.1.1",
"implementation_status": "DEV_HASH_BOUND", "implementation_status": "DEV_HASH_BOUND",
"semantic_review_status": "PENDING_CROSS_AUDIT", "semantic_review_status": "PENDING_CROSS_AUDIT",
"owner": "Stage_2_regression_owner", "owner": "Stage_2_regression_owner",
@@ -359,7 +248,6 @@
], ],
"authority_ids": [], "authority_ids": [],
"dependency_module_ids": [ "dependency_module_ids": [
"BINDING-S2_00",
"CACHE-POLICY-STATIC-PREFIX", "CACHE-POLICY-STATIC-PREFIX",
"P00", "P00",
"P10", "P10",
@@ -371,9 +259,9 @@
"RAW-STAGE1-REREAD" "RAW-STAGE1-REREAD"
], ],
"path": "workflows/S2_10_domain_relief_resolution_map.yml", "path": "workflows/S2_10_domain_relief_resolution_map.yml",
"sha256": "e6d59ce93edb0c5854052e2d521a4c122cf9feda24d35e7344d101c2c29f4d26", "sha256": "fb181fedd5ceb1e5503203ef05dfc361c20ff101e050930c2648d95a4e8760da",
"schema_version": "stage2_workflow_contract.v1", "schema_version": "stage2_workflow_contract.v1",
"asset_version": "s2_10.1", "asset_version": "s2_10.1.1",
"implementation_status": "DRAFT_HANDOFF_STUB_HASH_BOUND", "implementation_status": "DRAFT_HANDOFF_STUB_HASH_BOUND",
"semantic_review_status": "PENDING_CROSS_AUDIT", "semantic_review_status": "PENDING_CROSS_AUDIT",
"owner": "Stage_2_S2_10_owner", "owner": "Stage_2_S2_10_owner",
@@ -432,12 +320,10 @@
"consumed_schema_ids": [], "consumed_schema_ids": [],
"produced_schema_ids": [], "produced_schema_ids": [],
"authority_ids": [], "authority_ids": [],
"dependency_module_ids": [ "dependency_module_ids": [],
"RUNTIME-S2_00"
],
"incompatible_module_ids": [], "incompatible_module_ids": [],
"path": "tests/s2_00/test_resolver_source_lock.py", "path": "tests/s2_00/test_resolver_source_lock.py",
"sha256": "235e05985fb4b574c59cc44ff1cc803f4ec064d7f0fdb7fcf8c694e93d445fe0", "sha256": "51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e",
"schema_version": "pytest.v1", "schema_version": "pytest.v1",
"asset_version": "s2_00.test.1", "asset_version": "s2_00.test.1",
"implementation_status": "DEV_HASH_BOUND", "implementation_status": "DEV_HASH_BOUND",
@@ -457,9 +343,7 @@
"consumed_schema_ids": [], "consumed_schema_ids": [],
"produced_schema_ids": [], "produced_schema_ids": [],
"authority_ids": [], "authority_ids": [],
"dependency_module_ids": [ "dependency_module_ids": [],
"RUNTIME-S2_00"
],
"incompatible_module_ids": [], "incompatible_module_ids": [],
"path": "tests/s2_00/test_schema_hash_and_signals.py", "path": "tests/s2_00/test_schema_hash_and_signals.py",
"sha256": "71a9a15e5910d99c8e8e7b8b2f607b41244b3fd83a8c6e07d03bc0a0b986193c", "sha256": "71a9a15e5910d99c8e8e7b8b2f607b41244b3fd83a8c6e07d03bc0a0b986193c",
@@ -482,9 +366,7 @@
"consumed_schema_ids": [], "consumed_schema_ids": [],
"produced_schema_ids": [], "produced_schema_ids": [],
"authority_ids": [], "authority_ids": [],
"dependency_module_ids": [ "dependency_module_ids": [],
"RUNTIME-S2_00"
],
"incompatible_module_ids": [], "incompatible_module_ids": [],
"path": "tests/s2_00/test_conservation.py", "path": "tests/s2_00/test_conservation.py",
"sha256": "c906dff7e11678a60556818d1baf24e66844d9c982c9d333ec339d2ed9ca6061", "sha256": "c906dff7e11678a60556818d1baf24e66844d9c982c9d333ec339d2ed9ca6061",
@@ -507,9 +389,7 @@
"consumed_schema_ids": [], "consumed_schema_ids": [],
"produced_schema_ids": [], "produced_schema_ids": [],
"authority_ids": [], "authority_ids": [],
"dependency_module_ids": [ "dependency_module_ids": [],
"RUNTIME-S2_00"
],
"incompatible_module_ids": [], "incompatible_module_ids": [],
"path": "tests/s2_00/test_canonical_ids.py", "path": "tests/s2_00/test_canonical_ids.py",
"sha256": "c463506a90859daeef7eafddc4a6c08c563e2ae73200d921c1f00efb7bc24361", "sha256": "c463506a90859daeef7eafddc4a6c08c563e2ae73200d921c1f00efb7bc24361",
@@ -532,12 +412,10 @@
"consumed_schema_ids": [], "consumed_schema_ids": [],
"produced_schema_ids": [], "produced_schema_ids": [],
"authority_ids": [], "authority_ids": [],
"dependency_module_ids": [ "dependency_module_ids": [],
"RUNTIME-S2_00"
],
"incompatible_module_ids": [], "incompatible_module_ids": [],
"path": "tests/s2_00/test_cluster_bundle_compile.py", "path": "tests/s2_00/test_cluster_bundle_compile.py",
"sha256": "8e37dda051562b4c1a3fc595a1678fc7758742f89b19cfe8f9d5a0b342dfa5d1", "sha256": "c2b01c8d39be31d43b11f13a9901db036ef967337a388a4b85d951fbb4f51efe",
"schema_version": "pytest.v1", "schema_version": "pytest.v1",
"asset_version": "s2_00.test.1", "asset_version": "s2_00.test.1",
"implementation_status": "DEV_HASH_BOUND", "implementation_status": "DEV_HASH_BOUND",
@@ -557,12 +435,10 @@
"consumed_schema_ids": [], "consumed_schema_ids": [],
"produced_schema_ids": [], "produced_schema_ids": [],
"authority_ids": [], "authority_ids": [],
"dependency_module_ids": [ "dependency_module_ids": [],
"RUNTIME-S2_00"
],
"incompatible_module_ids": [], "incompatible_module_ids": [],
"path": "tests/s2_00/test_failure_and_atomic_publish.py", "path": "tests/s2_00/test_failure_and_atomic_publish.py",
"sha256": "bb7879a23c207bba304cae1eefe89a8f0b7b9263787c80c3fbcea523300f0fb8", "sha256": "4bc5060ce95ec884c1193f16e8348d095c1b1a89181b0455ad809b2bb05cfb0c",
"schema_version": "pytest.v1", "schema_version": "pytest.v1",
"asset_version": "s2_00.test.1", "asset_version": "s2_00.test.1",
"implementation_status": "DEV_HASH_BOUND", "implementation_status": "DEV_HASH_BOUND",
@@ -1790,22 +1666,82 @@
"outputs": [ "outputs": [
"ACTIVE_PROFILE_CONTEXT" "ACTIVE_PROFILE_CONTEXT"
] ]
},
{
"module_id": "BUILD-S2_00-INLINE-PROJECTION",
"module_kind": "BUILD_TOOL",
"scope_predicate": "build_target == S2_00_INLINE_AGENT",
"consumed_schema_ids": [
"https://schemas.liti-agent.local/stage2/shared/deployment.schema.v1.json"
],
"produced_schema_ids": [
"stage2_s2_00_inline_code_receipt.v1"
],
"authority_ids": [],
"dependency_module_ids": [
"SCHEMA-DEPLOYMENT"
],
"incompatible_module_ids": [],
"forbidden_contract_codes": [
"LEGACY-STAGE2-V0-V3"
],
"path": "offline_build/build_s2_00_inline_projection.py",
"sha256": "930f058f99e76b63b2c4fc8921892e40bfdcca7df51c2cb0a6aff34d721c0e10",
"schema_version": "offline_projection_builder.v1",
"asset_version": "s2_00.build.1",
"implementation_status": "DEV_HASH_BOUND_OFFLINE_ONLY",
"semantic_review_status": "PENDING_CROSS_AUDIT",
"owner": "Stage_2_release_build_owner",
"inputs": [
"AUTHORING-AGENT-YAML"
],
"outputs": [
"DEPLOYMENT-AGENT-PROJECTION",
"FULL-CODE-MIRRORS",
"INLINE-CODE-RECEIPT"
]
},
{
"module_id": "TEST-S2_00-INLINE-CODE-PARITY",
"module_kind": "TEST",
"scope_predicate": "test_axis == inline_code_parity",
"consumed_schema_ids": [
"https://schemas.liti-agent.local/stage2/shared/deployment.schema.v1.json"
],
"produced_schema_ids": [],
"authority_ids": [],
"dependency_module_ids": [
"BUILD-S2_00-INLINE-PROJECTION",
"SCHEMA-DEPLOYMENT",
"WF-S2_00"
],
"incompatible_module_ids": [],
"forbidden_contract_codes": [
"LEGACY-STAGE2-V0-V3"
],
"path": "tests/s2_00/test_inline_code_parity.py",
"sha256": "6a03a8e67661c5599925c0fa01b4a79602d4b745936f783d5b68617ec2c4633e",
"schema_version": "pytest.v1",
"asset_version": "s2_00.test.1",
"implementation_status": "DEV_HASH_BOUND",
"semantic_review_status": "PENDING_CROSS_AUDIT",
"owner": "Stage_2_test_owner",
"inputs": [
"AUTHORING-AGENT-YAML",
"DEPLOYMENT-AGENT-PROJECTION",
"FULL-CODE-MIRRORS"
],
"outputs": [
"TEST-RECEIPT"
]
} }
], ],
"documentation_mirrors": [ "documentation_mirrors": [
{ {
"source_path": "release_ops/stage2_loader.py", "source_path": "offline_build/build_s2_00_inline_projection.py",
"mirror_path": "release_ops/stage2_loader.txt", "mirror_path": "offline_build/build_s2_00_inline_projection.txt",
"source_sha256": "bd961b79117240bfb2985fa71e84d24cabfd66fb4eabd55b03f80d6ce11698d2", "source_sha256": "930f058f99e76b63b2c4fc8921892e40bfdcca7df51c2cb0a6aff34d721c0e10",
"mirror_sha256": "bd961b79117240bfb2985fa71e84d24cabfd66fb4eabd55b03f80d6ce11698d2", "mirror_sha256": "930f058f99e76b63b2c4fc8921892e40bfdcca7df51c2cb0a6aff34d721c0e10",
"byte_identical": true,
"runtime_import_allowed": false
},
{
"source_path": "runtime/s2_00_ingress.py",
"mirror_path": "runtime/s2_00_ingress.txt",
"source_sha256": "3abbc90b23b9ab7893addffc30302c36483d256e105712508f7f5e901a5f9f2e",
"mirror_sha256": "3abbc90b23b9ab7893addffc30302c36483d256e105712508f7f5e901a5f9f2e",
"byte_identical": true, "byte_identical": true,
"runtime_import_allowed": false "runtime_import_allowed": false
}, },
@@ -1820,8 +1756,8 @@
{ {
"source_path": "tests/s2_00/test_cluster_bundle_compile.py", "source_path": "tests/s2_00/test_cluster_bundle_compile.py",
"mirror_path": "tests/s2_00/test_cluster_bundle_compile.txt", "mirror_path": "tests/s2_00/test_cluster_bundle_compile.txt",
"source_sha256": "8e37dda051562b4c1a3fc595a1678fc7758742f89b19cfe8f9d5a0b342dfa5d1", "source_sha256": "c2b01c8d39be31d43b11f13a9901db036ef967337a388a4b85d951fbb4f51efe",
"mirror_sha256": "8e37dda051562b4c1a3fc595a1678fc7758742f89b19cfe8f9d5a0b342dfa5d1", "mirror_sha256": "c2b01c8d39be31d43b11f13a9901db036ef967337a388a4b85d951fbb4f51efe",
"byte_identical": true, "byte_identical": true,
"runtime_import_allowed": false "runtime_import_allowed": false
}, },
@@ -1836,16 +1772,24 @@
{ {
"source_path": "tests/s2_00/test_failure_and_atomic_publish.py", "source_path": "tests/s2_00/test_failure_and_atomic_publish.py",
"mirror_path": "tests/s2_00/test_failure_and_atomic_publish.txt", "mirror_path": "tests/s2_00/test_failure_and_atomic_publish.txt",
"source_sha256": "bb7879a23c207bba304cae1eefe89a8f0b7b9263787c80c3fbcea523300f0fb8", "source_sha256": "4bc5060ce95ec884c1193f16e8348d095c1b1a89181b0455ad809b2bb05cfb0c",
"mirror_sha256": "bb7879a23c207bba304cae1eefe89a8f0b7b9263787c80c3fbcea523300f0fb8", "mirror_sha256": "4bc5060ce95ec884c1193f16e8348d095c1b1a89181b0455ad809b2bb05cfb0c",
"byte_identical": true,
"runtime_import_allowed": false
},
{
"source_path": "tests/s2_00/test_inline_code_parity.py",
"mirror_path": "tests/s2_00/test_inline_code_parity.txt",
"source_sha256": "6a03a8e67661c5599925c0fa01b4a79602d4b745936f783d5b68617ec2c4633e",
"mirror_sha256": "6a03a8e67661c5599925c0fa01b4a79602d4b745936f783d5b68617ec2c4633e",
"byte_identical": true, "byte_identical": true,
"runtime_import_allowed": false "runtime_import_allowed": false
}, },
{ {
"source_path": "tests/s2_00/test_resolver_source_lock.py", "source_path": "tests/s2_00/test_resolver_source_lock.py",
"mirror_path": "tests/s2_00/test_resolver_source_lock.txt", "mirror_path": "tests/s2_00/test_resolver_source_lock.txt",
"source_sha256": "235e05985fb4b574c59cc44ff1cc803f4ec064d7f0fdb7fcf8c694e93d445fe0", "source_sha256": "51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e",
"mirror_sha256": "235e05985fb4b574c59cc44ff1cc803f4ec064d7f0fdb7fcf8c694e93d445fe0", "mirror_sha256": "51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e",
"byte_identical": true, "byte_identical": true,
"runtime_import_allowed": false "runtime_import_allowed": false
}, },
@@ -1859,14 +1803,19 @@
} }
], ],
"closure_summary": { "closure_summary": {
"module_count": 65, "module_count": 64,
"prompt_module_count": 2, "prompt_module_count": 2,
"profile_module_count": 45, "profile_module_count": 45,
"test_module_count": 6, "test_module_count": 7,
"documentation_mirror_count": 8, "documentation_mirror_count": 8,
"fixture_closure_ref": "tests/fixtures/regression_manifest.json", "fixture_closure_ref": "tests/fixtures/regression_manifest.json",
"fixture_descriptor_count": 60, "fixture_descriptor_count": 60,
"self_hash_included": false, "self_hash_included": false,
"stage2_release_hash_included": false "stage2_release_hash_included": false,
"build_tool_module_count": 1,
"runtime_code_hash_included": false,
"executable_agent_hash_included": false,
"executor_binding_hash_included": false,
"cycle_breaking_contract": "AGENT_CODE_RECEIPT_AND_EXECUTOR_BINDING_EXTERNALLY_BIND_RELEASE_RAW_HASH"
} }
} }
@@ -0,0 +1 @@
{"authoring":{"path":"Stage_2_S2_00_v.1.yml","sha256":"2e0bf36786a64d74070f8cc97dfde05e9d17c7d7bef3a5b1e60aecdb0accc71d","size_bytes":362391,"unique_key_parse":"PASS"},"authoring_rewritten":false,"build_kind":"OFFLINE_AUTHORING_PROJECTION","canonical_code":{"ast_status":"PASS","code_sha256":"269d775690beb806a1e922b71909448b1f11a10f344e6a2d064295bf80ae1c10","code_size_bytes":280045,"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":"93f79ac6acae086471beb3f3cf60c8bb1538f29748fee96cad0c9d33d178a85a","path":"Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml","sha256":"2e0bf36786a64d74070f8cc97dfde05e9d17c7d7bef3a5b1e60aecdb0accc71d","size_bytes":362391},"full_code_mirrors":[{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.py","sha256":"269d775690beb806a1e922b71909448b1f11a10f344e6a2d064295bf80ae1c10","size_bytes":280045},{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.txt","sha256":"269d775690beb806a1e922b71909448b1f11a10f344e6a2d064295bf80ae1c10","size_bytes":280045}],"parity_status":"PASS","schema_version":"stage2_s2_00_inline_code_receipt.v1","source_of_truth":"Stage_2_S2_00_v.1.yml","task_contract":{"agent":{"name":"Stage_2_S2_00_v1","version":"1.1.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":"269d775690beb806a1e922b71909448b1f11a10f344e6a2d064295bf80ae1c10","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,24 +1,24 @@
{ {
"schema_version": "stage2_release.v1", "schema_version": "stage2_release.v1",
"release_id": "STAGE2-CLEAN-DEV-DRAFT-2026-08-30", "release_id": "STAGE2-CLEAN-DEV-DRAFT-INLINE-S2_00-2026-08-30",
"release_class": "DEV_FIXTURE_RELEASE", "release_class": "DEV_FIXTURE_RELEASE",
"release_status": "DRAFT_NOT_EXECUTABLE", "release_status": "DRAFT_NOT_EXECUTABLE",
"authorization_status": "DEV_VALIDATION_ONLY", "authorization_status": "DEV_VALIDATION_ONLY",
"release_digest": "49ff3967f8eaa9c2291af6d0c17af1da2504296f03a020a84d1ea21c5954a2f0", "release_digest": "fb88cc08ba7e32f9d12fe74411bf666df71b9e6e43e85ace897db1fba1dfe8af",
"signature": "PENDING_SEQUENTIAL_BIND", "signature": "PENDING_SEQUENTIAL_BIND",
"authoring_root": "Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean", "authoring_root": "Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean",
"module_manifest_ref": { "module_manifest_ref": {
"asset_id": "MANIFEST-MODULE", "asset_id": "MANIFEST-MODULE",
"path": "manifest/module_manifest.json", "path": "manifest/module_manifest.json",
"sha256": "45841ecb5d05399974cd11751bb42ac95ad0285c914f5b7545e4bc97eb86a4ad", "sha256": "5c18affa5bdcbca7df28f5f00d9b93c977f604e213bfc5fdf403f46f607c2321",
"schema_id": "stage2_module_manifest.v1", "schema_id": "stage2_module_manifest.v1",
"binding_status": "BOUND" "binding_status": "BOUND"
}, },
"loader_binding_ref": { "loader_binding_ref": {
"asset_id": "BINDING-S2_00", "asset_id": "BINDING-S2_00-LEGACY-REFERENCE",
"path": "deployment/stage2_loader_binding.yml", "path": "deployment/stage2_loader_binding.yml",
"sha256": "d740f73274f39c5196c48e2bd3760ccd2347eadf8c59938fbe84a9f56ccb16f1", "sha256": "61b2f85a319103e8c915f13dd642c75c7b7cf2d89575c8fe493d8ee074a8508b",
"schema_id": "stage2_loader_binding.v1", "schema_id": "stage2_loader_binding.reference.v1",
"binding_status": "BOUND" "binding_status": "BOUND"
}, },
"dependency_locks": { "dependency_locks": {
@@ -473,12 +473,6 @@
"path": null, "path": null,
"sha256": null "sha256": null
}, },
"completion_seal_ref": {
"status": "PENDING_SEQUENTIAL_BIND",
"path": "PENDING_SEQUENTIAL_BIND",
"sha256": "PENDING_SEQUENTIAL_BIND",
"producer_id": "PENDING_SEQUENTIAL_BIND"
},
"closure_scope": "REFERENCED_55_ONLY_NOT_FULL_STAGE1_RUNTIME_RELEASE", "closure_scope": "REFERENCED_55_ONLY_NOT_FULL_STAGE1_RUNTIME_RELEASE",
"full_stage1_runtime_release_status": "STAGE1_NOT_RELEASE_READY" "full_stage1_runtime_release_status": "STAGE1_NOT_RELEASE_READY"
}, },
@@ -1359,18 +1353,6 @@
"bidirectional_match_allowed": true, "bidirectional_match_allowed": true,
"global_alias_allowed": false "global_alias_allowed": false
} }
},
{
"adapter_id": "S2A-SNAPSHOT-SEAL-V1",
"adapter_kind": "SNAPSHOT_SEAL",
"contract_status": "PENDING_SEQUENTIAL_BIND",
"schema_ref": "schemas/ingress.schema.json#/$defs/source_contract_row",
"decision": {
"completion_seal_path": "PENDING_SEQUENTIAL_BIND",
"producer_id": "PENDING_SEQUENTIAL_BIND",
"one_read_same_descriptor_required": true,
"pre_post_seal_compare_required": true
}
} }
], ],
"retry_policies": [ "retry_policies": [
@@ -1399,20 +1381,14 @@
{ {
"evidence_id": "DEV-DRAFT-UNSIGNED-001", "evidence_id": "DEV-DRAFT-UNSIGNED-001",
"release_class": "DEV_FIXTURE_RELEASE", "release_class": "DEV_FIXTURE_RELEASE",
"scope": "HASH_BOUND_STRUCTURAL_VALIDATION_ONLY", "scope": "INLINE_CODE_EXECUTOR_OFFLINE_HASH_BOUND_VALIDATION_ONLY",
"signer_id": "UNSIGNED_DRAFT", "signer_id": "UNSIGNED_DRAFT",
"input_digest": "660fde446a46832300e8580fa05d3e27312f57a5943a16748fbdad98e6e86cb0", "input_digest": "5c18affa5bdcbca7df28f5f00d9b93c977f604e213bfc5fdf403f46f607c2321",
"signature": "PENDING_SEQUENTIAL_BIND", "signature": "PENDING_SEQUENTIAL_BIND",
"status": "PENDING_SEQUENTIAL_BIND" "status": "PENDING_SEQUENTIAL_BIND"
} }
], ],
"open_items": [ "open_items": [
{
"open_id": "O-06",
"status": "OPEN_EXTERNAL_BACKEND",
"owner": "AgentBackend_owner",
"required_evidence": "native external .py loader invocation receipt proving loader-only fixed argv"
},
{ {
"open_id": "O-07", "open_id": "O-07",
"status": "OPEN_RELEASE_AUTHORIZATION", "status": "OPEN_RELEASE_AUTHORIZATION",
@@ -1420,16 +1396,52 @@
"required_evidence": "signed canary or production admission with current Stage 1 integrity closure" "required_evidence": "signed canary or production admission with current Stage 1 integrity closure"
}, },
{ {
"open_id": "SNAPSHOT-SEAL-BIND", "open_id": "CEG-02-DIRECT-MCP-LIVE",
"status": "PENDING_SEQUENTIAL_BIND", "status": "OPEN_EXTERNAL_BACKEND",
"owner": "Stage_1_contract_owner", "owner": "AgentBackend_owner",
"required_evidence": "exact completion seal path, producer and raw SHA-256" "required_evidence": "live code-executor.run_code outer result and inner single-JSON receipt with exact Agent/code/release binding"
},
{
"open_id": "CEG-03-SECRET-INJECTION",
"status": "OPEN_EXTERNAL_BACKEND",
"owner": "AgentBackend_owner",
"required_evidence": "backend-injected or pre-registered Code Executor authentication with no plaintext credential in YAML or code"
},
{
"open_id": "CEG-04-RUNTIME-IMAGE-PIN",
"status": "OPEN_EXTERNAL_BACKEND",
"owner": "Code_Executor_owner",
"required_evidence": "verified Python runtime image digest compatible with the bound httpx dependency"
},
{
"open_id": "CEG-05-REQUEST-SIZE-TIMEOUT",
"status": "OPEN_EXTERNAL_BACKEND",
"owner": "Code_Executor_owner",
"required_evidence": "representative S2_00 Agent request accepted and completed within backend request-size and 300-second limits"
},
{
"open_id": "CEG-06-BINARY-LOCALDOCS",
"status": "OPEN_EXTERNAL_BACKEND",
"owner": "localdocs_owner",
"required_evidence": "live read_binary_doc and write_binary_file byte-preservation receipt over the approved path set"
},
{
"open_id": "CEG-07-ISOLATION-EGRESS",
"status": "OPEN_EXTERNAL_BACKEND",
"owner": "AgentBackend_security_owner",
"required_evidence": "workspace identity substitution and backend-enforced S2_00_LOCALDOCS_ONLY_V1 egress verification"
},
{
"open_id": "CEG-08-BARRIER-ROUTE",
"status": "OPEN_EXTERNAL_BACKEND",
"owner": "Stage_2_integration_owner",
"required_evidence": "live status-last logical publish and exactly-one downstream route receipt"
}, },
{ {
"open_id": "DEV-DETACHED-RELEASE-ENVELOPE", "open_id": "DEV-DETACHED-RELEASE-ENVELOPE",
"status": "OPEN_RELEASE_AUTHORIZATION", "status": "OPEN_RELEASE_AUTHORIZATION",
"owner": "release_operator", "owner": "release_operator",
"required_evidence": "detached signed envelope closes binding-to-release and release admission without a cross-file hash cycle" "required_evidence": "detached signed envelope admits the release and executor binding without a cross-file hash cycle"
}, },
{ {
"open_id": "DOWNSTREAM-CASE-TYPE-REGISTRY", "open_id": "DOWNSTREAM-CASE-TYPE-REGISTRY",
@@ -1461,7 +1473,7 @@
"expected_prefix_sha256": "3634cb6929cce8395683048eabb068ed63aed0427869b19ce4b56c586ab48071", "expected_prefix_sha256": "3634cb6929cce8395683048eabb068ed63aed0427869b19ce4b56c586ab48071",
"cache_key_contract": { "cache_key_contract": {
"policy_id": "S2-CACHE-STATIC-PREFIX-V1", "policy_id": "S2-CACHE-STATIC-PREFIX-V1",
"model_binding_ref": "deployment/stage2_loader_binding.yml#/downstream_llm_candidate_bindings/0", "model_binding_ref": "deployment/stage2_code_executor_binding.yml#/downstream_llm_candidate_bindings/0",
"model_id": "gpt-5.6-sol", "model_id": "gpt-5.6-sol",
"reasoning_effort": "ultra", "reasoning_effort": "ultra",
"prompt_contract_version": "stage2.prompt_contract.v1", "prompt_contract_version": "stage2.prompt_contract.v1",
@@ -1476,7 +1488,8 @@
"reason_codes": [ "reason_codes": [
"STRUCTURAL_FIXTURE_NOT_EXECUTABLE", "STRUCTURAL_FIXTURE_NOT_EXECUTABLE",
"AUTHORITY_RELEASE_UNAVAILABLE", "AUTHORITY_RELEASE_UNAVAILABLE",
"PROMPT_AND_PROFILE_LEGAL_REVIEW_PENDING" "PROMPT_AND_PROFILE_LEGAL_REVIEW_PENDING",
"DIRECT_MCP_LIVE_ADMISSION_PENDING"
] ]
}, },
"stage1_sources": [ "stage1_sources": [
@@ -1783,5 +1796,11 @@
"transaction_identity_pointer": null, "transaction_identity_pointer": null,
"raw_hash_source": "MANIFEST_ROW" "raw_hash_source": "MANIFEST_ROW"
} }
] ],
"executor_binding_ref": {
"asset_id": "BINDING-S2_00-CODE-EXECUTOR",
"path": "deployment/stage2_code_executor_binding.yml",
"schema_id": "stage2_code_executor_binding.v1",
"binding_status": "EXTERNAL_TRUST_ROOT_PENDING_LIVE_ADMISSION"
}
} }
@@ -0,0 +1,751 @@
#!/usr/bin/env python3
"""Build the version-free S2_00 Agent projection from its sole authoring YAML.
This is an offline build tool. It never executes a matter, imports project
runtime code, rewrites the authoring YAML, or invokes a subprocess. The YAML
parser-returned ``parameters.code`` string is encoded directly as UTF-8; no
dedent, newline normalization, or source transformation is permitted.
"""
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 - exercised only on an incomplete 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_00_v.1.yml"
PROJECTION_PATH = DEPLOYMENT_ROOT / "agent_scripts" / "Stage_2_S2_00.yml"
MIRROR_PY_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.py"
MIRROR_TXT_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.txt"
RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_00_inline_code_receipt.json"
EXPECTED_TASK_NAME = "Task_S2_00_deterministic_ingress"
EXPECTED_AGENT_NAME = "Stage_2_S2_00_v1"
EXPECTED_AGENT_VERSION = "1.1.0"
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"
REQUIRED_CODE_TOKENS = (
EXPECTED_LOCALDOCS_URL,
"{{__user_hash__}}",
"{{__workspace_hash__}}",
"read_binary_doc",
"write_binary_file",
)
REQUIRED_CODE_TOKEN_ALTERNATIVES = (
("expected_stage2_release_sha256", "EXPECTED_STAGE2_RELEASE_SHA256"),
)
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"})
FORBIDDEN_ATTRIBUTE_CALLS = frozenset(
{
("os", "popen"),
("os", "spawnl"),
("os", "spawnle"),
("os", "spawnlp"),
("os", "spawnlpe"),
("os", "spawnv"),
("os", "spawnve"),
("os", "spawnvp"),
("os", "spawnvpe"),
("os", "system"),
}
)
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*['\"][^'\"]+['\"]"
),
)
URL_RE = re.compile(r"https?://[^\s'\"]+")
PYTHON_SOURCE_REF_RE = re.compile(r"(?i)(?:^|[/\\])[^\r\n'\"]+\.py(?:$|[?#])")
ALLOWED_IDENTIFIER_URL_PREFIXES = ("https://schemas.liti-agent.local/",)
HTTP_NETWORK_METHODS = frozenset({"delete", "get", "head", "options", "patch", "post", "put", "request", "stream"})
class ProjectionError(RuntimeError):
"""A 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
class AuthoringMissingError(ProjectionError):
def __init__(self, path: Path) -> None:
super().__init__("AUTHORING_YAML_MISSING", path.as_posix())
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)
location = f" line {mark.line + 1}" if mark is not None else ""
raise ProjectionError("YAML_DUPLICATE_KEY", f"{key!r}{location}")
result[key] = self.construct_object(value_node, deep=deep)
return result
else: # pragma: no cover - type placeholder for hosts without PyYAML
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 parse_authoring_bytes(raw: bytes, *, source: str = "<authoring>") -> dict[str, Any]:
if yaml is None:
raise ProjectionError("PYYAML_REQUIRED", "install PyYAML on the 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:
loaded = 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(loaded, dict):
raise ProjectionError("AUTHORING_ROOT_OBJECT_REQUIRED", source)
return loaded
def load_authoring(path: Path | None = None) -> tuple[bytes, dict[str, Any]]:
path = AUTHORING_PATH if path is None else path
if not path.is_file():
raise AuthoringMissingError(path)
if path.is_symlink():
raise ProjectionError("AUTHORING_SYMLINK_FORBIDDEN", path.as_posix())
raw = path.read_bytes()
return raw, parse_authoring_bytes(raw, source=path.as_posix())
def _require_mapping(value: Any, code: str) -> dict[str, Any]:
if not isinstance(value, dict):
raise ProjectionError(code, repr(value)[:200])
return value
def _require_list(value: Any, code: str) -> list[Any]:
if not isinstance(value, list):
raise ProjectionError(code, repr(value)[:200])
return value
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}",
)
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") != "S2_00":
raise ProjectionError("S2_00_STAGE_NAME_REQUIRED", repr(stage.get("name")))
if "skip_confirm" in stage:
raise ProjectionError(
"SKIP_CONFIRM_HOST_POLICY_ONLY",
"skip_confirm belongs to the executor binding, not the authoring YAML",
)
for forbidden in ("llm_provider", "llm_model", "llm_reasoning", "llm_verbosity"):
if forbidden in stage:
raise ProjectionError("MODEL_FIELD_FORBIDDEN", forbidden)
servers = _require_mapping(
_require_mapping(stage.get("tools"), "TOOLS_OBJECT_REQUIRED").get("mcpServers"),
"MCP_SERVERS_OBJECT_REQUIRED",
)
localdocs = _require_mapping(servers.get("localdocs"), "LOCALDOCS_SERVER_REQUIRED")
code_executor = _require_mapping(
servers.get("code-executor"), "CODE_EXECUTOR_SERVER_REQUIRED"
)
if localdocs.get("type") != "streamable-http" or localdocs.get("url") != EXPECTED_LOCALDOCS_URL:
raise ProjectionError("LOCALDOCS_SERVER_BINDING_INVALID", repr(localdocs))
if (
code_executor.get("type") != "streamable-http"
or code_executor.get("url") != EXPECTED_CODE_EXECUTOR_URL
):
raise ProjectionError("CODE_EXECUTOR_SERVER_BINDING_INVALID", repr(code_executor))
if "headers" in code_executor:
raise ProjectionError(
"PLAINTEXT_OR_INLINE_AUTH_HEADER_FORBIDDEN",
"authentication must be injected or pre-registered by the backend",
)
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 = [
row
for row in tasks
if isinstance(row, dict)
and row.get("mcp") == "code-executor"
and row.get("tool_name") == "run_code"
]
if len(run_code_tasks) != 1:
raise ProjectionError("EXACTLY_ONE_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")))
parameters = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")
expected_parameter_keys = set(EXPECTED_PARAMETERS) | {"code"}
if set(parameters) != expected_parameter_keys:
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)[:100])
if code.endswith(("\n", "\r")):
raise ProjectionError(
"INLINE_CODE_TRAILING_NEWLINE_FORBIDDEN",
"authoring YAML must use code: |- so parser-returned code has no trailing newline",
)
procedure = _require_mapping(stage.get("task_procedure"), "TASK_PROCEDURE_REQUIRED")
expected_procedure = {
"IN": {"nexts": [EXPECTED_TASK_NAME], "wait_until": []},
EXPECTED_TASK_NAME: {"nexts": ["OUT"], "wait_until": ["IN"]},
"OUT": {"nexts": [], "wait_until": [EXPECTED_TASK_NAME]},
}
if procedure != expected_procedure:
raise ProjectionError("TASK_PROCEDURE_MISMATCH", repr(procedure)[:500])
if stage.get("prevs") != [] or stage.get("nexts") != []:
raise ProjectionError("STANDALONE_STAGE_EDGES_MUST_BE_EMPTY", repr(stage))
return stage, task
def _import_root(name: str | None) -> str:
return (name or "").split(".", 1)[0]
def _attribute_pair(node: ast.Attribute) -> tuple[str, str] | None:
if isinstance(node.value, ast.Name):
return node.value.id, node.attr
return None
def _is_http_client_receiver(
node: ast.expr,
derived_client_names: set[str] | None = None,
) -> bool:
if isinstance(node, ast.Name):
return node.id in {"client", "http_client", "httpx"} | (derived_client_names or set())
if isinstance(node, ast.Attribute):
return (
isinstance(node.value, ast.Name)
and node.value.id == "self"
and node.attr in {"client", "http_client"}
)
return False
def _is_direct_localdocs_post(call: ast.Call) -> bool:
if not isinstance(call.func, ast.Attribute) or call.func.attr != "post":
return False
receiver = call.func.value
if not (
isinstance(receiver, ast.Attribute)
and isinstance(receiver.value, ast.Name)
and receiver.value.id == "self"
and receiver.attr == "client"
):
return False
return _is_localdocs_endpoint(_network_endpoint(call) or ast.Constant(value=None))
def _network_endpoint(call: ast.Call) -> ast.expr | None:
"""Return a statically identifiable httpx/client endpoint expression."""
if not isinstance(call.func, ast.Attribute) or call.func.attr not in HTTP_NETWORK_METHODS:
return None
if not _is_http_client_receiver(call.func.value):
return None
for keyword in call.keywords:
if keyword.arg == "url":
return keyword.value
index = 1 if call.func.attr == "request" else 0
return call.args[index] if len(call.args) > index else ast.Constant(value=None)
def _is_localdocs_endpoint(node: ast.expr) -> bool:
return (
isinstance(node, ast.Name)
and node.id == "LOCALDOCS_URL"
or isinstance(node, ast.Constant)
and node.value == EXPECTED_LOCALDOCS_URL
)
def validate_inline_code(code: str) -> dict[str, Any]:
code_bytes = code.encode("utf-8")
try:
compile(code, "<Stage_2_S2_00.parameters.code>", "exec", dont_inherit=True)
tree = ast.parse(code, filename="<Stage_2_S2_00.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]
missing_tokens.extend(
"|".join(alternatives)
for alternatives in REQUIRED_CODE_TOKEN_ALTERNATIVES
if not any(token in code for token in alternatives)
)
if missing_tokens:
raise ProjectionError("INLINE_CODE_REQUIRED_TOKEN_MISSING", ",".join(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()
forbidden_nodes: list[str] = []
external_urls: set[str] = set()
forbidden_network_endpoints: set[str] = set()
project_source_refs: set[str] = set()
derived_client_names: set[str] = set()
for candidate in ast.walk(tree):
if not isinstance(candidate, (ast.Assign, ast.AnnAssign)):
continue
value = candidate.value
if not (
isinstance(value, ast.Call)
and isinstance(value.func, ast.Attribute)
and isinstance(value.func.value, ast.Name)
and value.func.value.id == "httpx"
and value.func.attr in {"Client", "AsyncClient"}
):
continue
targets = candidate.targets if isinstance(candidate, ast.Assign) else [candidate.target]
derived_client_names.update(target.id for target in targets if isinstance(target, ast.Name))
for node in ast.walk(tree):
if isinstance(node, ast.Import):
imports.update(_import_root(alias.name) for alias in node.names)
elif isinstance(node, ast.ImportFrom):
if node.level:
forbidden_nodes.append(f"relative-import:{node.module or ''}")
imports.add(_import_root(node.module))
elif isinstance(node, ast.Pass):
forbidden_nodes.append("Pass")
elif isinstance(node, ast.Expr) and isinstance(node.value, ast.Constant):
if node.value.value is Ellipsis:
forbidden_nodes.append("Ellipsis-expression")
elif isinstance(node, (ast.Assign, ast.AnnAssign)):
if isinstance(node.value, ast.Constant) and node.value.value is Ellipsis:
forbidden_nodes.append("Ellipsis-assignment")
if (
isinstance(node.value, ast.Attribute)
and node.value.attr in HTTP_NETWORK_METHODS
and _is_http_client_receiver(node.value.value, derived_client_names)
):
forbidden_nodes.append(f"network-method-alias:{node.value.attr}")
elif isinstance(node, ast.Constant):
if isinstance(node.value, str):
for match in URL_RE.findall(node.value):
normalized = match.rstrip(".,);]")
if (
normalized != EXPECTED_LOCALDOCS_URL
and not normalized.startswith(ALLOWED_IDENTIFIER_URL_PREFIXES)
):
external_urls.add(normalized)
if PYTHON_SOURCE_REF_RE.search(node.value.strip()):
project_source_refs.add(node.value[:200])
if node.value.strip().lower() in {
"todo",
"tbd",
"placeholder",
"omitted",
"implement me",
"...",
}:
forbidden_nodes.append(f"placeholder-string:{node.value!r}")
elif isinstance(node, ast.Call):
if (
isinstance(node.func, ast.Attribute)
and node.func.attr in HTTP_NETWORK_METHODS
and _is_http_client_receiver(node.func.value, derived_client_names)
):
if not _is_direct_localdocs_post(node):
forbidden_network_endpoints.add(ast.unparse(node.func)[:200])
if (
isinstance(node.func, ast.Name)
and node.func.id == "getattr"
and len(node.args) >= 2
and isinstance(node.args[1], ast.Constant)
and node.args[1].value in HTTP_NETWORK_METHODS
):
forbidden_nodes.append(f"dynamic-network-method:{node.args[1].value}")
if isinstance(node.func, ast.Name) and node.func.id in FORBIDDEN_CALL_NAMES:
forbidden_nodes.append(f"call:{node.func.id}")
elif isinstance(node.func, ast.Attribute):
pair = _attribute_pair(node.func)
if pair in FORBIDDEN_ATTRIBUTE_CALLS:
forbidden_nodes.append(f"call:{pair[0]}.{pair[1]}")
elif isinstance(node, ast.Raise):
target = node.exc
if isinstance(target, ast.Call):
target = target.func
if isinstance(target, ast.Name) and target.id == "NotImplementedError":
forbidden_nodes.append("raise:NotImplementedError")
imports.discard("")
disallowed_imports = sorted(
root
for root in imports
if root in FORBIDDEN_IMPORT_ROOTS
or (root not in sys.stdlib_module_names and root not in ALLOWED_NON_STDLIB_IMPORTS)
)
if disallowed_imports:
raise ProjectionError("INLINE_CODE_IMPORT_FORBIDDEN", ",".join(disallowed_imports))
if forbidden_nodes:
raise ProjectionError("INLINE_CODE_DYNAMIC_OR_PLACEHOLDER_FORBIDDEN", ",".join(forbidden_nodes))
if external_urls:
raise ProjectionError("INLINE_CODE_EXTERNAL_URL_FORBIDDEN", ",".join(sorted(external_urls)))
if forbidden_network_endpoints:
raise ProjectionError(
"INLINE_CODE_NETWORK_ENDPOINT_FORBIDDEN",
",".join(sorted(forbidden_network_endpoints)),
)
if project_source_refs:
raise ProjectionError(
"INLINE_CODE_EXTERNAL_PY_SOURCE_REF_FORBIDDEN", ",".join(sorted(project_source_refs))
)
return {
"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_url_count": 0,
"placeholder_count": 0,
"plaintext_secret_count": 0,
"external_python_source_ref_count": 0,
}
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"),
},
"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 ("language", "requirements", "network", "timeout")
},
"code_sha256": sha256_bytes(parameters["code"].encode("utf-8")),
},
"task_procedure": stage.get("task_procedure"),
}
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)
semantics_sha256 = sha256_bytes(canonical_json_bytes(semantics))
receipt = {
"schema_version": "stage2_s2_00_inline_code_receipt.v1",
"workflow_id": "S2_00",
"build_kind": "OFFLINE_AUTHORING_PROJECTION",
"source_of_truth": _logical_path(AUTHORING_PATH),
"authoring_rewritten": False,
"authoring": {
"path": _logical_path(AUTHORING_PATH),
"sha256": sha256_bytes(authoring_raw),
"size_bytes": len(authoring_raw),
"unique_key_parse": "PASS",
},
"deployment_projection": {
"path": _logical_path(PROJECTION_PATH),
"sha256": sha256_bytes(authoring_raw),
"size_bytes": len(authoring_raw),
"byte_identical_to_authoring": True,
"canonical_task_semantics_sha256": semantics_sha256,
},
"canonical_code": {
"yaml_pointer": "/Agent/Stages/0/tasks/0/parameters/code",
"encoding": "UTF-8",
"extraction_transform": "NONE",
**validation,
},
"full_code_mirrors": [
{
"path": _logical_path(MIRROR_PY_PATH),
"sha256": validation["code_sha256"],
"size_bytes": len(code_bytes),
"byte_identical_to_canonical_code": True,
},
{
"path": _logical_path(MIRROR_TXT_PATH),
"sha256": validation["code_sha256"],
"size_bytes": len(code_bytes),
"byte_identical_to_canonical_code": True,
},
],
"task_contract": semantics,
"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:
continue
_atomic_write(path, payload)
after_artifacts = AUTHORING_PATH.read_bytes()
if after_artifacts != before:
raise ProjectionError(
"AUTHORING_CHANGED_DURING_BUILD",
f"before={sha256_bytes(before)} after={sha256_bytes(after_artifacts)}",
)
_atomic_write(RECEIPT_PATH, receipt_payload)
after_receipt = AUTHORING_PATH.read_bytes()
if after_receipt != before:
raise ProjectionError(
"AUTHORING_CHANGED_DURING_RECEIPT_WRITE",
f"before={sha256_bytes(before)} after={sha256_bytes(after_receipt)}",
)
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 the S2_00 inline Agent projection"
)
parser.add_argument(
"--check",
action="store_true",
help="perform a no-write byte-parity check against generated outputs",
)
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" 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,751 @@
#!/usr/bin/env python3
"""Build the version-free S2_00 Agent projection from its sole authoring YAML.
This is an offline build tool. It never executes a matter, imports project
runtime code, rewrites the authoring YAML, or invokes a subprocess. The YAML
parser-returned ``parameters.code`` string is encoded directly as UTF-8; no
dedent, newline normalization, or source transformation is permitted.
"""
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 - exercised only on an incomplete 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_00_v.1.yml"
PROJECTION_PATH = DEPLOYMENT_ROOT / "agent_scripts" / "Stage_2_S2_00.yml"
MIRROR_PY_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.py"
MIRROR_TXT_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_00_ingress.txt"
RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_00_inline_code_receipt.json"
EXPECTED_TASK_NAME = "Task_S2_00_deterministic_ingress"
EXPECTED_AGENT_NAME = "Stage_2_S2_00_v1"
EXPECTED_AGENT_VERSION = "1.1.0"
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"
REQUIRED_CODE_TOKENS = (
EXPECTED_LOCALDOCS_URL,
"{{__user_hash__}}",
"{{__workspace_hash__}}",
"read_binary_doc",
"write_binary_file",
)
REQUIRED_CODE_TOKEN_ALTERNATIVES = (
("expected_stage2_release_sha256", "EXPECTED_STAGE2_RELEASE_SHA256"),
)
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"})
FORBIDDEN_ATTRIBUTE_CALLS = frozenset(
{
("os", "popen"),
("os", "spawnl"),
("os", "spawnle"),
("os", "spawnlp"),
("os", "spawnlpe"),
("os", "spawnv"),
("os", "spawnve"),
("os", "spawnvp"),
("os", "spawnvpe"),
("os", "system"),
}
)
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*['\"][^'\"]+['\"]"
),
)
URL_RE = re.compile(r"https?://[^\s'\"]+")
PYTHON_SOURCE_REF_RE = re.compile(r"(?i)(?:^|[/\\])[^\r\n'\"]+\.py(?:$|[?#])")
ALLOWED_IDENTIFIER_URL_PREFIXES = ("https://schemas.liti-agent.local/",)
HTTP_NETWORK_METHODS = frozenset({"delete", "get", "head", "options", "patch", "post", "put", "request", "stream"})
class ProjectionError(RuntimeError):
"""A 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
class AuthoringMissingError(ProjectionError):
def __init__(self, path: Path) -> None:
super().__init__("AUTHORING_YAML_MISSING", path.as_posix())
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)
location = f" line {mark.line + 1}" if mark is not None else ""
raise ProjectionError("YAML_DUPLICATE_KEY", f"{key!r}{location}")
result[key] = self.construct_object(value_node, deep=deep)
return result
else: # pragma: no cover - type placeholder for hosts without PyYAML
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 parse_authoring_bytes(raw: bytes, *, source: str = "<authoring>") -> dict[str, Any]:
if yaml is None:
raise ProjectionError("PYYAML_REQUIRED", "install PyYAML on the 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:
loaded = 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(loaded, dict):
raise ProjectionError("AUTHORING_ROOT_OBJECT_REQUIRED", source)
return loaded
def load_authoring(path: Path | None = None) -> tuple[bytes, dict[str, Any]]:
path = AUTHORING_PATH if path is None else path
if not path.is_file():
raise AuthoringMissingError(path)
if path.is_symlink():
raise ProjectionError("AUTHORING_SYMLINK_FORBIDDEN", path.as_posix())
raw = path.read_bytes()
return raw, parse_authoring_bytes(raw, source=path.as_posix())
def _require_mapping(value: Any, code: str) -> dict[str, Any]:
if not isinstance(value, dict):
raise ProjectionError(code, repr(value)[:200])
return value
def _require_list(value: Any, code: str) -> list[Any]:
if not isinstance(value, list):
raise ProjectionError(code, repr(value)[:200])
return value
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}",
)
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") != "S2_00":
raise ProjectionError("S2_00_STAGE_NAME_REQUIRED", repr(stage.get("name")))
if "skip_confirm" in stage:
raise ProjectionError(
"SKIP_CONFIRM_HOST_POLICY_ONLY",
"skip_confirm belongs to the executor binding, not the authoring YAML",
)
for forbidden in ("llm_provider", "llm_model", "llm_reasoning", "llm_verbosity"):
if forbidden in stage:
raise ProjectionError("MODEL_FIELD_FORBIDDEN", forbidden)
servers = _require_mapping(
_require_mapping(stage.get("tools"), "TOOLS_OBJECT_REQUIRED").get("mcpServers"),
"MCP_SERVERS_OBJECT_REQUIRED",
)
localdocs = _require_mapping(servers.get("localdocs"), "LOCALDOCS_SERVER_REQUIRED")
code_executor = _require_mapping(
servers.get("code-executor"), "CODE_EXECUTOR_SERVER_REQUIRED"
)
if localdocs.get("type") != "streamable-http" or localdocs.get("url") != EXPECTED_LOCALDOCS_URL:
raise ProjectionError("LOCALDOCS_SERVER_BINDING_INVALID", repr(localdocs))
if (
code_executor.get("type") != "streamable-http"
or code_executor.get("url") != EXPECTED_CODE_EXECUTOR_URL
):
raise ProjectionError("CODE_EXECUTOR_SERVER_BINDING_INVALID", repr(code_executor))
if "headers" in code_executor:
raise ProjectionError(
"PLAINTEXT_OR_INLINE_AUTH_HEADER_FORBIDDEN",
"authentication must be injected or pre-registered by the backend",
)
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 = [
row
for row in tasks
if isinstance(row, dict)
and row.get("mcp") == "code-executor"
and row.get("tool_name") == "run_code"
]
if len(run_code_tasks) != 1:
raise ProjectionError("EXACTLY_ONE_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")))
parameters = _require_mapping(task.get("parameters"), "TASK_PARAMETERS_REQUIRED")
expected_parameter_keys = set(EXPECTED_PARAMETERS) | {"code"}
if set(parameters) != expected_parameter_keys:
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)[:100])
if code.endswith(("\n", "\r")):
raise ProjectionError(
"INLINE_CODE_TRAILING_NEWLINE_FORBIDDEN",
"authoring YAML must use code: |- so parser-returned code has no trailing newline",
)
procedure = _require_mapping(stage.get("task_procedure"), "TASK_PROCEDURE_REQUIRED")
expected_procedure = {
"IN": {"nexts": [EXPECTED_TASK_NAME], "wait_until": []},
EXPECTED_TASK_NAME: {"nexts": ["OUT"], "wait_until": ["IN"]},
"OUT": {"nexts": [], "wait_until": [EXPECTED_TASK_NAME]},
}
if procedure != expected_procedure:
raise ProjectionError("TASK_PROCEDURE_MISMATCH", repr(procedure)[:500])
if stage.get("prevs") != [] or stage.get("nexts") != []:
raise ProjectionError("STANDALONE_STAGE_EDGES_MUST_BE_EMPTY", repr(stage))
return stage, task
def _import_root(name: str | None) -> str:
return (name or "").split(".", 1)[0]
def _attribute_pair(node: ast.Attribute) -> tuple[str, str] | None:
if isinstance(node.value, ast.Name):
return node.value.id, node.attr
return None
def _is_http_client_receiver(
node: ast.expr,
derived_client_names: set[str] | None = None,
) -> bool:
if isinstance(node, ast.Name):
return node.id in {"client", "http_client", "httpx"} | (derived_client_names or set())
if isinstance(node, ast.Attribute):
return (
isinstance(node.value, ast.Name)
and node.value.id == "self"
and node.attr in {"client", "http_client"}
)
return False
def _is_direct_localdocs_post(call: ast.Call) -> bool:
if not isinstance(call.func, ast.Attribute) or call.func.attr != "post":
return False
receiver = call.func.value
if not (
isinstance(receiver, ast.Attribute)
and isinstance(receiver.value, ast.Name)
and receiver.value.id == "self"
and receiver.attr == "client"
):
return False
return _is_localdocs_endpoint(_network_endpoint(call) or ast.Constant(value=None))
def _network_endpoint(call: ast.Call) -> ast.expr | None:
"""Return a statically identifiable httpx/client endpoint expression."""
if not isinstance(call.func, ast.Attribute) or call.func.attr not in HTTP_NETWORK_METHODS:
return None
if not _is_http_client_receiver(call.func.value):
return None
for keyword in call.keywords:
if keyword.arg == "url":
return keyword.value
index = 1 if call.func.attr == "request" else 0
return call.args[index] if len(call.args) > index else ast.Constant(value=None)
def _is_localdocs_endpoint(node: ast.expr) -> bool:
return (
isinstance(node, ast.Name)
and node.id == "LOCALDOCS_URL"
or isinstance(node, ast.Constant)
and node.value == EXPECTED_LOCALDOCS_URL
)
def validate_inline_code(code: str) -> dict[str, Any]:
code_bytes = code.encode("utf-8")
try:
compile(code, "<Stage_2_S2_00.parameters.code>", "exec", dont_inherit=True)
tree = ast.parse(code, filename="<Stage_2_S2_00.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]
missing_tokens.extend(
"|".join(alternatives)
for alternatives in REQUIRED_CODE_TOKEN_ALTERNATIVES
if not any(token in code for token in alternatives)
)
if missing_tokens:
raise ProjectionError("INLINE_CODE_REQUIRED_TOKEN_MISSING", ",".join(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()
forbidden_nodes: list[str] = []
external_urls: set[str] = set()
forbidden_network_endpoints: set[str] = set()
project_source_refs: set[str] = set()
derived_client_names: set[str] = set()
for candidate in ast.walk(tree):
if not isinstance(candidate, (ast.Assign, ast.AnnAssign)):
continue
value = candidate.value
if not (
isinstance(value, ast.Call)
and isinstance(value.func, ast.Attribute)
and isinstance(value.func.value, ast.Name)
and value.func.value.id == "httpx"
and value.func.attr in {"Client", "AsyncClient"}
):
continue
targets = candidate.targets if isinstance(candidate, ast.Assign) else [candidate.target]
derived_client_names.update(target.id for target in targets if isinstance(target, ast.Name))
for node in ast.walk(tree):
if isinstance(node, ast.Import):
imports.update(_import_root(alias.name) for alias in node.names)
elif isinstance(node, ast.ImportFrom):
if node.level:
forbidden_nodes.append(f"relative-import:{node.module or ''}")
imports.add(_import_root(node.module))
elif isinstance(node, ast.Pass):
forbidden_nodes.append("Pass")
elif isinstance(node, ast.Expr) and isinstance(node.value, ast.Constant):
if node.value.value is Ellipsis:
forbidden_nodes.append("Ellipsis-expression")
elif isinstance(node, (ast.Assign, ast.AnnAssign)):
if isinstance(node.value, ast.Constant) and node.value.value is Ellipsis:
forbidden_nodes.append("Ellipsis-assignment")
if (
isinstance(node.value, ast.Attribute)
and node.value.attr in HTTP_NETWORK_METHODS
and _is_http_client_receiver(node.value.value, derived_client_names)
):
forbidden_nodes.append(f"network-method-alias:{node.value.attr}")
elif isinstance(node, ast.Constant):
if isinstance(node.value, str):
for match in URL_RE.findall(node.value):
normalized = match.rstrip(".,);]")
if (
normalized != EXPECTED_LOCALDOCS_URL
and not normalized.startswith(ALLOWED_IDENTIFIER_URL_PREFIXES)
):
external_urls.add(normalized)
if PYTHON_SOURCE_REF_RE.search(node.value.strip()):
project_source_refs.add(node.value[:200])
if node.value.strip().lower() in {
"todo",
"tbd",
"placeholder",
"omitted",
"implement me",
"...",
}:
forbidden_nodes.append(f"placeholder-string:{node.value!r}")
elif isinstance(node, ast.Call):
if (
isinstance(node.func, ast.Attribute)
and node.func.attr in HTTP_NETWORK_METHODS
and _is_http_client_receiver(node.func.value, derived_client_names)
):
if not _is_direct_localdocs_post(node):
forbidden_network_endpoints.add(ast.unparse(node.func)[:200])
if (
isinstance(node.func, ast.Name)
and node.func.id == "getattr"
and len(node.args) >= 2
and isinstance(node.args[1], ast.Constant)
and node.args[1].value in HTTP_NETWORK_METHODS
):
forbidden_nodes.append(f"dynamic-network-method:{node.args[1].value}")
if isinstance(node.func, ast.Name) and node.func.id in FORBIDDEN_CALL_NAMES:
forbidden_nodes.append(f"call:{node.func.id}")
elif isinstance(node.func, ast.Attribute):
pair = _attribute_pair(node.func)
if pair in FORBIDDEN_ATTRIBUTE_CALLS:
forbidden_nodes.append(f"call:{pair[0]}.{pair[1]}")
elif isinstance(node, ast.Raise):
target = node.exc
if isinstance(target, ast.Call):
target = target.func
if isinstance(target, ast.Name) and target.id == "NotImplementedError":
forbidden_nodes.append("raise:NotImplementedError")
imports.discard("")
disallowed_imports = sorted(
root
for root in imports
if root in FORBIDDEN_IMPORT_ROOTS
or (root not in sys.stdlib_module_names and root not in ALLOWED_NON_STDLIB_IMPORTS)
)
if disallowed_imports:
raise ProjectionError("INLINE_CODE_IMPORT_FORBIDDEN", ",".join(disallowed_imports))
if forbidden_nodes:
raise ProjectionError("INLINE_CODE_DYNAMIC_OR_PLACEHOLDER_FORBIDDEN", ",".join(forbidden_nodes))
if external_urls:
raise ProjectionError("INLINE_CODE_EXTERNAL_URL_FORBIDDEN", ",".join(sorted(external_urls)))
if forbidden_network_endpoints:
raise ProjectionError(
"INLINE_CODE_NETWORK_ENDPOINT_FORBIDDEN",
",".join(sorted(forbidden_network_endpoints)),
)
if project_source_refs:
raise ProjectionError(
"INLINE_CODE_EXTERNAL_PY_SOURCE_REF_FORBIDDEN", ",".join(sorted(project_source_refs))
)
return {
"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_url_count": 0,
"placeholder_count": 0,
"plaintext_secret_count": 0,
"external_python_source_ref_count": 0,
}
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"),
},
"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 ("language", "requirements", "network", "timeout")
},
"code_sha256": sha256_bytes(parameters["code"].encode("utf-8")),
},
"task_procedure": stage.get("task_procedure"),
}
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)
semantics_sha256 = sha256_bytes(canonical_json_bytes(semantics))
receipt = {
"schema_version": "stage2_s2_00_inline_code_receipt.v1",
"workflow_id": "S2_00",
"build_kind": "OFFLINE_AUTHORING_PROJECTION",
"source_of_truth": _logical_path(AUTHORING_PATH),
"authoring_rewritten": False,
"authoring": {
"path": _logical_path(AUTHORING_PATH),
"sha256": sha256_bytes(authoring_raw),
"size_bytes": len(authoring_raw),
"unique_key_parse": "PASS",
},
"deployment_projection": {
"path": _logical_path(PROJECTION_PATH),
"sha256": sha256_bytes(authoring_raw),
"size_bytes": len(authoring_raw),
"byte_identical_to_authoring": True,
"canonical_task_semantics_sha256": semantics_sha256,
},
"canonical_code": {
"yaml_pointer": "/Agent/Stages/0/tasks/0/parameters/code",
"encoding": "UTF-8",
"extraction_transform": "NONE",
**validation,
},
"full_code_mirrors": [
{
"path": _logical_path(MIRROR_PY_PATH),
"sha256": validation["code_sha256"],
"size_bytes": len(code_bytes),
"byte_identical_to_canonical_code": True,
},
{
"path": _logical_path(MIRROR_TXT_PATH),
"sha256": validation["code_sha256"],
"size_bytes": len(code_bytes),
"byte_identical_to_canonical_code": True,
},
],
"task_contract": semantics,
"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:
continue
_atomic_write(path, payload)
after_artifacts = AUTHORING_PATH.read_bytes()
if after_artifacts != before:
raise ProjectionError(
"AUTHORING_CHANGED_DURING_BUILD",
f"before={sha256_bytes(before)} after={sha256_bytes(after_artifacts)}",
)
_atomic_write(RECEIPT_PATH, receipt_payload)
after_receipt = AUTHORING_PATH.read_bytes()
if after_receipt != before:
raise ProjectionError(
"AUTHORING_CHANGED_DURING_RECEIPT_WRITE",
f"before={sha256_bytes(before)} after={sha256_bytes(after_receipt)}",
)
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 the S2_00 inline Agent projection"
)
parser.add_argument(
"--check",
action="store_true",
help="perform a no-write byte-parity check against generated outputs",
)
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" 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())
@@ -1,12 +1,16 @@
{ {
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.liti-agent.local/stage2/shared/deployment.schema.v1.json", "$id": "https://schemas.liti-agent.local/stage2/shared/deployment.schema.v1.json",
"title": "Stage 2 release, loader binding and invocation receipt", "title": "Stage 2 release, direct Code Executor binding and invocation receipts",
"schema_version": "stage2_deployment.v1", "schema_version": "stage2_deployment.v1.1",
"oneOf": [ "oneOf": [
{"$ref": "#/$defs/workflow_binding"}, {"$ref": "#/$defs/code_executor_binding"},
{"$ref": "#/$defs/stage2_release"}, {"$ref": "#/$defs/inline_code_receipt"},
{"$ref": "#/$defs/loader_receipt"} {"$ref": "#/$defs/code_executor_outer_result"},
{"$ref": "#/$defs/s2_00_inner_receipt"},
{"$ref": "#/$defs/logical_publish_receipt"},
{"$ref": "#/$defs/superseded_loader_binding"},
{"$ref": "#/$defs/stage2_release"}
], ],
"$defs": { "$defs": {
"sha256": { "sha256": {
@@ -46,6 +50,524 @@
} }
} }
}, },
"external_execution_binding_ref": {
"type": "object",
"additionalProperties": false,
"$comment": "Cycle-breaking release pointer. The executor binding independently binds the release raw hash at the external trust boundary.",
"required": ["asset_id", "path", "schema_id", "binding_status"],
"properties": {
"asset_id": {"$ref": "#/$defs/nonempty_string"},
"path": {"const": "deployment/stage2_code_executor_binding.yml"},
"schema_id": {"const": "stage2_code_executor_binding.v1"},
"binding_status": {
"enum": [
"EXTERNAL_TRUST_ROOT_PENDING_LIVE_ADMISSION",
"EXTERNAL_TRUST_ROOT_ADMITTED"
]
}
}
},
"dependency_lock": {
"type": "object",
"additionalProperties": false,
"required": ["requirements", "requirements_sha256", "lock_status"],
"properties": {
"requirements": {"const": "httpx==0.28.1"},
"requirements_sha256": {"$ref": "#/$defs/sha256"},
"lock_status": {"enum": ["STATIC_PIN_BOUND", "LIVE_BACKEND_PENDING"]}
}
},
"code_executor_binding": {
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"binding_id",
"workflow_id",
"execution_class",
"active_runtime_authority",
"agent_script_ref",
"workflow_contract_ref",
"inline_code_receipt_ref",
"stage2_release_ref",
"expected_release_sha256",
"agent_script_sha256",
"canonical_code_sha256",
"mcp_server_id",
"tool_name",
"language",
"network",
"timeout_seconds",
"runtime_image_digest",
"runtime_image_status",
"dependency_lock",
"localdocs_contract",
"egress_profile_id",
"egress_profile_status",
"downstream_llm_candidate_bindings",
"live_admission_status",
"legacy_fallbacks"
],
"properties": {
"schema_version": {"const": "stage2_code_executor_binding.v1"},
"binding_id": {"$ref": "#/$defs/nonempty_string"},
"workflow_id": {"const": "S2_00"},
"execution_class": {"const": "NON-LLM-DETERMINISTIC"},
"active_runtime_authority": {"const": true},
"agent_script_ref": {"$ref": "#/$defs/asset_ref"},
"workflow_contract_ref": {"$ref": "#/$defs/asset_ref"},
"inline_code_receipt_ref": {"$ref": "#/$defs/asset_ref"},
"stage2_release_ref": {"$ref": "#/$defs/asset_ref"},
"expected_release_sha256": {"$ref": "#/$defs/bindable_sha256"},
"agent_script_sha256": {"$ref": "#/$defs/bindable_sha256"},
"canonical_code_sha256": {"$ref": "#/$defs/bindable_sha256"},
"mcp_server_id": {"const": "code-executor"},
"tool_name": {"const": "run_code"},
"language": {"const": "python"},
"network": {"const": "agent-network"},
"timeout_seconds": {"const": 300},
"runtime_image_digest": {"$ref": "#/$defs/bindable_sha256"},
"runtime_image_status": {
"enum": ["PINNED_VERIFIED", "PENDING_BACKEND_EVIDENCE"]
},
"dependency_lock": {"$ref": "#/$defs/dependency_lock"},
"localdocs_contract": {
"type": "object",
"additionalProperties": false,
"required": [
"endpoint",
"user_id_template",
"workspace_id_template",
"tool_allowlist",
"fixed_request_path",
"read_path_allowlist",
"write_root_rule"
],
"properties": {
"endpoint": {"const": "http://mcp-localdocs:8012/mcp"},
"user_id_template": {"const": "{{__user_hash__}}"},
"workspace_id_template": {"const": "{{__workspace_hash__}}"},
"tool_allowlist": {
"type": "array",
"prefixItems": [
{"const": "read_binary_doc"},
{"const": "write_binary_file"}
],
"items": false,
"minItems": 2,
"maxItems": 2
},
"fixed_request_path": {"const": "stage2_control/s2_00_request.json"},
"read_path_allowlist": {
"type": "array",
"items": {"$ref": "#/$defs/path_ref"},
"minItems": 1,
"uniqueItems": true
},
"write_root_rule": {
"const": "stage2_runs/by-binding/<run_binding_digest>/"
}
}
},
"egress_profile_id": {"const": "S2_00_LOCALDOCS_ONLY_V1"},
"egress_profile_status": {
"enum": ["STATIC_ALLOWLIST_BOUND", "PENDING_LIVE_VERIFICATION"]
},
"downstream_llm_candidate_bindings": {
"type": "array",
"prefixItems": [
{"$ref": "#/$defs/downstream_llm_candidate_binding"}
],
"items": false,
"minItems": 1,
"maxItems": 1
},
"live_admission_status": {
"enum": [
"PENDING_SECRET_BINDING",
"PENDING_LIVE_EVIDENCE",
"LIVE_CANARY_ADMITTED"
]
},
"legacy_fallbacks": {"type": "array", "maxItems": 0}
}
},
"inline_code_receipt": {
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"workflow_id",
"build_kind",
"source_of_truth",
"authoring_rewritten",
"authoring",
"deployment_projection",
"canonical_code",
"full_code_mirrors",
"task_contract",
"parity_status"
],
"properties": {
"schema_version": {"const": "stage2_s2_00_inline_code_receipt.v1"},
"workflow_id": {"const": "S2_00"},
"build_kind": {"const": "OFFLINE_AUTHORING_PROJECTION"},
"source_of_truth": {"const": "Stage_2_S2_00_v.1.yml"},
"authoring_rewritten": {"const": false},
"authoring": {
"type": "object",
"additionalProperties": false,
"required": ["path", "sha256", "size_bytes", "unique_key_parse"],
"properties": {
"path": {"const": "Stage_2_S2_00_v.1.yml"},
"sha256": {"$ref": "#/$defs/sha256"},
"size_bytes": {"type": "integer", "minimum": 1},
"unique_key_parse": {"const": "PASS"}
}
},
"deployment_projection": {
"type": "object",
"additionalProperties": false,
"required": [
"path",
"sha256",
"size_bytes",
"byte_identical_to_authoring",
"canonical_task_semantics_sha256"
],
"properties": {
"path": {"const": "Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml"},
"sha256": {"$ref": "#/$defs/sha256"},
"size_bytes": {"type": "integer", "minimum": 1},
"byte_identical_to_authoring": {"const": true},
"canonical_task_semantics_sha256": {"$ref": "#/$defs/sha256"}
}
},
"canonical_code": {
"type": "object",
"additionalProperties": false,
"required": [
"ast_status",
"code_sha256",
"code_size_bytes",
"compile_status",
"encoding",
"external_python_source_ref_count",
"external_url_count",
"extraction_transform",
"forbidden_dynamic_call_count",
"forbidden_import_count",
"imports",
"placeholder_count",
"plaintext_secret_count",
"yaml_pointer"
],
"properties": {
"ast_status": {"const": "PASS"},
"code_sha256": {"$ref": "#/$defs/sha256"},
"code_size_bytes": {"type": "integer", "minimum": 1},
"compile_status": {"const": "PASS"},
"encoding": {"const": "UTF-8"},
"external_python_source_ref_count": {"const": 0},
"external_url_count": {"const": 0},
"extraction_transform": {"const": "NONE"},
"forbidden_dynamic_call_count": {"const": 0},
"forbidden_import_count": {"const": 0},
"imports": {
"type": "array",
"items": {"$ref": "#/$defs/nonempty_string"},
"uniqueItems": true
},
"placeholder_count": {"const": 0},
"plaintext_secret_count": {"const": 0},
"yaml_pointer": {"const": "/Agent/Stages/0/tasks/0/parameters/code"}
}
},
"full_code_mirrors": {
"type": "array",
"prefixItems": [
{
"type": "object",
"additionalProperties": false,
"required": ["path", "sha256", "size_bytes", "byte_identical_to_canonical_code"],
"properties": {
"path": {"const": "Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.py"},
"sha256": {"$ref": "#/$defs/sha256"},
"size_bytes": {"type": "integer", "minimum": 1},
"byte_identical_to_canonical_code": {"const": true}
}
},
{
"type": "object",
"additionalProperties": false,
"required": ["path", "sha256", "size_bytes", "byte_identical_to_canonical_code"],
"properties": {
"path": {"const": "Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.txt"},
"sha256": {"$ref": "#/$defs/sha256"},
"size_bytes": {"type": "integer", "minimum": 1},
"byte_identical_to_canonical_code": {"const": true}
}
}
],
"items": false,
"minItems": 2,
"maxItems": 2
},
"task_contract": {
"type": "object",
"additionalProperties": false,
"required": ["agent", "mcp_servers", "stage", "task", "task_procedure"],
"properties": {
"agent": {"const": {"name": "Stage_2_S2_00_v1", "version": "1.1.0"}},
"mcp_servers": {
"const": {
"code-executor": {"type": "streamable-http", "url": "https://code-executor.mcp.eroomai.com/mcp"},
"localdocs": {"type": "streamable-http", "url": "http://mcp-localdocs:8012/mcp"}
}
},
"stage": {"const": {"name": "S2_00", "nexts": [], "prevs": []}},
"task": {
"type": "object",
"additionalProperties": false,
"required": ["task_name", "mcp", "tool_name", "parameters", "code_sha256"],
"properties": {
"task_name": {"const": "Task_S2_00_deterministic_ingress"},
"mcp": {"const": "code-executor"},
"tool_name": {"const": "run_code"},
"parameters": {
"const": {
"language": "python",
"requirements": "httpx==0.28.1",
"network": "agent-network",
"timeout": 300
}
},
"code_sha256": {"$ref": "#/$defs/sha256"}
}
},
"task_procedure": {
"const": {
"IN": {"nexts": ["Task_S2_00_deterministic_ingress"], "wait_until": []},
"Task_S2_00_deterministic_ingress": {"nexts": ["OUT"], "wait_until": ["IN"]},
"OUT": {"nexts": [], "wait_until": ["Task_S2_00_deterministic_ingress"]}
}
}
}
},
"parity_status": {"const": "PASS"}
}
},
"published_artifact_ref": {
"type": "object",
"additionalProperties": false,
"required": ["logical_artifact_id", "path", "schema_id", "raw_sha256", "byte_length"],
"properties": {
"logical_artifact_id": {"$ref": "#/$defs/nonempty_string"},
"path": {"$ref": "#/$defs/path_ref"},
"schema_id": {"$ref": "#/$defs/nonempty_string"},
"raw_sha256": {"$ref": "#/$defs/sha256"},
"byte_length": {"type": "integer", "minimum": 0}
}
},
"logical_publish_receipt": {
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"barrier_id",
"barrier_path",
"publish_semantics",
"canonical_output_root",
"run_binding_digest",
"branch",
"artifacts",
"artifact_set_digest",
"barrier_raw_sha256",
"non_status_artifacts_read_back_verified",
"barrier_written_last",
"downstream_consumption_allowed",
"publication_status"
],
"properties": {
"schema_version": {"const": "stage2_logical_publish_receipt.v1"},
"barrier_id": {"const": "S2_00_INGRESS_STATUS_BARRIER"},
"barrier_path": {"const": "ingress/ingress_status.json"},
"publish_semantics": {"const": "STATUS_LAST_LOGICAL_COMMIT"},
"canonical_output_root": {
"type": "string",
"pattern": "^stage2_runs/by-binding/[a-f0-9]{64}/$"
},
"run_binding_digest": {"$ref": "#/$defs/sha256"},
"branch": {"enum": ["NORMAL", "DIAGNOSTIC"]},
"artifacts": {
"type": "array",
"items": {"$ref": "#/$defs/published_artifact_ref"}
},
"artifact_set_digest": {"$ref": "#/$defs/sha256"},
"barrier_raw_sha256": {"$ref": "#/$defs/sha256"},
"non_status_artifacts_read_back_verified": {"const": true},
"barrier_written_last": {"const": true},
"downstream_consumption_allowed": {"type": "boolean"},
"publication_status": {
"enum": ["PUBLISHED_STATUS_LAST", "IDEMPOTENT_SUCCESS"]
}
},
"$comment": "The output-root digest segment and all run identities are recomputed and compared to run_binding_digest by deterministic validation."
},
"s2_00_inner_receipt": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"workflow_id",
"ok",
"status",
"request_id",
"route",
"run_id",
"run_binding_digest",
"expected_release_sha256",
"algorithm_digest",
"artifact_set_digest",
"ingress_status_sha256",
"logical_publish_receipt"
],
"properties": {
"schema_version": {"const": "stage2_s2_00_inner_receipt.v1"},
"workflow_id": {"const": "S2_00"},
"ok": {"const": true},
"status": {"enum": ["SUCCEEDED", "DIAGNOSTIC_PUBLISHED"]},
"request_id": {"$ref": "#/$defs/nonempty_string"},
"route": {"enum": ["TO_S2_10", "TO_S2_10_WITH_ISSUES", "TO_S2_40_STATUS_ONLY"]},
"run_id": {"type": "string", "pattern": "^S2RUN-[a-f0-9]{64}$"},
"run_binding_digest": {"$ref": "#/$defs/sha256"},
"expected_release_sha256": {"$ref": "#/$defs/sha256"},
"algorithm_digest": {"$ref": "#/$defs/sha256"},
"artifact_set_digest": {"$ref": "#/$defs/sha256"},
"ingress_status_sha256": {"$ref": "#/$defs/sha256"},
"logical_publish_receipt": {"$ref": "#/$defs/logical_publish_receipt"}
}
},
{
"type": "object",
"additionalProperties": false,
"required": ["schema_version", "workflow_id", "ok", "status", "expected_release_sha256", "error"],
"properties": {
"schema_version": {"const": "stage2_s2_00_inner_receipt.v1"},
"workflow_id": {"const": "S2_00"},
"ok": {"const": false},
"status": {"const": "FAILED_NO_BARRIER"},
"expected_release_sha256": {"$ref": "#/$defs/sha256"},
"error": {
"type": "object",
"additionalProperties": false,
"required": ["code", "message"],
"properties": {
"code": {"$ref": "#/$defs/nonempty_string"},
"message": {"type": "string"},
"logical_input_id": {"$ref": "#/$defs/nonempty_string"},
"details": {"type": "object"}
}
}
}
}
]
},
"code_executor_outer_result": {
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"workflow_id",
"task_name",
"mcp_server_id",
"tool_name",
"expected_release_sha256",
"agent_script_sha256",
"canonical_code_sha256",
"runtime_image_digest",
"runtime_image_status",
"dependency_lock",
"egress_profile_id",
"egress_profile_status",
"inner_receipt_sha256",
"tool_result_status",
"live_admission_status"
],
"properties": {
"schema_version": {"const": "stage2_code_executor_outer_result.v1"},
"workflow_id": {"const": "S2_00"},
"task_name": {"const": "Task_S2_00_deterministic_ingress"},
"mcp_server_id": {"const": "code-executor"},
"tool_name": {"const": "run_code"},
"expected_release_sha256": {"$ref": "#/$defs/sha256"},
"agent_script_sha256": {"$ref": "#/$defs/sha256"},
"canonical_code_sha256": {"$ref": "#/$defs/sha256"},
"runtime_image_digest": {"$ref": "#/$defs/bindable_sha256"},
"runtime_image_status": {"enum": ["PINNED_VERIFIED", "PENDING_BACKEND_EVIDENCE"]},
"dependency_lock": {"$ref": "#/$defs/dependency_lock"},
"egress_profile_id": {"const": "S2_00_LOCALDOCS_ONLY_V1"},
"egress_profile_status": {"enum": ["VERIFIED", "PENDING_LIVE_VERIFICATION"]},
"inner_receipt_sha256": {
"oneOf": [
{"$ref": "#/$defs/sha256"},
{"type": "null"}
]
},
"tool_result_status": {"enum": ["SUCCEEDED", "FAILED", "TIMED_OUT"]},
"live_admission_status": {
"enum": ["PENDING_SECRET_BINDING", "PENDING_LIVE_EVIDENCE", "LIVE_CANARY_ADMITTED"]
}
},
"allOf": [
{
"if": {
"properties": {"tool_result_status": {"const": "SUCCEEDED"}},
"required": ["tool_result_status"]
},
"then": {
"properties": {"inner_receipt_sha256": {"$ref": "#/$defs/sha256"}}
}
}
]
},
"superseded_loader_binding": {
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"binding_id",
"workflow_id",
"disposition",
"active_runtime_authority",
"invocation_allowed",
"fallback_allowed",
"superseded_by",
"retained_legacy_refs",
"reason_code"
],
"properties": {
"schema_version": {"const": "stage2_loader_binding.reference.v1"},
"binding_id": {"const": "S2-BINDING-S2_00-V1"},
"workflow_id": {"const": "S2_00"},
"disposition": {"const": "REFERENCE_ONLY_SUPERSEDED_FOR_S2_00"},
"active_runtime_authority": {"const": false},
"invocation_allowed": {"const": false},
"fallback_allowed": {"const": false},
"superseded_by": {"$ref": "#/$defs/external_execution_binding_ref"},
"retained_legacy_refs": {
"type": "array",
"items": {"$ref": "#/$defs/path_ref"},
"minItems": 1,
"uniqueItems": true
},
"reason_code": {
"const": "O-06_SUPERSEDED_NOT_APPLICABLE_BY_DIRECT_MCP_CODE_EXECUTOR"
}
}
},
"fixed_argv_contract": { "fixed_argv_contract": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@@ -149,6 +671,8 @@
"workflow_binding": { "workflow_binding": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"deprecated": true,
"$comment": "Historical host-loader shape retained for audit parsing only; it is not an S2_00 runtime authority or fallback in v1.1.",
"required": [ "required": [
"schema_version", "schema_version",
"binding_id", "binding_id",
@@ -354,7 +878,6 @@
"raw_hash_source": { "raw_hash_source": {
"description": "Static release records only the runtime hash authority. It never embeds case-run bytes or their observed raw hash.", "description": "Static release records only the runtime hash authority. It never embeds case-run bytes or their observed raw hash.",
"enum": [ "enum": [
"COMPLETION_SEAL",
"MANIFEST_ROW", "MANIFEST_ROW",
"UNAVAILABLE_DEV" "UNAVAILABLE_DEV"
] ]
@@ -420,7 +943,7 @@
"properties": { "properties": {
"policy_id": {"const": "S2-CACHE-STATIC-PREFIX-V1"}, "policy_id": {"const": "S2-CACHE-STATIC-PREFIX-V1"},
"model_binding_ref": { "model_binding_ref": {
"const": "deployment/stage2_loader_binding.yml#/downstream_llm_candidate_bindings/0" "const": "deployment/stage2_code_executor_binding.yml#/downstream_llm_candidate_bindings/0"
}, },
"model_id": {"const": "gpt-5.6-sol"}, "model_id": {"const": "gpt-5.6-sol"},
"reasoning_effort": {"const": "ultra"}, "reasoning_effort": {"const": "ultra"},
@@ -488,6 +1011,30 @@
"executable": {"const": false} "executable": {"const": false}
} }
} }
},
{
"if": {
"properties": {"mode": {"const": "SUBSET_CANARY"}},
"required": ["mode"]
},
"then": {
"properties": {
"authority_release_status": {"const": "SUBSET_CANARY_ADMITTED"},
"executable": {"const": true}
}
}
},
{
"if": {
"properties": {"mode": {"const": "PRODUCTION"}},
"required": ["mode"]
},
"then": {
"properties": {
"authority_release_status": {"const": "PRODUCTION_ADMITTED"},
"executable": {"const": true}
}
}
} }
] ]
}, },
@@ -619,7 +1166,7 @@
"signature", "signature",
"authoring_root", "authoring_root",
"module_manifest_ref", "module_manifest_ref",
"loader_binding_ref", "executor_binding_ref",
"stage1_sources", "stage1_sources",
"dependency_locks", "dependency_locks",
"adapter_decisions", "adapter_decisions",
@@ -663,7 +1210,12 @@
"const": "Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean" "const": "Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean"
}, },
"module_manifest_ref": {"$ref": "#/$defs/asset_ref"}, "module_manifest_ref": {"$ref": "#/$defs/asset_ref"},
"loader_binding_ref": {"$ref": "#/$defs/asset_ref"}, "executor_binding_ref": {"$ref": "#/$defs/external_execution_binding_ref"},
"loader_binding_ref": {
"$ref": "#/$defs/asset_ref",
"deprecated": true,
"$comment": "Historical audit pointer only; it cannot authorize or provide fallback execution for S2_00."
},
"stage1_sources": { "stage1_sources": {
"type": "array", "type": "array",
"items": {"$ref": "#/$defs/stage1_source_contract_row"}, "items": {"$ref": "#/$defs/stage1_source_contract_row"},
@@ -683,7 +1235,6 @@
"expected_concrete_path_count", "expected_concrete_path_count",
"concrete_paths", "concrete_paths",
"contract_manifest_ref", "contract_manifest_ref",
"completion_seal_ref",
"closure_scope", "closure_scope",
"full_stage1_runtime_release_status" "full_stage1_runtime_release_status"
], ],
@@ -717,27 +1268,6 @@
} }
} }
}, },
"completion_seal_ref": {
"type": "object",
"additionalProperties": false,
"required": ["status", "path", "sha256", "producer_id"],
"properties": {
"status": {
"enum": [
"PENDING_SEQUENTIAL_BIND",
"BOUND"
]
},
"path": {
"anyOf": [
{"$ref": "#/$defs/path_ref"},
{"const": "PENDING_SEQUENTIAL_BIND"}
]
},
"sha256": {"$ref": "#/$defs/bindable_sha256"},
"producer_id": {"$ref": "#/$defs/nonempty_string"}
}
},
"closure_scope": { "closure_scope": {
"const": "REFERENCED_55_ONLY_NOT_FULL_STAGE1_RUNTIME_RELEASE" "const": "REFERENCED_55_ONLY_NOT_FULL_STAGE1_RUNTIME_RELEASE"
}, },
@@ -798,17 +1328,85 @@
{ {
"if": { "if": {
"properties": { "properties": {
"release_class": { "release_class": {"const": "DEV_FIXTURE_RELEASE"}
"enum": ["SUBSET_CANARY_RELEASE", "PRODUCTION_RELEASE"]
}
}, },
"required": ["release_class"] "required": ["release_class"]
}, },
"then": {
"properties": {
"release_status": {"enum": ["DRAFT_NOT_EXECUTABLE", "DEV_VALIDATED"]},
"authorization_status": {"const": "DEV_VALIDATION_ONLY"},
"executor_binding_ref": {
"properties": {
"binding_status": {"const": "EXTERNAL_TRUST_ROOT_PENDING_LIVE_ADMISSION"}
}
},
"bundle": {
"properties": {
"mode": {"const": "STRUCTURAL_FIXTURE"},
"authority_release_status": {"const": "DEV_UNAVAILABLE"},
"executable": {"const": false}
}
}
}
}
},
{
"if": {
"properties": {"release_class": {"const": "SUBSET_CANARY_RELEASE"}},
"required": ["release_class"]
},
"then": { "then": {
"properties": { "properties": {
"release_status": {"const": "ADMITTED"}, "release_status": {"const": "ADMITTED"},
"authorization_status": {"const": "CANARY_ADMITTED"},
"release_digest": {"$ref": "#/$defs/sha256"}, "release_digest": {"$ref": "#/$defs/sha256"},
"signature": {"not": {"const": "PENDING_SEQUENTIAL_BIND"}}, "signature": {"not": {"const": "PENDING_SEQUENTIAL_BIND"}},
"executor_binding_ref": {
"properties": {
"binding_status": {"const": "EXTERNAL_TRUST_ROOT_ADMITTED"}
}
},
"bundle": {
"properties": {
"mode": {"const": "SUBSET_CANARY"},
"authority_release_status": {"const": "SUBSET_CANARY_ADMITTED"},
"executable": {"const": true}
}
},
"release_evidence": {
"contains": {
"type": "object",
"properties": {"status": {"const": "SIGNED_ADMITTED"}},
"required": ["status"]
}
}
}
}
},
{
"if": {
"properties": {"release_class": {"const": "PRODUCTION_RELEASE"}},
"required": ["release_class"]
},
"then": {
"properties": {
"release_status": {"const": "ADMITTED"},
"authorization_status": {"const": "PRODUCTION_ADMITTED"},
"release_digest": {"$ref": "#/$defs/sha256"},
"signature": {"not": {"const": "PENDING_SEQUENTIAL_BIND"}},
"executor_binding_ref": {
"properties": {
"binding_status": {"const": "EXTERNAL_TRUST_ROOT_ADMITTED"}
}
},
"bundle": {
"properties": {
"mode": {"const": "PRODUCTION"},
"authority_release_status": {"const": "PRODUCTION_ADMITTED"},
"executable": {"const": true}
}
},
"release_evidence": { "release_evidence": {
"contains": { "contains": {
"type": "object", "type": "object",
@@ -1,10 +1,10 @@
{ {
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json", "$id": "https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json",
"title": "Stage 2 S2_00 ingress and routing artifacts", "title": "Stage 2 S2_00 direct-Code-Executor ingress and routing artifacts",
"schema_version": "stage2_s2_00_ingress.v1", "schema_version": "stage2_s2_00_ingress.v1.1",
"oneOf": [ "oneOf": [
{"$ref": "#/$defs/run_request"}, {"$ref": "#/$defs/execution_request"},
{"$ref": "#/$defs/stage1_input_manifest"}, {"$ref": "#/$defs/stage1_input_manifest"},
{"$ref": "#/$defs/intake_report"}, {"$ref": "#/$defs/intake_report"},
{"$ref": "#/$defs/ingress_status"}, {"$ref": "#/$defs/ingress_status"},
@@ -20,6 +20,21 @@
"type": "string", "type": "string",
"minLength": 1 "minLength": 1
}, },
"logical_path": {
"type": "string",
"minLength": 1,
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\x00).+$"
},
"logical_root_ref": {
"type": "string",
"minLength": 1,
"maxLength": 256,
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\x00)[A-Za-z0-9][A-Za-z0-9._/-]*$"
},
"canonical_run_id": {
"type": "string",
"pattern": "^S2RUN-[a-f0-9]{64}$"
},
"string_set": { "string_set": {
"type": "array", "type": "array",
"items": {"$ref": "#/$defs/nonempty_string"}, "items": {"$ref": "#/$defs/nonempty_string"},
@@ -206,23 +221,22 @@
} }
} }
}, },
"run_request": { "execution_request": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"$comment": "The only accepted runtime request is read from stage2_control/s2_00_request.json. User/workspace identities and release class are backend/release bindings, not caller fields.",
"required": [ "required": [
"schema_version", "schema_version",
"workflow_id", "workflow_id",
"run_id", "request_id",
"release_class", "attempt_id",
"user_context_sha256",
"workspace_context_sha256",
"stage1_run_root_ref", "stage1_run_root_ref",
"stage1_deployment_root_ref" "stage1_deployment_root_ref"
], ],
"properties": { "properties": {
"schema_version": {"const": "stage2_s2_00_run_request.v1"}, "schema_version": {"const": "stage2_s2_00_execution_request.v1"},
"workflow_id": {"const": "S2_00"}, "workflow_id": {"const": "S2_00"},
"run_id": { "request_id": {
"type": "string", "type": "string",
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$" "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$"
}, },
@@ -230,25 +244,15 @@
"type": "string", "type": "string",
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$" "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$"
}, },
"release_class": { "stage1_run_root_ref": {"$ref": "#/$defs/logical_root_ref"},
"enum": [ "stage1_deployment_root_ref": {"$ref": "#/$defs/logical_root_ref"}
"DEV_FIXTURE_RELEASE",
"SUBSET_CANARY_RELEASE",
"PRODUCTION_RELEASE"
]
},
"user_context_sha256": {"$ref": "#/$defs/sha256"},
"workspace_context_sha256": {"$ref": "#/$defs/sha256"},
"stage1_run_root_ref": {
"type": "string",
"pattern": "^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$"
},
"stage1_deployment_root_ref": {
"type": "string",
"pattern": "^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$"
}
} }
}, },
"run_request": {
"$ref": "#/$defs/execution_request",
"deprecated": true,
"$comment": "Compatibility definition name only; it does not restore caller-supplied run_id, release, or host-loader invocation."
},
"all_expansion_contract": { "all_expansion_contract": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@@ -632,6 +636,58 @@
} }
} }
}, },
"binary_hydration_source_receipt": {
"type": "object",
"additionalProperties": false,
"required": [
"logical_input_id",
"logical_path",
"pass_1_raw_sha256",
"pass_2_raw_sha256",
"pass_1_byte_length",
"pass_2_byte_length",
"stability_status"
],
"properties": {
"logical_input_id": {"$ref": "#/$defs/nonempty_string"},
"logical_path": {"$ref": "#/$defs/logical_path"},
"pass_1_raw_sha256": {"$ref": "#/$defs/sha256"},
"pass_2_raw_sha256": {"$ref": "#/$defs/sha256"},
"pass_1_byte_length": {"type": "integer", "minimum": 0},
"pass_2_byte_length": {"type": "integer", "minimum": 0},
"stability_status": {"enum": ["STABLE", "CHANGED", "UNEVALUABLE"]}
}
},
"two_pass_hydration_stability_receipt": {
"type": "object",
"additionalProperties": false,
"$comment": "Every release-enumerated source is read as binary at most twice. Equality is over the complete ordered logical-path to raw-hash map, not normalized text.",
"required": [
"schema_version",
"transport",
"read_policy",
"read_pass_count",
"max_read_passes",
"pass_1_raw_hash_map_digest",
"pass_2_raw_hash_map_digest",
"source_receipts",
"stability_status"
],
"properties": {
"schema_version": {"const": "stage2_s2_00_two_pass_hydration_receipt.v1"},
"transport": {"const": "localdocs.read_binary_doc"},
"read_policy": {"const": "BOUNDED_TWO_PASS_BINARY_RAW_HASH_MAP_EQUALITY"},
"read_pass_count": {"const": 2},
"max_read_passes": {"const": 2},
"pass_1_raw_hash_map_digest": {"$ref": "#/$defs/sha256"},
"pass_2_raw_hash_map_digest": {"$ref": "#/$defs/sha256"},
"source_receipts": {
"type": "array",
"items": {"$ref": "#/$defs/binary_hydration_source_receipt"}
},
"stability_status": {"enum": ["STABLE", "CHANGED", "UNEVALUABLE"]}
}
},
"stage1_input_manifest": { "stage1_input_manifest": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@@ -643,14 +699,14 @@
"source_row_order", "source_row_order",
"signal_all_adapter_id", "signal_all_adapter_id",
"dual_sg01_adapter_id", "dual_sg01_adapter_id",
"snapshot_start_digest",
"snapshot_end_digest",
"snapshot_status",
"input_set_digest" "input_set_digest"
], ],
"properties": { "properties": {
"schema_version": { "schema_version": {
"const": "stage2_s2_00_stage1_input_manifest.v1" "enum": [
"stage2_s2_00_stage1_input_manifest.v1",
"stage2_s2_00_stage1_input_manifest.v1.1"
]
}, },
"run_id": {"$ref": "#/$defs/nonempty_string"}, "run_id": {"$ref": "#/$defs/nonempty_string"},
"release_class": { "release_class": {
@@ -670,12 +726,36 @@
}, },
"signal_all_adapter_id": {"const": "S2A-SIGNAL-ALL-V1"}, "signal_all_adapter_id": {"const": "S2A-SIGNAL-ALL-V1"},
"dual_sg01_adapter_id": {"const": "S2A-DUAL-SG01-V1"}, "dual_sg01_adapter_id": {"const": "S2A-DUAL-SG01-V1"},
"hydration_stability_receipt": {
"$ref": "#/$defs/two_pass_hydration_stability_receipt"
},
"snapshot_start_digest": {"$ref": "#/$defs/sha256"}, "snapshot_start_digest": {"$ref": "#/$defs/sha256"},
"snapshot_end_digest": {"$ref": "#/$defs/sha256"}, "snapshot_end_digest": {"$ref": "#/$defs/sha256"},
"snapshot_status": {"enum": ["STABLE", "CHANGED", "UNEVALUABLE"]}, "snapshot_status": {"enum": ["STABLE", "CHANGED", "UNEVALUABLE"]},
"input_set_digest": {"$ref": "#/$defs/sha256"} "input_set_digest": {"$ref": "#/$defs/sha256"}
},
"allOf": [
{
"if": {
"properties": {"schema_version": {"const": "stage2_s2_00_stage1_input_manifest.v1"}},
"required": ["schema_version"]
},
"then": {
"required": ["snapshot_start_digest", "snapshot_end_digest", "snapshot_status"]
} }
}, },
{
"if": {
"properties": {"schema_version": {"const": "stage2_s2_00_stage1_input_manifest.v1.1"}},
"required": ["schema_version"]
},
"then": {
"required": ["hydration_stability_receipt"],
"properties": {"run_id": {"$ref": "#/$defs/canonical_run_id"}}
}
}
]
},
"intake_report": { "intake_report": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@@ -734,7 +814,16 @@
"workspace_context_sha256" "workspace_context_sha256"
], ],
"properties": { "properties": {
"schema_version": {"const": "stage2_s2_00_run_binding_receipt.v1"}, "schema_version": {
"enum": [
"stage2_s2_00_run_binding_receipt.v1",
"stage2_s2_00_run_binding_receipt.v1.1"
]
},
"request_id": {
"type": "string",
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$"
},
"run_id": {"$ref": "#/$defs/nonempty_string"}, "run_id": {"$ref": "#/$defs/nonempty_string"},
"input_set_digest": {"$ref": "#/$defs/sha256"}, "input_set_digest": {"$ref": "#/$defs/sha256"},
"stage2_release_digest": {"$ref": "#/$defs/sha256"}, "stage2_release_digest": {"$ref": "#/$defs/sha256"},
@@ -747,9 +836,37 @@
] ]
}, },
"run_binding_digest": {"$ref": "#/$defs/sha256"}, "run_binding_digest": {"$ref": "#/$defs/sha256"},
"canonical_output_root": {
"type": "string",
"pattern": "^stage2_runs/by-binding/[a-f0-9]{64}/$"
},
"run_identity_derivation": {
"const": "RUN_ID_PREFIXED_FROM_RUN_BINDING_DIGEST"
},
"output_root_derivation": {
"const": "stage2_runs/by-binding/<run_binding_digest>/"
},
"user_context_sha256": {"$ref": "#/$defs/sha256"}, "user_context_sha256": {"$ref": "#/$defs/sha256"},
"workspace_context_sha256": {"$ref": "#/$defs/sha256"} "workspace_context_sha256": {"$ref": "#/$defs/sha256"}
},
"allOf": [
{
"if": {
"properties": {"schema_version": {"const": "stage2_s2_00_run_binding_receipt.v1.1"}},
"required": ["schema_version"]
},
"then": {
"required": [
"request_id",
"canonical_output_root",
"run_identity_derivation",
"output_root_derivation"
],
"properties": {"run_id": {"$ref": "#/$defs/canonical_run_id"}}
} }
}
],
"$comment": "For v1.1, run_id is S2RUN- plus run_binding_digest while the output-root digest segment is the raw run_binding_digest; deterministic validation recomputes both equalities."
}, },
"output_artifact_ref": { "output_artifact_ref": {
"type": "object", "type": "object",
@@ -757,9 +874,10 @@
"required": ["logical_artifact_id", "path", "schema_id", "raw_sha256"], "required": ["logical_artifact_id", "path", "schema_id", "raw_sha256"],
"properties": { "properties": {
"logical_artifact_id": {"$ref": "#/$defs/nonempty_string"}, "logical_artifact_id": {"$ref": "#/$defs/nonempty_string"},
"path": {"$ref": "#/$defs/nonempty_string"}, "path": {"$ref": "#/$defs/logical_path"},
"schema_id": {"$ref": "#/$defs/nonempty_string"}, "schema_id": {"$ref": "#/$defs/nonempty_string"},
"raw_sha256": {"$ref": "#/$defs/sha256"} "raw_sha256": {"$ref": "#/$defs/sha256"},
"byte_length": {"type": "integer", "minimum": 0}
} }
}, },
"output_barrier": { "output_barrier": {
@@ -774,12 +892,19 @@
], ],
"properties": { "properties": {
"barrier_id": {"const": "S2_00_INGRESS_STATUS_BARRIER"}, "barrier_id": {"const": "S2_00_INGRESS_STATUS_BARRIER"},
"barrier_path": {"const": "ingress/ingress_status.json"},
"publish_semantics": {"const": "STATUS_LAST_LOGICAL_COMMIT"},
"canonical_output_root": {
"type": "string",
"pattern": "^stage2_runs/by-binding/[a-f0-9]{64}/$"
},
"branch": {"enum": ["NORMAL", "DIAGNOSTIC"]}, "branch": {"enum": ["NORMAL", "DIAGNOSTIC"]},
"artifacts": { "artifacts": {
"type": "array", "type": "array",
"items": {"$ref": "#/$defs/output_artifact_ref"} "items": {"$ref": "#/$defs/output_artifact_ref"}
}, },
"artifact_set_digest": {"$ref": "#/$defs/sha256"}, "artifact_set_digest": {"$ref": "#/$defs/sha256"},
"non_status_artifacts_read_back_verified": {"const": true},
"written_last": {"const": true} "written_last": {"const": true}
} }
}, },
@@ -797,7 +922,12 @@
"output_barrier" "output_barrier"
], ],
"properties": { "properties": {
"schema_version": {"const": "stage2_s2_00_ingress_status.v1"}, "schema_version": {
"enum": [
"stage2_s2_00_ingress_status.v1",
"stage2_s2_00_ingress_status.v1.1"
]
},
"run_id": {"$ref": "#/$defs/nonempty_string"}, "run_id": {"$ref": "#/$defs/nonempty_string"},
"run_binding_receipt": {"$ref": "#/$defs/run_binding_receipt"}, "run_binding_receipt": {"$ref": "#/$defs/run_binding_receipt"},
"route": { "route": {
@@ -813,6 +943,25 @@
"output_barrier": {"$ref": "#/$defs/output_barrier"} "output_barrier": {"$ref": "#/$defs/output_barrier"}
}, },
"allOf": [ "allOf": [
{
"if": {
"properties": {"schema_version": {"const": "stage2_s2_00_ingress_status.v1.1"}},
"required": ["schema_version"]
},
"then": {
"properties": {
"run_id": {"$ref": "#/$defs/canonical_run_id"},
"output_barrier": {
"required": [
"barrier_path",
"publish_semantics",
"canonical_output_root",
"non_status_artifacts_read_back_verified"
]
}
}
}
},
{ {
"if": { "if": {
"properties": { "properties": {
@@ -1199,7 +1199,7 @@
}, },
{ {
"path": "tests/s2_00/test_cluster_bundle_compile.py", "path": "tests/s2_00/test_cluster_bundle_compile.py",
"sha256": "8e37dda051562b4c1a3fc595a1678fc7758742f89b19cfe8f9d5a0b342dfa5d1", "sha256": "c2b01c8d39be31d43b11f13a9901db036ef967337a388a4b85d951fbb4f51efe",
"status": "DEV_HASH_BOUND" "status": "DEV_HASH_BOUND"
}, },
{ {
@@ -1209,12 +1209,17 @@
}, },
{ {
"path": "tests/s2_00/test_failure_and_atomic_publish.py", "path": "tests/s2_00/test_failure_and_atomic_publish.py",
"sha256": "bb7879a23c207bba304cae1eefe89a8f0b7b9263787c80c3fbcea523300f0fb8", "sha256": "4bc5060ce95ec884c1193f16e8348d095c1b1a89181b0455ad809b2bb05cfb0c",
"status": "DEV_HASH_BOUND"
},
{
"path": "tests/s2_00/test_inline_code_parity.py",
"sha256": "6a03a8e67661c5599925c0fa01b4a79602d4b745936f783d5b68617ec2c4633e",
"status": "DEV_HASH_BOUND" "status": "DEV_HASH_BOUND"
}, },
{ {
"path": "tests/s2_00/test_resolver_source_lock.py", "path": "tests/s2_00/test_resolver_source_lock.py",
"sha256": "235e05985fb4b574c59cc44ff1cc803f4ec064d7f0fdb7fcf8c694e93d445fe0", "sha256": "51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e",
"status": "DEV_HASH_BOUND" "status": "DEV_HASH_BOUND"
}, },
{ {
@@ -13,7 +13,6 @@ import yaml
ROOT = Path(__file__).resolve().parents[2] ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT)) sys.path.insert(0, str(ROOT))
from runtime import s2_00_ingress as s2 # noqa: E402 from runtime import s2_00_ingress as s2 # noqa: E402
from release_ops import stage2_loader as loader # noqa: E402
def members() -> list[dict[str, object]]: def members() -> list[dict[str, object]]:
@@ -296,7 +295,21 @@ class ClusterAndBundleTests(unittest.TestCase):
) )
stage = workflow["Agent"]["Stages"][0] stage = workflow["Agent"]["Stages"][0]
handoff = stage["handoff_contract"] handoff = stage["handoff_contract"]
required = set(handoff["item_contract"]["required_fields"]) required_fields = handoff["item_contract"]["required_fields"]
self.assertEqual(
required_fields,
[
"run_id",
"cluster_id",
"cluster_slice_json",
"cluster_slice_sha256",
"executable_bundle_json",
"executable_bundle_sha256",
"input_set_digest",
"stage2_release_digest",
],
)
required = set(required_fields)
self.assertNotIn("materialized_static_prefix_text", required) self.assertNotIn("materialized_static_prefix_text", required)
self.assertNotIn("materialization_receipt_json", required) self.assertNotIn("materialization_receipt_json", required)
self.assertIn("executable_bundle_json", required) self.assertIn("executable_bundle_json", required)
@@ -331,13 +344,17 @@ class ClusterAndBundleTests(unittest.TestCase):
self.assertTrue(materialization["verify_raw_sha256_before_decode"]) self.assertTrue(materialization["verify_raw_sha256_before_decode"])
self.assertTrue(materialization["verify_canonical_sha256_after_decode"]) self.assertTrue(materialization["verify_canonical_sha256_after_decode"])
self.assertFalse(materialization["llm_filesystem_resolution_allowed"]) self.assertFalse(materialization["llm_filesystem_resolution_allowed"])
self.assertFalse(handoff["raw_stage1_reread_allowed"])
self.assertFalse(handoff["file_write_allowed"])
self.assertFalse(handoff["tool_calls_allowed"])
self.assertTrue(handoff["item_contract"]["exact_cluster_membership_required"])
task = stage["tasks"][0] task = stage["tasks"][0]
self.assertNotIn("llm_model", task) self.assertNotIn("llm_model", task)
self.assertNotIn("llm_reasoning", task) self.assertNotIn("llm_reasoning", task)
self.assertEqual( self.assertEqual(
task["deployment_binding_ref"], task["deployment_binding_ref"],
"deployment/stage2_loader_binding.yml#/downstream_llm_candidate_bindings/0", "deployment/stage2_code_executor_binding.yml#/downstream_llm_candidate_bindings/0",
) )
assembly = task["prompt_assembly"] assembly = task["prompt_assembly"]
self.assertEqual( self.assertEqual(
@@ -357,8 +374,10 @@ class ClusterAndBundleTests(unittest.TestCase):
"prompt_assembly.static_prefix", "prompt_assembly.static_prefix",
) )
binding = json.loads( binding = yaml.safe_load(
(ROOT / "deployment/stage2_loader_binding.yml").read_text(encoding="utf-8") (ROOT / "deployment/stage2_code_executor_binding.yml").read_text(
encoding="utf-8"
)
) )
candidate = binding["downstream_llm_candidate_bindings"] candidate = binding["downstream_llm_candidate_bindings"]
self.assertEqual(len(candidate), 1) self.assertEqual(len(candidate), 1)
@@ -385,53 +404,61 @@ class ClusterAndBundleTests(unittest.TestCase):
stage["handoff_contract"]["final_status_fields"]["legal_readiness"], stage["handoff_contract"]["final_status_fields"]["legal_readiness"],
["NOT_ASSESSED"], ["NOT_ASSESSED"],
) )
expected_inputs = [
"ingress/ingress_status.json",
"ingress/technical_diagnostic.json",
"ingress/stage1_input_manifest.json",
"ingress/intake_report.json",
"review/issue_ledger.base.json",
]
self.assertEqual(stage["handoff_contract"]["exact_input_count"], 5)
self.assertEqual(stage["handoff_contract"]["exact_inputs"], expected_inputs)
self.assertEqual(task["exact_input_files"], expected_inputs)
self.assertFalse(stage["handoff_contract"]["additional_input_allowed"])
self.assertEqual(
workflow["Agent"]["metadata"]["final_status_single_writer"],
"S2_40",
)
self.assertFalse(
stage["prohibitions"]["final_status_writer_other_than_s2_40_allowed"]
)
self.assertEqual(stage["prohibitions"]["output_paths"], ["control/run_status.json"])
def test_release_oracle_verifies_module_manifest_and_binding_raw_bytes(self) -> None: def test_release_oracle_verifies_active_executor_cross_hashes(self) -> None:
with tempfile.TemporaryDirectory() as directory: release_path = ROOT / "manifest/stage2_release.json"
root = Path(directory).resolve() release = s2.load_json_strict(release_path.read_bytes())
module_path = root / loader.MODULE_MANIFEST_REF binding_path = ROOT / "deployment/stage2_code_executor_binding.yml"
binding_path = root / loader.BINDING_REF binding = yaml.safe_load(binding_path.read_text(encoding="utf-8"))
module_path.parent.mkdir(parents=True)
binding_path.parent.mkdir(parents=True)
module_path.write_bytes(b'{"modules":[]}\n')
binding_path.write_bytes(b'{"binding_id":"fixture"}\n')
def raw_sha256(path: Path) -> str: def assert_ref(ref: dict[str, str]) -> Path:
return hashlib.sha256(path.read_bytes()).hexdigest() path = ROOT / ref["path"]
self.assertTrue(path.is_file(), path)
self.assertEqual(hashlib.sha256(path.read_bytes()).hexdigest(), ref["sha256"])
return path
release = { assert_ref(release["module_manifest_ref"])
"module_manifest_ref": { self.assertEqual(
"asset_id": "MANIFEST-MODULE", release["executor_binding_ref"]["path"],
"path": loader.MODULE_MANIFEST_REF, "deployment/stage2_code_executor_binding.yml",
"sha256": raw_sha256(module_path), )
"schema_id": "stage2_module_manifest.v1", self.assertIn(
"binding_status": "BOUND", release["executor_binding_ref"]["binding_status"],
{
"EXTERNAL_TRUST_ROOT_PENDING_LIVE_ADMISSION",
"EXTERNAL_TRUST_ROOT_ADMITTED",
}, },
"loader_binding_ref": { )
"asset_id": "BINDING-S2_00", agent_path = assert_ref(binding["agent_script_ref"])
"path": loader.BINDING_REF, assert_ref(binding["workflow_contract_ref"])
"sha256": raw_sha256(binding_path), assert_ref(binding["inline_code_receipt_ref"])
"schema_id": "stage2_loader_binding.v1", bound_release_path = assert_ref(binding["stage2_release_ref"])
"binding_status": "BOUND", self.assertEqual(bound_release_path, release_path)
}, self.assertEqual(binding["expected_release_sha256"], binding["stage2_release_ref"]["sha256"])
} self.assertEqual(binding["expected_release_sha256"], hashlib.sha256(release_path.read_bytes()).hexdigest())
binding = { agent = yaml.safe_load(agent_path.read_text(encoding="utf-8"))
"module_manifest_ref": {"path": loader.MODULE_MANIFEST_REF}, code = agent["Agent"]["Stages"][0]["tasks"][0]["parameters"]["code"]
"stage2_release_ref": {"path": loader.RELEASE_REF}, self.assertEqual(hashlib.sha256(code.encode("utf-8")).hexdigest(), binding["canonical_code_sha256"])
} self.assertEqual(binding["agent_script_sha256"], binding["agent_script_ref"]["sha256"])
receipt = loader._validate_cross_binding(root, release, binding)
self.assertEqual([row["status"] for row in receipt], ["PASS", "PASS"])
module_path.write_bytes(b'{"modules":["tampered"]}\n')
with self.assertRaises(loader.LoaderError) as caught:
loader._validate_cross_binding(root, release, binding)
self.assertEqual(caught.exception.reason_code, "RELEASE_ORACLE_HASH_MISMATCH")
module_path.write_bytes(b'{"modules":[]}\n')
binding_path.write_bytes(b'{"binding_id":"tampered"}\n')
with self.assertRaises(loader.LoaderError) as caught:
loader._validate_cross_binding(root, release, binding)
self.assertEqual(caught.exception.reason_code, "RELEASE_ORACLE_HASH_MISMATCH")
if __name__ == "__main__": if __name__ == "__main__":
@@ -13,7 +13,6 @@ import yaml
ROOT = Path(__file__).resolve().parents[2] ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT)) sys.path.insert(0, str(ROOT))
from runtime import s2_00_ingress as s2 # noqa: E402 from runtime import s2_00_ingress as s2 # noqa: E402
from release_ops import stage2_loader as loader # noqa: E402
def members() -> list[dict[str, object]]: def members() -> list[dict[str, object]]:
@@ -296,7 +295,21 @@ class ClusterAndBundleTests(unittest.TestCase):
) )
stage = workflow["Agent"]["Stages"][0] stage = workflow["Agent"]["Stages"][0]
handoff = stage["handoff_contract"] handoff = stage["handoff_contract"]
required = set(handoff["item_contract"]["required_fields"]) required_fields = handoff["item_contract"]["required_fields"]
self.assertEqual(
required_fields,
[
"run_id",
"cluster_id",
"cluster_slice_json",
"cluster_slice_sha256",
"executable_bundle_json",
"executable_bundle_sha256",
"input_set_digest",
"stage2_release_digest",
],
)
required = set(required_fields)
self.assertNotIn("materialized_static_prefix_text", required) self.assertNotIn("materialized_static_prefix_text", required)
self.assertNotIn("materialization_receipt_json", required) self.assertNotIn("materialization_receipt_json", required)
self.assertIn("executable_bundle_json", required) self.assertIn("executable_bundle_json", required)
@@ -331,13 +344,17 @@ class ClusterAndBundleTests(unittest.TestCase):
self.assertTrue(materialization["verify_raw_sha256_before_decode"]) self.assertTrue(materialization["verify_raw_sha256_before_decode"])
self.assertTrue(materialization["verify_canonical_sha256_after_decode"]) self.assertTrue(materialization["verify_canonical_sha256_after_decode"])
self.assertFalse(materialization["llm_filesystem_resolution_allowed"]) self.assertFalse(materialization["llm_filesystem_resolution_allowed"])
self.assertFalse(handoff["raw_stage1_reread_allowed"])
self.assertFalse(handoff["file_write_allowed"])
self.assertFalse(handoff["tool_calls_allowed"])
self.assertTrue(handoff["item_contract"]["exact_cluster_membership_required"])
task = stage["tasks"][0] task = stage["tasks"][0]
self.assertNotIn("llm_model", task) self.assertNotIn("llm_model", task)
self.assertNotIn("llm_reasoning", task) self.assertNotIn("llm_reasoning", task)
self.assertEqual( self.assertEqual(
task["deployment_binding_ref"], task["deployment_binding_ref"],
"deployment/stage2_loader_binding.yml#/downstream_llm_candidate_bindings/0", "deployment/stage2_code_executor_binding.yml#/downstream_llm_candidate_bindings/0",
) )
assembly = task["prompt_assembly"] assembly = task["prompt_assembly"]
self.assertEqual( self.assertEqual(
@@ -357,8 +374,10 @@ class ClusterAndBundleTests(unittest.TestCase):
"prompt_assembly.static_prefix", "prompt_assembly.static_prefix",
) )
binding = json.loads( binding = yaml.safe_load(
(ROOT / "deployment/stage2_loader_binding.yml").read_text(encoding="utf-8") (ROOT / "deployment/stage2_code_executor_binding.yml").read_text(
encoding="utf-8"
)
) )
candidate = binding["downstream_llm_candidate_bindings"] candidate = binding["downstream_llm_candidate_bindings"]
self.assertEqual(len(candidate), 1) self.assertEqual(len(candidate), 1)
@@ -385,53 +404,61 @@ class ClusterAndBundleTests(unittest.TestCase):
stage["handoff_contract"]["final_status_fields"]["legal_readiness"], stage["handoff_contract"]["final_status_fields"]["legal_readiness"],
["NOT_ASSESSED"], ["NOT_ASSESSED"],
) )
expected_inputs = [
"ingress/ingress_status.json",
"ingress/technical_diagnostic.json",
"ingress/stage1_input_manifest.json",
"ingress/intake_report.json",
"review/issue_ledger.base.json",
]
self.assertEqual(stage["handoff_contract"]["exact_input_count"], 5)
self.assertEqual(stage["handoff_contract"]["exact_inputs"], expected_inputs)
self.assertEqual(task["exact_input_files"], expected_inputs)
self.assertFalse(stage["handoff_contract"]["additional_input_allowed"])
self.assertEqual(
workflow["Agent"]["metadata"]["final_status_single_writer"],
"S2_40",
)
self.assertFalse(
stage["prohibitions"]["final_status_writer_other_than_s2_40_allowed"]
)
self.assertEqual(stage["prohibitions"]["output_paths"], ["control/run_status.json"])
def test_release_oracle_verifies_module_manifest_and_binding_raw_bytes(self) -> None: def test_release_oracle_verifies_active_executor_cross_hashes(self) -> None:
with tempfile.TemporaryDirectory() as directory: release_path = ROOT / "manifest/stage2_release.json"
root = Path(directory).resolve() release = s2.load_json_strict(release_path.read_bytes())
module_path = root / loader.MODULE_MANIFEST_REF binding_path = ROOT / "deployment/stage2_code_executor_binding.yml"
binding_path = root / loader.BINDING_REF binding = yaml.safe_load(binding_path.read_text(encoding="utf-8"))
module_path.parent.mkdir(parents=True)
binding_path.parent.mkdir(parents=True)
module_path.write_bytes(b'{"modules":[]}\n')
binding_path.write_bytes(b'{"binding_id":"fixture"}\n')
def raw_sha256(path: Path) -> str: def assert_ref(ref: dict[str, str]) -> Path:
return hashlib.sha256(path.read_bytes()).hexdigest() path = ROOT / ref["path"]
self.assertTrue(path.is_file(), path)
self.assertEqual(hashlib.sha256(path.read_bytes()).hexdigest(), ref["sha256"])
return path
release = { assert_ref(release["module_manifest_ref"])
"module_manifest_ref": { self.assertEqual(
"asset_id": "MANIFEST-MODULE", release["executor_binding_ref"]["path"],
"path": loader.MODULE_MANIFEST_REF, "deployment/stage2_code_executor_binding.yml",
"sha256": raw_sha256(module_path), )
"schema_id": "stage2_module_manifest.v1", self.assertIn(
"binding_status": "BOUND", release["executor_binding_ref"]["binding_status"],
{
"EXTERNAL_TRUST_ROOT_PENDING_LIVE_ADMISSION",
"EXTERNAL_TRUST_ROOT_ADMITTED",
}, },
"loader_binding_ref": { )
"asset_id": "BINDING-S2_00", agent_path = assert_ref(binding["agent_script_ref"])
"path": loader.BINDING_REF, assert_ref(binding["workflow_contract_ref"])
"sha256": raw_sha256(binding_path), assert_ref(binding["inline_code_receipt_ref"])
"schema_id": "stage2_loader_binding.v1", bound_release_path = assert_ref(binding["stage2_release_ref"])
"binding_status": "BOUND", self.assertEqual(bound_release_path, release_path)
}, self.assertEqual(binding["expected_release_sha256"], binding["stage2_release_ref"]["sha256"])
} self.assertEqual(binding["expected_release_sha256"], hashlib.sha256(release_path.read_bytes()).hexdigest())
binding = { agent = yaml.safe_load(agent_path.read_text(encoding="utf-8"))
"module_manifest_ref": {"path": loader.MODULE_MANIFEST_REF}, code = agent["Agent"]["Stages"][0]["tasks"][0]["parameters"]["code"]
"stage2_release_ref": {"path": loader.RELEASE_REF}, self.assertEqual(hashlib.sha256(code.encode("utf-8")).hexdigest(), binding["canonical_code_sha256"])
} self.assertEqual(binding["agent_script_sha256"], binding["agent_script_ref"]["sha256"])
receipt = loader._validate_cross_binding(root, release, binding)
self.assertEqual([row["status"] for row in receipt], ["PASS", "PASS"])
module_path.write_bytes(b'{"modules":["tampered"]}\n')
with self.assertRaises(loader.LoaderError) as caught:
loader._validate_cross_binding(root, release, binding)
self.assertEqual(caught.exception.reason_code, "RELEASE_ORACLE_HASH_MISMATCH")
module_path.write_bytes(b'{"modules":[]}\n')
binding_path.write_bytes(b'{"binding_id":"tampered"}\n')
with self.assertRaises(loader.LoaderError) as caught:
loader._validate_cross_binding(root, release, binding)
self.assertEqual(caught.exception.reason_code, "RELEASE_ORACLE_HASH_MISMATCH")
if __name__ == "__main__": if __name__ == "__main__":
@@ -1,12 +1,13 @@
from __future__ import annotations from __future__ import annotations
import hashlib import hashlib
import io
import json import json
from pathlib import Path from pathlib import Path
import subprocess
import sys import sys
import tempfile import tempfile
import unittest import unittest
from unittest import mock
ROOT = Path(__file__).resolve().parents[2] ROOT = Path(__file__).resolve().parents[2]
@@ -14,27 +15,79 @@ sys.path.insert(0, str(ROOT))
from runtime import s2_00_ingress as s2 # noqa: E402 from runtime import s2_00_ingress as s2 # noqa: E402
class MemoryLocaldocs:
def __init__(self) -> None:
self.files: dict[str, bytes] = {}
self.operations: list[tuple[str, str]] = []
def read_binary_optional(self, path: str) -> bytes | None:
self.operations.append(("read_optional", path))
return self.files.get(path)
def read_binary(self, path: str) -> bytes:
self.operations.append(("read", path))
if path not in self.files:
raise s2.IngressError("LOCALDOCS_NOT_FOUND", f"missing: {path}")
return self.files[path]
def write_binary_verified(self, path: str, payload: bytes) -> str:
self.operations.append(("write", path))
self.files[path] = payload
self.operations.append(("read", path))
if self.files[path] != payload:
raise AssertionError("memory read-back failed")
return hashlib.sha256(payload).hexdigest()
class CaptureStdout:
def __init__(self) -> None:
self.buffer = io.BytesIO()
def write(self, _text: str) -> int:
raise AssertionError("receipt must be written through stdout.buffer")
def flush(self) -> None:
return None
class FailureAndAtomicPublishTests(unittest.TestCase): class FailureAndAtomicPublishTests(unittest.TestCase):
def _artifacts(self, route: str = "TO_S2_10") -> dict[str, object]: def _artifacts(self, route: str = "TO_S2_10") -> dict[str, object]:
binding_digest = "a" * 64
run_id = f"S2RUN-{binding_digest}"
run_binding = { run_binding = {
"schema_version": "stage2_s2_00_run_binding_receipt.v1", "schema_version": "stage2_s2_00_run_binding_receipt.v1.1",
"run_id": "RUN-1", "request_id": "REQUEST-1",
"run_id": run_id,
"input_set_digest": "1" * 64, "input_set_digest": "1" * 64,
"stage2_release_digest": "2" * 64, "stage2_release_digest": "2" * 64,
"algorithm_digest": "3" * 64, "algorithm_digest": "3" * 64,
"release_class": "SUBSET_CANARY_RELEASE", "release_class": "SUBSET_CANARY_RELEASE",
"run_binding_digest": "a" * 64, "run_binding_digest": binding_digest,
"canonical_output_root": f"stage2_runs/by-binding/{binding_digest}/",
"run_identity_derivation": "RUN_ID_PREFIXED_FROM_RUN_BINDING_DIGEST",
"output_root_derivation": "stage2_runs/by-binding/<run_binding_digest>/",
"user_context_sha256": "4" * 64, "user_context_sha256": "4" * 64,
"workspace_context_sha256": "5" * 64, "workspace_context_sha256": "5" * 64,
} }
manifest = { manifest = {
"schema_version": "stage2_s2_00_stage1_input_manifest.v1", "schema_version": "stage2_s2_00_stage1_input_manifest.v1.1",
"run_id": "RUN-1", "run_id": run_id,
"release_class": "SUBSET_CANARY_RELEASE", "release_class": "SUBSET_CANARY_RELEASE",
"source_rows": [], "source_rows": [],
"source_row_order": [], "source_row_order": [],
"signal_all_adapter_id": "S2A-SIGNAL-ALL-V1", "signal_all_adapter_id": "S2A-SIGNAL-ALL-V1",
"dual_sg01_adapter_id": "S2A-DUAL-SG01-V1", "dual_sg01_adapter_id": "S2A-DUAL-SG01-V1",
"hydration_stability_receipt": {
"schema_version": "stage2_s2_00_two_pass_hydration_receipt.v1",
"transport": "localdocs.read_binary_doc",
"read_policy": "BOUNDED_TWO_PASS_BINARY_RAW_HASH_MAP_EQUALITY",
"read_pass_count": 2,
"max_read_passes": 2,
"pass_1_raw_hash_map_digest": "6" * 64,
"pass_2_raw_hash_map_digest": "6" * 64,
"source_receipts": [],
"stability_status": "STABLE",
},
"snapshot_start_digest": "6" * 64, "snapshot_start_digest": "6" * 64,
"snapshot_end_digest": "6" * 64, "snapshot_end_digest": "6" * 64,
"snapshot_status": "STABLE", "snapshot_status": "STABLE",
@@ -42,7 +95,7 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
} }
intake = { intake = {
"schema_version": "stage2_s2_00_intake_report.v1", "schema_version": "stage2_s2_00_intake_report.v1",
"run_id": "RUN-1", "run_id": run_id,
"source_counts": { "source_counts": {
"declared": 0, "declared": 0,
"observed": 0, "observed": 0,
@@ -74,7 +127,7 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
ledger = { ledger = {
"schema_version": "stage2_issue_ledger_base.v1", "schema_version": "stage2_issue_ledger_base.v1",
"producer_id": "S2_00", "producer_id": "S2_00",
"run_id": "RUN-1", "run_id": run_id,
"input_set_digest": "1" * 64, "input_set_digest": "1" * 64,
"mapping_table_version": "S2-REVIEW-MAP-V1", "mapping_table_version": "S2-REVIEW-MAP-V1",
"issues": [], "issues": [],
@@ -87,8 +140,8 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
"ingress/intake_report.json": intake, "ingress/intake_report.json": intake,
"review/issue_ledger.base.json": ledger, "review/issue_ledger.base.json": ledger,
"ingress/ingress_status.json": { "ingress/ingress_status.json": {
"schema_version": "stage2_s2_00_ingress_status.v1", "schema_version": "stage2_s2_00_ingress_status.v1.1",
"run_id": "RUN-1", "run_id": run_id,
"run_binding_receipt": run_binding, "run_binding_receipt": run_binding,
"route": route, "route": route,
"executable_cluster_ids": ["CL-" + "a" * 24], "executable_cluster_ids": ["CL-" + "a" * 24],
@@ -96,9 +149,13 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
"issue_codes": [], "issue_codes": [],
"output_barrier": { "output_barrier": {
"barrier_id": "S2_00_INGRESS_STATUS_BARRIER", "barrier_id": "S2_00_INGRESS_STATUS_BARRIER",
"barrier_path": "ingress/ingress_status.json",
"publish_semantics": "STATUS_LAST_LOGICAL_COMMIT",
"canonical_output_root": f"stage2_runs/by-binding/{binding_digest}/",
"branch": "NORMAL", "branch": "NORMAL",
"artifacts": [], "artifacts": [],
"artifact_set_digest": s2.canonical_digest([]), "artifact_set_digest": s2.canonical_digest([]),
"non_status_artifacts_read_back_verified": True,
"written_last": True, "written_last": True,
}, },
}, },
@@ -134,16 +191,208 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
self.assertEqual(raised.exception.code, "RUN_TUPLE_CONFLICT") self.assertEqual(raised.exception.code, "RUN_TUPLE_CONFLICT")
self.assertEqual((output / "ingress" / "ingress_status.json").read_bytes(), original) self.assertEqual((output / "ingress" / "ingress_status.json").read_bytes(), original)
def test_remote_publish_is_status_last_and_idempotent(self) -> None:
binding = "a" * 64
with tempfile.TemporaryDirectory() as directory:
local_output = Path(directory) / "core"
s2.publish_atomically(
local_output,
self._artifacts(),
run_binding_digest=binding,
attempt_id="A-REMOTE",
)
files = s2._inline_output_files(local_output, binding)
localdocs = MemoryLocaldocs()
receipt = s2._inline_publish_remote(localdocs, files, binding)
self.assertEqual(receipt["publication_status"], "PUBLISHED_STATUS_LAST")
self.assertEqual(receipt["schema_version"], "stage2_logical_publish_receipt.v1")
self.assertEqual(receipt["run_binding_digest"], binding)
self.assertEqual(receipt["canonical_output_root"], f"stage2_runs/by-binding/{binding}/")
self.assertTrue(receipt["barrier_written_last"])
self.assertTrue(receipt["non_status_artifacts_read_back_verified"])
self.assertEqual(
receipt["artifact_set_digest"],
s2.canonical_digest(receipt["artifacts"]),
)
self.assertTrue(all("byte_length" in row for row in receipt["artifacts"]))
writes = [row for row in localdocs.operations if row[0] == "write"]
self.assertTrue(writes)
self.assertTrue(writes[-1][1].endswith("/ingress/ingress_status.json"))
before = list(localdocs.operations)
repeated = s2._inline_publish_remote(localdocs, files, binding)
self.assertEqual(repeated["publication_status"], "IDEMPOTENT_SUCCESS")
self.assertFalse(any(op == "write" for op, _path in localdocs.operations[len(before) :]))
def test_localdocs_write_requires_byte_identical_readback(self) -> None:
class Response:
def __init__(self, payload: object) -> None:
self.content = json.dumps(payload).encode("utf-8")
self.headers = {"mcp-session-id": "session-a"}
def raise_for_status(self) -> None:
return None
class Client:
def __init__(self) -> None:
wrong = b"wrong"
self.responses = [
Response(
{
"jsonrpc": "2.0",
"id": 10,
"result": {"content": [{"type": "text", "text": "{}"}]},
}
),
Response(
{
"jsonrpc": "2.0",
"id": 11,
"result": {
"content": [
{
"type": "text",
"text": json.dumps(
{
"content_base64": __import__("base64").b64encode(wrong).decode("ascii"),
"byte_length": len(wrong),
"sha256": hashlib.sha256(wrong).hexdigest(),
}
),
}
]
},
}
),
]
def post(self, *_args: object, **_kwargs: object) -> Response:
return self.responses.pop(0)
def close(self) -> None:
return None
localdocs = s2._InlineLocaldocs("a" * 64, "b" * 64, client=Client())
localdocs._initialized = True
localdocs._session_id = "session-a"
localdocs.headers["mcp-session-id"] = "session-a"
with self.assertRaises(s2.IngressError) as raised:
localdocs.write_binary_verified("stage2_runs/by-binding/" + "a" * 64 + "/x.json", b"expected")
self.assertEqual(raised.exception.code, "LOCALDOCS_WRITE_READBACK_MISMATCH")
def test_inline_runner_suppresses_internal_stdout_and_emits_schema_shaped_receipts(self) -> None:
class NoisyLocaldocs:
def __init__(self, *_args: object, **_kwargs: object) -> None:
return None
def initialize(self) -> None:
print("internal initialize noise")
def close(self) -> None:
print("internal close noise")
binding = "a" * 64
logical_receipt = {
"schema_version": "stage2_logical_publish_receipt.v1",
"barrier_id": "S2_00_INGRESS_STATUS_BARRIER",
"barrier_path": "ingress/ingress_status.json",
"publish_semantics": "STATUS_LAST_LOGICAL_COMMIT",
"canonical_output_root": f"stage2_runs/by-binding/{binding}/",
"run_binding_digest": binding,
"branch": "NORMAL",
"artifacts": [],
"artifact_set_digest": s2.canonical_digest([]),
"barrier_raw_sha256": "b" * 64,
"non_status_artifacts_read_back_verified": True,
"barrier_written_last": True,
"downstream_consumption_allowed": True,
"publication_status": "PUBLISHED_STATUS_LAST",
}
capture = CaptureStdout()
with (
mock.patch.object(s2.sys, "stdout", capture),
mock.patch.object(s2, "_InlineLocaldocs", NoisyLocaldocs),
mock.patch.object(
s2,
"_inline_hydrate",
return_value=(
{"request_id": "REQUEST-1", "attempt_id": "ATTEMPT-1"},
{},
Path("stage1"),
Path("stage1_deployment"),
Path("stage2_assets"),
{},
),
),
mock.patch.object(s2, "load_release_lock", return_value={}),
mock.patch.object(s2, "_load_bound_contract_manifest", return_value=None),
mock.patch.object(
s2,
"execute_ingress",
side_effect=lambda *_args, **_kwargs: (
print("internal core noise")
or {"route": "TO_S2_10", "run_binding_digest": binding}
),
),
mock.patch.object(s2, "_inline_output_files", return_value={}),
mock.patch.object(s2, "_inline_publish_remote", return_value=logical_receipt),
):
self.assertEqual(s2.run_inline_mcp(), 0)
success = json.loads(capture.buffer.getvalue())
self.assertTrue(success["ok"])
self.assertEqual(success["workflow_id"], "S2_00")
self.assertEqual(success["status"], "SUCCEEDED")
self.assertEqual(success["run_id"], f"S2RUN-{binding}")
self.assertEqual(success["logical_publish_receipt"], logical_receipt)
self.assertNotIn(b"noise", capture.buffer.getvalue())
class FailingLocaldocs(NoisyLocaldocs):
def initialize(self) -> None:
print("failure noise")
raise s2.IngressError("FORCED_FAILURE", "forced")
capture = CaptureStdout()
with mock.patch.object(s2.sys, "stdout", capture), mock.patch.object(
s2,
"_InlineLocaldocs",
FailingLocaldocs,
):
self.assertEqual(s2.run_inline_mcp(), 2)
failure = json.loads(capture.buffer.getvalue())
self.assertFalse(failure["ok"])
self.assertEqual(failure["workflow_id"], "S2_00")
self.assertEqual(failure["status"], "FAILED_NO_BARRIER")
self.assertEqual(failure["expected_release_sha256"], s2.EXPECTED_STAGE2_RELEASE_SHA256)
self.assertEqual(failure["error"]["code"], "FORCED_FAILURE")
def test_existing_remote_status_with_other_binding_blocks_all_writes(self) -> None:
binding = "a" * 64
with tempfile.TemporaryDirectory() as directory:
local_output = Path(directory) / "core"
s2.publish_atomically(
local_output,
self._artifacts(),
run_binding_digest=binding,
attempt_id="A-CONFLICT",
)
files = s2._inline_output_files(local_output, binding)
localdocs = MemoryLocaldocs()
output_root = f"stage2_runs/by-binding/{binding}"
status_path = f"{output_root}/ingress/ingress_status.json"
conflict = json.loads(files["ingress/ingress_status.json"])
conflict["run_binding_receipt"]["run_binding_digest"] = "b" * 64
localdocs.files[status_path] = s2.canonical_json_bytes(conflict)
with self.assertRaises(s2.IngressError) as raised:
s2._inline_publish_remote(localdocs, files, binding)
self.assertEqual(raised.exception.code, "RUN_ID_BINDING_CONFLICT")
self.assertFalse(any(op == "write" for op, _path in localdocs.operations))
def test_structural_fixture_cli_stdout_is_one_json_and_does_not_publish(self) -> None: def test_structural_fixture_cli_stdout_is_one_json_and_does_not_publish(self) -> None:
release_path = ROOT / "manifest" / "stage2_release.json" release_path = ROOT / "manifest" / "stage2_release.json"
fixture_path = ROOT / "tests" / "fixtures" / "cases" / "case_001_minimal_single_domain_single_cluster.json" fixture_path = ROOT / "tests" / "fixtures" / "cases" / "case_001_minimal_single_domain_single_cluster.json"
direct = s2._execute_structural_fixture(fixture_path, s2.load_release_lock(release_path)) direct = s2._execute_structural_fixture(fixture_path, s2.load_release_lock(release_path))
self.assertFalse(direct["published"]) self.assertFalse(direct["published"])
project_root = ROOT.parents[3] project_root = ROOT.parents[3]
completed = subprocess.run( argv = [
[
sys.executable,
str(ROOT / "runtime" / "s2_00_ingress.py"),
"--workflow-id", "--workflow-id",
"S2_00", "S2_00",
"--release-ref", "--release-ref",
@@ -160,27 +409,21 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
str(project_root), str(project_root),
"--stage1-deployment-root-ref", "--stage1-deployment-root-ref",
str(project_root), str(project_root),
], ]
check=False, capture = CaptureStdout()
capture_output=True, with mock.patch.object(s2.sys, "stdout", capture):
text=True, returncode = s2.main(argv)
timeout=10, self.assertEqual(returncode, 2, capture.buffer.getvalue())
) parsed = json.loads(capture.buffer.getvalue())
self.assertEqual(completed.returncode, 2, completed.stdout)
parsed = json.loads(completed.stdout)
self.assertFalse(parsed["ok"]) self.assertFalse(parsed["ok"])
self.assertEqual(parsed["error"]["code"], "DEV_FIXTURE_REAL_RUN_FORBIDDEN") self.assertEqual(parsed["error"]["code"], "DEV_FIXTURE_REAL_RUN_FORBIDDEN")
self.assertFalse((project_root / "stage2_runs" / "UNIT-CLI-DEV-NOPUBLISH").exists()) self.assertFalse((project_root / "stage2_runs" / "UNIT-CLI-DEV-NOPUBLISH").exists())
self.assertEqual(completed.stderr, "")
def test_structural_fixture_cannot_accept_output_argument(self) -> None: def test_structural_fixture_cannot_accept_output_argument(self) -> None:
with tempfile.TemporaryDirectory() as directory: with tempfile.TemporaryDirectory() as directory:
root = Path(directory) root = Path(directory)
project_root = ROOT.parents[3] project_root = ROOT.parents[3]
completed = subprocess.run( argv = [
[
sys.executable,
str(ROOT / "runtime" / "s2_00_ingress.py"),
"--workflow-id", "--workflow-id",
"S2_00", "S2_00",
"--release-ref", "--release-ref",
@@ -199,14 +442,12 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
str(project_root), str(project_root),
"--output-dir", "--output-dir",
str(root / "forbidden"), str(root / "forbidden"),
], ]
check=False, capture = CaptureStdout()
capture_output=True, with mock.patch.object(s2.sys, "stdout", capture):
text=True, returncode = s2.main(argv)
timeout=10, self.assertEqual(returncode, 2)
) self.assertEqual(json.loads(capture.buffer.getvalue())["error"]["code"], "CLI_ARGUMENT_ERROR")
self.assertEqual(completed.returncode, 2)
self.assertEqual(json.loads(completed.stdout)["error"]["code"], "CLI_ARGUMENT_ERROR")
self.assertFalse((root / "forbidden").exists()) self.assertFalse((root / "forbidden").exists())
def test_fixture_inventory_has_all_ten_cases_and_single_defect_mutations(self) -> None: def test_fixture_inventory_has_all_ten_cases_and_single_defect_mutations(self) -> None:
@@ -1,12 +1,13 @@
from __future__ import annotations from __future__ import annotations
import hashlib import hashlib
import io
import json import json
from pathlib import Path from pathlib import Path
import subprocess
import sys import sys
import tempfile import tempfile
import unittest import unittest
from unittest import mock
ROOT = Path(__file__).resolve().parents[2] ROOT = Path(__file__).resolve().parents[2]
@@ -14,27 +15,79 @@ sys.path.insert(0, str(ROOT))
from runtime import s2_00_ingress as s2 # noqa: E402 from runtime import s2_00_ingress as s2 # noqa: E402
class MemoryLocaldocs:
def __init__(self) -> None:
self.files: dict[str, bytes] = {}
self.operations: list[tuple[str, str]] = []
def read_binary_optional(self, path: str) -> bytes | None:
self.operations.append(("read_optional", path))
return self.files.get(path)
def read_binary(self, path: str) -> bytes:
self.operations.append(("read", path))
if path not in self.files:
raise s2.IngressError("LOCALDOCS_NOT_FOUND", f"missing: {path}")
return self.files[path]
def write_binary_verified(self, path: str, payload: bytes) -> str:
self.operations.append(("write", path))
self.files[path] = payload
self.operations.append(("read", path))
if self.files[path] != payload:
raise AssertionError("memory read-back failed")
return hashlib.sha256(payload).hexdigest()
class CaptureStdout:
def __init__(self) -> None:
self.buffer = io.BytesIO()
def write(self, _text: str) -> int:
raise AssertionError("receipt must be written through stdout.buffer")
def flush(self) -> None:
return None
class FailureAndAtomicPublishTests(unittest.TestCase): class FailureAndAtomicPublishTests(unittest.TestCase):
def _artifacts(self, route: str = "TO_S2_10") -> dict[str, object]: def _artifacts(self, route: str = "TO_S2_10") -> dict[str, object]:
binding_digest = "a" * 64
run_id = f"S2RUN-{binding_digest}"
run_binding = { run_binding = {
"schema_version": "stage2_s2_00_run_binding_receipt.v1", "schema_version": "stage2_s2_00_run_binding_receipt.v1.1",
"run_id": "RUN-1", "request_id": "REQUEST-1",
"run_id": run_id,
"input_set_digest": "1" * 64, "input_set_digest": "1" * 64,
"stage2_release_digest": "2" * 64, "stage2_release_digest": "2" * 64,
"algorithm_digest": "3" * 64, "algorithm_digest": "3" * 64,
"release_class": "SUBSET_CANARY_RELEASE", "release_class": "SUBSET_CANARY_RELEASE",
"run_binding_digest": "a" * 64, "run_binding_digest": binding_digest,
"canonical_output_root": f"stage2_runs/by-binding/{binding_digest}/",
"run_identity_derivation": "RUN_ID_PREFIXED_FROM_RUN_BINDING_DIGEST",
"output_root_derivation": "stage2_runs/by-binding/<run_binding_digest>/",
"user_context_sha256": "4" * 64, "user_context_sha256": "4" * 64,
"workspace_context_sha256": "5" * 64, "workspace_context_sha256": "5" * 64,
} }
manifest = { manifest = {
"schema_version": "stage2_s2_00_stage1_input_manifest.v1", "schema_version": "stage2_s2_00_stage1_input_manifest.v1.1",
"run_id": "RUN-1", "run_id": run_id,
"release_class": "SUBSET_CANARY_RELEASE", "release_class": "SUBSET_CANARY_RELEASE",
"source_rows": [], "source_rows": [],
"source_row_order": [], "source_row_order": [],
"signal_all_adapter_id": "S2A-SIGNAL-ALL-V1", "signal_all_adapter_id": "S2A-SIGNAL-ALL-V1",
"dual_sg01_adapter_id": "S2A-DUAL-SG01-V1", "dual_sg01_adapter_id": "S2A-DUAL-SG01-V1",
"hydration_stability_receipt": {
"schema_version": "stage2_s2_00_two_pass_hydration_receipt.v1",
"transport": "localdocs.read_binary_doc",
"read_policy": "BOUNDED_TWO_PASS_BINARY_RAW_HASH_MAP_EQUALITY",
"read_pass_count": 2,
"max_read_passes": 2,
"pass_1_raw_hash_map_digest": "6" * 64,
"pass_2_raw_hash_map_digest": "6" * 64,
"source_receipts": [],
"stability_status": "STABLE",
},
"snapshot_start_digest": "6" * 64, "snapshot_start_digest": "6" * 64,
"snapshot_end_digest": "6" * 64, "snapshot_end_digest": "6" * 64,
"snapshot_status": "STABLE", "snapshot_status": "STABLE",
@@ -42,7 +95,7 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
} }
intake = { intake = {
"schema_version": "stage2_s2_00_intake_report.v1", "schema_version": "stage2_s2_00_intake_report.v1",
"run_id": "RUN-1", "run_id": run_id,
"source_counts": { "source_counts": {
"declared": 0, "declared": 0,
"observed": 0, "observed": 0,
@@ -74,7 +127,7 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
ledger = { ledger = {
"schema_version": "stage2_issue_ledger_base.v1", "schema_version": "stage2_issue_ledger_base.v1",
"producer_id": "S2_00", "producer_id": "S2_00",
"run_id": "RUN-1", "run_id": run_id,
"input_set_digest": "1" * 64, "input_set_digest": "1" * 64,
"mapping_table_version": "S2-REVIEW-MAP-V1", "mapping_table_version": "S2-REVIEW-MAP-V1",
"issues": [], "issues": [],
@@ -87,8 +140,8 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
"ingress/intake_report.json": intake, "ingress/intake_report.json": intake,
"review/issue_ledger.base.json": ledger, "review/issue_ledger.base.json": ledger,
"ingress/ingress_status.json": { "ingress/ingress_status.json": {
"schema_version": "stage2_s2_00_ingress_status.v1", "schema_version": "stage2_s2_00_ingress_status.v1.1",
"run_id": "RUN-1", "run_id": run_id,
"run_binding_receipt": run_binding, "run_binding_receipt": run_binding,
"route": route, "route": route,
"executable_cluster_ids": ["CL-" + "a" * 24], "executable_cluster_ids": ["CL-" + "a" * 24],
@@ -96,9 +149,13 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
"issue_codes": [], "issue_codes": [],
"output_barrier": { "output_barrier": {
"barrier_id": "S2_00_INGRESS_STATUS_BARRIER", "barrier_id": "S2_00_INGRESS_STATUS_BARRIER",
"barrier_path": "ingress/ingress_status.json",
"publish_semantics": "STATUS_LAST_LOGICAL_COMMIT",
"canonical_output_root": f"stage2_runs/by-binding/{binding_digest}/",
"branch": "NORMAL", "branch": "NORMAL",
"artifacts": [], "artifacts": [],
"artifact_set_digest": s2.canonical_digest([]), "artifact_set_digest": s2.canonical_digest([]),
"non_status_artifacts_read_back_verified": True,
"written_last": True, "written_last": True,
}, },
}, },
@@ -134,16 +191,208 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
self.assertEqual(raised.exception.code, "RUN_TUPLE_CONFLICT") self.assertEqual(raised.exception.code, "RUN_TUPLE_CONFLICT")
self.assertEqual((output / "ingress" / "ingress_status.json").read_bytes(), original) self.assertEqual((output / "ingress" / "ingress_status.json").read_bytes(), original)
def test_remote_publish_is_status_last_and_idempotent(self) -> None:
binding = "a" * 64
with tempfile.TemporaryDirectory() as directory:
local_output = Path(directory) / "core"
s2.publish_atomically(
local_output,
self._artifacts(),
run_binding_digest=binding,
attempt_id="A-REMOTE",
)
files = s2._inline_output_files(local_output, binding)
localdocs = MemoryLocaldocs()
receipt = s2._inline_publish_remote(localdocs, files, binding)
self.assertEqual(receipt["publication_status"], "PUBLISHED_STATUS_LAST")
self.assertEqual(receipt["schema_version"], "stage2_logical_publish_receipt.v1")
self.assertEqual(receipt["run_binding_digest"], binding)
self.assertEqual(receipt["canonical_output_root"], f"stage2_runs/by-binding/{binding}/")
self.assertTrue(receipt["barrier_written_last"])
self.assertTrue(receipt["non_status_artifacts_read_back_verified"])
self.assertEqual(
receipt["artifact_set_digest"],
s2.canonical_digest(receipt["artifacts"]),
)
self.assertTrue(all("byte_length" in row for row in receipt["artifacts"]))
writes = [row for row in localdocs.operations if row[0] == "write"]
self.assertTrue(writes)
self.assertTrue(writes[-1][1].endswith("/ingress/ingress_status.json"))
before = list(localdocs.operations)
repeated = s2._inline_publish_remote(localdocs, files, binding)
self.assertEqual(repeated["publication_status"], "IDEMPOTENT_SUCCESS")
self.assertFalse(any(op == "write" for op, _path in localdocs.operations[len(before) :]))
def test_localdocs_write_requires_byte_identical_readback(self) -> None:
class Response:
def __init__(self, payload: object) -> None:
self.content = json.dumps(payload).encode("utf-8")
self.headers = {"mcp-session-id": "session-a"}
def raise_for_status(self) -> None:
return None
class Client:
def __init__(self) -> None:
wrong = b"wrong"
self.responses = [
Response(
{
"jsonrpc": "2.0",
"id": 10,
"result": {"content": [{"type": "text", "text": "{}"}]},
}
),
Response(
{
"jsonrpc": "2.0",
"id": 11,
"result": {
"content": [
{
"type": "text",
"text": json.dumps(
{
"content_base64": __import__("base64").b64encode(wrong).decode("ascii"),
"byte_length": len(wrong),
"sha256": hashlib.sha256(wrong).hexdigest(),
}
),
}
]
},
}
),
]
def post(self, *_args: object, **_kwargs: object) -> Response:
return self.responses.pop(0)
def close(self) -> None:
return None
localdocs = s2._InlineLocaldocs("a" * 64, "b" * 64, client=Client())
localdocs._initialized = True
localdocs._session_id = "session-a"
localdocs.headers["mcp-session-id"] = "session-a"
with self.assertRaises(s2.IngressError) as raised:
localdocs.write_binary_verified("stage2_runs/by-binding/" + "a" * 64 + "/x.json", b"expected")
self.assertEqual(raised.exception.code, "LOCALDOCS_WRITE_READBACK_MISMATCH")
def test_inline_runner_suppresses_internal_stdout_and_emits_schema_shaped_receipts(self) -> None:
class NoisyLocaldocs:
def __init__(self, *_args: object, **_kwargs: object) -> None:
return None
def initialize(self) -> None:
print("internal initialize noise")
def close(self) -> None:
print("internal close noise")
binding = "a" * 64
logical_receipt = {
"schema_version": "stage2_logical_publish_receipt.v1",
"barrier_id": "S2_00_INGRESS_STATUS_BARRIER",
"barrier_path": "ingress/ingress_status.json",
"publish_semantics": "STATUS_LAST_LOGICAL_COMMIT",
"canonical_output_root": f"stage2_runs/by-binding/{binding}/",
"run_binding_digest": binding,
"branch": "NORMAL",
"artifacts": [],
"artifact_set_digest": s2.canonical_digest([]),
"barrier_raw_sha256": "b" * 64,
"non_status_artifacts_read_back_verified": True,
"barrier_written_last": True,
"downstream_consumption_allowed": True,
"publication_status": "PUBLISHED_STATUS_LAST",
}
capture = CaptureStdout()
with (
mock.patch.object(s2.sys, "stdout", capture),
mock.patch.object(s2, "_InlineLocaldocs", NoisyLocaldocs),
mock.patch.object(
s2,
"_inline_hydrate",
return_value=(
{"request_id": "REQUEST-1", "attempt_id": "ATTEMPT-1"},
{},
Path("stage1"),
Path("stage1_deployment"),
Path("stage2_assets"),
{},
),
),
mock.patch.object(s2, "load_release_lock", return_value={}),
mock.patch.object(s2, "_load_bound_contract_manifest", return_value=None),
mock.patch.object(
s2,
"execute_ingress",
side_effect=lambda *_args, **_kwargs: (
print("internal core noise")
or {"route": "TO_S2_10", "run_binding_digest": binding}
),
),
mock.patch.object(s2, "_inline_output_files", return_value={}),
mock.patch.object(s2, "_inline_publish_remote", return_value=logical_receipt),
):
self.assertEqual(s2.run_inline_mcp(), 0)
success = json.loads(capture.buffer.getvalue())
self.assertTrue(success["ok"])
self.assertEqual(success["workflow_id"], "S2_00")
self.assertEqual(success["status"], "SUCCEEDED")
self.assertEqual(success["run_id"], f"S2RUN-{binding}")
self.assertEqual(success["logical_publish_receipt"], logical_receipt)
self.assertNotIn(b"noise", capture.buffer.getvalue())
class FailingLocaldocs(NoisyLocaldocs):
def initialize(self) -> None:
print("failure noise")
raise s2.IngressError("FORCED_FAILURE", "forced")
capture = CaptureStdout()
with mock.patch.object(s2.sys, "stdout", capture), mock.patch.object(
s2,
"_InlineLocaldocs",
FailingLocaldocs,
):
self.assertEqual(s2.run_inline_mcp(), 2)
failure = json.loads(capture.buffer.getvalue())
self.assertFalse(failure["ok"])
self.assertEqual(failure["workflow_id"], "S2_00")
self.assertEqual(failure["status"], "FAILED_NO_BARRIER")
self.assertEqual(failure["expected_release_sha256"], s2.EXPECTED_STAGE2_RELEASE_SHA256)
self.assertEqual(failure["error"]["code"], "FORCED_FAILURE")
def test_existing_remote_status_with_other_binding_blocks_all_writes(self) -> None:
binding = "a" * 64
with tempfile.TemporaryDirectory() as directory:
local_output = Path(directory) / "core"
s2.publish_atomically(
local_output,
self._artifacts(),
run_binding_digest=binding,
attempt_id="A-CONFLICT",
)
files = s2._inline_output_files(local_output, binding)
localdocs = MemoryLocaldocs()
output_root = f"stage2_runs/by-binding/{binding}"
status_path = f"{output_root}/ingress/ingress_status.json"
conflict = json.loads(files["ingress/ingress_status.json"])
conflict["run_binding_receipt"]["run_binding_digest"] = "b" * 64
localdocs.files[status_path] = s2.canonical_json_bytes(conflict)
with self.assertRaises(s2.IngressError) as raised:
s2._inline_publish_remote(localdocs, files, binding)
self.assertEqual(raised.exception.code, "RUN_ID_BINDING_CONFLICT")
self.assertFalse(any(op == "write" for op, _path in localdocs.operations))
def test_structural_fixture_cli_stdout_is_one_json_and_does_not_publish(self) -> None: def test_structural_fixture_cli_stdout_is_one_json_and_does_not_publish(self) -> None:
release_path = ROOT / "manifest" / "stage2_release.json" release_path = ROOT / "manifest" / "stage2_release.json"
fixture_path = ROOT / "tests" / "fixtures" / "cases" / "case_001_minimal_single_domain_single_cluster.json" fixture_path = ROOT / "tests" / "fixtures" / "cases" / "case_001_minimal_single_domain_single_cluster.json"
direct = s2._execute_structural_fixture(fixture_path, s2.load_release_lock(release_path)) direct = s2._execute_structural_fixture(fixture_path, s2.load_release_lock(release_path))
self.assertFalse(direct["published"]) self.assertFalse(direct["published"])
project_root = ROOT.parents[3] project_root = ROOT.parents[3]
completed = subprocess.run( argv = [
[
sys.executable,
str(ROOT / "runtime" / "s2_00_ingress.py"),
"--workflow-id", "--workflow-id",
"S2_00", "S2_00",
"--release-ref", "--release-ref",
@@ -160,27 +409,21 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
str(project_root), str(project_root),
"--stage1-deployment-root-ref", "--stage1-deployment-root-ref",
str(project_root), str(project_root),
], ]
check=False, capture = CaptureStdout()
capture_output=True, with mock.patch.object(s2.sys, "stdout", capture):
text=True, returncode = s2.main(argv)
timeout=10, self.assertEqual(returncode, 2, capture.buffer.getvalue())
) parsed = json.loads(capture.buffer.getvalue())
self.assertEqual(completed.returncode, 2, completed.stdout)
parsed = json.loads(completed.stdout)
self.assertFalse(parsed["ok"]) self.assertFalse(parsed["ok"])
self.assertEqual(parsed["error"]["code"], "DEV_FIXTURE_REAL_RUN_FORBIDDEN") self.assertEqual(parsed["error"]["code"], "DEV_FIXTURE_REAL_RUN_FORBIDDEN")
self.assertFalse((project_root / "stage2_runs" / "UNIT-CLI-DEV-NOPUBLISH").exists()) self.assertFalse((project_root / "stage2_runs" / "UNIT-CLI-DEV-NOPUBLISH").exists())
self.assertEqual(completed.stderr, "")
def test_structural_fixture_cannot_accept_output_argument(self) -> None: def test_structural_fixture_cannot_accept_output_argument(self) -> None:
with tempfile.TemporaryDirectory() as directory: with tempfile.TemporaryDirectory() as directory:
root = Path(directory) root = Path(directory)
project_root = ROOT.parents[3] project_root = ROOT.parents[3]
completed = subprocess.run( argv = [
[
sys.executable,
str(ROOT / "runtime" / "s2_00_ingress.py"),
"--workflow-id", "--workflow-id",
"S2_00", "S2_00",
"--release-ref", "--release-ref",
@@ -199,14 +442,12 @@ class FailureAndAtomicPublishTests(unittest.TestCase):
str(project_root), str(project_root),
"--output-dir", "--output-dir",
str(root / "forbidden"), str(root / "forbidden"),
], ]
check=False, capture = CaptureStdout()
capture_output=True, with mock.patch.object(s2.sys, "stdout", capture):
text=True, returncode = s2.main(argv)
timeout=10, self.assertEqual(returncode, 2)
) self.assertEqual(json.loads(capture.buffer.getvalue())["error"]["code"], "CLI_ARGUMENT_ERROR")
self.assertEqual(completed.returncode, 2)
self.assertEqual(json.loads(completed.stdout)["error"]["code"], "CLI_ARGUMENT_ERROR")
self.assertFalse((root / "forbidden").exists()) self.assertFalse((root / "forbidden").exists())
def test_fixture_inventory_has_all_ten_cases_and_single_defect_mutations(self) -> None: def test_fixture_inventory_has_all_ten_cases_and_single_defect_mutations(self) -> None:
@@ -0,0 +1,281 @@
from __future__ import annotations
import json
from pathlib import Path
import sys
import tempfile
import unittest
from unittest import mock
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
from offline_build import build_s2_00_inline_projection as builder # noqa: E402
def valid_inline_code() -> str:
return "\n".join(
[
"#!/usr/bin/env python3",
"from __future__ import annotations",
"import json",
"import httpx",
"LOCALDOCS_URL = 'http://mcp-localdocs:8012/mcp'",
"USER_HASH = '{{__user_hash__}}'",
"WORKSPACE_HASH = '{{__workspace_hash__}}'",
"READ_TOOL = 'read_binary_doc'",
"WRITE_TOOL = 'write_binary_file'",
"expected_stage2_release_sha256 = '0' * 64",
"def main():",
" return {'status': 'OK'}",
"print(json.dumps(main(), ensure_ascii=False, sort_keys=True))",
]
)
def authoring_yaml(code: str | None = None) -> bytes:
source = valid_inline_code() if code is None else code
indented = "\n".join(f" {line}" for line in source.split("\n"))
return (
"Agent:\n"
" name: Stage_2_S2_00_v1\n"
" version: '1.1.0'\n"
" Stages:\n"
" - name: S2_00\n"
" tools:\n"
" mcpServers:\n"
" localdocs:\n"
" type: streamable-http\n"
" url: http://mcp-localdocs:8012/mcp\n"
" code-executor:\n"
" type: streamable-http\n"
" url: https://code-executor.mcp.eroomai.com/mcp\n"
" tasks:\n"
" - task_name: Task_S2_00_deterministic_ingress\n"
" mcp: code-executor\n"
" tool_name: run_code\n"
" parameters:\n"
" language: python\n"
" requirements: 'httpx==0.28.1'\n"
" network: agent-network\n"
" timeout: 300\n"
" code: |-\n"
f"{indented}\n"
" task_procedure:\n"
" IN:\n"
" nexts: [Task_S2_00_deterministic_ingress]\n"
" wait_until: []\n"
" Task_S2_00_deterministic_ingress:\n"
" nexts: [OUT]\n"
" wait_until: [IN]\n"
" OUT:\n"
" nexts: []\n"
" wait_until: [Task_S2_00_deterministic_ingress]\n"
" prevs: []\n"
" nexts: []\n"
).encode("utf-8")
class InlineCodeProjectionUnitTests(unittest.TestCase):
def test_unique_key_loader_rejects_duplicate_mapping_key(self) -> None:
with self.assertRaises(builder.ProjectionError) as raised:
builder.parse_authoring_bytes(b"Agent:\n name: one\n name: two\n")
self.assertEqual(raised.exception.code, "YAML_DUPLICATE_KEY")
def test_authoring_plaintext_secret_outside_code_is_rejected(self) -> None:
raw = authoring_yaml().replace(
b" version: '1.1.0'",
b" version: '1.1.0'\n leaked_token: 'Bearer abcdefghijklmnopqrstuvwxyz'",
)
with self.assertRaises(builder.ProjectionError) as raised:
builder.parse_authoring_bytes(raw)
self.assertEqual(raised.exception.code, "AUTHORING_PLAINTEXT_SECRET")
def test_parser_returned_code_bytes_are_not_transformed(self) -> None:
expected_code = valid_inline_code()
raw = authoring_yaml(expected_code)
document = builder.parse_authoring_bytes(raw)
_stage, task = builder.extract_run_code_task(document)
observed = task["parameters"]["code"]
self.assertEqual(observed, expected_code)
self.assertEqual(observed.encode("utf-8"), expected_code.encode("utf-8"))
self.assertFalse(observed.endswith("\n"))
def test_valid_code_compiles_and_has_closed_imports(self) -> None:
report = builder.validate_inline_code(valid_inline_code())
self.assertEqual(report["compile_status"], "PASS")
self.assertEqual(report["ast_status"], "PASS")
self.assertEqual(report["imports"], ["__future__", "httpx", "json"])
self.assertEqual(report["code_sha256"], builder.sha256_bytes(valid_inline_code().encode("utf-8")))
def test_schema_identifier_url_is_allowed_but_network_endpoint_is_localdocs_only(self) -> None:
schema_identifier = (
valid_inline_code()
+ "\nSCHEMA_ID = 'https://schemas.liti-agent.local/stage2/s2_00/context.schema.v1.json'"
)
self.assertEqual(builder.validate_inline_code(schema_identifier)["external_url_count"], 0)
with self.assertRaises(builder.ProjectionError) as raised:
builder.validate_inline_code(
schema_identifier + "\nhttpx.post('https://schemas.liti-agent.local/not-an-endpoint')"
)
self.assertEqual(raised.exception.code, "INLINE_CODE_NETWORK_ENDPOINT_FORBIDDEN")
def test_expected_outputs_are_exact_source_and_code_bytes(self) -> None:
raw = authoring_yaml()
document = builder.parse_authoring_bytes(raw)
outputs, receipt = builder.expected_outputs(raw, document)
self.assertEqual(outputs[builder.PROJECTION_PATH], raw)
self.assertEqual(outputs[builder.MIRROR_PY_PATH], valid_inline_code().encode("utf-8"))
self.assertEqual(outputs[builder.MIRROR_TXT_PATH], outputs[builder.MIRROR_PY_PATH])
parsed_receipt = json.loads(outputs[builder.RECEIPT_PATH])
self.assertEqual(parsed_receipt, receipt)
self.assertEqual(parsed_receipt["parity_status"], "PASS")
self.assertFalse(parsed_receipt["authoring_rewritten"])
def test_forbidden_runtime_constructs_are_rejected(self) -> None:
cases = {
"subprocess": "import subprocess",
"dynamic-import": "import importlib",
"exec": "exec('x = 1')",
"eval": "eval('1 + 1')",
"compile": "compile('1', '<x>', 'eval')",
"external-project-import": "import project_runtime",
"external-python-source": "SOURCE = 'runtime/other.py'",
"external-url": "REMOTE = 'https://example.invalid/api'",
"placeholder-comment": "# TODO implement body",
"pass-node": "def unfinished():\n pass",
"ellipsis-placeholder": "UNFINISHED = ...",
"plaintext-secret": "TOKEN = 'Bearer abcdefghijklmnopqrstuvwxyz'",
}
for label, addition in cases.items():
with self.subTest(label=label):
with self.assertRaises(builder.ProjectionError):
builder.validate_inline_code(valid_inline_code() + "\n" + addition)
typed_ellipsis = valid_inline_code() + "\nPAIR: tuple[str, ...] = ('ok',)"
self.assertEqual(builder.validate_inline_code(typed_ellipsis)["ast_status"], "PASS")
def test_run_code_parameter_drift_is_rejected(self) -> None:
raw = authoring_yaml().replace(b"timeout: 300", b"timeout: 301")
document = builder.parse_authoring_bytes(raw)
with self.assertRaises(builder.ProjectionError) as raised:
builder.extract_run_code_task(document)
self.assertEqual(raised.exception.code, "RUN_CODE_PARAMETER_MISMATCH")
def test_code_scalar_must_strip_trailing_newline(self) -> None:
raw = authoring_yaml().replace(b" code: |-", b" code: |")
document = builder.parse_authoring_bytes(raw)
with self.assertRaises(builder.ProjectionError) as raised:
builder.extract_run_code_task(document)
self.assertEqual(raised.exception.code, "INLINE_CODE_TRAILING_NEWLINE_FORBIDDEN")
def test_agent_identity_and_exact_parameter_set_are_closed(self) -> None:
wrong_agent = authoring_yaml().replace(
b"name: Stage_2_S2_00_v1",
b"name: Stage_2_S2_00_drift",
)
with self.assertRaises(builder.ProjectionError) as raised:
builder.extract_run_code_task(builder.parse_authoring_bytes(wrong_agent))
self.assertEqual(raised.exception.code, "AGENT_IDENTITY_MISMATCH")
extra_parameter = authoring_yaml().replace(
b" code: |-",
b" unapproved: true\n code: |-",
)
with self.assertRaises(builder.ProjectionError) as raised:
builder.extract_run_code_task(builder.parse_authoring_bytes(extra_parameter))
self.assertEqual(raised.exception.code, "RUN_CODE_PARAMETER_SET_MISMATCH")
def test_only_direct_localdocs_post_is_allowed(self) -> None:
direct = (
valid_inline_code()
+ "\nclass DirectClient:\n"
+ " def send(self):\n"
+ " return self.client.post(LOCALDOCS_URL)"
)
self.assertEqual(builder.validate_inline_code(direct)["ast_status"], "PASS")
cases = {
"method-alias": "post = httpx.post\npost(LOCALDOCS_URL)",
"dynamic-endpoint": (
"class DynamicClient:\n"
" def send(self, target):\n"
" return self.client.post(target)"
),
"dynamic-getattr": "getattr(httpx, 'post')(LOCALDOCS_URL)",
"network-stdlib": "import urllib.request",
}
for label, addition in cases.items():
with self.subTest(label=label):
with self.assertRaises(builder.ProjectionError):
builder.validate_inline_code(valid_inline_code() + "\n" + addition)
def test_missing_authoring_is_a_controlled_condition(self) -> None:
with tempfile.TemporaryDirectory() as directory:
missing = Path(directory) / "Stage_2_S2_00_v.1.yml"
with self.assertRaises(builder.AuthoringMissingError) as raised:
builder.load_authoring(missing)
self.assertEqual(raised.exception.code, "AUTHORING_YAML_MISSING")
def test_build_and_check_modes_preserve_authoring_and_close_parity(self) -> None:
with tempfile.TemporaryDirectory() as directory:
main = Path(directory) / "2. Stage_2"
root = main / "Default_Agent" / "Stage_2_Clean"
authoring = main / "Stage_2_S2_00_v.1.yml"
projection = root / "agent_scripts" / "Stage_2_S2_00.yml"
mirror_py = root / "runtime" / "s2_00_ingress.py"
mirror_txt = root / "runtime" / "s2_00_ingress.txt"
receipt = root / "manifest" / "s2_00_inline_code_receipt.json"
root.mkdir(parents=True)
original = authoring_yaml()
authoring.write_bytes(original)
with (
mock.patch.object(builder, "MAIN_WORKING_DIRECTORY", main),
mock.patch.object(builder, "DEPLOYMENT_ROOT", root),
mock.patch.object(builder, "AUTHORING_PATH", authoring),
mock.patch.object(builder, "PROJECTION_PATH", projection),
mock.patch.object(builder, "MIRROR_PY_PATH", mirror_py),
mock.patch.object(builder, "MIRROR_TXT_PATH", mirror_txt),
mock.patch.object(builder, "RECEIPT_PATH", receipt),
):
status, payload = builder.run(check=False)
self.assertEqual(status, 0)
self.assertEqual(payload["status"], "BUILT_AND_VERIFIED")
self.assertEqual(authoring.read_bytes(), original)
self.assertEqual(projection.read_bytes(), original)
self.assertEqual(mirror_py.read_bytes(), valid_inline_code().encode("utf-8"))
self.assertEqual(mirror_py.read_bytes(), mirror_txt.read_bytes())
receipt_before = receipt.read_bytes()
status, payload = builder.run(check=True)
self.assertEqual(status, 0)
self.assertEqual(payload["status"], "PARITY_PASS")
self.assertEqual(receipt.read_bytes(), receipt_before)
class DeployedArtifactParityTests(unittest.TestCase):
def test_builder_and_test_sources_have_byte_identical_txt_mirrors(self) -> None:
pairs = [
(
ROOT / "offline_build" / "build_s2_00_inline_projection.py",
ROOT / "offline_build" / "build_s2_00_inline_projection.txt",
),
(Path(__file__), Path(__file__).with_suffix(".txt")),
]
for source, mirror in pairs:
with self.subTest(source=source.name):
self.assertTrue(mirror.is_file(), mirror)
self.assertEqual(source.read_bytes(), mirror.read_bytes())
def test_real_authoring_projection_and_mirrors_are_in_parity(self) -> None:
if not builder.AUTHORING_PATH.is_file():
self.skipTest(
"CONTROLLED_MISSING_AUTHORING_YAML: main agent has not created Stage_2_S2_00_v.1.yml"
)
raw, document = builder.load_authoring()
outputs, _receipt = builder.expected_outputs(raw, document)
mismatches = builder.compare_outputs(outputs)
self.assertEqual(mismatches, [], json.dumps(mismatches, ensure_ascii=False, indent=2))
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,281 @@
from __future__ import annotations
import json
from pathlib import Path
import sys
import tempfile
import unittest
from unittest import mock
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
from offline_build import build_s2_00_inline_projection as builder # noqa: E402
def valid_inline_code() -> str:
return "\n".join(
[
"#!/usr/bin/env python3",
"from __future__ import annotations",
"import json",
"import httpx",
"LOCALDOCS_URL = 'http://mcp-localdocs:8012/mcp'",
"USER_HASH = '{{__user_hash__}}'",
"WORKSPACE_HASH = '{{__workspace_hash__}}'",
"READ_TOOL = 'read_binary_doc'",
"WRITE_TOOL = 'write_binary_file'",
"expected_stage2_release_sha256 = '0' * 64",
"def main():",
" return {'status': 'OK'}",
"print(json.dumps(main(), ensure_ascii=False, sort_keys=True))",
]
)
def authoring_yaml(code: str | None = None) -> bytes:
source = valid_inline_code() if code is None else code
indented = "\n".join(f" {line}" for line in source.split("\n"))
return (
"Agent:\n"
" name: Stage_2_S2_00_v1\n"
" version: '1.1.0'\n"
" Stages:\n"
" - name: S2_00\n"
" tools:\n"
" mcpServers:\n"
" localdocs:\n"
" type: streamable-http\n"
" url: http://mcp-localdocs:8012/mcp\n"
" code-executor:\n"
" type: streamable-http\n"
" url: https://code-executor.mcp.eroomai.com/mcp\n"
" tasks:\n"
" - task_name: Task_S2_00_deterministic_ingress\n"
" mcp: code-executor\n"
" tool_name: run_code\n"
" parameters:\n"
" language: python\n"
" requirements: 'httpx==0.28.1'\n"
" network: agent-network\n"
" timeout: 300\n"
" code: |-\n"
f"{indented}\n"
" task_procedure:\n"
" IN:\n"
" nexts: [Task_S2_00_deterministic_ingress]\n"
" wait_until: []\n"
" Task_S2_00_deterministic_ingress:\n"
" nexts: [OUT]\n"
" wait_until: [IN]\n"
" OUT:\n"
" nexts: []\n"
" wait_until: [Task_S2_00_deterministic_ingress]\n"
" prevs: []\n"
" nexts: []\n"
).encode("utf-8")
class InlineCodeProjectionUnitTests(unittest.TestCase):
def test_unique_key_loader_rejects_duplicate_mapping_key(self) -> None:
with self.assertRaises(builder.ProjectionError) as raised:
builder.parse_authoring_bytes(b"Agent:\n name: one\n name: two\n")
self.assertEqual(raised.exception.code, "YAML_DUPLICATE_KEY")
def test_authoring_plaintext_secret_outside_code_is_rejected(self) -> None:
raw = authoring_yaml().replace(
b" version: '1.1.0'",
b" version: '1.1.0'\n leaked_token: 'Bearer abcdefghijklmnopqrstuvwxyz'",
)
with self.assertRaises(builder.ProjectionError) as raised:
builder.parse_authoring_bytes(raw)
self.assertEqual(raised.exception.code, "AUTHORING_PLAINTEXT_SECRET")
def test_parser_returned_code_bytes_are_not_transformed(self) -> None:
expected_code = valid_inline_code()
raw = authoring_yaml(expected_code)
document = builder.parse_authoring_bytes(raw)
_stage, task = builder.extract_run_code_task(document)
observed = task["parameters"]["code"]
self.assertEqual(observed, expected_code)
self.assertEqual(observed.encode("utf-8"), expected_code.encode("utf-8"))
self.assertFalse(observed.endswith("\n"))
def test_valid_code_compiles_and_has_closed_imports(self) -> None:
report = builder.validate_inline_code(valid_inline_code())
self.assertEqual(report["compile_status"], "PASS")
self.assertEqual(report["ast_status"], "PASS")
self.assertEqual(report["imports"], ["__future__", "httpx", "json"])
self.assertEqual(report["code_sha256"], builder.sha256_bytes(valid_inline_code().encode("utf-8")))
def test_schema_identifier_url_is_allowed_but_network_endpoint_is_localdocs_only(self) -> None:
schema_identifier = (
valid_inline_code()
+ "\nSCHEMA_ID = 'https://schemas.liti-agent.local/stage2/s2_00/context.schema.v1.json'"
)
self.assertEqual(builder.validate_inline_code(schema_identifier)["external_url_count"], 0)
with self.assertRaises(builder.ProjectionError) as raised:
builder.validate_inline_code(
schema_identifier + "\nhttpx.post('https://schemas.liti-agent.local/not-an-endpoint')"
)
self.assertEqual(raised.exception.code, "INLINE_CODE_NETWORK_ENDPOINT_FORBIDDEN")
def test_expected_outputs_are_exact_source_and_code_bytes(self) -> None:
raw = authoring_yaml()
document = builder.parse_authoring_bytes(raw)
outputs, receipt = builder.expected_outputs(raw, document)
self.assertEqual(outputs[builder.PROJECTION_PATH], raw)
self.assertEqual(outputs[builder.MIRROR_PY_PATH], valid_inline_code().encode("utf-8"))
self.assertEqual(outputs[builder.MIRROR_TXT_PATH], outputs[builder.MIRROR_PY_PATH])
parsed_receipt = json.loads(outputs[builder.RECEIPT_PATH])
self.assertEqual(parsed_receipt, receipt)
self.assertEqual(parsed_receipt["parity_status"], "PASS")
self.assertFalse(parsed_receipt["authoring_rewritten"])
def test_forbidden_runtime_constructs_are_rejected(self) -> None:
cases = {
"subprocess": "import subprocess",
"dynamic-import": "import importlib",
"exec": "exec('x = 1')",
"eval": "eval('1 + 1')",
"compile": "compile('1', '<x>', 'eval')",
"external-project-import": "import project_runtime",
"external-python-source": "SOURCE = 'runtime/other.py'",
"external-url": "REMOTE = 'https://example.invalid/api'",
"placeholder-comment": "# TODO implement body",
"pass-node": "def unfinished():\n pass",
"ellipsis-placeholder": "UNFINISHED = ...",
"plaintext-secret": "TOKEN = 'Bearer abcdefghijklmnopqrstuvwxyz'",
}
for label, addition in cases.items():
with self.subTest(label=label):
with self.assertRaises(builder.ProjectionError):
builder.validate_inline_code(valid_inline_code() + "\n" + addition)
typed_ellipsis = valid_inline_code() + "\nPAIR: tuple[str, ...] = ('ok',)"
self.assertEqual(builder.validate_inline_code(typed_ellipsis)["ast_status"], "PASS")
def test_run_code_parameter_drift_is_rejected(self) -> None:
raw = authoring_yaml().replace(b"timeout: 300", b"timeout: 301")
document = builder.parse_authoring_bytes(raw)
with self.assertRaises(builder.ProjectionError) as raised:
builder.extract_run_code_task(document)
self.assertEqual(raised.exception.code, "RUN_CODE_PARAMETER_MISMATCH")
def test_code_scalar_must_strip_trailing_newline(self) -> None:
raw = authoring_yaml().replace(b" code: |-", b" code: |")
document = builder.parse_authoring_bytes(raw)
with self.assertRaises(builder.ProjectionError) as raised:
builder.extract_run_code_task(document)
self.assertEqual(raised.exception.code, "INLINE_CODE_TRAILING_NEWLINE_FORBIDDEN")
def test_agent_identity_and_exact_parameter_set_are_closed(self) -> None:
wrong_agent = authoring_yaml().replace(
b"name: Stage_2_S2_00_v1",
b"name: Stage_2_S2_00_drift",
)
with self.assertRaises(builder.ProjectionError) as raised:
builder.extract_run_code_task(builder.parse_authoring_bytes(wrong_agent))
self.assertEqual(raised.exception.code, "AGENT_IDENTITY_MISMATCH")
extra_parameter = authoring_yaml().replace(
b" code: |-",
b" unapproved: true\n code: |-",
)
with self.assertRaises(builder.ProjectionError) as raised:
builder.extract_run_code_task(builder.parse_authoring_bytes(extra_parameter))
self.assertEqual(raised.exception.code, "RUN_CODE_PARAMETER_SET_MISMATCH")
def test_only_direct_localdocs_post_is_allowed(self) -> None:
direct = (
valid_inline_code()
+ "\nclass DirectClient:\n"
+ " def send(self):\n"
+ " return self.client.post(LOCALDOCS_URL)"
)
self.assertEqual(builder.validate_inline_code(direct)["ast_status"], "PASS")
cases = {
"method-alias": "post = httpx.post\npost(LOCALDOCS_URL)",
"dynamic-endpoint": (
"class DynamicClient:\n"
" def send(self, target):\n"
" return self.client.post(target)"
),
"dynamic-getattr": "getattr(httpx, 'post')(LOCALDOCS_URL)",
"network-stdlib": "import urllib.request",
}
for label, addition in cases.items():
with self.subTest(label=label):
with self.assertRaises(builder.ProjectionError):
builder.validate_inline_code(valid_inline_code() + "\n" + addition)
def test_missing_authoring_is_a_controlled_condition(self) -> None:
with tempfile.TemporaryDirectory() as directory:
missing = Path(directory) / "Stage_2_S2_00_v.1.yml"
with self.assertRaises(builder.AuthoringMissingError) as raised:
builder.load_authoring(missing)
self.assertEqual(raised.exception.code, "AUTHORING_YAML_MISSING")
def test_build_and_check_modes_preserve_authoring_and_close_parity(self) -> None:
with tempfile.TemporaryDirectory() as directory:
main = Path(directory) / "2. Stage_2"
root = main / "Default_Agent" / "Stage_2_Clean"
authoring = main / "Stage_2_S2_00_v.1.yml"
projection = root / "agent_scripts" / "Stage_2_S2_00.yml"
mirror_py = root / "runtime" / "s2_00_ingress.py"
mirror_txt = root / "runtime" / "s2_00_ingress.txt"
receipt = root / "manifest" / "s2_00_inline_code_receipt.json"
root.mkdir(parents=True)
original = authoring_yaml()
authoring.write_bytes(original)
with (
mock.patch.object(builder, "MAIN_WORKING_DIRECTORY", main),
mock.patch.object(builder, "DEPLOYMENT_ROOT", root),
mock.patch.object(builder, "AUTHORING_PATH", authoring),
mock.patch.object(builder, "PROJECTION_PATH", projection),
mock.patch.object(builder, "MIRROR_PY_PATH", mirror_py),
mock.patch.object(builder, "MIRROR_TXT_PATH", mirror_txt),
mock.patch.object(builder, "RECEIPT_PATH", receipt),
):
status, payload = builder.run(check=False)
self.assertEqual(status, 0)
self.assertEqual(payload["status"], "BUILT_AND_VERIFIED")
self.assertEqual(authoring.read_bytes(), original)
self.assertEqual(projection.read_bytes(), original)
self.assertEqual(mirror_py.read_bytes(), valid_inline_code().encode("utf-8"))
self.assertEqual(mirror_py.read_bytes(), mirror_txt.read_bytes())
receipt_before = receipt.read_bytes()
status, payload = builder.run(check=True)
self.assertEqual(status, 0)
self.assertEqual(payload["status"], "PARITY_PASS")
self.assertEqual(receipt.read_bytes(), receipt_before)
class DeployedArtifactParityTests(unittest.TestCase):
def test_builder_and_test_sources_have_byte_identical_txt_mirrors(self) -> None:
pairs = [
(
ROOT / "offline_build" / "build_s2_00_inline_projection.py",
ROOT / "offline_build" / "build_s2_00_inline_projection.txt",
),
(Path(__file__), Path(__file__).with_suffix(".txt")),
]
for source, mirror in pairs:
with self.subTest(source=source.name):
self.assertTrue(mirror.is_file(), mirror)
self.assertEqual(source.read_bytes(), mirror.read_bytes())
def test_real_authoring_projection_and_mirrors_are_in_parity(self) -> None:
if not builder.AUTHORING_PATH.is_file():
self.skipTest(
"CONTROLLED_MISSING_AUTHORING_YAML: main agent has not created Stage_2_S2_00_v.1.yml"
)
raw, document = builder.load_authoring()
outputs, _receipt = builder.expected_outputs(raw, document)
mismatches = builder.compare_outputs(outputs)
self.assertEqual(mismatches, [], json.dumps(mismatches, ensure_ascii=False, indent=2))
if __name__ == "__main__":
unittest.main()
@@ -1,10 +1,14 @@
from __future__ import annotations from __future__ import annotations
import base64
import hashlib
import json
import os import os
from pathlib import Path from pathlib import Path
import sys import sys
import tempfile import tempfile
import unittest import unittest
from unittest import mock
ROOT = Path(__file__).resolve().parents[2] ROOT = Path(__file__).resolve().parents[2]
@@ -52,14 +56,242 @@ class ResolverAndSourceLockTests(unittest.TestCase):
def test_default_allowlist_is_exact_and_override_cannot_invent_kind(self) -> None: def test_default_allowlist_is_exact_and_override_cannot_invent_kind(self) -> None:
with tempfile.TemporaryDirectory() as directory: with tempfile.TemporaryDirectory() as directory:
rows = s2.resolve_stage1_sources(directory) rows = s2.resolve_stage1_sources(directory)
self.assertEqual(len(rows), 16) expected = [
observed = {row["observed_path"] for row in rows} ("evidence_indexed", "evidence_indexed.json", "evidence_scope"),
self.assertIn("routing/domain_activation_manifest.json", observed) ("evidence_event_candidates", "evidence_event_candidates.json", "event_scope"),
self.assertNotIn("domain_activation_manifest.json", observed) ("client_goal", "client_goal.json", "optimization_context"),
("domain_screening", "routing/domain_screening.json", "routing_profile_backbone"),
("domain_activation_manifest", "routing/domain_activation_manifest.json", "routing_profile_backbone"),
("b1_evidence_indexed_gate", "quality_gates/B1_evidence_indexed_gate.json", "integrity_corroborator"),
("b2_event_candidates_gate", "quality_gates/B2_event_candidates_gate.json", "integrity_corroborator"),
("stage1_part1_soft_gate_handoff", "quality_gates/stage1_part1_soft_gate_handoff.json", "integrity_corroborator"),
("bo", "BO.json", "identity_backbone"),
("signal_manifest", "signals/signal_manifest.json", "routing_profile_backbone"),
("stage1_part2_review_handoff", "quality_gates/stage1_part2_review_handoff.json", "integrity_corroborator"),
("legal_effect_structures", "legal_effect_structures.json", "routing_profile_backbone"),
("stage1_part3_review_handoff", "quality_gates/stage1_part3_review_handoff.json", "integrity_corroborator"),
("fact_ledger_base", "Fact_Ledger_base.json", "identity_backbone"),
("fact_ledger_writer_report", "stage1_tmp/fact_ledger/fact_ledger_writer_report.json", "integrity_corroborator"),
("stage1_part4_review_handoff", "quality_gates/stage1_part4_review_handoff.json", "integrity_corroborator"),
]
observed = [
(row["logical_input_id"], row["observed_path"], row["criticality"])
for row in rows
]
self.assertEqual(observed, expected)
with self.assertRaises(s2.IngressError) as invented: with self.assertRaises(s2.IngressError) as invented:
s2.resolve_stage1_sources(directory, {"path_overrides": {"invented": "x.json"}}) s2.resolve_stage1_sources(directory, {"path_overrides": {"invented": "x.json"}})
self.assertEqual(invented.exception.code, "UNAPPROVED_LOGICAL_KIND") self.assertEqual(invented.exception.code, "UNAPPROVED_LOGICAL_KIND")
def test_mcp_terminal_parser_requires_exact_jsonrpc_id_and_strict_json(self) -> None:
direct = s2._inline_parse_mcp_payload(
b'{"jsonrpc":"2.0","id":10,"result":{}}',
10,
)
self.assertEqual(direct["id"], 10)
sse = s2._inline_parse_mcp_payload(
b'event: message\ndata: {"jsonrpc":"2.0","id":11,"result":{}}\n\n',
11,
)
self.assertEqual(sse["id"], 11)
for raw, code in (
(b'{"jsonrpc":"2.0","id":12,"result":{}}', "MCP_RESPONSE_ID_MISMATCH"),
(b'{"jsonrpc":"2.0","id":10,"id":10,"result":{}}', "MCP_SSE_SHAPE"),
(b'{"jsonrpc":"2.0","id":10,"result":{}} {}', "MCP_SSE_SHAPE"),
(b'{"jsonrpc":"2.0","id":10,"error":{"code":-1}}', "MCP_JSONRPC_ERROR"),
):
with self.subTest(raw=raw):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_parse_mcp_payload(raw, 10)
self.assertEqual(raised.exception.code, code)
def test_binary_envelope_uses_strict_base64_and_declared_integrity(self) -> None:
payload = b"\x00raw-stage1-bytes\xff"
envelope = json.dumps(
{
"content_base64": base64.b64encode(payload).decode("ascii"),
"byte_length": len(payload),
"sha256": __import__("hashlib").sha256(payload).hexdigest(),
}
)
self.assertEqual(s2._inline_binary_envelope(envelope, "x.bin"), payload)
for malformed, code in (
('{"content_base64":"%%%%"}', "LOCALDOCS_BASE64_INVALID"),
('{"content_base64":"YQ==","byte_length":2}', "LOCALDOCS_BYTE_LENGTH_MISMATCH"),
('{"content_base64":"YQ==","sha256":"' + "0" * 64 + '"}', "LOCALDOCS_HASH_MISMATCH"),
):
with self.subTest(malformed=malformed):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_binary_envelope(malformed, "x.bin")
self.assertEqual(raised.exception.code, code)
def test_tool_result_parser_enforces_one_text_block_and_is_error(self) -> None:
self.assertEqual(
s2._inline_tool_text(
{"content": [{"type": "text", "text": "payload"}]},
"read_binary_doc",
),
"payload",
)
for result, code in (
({"content": []}, "MCP_CONTENT_CARDINALITY"),
({"content": [{"type": "image", "data": "x"}]}, "MCP_CONTENT_SHAPE"),
({"isError": True, "content": [{"type": "text", "text": "not found"}]}, "LOCALDOCS_NOT_FOUND"),
):
with self.subTest(result=result):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_tool_text(result, "read_binary_doc")
self.assertEqual(raised.exception.code, code)
def test_mcp_initialize_locks_protocol_and_session_identity(self) -> None:
class Response:
def __init__(self, payload: object, session_id: str | None) -> None:
self.content = json.dumps(payload).encode("utf-8")
self.headers = {} if session_id is None else {"mcp-session-id": session_id}
def raise_for_status(self) -> None:
return None
class Client:
def __init__(self, responses: list[Response]) -> None:
self.responses = list(responses)
def post(self, *_args: object, **_kwargs: object) -> Response:
return self.responses.pop(0)
def close(self) -> None:
return None
initialize = {
"jsonrpc": "2.0",
"id": 1,
"result": {"protocolVersion": s2.MCP_PROTOCOL_VERSION},
}
notification = {"jsonrpc": "2.0", "result": {}}
client = Client([Response(initialize, "session-a"), Response(notification, "session-a")])
localdocs = s2._InlineLocaldocs("a" * 64, "b" * 64, client=client)
localdocs.initialize()
self.assertEqual(localdocs.headers["mcp-session-id"], "session-a")
changed = Client(
[
Response(initialize, "session-a"),
Response(notification, "session-a"),
Response({"jsonrpc": "2.0", "id": 10, "result": {}}, "session-b"),
]
)
localdocs = s2._InlineLocaldocs("a" * 64, "b" * 64, client=changed)
localdocs.initialize()
with self.assertRaises(s2.IngressError) as raised:
localdocs.call("read_binary_doc", {"doc_name": "x"})
self.assertEqual(raised.exception.code, "MCP_SESSION_ID_CHANGED")
bad_protocol = dict(initialize)
bad_protocol["result"] = {"protocolVersion": "1900-01-01"}
localdocs = s2._InlineLocaldocs(
"a" * 64,
"b" * 64,
client=Client([Response(bad_protocol, "session-a")]),
)
with self.assertRaises(s2.IngressError) as raised:
localdocs.initialize()
self.assertEqual(raised.exception.code, "MCP_PROTOCOL_VERSION_MISMATCH")
def test_inline_hydration_rejects_second_pass_mutation_and_initial_budget(self) -> None:
request = {
"schema_version": "stage2_s2_00_execution_request.v1",
"workflow_id": "S2_00",
"request_id": "trace-1",
"attempt_id": "attempt-1",
"stage1_run_root_ref": "stage1_runs/current",
"stage1_deployment_root_ref": "Default_Agent",
}
request_raw = s2.canonical_json_bytes(request)
release_raw = s2.canonical_json_bytes(
{"limits": {"max_file_bytes": s2.MAX_FILE_BYTES, "max_run_bytes": s2.MAX_RUN_BYTES, "max_hydration_paths": 1024}}
)
class Reader:
def __init__(self, mutate_request: bool = False) -> None:
self.counts: dict[str, int] = {}
self.mutate_request = mutate_request
def read_binary(self, path: str) -> bytes:
self.counts[path] = self.counts.get(path, 0) + 1
if path == s2.INLINE_REQUEST_PATH:
if self.mutate_request and self.counts[path] > 1:
return request_raw.replace(b"trace-1", b"trace-2")
return request_raw
if path == s2.INLINE_STAGE2_RELEASE_PATH:
return release_raw
raise AssertionError(path)
destinations = [
(s2.INLINE_REQUEST_PATH, "stage1_run", "request.json"),
(s2.INLINE_STAGE2_RELEASE_PATH, "stage2_asset", "manifest/stage2_release.json"),
]
release_hash = hashlib.sha256(release_raw).hexdigest()
with tempfile.TemporaryDirectory() as directory, mock.patch.object(
s2,
"EXPECTED_STAGE2_RELEASE_SHA256",
release_hash,
), mock.patch.object(
s2,
"_inline_release_materialization_plan",
return_value=(destinations, {s2.INLINE_STAGE2_RELEASE_PATH: release_hash}),
):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_hydrate(Reader(mutate_request=True), Path(directory))
self.assertEqual(raised.exception.code, "SOURCE_SNAPSHOT_CHANGED")
tiny_release_raw = s2.canonical_json_bytes(
{"limits": {"max_file_bytes": s2.MAX_FILE_BYTES, "max_run_bytes": 1, "max_hydration_paths": 1024}}
)
tiny_hash = hashlib.sha256(tiny_release_raw).hexdigest()
class TinyReader(Reader):
def read_binary(self, path: str) -> bytes:
if path == s2.INLINE_STAGE2_RELEASE_PATH:
return tiny_release_raw
return super().read_binary(path)
with tempfile.TemporaryDirectory() as directory, mock.patch.object(
s2,
"EXPECTED_STAGE2_RELEASE_SHA256",
tiny_hash,
):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_hydrate(TinyReader(), Path(directory))
self.assertEqual(raised.exception.code, "AGGREGATE_RUN_SIZE_LIMIT")
def test_execution_request_is_closed_and_paths_are_workspace_relative(self) -> None:
valid = {
"schema_version": "stage2_s2_00_execution_request.v1",
"workflow_id": "S2_00",
"request_id": "trace-1",
"attempt_id": "attempt-1",
"stage1_run_root_ref": "stage1_runs/current",
"stage1_deployment_root_ref": "Default_Agent",
}
parsed = s2._inline_validate_request(json.dumps(valid).encode())
self.assertEqual(parsed["request_id"], "trace-1")
for mutation, code in (
({**valid, "unknown": True}, "RUN_REQUEST_CLOSED_SHAPE"),
({**valid, "stage1_run_root_ref": "../escape"}, "STAGE1_RUN_ROOT_REF_INVALID"),
({**valid, "stage1_deployment_root_ref": "/absolute"}, "STAGE1_DEPLOYMENT_ROOT_REF_INVALID"),
):
with self.subTest(mutation=mutation):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_validate_request(json.dumps(mutation).encode())
self.assertEqual(raised.exception.code, code)
def test_algorithm_digest_and_run_id_do_not_depend_on_mirror_path(self) -> None:
self.assertEqual(len(s2.ALGORITHM_SEMANTIC_DIGEST), 64)
binding = "a" * 64
self.assertEqual(s2.canonical_run_id(binding), f"S2RUN-{binding}")
with self.assertRaises(s2.IngressError):
s2.canonical_run_id("not-a-digest")
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
@@ -1,10 +1,14 @@
from __future__ import annotations from __future__ import annotations
import base64
import hashlib
import json
import os import os
from pathlib import Path from pathlib import Path
import sys import sys
import tempfile import tempfile
import unittest import unittest
from unittest import mock
ROOT = Path(__file__).resolve().parents[2] ROOT = Path(__file__).resolve().parents[2]
@@ -52,14 +56,242 @@ class ResolverAndSourceLockTests(unittest.TestCase):
def test_default_allowlist_is_exact_and_override_cannot_invent_kind(self) -> None: def test_default_allowlist_is_exact_and_override_cannot_invent_kind(self) -> None:
with tempfile.TemporaryDirectory() as directory: with tempfile.TemporaryDirectory() as directory:
rows = s2.resolve_stage1_sources(directory) rows = s2.resolve_stage1_sources(directory)
self.assertEqual(len(rows), 16) expected = [
observed = {row["observed_path"] for row in rows} ("evidence_indexed", "evidence_indexed.json", "evidence_scope"),
self.assertIn("routing/domain_activation_manifest.json", observed) ("evidence_event_candidates", "evidence_event_candidates.json", "event_scope"),
self.assertNotIn("domain_activation_manifest.json", observed) ("client_goal", "client_goal.json", "optimization_context"),
("domain_screening", "routing/domain_screening.json", "routing_profile_backbone"),
("domain_activation_manifest", "routing/domain_activation_manifest.json", "routing_profile_backbone"),
("b1_evidence_indexed_gate", "quality_gates/B1_evidence_indexed_gate.json", "integrity_corroborator"),
("b2_event_candidates_gate", "quality_gates/B2_event_candidates_gate.json", "integrity_corroborator"),
("stage1_part1_soft_gate_handoff", "quality_gates/stage1_part1_soft_gate_handoff.json", "integrity_corroborator"),
("bo", "BO.json", "identity_backbone"),
("signal_manifest", "signals/signal_manifest.json", "routing_profile_backbone"),
("stage1_part2_review_handoff", "quality_gates/stage1_part2_review_handoff.json", "integrity_corroborator"),
("legal_effect_structures", "legal_effect_structures.json", "routing_profile_backbone"),
("stage1_part3_review_handoff", "quality_gates/stage1_part3_review_handoff.json", "integrity_corroborator"),
("fact_ledger_base", "Fact_Ledger_base.json", "identity_backbone"),
("fact_ledger_writer_report", "stage1_tmp/fact_ledger/fact_ledger_writer_report.json", "integrity_corroborator"),
("stage1_part4_review_handoff", "quality_gates/stage1_part4_review_handoff.json", "integrity_corroborator"),
]
observed = [
(row["logical_input_id"], row["observed_path"], row["criticality"])
for row in rows
]
self.assertEqual(observed, expected)
with self.assertRaises(s2.IngressError) as invented: with self.assertRaises(s2.IngressError) as invented:
s2.resolve_stage1_sources(directory, {"path_overrides": {"invented": "x.json"}}) s2.resolve_stage1_sources(directory, {"path_overrides": {"invented": "x.json"}})
self.assertEqual(invented.exception.code, "UNAPPROVED_LOGICAL_KIND") self.assertEqual(invented.exception.code, "UNAPPROVED_LOGICAL_KIND")
def test_mcp_terminal_parser_requires_exact_jsonrpc_id_and_strict_json(self) -> None:
direct = s2._inline_parse_mcp_payload(
b'{"jsonrpc":"2.0","id":10,"result":{}}',
10,
)
self.assertEqual(direct["id"], 10)
sse = s2._inline_parse_mcp_payload(
b'event: message\ndata: {"jsonrpc":"2.0","id":11,"result":{}}\n\n',
11,
)
self.assertEqual(sse["id"], 11)
for raw, code in (
(b'{"jsonrpc":"2.0","id":12,"result":{}}', "MCP_RESPONSE_ID_MISMATCH"),
(b'{"jsonrpc":"2.0","id":10,"id":10,"result":{}}', "MCP_SSE_SHAPE"),
(b'{"jsonrpc":"2.0","id":10,"result":{}} {}', "MCP_SSE_SHAPE"),
(b'{"jsonrpc":"2.0","id":10,"error":{"code":-1}}', "MCP_JSONRPC_ERROR"),
):
with self.subTest(raw=raw):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_parse_mcp_payload(raw, 10)
self.assertEqual(raised.exception.code, code)
def test_binary_envelope_uses_strict_base64_and_declared_integrity(self) -> None:
payload = b"\x00raw-stage1-bytes\xff"
envelope = json.dumps(
{
"content_base64": base64.b64encode(payload).decode("ascii"),
"byte_length": len(payload),
"sha256": __import__("hashlib").sha256(payload).hexdigest(),
}
)
self.assertEqual(s2._inline_binary_envelope(envelope, "x.bin"), payload)
for malformed, code in (
('{"content_base64":"%%%%"}', "LOCALDOCS_BASE64_INVALID"),
('{"content_base64":"YQ==","byte_length":2}', "LOCALDOCS_BYTE_LENGTH_MISMATCH"),
('{"content_base64":"YQ==","sha256":"' + "0" * 64 + '"}', "LOCALDOCS_HASH_MISMATCH"),
):
with self.subTest(malformed=malformed):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_binary_envelope(malformed, "x.bin")
self.assertEqual(raised.exception.code, code)
def test_tool_result_parser_enforces_one_text_block_and_is_error(self) -> None:
self.assertEqual(
s2._inline_tool_text(
{"content": [{"type": "text", "text": "payload"}]},
"read_binary_doc",
),
"payload",
)
for result, code in (
({"content": []}, "MCP_CONTENT_CARDINALITY"),
({"content": [{"type": "image", "data": "x"}]}, "MCP_CONTENT_SHAPE"),
({"isError": True, "content": [{"type": "text", "text": "not found"}]}, "LOCALDOCS_NOT_FOUND"),
):
with self.subTest(result=result):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_tool_text(result, "read_binary_doc")
self.assertEqual(raised.exception.code, code)
def test_mcp_initialize_locks_protocol_and_session_identity(self) -> None:
class Response:
def __init__(self, payload: object, session_id: str | None) -> None:
self.content = json.dumps(payload).encode("utf-8")
self.headers = {} if session_id is None else {"mcp-session-id": session_id}
def raise_for_status(self) -> None:
return None
class Client:
def __init__(self, responses: list[Response]) -> None:
self.responses = list(responses)
def post(self, *_args: object, **_kwargs: object) -> Response:
return self.responses.pop(0)
def close(self) -> None:
return None
initialize = {
"jsonrpc": "2.0",
"id": 1,
"result": {"protocolVersion": s2.MCP_PROTOCOL_VERSION},
}
notification = {"jsonrpc": "2.0", "result": {}}
client = Client([Response(initialize, "session-a"), Response(notification, "session-a")])
localdocs = s2._InlineLocaldocs("a" * 64, "b" * 64, client=client)
localdocs.initialize()
self.assertEqual(localdocs.headers["mcp-session-id"], "session-a")
changed = Client(
[
Response(initialize, "session-a"),
Response(notification, "session-a"),
Response({"jsonrpc": "2.0", "id": 10, "result": {}}, "session-b"),
]
)
localdocs = s2._InlineLocaldocs("a" * 64, "b" * 64, client=changed)
localdocs.initialize()
with self.assertRaises(s2.IngressError) as raised:
localdocs.call("read_binary_doc", {"doc_name": "x"})
self.assertEqual(raised.exception.code, "MCP_SESSION_ID_CHANGED")
bad_protocol = dict(initialize)
bad_protocol["result"] = {"protocolVersion": "1900-01-01"}
localdocs = s2._InlineLocaldocs(
"a" * 64,
"b" * 64,
client=Client([Response(bad_protocol, "session-a")]),
)
with self.assertRaises(s2.IngressError) as raised:
localdocs.initialize()
self.assertEqual(raised.exception.code, "MCP_PROTOCOL_VERSION_MISMATCH")
def test_inline_hydration_rejects_second_pass_mutation_and_initial_budget(self) -> None:
request = {
"schema_version": "stage2_s2_00_execution_request.v1",
"workflow_id": "S2_00",
"request_id": "trace-1",
"attempt_id": "attempt-1",
"stage1_run_root_ref": "stage1_runs/current",
"stage1_deployment_root_ref": "Default_Agent",
}
request_raw = s2.canonical_json_bytes(request)
release_raw = s2.canonical_json_bytes(
{"limits": {"max_file_bytes": s2.MAX_FILE_BYTES, "max_run_bytes": s2.MAX_RUN_BYTES, "max_hydration_paths": 1024}}
)
class Reader:
def __init__(self, mutate_request: bool = False) -> None:
self.counts: dict[str, int] = {}
self.mutate_request = mutate_request
def read_binary(self, path: str) -> bytes:
self.counts[path] = self.counts.get(path, 0) + 1
if path == s2.INLINE_REQUEST_PATH:
if self.mutate_request and self.counts[path] > 1:
return request_raw.replace(b"trace-1", b"trace-2")
return request_raw
if path == s2.INLINE_STAGE2_RELEASE_PATH:
return release_raw
raise AssertionError(path)
destinations = [
(s2.INLINE_REQUEST_PATH, "stage1_run", "request.json"),
(s2.INLINE_STAGE2_RELEASE_PATH, "stage2_asset", "manifest/stage2_release.json"),
]
release_hash = hashlib.sha256(release_raw).hexdigest()
with tempfile.TemporaryDirectory() as directory, mock.patch.object(
s2,
"EXPECTED_STAGE2_RELEASE_SHA256",
release_hash,
), mock.patch.object(
s2,
"_inline_release_materialization_plan",
return_value=(destinations, {s2.INLINE_STAGE2_RELEASE_PATH: release_hash}),
):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_hydrate(Reader(mutate_request=True), Path(directory))
self.assertEqual(raised.exception.code, "SOURCE_SNAPSHOT_CHANGED")
tiny_release_raw = s2.canonical_json_bytes(
{"limits": {"max_file_bytes": s2.MAX_FILE_BYTES, "max_run_bytes": 1, "max_hydration_paths": 1024}}
)
tiny_hash = hashlib.sha256(tiny_release_raw).hexdigest()
class TinyReader(Reader):
def read_binary(self, path: str) -> bytes:
if path == s2.INLINE_STAGE2_RELEASE_PATH:
return tiny_release_raw
return super().read_binary(path)
with tempfile.TemporaryDirectory() as directory, mock.patch.object(
s2,
"EXPECTED_STAGE2_RELEASE_SHA256",
tiny_hash,
):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_hydrate(TinyReader(), Path(directory))
self.assertEqual(raised.exception.code, "AGGREGATE_RUN_SIZE_LIMIT")
def test_execution_request_is_closed_and_paths_are_workspace_relative(self) -> None:
valid = {
"schema_version": "stage2_s2_00_execution_request.v1",
"workflow_id": "S2_00",
"request_id": "trace-1",
"attempt_id": "attempt-1",
"stage1_run_root_ref": "stage1_runs/current",
"stage1_deployment_root_ref": "Default_Agent",
}
parsed = s2._inline_validate_request(json.dumps(valid).encode())
self.assertEqual(parsed["request_id"], "trace-1")
for mutation, code in (
({**valid, "unknown": True}, "RUN_REQUEST_CLOSED_SHAPE"),
({**valid, "stage1_run_root_ref": "../escape"}, "STAGE1_RUN_ROOT_REF_INVALID"),
({**valid, "stage1_deployment_root_ref": "/absolute"}, "STAGE1_DEPLOYMENT_ROOT_REF_INVALID"),
):
with self.subTest(mutation=mutation):
with self.assertRaises(s2.IngressError) as raised:
s2._inline_validate_request(json.dumps(mutation).encode())
self.assertEqual(raised.exception.code, code)
def test_algorithm_digest_and_run_id_do_not_depend_on_mirror_path(self) -> None:
self.assertEqual(len(s2.ALGORITHM_SEMANTIC_DIGEST), 64)
binding = "a" * 64
self.assertEqual(s2.canonical_run_id(binding), f"S2RUN-{binding}")
with self.assertRaises(s2.IngressError):
s2.canonical_run_id("not-a-digest")
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
@@ -3,23 +3,27 @@ Agent:
description: >- description: >-
Stage 1 Part 1-4의 봉인 입력을 결정적으로 검증·보존·정규화하고, Stage 1 Part 1-4의 봉인 입력을 결정적으로 검증·보존·정규화하고,
claim-neutral cluster slice와 bundle plan을 작성하는 NON-LLM workflow 계약. claim-neutral cluster slice와 bundle plan을 작성하는 NON-LLM workflow 계약.
version: "1.0.0-draft" version: "1.1.0"
metadata: metadata:
workflow_id: S2_00 workflow_id: S2_00
execution_class: NON-LLM-DETERMINISTIC execution_class: NON-LLM-DETERMINISTIC
workflow_schema_version: stage2_workflow_contract.v1 workflow_schema_version: stage2_workflow_contract.v1.1
asset_version: s2_00.1 asset_version: s2_00.1.1
owner: Stage_2_workflow_maintainer owner: Stage_2_workflow_maintainer
implementation_status: DRAFT_PENDING_SEQUENTIAL_BIND implementation_status: IMPLEMENTED_DECLARATIVE_CONTRACT
invocation_status: OPEN_EXTERNAL_BACKEND invocation_status: PENDING_SECRET_AND_LIVE_BINDING
release_binding_ref: manifest/stage2_release.json#/module_manifest_ref release_binding_ref: manifest/stage2_release.json
loader_binding_ref: deployment/stage2_loader_binding.yml executor_binding_ref: deployment/stage2_code_executor_binding.yml
inline_code_receipt_ref: manifest/s2_00_inline_code_receipt.json
agent_script_ref: agent_scripts/Stage_2_S2_00.yml
loader_binding_disposition: REFERENCE_ONLY_SUPERSEDED_FOR_S2_00
Stages: Stages:
- name: S2_00 - name: S2_00
description: >- description: >-
C00, C05, C10, C15를 순서대로 수행하는 fixed-runtime entry. C00, C05, C10, C15의 IO·순서·분기·배리어를 선언하는 NON-LLM 계약.
외부 AgentBackend primitive가 검증되기 전에는 이 선언 자체가 실행 가능성을 뜻하지 않는다. 실행 Python은 이 문서가 아니라 Agent YAML의 exactly-one
code-executor.run_code task에만 존재한다.
prevs: [] prevs: []
nexts: nexts:
- S2_10 - S2_10
@@ -29,10 +33,14 @@ Agent:
orchestration_contract: orchestration_contract:
workflow_id: S2_00 workflow_id: S2_00
execution_class: NON-LLM-DETERMINISTIC execution_class: NON-LLM-DETERMINISTIC
entrypoint_ref: runtime/s2_00_ingress.py executable_agent_ref: agent_scripts/Stage_2_S2_00.yml
loader_ref: release_ops/stage2_loader.py executor_binding_ref: deployment/stage2_code_executor_binding.yml
binding_ref: deployment/stage2_loader_binding.yml inline_code_receipt_ref: manifest/s2_00_inline_code_receipt.json
invocation_status: OPEN_EXTERNAL_BACKEND workflow_contract_is_executable: false
task_count: 0
invocation_status: PENDING_SECRET_AND_LIVE_BINDING
external_runtime_mirror_ref: runtime/s2_00_ingress.py
external_runtime_mirror_disposition: TEST_PARITY_ORACLE_ONLY_RUNTIME_IMPORT_FORBIDDEN
component_order: component_order:
- C00 - C00
- C05 - C05
@@ -80,7 +88,7 @@ Agent:
- compile_cluster_slices - compile_cluster_slices
- compile_bundle_plan - compile_bundle_plan
- validate_bundle_release_cohorts - validate_bundle_release_cohorts
- publish_atomically - publish_with_status_last_logical_barrier
writes: writes:
- context/cluster_plan.json - context/cluster_plan.json
- context/cluster_slices/<cluster_id>.json - context/cluster_slices/<cluster_id>.json
@@ -88,7 +96,14 @@ Agent:
- ingress/ingress_status.json - ingress/ingress_status.json
execution: execution:
timeout_seconds: 600 mcp_server_id: code-executor
tool_name: run_code
language: python
requirements: "httpx==0.28.1"
network_profile: agent-network
timeout_seconds: 300
inline_task_count: 1
executable_task_owner_ref: agent_scripts/Stage_2_S2_00.yml#/Agent/Stages/0/tasks/0
retry_policy_id: S2-RETRY-TRANSIENT-READ-V1 retry_policy_id: S2-RETRY-TRANSIENT-READ-V1
retry_policy_ref: manifest/stage2_release.json#/retry_policies/0 retry_policy_ref: manifest/stage2_release.json#/retry_policies/0
idempotence_key_material: idempotence_key_material:
@@ -98,24 +113,47 @@ Agent:
- release_class - release_class
attempt_id_is_canonical_id_input: false attempt_id_is_canonical_id_input: false
same_input_outputs_must_be_byte_identical: true same_input_outputs_must_be_byte_identical: true
whole_tree_atomic_publish_required: true whole_tree_atomic_publish_required: false
physical_directory_rename_claimed: false
logical_publish_barrier_required: true
logical_publish_barrier_id: S2_00_INGRESS_STATUS_BARRIER
logical_publish_barrier_path: ingress/ingress_status.json
ingress_status_written_last: true ingress_status_written_last: true
root_arguments: request_contract:
- argument_id: stage1_run_root_ref fixed_path: stage2_control/s2_00_request.json
binding: backend_workspace_transport schema_ref: schemas/ingress.schema.json#/$defs/execution_request
directory_scan_allowed: false
alternate_request_path_allowed: false
required_fields:
- schema_version
- workflow_id
- request_id
- attempt_id
- stage1_run_root_ref
- stage1_deployment_root_ref
root_bindings:
- binding_id: workspace_logical_root
binding: localdocs_initialized_user_workspace_session
arbitrary_absolute_path_allowed: false arbitrary_absolute_path_allowed: false
- argument_id: stage1_deployment_root_ref - binding_id: stage1_run_root_ref
binding: stage2_release_dependency_lock binding: fixed_request_payload
arbitrary_absolute_path_allowed: false arbitrary_absolute_path_allowed: false
- argument_id: run_id - binding_id: stage1_deployment_root_ref
binding: run_tuple binding: fixed_request_payload_and_stage2_release_dependency_lock
- argument_id: attempt_id arbitrary_absolute_path_allowed: false
binding: transient_retry_only - binding_id: canonical_run_id
- argument_id: user_context_sha256 binding: run_binding_digest
binding: backend_session caller_supplied_value_allowed: false
- argument_id: workspace_context_sha256 - binding_id: canonical_output_root
binding: backend_session binding: stage2_runs/by-binding/<run_binding_digest>/
caller_supplied_value_allowed: false
- binding_id: attempt_id
binding: fixed_request_payload_transient_retry_only
- binding_id: user_workspace_context
binding: localdocs_initialize_client_info_hash_templates
raw_identifier_persistence_allowed: false
input_contract: input_contract:
- logical_input_id: evidence_indexed - logical_input_id: evidence_indexed
@@ -203,6 +241,8 @@ Agent:
glob_allowed: false glob_allowed: false
fuzzy_basename_allowed: false fuzzy_basename_allowed: false
root_level_domain_activation_manifest_allowed: false root_level_domain_activation_manifest_allowed: false
hydration_stability_policy: BOUNDED_TWO_PASS_BINARY_RAW_HASH_MAP_EQUALITY
hydration_max_passes: 2
signal_contract: signal_contract:
all_expansion_adapter_id: S2A-SIGNAL-ALL-V1 all_expansion_adapter_id: S2A-SIGNAL-ALL-V1
@@ -295,6 +335,14 @@ Agent:
- ingress/ingress_status.json - ingress/ingress_status.json
normal_branch_technical_diagnostic_allowed: false normal_branch_technical_diagnostic_allowed: false
diagnostic_branch_context_publish_allowed: false diagnostic_branch_context_publish_allowed: false
canonical_output_root_rule: stage2_runs/by-binding/<run_binding_digest>/
output_root_from_request_allowed: false
publish_barrier:
barrier_id: S2_00_INGRESS_STATUS_BARRIER
relative_path: ingress/ingress_status.json
semantics: STATUS_LAST_LOGICAL_COMMIT
non_status_artifact_readback_required: true
barrier_readback_required: true
routing: routing:
success_handoff: success_handoff:
@@ -314,9 +362,18 @@ Agent:
prohibitions: prohibitions:
llm_calls_allowed: false llm_calls_allowed: false
llm_configuration_present: false llm_configuration_present: false
inline_python_allowed: false inline_python_allowed_in_workflow_contract: false
executable_inline_python_owner: agent_scripts/Stage_2_S2_00.yml#/Agent/Stages/0/tasks/0/parameters/code
inline_schema_allowed: false inline_schema_allowed: false
external_network_access_allowed: false external_internet_access_allowed: false
mcp_endpoint_allowlist:
- http://mcp-localdocs:8012/mcp
localdocs_tool_allowlist:
- read_binary_doc
- write_binary_file
external_runtime_import_allowed: false
loader_invocation_allowed: false
loader_fallback_allowed: false
dynamic_code_allowed: false dynamic_code_allowed: false
runtime_package_install_allowed: false runtime_package_install_allowed: false
raw_stage1_id_normalization_allowed: false raw_stage1_id_normalization_allowed: false
@@ -112,7 +112,7 @@ Agent:
- task_name: Task_S2_10_resolve_cluster_* - task_name: Task_S2_10_resolve_cluster_*
max_concurrency: 8 max_concurrency: 8
execution_class: LLM-DIRECT execution_class: LLM-DIRECT
deployment_binding_ref: deployment/stage2_loader_binding.yml#/downstream_llm_candidate_bindings/0 deployment_binding_ref: deployment/stage2_code_executor_binding.yml#/downstream_llm_candidate_bindings/0
deployment_binding_status_required: SIGNED_RELEASE_BOUND deployment_binding_status_required: SIGNED_RELEASE_BOUND
llm_verbosity: medium llm_verbosity: medium
llm_endpoint: responses llm_endpoint: responses
@@ -16,8 +16,20 @@
- 하위 에이전트(subagents)를 사용하여 핵심 테마와 교훈을 식별하고 MEMORY.md에 섹션으로 저장하라. - 하위 에이전트(subagents)를 사용하여 핵심 테마와 교훈을 식별하고 MEMORY.md에 섹션으로 저장하라.
- 향후 세션 시작 시 MEMORY.md의 이전 섹션을 참조하라. - 향후 세션 시작 시 MEMORY.md의 이전 섹션을 참조하라.
## 2026-08-30 — Stage 2 v5 direct MCP inline S2_00 구현
한 줄 요약: v4의 외부 loader 호출 전제를 폐기하고, `Stage_2_S2_00_v.1.yml`의 단일 `run_code`가 MCP Code Executor 프로토콜로 `runtime/s2_00_ingress.py`와 byte-identical한 코드를 직접 실행하도록 v5 전략·SOW·자산 계약과 S2_00 구현을 일관되게 개정했다.
- 핵심 산출물: `stage_2_optimal_update_strategy_v.5.md`, `stage_2_optimal_update_strategy_v.5_workflow.svg`, `S_00_SOW_v.1.md`, `S2_00_assets_v.1.md`, `Stage_2_S2_00_v.1.yml`; 배포 projection은 `Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml`이다. deterministic stage는 각 1개의 executable Agent script와 정확히 1개의 `run_code`를 소유하며 전체 계획 수량은 declarative YAML 92 + executable Agent script 5 = 97이다.
- 실행·배포 계약: authoring YAML의 `code: |-` scalar를 단일 원천으로 삼고 `offline_build/build_s2_00_inline_projection.py`가 runtime `.py`·byte-identical `.txt` mirror·배포 YAML·inline receipt를 투영한다. 고정 요청은 `stage2_control/s2_00_request.json`, 결과는 `stage2_runs/by-binding/<run_binding_digest>/` 아래에 저장하며, O-06 external native loader binding은 `SUPERSEDED_BY_DIRECT_MCP_INLINE_CODE`로 닫았다.
- 안전·정합성 교정: two-pass bounded raw-byte hydration, initialize protocolVersion·MCP session 고정, localdocs-only 직접 호출, stdout single-JSON 격리, 성공/실패 inner receipt와 outer receipt schema, release/module/executor 상호 hash 결속, output readback allowlist·idempotency, S2_10 exact handoff와 S2_40 exact five-input single-writer 경계를 구현했다. unbound user/workspace identity는 network 전 단계에서 schema-valid `FAILED_NO_BARRIER` receipt 하나만 출력한다.
- 검증 이력: 전략·SOW·자산 문서는 독립 evaluator 2개씩 정확히 2회, 변경 자산 17개는 자산별 독립 verifier로 정확히 1회 검증 후 일괄 개정했다. YAML 검증 Round 1의 두 결함(unbound identity의 legacy CLI 분기, `code: |` chomping)을 교정했고 Round 2는 추가 finding 없이 PASS했다. 최종 builder parity, JSON/YAML/schema/hash·mirror 무결성, 직접 failure-path 실행과 `tests/s2_00` 64/64 PASS를 확인했다.
- 상태 경계: 현 상태는 `IMPLEMENTED_OFFLINE_VERIFIED / LIVE_ADMISSION_PENDING`이다. Code Executor secret/auth, runtime image digest, live egress enforcement, 300초 live benchmark, 실제 binary I/O·outer receipt, canary/production admission과 법률 sign-off는 별도 운영 검증 대상이며 완료로 주장하지 않는다.
## 2026-08-30 — S2_00 AgentBackend YAML 작업명세 구현 ## 2026-08-30 — S2_00 AgentBackend YAML 작업명세 구현
> 상태: 아래 O-06 대기형 설계는 바로 위의 v5 direct MCP inline 구현으로 대체되었으며, 역사 기록으로만 유지한다.
한 줄 요약: `S_00_SOW.md`의 S2_00 계약을 두 독립 후보의 앙상블과 독립 evaluator 2개씩 정확히 2회 검증·증분개정하여 `Stage_2_S2_00.yml`로 구현하되, 미확인 native primitive를 창작하지 않고 O-06이 닫힐 때까지 명시적인 비실행 authoring projection으로 고정했다. 한 줄 요약: `S_00_SOW.md`의 S2_00 계약을 두 독립 후보의 앙상블과 독립 evaluator 2개씩 정확히 2회 검증·증분개정하여 `Stage_2_S2_00.yml`로 구현하되, 미확인 native primitive를 창작하지 않고 O-06이 닫힐 때까지 명시적인 비실행 authoring projection으로 고정했다.
- 최종 산출물: `YAML_Prompts/2. Stage_2/Stage_2_S2_00.yml`; 954행/45,833 bytes/SHA-256 `3fbadd9bf48e8d3921b43f766690bf67ad1dd2cd0a8f624d78a9b3223edeeeb7`. 후보 A는 계약 완전성, 후보 B는 canonical 참조 최소화를 강화했고 main agent가 thin loader-adapter 구조로 병합했다. - 최종 산출물: `YAML_Prompts/2. Stage_2/Stage_2_S2_00.yml`; 954행/45,833 bytes/SHA-256 `3fbadd9bf48e8d3921b43f766690bf67ad1dd2cd0a8f624d78a9b3223edeeeb7`. 후보 A는 계약 완전성, 후보 B는 canonical 참조 최소화를 강화했고 main agent가 thin loader-adapter 구조로 병합했다.
@@ -39,6 +51,38 @@
- 최종 검증: `unittest discover tests/s2_00` 38/38 PASS, loader validate-only `VALIDATED_WITH_PENDING_BINDINGS`, JSON/YAML parse·Python in-memory compile·deployment schema·모든 raw hash·module/release digest·P00/P10 NFC/prefix 검증 PASS. release digest는 `49ff3967f8eaa9c2291af6d0c17af1da2504296f03a020a84d1ea21c5954a2f0`, materialized base prefix digest는 `3634cb6929cce8395683048eabb068ed63aed0427869b19ce4b56c586ab48071`이다. - 최종 검증: `unittest discover tests/s2_00` 38/38 PASS, loader validate-only `VALIDATED_WITH_PENDING_BINDINGS`, JSON/YAML parse·Python in-memory compile·deployment schema·모든 raw hash·module/release digest·P00/P10 NFC/prefix 검증 PASS. release digest는 `49ff3967f8eaa9c2291af6d0c17af1da2504296f03a020a84d1ea21c5954a2f0`, materialized base prefix digest는 `3634cb6929cce8395683048eabb068ed63aed0427869b19ce4b56c586ab48071`이다.
- 상태·잔여한계: release는 의도적으로 `DRAFT_NOT_EXECUTABLE`·`DEV_VALIDATION_ONLY`다. O-06 external AgentBackend invocation, O-07 signed admission, Stage 1 completion seal, detached signature가 열려 있고 full Stage 1 runtime manifest도 `STAGE1_NOT_RELEASE_READY`다. authority/corpus는 미배포, P00/P10과 profile은 `DRAFT_UNVERIFIED`·법률가 검수 대기다. 10+50 fixture는 `NOT_RUN_DESCRIPTOR_BOUND_ONLY`이며 live Stage 1→S2_00→S2_10/S2_40 E2E·대한민국 변호사 법률 sign-off·production 배포를 수행하거나 주장하지 않는다. - 상태·잔여한계: release는 의도적으로 `DRAFT_NOT_EXECUTABLE`·`DEV_VALIDATION_ONLY`다. O-06 external AgentBackend invocation, O-07 signed admission, Stage 1 completion seal, detached signature가 열려 있고 full Stage 1 runtime manifest도 `STAGE1_NOT_RELEASE_READY`다. authority/corpus는 미배포, P00/P10과 profile은 `DRAFT_UNVERIFIED`·법률가 검수 대기다. 10+50 fixture는 `NOT_RUN_DESCRIPTOR_BOUND_ONLY`이며 live Stage 1→S2_00→S2_10/S2_40 E2E·대한민국 변호사 법률 sign-off·production 배포를 수행하거나 주장하지 않는다.
## 2026-08-29 — S2_00 YAML·assets·sources 생성 SOW
한 줄 요약: Stage 2 v4의 `S2_00`을 현행 Stage 1 Part 1~4만 소비하는 단일 fixed-Python deterministic ingress로 구현하기 위한 source lock·보존식·context ID·cluster/bundle·loader·atomic publish·fixture/release 계약을 `S_00_SOW.md`에 확정했다.
- 최종 산출물: `S_00_SOW.md`; 978행/67,381 bytes/SHA-256 `a1a20207480d63ee90d61f83fa88848d1936f318d0ce8ab8f5b34b5cf1ca11c4`. 실제 생성대상은 전담 workflow YAML 1, fixed Python 1, schema 2, test 6축과 fixture family이며, 공유 변경은 §2.2의 10 logical family다.
- 실행 backbone: `C00 exact bounded snapshot/source lock → C05 독립 보존검사 → C10 context·crosswalk·base issue → C15 explicit-relation cluster·slice·bundle`. executable cluster가 있으면 exact S2_10 workflow로, coherent executable package가 없으면 정확한 5개 artifact만 exact S2_40 status-only workflow로 보낸다.
- Stage 1 실물 교정: `routing/domain_screening.json`, routing/signal dual SG-01, `downstream_read_sets.stage2=["ALL"] + files[]`, P1 flat seven-key/P2 flat/P3·P4 wrapper, current-v8 Fact Ledger의 필수 `domain_effects`·`calculation_requests`, `client_goal.json` 내부 target/asset JSON Pointer를 고정했다. Stage 1 제5 task나 별도 target/asset file을 요구하지 않는다.
- 보존·식별 계약: signal file row Counter와 semantic record occurrence Counter를 분리하고 compatibility view는 integrity-only로 둔다. Stage 1에 canonical party/object ID가 없으면 실체 동일성을 확정하지 않는 occurrence·lineage context ID만 mint하며 fuzzy merge를 금지한다. review ID는 logical input·canonical raw hash·duplicate occurrence index로 만든다.
- 실행 경계: v4의 `release_ops/stage2_loader.py`가 signed release/hash/workspace를 확인하는 유일 host trust boundary다. raw digest는 byte-preserving one-read snapshot만 사용하고 TOCTOU·resource limit을 검사한다. 하나의 run ID는 input/release/algorithm/class tuple에 영구 결속하며 sibling staging 전체를 fsync 후 whole-tree atomic rename한다.
- 평가: 독립 설계안 2개를 앙상블한 뒤 서로 다른 evaluator로 정확히 2회 평가·증분 개정했다. Round 1 `CRITICAL 3/MAJOR 8/MINOR 3`, Round 2 `CRITICAL 4/MAJOR 9/MINOR 3`의 30건을 모두 `APPLIED`로 닫았다. 사용자 지정 횟수에 따라 제3회 평가·사후 PASS 선언은 하지 않았다.
- 정적검사: Markdown fence 36(짝수), Round finding 14/16, shared inventory 10행, UTF-8 PASS, trailing whitespace 0, 구 Stage 2 v.0~v.3 import edge 0.
- 경계: 이번 작업은 구현 SOW와 검증 기록의 작성이다. `Default_Agent/Stage_2_Clean/`의 실제 YAML/Python/schema/test/fixture 생성·배포, live loader invocation, Stage 1→S2_00→S2_10/S2_40 E2E, canary/production admission과 대한민국 변호사 법률 검수는 아직 수행하지 않았다.
## 2026-08-29 — 137종 청구취지 규칙 문서와 원자적 `sub_rule_id`
한 줄 요약: 사건종류별 청구취지 Markdown은 137개 고정 문서로 사전 구축하되, 복합·주제형·포괄 문서 내부의 원자적 규칙 branch를 안정적인 `sub_rule_id`로 분리하고 runtime은 구조화 registry에서 정확한 branch만 선택한다.
- 수량 정정: `N_claim_capable`은 사건별 식별 청구권 수가 아니다. 사용자의 확정 설계에서는 물리 Markdown 문서 수를 `137`로 고정하고, 별도의 구조화된 원자적 규칙 수를 `N_rule_branch`로 관리한다. 하나의 문서가 여러 개별 청구 규칙을 포함할 수 있으므로 두 수량을 혼동하지 않는다.
- 실행정책: 사건 실행 중 문서를 생성하지 않는다. S2_10/S2_20에서 식별·정규화한 atomic claim signature를 C25가 exact predicate로 `case_type_id`와 `sub_rule_id`에 결속하고, S2_30에는 해당 사전 승인 branch만 공급한다.
- 문서 metadata: 각 문서는 document-level `case_type_id`를 가지고, 각 원자적 section에는 `sub_rule_id=RELIEF.<case_type_id>.<immutable_branch_key>`, `signature_predicate_id`, `renderer_id`, `required_slots`, 병합·예비적 관계, 금지조건, authority·적용기간·review status를 기계 판독 가능한 YAML block으로 기록한다. 순번·내용 hash 기반 ID와 폐기 ID 재사용은 금지한다.
- projection: 법률가가 branch 경계·내용·ID를 승인한 뒤 `offline_build/compile_relief_rule_projection.py`가 Markdown을 검증하여 `case_type_rule_registry.yml`과 `case_type_relief_rules.yml`의 `signature predicate → case_type_id → sub_rule_id` row로 projection한다. runtime은 Markdown 자유문을 직접 해석하지 않는다.
- YAML 성격: canonical 92개는 실제로 `LLM-DIRECT` 2, `LLM-CONTEXT` 45, `DUAL-CONTRACT` 6, `NON-LLM-DETERMINISTIC` 39의 네 종류다. DIRECT만 모델을 호출하고, CONTEXT는 선택 주입되는 법리정보, NON-LLM은 고정 Python용 선언 데이터, DUAL은 deterministic 정본과 제한된 LLM projection을 함께 가진다.
- 경계: 이번 세션은 설계 해석을 확정하여 MEMORY에 기록한 것이다. `assets_for_stage_2_v.4.md`의 `N_claim_capable` 표기, v4 전략서, 137개 Markdown, `sub_rule_id` registry와 compiler 구현은 아직 개정·생성하지 않았다.
## 2026-08-29 — ACTIO 지정 10종의 migration 경계
한 줄 요약: 기존 ACTIO 10종은 사건별 runtime 입력이 아니라 신규 canonical ACTIO 자산을 만드는 일회성 offline migration source이며, runtime은 검수·봉인된 canonical target만 소비한다.
- migration 처리: 원본에서 법리 명제·route·계산 operand·항변·검증조건을 추출하고 현행 공식 법령·판례와 대조한 뒤, 승인된 내용만 CE-10 계산규칙, ACTIO overlay·route registry·validator·regression fixture 등으로 이관한다. 원본 내용의 무검증 복사나 runtime fallback은 금지한다.
- 감사증적: `migration/actio_assets_receipt.json`은 원본 exact path, raw basename bytes/NFC display name, source hash, 추출 proposition, official authority, 교정·제외 이유, canonical target와 target hash를 기록한다.
- 경계: 이번 작업은 위 문구의 의미를 확정하여 MEMORY에 기록한 것이며 ACTIO canonical 자산·migration receipt·compiler를 실제 생성하거나 실행하지 않았다.
## 2026-08-28 — Stage 2 최적 개정 전략 v4 및 자산 명세 ## 2026-08-28 — Stage 2 최적 개정 전략 v4 및 자산 명세
한 줄 요약: v3의 유효 계약을 보존하면서 `take_away_from_eval_v.3.md`의 채택사항을 5-task clean-slate DAG에 흡수하고, 2회 독립 병렬 전략 검증과 1회 독립 자산 검증을 거쳐 v4 전략서·상세 SVG·version-free 자산/source inventory를 완성했다. 한 줄 요약: v3의 유효 계약을 보존하면서 `take_away_from_eval_v.3.md`의 채택사항을 5-task clean-slate DAG에 흡수하고, 2회 독립 병렬 전략 검증과 1회 독립 자산 검증을 거쳐 v4 전략서·상세 SVG·version-free 자산/source inventory를 완성했다.
@@ -0,0 +1,412 @@
# S2_00 고정 자산·계약·source inventory v1
> 기준 문서: `S_00_SOW_v.1.md`; 최종 SHA-256은 문서·자산 검증 완료 시 receipt에 기록
>
> 기준일: 2026-08-30 (Asia/Seoul)
>
> 문서 목적: S2_00을 구현·시험·배포·실행할 때 필요한 고정 파일과 고정 locator를 누락 없이 구분한다.
## 0. 판독 기준
이 문서는 `stage_2_optimal_update_strategy_v.5.md`와 `S_00_SOW_v.1.md`의 direct MCP inline Code Executor 계약을 기준으로 작성한다.
```text
P = workspace logical root
M = Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/
R = Default_Agent/Stage_2_Clean/
U = workspace Stage 1 current-run logical root
D = Default_Agent/
Q = stage2_control/s2_00_request.json (사건별 runtime input; 고정 자산 아님)
O = stage2_runs/by-binding/<run_binding_digest>/
```
2026-08-30 현재 repository authoring tree의 `M/Default_Agent/Stage_2_Clean/`에는 S2_00 고정 자산이 존재한다. 아래 표는 이를 runtime version-free `R/`로 투영한 경로를 사용하고 각 자산을 `REUSE`, `UPDATE`, `NEW`, `REFERENCE_ONLY`로 처분한다.
이 문서에서 구분하는 물리 성격은 다음과 같다.
| 성격 | 의미 |
|---|---|
| `EXACT-OWNED` | S2_00이 직접 소유하는 고정 파일 |
| `EXACT-SHARED` | 다른 task/release owner가 소유하지만 S2_00 때문에 생성·개정해야 하는 고정 파일 |
| `FIXED-RELEASE` | 사건과 무관하게 미리 작성되며, release가 활성 subset의 exact path/hash를 봉인하는 파일 |
| `FIXED-FAMILY` | 파일명 개수는 release에 따라 달라지지만 각 물리 파일은 실행 전에 생성·검수·봉인되는 family |
| `UPSTREAM-DEPLOYMENT` | Stage 1 배포본의 read-only 고정 계약 파일 |
| `RUNTIME-LOCATOR` | 경로·producer 계약은 고정이나 내용은 사건마다 Stage 1이 생성하는 입력 파일 |
| `CONDITIONAL` | 기본 배포에는 없고 명시된 조건에서만 release가 exact path/hash를 제공하는 파일 |
### 0.1 수량 요약
| 범주 | exact file | family | 비고 |
|---|---:|---:|---|
| S2_00 실행·binding 신규 | 4 physical | 0 | authoring YAML, deployment projection, executor binding, inline-code receipt |
| S2_00 직접 소유 core | 4 logical / 5 physical | 0 | workflow 1, full-code mirror pair 2, schema 2 |
| S2_00 projection builder | 1 logical / 2 physical | 0 | build-only `.py/.txt` pair |
| S2_00 명명 test source | 7 logical / 14 physical | 0 | 기존 6축 + inline-code parity; 각 `.py`는 byte-identical `.txt` mirror 필요 |
| S2_00 fixture | 0 | 2 | case fixture와 mutation fixture |
| 공유 계약·executor·handoff | 10 logical | 0 | loader 2종은 active closure에서 빠지고 executor binding/receipt가 들어감 |
| S2_10 direct bundle 전체 planned catalog | 49 | 1 | P00/P10 2, profile 45, authority registry/release 2, capture family 1; 사건별로는 active subset만 결속 |
| authority closure 조건부 law-value | 2 | 0 | authority release가 참조할 때만 exact closure에 포함; bundle 전체-row 복제 금지 |
| 후단 availability manifest | 2 | 0 | S2_00은 내용 ingest 없이 digest/availability만 확인 |
| Stage 1 배포 계약 현행 closure | 55 | 0 | anchor 3 + domain config 26 + platform schema 9 + signal-support schema 17 |
| Stage 1 사건별 입력 | 16 | 1 | direct allowlist 16 + signal payload family; optional JSON Pointer 2개는 파일 아님 |
| 조건부 relocation 계약 | 0 | 1 | 기본 배포에는 요구하지 않음 |
서로 성격이 다른 범주를 합산한 단일 “총 파일 수”는 사용하지 않는다. 특히 runtime input과 run output은 신규 S2_00 고정 자산 수에 포함하지 않는다.
## 1. S2_00 전담 생성 파일
### 1.0 v1 실행·binding 신규 4종
| 파일·배포 위치 | 성격 | brief 역할 | 조치 |
|---|---|---|---|
| `M/Stage_2_S2_00_v.1.yml` | `AUTHORING_EXECUTABLE_SHAPE / PENDING_SECRET_AND_LIVE_BINDING` | 유일 편집 정본; exactly-one inline `run_code` task | `NEW` |
| `R/agent_scripts/Stage_2_S2_00.yml` | `EXACT-OWNED` deployment projection candidate | builder가 authoring 정본에서 생성하는 version-free signed 실행본; canary/production 실행 대상 | `NEW` |
| `R/deployment/stage2_code_executor_binding.yml` | `EXACT-SHARED` | MCP server/tool, Python/runtime image와 `httpx==0.28.1`, agent-network/300초, Agent/code/mirror/release hash, egress profile, localdocs tool/path allowlist | `NEW` |
| `R/manifest/s2_00_inline_code_receipt.json` | `EXACT-SHARED` | authoring/deployment canonical task semantics, canonical code bytes, full mirror hash·compile·AST parity receipt | `NEW` |
### 1.1 retained·updated core 4 logical units
| 번호 | 파일·배포 위치 | 성격 | brief 역할 | 조치 |
|---:|---|---|---|---|
| 1 | `R/workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml` | `EXACT-OWNED` | C00→C05→C10→C15 IO·route·binary localdocs·status-last barrier 계약 | `UPDATE` |
| 2 | `R/runtime/s2_00_ingress.py`와 `.txt` | `EXACT-OWNED` full-code parity oracle | unique-key parser가 반환한 전체 YAML `parameters.code` 문자열을 변경 없이 UTF-8 encode한 byte-identical mirror; runtime read/import 금지 | `UPDATE` |
| 3 | `R/schemas/ingress.schema.json` | `EXACT-OWNED` | source contract, two-pass binary snapshot receipt, input/intake/diagnostic/logical barrier/run binding | `UPDATE` |
| 4 | `R/schemas/context.schema.json` | `EXACT-OWNED` | case/evidence/object/party-title/slot/cluster/slice/bundle 의미계약 | `REUSE` |
### 1.1A build-only projection asset
| 파일·배포 위치 | 성격 | brief 역할 | 조치 |
|---|---|---|---|
| `R/offline_build/build_s2_00_inline_projection.py`와 `.txt` | `BUILD_ONLY` | authoring YAML을 읽어 version-free projection→전체 code mirror→receipt만 생성하고 hash/compile/parity를 검증; authoring YAML 재작성·사건 runtime 실행 금지 | `NEW` |
### 1.2 명명된 test source 7 logical axes
| 번호 | 파일·배포 위치 | 성격 | brief 역할 | 조치 |
|---:|---|---|---|---|
| 5 | `R/tests/s2_00/test_resolver_source_lock.py`와 `.txt` | `EXACT-OWNED` | localdocs binary hydration, workspace/path isolation, bounded two-pass hash stability, strict parser/source lock | `UPDATE` |
| 6 | `R/tests/s2_00/test_schema_hash_and_signals.py`와 `.txt` | `EXACT-OWNED` | schema/hash, signal file·record 이중 보존식, routing/signal dual SG-01 시험 | `REUSE` |
| 7 | `R/tests/s2_00/test_conservation.py`와 `.txt` | `EXACT-OWNED` | BO·Fact Ledger·LES·evidence·event·signal·review multiset과 join 보존 시험 | `REUSE` |
| 8 | `R/tests/s2_00/test_canonical_ids.py`와 `.txt` | `EXACT-OWNED` | Stage 1 ID 보존, party/object occurrence ID, review ID, Unicode와 collision 시험 | `REUSE` |
| 9 | `R/tests/s2_00/test_cluster_bundle_compile.py`와 `.txt` | `EXACT-OWNED` | explicit-relation cluster, SCC/DAG, slice, cache prefix와 executable cohort 시험 | `REUSE` |
| 10 | `R/tests/s2_00/test_failure_and_atomic_publish.py`와 `.txt` | `EXACT-OWNED` | affected-scope route, retry/idempotence, partial write와 status-last barrier | `UPDATE` |
| 11 | `R/tests/s2_00/test_inline_code_parity.py`와 `.txt` | `EXACT-OWNED` | YAML code extraction·compile·hash·mirror parity, placeholder/외부 `.py`/plaintext credential 0 | `NEW` |
각 `.py` test는 동일 내용의 `.txt` mirror를 유지한다. test file을 통합하려면 `module_manifest.json`, `regression_manifest.json`과 본 inventory를 동시에 개정한다.
### 1.3 fixture family
| 파일·배포 위치 | 성격 | brief 역할 | exact set 결정 방식 |
|---|---|---|---|
| `R/tests/fixtures/cases/<fixture_id>.json` | `FIXED-FAMILY` | 정상·경계 사건의 source locator, raw hash, expected artifact·issue·route·digest를 제공 | `regression_manifest.json`이 path/hash를 전수 봉인 |
| `R/tests/fixtures/mutations/<mutation_id>.json` | `FIXED-FAMILY` | 단일 결함을 주입하여 invariant와 expected reason code를 검증 | `regression_manifest.json`이 path/hash를 전수 봉인 |
## 2. 공유 계약·executor·handoff 고정 파일
| 번호 | 파일·배포 위치 | 성격 | brief 역할 | owner·S2_00 경계 |
|---:|---|---|---|---|
| 1 | `R/manifest/module_manifest.json` | `EXACT-SHARED` | 법률/data/workflow-contract/schema/test/profile closure; release hash를 내장하는 Agent/full mirror는 executor binding/receipt가 단독 결속하여 hash cycle 방지 | release build owner; `UPDATE` |
| 2 | `R/manifest/stage2_release.json` | `EXACT-SHARED` | Stage 1 dependency lock, executor binding, module/authority/corpus/coverage digest, admission | release operator; `UPDATE` |
| 3 | `R/deployment/stage2_code_executor_binding.yml` | `EXACT-SHARED` | S2_00 Agent/code/tool/localdocs allowlist exact binding | release operator; §1.0과 같은 physical file |
| 4 | `R/manifest/s2_00_inline_code_receipt.json` | `EXACT-SHARED` | unique-key parser가 반환한 code 문자열의 변경 없는 UTF-8 bytes, full mirror equality·compile/AST와 pure-core 별도 hash scope 증거 | release build owner; §1.0과 같은 physical file |
| 5 | `R/schemas/deployment.schema.json` | `EXACT-SHARED` | executor binding, outer result, inner receipt, logical publish receipt `$defs` | deployment schema owner; `UPDATE` |
| 6 | `R/schemas/review_status.schema.json` | `EXACT-SHARED` | `issue_ledger.base`, review normalization, impact scope와 downstream action을 검증 | review schema owner |
| 7 | `R/registry/cache/prompt_cache_policy.yml` | `EXACT-SHARED` | PII-free static prefix, canonical hash, key, cache miss와 release-integrity failure를 구분 | cache policy owner |
| 8 | `R/tests/fixtures/regression_manifest.json` | `EXACT-SHARED` | case/mutation fixture의 exact path/hash/seed/expected digest를 봉인 | regression owner |
| 9 | `R/workflows/S2_10_domain_relief_resolution_map.yml` | `EXACT-SHARED` | `executable_cluster_ids[]`가 지정한 immutable slice/bundle만 소비하도록 handoff를 고정 | S2_10 owner; raw Stage 1 재탐색 금지 |
| 10 | `R/workflows/S2_40_final_review_render_and_commit.yml` | `EXACT-SHARED` | diagnostic branch에서 S2_00의 정확한 5개 artifact만 받는 status-only entry를 제공 | S2_40 owner; final status single writer |
다음 두 파일은 물리적으로 보존하되 active S2_00 runtime closure에서는 제외한다.
| 파일 | disposition | 이유 |
|---|---|---|
| `R/release_ops/stage2_loader.py`와 `.txt` | `REFERENCE_ONLY_SUPERSEDED_FOR_S2_00` | host subprocess loader를 사용하지 않음 |
| `R/deployment/stage2_loader_binding.yml` | `REFERENCE_ONLY_SUPERSEDED_FOR_S2_00` | 새 executor binding이 active authority |
## 3. S2_10 bundle을 위해 S2_00이 검증할 고정 자산
S2_00은 아래 자산으로 법률판단을 수행하지 않는다. canary/production bundle의 static prefix와 active context subset을 선정하고 path/hash/PII/release closure만 검증한다.
따라서 아래 49개는 물리적 planned catalog 수이지 사건별 bundle 수가 아니다. 사건별 closure는 `P00 + P10 + authority registry/release + N_active_profiles + N_selected_captures`이며, release가 선택하지 않은 profile·capture를 bundle에 넣지 않는다.
### 3.1 static prompt·authority 4개와 capture family
| 번호 | 파일·배포 위치 | 성격 | brief 역할 | S2_00 처리 |
|---:|---|---|---|---|
| 1 | `R/prompts/P00_system_and_safety_contract.md` | `FIXED-RELEASE` | 공통 role, source hierarchy, provenance, security와 금지규칙 static prefix | canonical hash·PII 검사 후 bundle ref만 작성 |
| 2 | `R/prompts/P10_legal_resolution_contract.md` | `FIXED-RELEASE` | S2_10 판단 순서, typed output contract와 self-check static prefix | canonical hash·PII 검사 후 bundle ref만 작성 |
| 3 | `R/registry/authority/authority_registry.yml` | `FIXED-RELEASE` | 승인된 proposition, temporal scope, official locator와 후속 취급의 정본 | active common-authority row만 선택·봉인 |
| 4 | `R/manifest/authority_release.json` | `FIXED-RELEASE` | authority registry, capture와 law-value dependency의 exact set/hash seal | signed release와 cross-hash 검사 |
| family | `R/authority/source_captures/<authority_id>.json` | `FIXED-FAMILY` | 공식 원문 locator, 원문/발췌 hash, 시행·선고일과 temporal metadata | authority release가 선정한 capture만 검증; glob 금지 |
`P00` 또는 `P10`이 없는 단계에서는 사건 run을 executable로 표시하지 않고 `STRUCTURAL_FIXTURE`만 허용한다.
다음 두 law-value 파일은 모든 사건 bundle에 일괄 삽입하는 자산이 아니다. `authority_release.json`이 해당 사건의 approved common-authority ref가 사용하는 token을 exact dependency로 열거할 때만 hash closure를 검증하고 필요한 row ref만 bundle에 결속한다.
| 파일·배포 위치 | 성격 | brief 역할 | S2_00 처리 |
|---|---|---|---|
| `R/law_values/general_law_values.yml` | `CONDITIONAL` | 이율·기간·상한 등 output-affecting authority-bound token | authority release에 참조된 exact token/file hash만 검증; 전체 row ingest 금지 |
| `R/law_values/court_fee_values.yml` | `CONDITIONAL` | 소가·인지·송달비용의 시점별 authority-bound token | S2_10 static bundle이 참조할 때만 결속; 후단 전용이면 availability 범위에 머묾 |
### 3.2 substantive profile 22개
| 번호 | 파일·배포 위치 | brief 역할 |
|---:|---|---|
| 1 | `R/registry/substantive/EC-00_contract_general.yml` | 계약 공통 성립·효력·이행·해제·손해배상 context |
| 2 | `R/registry/substantive/E-01_juristic_act_validity.yml` | 법률행위 무효·취소·추인·원상회복 context |
| 3 | `R/registry/substantive/E-02_contract_money_claim.yml` | 대금·대여금 등 계약상 금전채권 context |
| 4 | `R/registry/substantive/E-03_parties_liability_succession.yml` | 보증·연대·승계·상호속용 등 책임주체 context |
| 5 | `R/registry/substantive/E-04_unjust_enrichment.yml` | 부당이득 유형·법률상 원인·반환범위 context |
| 6 | `R/registry/substantive/E-05_tort_general.yml` | 일반 불법행위·인과관계·손해·과실상계 context |
| 7 | `R/registry/substantive/E-06_professional_liability.yml` | 전문직 위임·주의의무·손해 context |
| 8 | `R/registry/substantive/E-07_construction_defect.yml` | 공사대금·추가공사·하자·감액 context |
| 9 | `R/registry/substantive/E-08_lease_deposit.yml` | 임대차보증금·명도·공제·동시이행 context |
| 10 | `R/registry/substantive/E-09_registry_transfer_claims.yml` | 소유권이전·말소·회복·경정 등기 context |
| 11 | `R/registry/substantive/E-10_secured_registry.yml` | 근저당·전세권·담보권 등기·말소 context |
| 12 | `R/registry/substantive/E-11_possession_vindication.yml` | 인도·명도·방해배제·점유 context |
| 13 | `R/registry/substantive/E-12_co_ownership_boundary.yml` | 공유물분할·경계·지분 관계 context |
| 14 | `R/registry/substantive/E-13_creditor_preservation.yml` | 채권자대위·사해행위취소·보전 context |
| 15 | `R/registry/substantive/E-14_execution_linked_claims.yml` | 배당·청구이의·집행 관련 본안 context |
| 16 | `R/registry/substantive/E-15_succession_family_property.yml` | 상속·유류분·상속재산 귀속 context |
| 17 | `R/registry/substantive/E-16_negotiable_instruments.yml` | 어음·수표 권리·항변 context |
| 18 | `R/registry/substantive/E-17_labor_wage_claims.yml` | 임금·수당·퇴직금 context |
| 19 | `R/registry/substantive/E-18_org_resolution_status.yml` | 회사·조합 결의·지위·청산 context |
| 20 | `R/registry/substantive/E-19_insurance_claims.yml` | 보험금·면책·대위·중복보험 context |
| 21 | `R/registry/substantive/E-20_ip_claims.yml` | 지식재산 침해·금지·손해배상 context |
| 22 | `R/registry/substantive/E-21_media_personality_rights.yml` | 명예·인격권·보도 관련 구제 context |
### 3.3 crosscut profile 5개
| 번호 | 파일·배포 위치 | brief 역할 |
|---:|---|---|
| 1 | `R/profiles/crosscut/E-00_residual_unrouted.yml` | 기존 profile로 routing되지 않는 이슈를 보존하고 review로 전달 |
| 2 | `R/profiles/crosscut/X1_notice_lifecycle.yml` | 최고·통지·해제·송달의 actor·도달·효과 lifecycle |
| 3 | `R/profiles/crosscut/X2_asset_identity_lineage.yml` | 목적물 동일성·변동·등기·점유 lineage |
| 4 | `R/profiles/crosscut/X3_procedure_standing_relief.yml` | 당사자적격·소의 이익·필수당사자·구제 적합성 |
| 5 | `R/profiles/crosscut/X4_response_admission_defense.yml` | 항변·재항변·불리한 사실·자백위험·선진술 |
### 3.4 special-law profile 13개
| 번호 | 파일·배포 위치 | brief 역할 |
|---:|---|---|
| 1 | `R/profiles/special_law/SL-AUTO_motor_vehicle.yml` | 자동차손해 책임·보험·과실 context |
| 2 | `R/profiles/special_law/SL-INDUSTRIAL_ACCIDENT.yml` | 산업재해·보상·손해 조정 context |
| 3 | `R/profiles/special_law/SL-PRODUCT_LIABILITY.yml` | 제조물책임 요건·면책·손해 context |
| 4 | `R/profiles/special_law/SL-RESIDENTIAL_LEASE.yml` | 주택임대차 대항력·우선변제·승계 context |
| 5 | `R/profiles/special_law/SL-COMMERCIAL_LEASE.yml` | 상가임대차 대항력·갱신·권리금 context |
| 6 | `R/profiles/special_law/SL-LABOR.yml` | 노동관계 강행규정·지위·기간 context |
| 7 | `R/profiles/special_law/SL-STATE_LIABILITY.yml` | 국가배상 특별요건·공법경계·review trigger |
| 8 | `R/profiles/special_law/SL-IP-PATENT.yml` | 특허·실용신안 권리범위·침해·구제 context |
| 9 | `R/profiles/special_law/SL-IP-COPYRIGHT.yml` | 저작권·저작인격권 침해·구제 context |
| 10 | `R/profiles/special_law/SL-IP-OTHER.yml` | 상표·디자인·부정경쟁·영업비밀 context |
| 11 | `R/profiles/special_law/SL-MEDIA.yml` | 정정·반론·추후보도와 명예구제 context |
| 12 | `R/profiles/special_law/SL-TRANSPORT_MARITIME.yml` | 운송·해상 책임기간·면책·책임제한 context |
| 13 | `R/profiles/special_law/SL-CONSUMER_CONTRACT.yml` | 소비자성·거래방식·철회·무효·환급 context |
### 3.5 ACTIO overlay 5개
| 번호 | 파일·배포 위치 | brief 역할 |
|---:|---|---|
| 1 | `R/profiles/overlays/ACTIO-MORTGAGE.yml` | 기존 담보부 목적물 양도·실채무·공동담보 overlay |
| 2 | `R/profiles/overlays/ACTIO-MORTGAGE-CREATION.yml` | 사해적 담보권 설정·배당 route overlay |
| 3 | `R/profiles/overlays/ACTIO-ENCUMBERED-TRANSFER.yml` | 부담부 소유권이전·가액배상 overlay |
| 4 | `R/profiles/overlays/ACTIO-PRESERVED-CLAIM-BUNDLE.yml` | 복수 피보전채권·이자·변제·담보부족 overlay |
| 5 | `R/profiles/overlays/ACTIO-DEFENSE-MAP.yml` | 충분담보·상계·수익자·전득자 선의·재항변 overlay |
45개 profile은 모두 `FIXED-RELEASE`·`LLM-CONTEXT` 자산이다. S2_00은 전체를 사건 bundle에 넣지 않고 Stage 1 activation·release manifest가 지정한 active subset만 exact path/hash로 결속한다.
### 3.6 후단 availability만 확인할 manifest 2개
| 파일·배포 위치 | 성격 | brief 역할 | S2_00 경계 |
|---|---|---|---|
| `R/manifest/case_type_coverage.json` | `EXACT-SHARED` | 137 row별 rule·renderer·corpus·profile·계산·review coverage와 sign-off | digest/availability만 확인; catalog·rule 본문 ingest 금지 |
| `R/manifest/corpus_release.json` | `EXACT-SHARED` | Weaviate collection/schema/snapshot/chunk/crosswalk의 exact set/hash seal | digest/availability만 확인; raw corpus ingest 금지 |
## 4. Stage 1 배포 계약 source
### 4.1 exact deployment file 3개
| 번호 | 파일·배포 위치 | 성격 | brief 역할 | 처리 |
|---:|---|---|---|---|
| 1 | `D/runtime_manifest.json` | `UPSTREAM-DEPLOYMENT` | Stage 1 배포 asset의 path/hash integrity closure | referenced closure만 read-only 검증; historical status를 사건 상태로 복사 금지 |
| 2 | `D/domains/_registry_index.json` | `UPSTREAM-DEPLOYMENT` | domain ID, config path와 config hash의 정본 index | expected/active set과 비교 |
| 3 | `D/signals/signal_registry.v2.json` | `UPSTREAM-DEPLOYMENT` | SG-01~SG-13 filename, schema와 consumer registry | signal manifest coverage와 비교 |
### 4.2 현행 domain config closure 26개
아래는 현재 `_registry_index.json`이 열거하는 concrete path다. 모두 `UPSTREAM-DEPLOYMENT`이며, element/opposing/defense slot, calculation binding와 emitted signal 계약을 제공한다.
| 번호 | 파일·배포 위치 | brief 역할 |
|---:|---|---|
| 1 | `D/domains/E-00/domain_config.json` | residual/unrouted domain slot·signal 계약 |
| 2 | `D/domains/E-01/domain_config.json` | 법률행위 유효성 domain 계약 |
| 3 | `D/domains/E-02/domain_config.json` | 계약상 금전채권 domain 계약 |
| 4 | `D/domains/E-03/domain_config.json` | 당사자 책임·승계 domain 계약 |
| 5 | `D/domains/E-04/domain_config.json` | 부당이득 domain 계약 |
| 6 | `D/domains/E-05/domain_config.json` | 일반 불법행위 domain 계약 |
| 7 | `D/domains/E-06/domain_config.json` | 전문직 책임 domain 계약 |
| 8 | `D/domains/E-07/domain_config.json` | 공사·하자 domain 계약 |
| 9 | `D/domains/E-08/domain_config.json` | 임대차·보증금 domain 계약 |
| 10 | `D/domains/E-09/domain_config.json` | 소유권·등기 domain 계약 |
| 11 | `D/domains/E-10/domain_config.json` | 담보·제한물권 등기 domain 계약 |
| 12 | `D/domains/E-11/domain_config.json` | 점유·인도·명도 domain 계약 |
| 13 | `D/domains/E-12/domain_config.json` | 공유·경계 domain 계약 |
| 14 | `D/domains/E-13/domain_config.json` | 채권자 보전·사해행위취소 domain 계약 |
| 15 | `D/domains/E-14/domain_config.json` | 집행 연계 domain 계약 |
| 16 | `D/domains/E-15/domain_config.json` | 상속·가족재산 domain 계약 |
| 17 | `D/domains/E-16/domain_config.json` | 어음·수표 domain 계약 |
| 18 | `D/domains/E-17/domain_config.json` | 임금·퇴직금 domain 계약 |
| 19 | `D/domains/E-18/domain_config.json` | 회사·조합 결의·지위 domain 계약 |
| 20 | `D/domains/E-19/domain_config.json` | 보험 domain 계약 |
| 21 | `D/domains/E-20/domain_config.json` | 지식재산 domain 계약 |
| 22 | `D/domains/E-21/domain_config.json` | 언론·인격권 domain 계약 |
| 23 | `D/domains/EC-00/domain_config.json` | 계약 공통 lifecycle domain 계약 |
| 24 | `D/domains/X1/domain_config.json` | 통지·최고 lifecycle crosscut 계약 |
| 25 | `D/domains/X2/domain_config.json` | 목적물 identity/lineage crosscut 계약 |
| 26 | `D/domains/X3/domain_config.json` | 절차·당사자적격·구제 crosscut 계약 |
### 4.3 현행 platform schema closure 9개
| 번호 | 파일·배포 위치 | S2_00 관련성 | brief 역할 |
|---:|---|---|---|
| 1 | `D/platform/schemas/client_goal_domain_profiles.schema.json` | direct projection anchor | `client_goal.json` 중 domain-profile projection shape; 전체 client-goal schema로 오인 금지 |
| 2 | `D/platform/schemas/domain_fanout_plan.schema.json` | build/adapter evidence | activation 이후 domain fanout plan shape |
| 3 | `D/platform/schemas/domain_seed_output.schema.v3.json` | build/adapter evidence | domain별 seed output v3 shape |
| 4 | `D/platform/schemas/domain_slice.schema.v2.json` | build/adapter evidence | domain slice v2 shape와 source linkage |
| 5 | `D/platform/schemas/fact_exception_pack.schema.json` | review/adapter evidence | fact exception·review pack shape |
| 6 | `D/platform/schemas/fact_ledger_base.schema.json` | direct input anchor | `Fact_Ledger_base.json`의 typed fact·domain effect·calculation request shape |
| 7 | `D/platform/schemas/fact_ledger_candidate_bundle.schema.json` | build/adapter evidence | final ledger 전 candidate bundle shape |
| 8 | `D/platform/schemas/legal_effect_structures.schema.json` | direct input anchor | `legal_effect_structures.json`의 route·BO reverse index·calculation request shape |
| 9 | `D/platform/schemas/structure_seed_bundle.schema.json` | build/adapter evidence | LES 생성 전 structure-seed bundle shape |
`build/adapter evidence` schema는 사건별 파일을 별도로 allowlist에 추가한다는 뜻이 아니다. direct input의 현행 producer lineage와 adapter를 검증하기 위한 배포 closure다.
### 4.4 현행 signal-support schema closure 17개
| 번호 | 파일·배포 위치 | brief 역할 |
|---:|---|---|
| 1 | `D/signals/_common/evidence_slot_status.schema.json` | signal evidence-slot status 공통 enum·shape |
| 2 | `D/signals/_common/signal_item.schema.json` | SG record 공통 identity·source·detail shape |
| 3 | `D/signals/schemas/domain_activation_manifest.schema.json` | SG-01 activation compatibility payload shape |
| 4 | `D/signals/schemas/procedural_posture_relief_signals.schema.json` | SG-02 절차·구제 signal shape |
| 5 | `D/signals/schemas/party_capacity_standing_signals.schema.json` | SG-03 당사자능력·적격 signal shape |
| 6 | `D/signals/schemas/governing_law_version_signals.schema.json` | SG-04 준거법·법령버전 signal shape |
| 7 | `D/signals/schemas/legal_relation_lifecycle_signals.schema.json` | SG-05 법률관계 lifecycle signal shape |
| 8 | `D/signals/schemas/timeline_notice_condition_signals.schema.json` | SG-06 기한·최고·통지·조건 signal shape |
| 9 | `D/signals/schemas/asset_right_state_signals.schema.json` | SG-07 자산·권리상태 signal shape |
| 10 | `D/signals/schemas/liability_causation_damage_signals.schema.json` | SG-08 책임·인과관계·손해 signal shape |
| 11 | `D/signals/schemas/defense_exception_signals.schema.json` | SG-09 항변·예외 signal shape |
| 12 | `D/signals/schemas/evidence_proof_conflict_signals.schema.json` | SG-10 증거·증명·충돌 signal shape |
| 13 | `D/signals/schemas/calculation_requirements.schema.json` | SG-11 계산 필요사항 signal shape |
| 14 | `D/signals/schemas/remedy_enforcement_signals.schema.json` | SG-12 구제·집행 signal shape |
| 15 | `D/signals/schemas/legal_effect_routes.schema.json` | SG-13 법률효과 route signal shape |
| 16 | `D/signals/schemas/domain_signal_envelope.schema.v2.json` | active domain별 signal envelope v2 shape |
| 17 | `D/signals/schemas/signal_manifest.schema.json` | signal transaction, `files[]`, downstream read-set shape |
§4.2~§4.4의 52개 path와 §4.1의 3개 anchor가 현행 55-file closure다. 이는 2026-08-29 snapshot의 명시적 inventory이며 영구적인 glob 계약이 아니다. Phase S00-0에서 `_registry_index.json`, `runtime_manifest.json`, `signal_registry.v2.json`이 지정하는 각 path/hash/schema ID를 `stage2_release.json` dependency lock에 다시 materialize한다. release에서 빠진 파일을 directory scan으로 보충하거나 `*.json` glob으로 읽어서는 안 된다.
## 5. Stage 1 runtime input allowlist
아래 파일은 S2_00이 새로 생성하는 고정 자산이 아니다. 다만 logical path와 producer contract가 고정되어 있으므로 구현 allowlist에 반드시 포함한다.
| 번호 | logical 파일·위치 | 성격 | producer | brief 역할·처분 경계 |
|---:|---|---|---|---|
| 1 | `U/evidence_indexed.json` | `RUNTIME-LOCATOR` | Stage 1 Part 1 | evidence universe와 provenance; gap은 affected scope로 보존 |
| 2 | `U/evidence_event_candidates.json` | `RUNTIME-LOCATOR` | Stage 1 Part 1 | 이행기·최고·도달·해제·제공·거절 event 후보 |
| 3 | `U/client_goal.json` | `RUNTIME-LOCATOR` | Stage 1 Part 1 Task A | 의뢰인 목표·제약·당사자·회수정보; 부재를 청구권 부존재로 해석 금지 |
| 4 | `U/routing/domain_screening.json` | `RUNTIME-LOCATOR` | Stage 1 Part 1 | screening hash와 activation lineage anchor |
| 5 | `U/routing/domain_activation_manifest.json` | `RUNTIME-LOCATOR` | Stage 1 Part 1 D0 | canonical expected/active domain과 config refs |
| 6 | `U/quality_gates/B1_evidence_indexed_gate.json` | `RUNTIME-LOCATOR` | Stage 1 Part 1 | evidence-index gate와 assertion 제한 근거 |
| 7 | `U/quality_gates/B2_event_candidates_gate.json` | `RUNTIME-LOCATOR` | Stage 1 Part 1 | event-candidate gate와 assertion 제한 근거 |
| 8 | `U/quality_gates/stage1_part1_soft_gate_handoff.json` | `RUNTIME-LOCATOR` | Stage 1 Part 1 | flat seven-key digest guard와 review handoff |
| 9 | `U/BO.json` | `RUNTIME-LOCATOR` | Stage 1 Part 2 | BO identity backbone과 source occurrence |
| 10 | `U/signals/signal_manifest.json` | `RUNTIME-LOCATOR` | Stage 1 Part 2 | signal transaction, `files[]`와 Stage 2 `ALL` read-set 정본 |
| 11 | `U/quality_gates/stage1_part2_review_handoff.json` | `RUNTIME-LOCATOR` | Stage 1 Part 2 | flat review universe; 존재하지 않는 공통 count field 요구 금지 |
| 12 | `U/legal_effect_structures.json` | `RUNTIME-LOCATOR` | Stage 1 Part 3 | LES domain/type/route, BO reverse index와 calculation request |
| 13 | `U/quality_gates/stage1_part3_review_handoff.json` | `RUNTIME-LOCATOR` | Stage 1 Part 3 | wrapper-aware LES review handoff |
| 14 | `U/Fact_Ledger_base.json` | `RUNTIME-LOCATOR` | Stage 1 Part 4 | `fact_id`·`source_bo_id` anchor; current-v8 row의 `domain_effects`·`calculation_requests` 필수 |
| 15 | `U/stage1_tmp/fact_ledger/fact_ledger_writer_report.json` | `RUNTIME-LOCATOR` | Stage 1 Part 4 | ledger hash, conservation, gate firing와 calculation readiness receipt |
| 16 | `U/quality_gates/stage1_part4_review_handoff.json` | `RUNTIME-LOCATOR` | Stage 1 Part 4 | wrapper-aware final review handoff |
| family | `U/signals/<signal_manifest.files[i].path>` | `RUNTIME-LOCATOR` | Stage 1 Part 2 signal compiler | manifest가 열거한 canonical/domain/compatibility payload; `U/signals/` prefix를 붙여 읽음 |
signal family에는 `U/signals/domain_activation_manifest.json` SG-01이 포함된다. 이는 `U/routing/domain_activation_manifest.json`과 raw-byte 동일 파일이 아니므로 각각의 raw hash를 보존하고 승인된 semantic projection만 비교한다.
다음 둘은 별도 파일이 아니라 `client_goal.json` 내부 optional field다.
| JSON Pointer | brief 역할 | 금지사항 |
|---|---|---|
| `U/client_goal.json#/defendant_target_matrix` | 피고별 제소 유지·제외 의사와 현재 회수위험을 분리 | `defendant_target_matrix.json` 생성·탐색 금지 |
| `U/client_goal.json#/parties/defendants/*/asset_status` | 피고별 현재 재산·집행 관련 사실을 보존 | `asset_status.json` 생성·탐색 금지 |
## 6. 조건부 relocation 계약
| 파일·ref | 성격 | brief 역할 | 사용 조건 |
|---|---|---|---|
| `stage2_release.json#/dependency_locks/stage1/contract_manifest_ref → <exact path>/stage1_contract_manifest.json` | `CONDITIONAL` | 승인된 logical input의 logical→physical path·schema·producer·raw hash mapping | 기본 exact path와 다른 배포에서만 release operator가 제공 |
이 파일은 Stage 1 제5 production task의 산출물이 아니며 기본 run input도 아니다. 새 logical artifact kind를 추가하거나 directory scan·basename fallback을 허용할 수 없다.
## 7. 별도 파일 경로가 아직 닫히지 않은 고정 계약
아래 항목은 SOW가 구현 전에 고정하도록 요구하지만 독립 physical file을 새로 만들라고 지시하지 않는다. 기존 named file의 row·`$defs`·runtime adapter로 귀속해야 하며, 별도 파일이 필요하면 먼저 SOW와 inventory를 개정한다.
| 계약 | 우선 귀속할 기존 파일 | brief 역할·미결사항 |
|---|---|---|
| `ALL` expansion·dual SG-01 projection rule | `ingress.schema.json`, `s2_00_ingress.py`, `stage2_release.json` | exact field set과 adapter version을 Phase S00-0에서 봉인 |
| P1~P4 review normalization mapping | `review_status.schema.json`, `s2_00_ingress.py` | source status→normalized status의 closed mapping과 `UNMAPPED` 처리 |
| BO/evidence/event producer adapter | `ingress.schema.json`, `s2_00_ingress.py` | accepted wrapper/shape와 schema gap을 versioned adapter로 고정 |
| domain config v1/v2 adapter | `ingress.schema.json`, `context.schema.json`, `s2_00_ingress.py` | undeclared slot과 config-version 처리 |
| Fact Ledger current-v8/legacy 경계 | `ingress.schema.json`, `s2_00_ingress.py` | current-v8 두 확장키는 필수; legacy는 별도 adapter가 있을 때만 지원 |
| `retry_policy_id` closed policy | S2_00 workflow row와 `stage2_release.json` | 허용 횟수·backoff·retryable code의 canonical owner/JSON Pointer 확정 필요 |
| approved producer-alias table | `module_manifest.json` 또는 `stage2_release.json` | schema writer const와 orchestration producer label의 signed closed mapping 필요 |
| canary/production signed admission | `stage2_release.json#/release_evidence[]` | release class·scope·signer·input digest를 봉인 |
| Code Executor secret injection·live receipt | `stage2_code_executor_binding.yml`, `deployment.schema.json`, `s2_00_inline_code_receipt.json` | plaintext 없이 AgentBackend가 `run_code`를 호출하고 outer/inner receipt를 검증하는 증거 필요 |
| executor timeout/request-size | `stage2_code_executor_binding.yml`, `regression_manifest.json` | representative S2_00가 300초와 request-size 상한 안에서 끝나는 live benchmark 필요 |
| external release trust anchor | `Stage_2_S2_00.yml` code constant, `stage2_code_executor_binding.yml`, outer receipt | hash-admitted Agent가 `expected_stage2_release_sha256`를 보유하고 backend가 Agent/code/release digest를 workspace 밖 trust root로 검증 |
| runtime/dependency pin | `stage2_code_executor_binding.yml`, `s2_00_inline_code_receipt.json` | `httpx==0.28.1`과 Python/runtime image digest를 결속; image pin 미지원 시 live gate 미통과 |
| localdocs logical publish | `ingress.schema.json`, `test_failure_and_atomic_publish.py` | status-last barrier, read-back hash, partial-write non-consumption을 봉인 |
| Stage 1 bounded snapshot stability | `stage2_release.json` dependency lock와 `ingress.schema.json` | 현행 allowlist 전체를 최대 2회 binary read하여 path별 raw-hash map equality를 검사; 신규 completion seal 요구 0 |
사건별 `stage2_control/s2_00_request.json`은 `schema_version`, `workflow_id=S2_00`, `request_id`, `attempt_id`, `stage1_run_root_ref`, `stage1_deployment_root_ref`를 전달하는 runtime input이다. 고정 배포 자산 수에 포함하지 않으며 inline code는 이 exact path 외 request 파일을 탐색하지 않는다. canonical output root는 request가 아니라 `run_binding_digest`에서 파생한다.
## 8. 설계·감사용 고정 provenance
아래 파일은 S2_00 계약의 근거를 확인하거나 구현을 감사할 때 사용한다. 배포 runtime이 import·실행·prompt/context로 소비하는 의존성은 아니다.
| 파일·위치 | brief 역할 | runtime 경계 |
|---|---|---|
| `M/S_00_SOW_v.1.md` | S2_00 범위·IO·inline execution·불변식·시험의 직접 작업명세 | build/audit only; runtime read 금지 |
| `M/stage_2_optimal_update_strategy_v.5.md` | Stage 2 전체 DAG와 Code Executor 실행경계 | design only |
| `M/stage_2_optimal_update_strategy_v.5_workflow.svg` | v5 direct-MCP·named-barrier workflow의 사람이 읽는 시각화 | documentation only |
| `M/assets_for_stage_2_v.4.md` | 전체 Stage 2 자산/source 계획과 소유권 위치 | planning/audit only |
| `P/YAML_Prompts/1. Stage_1/v.8/stage_1_part_1_v.8.yml` | Part 1 producer·logical path·handoff 계약 조사 근거 | runtime prompt/context로 사용 금지 |
| `P/YAML_Prompts/1. Stage_1/v.8/stage_1_part_2_v.8.yml` | Part 2 BO·signal producer 계약 조사 근거 | runtime prompt/context로 사용 금지 |
| `P/YAML_Prompts/1. Stage_1/v.8/stage_1_part_3_v.8.yml` | Part 3 LES producer·wrapper 계약 조사 근거 | runtime prompt/context로 사용 금지 |
| `P/YAML_Prompts/1. Stage_1/v.8/stage_1_part_4_v.8.yml` | Part 4 Fact Ledger·writer receipt 계약 조사 근거 | runtime prompt/context로 사용 금지 |
| `P/YAML_Prompts/1. Stage_1/v.7/extension_research/Default_Agent/signals/compiler/signal_compiler.py` | `ALL`, SG-01, payload path와 manifest 보존식의 구현 조사 근거 | 신규 Stage 2 runtime이 import·호출 금지 |
## 9. 고정 자산 목록에서 제외할 항목
| 제외 대상 | 이유 |
|---|---|
| `O/ingress/*.json`, `O/context/*.json`, `O/review/issue_ledger.base.json` | 사건별 S2_00 run output이며 고정 배포 파일이 아님 |
| `O/context/cluster_slices/<cluster_id>.json` | 사건별 cluster 수에 따라 생기는 동적 output family |
| Code Executor temporary hydration tree | task 내부 transient data이며 localdocs 고정 자산·published output이 아님 |
| `O/control/run_status.json` | S2_40이 단독 작성하는 사건별 상태 파일 |
| `R/prompts/P30_joint_drafting_contract.md` | S2_30 전용 prompt이며 S2_00 bundle 직접 의존이 아님 |
| `R/rules/relief/<case_type_id>.md`, raw corpus 전체 | S2_20/S2_30 후단 자산; S2_00이 직접 ingest하거나 bundle에 복제하는 것이 금지됨 |
| calculation·renderer·relief-rule 본문 | S2_00은 `stage2_release`를 통한 downstream availability만 확인 |
| §8의 Stage 1 v.8 Part 1~4 YAML 본문 | producer/path/shape 조사용 design provenance이며 사건 runtime context가 아님 |
| §8의 Stage 1 signal compiler source | `ALL`·SG-01 계약 감사용 provenance이며 신규 runtime이 import·실행하지 않음 |
| 구 Stage 2 v.0~v.3 YAML·prompt·loader·중간산출물 | runtime dependency와 fallback이 명시적으로 금지됨 |
## 10. 생성·결속 순서
1. §1 core schema와 fixture golden shape를 먼저 작성한다.
2. §4~§6의 Stage 1 exact producer/path/schema contract를 실측하고 §7의 미결 계약을 기존 named file에 귀속한다.
3. inline full code/localdocs adapter와 test 7축을 구현하고 authoring YAML의 code를 compile한다.
4. projection builder는 version-free Agent projection, full mirror, inline-code receipt만 생성한다. 그 결과 hash를 받은 release build owner가 executor binding과 module/release/regression manifest를 별도로 exact-hash 결속한다.
5. offline fixture를 통과한 후 backend secret·request-size·300초·binary byte equality를 live DEV smoke로 검증한다.
6. P00/P10·active profile·authority closure가 있는 signed canary에서만 executable bundle handoff를 시험한다.
7. S2_10 immutable-slice handoff와 S2_40 diagnostic 5-input handoff를 각각 검증한다.
이 순서가 끝나기 전에는 파일이 directory에 존재한다는 사실만으로 S2_00을 implementation-complete, executable 또는 production-ready라고 선언하지 않는다.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1040" viewBox="0 0 1440 1040" role="img" aria-labelledby="title desc">
<title id="title">Stage 2 v5 detailed workflow DAG</title>
<desc id="desc">Stage 1 current outputs and distributed integrity receipts are independently verified by S2_00, then flow through three inline Code Executor deterministic stages and two LLM stages. Each deterministic stage publishes only after its named status-last logical barrier.</desc>
<defs>
<marker id="arrow" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#334155"/>
</marker>
<style>
.title{font:700 28px -apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo",sans-serif;fill:#0f172a}
.sub{font:500 15px -apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo",sans-serif;fill:#475569}
.h{font:700 18px -apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo",sans-serif;fill:#0f172a}
.t{font:500 14px -apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo",sans-serif;fill:#1e293b}
.small{font:500 12px -apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo",sans-serif;fill:#475569}
.det{fill:#e0f2fe;stroke:#0284c7;stroke-width:2}
.llm{fill:#f3e8ff;stroke:#9333ea;stroke-width:2}
.io{fill:#f8fafc;stroke:#64748b;stroke-width:1.5}
.review{fill:#fff7ed;stroke:#ea580c;stroke-width:2}
.edge{fill:none;stroke:#334155;stroke-width:2;marker-end:url(#arrow)}
.dash{fill:none;stroke:#64748b;stroke-width:1.5;stroke-dasharray:7 6;marker-end:url(#arrow)}
</style>
</defs>
<text x="720" y="45" text-anchor="middle" class="title">Stage 2 v5 — Direct MCP Inline Code Executor DAG</text>
<text x="720" y="72" text-anchor="middle" class="sub">외부 loader/.py runtime dependency 0 · deterministic stage별 exactly-one run_code · final status/barrier last</text>
<rect x="470" y="95" width="500" height="78" rx="12" class="io"/>
<text x="720" y="125" text-anchor="middle" class="h">Stage 1 current outputs</text>
<text x="720" y="150" text-anchor="middle" class="t">16 direct inputs + signal family + release-bound deployment closure</text>
<path d="M720 173 L720 210" class="edge"/>
<rect x="330" y="210" width="780" height="135" rx="14" class="det"/>
<text x="720" y="239" text-anchor="middle" class="h">S2_00 — deterministic ingress (one code-executor.run_code)</text>
<text x="720" y="265" text-anchor="middle" class="t">localdocs binary two-pass stability → C00 source lock → C05 conservation</text>
<text x="720" y="289" text-anchor="middle" class="t">C10 context/identity → C15 claim-neutral cluster &amp; bundle plan</text>
<text x="720" y="317" text-anchor="middle" class="small">non-status writes → read-back hash verification → ingress_status.json last</text>
<path d="M720 345 L720 382" class="edge"/>
<rect x="330" y="382" width="780" height="105" rx="14" class="llm"/>
<text x="720" y="412" text-anchor="middle" class="h">S2_10 — LLM legal resolution map</text>
<text x="720" y="438" text-anchor="middle" class="t">immutable cluster slice + active legal profiles + authority excerpt</text>
<text x="720" y="462" text-anchor="middle" class="small">typed claim options and normalized signatures; case name alone never activates a claim</text>
<path d="M720 487 L720 524" class="edge"/>
<rect x="250" y="524" width="940" height="155" rx="14" class="det"/>
<text x="720" y="554" text-anchor="middle" class="h">S2_20 — deterministic reduce &amp; freeze (one code-executor.run_code)</text>
<text x="720" y="580" text-anchor="middle" class="t">option reduce · calculations · compatibility · recovery deduplication</text>
<text x="720" y="604" text-anchor="middle" class="t">case-type predicate → case_type_id → sub-rule predicate → sub_rule_id</text>
<text x="720" y="628" text-anchor="middle" class="t">release-bound read-only Weaviate retrieval → approved requirement-fact pack</text>
<text x="720" y="653" text-anchor="middle" class="small">freeze plan and context; plan/plan_publish_status.json last</text>
<path d="M720 679 L720 716" class="edge"/>
<rect x="330" y="716" width="780" height="105" rx="14" class="llm"/>
<text x="720" y="746" text-anchor="middle" class="h">S2_30 — LLM joint drafting</text>
<text x="720" y="772" text-anchor="middle" class="t">group-parallel relief/cause/worknote atoms from frozen plan and selected context</text>
<text x="720" y="796" text-anchor="middle" class="small">no new claim · no arithmetic · no commit</text>
<path d="M720 821 L720 858" class="edge"/>
<rect x="250" y="858" width="940" height="132" rx="14" class="det"/>
<text x="720" y="888" text-anchor="middle" class="h">S2_40 — deterministic review/render/commit (one code-executor.run_code)</text>
<text x="720" y="914" text-anchor="middle" class="t">part reduce → closed render → V01–V18 → review receipt/seal</text>
<text x="720" y="938" text-anchor="middle" class="t">content-addressed write → read-back → control/run_status.json last</text>
<text x="720" y="963" text-anchor="middle" class="small">final status single writer; partial writes are never consumable</text>
<rect x="35" y="228" width="245" height="100" rx="12" class="review"/>
<text x="157" y="258" text-anchor="middle" class="h">S2_00 impossible</text>
<text x="157" y="284" text-anchor="middle" class="t">technical diagnostic only</text>
<text x="157" y="307" text-anchor="middle" class="small">route to S2_40 status-only</text>
<path d="M330 278 L280 278" class="dash"/>
<path d="M157 328 L157 924 L250 924" class="dash"/>
<rect x="1215" y="550" width="190" height="100" rx="12" class="io"/>
<text x="1310" y="580" text-anchor="middle" class="h">Weaviate</text>
<text x="1310" y="606" text-anchor="middle" class="t">release-bound tenant</text>
<text x="1310" y="629" text-anchor="middle" class="small">read-only exact filter</text>
<path d="M1215 600 L1190 600" class="dash"/>
<text x="720" y="1021" text-anchor="middle" class="small">Offline compile/parity does not establish live secret binding, request-size/timeout admission, legal sign-off, or production readiness.</text>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

@@ -0,0 +1,142 @@
# Stage 2 v5 MCP Code Executor 전환
## Objective
Stage 2 v4의 5-workflow 법률·IO 구조를 보존하면서 deterministic task의 실행 방식을
외부 native `.py` adapter(O-06)에서 AgentBackend가 이미 지원하는 MCP Code Executor
inline Python으로 전환한다. `stage_2_optimal_update_strategy_v.5.md`,
`S_00_SOW_v.1.md`, `S2_00_assets_v.1.md`, `Stage_2_S2_00_v.1.yml`과 필요한
`Default_Agent/Stage_2_Clean/` 자산을 일관되게 생성·개정한다.
## Deliverables
- `YAML_Prompts/2. Stage_2/stage_2_optimal_update_strategy_v.5.md`
- `YAML_Prompts/2. Stage_2/S_00_SOW_v.1.md`
- `YAML_Prompts/2. Stage_2/S2_00_assets_v.1.md`
- `YAML_Prompts/2. Stage_2/Stage_2_S2_00_v.1.yml`
- 위 inventory가 지정하는 version-free `Default_Agent/Stage_2_Clean/` 개정·신규 자산
- `YAML_Prompts/2. Stage_2/MEMORY.md` 압축 기록
## Scope and Non-Scope
- 범위: S2_00 inline deterministic code, localdocs session/격리, release/hash contract,
schema·manifest·test·workflow 자산, S2_10/S2_40 handoff 계약.
- 비범위: S2_10 이후 LLM 법률판단의 실제 실행, 외부 Code Executor live 호출,
Stage 1 live case run, canary/production 서명·법률가 승인.
- 기존 v4/SOW/assets/YAML은 변경하지 않고 새 버전 파일을 만든다.
- 기존 Stage 2 v.0~v.3 runtime dependency는 계속 0으로 유지한다.
## Known Inputs
- `YAML_Prompts/2. Stage_2/stage_2_optimal_update_strategy_v.4.md`
- `YAML_Prompts/2. Stage_2/S_00_SOW.md`
- `YAML_Prompts/2. Stage_2/S2_00_assets.md`
- `YAML_Prompts/2. Stage_2/Stage_2_S2_00.yml`
- `YAML_Prompts/2. Stage_2/S2_00_yaml_구현_QA.txt`
- `YAML_Prompts/2. Stage_2/SKILL.md`
- `YAML_Prompts/2. Stage_2/test_code_executor.ipynb`
- `YAML_Prompts/1. Stage_1/v.8/stage_1_part_{1..4}_v.8.yml`
- `YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/`
## Material Assumptions
- 사용자의 이번 지시는 기존 SOW의 inline code-executor 기각 결정을 명시적으로
대체한다.
- AgentBackend가 문서화한 `mcp: code-executor`, `tool_name: run_code` task는
실행 가능한 승인 primitive로 취급한다.
- localdocs 접근은 `{{__user_hash__}}`와 `{{__workspace_hash__}}`를 포함한
`SKILL.md` 전체 boilerplate를 사용한다.
- 외부 live MCP 실행은 별도 네트워크·운영 권한과 실제 workspace 입력이 필요하므로
이번 완료 조건은 strict static validation과 local/mock regression이다.
## Questions That Could Change the Outcome
- inline source를 단일 task에 완전 삽입할지 C00/C05/C10/C15 여러 task로 나눌지는
Stage 1 실물 grammar, output 전달 한계와 atomic publish 계약을 대조한 뒤 확정한다.
- 기존 `stage2_loader.py`와 `runtime/s2_00_ingress.py`는 runtime dependency에서
제거하되, test oracle/migration source로 유지할지 manifest에서 완전히 제외할지
자산 delta 조사 후 결정한다.
## Workstreams and Dependencies
1. Stage 1 code-executor grammar와 현행 S2_00 계약·자산 delta 조사.
2. v5 → SOW_v1/assets_v1 순서의 문서 초안.
3. 서로 다른 evaluator 2개를 사용한 문서 평가→main 개정, 정확히 2회.
4. inventory 기반 자산 구현과 실행 YAML 구현을 병렬 진행.
5. 생성·개정 자산별 독립 검증 정확히 1회; YAML 독립 검증→개정 정확히 2회.
6. syntax/schema/mock/regression/hash/경로/금지 edge 검증과 MEMORY 기록.
## Source and Tool Plan
- 로컬 정본과 실제 Stage 1 YAML을 우선한다.
- `rg`, strict YAML/JSON parser, AST compile, existing unittest, mock localdocs harness를
사용한다.
- 파일 편집은 `apply_patch`만 사용한다.
- sub-agent는 독립 조사·평가·자산별 검증에만 사용하고 최종 설계 병합은 main이 한다.
## Validation Plan
- YAML duplicate-key parse와 AgentBackend grammar/task DAG 확인
- 모든 code-executor task의 `language/python`, full code, timeout, network,
user/workspace binding, stdout single-JSON 확인
- inline Python 추출 후 AST compile 및 금지 import/call 검사
- localdocs mock을 통한 read/write/overwrite/path/NFC/SSE/Extra-data 처리 검사
- S2_00 16+1 ingress, C00→C05→C10→C15, normal 12/diagnostic 5,
route mutual exclusion, S2_40 single-writer 보존
- manifest/schema/hash closure와 구 v.0~v.3 dependency 0 확인
- 기존 `tests/s2_00` 및 신규 inline adapter regression 실행
## Approval Boundaries
- 요청된 로컬 문서·YAML·Default_Agent 자산만 변경한다.
- commit/push, 외부 MCP 호출, production admission·서명은 수행하지 않는다.
- dirty worktree의 무관 변경은 건드리지 않는다.
## Progress
- [x] MEMORY·AGENTS·PLANS·SKILL·notebook 확인
- [ ] Stage 1 grammar와 현행 asset delta 조사
- [ ] v5/SOW_v1/assets_v1 초안
- [ ] 문서 평가·개정 Round 1
- [ ] 문서 평가·개정 Round 2
- [ ] Default_Agent 자산 구현
- [ ] Stage_2_S2_00_v.1 YAML 구현
- [ ] 자산 1회·YAML 2회 검증
- [ ] 최종 회귀검사·MEMORY
## Decision Log
- 2026-08-30: v5 execution TCB is `AgentBackend -> code-executor.run_code -> static inline Python -> user/workspace-bound localdocs`; O-06 native loader is superseded.
- 2026-08-30: One Code Executor task owns C00→C05→C10→C15. Splitting is deferred because intermediate artifacts would enlarge transport and weaken one-receipt semantics.
- 2026-08-30: The current filesystem core is retained as a test/parity oracle only. Runtime execution must not read/import `runtime/s2_00_ingress.py` or call `stage2_loader.py`.
- 2026-08-30: localdocs lacks a documented atomic directory rename contract. v1 uses byte write/read-back plus `ingress_status.json` last as a logical commit barrier.
- 2026-08-30: New YAML must not duplicate the plaintext bearer credential found in historical Stage 1/notebook sources. Live status remains pending backend secret binding.
- 2026-08-30: Timeout target is 300 seconds, subject to live representative benchmark and request-size admission.
| Date/Stage | Decision | Basis | Consequence |
|---|---|---|---|
| 2026-08-30 / 착수 | O-06 native adapter 방식을 MCP Code Executor inline task로 대체 | 사용자 명시적 목표와 `SKILL.md`의 지원 grammar | v5가 이전 SOW의 inline-code 기각을 명시적으로 supersede해야 함 |
| 2026-08-30 / 착수 | 외부 live 실행과 production-ready 주장은 완료 범위에서 제외 | 실제 user workspace와 운영 Code Executor admission 증거 부재 | static/mock 검증과 live E2E 경계를 문서마다 명시 |
## Evidence Ledger
| Claim/Issue | Source or Test | Status | Notes |
|---|---|---|---|
| AgentBackend inline task grammar | `SKILL.md` §3.3 | 확인 | `mcp: code-executor`, `tool_name: run_code`, `parameters.code` |
| workspace 격리 | `SKILL.md` §5·§5.2 | 확인 | hash template 포함 full localdocs init 필요 |
| prior inline rejection | `S_00_SOW.md` §14 | superseded 예정 | 사용자 지시로 v1에서 대체 |
| current YAML non-executable | `Stage_2_S2_00.yml` | 확인 | `tasks: []`, O-06 OPEN |
| fixed runtime 규모 | `runtime/s2_00_ingress.py` | 확인 | 5,134행; inline 구조 최적화 필요 |
## Risks and Failure Modes
- YAML source와 기존 `.py`가 이중 정본이 되는 drift
- code-executor가 local filesystem을 공유한다고 잘못 가정하는 오류
- localdocs text transport가 raw-byte digest 의미를 바꾸는 오류
- YAML parser/template renderer가 Python braces를 오인하는 오류
- 인라인 코드가 너무 커져 AgentBackend payload·timeout 한도를 넘는 위험
- mock PASS를 live Code Executor E2E로 과장하는 위험
## Results and Residual Uncertainty
작업 완료 시 파일 수·hash·검증 결과와 live 경계를 기록한다.