diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml index 13248d63..b8c468d2 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml @@ -192,7 +192,7 @@ Agent: # literal placeholders in the offline parity mirror and its unit tests. INLINE_USER_HASH = "{{__user_hash__}}" INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}" - EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" + EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" INLINE_REQUEST_PATH = "stage2_control/s2_00_request.json" INLINE_STAGE2_ASSET_ROOT = "Default_Agent/Stage_2_Clean" INLINE_STAGE2_RELEASE_PATH = ( diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml index 2b14d329..eb547a7e 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml @@ -71,7 +71,7 @@ Agent: WORKFLOW_ID = "S2_20" ALGORITHM_VERSION = "s2_20_relief_plan/1.0.0" - EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" + EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" WEAVIATE_MCP_URL = "https://weaviate.eroomai.com/mcp" MCP_PROTOCOL_VERSION = "2025-03-26" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_30.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_30.yml index 1c34ce9a..55c36d46 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_30.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_30.yml @@ -73,7 +73,7 @@ Agent: from typing import Any, Mapping - EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" + EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" MCP_PROTOCOL_VERSION = "2025-03-26" INLINE_USER_HASH = "{{__user_hash__}}" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml new file mode 100644 index 00000000..57d65722 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml @@ -0,0 +1,3575 @@ +Agent: + name: Stage_2_S2_40 + version: "1.0.0" + description: >- + S2_20 frozen plan과 S2_30 immutable group parts를 exact manifest로 reduce하고, + closed renderer 재전개, V01~V18, review state, content-addressed seal과 + barrier-last logical commit을 수행하는 S2_40 NON-LLM-DETERMINISTIC Agent. + metadata: + workflow_id: S2_40 + execution_class: NON-LLM-DETERMINISTIC + execution_authority: MCP_CODE_EXECUTOR_INLINE + task_constitution: S2_40_EXACTLY_ONE_INLINE_RUN_CODE_V1 + implementation_status: IMPLEMENTED_OFFLINE_VERIFIED_LIVE_AND_LEGAL_ADMISSION_PENDING + legacy_stage2_v0_v3_runtime_dependency_count: 0 + Stages: + - name: S2_40 + description: >- + 단일 Code Executor 호출 내부에서 C40 -> C45 -> C46 -> C47 -> C48을 + 실행한다. S2_00 exact-five status-only route도 같은 task의 닫힌 branch다. + prevs: [] + nexts: [] + skip_confirm: true + tools: + mcpServers: + localdocs: + type: streamable-http + url: http://mcp-localdocs:8012/mcp + code-executor: + type: streamable-http + url: https://code-executor.mcp.eroomai.com/mcp + tasks: + - task_name: Task_S2_40_deterministic_finalizer + description: >- + release-bound request와 barrier가 열거한 immutable input만 읽어 + candidate/review/package를 봉인하고 run_status를 마지막에 발행한다. + mcp: code-executor + tool_name: run_code + parameters: + language: python + requirements: "httpx==0.28.1" + network: agent-network + timeout: 300 + code: |- + #!/usr/bin/env python3 + """Release-bound deterministic S2_40 finalizer. + + This module is self-contained. It never imports workspace Python, calls + an LLM, scans directories, invokes a shell, or invents legal content. + All runtime reads and writes use the localdocs MCP binary contract. + """ + + from __future__ import annotations + + import base64 + import binascii + import contextlib + from datetime import datetime, timezone + import hashlib + import io + import itertools + import json + import re + import sys + import unicodedata + from pathlib import PurePosixPath + from typing import Any, Iterable, Mapping, Sequence + + + WORKFLOW_ID = "S2_40" + ALGORITHM_VERSION = "s2_40_finalizer/1.0.0" + EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" + LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" + MCP_PROTOCOL_VERSION = "2025-03-26" + INLINE_USER_HASH = "{{__user_hash__}}" + INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}" + REQUEST_PATH = "stage2_control/s2_40_request.json" + ASSET_ROOT = "Default_Agent/Stage_2_Clean" + AGENT_PATH = f"{ASSET_ROOT}/agent_scripts/Stage_2_S2_40.yml" + BINDING_PATH = f"{ASSET_ROOT}/deployment/stage2_code_executor_binding.yml" + INLINE_RECEIPT_PATH = f"{ASSET_ROOT}/manifest/s2_40_inline_code_receipt.json" + PARENT_RELEASE_PATH = f"{ASSET_ROOT}/manifest/stage2_release.json" + MODULE_MANIFEST_PATH = f"{ASSET_ROOT}/manifest/module_manifest.json" + AUTHORITY_RELEASE_REL = "manifest/authority_release.json" + CASE_TYPE_COVERAGE_REL = "manifest/case_type_coverage.json" + CASE_TYPE_REGISTRY_REL = "manifest/case_type_registry.yml" + CASE_TYPE_RULE_REGISTRY_REL = "manifest/case_type_rule_registry.yml" + INPUT_SCHEMA_RELS = ( + "schemas/ingress.schema.json", + "schemas/context.schema.json", + "schemas/domain_verdict.schema.json", + "schemas/s2_10.schema.json", + "schemas/relief_plan.schema.json", + "schemas/binding_retrieval.schema.json", + "schemas/calculation.schema.json", + "schemas/draft_atoms.schema.json", + "schemas/package.schema.json", + "schemas/review_status.schema.json", + "schemas/deployment.schema.json", + ) + MAX_FILE_BYTES = 32 * 1024 * 1024 + MAX_TOTAL_BYTES = 256 * 1024 * 1024 + MAX_ARTIFACT_ROWS = 20000 + HEX64 = re.compile(r"^[a-f0-9]{64}$") + IDENT = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$") + PLACEHOLDER = re.compile(r"\{\{([A-Za-z][A-Za-z0-9_]*)\}\}") + ENTRY_ROUTES = {"TO_S2_40", "TO_S2_40_STATUS_ONLY"} + COMPILE_MODES = {"STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"} + TRANSITIONS = {"FREEZE", "RESUME"} + V_IDS = tuple(f"V{i:02d}" for i in range(1, 19)) + PART_FAMILIES = ("DRAFT_PART", "ISSUE_PATCH", "USAGE_PART", "WORKNOTE_PART") + PART_DIRECTORIES = { + "DRAFT_PART": "draft_parts", + "ISSUE_PATCH": "issue_patches", + "USAGE_PART": "usage_parts", + "WORKNOTE_PART": "worknote_parts", + } + PART_SCHEMA_REFS = { + "DRAFT_PART": "schemas/draft_atoms.schema.json#/$defs/draft_part", + "ISSUE_PATCH": "schemas/draft_atoms.schema.json#/$defs/issue_patch_part", + "USAGE_PART": "schemas/draft_atoms.schema.json#/$defs/usage_part", + "WORKNOTE_PART": "schemas/draft_atoms.schema.json#/$defs/worknote_part", + } + COMMON_PROVENANCE_FIELDS = { + "compile_mode", "parent_stage2_release_sha256", "s2_30_release_sha256", + "s2_30_agent_sha256", "s2_30_binding_sha256", "p00_prompt_sha256", + "p30_prompt_sha256", "s2_30_producer_contract_digest", + } + GROUP_PROVENANCE_FIELDS = COMMON_PROVENANCE_FIELDS | { + "p31_rule_and_pack_sha256", "p32_common_authority_sha256", + "s30_group_slice_sha256", + } + TRUSTED_REVIEW_ISSUER = "AGENTBACKEND_STAGE2_REVIEW_AUTHORITY" + TRUSTED_REVIEW_KEY_IDS = {"AGENTBACKEND_STAGE2_REVIEW_KEY_V1"} + TRUSTED_REVIEW_SIGNATURE_ALGORITHM = "AGENTBACKEND_TRUSTED_ATTESTATION_V1" + TRUSTED_REVIEW_ROLE = "KOREAN_LAWYER" + TRUSTED_REVIEW_QUALIFICATION = "QUALIFIED_KOREAN_LAWYER" + REQUIRED_LEGAL_GATES = { + "binding", "authority", "renderer_branch", "rule_sub_rule", + "review_policy", "case_type_coverage_137", "corpus", "law_value", + "calculator", "required_receipts", + } + + + class S240Error(Exception): + def __init__(self, code: str, message: str, *, details: Any | None = None) -> None: + super().__init__(message) + self.code = code + self.message = message + self.details = details + + def as_dict(self) -> dict[str, Any]: + row: dict[str, Any] = {"code": self.code, "message": self.message} + if self.details is not None: + row["details"] = self.details + return row + + + def nfc(value: str) -> str: + return unicodedata.normalize("NFC", value) + + + def no_duplicates(pairs: list[tuple[str, Any]]) -> dict[str, Any]: + result: dict[str, Any] = {} + for key, value in pairs: + if key in result: + raise S240Error("DUPLICATE_JSON_KEY", f"duplicate JSON key: {key}") + result[key] = value + return result + + + def load_json(raw: bytes, *, label: str) -> Any: + if len(raw) > MAX_FILE_BYTES: + raise S240Error("SOURCE_SIZE_LIMIT", f"file exceeds limit: {label}") + try: + text = raw.decode("utf-8", errors="strict") + return json.loads( + text, + object_pairs_hook=no_duplicates, + parse_constant=lambda token: (_ for _ in ()).throw( + S240Error("NON_FINITE_NUMBER", f"non-finite number: {token}") + ), + ) + except (UnicodeDecodeError, json.JSONDecodeError) as exc: + raise S240Error("JSON_PARSE_ERROR", f"strict JSON parse failed: {label}") from exc + + + def canonical_bytes(value: Any) -> bytes: + return ( + json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False) + + "\n" + ).encode("utf-8") + + + def canonical_markdown(value: str) -> bytes: + if not isinstance(value, str): + raise S240Error("MARKDOWN_TYPE", "markdown must be a string") + text = nfc(value.replace("\r\n", "\n").replace("\r", "\n")).lstrip("\ufeff") + if "\x00" in text: + raise S240Error("MARKDOWN_NUL", "markdown contains NUL") + return (text.rstrip("\n") + "\n").encode("utf-8") + + + def digest(value: Any) -> str: + payload = value if isinstance(value, bytes) else canonical_bytes(value) + return hashlib.sha256(payload).hexdigest() + + + def require_hex(value: Any, *, code: str) -> str: + if not isinstance(value, str) or HEX64.fullmatch(value) is None: + raise S240Error(code, "expected lower-case SHA-256") + return value + + + def require_ident(value: Any, *, code: str) -> str: + if not isinstance(value, str) or IDENT.fullmatch(value) is None: + raise S240Error(code, "invalid identifier") + return value + + + def require_text(value: Any, *, code: str) -> str: + if not isinstance(value, str) or not value.strip(): + raise S240Error(code, "non-empty text required") + return nfc(value) + + + def safe_path(value: Any, *, code: str = "PATH_INVALID") -> str: + if not isinstance(value, str) or not value or "\x00" in value: + raise S240Error(code, "path must be a non-empty string") + if value.startswith("/") or "\\" in value: + raise S240Error(code, "absolute or backslash path is forbidden") + normalized = PurePosixPath(value) + if any(part in {"", ".", ".."} for part in normalized.parts): + raise S240Error(code, "path traversal or ambiguous component") + return normalized.as_posix() + + + def join_path(*parts: str) -> str: + return safe_path("/".join(part.strip("/") for part in parts if part)) + + + def stable_id(prefix: str, *parts: Any) -> str: + return f"{prefix}-{digest([nfc(str(part)) for part in parts])[:24]}" + + + def utc_now() -> str: + return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") + + + def require_object(value: Any, *, code: str) -> dict[str, Any]: + if not isinstance(value, dict): + raise S240Error(code, "object required") + return value + + + def require_list(value: Any, *, code: str) -> list[Any]: + if not isinstance(value, list): + raise S240Error(code, "array required") + return value + + + def _parse_mcp_payload(raw: bytes, expected_id: int) -> Mapping[str, Any]: + candidates: list[Any] + if raw.lstrip().startswith(b"{"): + try: + candidates = [load_json(raw, label="mcp-json")] + except S240Error as exc: + if exc.code != "JSON_PARSE_ERROR": + raise + try: + text = raw.decode("utf-8", errors="strict") + decoder = json.JSONDecoder(object_pairs_hook=no_duplicates) + first, offset = decoder.raw_decode(text.lstrip()) + tail = text.lstrip()[offset:].strip() + candidates = [first] + while tail: + extra, offset = decoder.raw_decode(tail) + candidates.append(extra) + tail = tail[offset:].strip() + except (UnicodeDecodeError, json.JSONDecodeError) as parse_exc: + raise S240Error("MCP_JSON_EXTRA_DATA", "invalid concatenated MCP JSON") from parse_exc + else: + try: + text = raw.decode("utf-8", errors="strict") + except UnicodeDecodeError as exc: + raise S240Error("MCP_SSE_UTF8", "invalid MCP SSE UTF-8") from exc + events: list[bytes] = [] + data_lines: list[str] = [] + for line in text.replace("\r\n", "\n").split("\n"): + if not line: + if data_lines: + events.append("\n".join(data_lines).encode("utf-8")) + data_lines = [] + continue + if line.startswith((":", "event:", "id:", "retry:")): + continue + if not line.startswith("data:"): + raise S240Error("MCP_SSE_SHAPE", "unexpected SSE line") + data_lines.append(line[5:].lstrip()) + if data_lines: + events.append("\n".join(data_lines).encode("utf-8")) + candidates = [load_json(event, label="mcp-sse-event") for event in events] + matches = [row for row in candidates if isinstance(row, dict) and row.get("id") == expected_id] + if len(matches) != 1: + raise S240Error("MCP_RESPONSE_ID", "exactly one matching JSON-RPC result required") + row = matches[0] + if row.get("jsonrpc") != "2.0" or row.get("error") is not None: + raise S240Error("MCP_JSONRPC_ERROR", "MCP returned an invalid/error response") + if not isinstance(row.get("result"), dict): + raise S240Error("MCP_RESULT_SHAPE", "MCP result must be an object") + return row + + + def _tool_text(result: Mapping[str, Any], tool: str) -> str: + if result.get("isError") is True: + rendered = str(result.get("content", "")) + code = "LOCALDOCS_NOT_FOUND" if "not found" in rendered.lower() else "MCP_TOOL_ERROR" + raise S240Error(code, f"{tool} returned isError=true") + content = result.get("content") + if not isinstance(content, list) or len(content) != 1: + raise S240Error("MCP_CONTENT_CARDINALITY", "one content block required") + block = content[0] + if not isinstance(block, dict) or block.get("type") != "text" or not isinstance(block.get("text"), str): + raise S240Error("MCP_CONTENT_SHAPE", "one text block required") + return block["text"] + + + def _binary_from_text(text: str, path: str) -> bytes: + value = load_json(text.encode("utf-8"), label=path) + if isinstance(value, dict) and isinstance(value.get("results"), list): + rows = value["results"] + if len(rows) != 1 or not isinstance(rows[0], dict): + raise S240Error("LOCALDOCS_RESULT_CARDINALITY", "one binary result required") + value = rows[0].get("content", rows[0].get("text")) + if isinstance(value, str): + value = load_json(value.encode("utf-8"), label=path) + if not isinstance(value, dict) or not isinstance(value.get("content_base64"), str): + raise S240Error("LOCALDOCS_BINARY_ENVELOPE", "content_base64 is required") + try: + raw = base64.b64decode(value["content_base64"].encode("ascii"), validate=True) + except (UnicodeEncodeError, binascii.Error, ValueError) as exc: + raise S240Error("LOCALDOCS_BASE64", "strict base64 required") from exc + if value.get("byte_length", value.get("size", len(raw))) != len(raw): + raise S240Error("LOCALDOCS_LENGTH", f"byte length mismatch: {path}") + if value.get("sha256", digest(raw)) != digest(raw): + raise S240Error("LOCALDOCS_HASH", f"raw hash mismatch: {path}") + return raw + + + class McpClient: + def __init__(self, endpoint: str, name: str) -> None: + try: + import httpx # type: ignore + except ImportError as exc: + raise S240Error("HTTPX_UNAVAILABLE", "httpx==0.28.1 is required") from exc + self.endpoint = endpoint + self.name = name + self.client = httpx.Client(timeout=60) + self.headers = {"Content-Type": "application/json", "Accept": "application/json, text/event-stream"} + self.ids = itertools.count(10) + self.initialized = False + + def close(self) -> None: + self.client.close() + + def _post(self, body: Mapping[str, Any], expected_id: int | None) -> Mapping[str, Any] | None: + try: + response = self.client.post(self.endpoint, json=dict(body), headers=dict(self.headers)) + response.raise_for_status() + except Exception as exc: + raise S240Error("MCP_TRANSPORT", f"{self.name} transport failed") from exc + session = response.headers.get("mcp-session-id") + if session: + self.headers["mcp-session-id"] = session + if expected_id is None: + return None + return _parse_mcp_payload(bytes(response.content), expected_id) + + def initialize(self) -> None: + row = self._post( + { + "jsonrpc": "2.0", "id": 1, "method": "initialize", + "params": { + "protocolVersion": MCP_PROTOCOL_VERSION, + "capabilities": {}, + "clientInfo": { + "name": "liti-s2-40-inline", "version": "1.0.0", + "user_id": INLINE_USER_HASH, "workspace_id": INLINE_WORKSPACE_HASH, + }, + }, + }, + 1, + ) + if row is None or row["result"].get("protocolVersion") != MCP_PROTOCOL_VERSION: + raise S240Error("MCP_PROTOCOL", "MCP protocol negotiation failed") + self._post({"jsonrpc": "2.0", "method": "notifications/initialized"}, None) + self.initialized = True + + def call(self, tool: str, arguments: Mapping[str, Any]) -> Mapping[str, Any]: + if not self.initialized: + raise S240Error("MCP_NOT_INITIALIZED", "initialize before tools/call") + message_id = next(self.ids) + row = self._post( + {"jsonrpc": "2.0", "id": message_id, "method": "tools/call", "params": {"name": tool, "arguments": dict(arguments)}}, + message_id, + ) + if row is None: + raise S240Error("MCP_EMPTY", f"empty response: {tool}") + return row["result"] + + def read_binary(self, path: str) -> bytes: + safe = safe_path(path) + return _binary_from_text(_tool_text(self.call("read_binary_doc", {"doc_name": safe}), "read_binary_doc"), safe) + + def read_optional(self, path: str) -> bytes | None: + try: + return self.read_binary(path) + except S240Error as exc: + if exc.code == "LOCALDOCS_NOT_FOUND": + return None + raise + + def write_immutable(self, path: str, payload: bytes) -> str: + safe = safe_path(path) + existing = self.read_optional(safe) + if existing is not None: + if existing != payload: + raise S240Error("IMMUTABLE_CONFLICT", f"existing bytes differ: {safe}") + return digest(existing) + encoded = base64.b64encode(payload).decode("ascii") + _tool_text( + self.call("write_binary_file", {"path": safe, "content_base64": encoded, "overwrite": False}), + "write_binary_file", + ) + observed = self.read_binary(safe) + if observed != payload: + raise S240Error("WRITE_READBACK_MISMATCH", f"read-back differs: {safe}") + return digest(observed) + + def write_latest(self, path: str, payload: bytes, expected_previous: str | None) -> str: + safe = safe_path(path) + existing = self.read_optional(safe) + if expected_previous is None: + if existing is not None and existing != payload: + raise S240Error("LATEST_BARRIER_CONFLICT", "unexpected previous latest barrier") + else: + if existing is None or digest(existing) != expected_previous: + raise S240Error("LATEST_BARRIER_CAS", "previous latest barrier hash mismatch") + if existing == payload: + return digest(existing) + encoded = base64.b64encode(payload).decode("ascii") + _tool_text( + self.call("write_binary_file", {"path": safe, "content_base64": encoded, "overwrite": existing is not None}), + "write_binary_file", + ) + observed = self.read_binary(safe) + if observed != payload: + raise S240Error("LATEST_READBACK_MISMATCH", "latest barrier read-back mismatch") + return digest(observed) + + + REQUEST_KEYS = { + "schema_version", "request_id", "candidate_attempt_id", "run_binding_digest", + "user_identity_hash", "workspace_identity_hash", "stage2_run_root_ref", + "entry_route", "compile_mode", "requested_transition", + "expected_previous_run_status_sha256", "expected_candidate_content_digest", + "expected_ingress_status_sha256", "expected_s2_10_publish_status_sha256", + "expected_plan_publish_status_sha256", "expected_s2_30_publish_status_sha256", + "expected_s2_30_artifact_manifest_sha256", "expected_parent_stage2_release_sha256", + "expected_s2_40_agent_sha256", "expected_s2_40_executor_binding_sha256", + "expected_s2_40_inline_code_receipt_sha256", "host_cas_receipt_ref", + "host_cas_receipt_sha256", "detached_admission_receipt_ref", + "detached_admission_receipt_sha256", "outer_execution_receipt_target_ref", + "review_receipt_refs", + } + + + def validate_request(raw: bytes) -> dict[str, Any]: + value = load_json(raw, label=REQUEST_PATH) + if not isinstance(value, dict) or set(value) != REQUEST_KEYS: + keys = set(value) if isinstance(value, dict) else set() + raise S240Error("REQUEST_CLOSED_SHAPE", "request keys differ", details={"missing": sorted(REQUEST_KEYS - keys), "extra": sorted(keys - REQUEST_KEYS)}) + if value["schema_version"] != "stage2_s2_40_request.v1": + raise S240Error("REQUEST_VERSION", "unsupported request schema") + for key in ("request_id", "candidate_attempt_id"): + require_ident(value[key], code="REQUEST_IDENTIFIER") + run_digest = require_hex(value["run_binding_digest"], code="RUN_BINDING_DIGEST") + for key in ( + "user_identity_hash", "workspace_identity_hash", "expected_ingress_status_sha256", + "expected_parent_stage2_release_sha256", "expected_s2_40_agent_sha256", + "expected_s2_40_executor_binding_sha256", "expected_s2_40_inline_code_receipt_sha256", + "host_cas_receipt_sha256", "detached_admission_receipt_sha256", + ): + require_hex(value[key], code=f"REQUEST_{key.upper()}") + for key in ( + "expected_previous_run_status_sha256", "expected_candidate_content_digest", + "expected_s2_10_publish_status_sha256", "expected_plan_publish_status_sha256", + "expected_s2_30_publish_status_sha256", "expected_s2_30_artifact_manifest_sha256", + ): + if value[key] is not None: + require_hex(value[key], code=f"REQUEST_{key.upper()}") + if value["user_identity_hash"] != INLINE_USER_HASH or value["workspace_identity_hash"] != INLINE_WORKSPACE_HASH: + raise S240Error("REQUEST_IDENTITY", "request identity differs from AgentBackend substitution") + expected_root = f"stage2_runs/by-binding/{run_digest}" + if value["stage2_run_root_ref"] != expected_root: + raise S240Error("REQUEST_RUN_ROOT", "run root must derive from binding digest") + if value["entry_route"] not in ENTRY_ROUTES or value["requested_transition"] not in TRANSITIONS: + raise S240Error("REQUEST_ENUM", "unsupported entry route or transition") + receipt_refs = require_list(value["review_receipt_refs"], code="REQUEST_REVIEW_REFS") + if len(receipt_refs) > 64 or len(set(receipt_refs)) != len(receipt_refs): + raise S240Error("REQUEST_REVIEW_REFS", "review receipt refs must be unique and bounded") + for ref in receipt_refs: + safe_path(ref, code="REQUEST_REVIEW_REF_PATH") + expected_cas = f"stage2_control/host_cas/{run_digest}/S2_40/{value['candidate_attempt_id']}/{value['requested_transition']}.json" + if value["host_cas_receipt_ref"] != expected_cas: + raise S240Error("REQUEST_CAS_PATH", "host CAS path mismatch") + if value["outer_execution_receipt_target_ref"] != f"{expected_root}/control/s2_40_outer_execution_receipt.json": + raise S240Error("REQUEST_OUTER_RECEIPT_PATH", "outer receipt target mismatch") + status_only = value["entry_route"] == "TO_S2_40_STATUS_ONLY" + upstream_keys = ( + "expected_s2_10_publish_status_sha256", "expected_plan_publish_status_sha256", + "expected_s2_30_publish_status_sha256", "expected_s2_30_artifact_manifest_sha256", + ) + if status_only: + if value["compile_mode"] is not None or value["requested_transition"] != "FREEZE": + raise S240Error("REQUEST_STATUS_ONLY_MODE", "status-only requires null mode and FREEZE") + if any(value[key] is not None for key in upstream_keys) or value["expected_candidate_content_digest"] is not None or receipt_refs: + raise S240Error("REQUEST_STATUS_ONLY_SCOPE", "status-only forbids normal input and review refs") + else: + if value["compile_mode"] not in COMPILE_MODES or any(value[key] is None for key in upstream_keys): + raise S240Error("REQUEST_NORMAL_SCOPE", "normal route requires mode and all upstream hashes") + if value["requested_transition"] == "FREEZE": + if value["expected_candidate_content_digest"] is not None: + raise S240Error("REQUEST_FREEZE_DIGEST", "FREEZE must not supply candidate digest") + if value["expected_previous_run_status_sha256"] is not None or receipt_refs: + raise S240Error("REQUEST_FREEZE_SCOPE", "FREEZE forbids previous status and review receipts") + if value["requested_transition"] == "RESUME": + if value["expected_candidate_content_digest"] is None or value["expected_previous_run_status_sha256"] is None: + raise S240Error("REQUEST_RESUME_SCOPE", "RESUME requires candidate and previous status digests") + return value + + + def read_bound_json(client: McpClient, path: str, expected_sha256: str | None = None) -> tuple[dict[str, Any], bytes]: + raw_a = client.read_binary(path) + if expected_sha256 is not None and digest(raw_a) != expected_sha256: + raise S240Error("BOUND_HASH_MISMATCH", f"raw hash mismatch: {path}") + value = require_object(load_json(raw_a, label=path), code="BOUND_OBJECT") + raw_b = client.read_binary(path) + if raw_b != raw_a: + raise S240Error("TOCTOU_INPUT_CHANGED", f"input changed between reads: {path}") + return value, raw_a + + + def read_release_bound_jsons( + client: McpClient, relative_paths: Sequence[str], + ) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], list[dict[str, Any]]]: + """Read exact module-manifest members; directory discovery is never used.""" + parent_raw = client.read_binary(PARENT_RELEASE_PATH) + if digest(parent_raw) != EXPECTED_STAGE2_RELEASE_SHA256: + raise S240Error("BOUND_PARENT_DRIFT", "parent release differs from inline constant") + parent = require_object(load_json(parent_raw, label=PARENT_RELEASE_PATH), code="BOUND_PARENT_OBJECT") + require_self_hash(parent, "release_digest", code="BOUND_PARENT_SELF_HASH") + module_ref = require_object(parent.get("module_manifest_ref"), code="BOUND_MODULE_REF") + module_raw = client.read_binary(MODULE_MANIFEST_PATH) + if digest(module_raw) != require_hex(module_ref.get("sha256"), code="BOUND_MODULE_HASH"): + raise S240Error("BOUND_MODULE_HASH", "module manifest differs from parent binding") + module = require_object(load_json(module_raw, label=MODULE_MANIFEST_PATH), code="BOUND_MODULE_OBJECT") + require_self_hash(module, "manifest_digest", code="BOUND_MODULE_SELF_HASH") + rows = require_list(module.get("modules"), code="BOUND_MODULE_ROWS") + values: dict[str, dict[str, Any]] = {} + raws: dict[str, bytes] = {} + source_rows: list[dict[str, Any]] = [] + for relative in relative_paths: + relative = safe_path(relative, code="BOUND_MEMBER_PATH") + matches = [row for row in rows if isinstance(row, dict) and row.get("path") == relative] + if len(matches) != 1: + raise S240Error("BOUND_MEMBER_CARDINALITY", f"release member must be exact-one: {relative}") + member = matches[0] + expected = require_hex(member.get("sha256"), code="BOUND_MEMBER_HASH") + raw = client.read_binary(join_path(ASSET_ROOT, relative)) + if digest(raw) != expected or member.get("size_bytes") != len(raw): + raise S240Error("BOUND_MEMBER_DRIFT", f"release member bytes differ: {relative}") + value = require_object(load_json(raw, label=relative), code="BOUND_MEMBER_OBJECT") + values[relative] = value + raws[relative] = raw + source_rows.append({"path": relative, "sha256": expected, "size_bytes": len(raw)}) + return values, raws, sorted(source_rows, key=lambda row: row["path"]) + + + def json_pointer(document: Any, fragment: str) -> Any: + if fragment in {"", "#"}: + return document + pointer = fragment[1:] if fragment.startswith("#") else fragment + if not pointer.startswith("/"): + raise S240Error("SCHEMA_POINTER", f"unsupported JSON pointer: {fragment}") + current = document + for token in pointer[1:].split("/"): + token = token.replace("~1", "/").replace("~0", "~") + if isinstance(current, dict) and token in current: + current = current[token] + elif isinstance(current, list) and token.isdigit() and int(token) < len(current): + current = current[int(token)] + else: + raise S240Error("SCHEMA_POINTER", f"unresolvable JSON pointer: {fragment}") + return current + + + def resolve_schema_ref( + ref: str, current_path: str, store: Mapping[str, Mapping[str, Any]], + ) -> tuple[Mapping[str, Any], str]: + if "#" in ref: + file_ref, fragment = ref.split("#", 1) + fragment = "#" + fragment + else: + file_ref, fragment = ref, "#" + if file_ref: + if file_ref.startswith("schemas/"): + target_path = safe_path(file_ref, code="SCHEMA_REF_PATH") + else: + target_path = safe_path( + str(PurePosixPath(current_path).parent / file_ref), code="SCHEMA_REF_PATH", + ) + else: + target_path = current_path + target_document = store.get(target_path) + if not isinstance(target_document, dict): + raise S240Error("SCHEMA_REF_UNBOUND", f"schema is not release-bound: {target_path}") + target = json_pointer(target_document, fragment) + return require_object(target, code="SCHEMA_REF_TARGET"), target_path + + + def schema_errors( + value: Any, + schema: Mapping[str, Any], + current_path: str, + store: Mapping[str, Mapping[str, Any]], + *, + location: str = "$", + depth: int = 0, + ) -> list[str]: + """Deterministic JSON-Schema subset covering every keyword used by Stage 2 input roots.""" + if depth > 160: + return [f"{location}:schema recursion limit"] + if "$ref" in schema: + target, target_path = resolve_schema_ref(str(schema["$ref"]), current_path, store) + return schema_errors(value, target, target_path, store, location=location, depth=depth + 1) + errors: list[str] = [] + if "const" in schema and value != schema["const"]: + errors.append(f"{location}:const") + if "enum" in schema and value not in schema["enum"]: + errors.append(f"{location}:enum") + expected_type = schema.get("type") + allowed_types = [expected_type] if isinstance(expected_type, str) else expected_type + if isinstance(allowed_types, list): + def type_ok(name: str) -> bool: + return { + "object": isinstance(value, dict), + "array": isinstance(value, list), + "string": isinstance(value, str), + "integer": isinstance(value, int) and not isinstance(value, bool), + "number": isinstance(value, (int, float)) and not isinstance(value, bool), + "boolean": isinstance(value, bool), + "null": value is None, + }.get(name, True) + if not any(type_ok(str(name)) for name in allowed_types): + return errors + [f"{location}:type"] + if isinstance(value, dict): + required = schema.get("required", []) + if isinstance(required, list): + errors.extend(f"{location}.{key}:required" for key in required if key not in value) + properties = schema.get("properties", {}) + if isinstance(properties, dict): + for key, child in properties.items(): + if key in value and isinstance(child, dict): + errors.extend(schema_errors(value[key], child, current_path, store, location=f"{location}.{key}", depth=depth + 1)) + if schema.get("additionalProperties") is False: + errors.extend(f"{location}.{key}:additional" for key in value if key not in properties) + if isinstance(schema.get("minProperties"), int) and len(value) < schema["minProperties"]: + errors.append(f"{location}:minProperties") + if isinstance(value, list): + if isinstance(schema.get("minItems"), int) and len(value) < schema["minItems"]: + errors.append(f"{location}:minItems") + if isinstance(schema.get("maxItems"), int) and len(value) > schema["maxItems"]: + errors.append(f"{location}:maxItems") + if schema.get("uniqueItems") is True: + serialized = [canonical_bytes(item) for item in value] + if len(serialized) != len(set(serialized)): + errors.append(f"{location}:uniqueItems") + prefix = schema.get("prefixItems") + if isinstance(prefix, list): + for index, child in enumerate(prefix): + if index < len(value) and isinstance(child, dict): + errors.extend(schema_errors(value[index], child, current_path, store, location=f"{location}[{index}]", depth=depth + 1)) + if schema.get("items") is False and len(value) > len(prefix): + errors.append(f"{location}:additionalItems") + elif isinstance(schema.get("items"), dict): + for index, item in enumerate(value): + errors.extend(schema_errors(item, schema["items"], current_path, store, location=f"{location}[{index}]", depth=depth + 1)) + contains = schema.get("contains") + if isinstance(contains, dict) and not any(not schema_errors(item, contains, current_path, store, location=location, depth=depth + 1) for item in value): + errors.append(f"{location}:contains") + if isinstance(value, str): + if isinstance(schema.get("minLength"), int) and len(value) < schema["minLength"]: + errors.append(f"{location}:minLength") + if isinstance(schema.get("maxLength"), int) and len(value) > schema["maxLength"]: + errors.append(f"{location}:maxLength") + if isinstance(schema.get("pattern"), str) and re.search(schema["pattern"], value) is None: + errors.append(f"{location}:pattern") + if isinstance(value, (int, float)) and not isinstance(value, bool): + if isinstance(schema.get("minimum"), (int, float)) and value < schema["minimum"]: + errors.append(f"{location}:minimum") + if isinstance(schema.get("maximum"), (int, float)) and value > schema["maximum"]: + errors.append(f"{location}:maximum") + for child in schema.get("allOf", []) if isinstance(schema.get("allOf"), list) else []: + if isinstance(child, dict): + errors.extend(schema_errors(value, child, current_path, store, location=location, depth=depth + 1)) + any_of = schema.get("anyOf") + if isinstance(any_of, list) and not any(isinstance(child, dict) and not schema_errors(value, child, current_path, store, location=location, depth=depth + 1) for child in any_of): + errors.append(f"{location}:anyOf") + one_of = schema.get("oneOf") + if isinstance(one_of, list) and sum(1 for child in one_of if isinstance(child, dict) and not schema_errors(value, child, current_path, store, location=location, depth=depth + 1)) != 1: + errors.append(f"{location}:oneOf") + forbidden = schema.get("not") + if isinstance(forbidden, dict) and not schema_errors(value, forbidden, current_path, store, location=location, depth=depth + 1): + errors.append(f"{location}:not") + condition = schema.get("if") + if isinstance(condition, dict): + branch_name = "then" if not schema_errors(value, condition, current_path, store, location=location, depth=depth + 1) else "else" + branch = schema.get(branch_name) + if isinstance(branch, dict): + errors.extend(schema_errors(value, branch, current_path, store, location=location, depth=depth + 1)) + return errors[:96] + + + def validate_schema_instance( + value: Any, schema_ref: str, store: Mapping[str, Mapping[str, Any]], *, code: str, + ) -> None: + target, path = resolve_schema_ref(schema_ref, "schemas/ingress.schema.json", store) + errors = schema_errors(value, target, path, store) + if errors: + raise S240Error(code, f"schema validation failed: {schema_ref}", details=errors[:16]) + + + def preflight(client: McpClient, request: Mapping[str, Any]) -> str: + if request["expected_parent_stage2_release_sha256"] != EXPECTED_STAGE2_RELEASE_SHA256: + raise S240Error("PARENT_CONSTANT_REQUEST", "request parent hash differs from inline constant") + fixed = ( + (PARENT_RELEASE_PATH, request["expected_parent_stage2_release_sha256"]), + (AGENT_PATH, request["expected_s2_40_agent_sha256"]), + (BINDING_PATH, request["expected_s2_40_executor_binding_sha256"]), + (INLINE_RECEIPT_PATH, request["expected_s2_40_inline_code_receipt_sha256"]), + (request["host_cas_receipt_ref"], request["host_cas_receipt_sha256"]), + (request["detached_admission_receipt_ref"], request["detached_admission_receipt_sha256"]), + ) + snapshot_rows: list[dict[str, Any]] = [] + fixed_raw: dict[str, bytes] = {} + for path, expected in fixed: + raw = client.read_binary(path) + if digest(raw) != expected: + raise S240Error("PREFLIGHT_HASH", f"preflight hash mismatch: {path}") + fixed_raw[path] = raw + snapshot_rows.append({"path": path, "sha256": expected, "size": len(raw)}) + parent = require_object(load_json(fixed_raw[PARENT_RELEASE_PATH], label=PARENT_RELEASE_PATH), code="PARENT_RELEASE_OBJECT") + require_self_hash(parent, "release_digest", code="PARENT_RELEASE_SELF_HASH") + module_ref = require_object(parent.get("module_manifest_ref"), code="PARENT_MODULE_REF") + if module_ref.get("path") != "manifest/module_manifest.json" or module_ref.get("binding_status") != "BOUND": + raise S240Error("PARENT_MODULE_REF", "parent does not bind canonical module manifest") + module_raw = client.read_binary(MODULE_MANIFEST_PATH) + if digest(module_raw) != require_hex(module_ref.get("sha256"), code="PARENT_MODULE_HASH"): + raise S240Error("PARENT_MODULE_HASH", "module manifest raw hash differs from parent") + module = require_object(load_json(module_raw, label=MODULE_MANIFEST_PATH), code="MODULE_MANIFEST_OBJECT") + require_self_hash(module, "manifest_digest", code="MODULE_MANIFEST_SELF_HASH") + modules = require_list(module.get("modules"), code="MODULE_ROWS") + workflow_rows = [row for row in modules if isinstance(row, dict) and row.get("module_id") == "WF-S2_40"] + if len(workflow_rows) != 1 or workflow_rows[0].get("path") != "workflows/S2_40_final_review_render_and_commit.yml": + raise S240Error("S240_MODULE_MEMBERSHIP", "exact S2_40 workflow module membership missing") + + inline_receipt = require_object(load_json(fixed_raw[INLINE_RECEIPT_PATH], label=INLINE_RECEIPT_PATH), code="INLINE_RECEIPT_OBJECT") + if (inline_receipt.get("schema_version") != "stage2_s2_40_inline_code_receipt.v1" + or inline_receipt.get("parity_status") != "PASS" + or inline_receipt.get("expected_parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or inline_receipt.get("deployment_projection", {}).get("sha256") != request["expected_s2_40_agent_sha256"] + or inline_receipt.get("deployment_projection", {}).get("path") != AGENT_PATH): + raise S240Error("INLINE_RECEIPT_MEMBERSHIP", "inline receipt does not bind parent and actual Agent") + binding_text = fixed_raw[BINDING_PATH].decode("utf-8", errors="strict") + required_binding_literals = ( + "stage_id: S2_40", "binding_id: S2-BINDING-S2_40-CODE-EXECUTOR-V1", + "path: agent_scripts/Stage_2_S2_40.yml", request["expected_s2_40_agent_sha256"], + "path: manifest/s2_40_inline_code_receipt.json", request["expected_s2_40_inline_code_receipt_sha256"], + "path: manifest/stage2_release.json", EXPECTED_STAGE2_RELEASE_SHA256, + ) + if any(literal not in binding_text for literal in required_binding_literals): + raise S240Error("BINDING_MEMBERSHIP", "binding does not bind exact S2_40 Agent/parent/receipt") + + admission = require_object(load_json(fixed_raw[request["detached_admission_receipt_ref"]], label="detached-admission"), code="ADMISSION_OBJECT") + admitted_status = "PRODUCTION_ADMITTED" if request.get("compile_mode") == "PRODUCTION" else "CANARY_ADMITTED" + if (admission.get("schema_version") != "stage2_deterministic_admission_receipt.v1" + or admission.get("parent_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or admission.get("executor_binding_sha256") != request["expected_s2_40_executor_binding_sha256"] + or admission.get("admission_status") not in {admitted_status, "PRODUCTION_ADMITTED"} + or admission.get("signature_verification_status") != "BACKEND_VERIFIED" + or admission.get("external_trust_verified") is not True + or not isinstance(admission.get("signature"), str) + or admission.get("signature", "").startswith("PENDING")): + raise S240Error("DETACHED_ADMISSION_NOT_TRUSTED", "release-bound external admission is absent or invalid") + signed_admission = { + key: value for key, value in admission.items() + if key not in {"signature", "signature_verification_status", "signed_payload_sha256"} + } + if (admission.get("signed_payload_sha256") != digest(signed_admission) + or HEX64.fullmatch(str(admission.get("backend_capability_receipt_sha256", ""))) is None): + raise S240Error("DETACHED_ADMISSION_SIGNATURE_SCOPE", "admission signed payload scope/hash differs") + receipt_matches = [row for row in admission.get("stage_receipts", []) if isinstance(row, dict) + and row.get("path") == "manifest/s2_40_inline_code_receipt.json" + and row.get("sha256") == request["expected_s2_40_inline_code_receipt_sha256"]] + if len(receipt_matches) != 1 or "S2_40" not in admission.get("present_deterministic_stage_ids", []): + raise S240Error("DETACHED_ADMISSION_S240", "admission does not bind exact S2_40 receipt") + + cas = require_object(load_json(fixed_raw[request["host_cas_receipt_ref"]], label="host-cas"), code="HOST_CAS_OBJECT") + if (cas.get("schema_version") != "stage2_s2_40_host_cas_receipt.v1" + or cas.get("run_binding_digest") != request["run_binding_digest"] + or cas.get("stage_id") != "S2_40" + or cas.get("candidate_attempt_id") != request["candidate_attempt_id"] + or cas.get("requested_transition") != request["requested_transition"] + or cas.get("expected_previous_run_status_sha256") != request["expected_previous_run_status_sha256"] + or cas.get("lease_status") != "ACQUIRED" + or HEX64.fullmatch(str(cas.get("signature_attestation", ""))) is None): + raise S240Error("HOST_CAS_NOT_BOUND", "host CAS receipt does not bind request transition") + try: + issued = datetime.fromisoformat(str(cas.get("issued_at")).replace("Z", "+00:00")) + expires = datetime.fromisoformat(str(cas.get("expires_at")).replace("Z", "+00:00")) + now = datetime.now(timezone.utc) + if issued.tzinfo is None or expires.tzinfo is None or issued > now or expires <= now or expires <= issued: + raise S240Error("HOST_CAS_TIME", "host CAS lease is not currently valid") + except (TypeError, ValueError) as exc: + raise S240Error("HOST_CAS_TIME", "host CAS timestamps are invalid") from exc + snapshot_rows.append({"path": MODULE_MANIFEST_PATH, "sha256": digest(module_raw), "size": len(module_raw)}) + return digest(snapshot_rows) + + + def load_output_schema_store(client: McpClient) -> dict[str, Mapping[str, Any]]: + values, _, _ = read_release_bound_jsons(client, INPUT_SCHEMA_RELS) + return {path: value for path, value in values.items() if path.startswith("schemas/")} + + + def write_terminal_status( + client: McpClient, + request: Mapping[str, Any], + *, + workflow_phase: str, + route: str, + candidate_content_digest: str | None, + run_technical_status: str, + artifact_technical_status: str, + legal_readiness: str, + validation_report_sha256: str | None = None, + review_subject_digest: str | None = None, + review_receipt_sha256s: Sequence[str] = (), + stage2_package_sha256: str | None = None, + artifact_set_digest: str | None = None, + commit_intent_sha256: str | None = None, + commit_result_sha256: str | None = None, + emit_status_event: bool = True, + schema_store: Mapping[str, Mapping[str, Any]] | None = None, + ) -> dict[str, Any]: + """Write one immutable transition event and the latest barrier last.""" + output_schemas = dict(schema_store) if schema_store is not None else load_output_schema_store(client) + root = request["stage2_run_root_ref"] + event_core = { + "schema_version": "stage2_s2_40_status_event.v1", + "writer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "workflow_phase": workflow_phase, "route": route, + "candidate_content_digest": candidate_content_digest, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "request_sha256": require_hex(request.get("_request_sha256"), code="REQUEST_RAW_HASH"), + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + } + event_raw_hash: str | None = None + if emit_status_event: + event = {**event_core, "event_digest": digest(event_core)} + validate_schema_instance( + event, "schemas/review_status.schema.json#/$defs/status_event", + output_schemas, code="GENERATED_STATUS_EVENT_SCHEMA", + ) + event_payload = canonical_bytes(event) + event_path = join_path(root, "control/status_events", f"{event['event_digest']}.json") + event_raw_hash = client.write_immutable(event_path, event_payload) + status = { + "schema_version": "stage2_s2_40_run_status.v1", "writer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "entry_route": request["entry_route"], "compile_mode": request["compile_mode"], + "workflow_phase": workflow_phase, "route": route, + "candidate_content_digest": candidate_content_digest, + "run_technical_status": run_technical_status, + "artifact_technical_status": artifact_technical_status, + "legal_readiness": legal_readiness, + "validation_report_sha256": validation_report_sha256, + "review_subject_digest": review_subject_digest, + "review_receipt_sha256s": sorted(set(review_receipt_sha256s)), + "stage2_package_sha256": stage2_package_sha256, + "artifact_set_digest": artifact_set_digest, + "commit_intent_sha256": commit_intent_sha256, + "commit_result_sha256": commit_result_sha256, + "request_sha256": request["_request_sha256"], + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + "outer_execution_receipt_sha256": None, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "status_event_sha256": event_raw_hash, + "barrier_written_last": True, "readback_verified": True, + } + validate_schema_instance( + status, "schemas/review_status.schema.json#/$defs/run_status", + output_schemas, code="GENERATED_RUN_STATUS_SCHEMA", + ) + status_payload = canonical_bytes(status) + status_path = join_path(root, "control/run_status.json") + status_hash = client.write_latest( + status_path, status_payload, request["expected_previous_run_status_sha256"], + ) + return {"status": status, "status_sha256": status_hash, "status_path": status_path} + + + def ingress_schema_ref(path: str) -> str: + exact = { + "ingress/stage1_input_manifest.json": "schemas/ingress.schema.json#/$defs/stage1_input_manifest", + "ingress/intake_report.json": "schemas/ingress.schema.json#/$defs/intake_report", + "ingress/technical_diagnostic.json": "schemas/ingress.schema.json#/$defs/technical_diagnostic", + "context/case_context.json": "schemas/context.schema.json#/$defs/case_context", + "context/evidence_inventory.json": "schemas/context.schema.json#/$defs/evidence_inventory", + "context/object_registry.json": "schemas/context.schema.json#/$defs/object_registry", + "context/party_and_title_context.json": "schemas/context.schema.json#/$defs/party_and_title_context", + "context/slot_crosswalk.json": "schemas/context.schema.json#/$defs/slot_crosswalk", + "context/cluster_plan.json": "schemas/context.schema.json#/$defs/cluster_plan", + "context/bundle_plan.json": "schemas/context.schema.json#/$defs/bundle_plan", + "review/issue_ledger.base.json": "schemas/review_status.schema.json#/$defs/issue_ledger_base", + } + if path in exact: + return exact[path] + if re.fullmatch(r"context/cluster_slices/[A-Za-z0-9][A-Za-z0-9._:-]{0,255}\.json", path): + return "schemas/context.schema.json#/$defs/cluster_slice" + raise S240Error("INGRESS_ARTIFACT_PATH", f"unrecognized ingress artifact path: {path}") + + + def hydrate_ingress_barrier_artifacts( + client: McpClient, + root: str, + ingress: Mapping[str, Any], + schema_store: Mapping[str, Mapping[str, Any]], + *, + exact_paths: set[str] | None = None, + ) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], list[dict[str, Any]]]: + barrier = require_object(ingress.get("output_barrier"), code="INGRESS_OUTPUT_BARRIER") + rows = require_list(barrier.get("artifacts"), code="INGRESS_OUTPUT_ROWS") + if barrier.get("artifact_set_digest") != digest(rows): + raise S240Error("INGRESS_OUTPUT_SET_DIGEST", "ingress artifact-set digest differs") + paths = [safe_path(row.get("path"), code="INGRESS_OUTPUT_PATH") for row in rows if isinstance(row, dict)] + if len(paths) != len(rows) or len(paths) != len(set(paths)) or paths != sorted(paths): + raise S240Error("INGRESS_OUTPUT_SET", "ingress artifact rows must be unique and sorted") + if exact_paths is not None and set(paths) != exact_paths: + raise S240Error("INGRESS_OUTPUT_EXACT_SET", "ingress barrier does not bind the exact expected paths") + values: dict[str, dict[str, Any]] = {} + raws: dict[str, bytes] = {} + normalized_rows: list[dict[str, Any]] = [] + for row in rows: + row = require_object(row, code="INGRESS_OUTPUT_ROW") + path = safe_path(row.get("path"), code="INGRESS_OUTPUT_PATH") + if row.get("logical_artifact_id") != path: + raise S240Error("INGRESS_OUTPUT_LOGICAL_ID", "logical artifact id must equal canonical path") + schema_ref = ingress_schema_ref(path) + schema_path = schema_ref.split("#", 1)[0] + if row.get("schema_id") != schema_store[schema_path].get("$id"): + raise S240Error("INGRESS_OUTPUT_SCHEMA_ID", f"schema id differs: {path}") + raw_a = client.read_binary(join_path(root, path)) + raw_b = client.read_binary(join_path(root, path)) + if raw_a != raw_b: + raise S240Error("INGRESS_OUTPUT_TOCTOU", f"ingress artifact changed between reads: {path}") + if digest(raw_a) != require_hex(row.get("raw_sha256"), code="INGRESS_OUTPUT_HASH"): + raise S240Error("INGRESS_OUTPUT_HASH", f"ingress artifact hash differs: {path}") + if row.get("byte_length", len(raw_a)) != len(raw_a): + raise S240Error("INGRESS_OUTPUT_SIZE", f"ingress artifact size differs: {path}") + value = require_object(load_json(raw_a, label=path), code="INGRESS_OUTPUT_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="INGRESS_OUTPUT_SCHEMA") + values[path] = value + raws[path] = raw_a + normalized_rows.append({ + "path": path, "raw_sha256": digest(raw_a), "byte_length": len(raw_a), + "schema_id": row.get("schema_id"), "schema_ref": schema_ref, + }) + return values, raws, normalized_rows + + + def status_only(client: McpClient, request: Mapping[str, Any], preflight_digest: str) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + schema_values, _, schema_rows = read_release_bound_jsons(client, INPUT_SCHEMA_RELS) + schema_store: dict[str, Mapping[str, Any]] = dict(schema_values) + rels_and_refs = ( + ("ingress/ingress_status.json", "schemas/ingress.schema.json#/$defs/ingress_status"), + ("ingress/technical_diagnostic.json", "schemas/ingress.schema.json#/$defs/technical_diagnostic"), + ("ingress/stage1_input_manifest.json", "schemas/ingress.schema.json#/$defs/stage1_input_manifest"), + ("ingress/intake_report.json", "schemas/ingress.schema.json#/$defs/intake_report"), + ("review/issue_ledger.base.json", "schemas/review_status.schema.json#/$defs/issue_ledger_base"), + ) + rows: list[dict[str, Any]] = [] + values: dict[str, dict[str, Any]] = {} + for rel, schema_ref in rels_and_refs: + path = join_path(root, rel) + raw = client.read_binary(path) + if rel == "ingress/ingress_status.json" and digest(raw) != request["expected_ingress_status_sha256"]: + raise S240Error("STATUS_ONLY_INGRESS_HASH", "ingress status hash mismatch") + value = require_object(load_json(raw, label=path), code="STATUS_ONLY_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="STATUS_ONLY_SCHEMA") + values[rel] = value + rows.append({ + "path": rel, "sha256": digest(raw), "size": len(raw), + "schema_ref": schema_ref, "schema_version": value.get("schema_version"), + }) + ingress = values["ingress/ingress_status.json"] + diagnostic = values["ingress/technical_diagnostic.json"] + manifest = values["ingress/stage1_input_manifest.json"] + intake = values["ingress/intake_report.json"] + ledger = values["review/issue_ledger.base.json"] + run_receipt = require_object(ingress.get("run_binding_receipt"), code="STATUS_ONLY_RUN_RECEIPT") + run_id = ingress.get("run_id") + input_set_digest = manifest.get("input_set_digest") + if ( + ingress.get("route") != "TO_S2_40_STATUS_ONLY" + or require_object(ingress.get("output_barrier"), code="STATUS_ONLY_BARRIER").get("branch") != "DIAGNOSTIC" + or ingress["output_barrier"].get("written_last") is not True + or diagnostic.get("route") != "TO_S2_40_STATUS_ONLY" + or diagnostic.get("context_published") is not False + or diagnostic.get("minimum_coherent_package_possible") is not False + or intake.get("minimum_coherent_package_possible") is not False + ): + raise S240Error("STATUS_ONLY_ROUTE_CONTRACT", "diagnostic route semantics differ") + if ( + run_receipt.get("run_binding_digest") != request["run_binding_digest"] + or run_receipt.get("stage2_release_digest") != EXPECTED_STAGE2_RELEASE_SHA256 + or run_receipt.get("run_id") != run_id + or run_receipt.get("input_set_digest") != input_set_digest + or manifest.get("run_id") != run_id + or intake.get("run_id") != run_id + or diagnostic.get("run_id") != run_id + or ledger.get("run_id") != run_id + or ledger.get("producer_id") != "S2_00" + or ledger.get("input_set_digest") != input_set_digest + ): + raise S240Error("STATUS_ONLY_CROSS_BINDING", "exact-five inputs do not bind one run/input/release") + if set(diagnostic.get("reason_codes", [])) - set(ingress.get("issue_codes", [])): + raise S240Error("STATUS_ONLY_REASON_CONSERVATION", "diagnostic reasons are absent from ingress issue codes") + _, barrier_raws, barrier_rows = hydrate_ingress_barrier_artifacts( + client, root, ingress, schema_store, + exact_paths={ + "ingress/technical_diagnostic.json", "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", "review/issue_ledger.base.json", + }, + ) + for row in rows[1:]: + if barrier_raws.get(row["path"]) is None or digest(barrier_raws[row["path"]]) != row["sha256"]: + raise S240Error("STATUS_ONLY_BARRIER_BINDING", f"barrier/raw mismatch: {row['path']}") + status_only_digest = digest({ + "domain_separator": "STAGE2_S2_40_STATUS_ONLY_EXACT_FIVE_V1", + "preflight_snapshot_digest": preflight_digest, + "run_id": run_id, "input_set_digest": input_set_digest, + "input_rows": rows, "barrier_rows": barrier_rows, + "release_schema_rows": schema_rows, + }) + return write_terminal_status( + client, request, + workflow_phase="DIAGNOSTIC_ONLY", route="STOP_TECHNICAL_INCOMPLETE", + candidate_content_digest=None, run_technical_status="TECHNICAL_INCOMPLETE", + artifact_technical_status="NOT_PRODUCED", legal_readiness="NOT_ASSESSED", + validation_report_sha256=status_only_digest, + emit_status_event=False, + schema_store=schema_store, + ) + + + def require_self_hash(value: Mapping[str, Any], field: str, *, code: str) -> None: + observed = require_hex(value.get(field), code=code) + material = {key: item for key, item in value.items() if key != field} + if observed != digest(material): + raise S240Error(code, f"self hash mismatch: {field}") + + + def hydrate_s210_artifacts( + client: McpClient, + root: str, + ingress: Mapping[str, Any], + ingress_documents: Mapping[str, Mapping[str, Any]], + ingress_raws: Mapping[str, bytes], + s210: Mapping[str, Any], + request: Mapping[str, Any], + schema_store: Mapping[str, Mapping[str, Any]], + ) -> dict[str, Any]: + """Hydrate the exact S2_10 universe named by the S2_00 plans.""" + cluster_plan = require_object( + ingress_documents.get("context/cluster_plan.json"), code="S210_CLUSTER_PLAN", + ) + bundle_plan = require_object( + ingress_documents.get("context/bundle_plan.json"), code="S210_BUNDLE_PLAN", + ) + cluster_ids = [ + require_ident(value, code="S210_CLUSTER_ID") + for value in require_list(cluster_plan.get("executable_cluster_ids"), code="S210_CLUSTER_IDS") + ] + if ( + cluster_ids != sorted(cluster_ids) + or len(cluster_ids) != len(set(cluster_ids)) + or cluster_ids != ingress.get("executable_cluster_ids") + or sorted(s210.get("expected_executable_cluster_ids", [])) != cluster_ids + or sorted(s210.get("valid_domain_verdict_cluster_ids", [])) != cluster_ids + or s210.get("terminal_technical_failure_cluster_ids") != [] + ): + raise S240Error("S210_CLUSTER_CLOSURE", "S2_00/S2_10 executable cluster sets differ") + + wave_by_cluster: dict[str, int] = {} + for cohort in require_list(bundle_plan.get("cohorts"), code="S210_BUNDLE_COHORTS"): + cohort = require_object(cohort, code="S210_BUNDLE_COHORT") + if cohort.get("cohort_status") != "EXECUTABLE": + continue + members = require_list(cohort.get("member_slices"), code="S210_BUNDLE_MEMBERS") + for member in members: + member = require_object(member, code="S210_BUNDLE_MEMBER") + cluster_id = require_ident(member.get("cluster_id"), code="S210_BUNDLE_CLUSTER") + ordinal = member.get("dependency_wave_ordinal") + if cluster_id in wave_by_cluster or cluster_id not in cluster_ids or not isinstance(ordinal, int) or ordinal < 0: + raise S240Error("S210_BUNDLE_WAVE", "bundle member/wave mapping is not exact") + expected_slice = f"context/cluster_slices/{cluster_id}.json" + if ( + member.get("path") != expected_slice + or member.get("sha256") != digest(ingress_raws[expected_slice]) + ): + raise S240Error("S210_BUNDLE_SLICE", f"bundle slice hash differs: {cluster_id}") + wave_by_cluster[cluster_id] = ordinal + if set(wave_by_cluster) != set(cluster_ids): + raise S240Error("S210_BUNDLE_COVERAGE", "bundle does not cover the exact executable cluster set") + wave_ordinals = sorted(set(wave_by_cluster.values())) + if wave_ordinals != list(range(len(wave_ordinals))): + raise S240Error("S210_WAVE_ORDINALS", "dependency-wave ordinals are not contiguous from zero") + + def stable_json(path: str, schema_ref: str) -> tuple[dict[str, Any], bytes]: + raw_a = client.read_binary(join_path(root, path)) + raw_b = client.read_binary(join_path(root, path)) + if raw_a != raw_b: + raise S240Error("S210_TOCTOU", f"S2_10 artifact changed between reads: {path}") + value = require_object(load_json(raw_a, label=path), code="S210_ARTIFACT_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="S210_ARTIFACT_SCHEMA") + closure_rows.append({ + "path": path, "sha256": digest(raw_a), "expected_sha256": digest(raw_a), + "schema_ref": schema_ref, "schema_version": value.get("schema_version"), + "producer_id": value.get("producer_id", "S2_10"), + "schema_valid": True, "hash_match": True, + }) + return value, raw_a + + verdicts: dict[str, dict[str, Any]] = {} + item_receipts: dict[str, dict[str, Any]] = {} + issue_parts: dict[str, dict[str, Any]] = {} + assumption_parts: dict[str, dict[str, Any]] = {} + usage_parts: dict[str, dict[str, Any]] = {} + raw_by_path: dict[str, bytes] = {} + closure_rows: list[dict[str, Any]] = [] + request_ids: set[str] = set() + producer_contract_digests: set[str] = set() + for cluster_id in cluster_ids: + paths = { + "verdict": f"map_s2_10/domain_verdicts/{cluster_id}.json", + "item": f"map_s2_10/item_receipts/{cluster_id}.json", + "issue": f"map_s2_10/issue_patches/{cluster_id}.json", + "assumption": f"map_s2_10/assumption_parts/{cluster_id}.json", + "usage": f"map_s2_10/usage_parts/{cluster_id}.json", + } + verdict, verdict_raw = stable_json(paths["verdict"], "schemas/s2_10.schema.json#/$defs/canonical_domain_verdict") + item, item_raw = stable_json(paths["item"], "schemas/s2_10.schema.json#/$defs/item_receipt") + issue, issue_raw = stable_json(paths["issue"], "schemas/s2_10.schema.json#/$defs/issue_part") + assumption, assumption_raw = stable_json(paths["assumption"], "schemas/s2_10.schema.json#/$defs/assumption_part") + usage, usage_raw = stable_json(paths["usage"], "schemas/s2_10.schema.json#/$defs/usage_part") + require_self_hash(verdict, "domain_verdict_sha256", code="S210_VERDICT_SELF_HASH") + require_self_hash(item, "receipt_sha256", code="S210_ITEM_SELF_HASH") + for part, label in ((issue, "ISSUE"), (assumption, "ASSUMPTION"), (usage, "USAGE")): + require_self_hash(part, "part_sha256", code=f"S210_{label}_SELF_HASH") + producer_contract_digest = require_hex( + verdict.get("producer_contract_digest"), code="S210_PRODUCER_CONTRACT", + ) + producer_contract_digests.add(producer_contract_digest) + verdict_hash = verdict["domain_verdict_sha256"] + if ( + verdict.get("cluster_id") != cluster_id + or verdict.get("run_binding_digest") != request["run_binding_digest"] + or verdict.get("cluster_slice_sha256") != digest(ingress_raws[f"context/cluster_slices/{cluster_id}.json"]) + or verdict.get("wave_ordinal") != wave_by_cluster[cluster_id] + or item.get("cluster_id") != cluster_id + or item.get("run_binding_digest") != request["run_binding_digest"] + or item.get("domain_verdict_path") != paths["verdict"] + or item.get("domain_verdict_sha256") != verdict_hash + or item.get("read_back_sha256") != verdict_hash + or item.get("request_id") != verdict.get("request_id") + or item.get("wave_ordinal") != verdict.get("wave_ordinal") + or item.get("attempt_no") != verdict.get("attempt_no") + or item.get("raw_model_output_sha256") != verdict.get("raw_model_output_sha256") + or item.get("validation_status") != "PASS" + or item.get("persistence_status") not in {"PUBLISHED", "IDEMPOTENT_BYTE_IDENTICAL"} + ): + raise S240Error("S210_ITEM_LINK", f"S2_10 verdict/item link differs: {cluster_id}") + for part, expected_hash, label in ( + (issue, item.get("issue_part_sha256"), "ISSUE"), + (assumption, item.get("assumption_part_sha256"), "ASSUMPTION"), + (usage, item.get("usage_part_sha256"), "USAGE"), + ): + header = require_object(part.get("header"), code=f"S210_{label}_HEADER") + if ( + part.get("part_sha256") != expected_hash + or header.get("producer_contract_digest") != producer_contract_digest + or header.get("request_id") != item.get("request_id") + or header.get("run_binding_digest") != request["run_binding_digest"] + or header.get("wave_ordinal") != item.get("wave_ordinal") + or header.get("attempt_no") != item.get("attempt_no") + or header.get("cluster_id") != cluster_id + or header.get("domain_verdict_sha256") != verdict_hash + ): + raise S240Error(f"S210_{label}_LINK", f"S2_10 {label.lower()} part link differs: {cluster_id}") + if assumption.get("assumptions") != verdict.get("assumptions"): + raise S240Error("S210_ASSUMPTION_CONTENT", f"assumption part differs from verdict: {cluster_id}") + request_ids.add(str(item.get("request_id"))) + verdicts[cluster_id] = verdict + item_receipts[cluster_id] = item + issue_parts[cluster_id] = issue + assumption_parts[cluster_id] = assumption + usage_parts[cluster_id] = usage + raw_by_path.update({ + paths["verdict"]: verdict_raw, paths["item"]: item_raw, + paths["issue"]: issue_raw, paths["assumption"]: assumption_raw, + paths["usage"]: usage_raw, + }) + if len(request_ids) != 1 or len(producer_contract_digests) != 1: + raise S240Error("S210_REQUEST_PRODUCER_SET", "S2_10 items do not share one request/producer contract") + + wave_receipts: list[dict[str, Any]] = [] + covered: set[str] = set() + for ordinal in wave_ordinals: + path = f"map_s2_10/wave_receipts/wave-{ordinal:04d}.json" + wave, raw = stable_json(path, "schemas/s2_10.schema.json#/$defs/wave_receipt") + require_self_hash(wave, "receipt_sha256", code="S210_WAVE_SELF_HASH") + expected_clusters = sorted(key for key, value in wave_by_cluster.items() if value == ordinal) + if ( + wave.get("request_id") not in request_ids + or wave.get("run_binding_digest") != request["run_binding_digest"] + or wave.get("wave_ordinal") != ordinal + or wave.get("is_final_wave") != (ordinal == wave_ordinals[-1]) + or sorted(wave.get("expected_wave_cluster_ids", [])) != expected_clusters + or sorted(wave.get("valid_domain_verdict_cluster_ids", [])) != expected_clusters + or wave.get("terminal_technical_failure_cluster_ids") != [] + or wave.get("wave_status") != "WAVE_COMPLETE" + or wave.get("route") != ("TO_S2_20" if ordinal == wave_ordinals[-1] else "NEXT_WAVE") + or wave.get("written_once") is not True + ): + raise S240Error("S210_WAVE_LINK", f"S2_10 wave receipt differs: {ordinal}") + covered.update(expected_clusters) + wave_receipts.append(wave) + raw_by_path[path] = raw + if covered != set(cluster_ids) or s210.get("terminal_wave_receipt_sha256s") != [ + row["receipt_sha256"] for row in wave_receipts + ]: + raise S240Error("S210_WAVE_CLOSURE", "S2_10 terminal wave receipt closure differs") + return { + "cluster_ids": cluster_ids, "verdicts": verdicts, + "item_receipts": item_receipts, "issue_parts": issue_parts, + "assumption_parts": assumption_parts, "usage_parts": usage_parts, + "wave_receipts": wave_receipts, "raw_by_path": raw_by_path, + "source_rows": [ + {"path": path, "sha256": digest(raw), "ref_family": "s2_10_runtime"} + for path, raw in sorted(raw_by_path.items()) + ], + "closure_rows": sorted(closure_rows, key=lambda row: row["path"]), + } + + + def validate_handoff_provenance( + value: Any, *, common_only: bool, expected_mode: str, code: str, + ) -> dict[str, Any]: + row = require_object(value, code=code) + expected = COMMON_PROVENANCE_FIELDS if common_only else GROUP_PROVENANCE_FIELDS + if set(row) != expected: + raise S240Error(code, "handoff provenance is not closed", details=sorted(set(row) ^ expected)) + if row.get("compile_mode") != expected_mode: + raise S240Error("COMPILE_MODE_DRIFT", "handoff compile mode differs") + for key in expected - {"compile_mode"}: + require_hex(row.get(key), code=code) + return row + + + def common_provenance(value: Mapping[str, Any]) -> dict[str, Any]: + return {key: value[key] for key in sorted(COMMON_PROVENANCE_FIELDS)} + + + def artifact_rows(manifest: Mapping[str, Any]) -> list[dict[str, Any]]: + rows = require_list(manifest.get("part_rows"), code="S230_MANIFEST_ROWS") + if len(rows) > MAX_ARTIFACT_ROWS: + raise S240Error("S230_MANIFEST_LIMIT", "too many artifact rows") + result: list[dict[str, Any]] = [] + seen_pairs: set[tuple[str, str]] = set() + seen_paths: set[str] = set() + for value in rows: + row = require_object(value, code="S230_MANIFEST_ROW") + if set(row) != {"claim_group_id", "part_family", "path", "sha256", "schema_ref"}: + raise S240Error("S230_MANIFEST_ROW_SHAPE", "manifest row is not closed") + group_id = require_ident(row.get("claim_group_id"), code="S230_MANIFEST_GROUP") + family = row.get("part_family") + if family not in PART_FAMILIES: + raise S240Error("S230_MANIFEST_KIND", f"unsupported part family: {family}") + path = safe_path(row.get("path"), code="S230_MANIFEST_PATH") + expected_path = f"map_s2_30/{PART_DIRECTORIES[family]}/{group_id}.json" + if path != expected_path or row.get("schema_ref") != PART_SCHEMA_REFS[family]: + raise S240Error("S230_MANIFEST_BINDING", "part path/schema differs from canonical binding") + pair = (group_id, family) + if pair in seen_pairs or path in seen_paths: + raise S240Error("S230_MANIFEST_DUPLICATE", "duplicate part pair/path") + seen_pairs.add(pair) + seen_paths.add(path) + result.append({ + "path": path, + "sha256": require_hex(row.get("sha256"), code="S230_MANIFEST_HASH"), + "schema_ref": row["schema_ref"], + "part_family": family, + "claim_group_id": group_id, + }) + if result != sorted(result, key=lambda row: (row["claim_group_id"], row["part_family"], row["path"])): + raise S240Error("S230_MANIFEST_ORDER", "part rows must be canonically sorted") + return result + + + def plan_artifact_rows(plan: Mapping[str, Any]) -> list[dict[str, Any]]: + rows = require_list(plan.get("artifact_rows"), code="S220_ARTIFACT_ROWS") + result: list[dict[str, Any]] = [] + seen: set[str] = set() + for value in rows: + row = require_object(value, code="S220_ARTIFACT_ROW") + path = safe_path(row.get("path"), code="S220_ARTIFACT_PATH") + if path in seen: + raise S240Error("S220_ARTIFACT_DUPLICATE", f"duplicate plan artifact: {path}") + seen.add(path) + result.append({ + "path": path, + "schema_ref": row.get("schema_ref"), + "raw_sha256": require_hex(row.get("raw_sha256"), code="S220_ARTIFACT_HASH"), + "byte_size": row.get("byte_size"), + "producer_component": row.get("producer_component"), + }) + if result != sorted(result, key=lambda row: row["path"]): + raise S240Error("S220_ARTIFACT_ORDER", "plan artifact rows must be sorted") + if plan.get("artifact_set_digest") != digest(result): + raise S240Error("S220_ARTIFACT_SET_DIGEST", "plan artifact set digest mismatch") + return result + + + def read_plan_artifacts( + client: McpClient, root: str, plan: Mapping[str, Any], total: int, + schema_store: Mapping[str, Mapping[str, Any]], + ) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], int]: + rows = plan_artifact_rows(plan) + documents: dict[str, dict[str, Any]] = {} + raw_by_path: dict[str, bytes] = {} + for row in rows: + value, raw = read_bound_json(client, join_path(root, row["path"]), row["raw_sha256"]) + if isinstance(row.get("schema_ref"), str) and row["schema_ref"].startswith("schemas/"): + validate_schema_instance(value, row["schema_ref"], schema_store, code="S220_ARTIFACT_SCHEMA") + if row["byte_size"] != len(raw): + raise S240Error("S220_ARTIFACT_SIZE", f"plan artifact size mismatch: {row['path']}") + total += len(raw) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + documents[row["path"]] = value + raw_by_path[row["path"]] = raw + return documents, raw_by_path, total + + + def resolve_frozen_ref( + client: McpClient, + root: str, + plan_rows: Mapping[str, bytes], + ref: Mapping[str, Any], + *, + code: str, + ) -> tuple[dict[str, Any], bytes, str]: + relative = safe_path(ref.get("path"), code=code) + expected = require_hex(ref.get("sha256"), code=code) + plan_path = relative if relative.startswith("plan/") else f"plan/{relative}" + if plan_path in plan_rows: + raw = plan_rows[plan_path] + if digest(raw) != expected: + raise S240Error(code, f"frozen plan ref hash mismatch: {relative}") + return require_object(load_json(raw, label=plan_path), code=code), raw, plan_path + asset_path = relative if relative.startswith(f"{ASSET_ROOT}/") else join_path(ASSET_ROOT, relative) + value, raw = read_bound_json(client, asset_path, expected) + return value, raw, asset_path + + + def hydrate_normal(client: McpClient, request: Mapping[str, Any]) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + ingress, ingress_raw = read_bound_json(client, join_path(root, "ingress/ingress_status.json"), request["expected_ingress_status_sha256"]) + s210, s210_raw = read_bound_json(client, join_path(root, "map_s2_10/s2_10_publish_status.json"), request["expected_s2_10_publish_status_sha256"]) + plan, plan_raw = read_bound_json(client, join_path(root, "plan/plan_publish_status.json"), request["expected_plan_publish_status_sha256"]) + s230, s230_raw = read_bound_json(client, join_path(root, "map_s2_30/s2_30_publish_status.json"), request["expected_s2_30_publish_status_sha256"]) + manifest_path = join_path(root, "map_s2_30/artifact_manifest.json") + manifest, manifest_raw = read_bound_json(client, manifest_path, request["expected_s2_30_artifact_manifest_sha256"]) + release_values, release_raws, release_rows = read_release_bound_jsons( + client, ( + *INPUT_SCHEMA_RELS, AUTHORITY_RELEASE_REL, CASE_TYPE_COVERAGE_REL, + CASE_TYPE_REGISTRY_REL, CASE_TYPE_RULE_REGISTRY_REL, + ), + ) + schema_store: dict[str, Mapping[str, Any]] = { + path: value for path, value in release_values.items() if path.startswith("schemas/") + } + validate_schema_instance(ingress, "schemas/ingress.schema.json#/$defs/ingress_status", schema_store, code="V01_INGRESS_SCHEMA") + validate_schema_instance(s210, "schemas/s2_10.schema.json#/$defs/global_publish_status", schema_store, code="V01_S210_SCHEMA") + validate_schema_instance(plan, "schemas/relief_plan.schema.json#/$defs/plan_publish_status", schema_store, code="V01_S220_SCHEMA") + validate_schema_instance(s230, "schemas/draft_atoms.schema.json#/$defs/publish_status", schema_store, code="V01_S230_SCHEMA") + validate_schema_instance(manifest, "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", schema_store, code="V01_S230_MANIFEST_SCHEMA") + executable_cluster_ids = [ + require_ident(value, code="INGRESS_EXECUTABLE_CLUSTER") + for value in require_list(ingress.get("executable_cluster_ids"), code="INGRESS_EXECUTABLE_CLUSTERS") + ] + normal_ingress_paths = { + "ingress/stage1_input_manifest.json", "ingress/intake_report.json", + "context/case_context.json", "context/evidence_inventory.json", + "context/object_registry.json", "context/party_and_title_context.json", + "context/slot_crosswalk.json", "context/cluster_plan.json", + "context/bundle_plan.json", "review/issue_ledger.base.json", + *{f"context/cluster_slices/{cluster_id}.json" for cluster_id in executable_cluster_ids}, + } + ingress_documents, ingress_raws, ingress_artifact_rows = hydrate_ingress_barrier_artifacts( + client, root, ingress, schema_store, exact_paths=normal_ingress_paths, + ) + ingress_barrier = require_object(ingress.get("output_barrier"), code="INGRESS_NORMAL_BARRIER") + if ( + ingress_barrier.get("branch") != "NORMAL" + or ingress_barrier.get("written_last") is not True + or ingress_barrier.get("non_status_artifacts_read_back_verified", True) is not True + or ingress_documents["context/cluster_plan.json"].get("executable_cluster_ids") != executable_cluster_ids + ): + raise S240Error("INGRESS_NORMAL_CLOSURE", "normal ingress barrier/context closure differs") + ingress_receipt = require_object(ingress.get("run_binding_receipt"), code="V01_INGRESS_RUN_BINDING") + if ( + ingress.get("route") not in {"TO_S2_10", "TO_S2_10_WITH_ISSUES"} + or ingress_receipt.get("run_binding_digest") != request["run_binding_digest"] + or ingress_receipt.get("stage2_release_digest") != EXPECTED_STAGE2_RELEASE_SHA256 + or s210.get("producer_id") != "S2_10_NATIVE_RESULT_ADAPTER" + or s210.get("run_binding_digest") != request["run_binding_digest"] + or s210.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or s210.get("status") != "COMPLETE" or s210.get("route") != "TO_S2_20" + or s210.get("status_written_last") is not True + or plan.get("workflow_id") != "S2_20" + or plan.get("run_binding_digest") != request["run_binding_digest"] + or plan.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or plan.get("s2_10_publish_status_sha256") != request["expected_s2_10_publish_status_sha256"] + or s230.get("run_binding_digest") != request["run_binding_digest"] + or s230.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or manifest.get("run_binding_digest") != request["run_binding_digest"] + ): + raise S240Error("V01_INPUT_LINEAGE", "normal barriers do not share exact producer/run/release lineage") + require_self_hash(s210, "status_sha256", code="S210_STATUS_SELF_HASH") + s210_handoff = hydrate_s210_artifacts( + client, root, ingress, ingress_documents, ingress_raws, + s210, request, schema_store, + ) + require_self_hash(plan, "barrier_sha256", code="S220_STATUS_SELF_HASH") + if plan.get("plan_status") == "TECHNICAL_INCOMPLETE" or plan.get("route") != "TO_S2_30" or plan.get("consumer_authorized") is not True: + raise S240Error("S220_BARRIER_NOT_CONSUMABLE", "S2_20 barrier is not consumer-authorized") + if s230.get("status") != "S2_30_COMPLETE" or s230.get("route") != "TO_S2_40" or s230.get("status_written_last") is not True: + raise S240Error("S230_BARRIER_NOT_CONSUMABLE", "S2_30 barrier is not complete") + require_self_hash(s230, "status_sha256", code="S230_STATUS_SELF_HASH") + require_self_hash(manifest, "part_manifest_core_sha256", code="S230_MANIFEST_SELF_HASH") + common = validate_handoff_provenance( + manifest.get("provenance"), common_only=True, + expected_mode=request["compile_mode"], code="S230_COMMON_PROVENANCE", + ) + if s230.get("compile_mode") != request["compile_mode"] or s230.get("provenance") != common: + raise S240Error("COMPILE_MODE_DRIFT", "S2_30 barrier/manifest mode or provenance differs") + if ( + s230.get("artifact_manifest_path") != "map_s2_30/artifact_manifest.json" + or s230.get("artifact_manifest_schema_ref") != "schemas/draft_atoms.schema.json#/$defs/part_manifest_core" + or s230.get("artifact_manifest_sha256") != digest(manifest_raw) + ): + raise S240Error("S230_BARRIER_MANIFEST", "S2_30 barrier does not bind exact manifest bytes") + expected_groups = require_list(manifest.get("expected_claim_group_ids"), code="S230_EXPECTED_GROUPS") + if expected_groups != sorted(expected_groups) or len(expected_groups) != len(set(expected_groups)): + raise S240Error("S230_EXPECTED_GROUP_ORDER", "manifest group ids must be unique and sorted") + if ( + s230.get("expected_claim_group_ids") != expected_groups + or s230.get("published_claim_group_ids") != expected_groups + or s230.get("terminal_failure_claim_group_ids") != [] + ): + raise S240Error("S230_GROUP_SET", "publish expected/published group set differs") + if sorted(plan.get("group_ids", [])) != expected_groups: + raise S240Error("S220_S230_GROUP_SET", "S2_20 and S2_30 group sets differ") + rows = artifact_rows(manifest) + expected_pairs = {(group_id, family) for group_id in expected_groups for family in PART_FAMILIES} + if {(row["claim_group_id"], row["part_family"]) for row in rows} != expected_pairs: + raise S240Error("S230_PART_COVERAGE", "manifest must contain exactly four part families per group") + parts: dict[str, list[dict[str, Any]]] = {family: [] for family in PART_FAMILIES} + group_provenance: dict[str, dict[str, Any]] = {} + total = ( + sum(len(raw) for raw in (ingress_raw, s210_raw, plan_raw, s230_raw, manifest_raw)) + + sum(len(raw) for raw in release_raws.values()) + + sum(len(raw) for raw in ingress_raws.values()) + + sum(len(raw) for raw in s210_handoff["raw_by_path"].values()) + ) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + for row in rows: + value, raw = read_bound_json(client, join_path(root, row["path"]), row["sha256"]) + validate_schema_instance(value, row["schema_ref"], schema_store, code="S230_PART_SCHEMA") + total += len(raw) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + require_self_hash(value, "part_sha256", code="S230_PART_SELF_HASH") + provenance = validate_handoff_provenance( + value.get("provenance"), common_only=False, + expected_mode=request["compile_mode"], code="S230_GROUP_PROVENANCE", + ) + if common_provenance(provenance) != common: + raise S240Error("S230_PART_COMMON_PROVENANCE", "part common provenance differs") + if value.get("claim_group_id") != row["claim_group_id"]: + raise S240Error("S230_PART_GROUP", "part group mismatch") + prior = group_provenance.setdefault(row["claim_group_id"], provenance) + if prior != provenance: + raise S240Error("S230_PART_GROUP_PROVENANCE", "part family provenance differs within group") + parts[row["part_family"]].append(value) + item_refs = require_list(s230.get("ordered_item_receipts"), code="S230_ITEM_RECEIPT_REFS") + cohort_refs = require_list(s230.get("ordered_cohort_receipts"), code="S230_COHORT_RECEIPT_REFS") + if item_refs != sorted(item_refs, key=lambda row: (row.get("claim_group_id"), row.get("path"))): + raise S240Error("S230_ITEM_RECEIPT_ORDER", "item receipt refs are not sorted") + if cohort_refs != sorted(cohort_refs, key=lambda row: row.get("path")): + raise S240Error("S230_COHORT_RECEIPT_ORDER", "cohort receipt refs are not sorted") + if [row.get("claim_group_id") for row in item_refs] != expected_groups: + raise S240Error("S230_ITEM_RECEIPT_GROUP_SET", "item receipt group set differs") + receipt_rows: list[dict[str, Any]] = [] + for kind, refs in (("ITEM", item_refs), ("COHORT", cohort_refs)): + for ref in refs: + receipt_path = safe_path(ref.get("path"), code="S230_RECEIPT_PATH") + receipt, receipt_raw = read_bound_json(client, join_path(root, receipt_path), require_hex(ref.get("sha256"), code="S230_RECEIPT_HASH")) + require_self_hash(receipt, "receipt_sha256", code="S230_RECEIPT_SELF_HASH") + if receipt.get("part_manifest_core_sha256") != manifest["part_manifest_core_sha256"]: + raise S240Error("S230_RECEIPT_CORE_HASH", "receipt references a different manifest core") + receipt_provenance = validate_handoff_provenance( + receipt.get("provenance"), common_only=kind == "COHORT", + expected_mode=request["compile_mode"], code="S230_RECEIPT_PROVENANCE", + ) + if common_provenance(receipt_provenance) != common: + raise S240Error("S230_RECEIPT_COMMON_PROVENANCE", "receipt provenance differs") + if kind == "ITEM": + group_id = ref.get("claim_group_id") + if receipt.get("claim_group_id") != group_id or receipt_provenance != group_provenance.get(group_id): + raise S240Error("S230_ITEM_RECEIPT_GROUP", "item receipt group/provenance differs") + total += len(receipt_raw) + receipt_rows.append({"kind": kind, "path": receipt_path, "sha256": digest(receipt_raw)}) + plan_documents, plan_raw_by_path, total = read_plan_artifacts(client, root, plan, total, schema_store) + rule_packs: dict[str, dict[str, Any]] = {} + group_slices: dict[str, dict[str, Any]] = {} + renderer_descriptors: dict[str, dict[str, Any]] = {} + frozen_assets: dict[str, dict[str, Any]] = {} + frozen_source_rows: list[dict[str, Any]] = [dict(row) for row in release_rows] + frozen_source_rows.extend({ + "path": row["path"], "sha256": row["raw_sha256"], "ref_family": "s2_00_runtime", + } for row in ingress_artifact_rows) + frozen_source_rows.extend(s210_handoff["source_rows"]) + frozen_source_rows.append({ + "path": "map_s2_30/artifact_manifest.json", + "sha256": digest(manifest_raw), "ref_family": "upstream_manifest", + }) + calculation_receipts: dict[str, dict[str, Any]] = {} + for group_id in expected_groups: + group_path = f"plan/group_slices/{group_id}.json" + group_slice = require_object(plan_documents.get(group_path), code="S220_GROUP_SLICE") + if group_slice.get("claim_group_id") != group_id: + raise S240Error("S220_GROUP_SLICE_ID", "group slice id differs") + group_echo = require_object(group_provenance.get(group_id), code="S230_GROUP_ECHO") + if (request["compile_mode"] != "STRUCTURAL_FIXTURE" + and digest(plan_raw_by_path[group_path]) != group_echo.get("s30_group_slice_sha256")): + raise S240Error("S220_S230_GROUP_SLICE_HASH", "S2_30 group-slice echo differs from frozen S2_20 bytes") + group_slices[group_id] = group_slice + rule_pack, rule_raw, resolved = resolve_frozen_ref( + client, root, plan_raw_by_path, + require_object(group_slice.get("rule_context_pack_ref"), code="S220_RULE_PACK_REF"), + code="S220_RULE_PACK_REF", + ) + if (request["compile_mode"] != "STRUCTURAL_FIXTURE" + and digest(rule_raw) != group_echo.get("p31_rule_and_pack_sha256")): + raise S240Error("S220_S230_RULE_PACK_HASH", "S2_30 rule-pack echo differs from frozen S2_20 bytes") + rule_packs[group_id] = rule_pack + frozen_source_rows.append({"path": resolved, "sha256": digest(rule_raw)}) + for ref in require_list(rule_pack.get("renderer_refs"), code="S220_RENDERER_REFS"): + descriptor, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_RENDERER_REF"), code="S220_RENDERER_REF") + renderer_id = require_ident(descriptor.get("renderer_id"), code="S220_RENDERER_ID") + if renderer_id in renderer_descriptors and canonical_bytes(renderer_descriptors[renderer_id]) != canonical_bytes(descriptor): + raise S240Error("S220_RENDERER_CONFLICT", "renderer id binds conflicting bytes") + renderer_descriptors[renderer_id] = descriptor + frozen_assets[resolved] = descriptor + frozen_source_rows.append({"path": resolved, "sha256": digest(raw)}) + for ref_name in ("structured_relief_rule_refs", "review_policy_refs", "ce13_branch_refs"): + for ref in require_list(rule_pack.get(ref_name), code="S220_RULE_ASSET_REFS"): + asset, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_RULE_ASSET_REF"), code="S220_RULE_ASSET_REF") + frozen_assets[resolved] = asset + frozen_source_rows.append({"path": resolved, "sha256": digest(raw), "ref_family": ref_name}) + for ref in require_list(group_slice.get("calculation_receipt_refs"), code="S220_CALC_REFS"): + receipt, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_CALC_REF"), code="S220_CALC_REF") + receipt_id = require_ident(receipt.get("calculation_receipt_id"), code="S220_CALC_ID") + calculation_receipts[receipt_id] = receipt + frozen_source_rows.append({"path": resolved, "sha256": digest(raw), "ref_family": "calculation"}) + exhibit_register = require_object(plan_documents.get("plan/exhibit_register.json"), code="S220_EXHIBIT_REGISTER") + authority_release = release_values[AUTHORITY_RELEASE_REL] + case_type_coverage = release_values[CASE_TYPE_COVERAGE_REL] + case_type_registry = release_values[CASE_TYPE_REGISTRY_REL] + case_type_rule_registry = release_values[CASE_TYPE_RULE_REGISTRY_REL] + input_closure_rows = [ + { + "path": "ingress/ingress_status.json", "sha256": digest(ingress_raw), + "expected_sha256": request["expected_ingress_status_sha256"], + "schema_ref": "schemas/ingress.schema.json#/$defs/ingress_status", + "schema_version": ingress.get("schema_version"), "producer_id": "S2_00", + "schema_valid": True, "hash_match": digest(ingress_raw) == request["expected_ingress_status_sha256"], + }, + { + "path": "map_s2_10/s2_10_publish_status.json", "sha256": digest(s210_raw), + "expected_sha256": request["expected_s2_10_publish_status_sha256"], + "schema_ref": "schemas/s2_10.schema.json#/$defs/global_publish_status", + "schema_version": s210.get("schema_version"), "producer_id": s210.get("producer_id"), + "schema_valid": True, "hash_match": digest(s210_raw) == request["expected_s2_10_publish_status_sha256"], + }, + { + "path": "plan/plan_publish_status.json", "sha256": digest(plan_raw), + "expected_sha256": request["expected_plan_publish_status_sha256"], + "schema_ref": "schemas/relief_plan.schema.json#/$defs/plan_publish_status", + "schema_version": plan.get("schema_version"), "producer_id": plan.get("workflow_id"), + "schema_valid": True, "hash_match": digest(plan_raw) == request["expected_plan_publish_status_sha256"], + }, + { + "path": "map_s2_30/s2_30_publish_status.json", "sha256": digest(s230_raw), + "expected_sha256": request["expected_s2_30_publish_status_sha256"], + "schema_ref": "schemas/draft_atoms.schema.json#/$defs/publish_status", + "schema_version": s230.get("schema_version"), "producer_id": "S2_30", + "schema_valid": True, "hash_match": digest(s230_raw) == request["expected_s2_30_publish_status_sha256"], + }, + { + "path": "map_s2_30/artifact_manifest.json", "sha256": digest(manifest_raw), + "expected_sha256": request["expected_s2_30_artifact_manifest_sha256"], + "schema_ref": "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", + "schema_version": manifest.get("schema_version"), "producer_id": "S2_30", + "schema_valid": True, "hash_match": digest(manifest_raw) == request["expected_s2_30_artifact_manifest_sha256"], + }, + ] + input_closure_rows.extend({ + "path": row["path"], "sha256": row["raw_sha256"], + "expected_sha256": row["raw_sha256"], "schema_ref": row["schema_ref"], + "schema_version": ingress_documents[row["path"]].get("schema_version"), + "producer_id": ingress_documents[row["path"]].get("producer_id", "S2_00"), + "schema_valid": True, "hash_match": True, + } for row in ingress_artifact_rows) + input_closure_rows.extend(s210_handoff["closure_rows"]) + input_snapshot_preimage = [ + digest(ingress_raw), digest(s210_raw), digest(plan_raw), digest(s230_raw), + digest(manifest_raw), *[row["sha256"] for row in rows], + *[row["sha256"] for row in receipt_rows], + *[digest(ingress_raws[path]) for path in sorted(ingress_raws)], + *[digest(s210_handoff["raw_by_path"][path]) for path in sorted(s210_handoff["raw_by_path"])], + *[digest(plan_raw_by_path[path]) for path in sorted(plan_raw_by_path)], + *[row["sha256"] for row in sorted(frozen_source_rows, key=lambda item: (item["path"], item["sha256"]))], + ] + return { + "ingress": ingress, "s210": s210, "plan": plan, "s230": s230, + "manifest": manifest, "manifest_sha256": digest(manifest_raw), "rows": rows, + "parts": parts, "group_ids": expected_groups, "group_provenance": group_provenance, + "receipt_rows": receipt_rows, "plan_documents": plan_documents, + "plan_raw_by_path": plan_raw_by_path, + "group_slices": group_slices, "rule_packs": rule_packs, + "renderer_descriptors": renderer_descriptors, + "frozen_assets": frozen_assets, + "calculation_receipts": calculation_receipts, + "exhibit_register": exhibit_register, + "ingress_documents": ingress_documents, "ingress_raws": ingress_raws, + "ingress_artifact_rows": ingress_artifact_rows, + "s210_handoff": s210_handoff, + "authority_release": authority_release, + "authority_release_sha256": digest(release_raws[AUTHORITY_RELEASE_REL]), + "case_type_coverage": case_type_coverage, + "case_type_coverage_sha256": digest(release_raws[CASE_TYPE_COVERAGE_REL]), + "case_type_registry": case_type_registry, + "case_type_registry_sha256": digest(release_raws[CASE_TYPE_REGISTRY_REL]), + "case_type_rule_registry": case_type_rule_registry, + "case_type_rule_registry_sha256": digest(release_raws[CASE_TYPE_RULE_REGISTRY_REL]), + "schema_store": schema_store, + "frozen_source_rows": sorted(frozen_source_rows, key=lambda row: (row["path"], row["sha256"])), + "input_closure_rows": input_closure_rows, + "input_snapshot_preimage": input_snapshot_preimage, + "input_snapshot_digest": digest(input_snapshot_preimage), + } + + + def flatten(parts: Iterable[Mapping[str, Any]], keys: Sequence[str]) -> list[Any]: + result: list[Any] = [] + for part in parts: + value: Any = None + for key in keys: + if key in part: + value = part[key] + break + if value is None: + continue + if not isinstance(value, list): + raise S240Error("PART_PAYLOAD_TYPE", f"part payload must be an array: {keys[0]}") + result.extend(value) + return result + + + def unique_sorted(rows: Iterable[Any], id_keys: Sequence[str], *, code: str) -> list[dict[str, Any]]: + by_id: dict[str, dict[str, Any]] = {} + for value in rows: + row = require_object(value, code=code) + row_id: Any = None + for key in id_keys: + if key in row: + row_id = row[key] + break + row_id = require_ident(row_id, code=code) + if row_id in by_id and canonical_bytes(by_id[row_id]) != canonical_bytes(row): + raise S240Error("IMMUTABLE_ID_CONFLICT", f"conflicting immutable row: {row_id}") + by_id[row_id] = row + return [by_id[key] for key in sorted(by_id)] + + + def provenance_source_refs(rows: Any) -> list[str]: + refs: set[str] = set() + for row in rows if isinstance(rows, list) else []: + if not isinstance(row, dict): + continue + for key, value in row.items(): + if key.endswith("_ref") and isinstance(value, str) and value: + refs.add(value) + elif key.endswith("_refs") and isinstance(value, list): + refs.update(item for item in value if isinstance(item, str) and item) + elif key == "locator" and isinstance(value, dict): + refs.add("locator:" + digest(value)) + return sorted(refs) + + + def slot_values(text_or_slots: Mapping[str, Any]) -> dict[str, str | list[str]]: + rows = require_list(text_or_slots.get("slots"), code="ATOM_TYPED_SLOTS") + values: dict[str, str | list[str]] = {} + for value in rows: + row = require_object(value, code="ATOM_TYPED_SLOT") + slot_id = require_ident(row.get("slot_id"), code="ATOM_SLOT_ID") + if slot_id in values: + raise S240Error("ATOM_SLOT_DUPLICATE", f"duplicate typed slot: {slot_id}") + raw = row.get("value") + if raw is None: + continue + if not isinstance(raw, str): + raise S240Error("ATOM_SLOT_VALUE", "typed slot value must be string or null") + rendered = nfc(raw) + if any(token in rendered for token in ("{{", "}}", "\x00")): + raise S240Error("ATOM_SLOT_INJECTION", "typed slot contains forbidden token") + values[slot_id] = rendered + return values + + + def select_renderer_branch( + descriptor: Mapping[str, Any], branch_id: str, *, allow_fixture: bool, + ) -> Mapping[str, Any]: + status = descriptor.get("status") + eligible = descriptor.get("execution_eligible") is True + if not eligible or status not in ({"APPROVED_LEGAL_CONTENT", "STRUCTURAL_FIXTURE_ONLY"} if allow_fixture else {"APPROVED_LEGAL_CONTENT"}): + raise S240Error("RENDERER_NOT_ELIGIBLE", "frozen renderer is not approved/execution-eligible") + branches = require_list(descriptor.get("branch_rows"), code="RENDER_BRANCH_ROWS") + matches = [row for row in branches if isinstance(row, dict) and row.get("branch_id") == branch_id] + if len(matches) != 1: + raise S240Error("RENDER_BRANCH_CARDINALITY", "template_branch_id must match exactly one frozen branch") + branch = matches[0] + if branch.get("approval_status") != "APPROVED": + raise S240Error("RENDER_BRANCH_NOT_APPROVED", "selected branch is not approved") + return branch + + + def render_segments( + descriptor: Mapping[str, Any], branch: Mapping[str, Any], slots: Mapping[str, Any], + ) -> tuple[str, str]: + definitions = { + row.get("name"): row + for row in descriptor.get("typed_slot_contract", {}).get("slot_definitions", []) + if isinstance(row, dict) and isinstance(row.get("name"), str) + } + if set(slots) - set(definitions): + raise S240Error("RENDERER_UNKNOWN_SLOT", "atom supplies a slot outside frozen descriptor") + for name, definition in definitions.items(): + if definition.get("cardinality") in {"EXACTLY_ONE", "ONE_OR_MORE"} and name not in slots: + raise S240Error("RENDERER_REQUIRED_SLOT_MISSING", f"missing frozen slot: {name}") + segments = require_list(branch.get("segments"), code="RENDER_SEGMENTS") + + def render_a() -> str: + pieces: list[str] = [] + for segment in segments: + row = require_object(segment, code="RENDER_SEGMENT") + if row.get("kind") == "LITERAL" and set(row) == {"kind", "value"} and isinstance(row.get("value"), str): + pieces.append(nfc(row["value"])) + elif row.get("kind") == "SLOT" and set(row) == {"kind", "name", "escape"}: + name = row.get("name") + if name not in slots: + if definitions.get(name, {}).get("cardinality") == "ZERO_OR_ONE": + continue + raise S240Error("RENDERER_REQUIRED_SLOT_MISSING", f"missing segment slot: {name}") + value = slots[name] + pieces.append(", ".join(value) if isinstance(value, list) else str(value)) + else: + raise S240Error("RENDER_SEGMENT_SHAPE", "closed renderer segment is invalid") + return nfc("".join(pieces)) + + primary = render_a() + independent_segments = [dict(row) for row in segments] + independent_slots = {key: (list(value) if isinstance(value, list) else value) for key, value in slots.items()} + independent = "".join( + nfc(str(row["value"])) if row.get("kind") == "LITERAL" + else ( + ", ".join(independent_slots[row["name"]]) + if isinstance(independent_slots.get(row["name"]), list) + else str(independent_slots.get(row["name"], "")) + ) + for row in independent_segments + ) + independent = nfc(independent) + if primary.encode("utf-8") != independent.encode("utf-8"): + raise S240Error("RENDERER_INDEPENDENT_RERENDER_MISMATCH", "independent renderer bytes differ") + if PLACEHOLDER.search(primary): + raise S240Error("RENDER_DANGLING_SLOT", "closed renderer left a template token") + return primary, independent + + + def reduce_and_render(inputs: Mapping[str, Any], request: Mapping[str, Any]) -> dict[str, Any]: + parts = inputs["parts"] + atoms = unique_sorted( + flatten(parts["DRAFT_PART"], ("canonical_atoms",)), + ("atom_id",), code="DRAFT_ATOM_ID", + ) + atom_by_id: dict[str, dict[str, Any]] = {} + source_plan_hashes: set[str] = set() + for part in parts["DRAFT_PART"]: + source_plan_hashes.add(require_hex(part.get("source_plan_sha256"), code="DRAFT_SOURCE_PLAN_HASH")) + for atom in part["canonical_atoms"]: + require_self_hash(atom, "canonical_atom_sha256", code="CANONICAL_ATOM_SELF_HASH") + if "legal_admission" in atom or "closed_renderer" in atom: + raise S240Error("ATOM_SELF_ASSERTED_LEGAL_ADMISSION", "atom may not carry legal admission or renderer bytes") + atom_by_id[atom["atom_id"]] = atom + base_ledger = require_object( + inputs["ingress_documents"].get("review/issue_ledger.base.json"), + code="BASE_ISSUE_LEDGER", + ) + plan_ledger = require_object( + inputs["plan_documents"].get("plan/issue_ledger.plan.json"), + code="PLAN_ISSUE_LEDGER", + ) + base_issues = [dict(row) for row in require_list(base_ledger.get("issues"), code="BASE_ISSUES")] + base_issue_ids = sorted(str(row.get("issue_id")) for row in base_issues) + if ( + len(base_issue_ids) != len(set(base_issue_ids)) + or plan_ledger.get("preserved_base_issue_ids") != base_issue_ids + or plan_ledger.get("base_ledger_sha256") != digest(inputs["ingress_raws"]["review/issue_ledger.base.json"]) + ): + raise S240Error("ISSUE_LEDGER_BASE_CONSERVATION", "S2_20 did not preserve the exact S2_00 issue universe") + issues: list[dict[str, Any]] = list(base_issues) + issue_source_keys: list[str] = [f"S2_00:{value}" for value in base_issue_ids] + for row in require_list(plan_ledger.get("plan_issues"), code="PLAN_ISSUES"): + row = require_object(row, code="PLAN_ISSUE") + source_id = require_ident(row.get("issue_id"), code="PLAN_ISSUE_ID") + issue_id = source_id if re.fullmatch(r"ISS-[A-Fa-f0-9]{16,64}", source_id) else stable_id("ISS", "S2_20", source_id) + code = require_ident(row.get("code"), code="PLAN_ISSUE_CODE") + scope_ref = require_ident(row.get("scope_ref"), code="PLAN_ISSUE_SCOPE") + issues.append({ + "issue_id": issue_id, "issue_code": code, + "technical_severity": "REVIEW", "review_partition": "UNRESOLVED", + "impact_scope": "REVIEW_ITEM", "scope_refs": [scope_ref], + "source_contract_row_refs": [f"S2_20:{source_id}"], + "reason_codes": [code], "downstream_allowed_actions": ["REVIEW"], + "source_refs": [f"S2_20:{source_id}"], "status": "CARRIED_FORWARD", + }) + issue_source_keys.append(f"S2_20:{source_id}") + s210_impact = {"RUN_WIDE": "GLOBAL", "CLUSTER_LOCAL": "CLUSTER", "OPTION_ONLY": "REVIEW_ITEM"} + s210_severity = {"INFO": "INFO", "WARNING": "REVIEW", "BLOCKING": "BLOCK"} + for cluster_id, part in sorted(inputs["s210_handoff"]["issue_parts"].items()): + for row in require_list(part.get("issues"), code="S210_ISSUES"): + row = require_object(row, code="S210_ISSUE") + source_id = require_ident(row.get("issue_id"), code="S210_ISSUE_ID") + issue_id = stable_id("ISS", "S2_10", cluster_id, source_id) + issue_code = require_ident(row.get("issue_code"), code="S210_ISSUE_CODE") + source_refs = sorted(set(str(value) for value in row.get("source_refs", []) if isinstance(value, str) and value)) + issues.append({ + "issue_id": issue_id, "issue_code": issue_code, + "technical_severity": s210_severity.get(str(row.get("severity")), "REVIEW"), + "review_partition": "SUPPORTED" if row.get("status") == "RESOLVED" else "UNRESOLVED", + "impact_scope": s210_impact.get(str(row.get("impact_scope")), "REVIEW_ITEM"), + "scope_refs": [cluster_id], "source_contract_row_refs": [f"S2_10:{source_id}"], + "reason_codes": sorted(set([issue_code, *[str(value) for value in row.get("resolution_condition_codes", [])]])), + "downstream_allowed_actions": ["REVIEW"], + "source_refs": source_refs or [f"S2_10:{cluster_id}"], + "status": "CARRIED_FORWARD", + "upstream_review_key": source_id, "raw_item_sha256": digest(row), + }) + issue_source_keys.append(f"S2_10:{cluster_id}:{source_id}") + for part in parts["ISSUE_PATCH"]: + for code in sorted(set(part.get("review_flags", [])) | set(part.get("missing_inputs", []))): + issues.append({ + "issue_id": stable_id("ISS", part["claim_group_id"], code), + "issue_code": str(code), "technical_severity": "REVIEW", + "review_partition": "UNRESOLVED", "impact_scope": "REVIEW_ITEM", + "scope_refs": [part["claim_group_id"]], + "source_contract_row_refs": [f"S2_30:{part['claim_group_id']}"], + "reason_codes": [str(code)], + "downstream_allowed_actions": ["REVIEW"], + "source_refs": [f"S2_30:{part['claim_group_id']}"], "status": "OPEN", + }) + issue_source_keys.append(f"S2_30:{part['claim_group_id']}:CODE:{code}") + for row in part.get("adverse_fact_rows", []): + adverse_digest = digest(row) + issues.append({ + "issue_id": stable_id("ISS", part["claim_group_id"], adverse_digest), + "issue_code": "ADVERSE_FACT_PRESERVED", "technical_severity": "REVIEW", + "review_partition": "CONDITIONAL", "impact_scope": "FACT", + "scope_refs": [part["claim_group_id"]], + "source_contract_row_refs": [f"S2_30:{part['claim_group_id']}"], + "reason_codes": ["ADVERSE_FACT_PRESERVED"], + "downstream_allowed_actions": ["REVIEW"], + "source_refs": provenance_source_refs([row]) or [f"S2_30:{part['claim_group_id']}"], + "status": "OPEN", + }) + issue_source_keys.append(f"S2_30:{part['claim_group_id']}:ADVERSE:{adverse_digest}") + issues = unique_sorted(issues, ("issue_id",), code="ISSUE_ID") if issues else [] + worknotes: list[dict[str, Any]] = [] + for part in parts["WORKNOTE_PART"]: + for atom_id in part.get("worknote_atom_ids", []): + atom = atom_by_id.get(atom_id) + if atom is None or atom.get("output_section") != "worknote_only": + raise S240Error("WORKNOTE_ATOM_REF", "worknote part references a missing/non-worknote atom") + text = atom.get("text_or_slots", {}).get("draft_text") + if not isinstance(text, str) or not text: + text = canonical_bytes(atom.get("text_or_slots", {}).get("slots", [])).decode("utf-8").strip() + worknotes.append({ + "worknote_id": atom_id, "text": nfc(text), + "source_refs": provenance_source_refs(atom.get("provenance")) or [f"ATOM:{atom_id}"], + }) + assumptions: list[dict[str, Any]] = [] + assumption_source_keys: list[str] = [] + assumption_impact = {"RUN_WIDE": "GLOBAL", "CLUSTER_LOCAL": "CLAIM_GROUP", "OPTION_ONLY": "ATOMIC_CLAIM"} + for cluster_id, part in sorted(inputs["s210_handoff"]["assumption_parts"].items()): + for row in require_list(part.get("assumptions"), code="S210_ASSUMPTIONS"): + row = require_object(row, code="S210_ASSUMPTION") + local_ref = require_ident(row.get("assumption_local_ref"), code="S210_ASSUMPTION_REF") + basis = sorted(set(str(value) for value in row.get("basis_refs", []) if isinstance(value, str) and value)) + assumptions.append({ + "assumption_id": stable_id("ASM", cluster_id, local_ref), + "text": require_text(row.get("statement"), code="S210_ASSUMPTION_TEXT"), + "status": "OPEN", "source_refs": basis or [f"S2_10:{cluster_id}"], + "impact_scope": assumption_impact.get(str(row.get("impact_scope")), "CLAIM_GROUP"), + }) + assumption_source_keys.append(f"S2_10:{cluster_id}:{local_ref}") + assumptions = unique_sorted(assumptions, ("assumption_id",), code="ASSUMPTION_ID") if assumptions else [] + usage: list[dict[str, Any]] = [] + usage_source_keys: list[str] = [] + for cluster_id, part in sorted(inputs["s210_handoff"]["usage_parts"].items()): + usage.append({ + "source_stage": "S2_10", "source_scope_id": cluster_id, + "source_part_sha256": part["part_sha256"], "payload": dict(part), + }) + usage_source_keys.append(f"S2_10:{cluster_id}:{part['part_sha256']}") + for part in sorted(parts["USAGE_PART"], key=lambda row: row["claim_group_id"]): + usage.append({ + "source_stage": "S2_30", "source_scope_id": part["claim_group_id"], + "source_part_sha256": part["part_sha256"], "payload": dict(part), + }) + usage_source_keys.append(f"S2_30:{part['claim_group_id']}:{part['part_sha256']}") + relief_rows: list[dict[str, Any]] = [] + cause_rows: list[dict[str, Any]] = [] + render_errors: list[str] = [] + render_absences: list[str] = [] + rerender_equal = True + group_contracts = { + group_id: require_object(group_slice.get("claim_group"), code="GROUP_CONTRACT") + for group_id, group_slice in inputs["group_slices"].items() + } + for atom in atoms: + if atom.get("drafting_disposition") == "WORKNOTE_ONLY" or atom.get("output_section") == "worknote_only": + continue + text_slots = require_object(atom.get("text_or_slots"), code="ATOM_TEXT_OR_SLOTS") + renderer_id = require_ident(text_slots.get("renderer_id"), code="ATOM_RENDERER_ID") + branch_id = require_ident(text_slots.get("template_branch_id"), code="ATOM_BRANCH_ID") + descriptor = inputs["renderer_descriptors"].get(renderer_id) + rendered: str | None = None + try: + if descriptor is None: + raise S240Error("RENDERER_DESCRIPTOR_MISSING", "S2_20 did not freeze selected renderer") + branch = select_renderer_branch(descriptor, branch_id, allow_fixture=request["compile_mode"] == "STRUCTURAL_FIXTURE") + rendered, independent = render_segments(descriptor, branch, slot_values(text_slots)) + rerender_equal = rerender_equal and rendered.encode("utf-8") == independent.encode("utf-8") + except S240Error as exc: + if exc.code in {"RENDERER_NOT_ELIGIBLE", "RENDERER_DESCRIPTOR_MISSING", "RENDER_BRANCH_NOT_APPROVED"}: + render_absences.append(f"{atom['atom_id']}:{exc.code}") + else: + render_errors.append(f"{atom['atom_id']}:{exc.code}") + section = atom.get("output_section") + group_contract = require_object(group_contracts.get(atom["claim_group_id"]), code="ATOM_GROUP_CONTRACT") + typed_group_projection = { + "party_refs": group_contract.get("party_refs", []), + "object_refs": group_contract.get("object_refs", []), + "amount_slots": group_contract.get("amount_slots", []), + "period_slots": group_contract.get("period_slots", []), + "calculation_receipt_ids": group_contract.get("calculation_receipt_ids", []), + "counter_performance_refs": group_contract.get("counter_performance_refs", []), + } + if section in {"relief_main", "relief_cost", "relief_provisional_execution"}: + if rendered is not None: + relief_rows.append({ + "atom_id": atom["atom_id"], "atomic_claim_id": atom["atomic_claim_id"], + "claim_group_id": atom["claim_group_id"], "output_section": section, + "renderer_id": renderer_id, "branch_id": branch_id, "text": rendered, + **typed_group_projection, + }) + elif section.startswith("cause_") or section == "procedural_declaration": + text = text_slots.get("draft_text") if text_slots.get("rendering_mode") == "REVIEW_TEXT_WITH_SLOTS" else rendered + if isinstance(text, str) and text and not PLACEHOLDER.search(text): + cause_rows.append({ + "atom_id": atom["atom_id"], "atomic_claim_id": atom["atomic_claim_id"], + "claim_group_id": atom["claim_group_id"], "output_section": section, + "text": nfc(text), "source_refs": provenance_source_refs(atom.get("provenance")), + **typed_group_projection, + }) + elif rendered is None: + render_absences.append(f"{atom['atom_id']}:CAUSE_TEXT_UNAVAILABLE") + relief_rows.sort(key=lambda row: (row["claim_group_id"], row["atomic_claim_id"], row["output_section"], row["atom_id"])) + cause_rows.sort(key=lambda row: (row["claim_group_id"], row["atomic_claim_id"], row["output_section"], row["atom_id"])) + legal_assets_admitted = bool(atoms) and not render_errors and not render_absences and all( + descriptor.get("status") == "APPROVED_LEGAL_CONTENT" and descriptor.get("execution_eligible") is True + for descriptor in inputs["renderer_descriptors"].values() + ) + clean_render_allowed = request["compile_mode"] in {"SUBSET_CANARY", "PRODUCTION"} and legal_assets_admitted + relief = "\n".join(f"{index}. {row['text']}" for index, row in enumerate(relief_rows, 1)) if clean_render_allowed else "" + cause = "\n\n".join(row["text"] for row in cause_rows) if clean_render_allowed else "" + pleading = f"# 청구취지\n\n{relief}\n\n# 청구원인\n\n{cause}" if clean_render_allowed else "" + return { + "atoms": atoms, "issues": issues, "worknotes": worknotes, "usage": usage, + "assumptions": assumptions, + "conservation": { + "issue_source_keys": sorted(issue_source_keys), + "issue_ids": sorted(str(row["issue_id"]) for row in issues), + "assumption_source_keys": sorted(assumption_source_keys), + "assumption_ids": sorted(str(row["assumption_id"]) for row in assumptions), + "usage_source_keys": sorted(usage_source_keys), + }, + "relief_rows": relief_rows, "cause_rows": cause_rows, + "relief": relief, "cause": cause, "pleading": pleading, + "render_errors": sorted(set(render_errors)), "render_absences": sorted(set(render_absences)), + "rerender_equal": rerender_equal, "clean_render_allowed": clean_render_allowed, + "legal_assets_admitted": legal_assets_admitted, + "source_plan_hashes": sorted(source_plan_hashes), + } + + + def invariant_result( + invariant_id: str, observed: bool | None, reason: str, + *, source_refs: Sequence[str] = (), incomplete: bool = False, + ) -> dict[str, Any]: + status = "UNEVALUABLE" if observed is None else ("PASS" if observed else "FAIL") + scope = "OK" if status == "PASS" else ("INCOMPLETE" if incomplete else "REVIEW_REQUIRED") + return { + "invariant_id": invariant_id, "evaluation_status": status, + "finding_ids": [] if status == "PASS" else [stable_id("F40", invariant_id, reason)], + "impact_scope": scope, "source_refs": sorted(set(source_refs)), + "expected": True, "observed": observed, "reason_codes": [reason], + "validator_algorithm_id": f"{ALGORITHM_VERSION}::{invariant_id}", + } + + + def invariant_results(inputs: Mapping[str, Any], reduced: Mapping[str, Any], request: Mapping[str, Any]) -> list[dict[str, Any]]: + atoms = reduced["atoms"] + relief_claims = {row["atomic_claim_id"] for row in reduced["relief_rows"]} + cause_claims = {row["atomic_claim_id"] for row in reduced["cause_rows"]} + slot_rows = [row for atom in atoms for row in atom.get("text_or_slots", {}).get("slots", []) if isinstance(row, dict)] + slot_ids = [(atom["atom_id"], row.get("slot_id")) for atom in atoms for row in atom.get("text_or_slots", {}).get("slots", []) if isinstance(row, dict)] + legal_provenance = [row for atom in atoms for row in atom.get("provenance", []) if isinstance(row, dict) and row.get("proposition_kind") == "LEGAL_PROPOSITION"] + defense_rows = [row for atom in atoms for row in atom.get("provenance", []) if isinstance(row, dict) and "REBUTTAL" in str(row.get("proposition_kind", ""))] + binding_rows = [row for pack in inputs["rule_packs"].values() for row in pack.get("binding_rows", []) if isinstance(row, dict)] + binding_by_claim: dict[str, list[dict[str, Any]]] = {} + for row in binding_rows: + binding_by_claim.setdefault(str(row.get("atomic_claim_id")), []).append(row) + selected_claims = {str(row.get("atomic_claim_id")) for row in binding_rows if row.get("case_type_binding_status") == "BOUND" and row.get("sub_rule_binding_status") == "BOUND"} + all_claims = {str(atom.get("atomic_claim_id")) for atom in atoms} + calculation_tokens = [row for row in slot_rows if row.get("value_kind") == "CALCULATION_TOKEN"] + calc_observed: bool | None = None if not calculation_tokens else bool(inputs["calculation_receipts"]) + provenance_complete = all(bool(provenance_source_refs(atom.get("provenance"))) for atom in atoms) + option_ids: list[str] = [] + partition_ids: list[str] = [] + option_evaluable = False + for group_slice in inputs["group_slices"].values(): + claim_group = group_slice.get("claim_group", {}) + if isinstance(claim_group, dict): + ids = claim_group.get("claim_option_ids", claim_group.get("option_ids", [])) + if isinstance(ids, list): + option_ids.extend(str(item) for item in ids) + partition = claim_group.get("option_partition", {}) + if isinstance(partition, dict): + option_evaluable = True + for name in ("selected", "alternative", "excluded", "deferred"): + values = partition.get(name, []) + if isinstance(values, list): + partition_ids.extend(str(item) for item in values) + option_ok = None if not option_evaluable else len(partition_ids) == len(set(partition_ids)) and set(partition_ids) == set(option_ids) + exhibit_rows = inputs["exhibit_register"].get("rows") + exhibit_ok = None if not isinstance(exhibit_rows, list) else all(isinstance(row, dict) for row in exhibit_rows) + authority_ok = None if not legal_provenance else all(row.get("authority_id") and row.get("locator") for row in legal_provenance) + closure_rows = inputs.get("input_closure_rows", []) + expected_closure = { + "ingress/ingress_status.json": ("stage2_s2_00_ingress_status.v1", "stage2_s2_00_ingress_status.v1.1", "S2_00"), + "map_s2_10/s2_10_publish_status.json": ("stage2_s2_10_publish_status.v2", "S2_10_NATIVE_RESULT_ADAPTER"), + "plan/plan_publish_status.json": ("stage2_plan_publish_status.v1", "S2_20"), + "map_s2_30/s2_30_publish_status.json": ("stage2_s2_30_publish_status.v1", "S2_30"), + "map_s2_30/artifact_manifest.json": ("stage2_s2_30_part_manifest_core.v1", "S2_30"), + } + closure_by_path = {str(row.get("path")): row for row in closure_rows if isinstance(row, dict)} + v01 = ( + len(closure_rows) == len(closure_by_path) + and set(expected_closure).issubset(closure_by_path) + and all( + row.get("schema_valid") is True + and row.get("hash_match") is True + and row.get("sha256") == row.get("expected_sha256") + and HEX64.fullmatch(str(row.get("sha256", ""))) + and isinstance(row.get("schema_ref"), str) + for row in closure_rows if isinstance(row, dict) + ) + ) + if v01: + for path, allowed in expected_closure.items(): + row = closure_by_path[path] + version_allowed = allowed[:-1] + producer = allowed[-1] + if not ( + row.get("schema_version") in version_allowed + and row.get("producer_id") == producer + and row.get("schema_valid") is True + and row.get("hash_match") is True + and row.get("sha256") == row.get("expected_sha256") + and HEX64.fullmatch(str(row.get("sha256", ""))) + and isinstance(row.get("schema_ref"), str) + ): + v01 = False + break + atom_groups = {str(atom.get("claim_group_id")) for atom in atoms} + source_atoms = [row for part in inputs["parts"]["DRAFT_PART"] for row in part.get("canonical_atoms", [])] + source_atom_ids = [str(row.get("atom_id")) for row in source_atoms if isinstance(row, dict)] + reduced_atom_ids = [str(row.get("atom_id")) for row in atoms] + source_worknote_ids = sorted( + str(atom_id) for part in inputs["parts"]["WORKNOTE_PART"] + for atom_id in part.get("worknote_atom_ids", []) + ) + conservation = require_object(reduced.get("conservation"), code="V02_CONSERVATION") + issue_source_keys = require_list(conservation.get("issue_source_keys"), code="V02_ISSUE_KEYS") + assumption_source_keys = require_list(conservation.get("assumption_source_keys"), code="V02_ASSUMPTION_KEYS") + usage_source_keys = require_list(conservation.get("usage_source_keys"), code="V02_USAGE_KEYS") + v02 = ( + bool(atoms) + and atom_groups == set(inputs["group_ids"]) + and len(source_atom_ids) == len(set(source_atom_ids)) + and sorted(source_atom_ids) == sorted(reduced_atom_ids) + and len(issue_source_keys) == len(set(issue_source_keys)) == len(reduced["issues"]) + and len(assumption_source_keys) == len(set(assumption_source_keys)) == len(reduced["assumptions"]) + and len(usage_source_keys) == len(set(usage_source_keys)) == len(reduced["usage"]) + and source_worknote_ids == sorted(str(row.get("worknote_id")) for row in reduced["worknotes"]) + and inputs["s210_handoff"]["cluster_ids"] == inputs["ingress"]["executable_cluster_ids"] + ) + v03 = all(row.get("slot_id") and row.get("namespace_owner") and row.get("domain_id") for row in slot_rows) if slot_rows else None + v04 = all( + row.get("opposing_fact_id") and row.get("rebuttal_id") and row.get("evidence_refs") + and row.get("polarity") and row.get("presentation_status") + for row in defense_rows + ) if defense_rows else None + v05 = all( + isinstance(group_slice.get("claim_group"), dict) + and group_slice.get("claim_group", {}).get("dependency_wave_id") + and group_slice.get("claim_group", {}).get("relation_consistency_status") == "PASS" + for group_slice in inputs["group_slices"].values() + ) if inputs["group_slices"] else None + v07 = all( + token.get("calculation_receipt_id") in inputs["calculation_receipts"] + and token.get("operand_digest") == inputs["calculation_receipts"][token["calculation_receipt_id"]].get("operand_digest") + and inputs["calculation_receipts"][token["calculation_receipt_id"]].get("missing_law_values") in ([], None) + for token in calculation_tokens + ) if calculation_tokens else None + recovery_keys = [(atom.get("recovery_object_id"), atom.get("recovery_scope")) for atom in atoms if atom.get("recovery_object_id")] + v08 = len(recovery_keys) == len(set(recovery_keys)) if recovery_keys else None + canonical_plan = inputs["plan_documents"].get("plan/canonical_relief_plan.json") + canonical_plan_raw = inputs["plan_raw_by_path"].get("plan/canonical_relief_plan.json") + plan_claims = { + str(row.get("atomic_claim_id")): row + for row in (canonical_plan.get("atomic_claims", []) if isinstance(canonical_plan, dict) else []) + if isinstance(row, dict) + } + plan_hash = digest(canonical_plan_raw) if isinstance(canonical_plan_raw, bytes) else None + v09 = all( + atom.get("source_plan_sha256") == plan_hash + and atom.get("atomic_claim_id") in plan_claims + and plan_claims[atom["atomic_claim_id"]].get("claim_group_id") == atom.get("claim_group_id") + and atom.get("claim_option_id") in plan_claims[atom["atomic_claim_id"]].get("source_claim_option_ids", []) + and len(binding_by_claim.get(str(atom.get("atomic_claim_id")), [])) == 1 + for atom in atoms + ) if atoms else None + v10 = (not reduced["render_errors"] and not reduced["render_absences"] and + all(row.get("output_section") and row.get("text") for row in reduced["relief_rows"] + reduced["cause_rows"])) if atoms else None + def relation_signature(row: Mapping[str, Any]) -> tuple[str, str, str, str, str, str, str]: + return ( + str(row.get("atomic_claim_id")), digest(row.get("party_refs", [])), + digest(row.get("object_refs", [])), digest(row.get("amount_slots", [])), + digest(row.get("period_slots", [])), digest(row.get("calculation_receipt_ids", [])), + digest(row.get("counter_performance_refs", [])), + ) + relief_relation = {relation_signature(row) for row in reduced["relief_rows"]} + cause_relation = {relation_signature(row) for row in reduced["cause_rows"]} + v11 = relief_relation == cause_relation if relief_relation or cause_relation else None + v12 = all(pack.get("corpus_release_sha256") and pack.get("slot_crosswalk_status") == "PASS" and pack.get("injection_isolation_status") == "PASS" for pack in inputs["plan_documents"].values() if isinstance(pack, dict) and pack.get("schema_version") == "stage2_requirement_fact_pack.v1") or None + v13 = all(row.get("authority_id") and row.get("locator") and row.get("temporal_scope_status") == "PASS" and row.get("negative_treatment_status") == "CLEAR" for row in legal_provenance) if legal_provenance else None + def contains_downstream_key(value: Any) -> bool: + forbidden_keys = { + "candidate_content_digest", "review_subject_digest", "review_receipt_sha256s", + "stage2_package_sha256", "commit_intent_sha256", + "commit_result_sha256", "status_event_sha256", + } + if isinstance(value, dict): + return any(key in forbidden_keys or contains_downstream_key(item) for key, item in value.items()) + if isinstance(value, list): + return any(contains_downstream_key(item) for item in value) + return False + v14 = not contains_downstream_key({ + "parts": inputs.get("parts"), "group_slices": inputs.get("group_slices"), + "rule_packs": inputs.get("rule_packs"), "plan_documents": inputs.get("plan_documents"), + "ingress_documents": inputs.get("ingress_documents"), + "s210_handoff": inputs.get("s210_handoff"), + }) and inputs.get("frozen_source_rows") == sorted( + inputs.get("frozen_source_rows", []), key=lambda row: (row["path"], row["sha256"]) + ) if atoms else None + v15 = all(atom.get("provenance") and all(row.get("source_ref") or row.get("source_refs") for row in atom.get("provenance", []) if isinstance(row, dict)) for atom in atoms) if atoms else None + v17 = all(row.get("party_id") and row.get("object_id") and row.get("exhibit_id") and row.get("party_title") for row in exhibit_rows) if isinstance(exhibit_rows, list) and exhibit_rows else None + renderer_observed: bool | None = ( + False if reduced["render_errors"] else + (None if reduced["render_absences"] else bool(reduced["relief_rows"] or reduced["cause_rows"]) and reduced["rerender_equal"]) + ) + checks = { + "V01": invariant_result("V01", v01, "BOUND_INPUT_HASH_SCHEMA_PRODUCER", incomplete=True), + "V02": invariant_result("V02", v02, "REVIEW_UNIVERSE_CONSERVED", incomplete=True), + "V03": invariant_result("V03", v03, "DOMAIN_SLOT_NAMESPACE_BOUND"), + "V04": invariant_result("V04", v04, "DEFENSE_REBUTTAL_PROVENANCE_BOUND"), + "V05": invariant_result("V05", v05, "DEPENDENCY_WAVE_BOUND"), + "V06": invariant_result("V06", all(len(binding_by_claim.get(claim, [])) == 1 and claim in selected_claims for claim in all_claims) if all_claims else None, "CASE_TYPE_SUB_RULE_EXACT"), + "V07": invariant_result("V07", v07, "CALCULATION_RECEIPT_BOUND"), + "V08": invariant_result("V08", v08, "DUPLICATE_RECOVERY_ABSENT"), + "V09": invariant_result("V09", v09, "RELIEF_PLAN_MATCH"), + "V10": invariant_result("V10", v10, "DOCUMENT_ORDER_TEMPLATE_MATCH"), + "V11": invariant_result("V11", v11, "RELIEF_CAUSE_CROSSMATCH"), + "V12": invariant_result("V12", v12, "CORPUS_BOUND"), + "V13": invariant_result("V13", v13, "AUTHORITY_TEMPORAL_BOUND"), + "V14": invariant_result("V14", v14, "NON_CYCLIC_DIGEST_GRAPH"), + "V15": invariant_result("V15", v15, "PROVENANCE_COMPLETE"), + "V16": invariant_result("V16", option_ok, "OPTION_PARTITION_EXACT"), + "V17": invariant_result("V17", v17, "PARTY_OBJECT_EXHIBIT_COMPLETE"), + "V18": invariant_result("V18", renderer_observed, "CLOSED_RENDER_AND_RERENDER_EQUAL"), + } + return [checks[invariant_id] for invariant_id in V_IDS] + + + def review_request_basis( + inputs: Mapping[str, Any], + validation: Sequence[Mapping[str, Any]], + review_policy_contract: Mapping[str, Any], + parent_release_sha256: str, + ) -> dict[str, Any]: + review_policies = [ + value for value in inputs.get("frozen_assets", {}).values() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + if len(review_policies) > 1: + raise S240Error("REVIEW_POLICY_CARDINALITY", "multiple frozen review policies") + policy = review_policies[0] if review_policies else None + policy_sha256 = digest(policy) if policy is not None else digest({"status": "MISSING_REVIEW_POLICY"}) + corpus_hashes = sorted({ + str(value.get("corpus_release_sha256")) for value in inputs.get("plan_documents", {}).values() + if isinstance(value, dict) and value.get("schema_version") == "stage2_requirement_fact_pack.v1" + }) + release_sha256s = { + "parent": parent_release_sha256, + "authority": require_hex(inputs.get("authority_release_sha256"), code="REVIEW_AUTHORITY_RELEASE_HASH"), + "corpus": corpus_hashes[0] if len(corpus_hashes) == 1 and HEX64.fullmatch(corpus_hashes[0]) else digest(corpus_hashes), + "case_type_coverage": require_hex(inputs.get("case_type_coverage_sha256"), code="REVIEW_CASE_TYPE_COVERAGE_HASH"), + } + return { + "schema_version": "stage2_s2_40_review_request_basis.v1", + "required_receipt_types": review_policy_contract["required_receipt_types"], + "scope_ids": inputs["group_ids"], + "finding_ids": sorted(row["finding_ids"][0] for row in validation if row["finding_ids"]), + "policy_version": str(policy.get("schema_version")) if policy is not None else "MISSING_REVIEW_POLICY", + "policy_sha256": policy_sha256, + "reviewer_role": TRUSTED_REVIEW_ROLE, + "reviewer_qualification": TRUSTED_REVIEW_QUALIFICATION, + "release_snapshot_sha256s": release_sha256s, + } + + + def review_subject( + candidate_digest: str, + lawyer_review_packet_core_sha256: str, + validation_envelope_core_sha256: str, + basis: Mapping[str, Any], + ) -> dict[str, Any]: + cores: list[dict[str, Any]] = [] + bindings: list[dict[str, str]] = [] + for receipt_type in require_list(basis.get("required_receipt_types"), code="REVIEW_REQUIRED_TYPES"): + core = { + "candidate_content_digest": candidate_digest, "receipt_type": receipt_type, + "scope_ids": basis["scope_ids"], "finding_ids": basis["finding_ids"], + "policy_version": basis["policy_version"], "policy_sha256": basis["policy_sha256"], + "reviewer_role": basis["reviewer_role"], + "reviewer_qualification": basis["reviewer_qualification"], + "release_snapshot_sha256s": basis["release_snapshot_sha256s"], + } + cores.append(core) + bindings.append({ + "receipt_type": str(receipt_type), + "review_request_core_sha256": digest(core), + }) + bindings.sort(key=lambda row: row["receipt_type"]) + if len(bindings) != len({row["receipt_type"] for row in bindings}): + raise S240Error("REVIEW_REQUEST_TYPE_DUPLICATE", "review request receipt types must be unique") + subject_core = { + "schema_version": "stage2_s2_40_review_subject.v1", + "domain_separator": "STAGE2_S2_40_REVIEW_SUBJECT_V1", + "candidate_content_digest": candidate_digest, + "review_request_core_bindings": bindings, + "lawyer_review_packet_core_sha256": lawyer_review_packet_core_sha256, + "validation_envelope_core_sha256": validation_envelope_core_sha256, + "finding_ids": basis["finding_ids"], "scope_ids": basis["scope_ids"], + "review_policy_sha256": basis["policy_sha256"], + "release_sha256s": basis["release_snapshot_sha256s"], + } + subject = digest(subject_core) + core_by_type = {str(core["receipt_type"]): core for core in cores} + requests = [ + { + "request_id": stable_id( + "RR40", "STAGE2_S2_40_REVIEW_REQUEST_V1", subject, + binding["receipt_type"], *sorted(basis["scope_ids"]), + ), + "receipt_type": binding["receipt_type"], + "core": core_by_type[binding["receipt_type"]], + "core_sha256": binding["review_request_core_sha256"], + "review_subject_digest": subject, + } + for binding in bindings + ] + return { + "review_subject_digest": subject, + "subject": {**subject_core, "review_subject_digest": subject}, + "bindings": bindings, "requests": requests, + } + + + def aggregate_validation(validation: Sequence[Mapping[str, Any]]) -> dict[str, str]: + scopes = {row.get("impact_scope") for row in validation} + if "INCOMPLETE" in scopes: + run_status = "TECHNICAL_INCOMPLETE" + elif any(row.get("evaluation_status") != "PASS" for row in validation): + run_status = "TECHNICAL_REVIEW_REQUIRED" + else: + run_status = "CONSISTENT" + artifact_status = ( + "NOT_PRODUCED" if run_status == "TECHNICAL_INCOMPLETE" + else ("TECHNICAL_REVIEW_REQUIRED" if run_status == "TECHNICAL_REVIEW_REQUIRED" else "CONSISTENT") + ) + return {"run_technical_status": run_status, "artifact_technical_status": artifact_status} + + + def legal_gate_snapshot(inputs: Mapping[str, Any], reduced: Mapping[str, Any]) -> dict[str, bool]: + binding_rows = [ + row for pack in inputs["rule_packs"].values() + for row in pack.get("binding_rows", []) if isinstance(row, dict) + ] + review_policies = [ + value for value in inputs.get("frozen_assets", {}).values() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + structured_rules = [ + value for path, value in inputs.get("frozen_assets", {}).items() + if "case_type_relief_rules" in path + ] + calculations = list(inputs.get("calculation_receipts", {}).values()) + requirement_packs = [ + value for value in inputs.get("plan_documents", {}).values() + if isinstance(value, dict) and value.get("schema_version") == "stage2_requirement_fact_pack.v1" + ] + authority_release = require_object(inputs.get("authority_release"), code="AUTHORITY_RELEASE_OBJECT") + authority_signature = authority_release.get("signature") + authority_ok = ( + authority_release.get("status") == "PRODUCTION_ADMITTED" + and authority_release.get("release_class") == "PRODUCTION_RELEASE" + and authority_release.get("sealed") is True + and authority_release.get("signed") is True + and authority_release.get("executable") is True + and authority_release.get("unresolved") == [] + and isinstance(authority_signature, str) and bool(authority_signature) + and not authority_signature.startswith("PENDING") + and require_object(authority_release.get("registry"), code="AUTHORITY_REGISTRY_REF").get("required_status") == "VERIFIED" + and authority_release.get("hash_binding_status") == "PRODUCTION_ADMITTED" + ) + coverage = require_object(inputs.get("case_type_coverage"), code="CASE_TYPE_COVERAGE_OBJECT") + coverage_rows = require_list(coverage.get("coverage_rows"), code="CASE_TYPE_COVERAGE_ROWS") + case_registry = require_object(inputs.get("case_type_registry"), code="CASE_TYPE_REGISTRY_OBJECT") + rule_registry = require_object(inputs.get("case_type_rule_registry"), code="CASE_TYPE_RULE_REGISTRY_OBJECT") + case_rows = require_list(case_registry.get("rows"), code="CASE_TYPE_REGISTRY_ROWS") + rule_rows = require_list(rule_registry.get("rows"), code="CASE_TYPE_RULE_REGISTRY_ROWS") + approved_values = {"APPROVED", "VERIFIED", "IMPLEMENTED", "RELEASED", "PRODUCTION_ADMITTED", "PASS"} + downstream_keys = { + "relief_rule", "renderer", "corpus", "substantive_profile", + "special_law_or_overlay", "calculation", "review_policy", + } + expected_case_ids = [f"CT-{index:03d}" for index in range(1, 138)] + expected_catalog_ids = [f"CAT-{index:03d}" for index in range(1, 138)] + coverage_ids = [row.get("case_type_id") for row in coverage_rows if isinstance(row, dict)] + case_ids = [row.get("case_type_id") for row in case_rows if isinstance(row, dict)] + rule_ids = [row.get("case_type_id") for row in rule_rows if isinstance(row, dict)] + claim_capable_ids = [ + str(row.get("case_type_id")) for row in case_rows if isinstance(row, dict) + and row.get("claim_capable_disposition") == "CLAIM_CAPABLE" + ] + coverage_rows_ok = ( + coverage_ids == expected_case_ids + and case_ids == expected_case_ids + and rule_ids == expected_case_ids + and case_registry.get("catalog_row_ids") == expected_catalog_ids + and [row.get("catalog_row_id") for row in case_rows] == expected_catalog_ids + and [row.get("source_ordinal") for row in case_rows] == list(range(1, 138)) + and [row.get("canonical_name_ko") for row in coverage_rows] + == [row.get("source_label") for row in case_rows] + ) + for row, registry_row, rule_row in zip(coverage_rows, case_rows, rule_rows): + if not isinstance(row, dict): + coverage_rows_ok = False + continue + downstream = row.get("downstream_coverage") + rule_branches = rule_row.get("rule_branches") if isinstance(rule_row, dict) else None + branch_or_nonclaim_ok = ( + isinstance(rule_branches, list) + and bool(rule_branches) + and all(isinstance(branch, dict) and branch.get("legal_content_status") == "APPROVED" for branch in rule_branches) + ) or ( + isinstance(rule_row, dict) + and rule_row.get("non_claim_disposition") in {"COMPANION_ONLY", "CLASSIFICATION_ONLY"} + and isinstance(rule_row.get("companion_case_type_ids"), list) + ) + if ( + row.get("catalog_mapping_status") not in approved_values + or row.get("legal_signoff") not in approved_values + or row.get("technical_verification") not in approved_values + or row.get("release_status") not in approved_values + or not isinstance(downstream, dict) + or set(downstream) != downstream_keys + or any(value not in approved_values for value in downstream.values()) + or row.get("issue_codes") != [] + or not isinstance(registry_row, dict) + or registry_row.get("legal_classification_status") != "APPROVED" + or registry_row.get("legal_content_status") != "APPROVED" + or not isinstance(rule_row, dict) + or rule_row.get("legal_classification_status") != "APPROVED" + or rule_row.get("legal_content_status") != "APPROVED" + or not branch_or_nonclaim_ok + ): + coverage_rows_ok = False + coverage_catalog = require_object(coverage.get("catalog"), code="CASE_TYPE_COVERAGE_CATALOG") + coverage_dependency = require_object(coverage.get("registry_dependency"), code="CASE_TYPE_COVERAGE_REGISTRY_DEPENDENCY") + coverage_summary = require_object(coverage.get("summary"), code="CASE_TYPE_COVERAGE_SUMMARY") + coverage_ok = ( + coverage.get("release_eligible") is True + and coverage.get("status") == "FULL_137_PRODUCTION_READY" + and coverage_catalog.get("sha256") == case_registry.get("catalog_source_sha256") + and coverage_dependency.get("path") == CASE_TYPE_REGISTRY_REL + and coverage_dependency.get("sha256") == inputs.get("case_type_registry_sha256") + and rule_registry.get("case_type_registry_ref") == CASE_TYPE_REGISTRY_REL + and rule_registry.get("case_type_registry_sha256") == inputs.get("case_type_registry_sha256") + and coverage_summary.get("total_case_type_rows") == 137 + and coverage_summary.get("markdown_doc_count") == 137 + and coverage.get("release_scope_catalog_row_ids") == expected_catalog_ids + and coverage.get("excluded_catalog_row_ids") == [] + and coverage.get("release_scope_claim_capable_ids") == claim_capable_ids + and coverage_rows_ok + ) + gates = { + "binding": bool(binding_rows) and all(row.get("case_type_binding_status") == "BOUND" and row.get("sub_rule_binding_status") == "BOUND" for row in binding_rows), + "authority": authority_ok, + "renderer_branch": reduced["legal_assets_admitted"], + "rule_sub_rule": bool(structured_rules) and all(value.get("execution_eligible") is True and value.get("status") in {"APPROVED", "LEGAL_CONTENT_ADMITTED"} for value in structured_rules), + "review_policy": len(review_policies) == 1 and review_policies[0].get("execution_eligible") is True and review_policies[0].get("status") == "APPROVED_LEGAL_CONTENT", + "case_type_coverage_137": coverage_ok, + "corpus": bool(requirement_packs) and all(require_hex(value.get("corpus_release_sha256"), code="CORPUS_RELEASE_HASH") for value in requirement_packs), + "law_value": all(row.get("calculation_status") == "CALCULATED" and not row.get("missing_law_values") for row in calculations) if calculations else True, + "calculator": all(row.get("calculation_status") == "CALCULATED" for row in calculations) if calculations else True, + "required_receipts": False, + } + if set(gates) != REQUIRED_LEGAL_GATES: + raise S240Error("LEGAL_GATE_SET", "legal gate set is not closed") + return gates + + + def resolve_review_policy_contract( + inputs: Mapping[str, Any], validation: Sequence[Mapping[str, Any]], legal_gates: Mapping[str, bool], + ) -> dict[str, Any]: + policy_values = [ + (path, value) for path, value in inputs.get("frozen_assets", {}).items() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + if len(policy_values) > 1: + raise S240Error("REVIEW_POLICY_CARDINALITY", "multiple frozen review policies") + policy_path, policy = policy_values[0] if len(policy_values) == 1 else ( + "MISSING_REVIEW_POLICY", {"status": "MISSING_REVIEW_POLICY"}, + ) + active_tags = sorted({ + str(reason) for row in validation if row.get("evaluation_status") != "PASS" + for reason in row.get("reason_codes", []) + }) + runtime_triggers = sorted( + str(row.get("invariant_id")) for row in validation if row.get("evaluation_status") != "PASS" + ) + approved = policy.get("execution_eligible") is True and policy.get("status") == "APPROVED_LEGAL_CONTENT" + final_contract = policy.get("final_review_contract") if isinstance(policy.get("final_review_contract"), dict) else {} + allowed_types = set(final_contract.get("policy_result_enum", [ + "STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW", + ])) + if approved: + required_types = list(final_contract.get("base_required_receipt_types", [])) + for row in policy.get("policy_rows", []) if isinstance(policy.get("policy_rows"), list) else []: + if not isinstance(row, dict): + raise S240Error("REVIEW_POLICY_ROW", "review policy row must be an object") + row_tags = set(row.get("trigger_tags", row.get("active_tags", []))) + row_triggers = set(row.get("runtime_triggers", row.get("invariant_ids", []))) + if row.get("always_required") is True or row_tags.intersection(active_tags) or row_triggers.intersection(runtime_triggers): + required_types.extend(row.get("required_receipt_types", [])) + else: + default = policy.get("default_unapproved_result") if isinstance(policy.get("default_unapproved_result"), dict) else {} + required_types = list(default.get("required_receipt_types", ["STANDARD_ATTORNEY_REVIEW"])) + if any(not isinstance(value, str) or value not in allowed_types for value in required_types): + raise S240Error("REVIEW_POLICY_RECEIPT_TYPE", "policy emitted a receipt type outside its closed enum") + required_types = sorted(set(required_types)) + if "MANDATORY_SPECIALIST_REVIEW" in required_types: + base_policy = "MANDATORY_SPECIALIST_REVIEW" + elif "STANDARD_ATTORNEY_REVIEW" in required_types: + base_policy = "STANDARD_ATTORNEY_REVIEW" + else: + fallback = final_contract.get("missing_or_unapproved_policy_result", "STANDARD_ATTORNEY_REVIEW") + base_policy = fallback if fallback in allowed_types else "STANDARD_ATTORNEY_REVIEW" + pre_receipt_ready = ( + approved + and not active_tags + and all(value for key, value in legal_gates.items() if key != "required_receipts") + ) + return { + "policy_path": policy_path, "policy": policy, + "policy_registry_sha256": digest(policy), "base_policy": base_policy, + "active_tags": active_tags, "runtime_triggers": runtime_triggers, + "required_receipt_types": required_types, + "pre_receipt_ready_eligible": pre_receipt_ready, + } + + + def candidate_material(inputs: Mapping[str, Any], reduced: Mapping[str, Any], validation: Sequence[Mapping[str, Any]], request: Mapping[str, Any]) -> dict[str, Any]: + schema_store = require_object(inputs.get("schema_store"), code="OUTPUT_SCHEMA_STORE") + documents: dict[str, bytes] = {} + if reduced["clean_render_allowed"]: + documents = { + "claim_relief.md": canonical_markdown(reduced["relief"]), + "claim_cause.md": canonical_markdown(reduced["cause"]), + "pleading_draft.md": canonical_markdown(reduced["pleading"]), + } + legal_gates = legal_gate_snapshot(inputs, reduced) + review_contract = resolve_review_policy_contract(inputs, validation, legal_gates) + conservation = require_object(reduced.get("conservation"), code="CONSERVATION_OBJECT") + issue_source_keys = require_list(conservation.get("issue_source_keys"), code="ISSUE_SOURCE_KEYS") + assumption_source_keys = require_list(conservation.get("assumption_source_keys"), code="ASSUMPTION_SOURCE_KEYS") + usage_source_keys = require_list(conservation.get("usage_source_keys"), code="USAGE_SOURCE_KEYS") + if ( + len(issue_source_keys) != len(set(issue_source_keys)) + or len(issue_source_keys) != len(reduced["issues"]) + or len(assumption_source_keys) != len(set(assumption_source_keys)) + or len(assumption_source_keys) != len(reduced["assumptions"]) + or len(usage_source_keys) != len(set(usage_source_keys)) + or len(usage_source_keys) != len(reduced["usage"]) + ): + raise S240Error("REVIEW_UNIVERSE_CONSERVATION", "issue/assumption/usage occurrence universe was not conserved") + source_ledger_hashes = sorted({ + digest(inputs["ingress_raws"]["review/issue_ledger.base.json"]), + digest(inputs["plan_raw_by_path"]["plan/issue_ledger.plan.json"]), + }) + s210_issue_hashes = { + digest(raw) for path, raw in inputs["s210_handoff"]["raw_by_path"].items() + if path.startswith("map_s2_10/issue_patches/") + } + s230_issue_hashes = { + row["sha256"] for row in inputs["rows"] if row["part_family"] == "ISSUE_PATCH" + } + ledger = { + "schema_version": "stage2_s2_40_final_issue_ledger.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "source_ledger_sha256s": source_ledger_hashes, + "source_issue_part_sha256s": sorted(s210_issue_hashes | s230_issue_hashes), + "issues": reduced["issues"], "conservation_status": "PASS", + } + s210_assumption_hashes = sorted({ + digest(raw) for path, raw in inputs["s210_handoff"]["raw_by_path"].items() + if path.startswith("map_s2_10/assumption_parts/") + }) + assumptions = { + "schema_version": "stage2_s2_40_assumption_ledger.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "source_assumption_part_sha256s": s210_assumption_hashes, + "rows": reduced["assumptions"], "conservation_status": "PASS", + } + source_usage_hashes = sorted({ + row["source_part_sha256"] for row in reduced["usage"] + }) + usage_projection = { + "schema_version": "stage2_s2_40_usage_projection.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "source_usage_part_sha256s": source_usage_hashes, + "rows": reduced["usage"], "conservation_status": "PASS", + } + worknotes_core = { + "schema_version": "stage2_s2_40_attorney_worknotes_core.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "rows": reduced["worknotes"], + } + render_diagnostic = { + "schema_version": "stage2_s2_40_render_diagnostic.v1", + "render_errors": reduced["render_errors"], "render_absences": reduced["render_absences"], + "independent_rerender_equal": reduced["rerender_equal"], + } + review_policy_core = { + "schema_version": "stage2_s2_40_review_policy_core.v1", + "policy_registry_sha256": review_contract["policy_registry_sha256"], + "base_policy": review_contract["base_policy"], + "active_tags": review_contract["active_tags"], + "runtime_triggers": review_contract["runtime_triggers"], + "required_receipt_types": review_contract["required_receipt_types"], + "pre_receipt_ready_eligible": review_contract["pre_receipt_ready_eligible"], + } + review_basis = review_request_basis( + inputs, validation, review_contract, request["expected_parent_stage2_release_sha256"], + ) + dependency_snapshot = { + "parent_release_sha256": request["expected_parent_stage2_release_sha256"], + "upstream_barrier_sha256s": [ + request["expected_ingress_status_sha256"], request["expected_s2_10_publish_status_sha256"], + request["expected_plan_publish_status_sha256"], request["expected_s2_30_publish_status_sha256"], + ], + "ordered_source_digest": inputs["input_snapshot_digest"], + } + ordered_source_preimage = { + "schema_version": "stage2_s2_40_ordered_source_snapshot_preimage.v1", + "ordered_sha256s": inputs["input_snapshot_preimage"], + "snapshot_digest": inputs["input_snapshot_digest"], + } + generated_pre_manifest = ( + (ledger, "schemas/review_status.schema.json#/$defs/final_issue_ledger", "GENERATED_FINAL_ISSUE_SCHEMA"), + (assumptions, "schemas/review_status.schema.json#/$defs/assumption_ledger", "GENERATED_ASSUMPTION_SCHEMA"), + (usage_projection, "schemas/package.schema.json#/$defs/usage_projection", "GENERATED_USAGE_SCHEMA"), + (worknotes_core, "schemas/package.schema.json#/$defs/attorney_worknotes_core", "GENERATED_WORKNOTES_CORE_SCHEMA"), + (render_diagnostic, "schemas/package.schema.json#/$defs/render_diagnostic", "GENERATED_RENDER_DIAGNOSTIC_SCHEMA"), + (review_policy_core, "schemas/package.schema.json#/$defs/review_policy_core", "GENERATED_REVIEW_POLICY_CORE_SCHEMA"), + (dependency_snapshot, "schemas/package.schema.json#/$defs/dependency_snapshot", "GENERATED_DEPENDENCY_SCHEMA"), + (ordered_source_preimage, "schemas/package.schema.json#/$defs/ordered_source_snapshot_preimage", "GENERATED_ORDERED_SOURCE_SCHEMA"), + (review_basis, "schemas/package.schema.json#/$defs/review_request_basis", "GENERATED_REVIEW_BASIS_SCHEMA"), + (inputs["frozen_source_rows"], "schemas/package.schema.json#/$defs/frozen_source_rows", "GENERATED_FROZEN_SOURCE_SCHEMA"), + (legal_gates, "schemas/package.schema.json#/$defs/legal_gate_snapshot", "GENERATED_LEGAL_GATE_SCHEMA"), + ) + for value, schema_ref, code in generated_pre_manifest: + validate_schema_instance(value, schema_ref, schema_store, code=code) + pre_payloads: dict[str, tuple[bytes, str | None, str]] = { + "issue_ledger.final.json": (canonical_bytes(ledger), "schemas/review_status.schema.json#/$defs/final_issue_ledger", "application/json"), + "assumption_ledger.json": (canonical_bytes(assumptions), "schemas/review_status.schema.json#/$defs/assumption_ledger", "application/json"), + "llm_usage_projection.json": (canonical_bytes(usage_projection), "schemas/package.schema.json#/$defs/usage_projection", "application/json"), + "attorney_worknotes.core.json": (canonical_bytes(worknotes_core), "schemas/package.schema.json#/$defs/attorney_worknotes_core", "application/json"), + "render_diagnostic.json": (canonical_bytes(render_diagnostic), "schemas/package.schema.json#/$defs/render_diagnostic", "application/json"), + "review_policy_core.json": (canonical_bytes(review_policy_core), "schemas/package.schema.json#/$defs/review_policy_core", "application/json"), + "upstream_dependency_snapshot.json": (canonical_bytes(dependency_snapshot), "schemas/package.schema.json#/$defs/dependency_snapshot", "application/json"), + "ordered_source_snapshot_preimage.json": ( + canonical_bytes(ordered_source_preimage), + "schemas/package.schema.json#/$defs/ordered_source_snapshot_preimage", + "application/json", + ), + "review_request_basis.json": (canonical_bytes(review_basis), "schemas/package.schema.json#/$defs/review_request_basis", "application/json"), + "frozen_source_rows.json": (canonical_bytes(inputs["frozen_source_rows"]), "schemas/package.schema.json#/$defs/frozen_source_rows", "application/json"), + "legal_gate_snapshot.json": (canonical_bytes(legal_gates), "schemas/package.schema.json#/$defs/legal_gate_snapshot", "application/json"), + } + for name, payload in documents.items(): + pre_payloads[name] = (payload, None, "text/markdown; charset=utf-8") + artifact_rows = [ + { + "path": name, "raw_sha256": digest(payload), "content_type": content_type, + "size_bytes": len(payload), "schema_ref": schema_ref, "producer_id": "S2_40", + } + for name, (payload, schema_ref, content_type) in sorted(pre_payloads.items()) + ] + manifest_core = { + "schema_version": "stage2_s2_40_candidate_manifest_core.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], "candidate_attempt_id": request["candidate_attempt_id"], + "dependency_snapshot": dependency_snapshot, "artifacts": artifact_rows, + } + validate_schema_instance( + manifest_core, "schemas/package.schema.json#/$defs/candidate_manifest_core", + schema_store, code="GENERATED_CANDIDATE_MANIFEST_SCHEMA", + ) + manifest_hash = digest(manifest_core) + statuses = aggregate_validation(validation) + validation_core = { + "schema_version": "stage2_s2_40_validation_core.v1", + "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "candidate_manifest_core_sha256": manifest_hash, + "invariant_results": list(validation), + "run_technical_status": statuses["run_technical_status"], + "artifact_technical_status": statuses["artifact_technical_status"], + } + validate_schema_instance( + validation_core, "schemas/package.schema.json#/$defs/validation_core", + schema_store, code="GENERATED_VALIDATION_CORE_SCHEMA", + ) + validation_hash = digest(validation_core) + document_sha256s = { + "claim_relief": digest(documents.get("claim_relief.md", b"")), + "claim_cause": digest(documents.get("claim_cause.md", b"")), + "pleading_draft": digest(documents.get("pleading_draft.md", b"")), + } + digest_core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + "run_binding_digest": request["run_binding_digest"], + "dependency_snapshot_sha256": digest(dependency_snapshot), + "candidate_manifest_core_sha256": manifest_hash, + "document_sha256s": document_sha256s, + "attorney_worknotes_core_sha256": digest(worknotes_core), + "final_issue_ledger_sha256": digest(ledger), + "assumption_ledger_sha256": digest(assumptions), + "validation_core_sha256": validation_hash, + "ordered_source_dependency_snapshot_digest": inputs["input_snapshot_digest"], + } + candidate_digest = digest(digest_core) + digest_envelope = { + **digest_core, + "candidate_content_digest": candidate_digest, + } + validate_schema_instance( + digest_envelope, "schemas/package.schema.json#/$defs/candidate_digest_envelope", + schema_store, code="GENERATED_CANDIDATE_DIGEST_SCHEMA", + ) + worknotes = { + "schema_version": "stage2_s2_40_attorney_worknotes.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], "candidate_content_digest": candidate_digest, + "rows": reduced["worknotes"], + } + validate_schema_instance( + worknotes, "schemas/package.schema.json#/$defs/attorney_worknotes", + schema_store, code="GENERATED_ATTORNEY_WORKNOTES_SCHEMA", + ) + packet_core = { + "schema_version": "stage2_s2_40_lawyer_review_packet_core.v1", + "candidate_content_digest": candidate_digest, + "finding_ids": sorted(row["finding_ids"][0] for row in validation if row["finding_ids"]), + "scope_ids": inputs["group_ids"], + "document_refs": sorted(documents) or ["issue_ledger.final.json"], + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + validation_envelope_core = { + "schema_version": "stage2_s2_40_validation_envelope_core.v1", + "candidate_content_digest": candidate_digest, + "validation_core_sha256": validation_hash, + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + subject = review_subject( + candidate_digest, digest(packet_core), digest(validation_envelope_core), review_basis, + ) + validate_schema_instance( + packet_core, "schemas/package.schema.json#/$defs/lawyer_review_packet_core", + schema_store, code="GENERATED_REVIEW_PACKET_CORE_SCHEMA", + ) + validate_schema_instance( + validation_envelope_core, "schemas/package.schema.json#/$defs/validation_envelope_core", + schema_store, code="GENERATED_VALIDATION_ENVELOPE_CORE_SCHEMA", + ) + validate_schema_instance( + subject["subject"], "schemas/package.schema.json#/$defs/review_subject", + schema_store, code="GENERATED_REVIEW_SUBJECT_SCHEMA", + ) + packet = { + "schema_version": "stage2_s2_40_lawyer_review_packet.v1", + "lawyer_review_packet_core": packet_core, + "lawyer_review_packet_core_sha256": digest(packet_core), + "review_subject_digest": subject["review_subject_digest"], + } + validation_envelope = { + "schema_version": "stage2_s2_40_validation_envelope.v1", + "validation_envelope_core": validation_envelope_core, + "validation_envelope_core_sha256": digest(validation_envelope_core), + "review_subject_digest": subject["review_subject_digest"], + } + review_policy_result = { + "schema_version": "stage2_s2_40_review_policy_result.v1", + "candidate_content_digest": candidate_digest, + "policy_registry_sha256": review_contract["policy_registry_sha256"], + "base_policy": review_contract["base_policy"], + "active_tags": review_contract["active_tags"], + "runtime_triggers": review_contract["runtime_triggers"], + "required_receipt_types": review_contract["required_receipt_types"], + "ready_eligible": review_contract["pre_receipt_ready_eligible"], + } + for value, schema_ref, code in ( + (packet, "schemas/package.schema.json#/$defs/lawyer_review_packet", "GENERATED_REVIEW_PACKET_SCHEMA"), + (validation_envelope, "schemas/package.schema.json#/$defs/validation_envelope", "GENERATED_VALIDATION_ENVELOPE_SCHEMA"), + (review_policy_result, "schemas/review_status.schema.json#/$defs/review_policy_result", "GENERATED_REVIEW_POLICY_RESULT_SCHEMA"), + ): + validate_schema_instance(value, schema_ref, schema_store, code=code) + return { + "documents": documents, "pre_payloads": pre_payloads, "ledger": ledger, + "assumptions": assumptions, "usage_projection": usage_projection, "worknotes": worknotes, + "validation_core": validation_core, "manifest_core": manifest_core, + "validation_envelope": validation_envelope, + "candidate_digest_envelope": digest_envelope, "candidate_digest": candidate_digest, + "review": subject, "packet": packet, "legal_gates": legal_gates, + "review_policy_result": review_policy_result, "review_policy_path": review_contract["policy_path"], + "schema_store": schema_store, + } + + + def publish_candidate(client: McpClient, request: Mapping[str, Any], material: Mapping[str, Any]) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + candidate_digest = material["candidate_digest"] + candidate_root = join_path(root, "candidates/by-content-digest", candidate_digest) + outputs: list[tuple[str, bytes]] = [ + ("candidate_package_manifest.json", canonical_bytes(material["manifest_core"])), + ("candidate_content_digest.json", canonical_bytes(material["candidate_digest_envelope"])), + ("attorney_worknotes.json", canonical_bytes(material["worknotes"])), + ("validation_core.json", canonical_bytes(material["validation_core"])), + ("validation_envelope.json", canonical_bytes(material["validation_envelope"])), + ("review_subject.json", canonical_bytes(material["review"]["subject"])), + ("lawyer_review_packet.json", canonical_bytes(material["packet"])), + ] + outputs.extend((name, payload[0]) for name, payload in sorted(material["pre_payloads"].items())) + outputs.extend(sorted(material["documents"].items())) + deduplicated: dict[str, bytes] = {} + for name, payload in outputs: + if name in deduplicated and deduplicated[name] != payload: + raise S240Error("CANDIDATE_ARTIFACT_CONFLICT", f"candidate path conflicts: {name}") + deduplicated[name] = payload + rows: list[dict[str, Any]] = [] + for rel, payload in sorted(deduplicated.items()): + path = join_path(candidate_root, rel) + observed = client.write_immutable(path, payload) + rows.append({"path": path, "raw_sha256": observed, "size_bytes": len(payload), "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8"}) + review = material["review"] + review_publications: list[dict[str, Any]] = [] + for request_row in review["requests"]: + request_envelope = { + "schema_version": "stage2_s2_40_review_request.v1", + "request_id": request_row["request_id"], + "review_request_core": request_row["core"], + "review_request_core_sha256": request_row["core_sha256"], + "review_subject_digest": request_row["review_subject_digest"], + } + validate_schema_instance( + request_envelope, "schemas/review_status.schema.json#/$defs/review_request", + material["schema_store"], code="GENERATED_REVIEW_REQUEST_SCHEMA", + ) + review_path = join_path(root, "review/review_requests", f"{request_row['request_id']}.json") + review_hash = client.write_immutable(review_path, canonical_bytes(request_envelope)) + review_publications.append({ + "receipt_type": request_row["receipt_type"], "path": review_path, + "sha256": review_hash, "request": request_envelope, + }) + return { + "candidate_root": candidate_root, "artifact_rows": rows, + "review_requests": review_publications, + } + + + def validate_review_receipts(client: McpClient, request: Mapping[str, Any], material: Mapping[str, Any]) -> tuple[bool, bool, list[dict[str, Any]]]: + refs = request["review_receipt_refs"] + required_types = set(material["review_policy_result"].get("required_receipt_types", [])) + expected_requests = { + str(row["receipt_type"]): row + for row in require_list(material["review"].get("requests"), code="REVIEW_EXPECTED_REQUESTS") + } + if set(expected_requests) != required_types or len(expected_requests) != len(material["review"]["requests"]): + raise S240Error("REVIEW_REQUEST_SET", "review request map differs from required receipt types") + if not refs: + return not required_types, False, [] + rows: list[dict[str, Any]] = [] + content_change = False + approved_types: set[str] = set() + seen_types: set[str] = set() + schema_store = require_object(material.get("schema_store"), code="REVIEW_SCHEMA_STORE") + for ref in refs: + raw: bytes | None = None + value: dict[str, Any] = {} + reasons: list[str] = [] + try: + raw = client.read_binary(ref) + value = require_object(load_json(raw, label=ref), code="REVIEW_RECEIPT_OBJECT") + if client.read_binary(ref) != raw: + reasons.append("REVIEW_RECEIPT_TOCTOU") + if canonical_bytes(value) != raw: + reasons.append("REVIEW_RECEIPT_NON_CANONICAL") + try: + validate_schema_instance( + value, "schemas/review_status.schema.json#/$defs/review_receipt", + schema_store, code="REVIEW_RECEIPT_SCHEMA", + ) + except S240Error as exc: + reasons.append(exc.code) + receipt_type = value.get("receipt_type") + expected_request = expected_requests.get(str(receipt_type)) + if expected_request is None: + reasons.append("REVIEW_RECEIPT_TYPE_NOT_REQUIRED") + if receipt_type in seen_types: + reasons.append("REVIEW_RECEIPT_TYPE_DUPLICATE") + seen_types.add(str(receipt_type)) + expected_core = expected_request.get("core", {}) if expected_request is not None else {} + if expected_request is None or ( + value.get("request_id") != expected_request.get("request_id") + or value.get("candidate_content_digest") != material["candidate_digest"] + or value.get("review_subject_digest") != material["review"]["review_subject_digest"] + or value.get("finding_ids") != expected_core.get("finding_ids") + or value.get("scope_ids") != expected_core.get("scope_ids") + or value.get("reviewer_role") != expected_core.get("reviewer_role") + or value.get("reviewer_qualification") != expected_core.get("reviewer_qualification") + ): + reasons.append("REVIEW_RECEIPT_SUBJECT") + if ( + value.get("reviewer_role") != TRUSTED_REVIEW_ROLE + or value.get("reviewer_qualification") != TRUSTED_REVIEW_QUALIFICATION + or value.get("issuer_id") != TRUSTED_REVIEW_ISSUER + or value.get("key_id") not in TRUSTED_REVIEW_KEY_IDS + or value.get("signature_algorithm") != TRUSTED_REVIEW_SIGNATURE_ALGORITHM + ): + reasons.append("REVIEW_RECEIPT_ISSUER") + if value.get("cryptographic_verification_status") != "VERIFIED_BY_EXTERNAL_ADAPTER" or value.get("revocation_status") != "NOT_REVOKED": + reasons.append("REVIEW_RECEIPT_TRUST") + if HEX64.fullmatch(str(value.get("external_verification_attestation_sha256", ""))) is None: + reasons.append("REVIEW_RECEIPT_EXTERNAL_ATTESTATION") + try: + issued = datetime.fromisoformat(str(value.get("issued_at")).replace("Z", "+00:00")) + expires = datetime.fromisoformat(str(value.get("expires_at")).replace("Z", "+00:00")) + now = datetime.now(timezone.utc) + if issued.tzinfo is None or expires.tzinfo is None or issued > now or expires <= now or expires <= issued: + reasons.append("REVIEW_RECEIPT_TIME") + except (TypeError, ValueError): + reasons.append("REVIEW_RECEIPT_TIME") + disposition = value.get("review_disposition") + change_scope = value.get("change_scope") + expected_signed_material = digest([ + "STAGE2_S2_40_REVIEW_RECEIPT_V1", value.get("request_id"), + value.get("candidate_content_digest"), value.get("review_subject_digest"), + value.get("receipt_type"), value.get("finding_ids"), value.get("scope_ids"), + value.get("reviewer_role"), value.get("reviewer_qualification"), + value.get("issuer_id"), value.get("key_id"), value.get("signature_algorithm"), + value.get("external_verification_attestation_sha256"), + value.get("issued_at"), value.get("expires_at"), + value.get("revocation_status"), value.get("cryptographic_verification_status"), + disposition, change_scope, value.get("reason_codes"), + ]) + if value.get("signed_material_digest") != expected_signed_material: + reasons.append("REVIEW_RECEIPT_SIGNED_SCOPE") + if disposition == "CONTENT_CHANGE_REQUIRED": + if change_scope not in {"STAGE1_CONTEXT", "LEGAL_JUDGMENT", "PLAN_RULE_CALCULATION_BINDING", "DRAFTING_TEXT_ATOM"}: + reasons.append("REVIEW_CHANGE_SCOPE") + elif disposition != "APPROVE_AS_IS" or change_scope != "NONE": + reasons.append("REVIEW_RECEIPT_DISPOSITION") + except (S240Error, TypeError, ValueError) as exc: + reasons.append(exc.code if isinstance(exc, S240Error) else "REVIEW_RECEIPT_PARSE") + if not reasons and value.get("review_disposition") == "CONTENT_CHANGE_REQUIRED": + content_change = True + if not reasons and value.get("review_disposition") == "APPROVE_AS_IS": + approved_types.add(str(value.get("receipt_type"))) + row = { + "path": ref, "receipt_id": value.get("receipt_id"), + "receipt_type": value.get("receipt_type"), + "disposition": value.get("review_disposition"), + "change_scope": value.get("change_scope"), + "validation_status": "VALID" if not reasons else "INVALID", + "reason_codes": sorted(set(reasons)), + } + if raw is not None: + row["sha256"] = digest(raw) + rows.append(row) + approved = not content_change and approved_types == required_types and len(rows) == len(required_types) and all( + row.get("validation_status") == "VALID" for row in rows + ) + return approved, content_change, rows + + + def final_status( + client: McpClient, + request: Mapping[str, Any], + preflight_digest: str, + inputs: Mapping[str, Any], + material: Mapping[str, Any], + publication: Mapping[str, Any], + approved: bool, + content_change: bool, + review_rows: Sequence[Mapping[str, Any]], + ) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + candidate_digest = material["candidate_digest"] + validation_rows = material["validation_core"]["invariant_results"] + all_pass = len(validation_rows) == 18 and all( + row["evaluation_status"] == "PASS" for row in validation_rows + ) + effective_gates = dict(material["legal_gates"]) + effective_gates["required_receipts"] = approved + full_production_gates = ( + request["compile_mode"] == "PRODUCTION" + and all_pass + and bool(material["documents"]) + and effective_gates == {key: True for key in REQUIRED_LEGAL_GATES} + and material["review_policy_result"]["ready_eligible"] + ) + receipt_hashes = sorted({ + str(row["sha256"]) for row in review_rows + if row.get("validation_status") == "VALID" + and HEX64.fullmatch(str(row.get("sha256", ""))) + }) + validation_hash = digest(material["validation_core"]) + review_subject_digest = material["review"]["review_subject_digest"] + if content_change: + scope_order = { + "STAGE1_CONTEXT": (0, "RESTART_FROM_S2_00"), + "LEGAL_JUDGMENT": (1, "RESTART_FROM_S2_10"), + "PLAN_RULE_CALCULATION_BINDING": (2, "RESTART_FROM_S2_20"), + "DRAFTING_TEXT_ATOM": (3, "RESTART_FROM_S2_30"), + } + scopes = [ + row["change_scope"] for row in review_rows + if row.get("validation_status") == "VALID" + and row.get("disposition") == "CONTENT_CHANGE_REQUIRED" + and row.get("change_scope") in scope_order + ] + if not scopes: + raise S240Error("REVIEW_CHANGE_SCOPE_MISSING", "content-change receipt lacks earliest-owner scope") + phase, route = "SUPERSEDED", scope_order[min(scopes, key=lambda value: scope_order[value][0])][1] + elif not full_production_gates: + phase, route = "AWAITING_EXTERNAL_REVIEW", "WAIT_EXTERNAL_REVIEW" + else: + phase, route = "READY_TO_COMMIT", "CONTINUE_TO_COMMIT" + artifact_set_digest: str | None = None + stage2_package_sha256: str | None = None + commit_intent_sha256: str | None = None + commit_result_sha256: str | None = None + if phase == "READY_TO_COMMIT": + final_payloads: dict[str, bytes] = { + "candidate_package_manifest.json": canonical_bytes(material["manifest_core"]), + "candidate_content_digest.json": canonical_bytes(material["candidate_digest_envelope"]), + "attorney_worknotes.json": canonical_bytes(material["worknotes"]), + "lawyer_review_packet.json": canonical_bytes(material["packet"]), + "stage2_final_validation_report.json": canonical_bytes(material["validation_core"]), + "review_policy_result.json": canonical_bytes(material["review_policy_result"]), + } + for rel, value in sorted(material["pre_payloads"].items()): + if rel in final_payloads and final_payloads[rel] != value[0]: + raise S240Error("FINAL_ARTIFACT_CONFLICT", f"final artifact path conflicts: {rel}") + final_payloads[rel] = value[0] + final_payloads.update(material["documents"]) + package_artifacts = [ + { + "path": join_path(root, "final", rel), "raw_sha256": digest(payload), + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, "producer_id": "S2_40", + } + for rel, payload in sorted(final_payloads.items()) + ] + package = { + "schema_version": "stage2_s2_40_package.v1", + "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "compile_mode": request["compile_mode"], + "candidate_manifest_core_sha256": digest(material["manifest_core"]), + "artifacts": package_artifacts, + "validation_report_sha256": validation_hash, + "review_policy_result_sha256": digest(material["review_policy_result"]), + "review_receipt_sha256s": receipt_hashes, + "filing_decision_receipt_sha256": None, + "run_technical_status": "CONSISTENT", + "artifact_technical_status": "CONSISTENT", + "legal_readiness": "READY_FOR_LAWYER_FILING_DECISION", + "filing_permission": "NOT_GRANTED", + } + validate_schema_instance( + package, "schemas/package.schema.json#/$defs/stage2_package", + material["schema_store"], code="GENERATED_STAGE2_PACKAGE_SCHEMA", + ) + package_payload = canonical_bytes(package) + stage2_package_sha256 = digest(package_payload) + final_payloads["stage2_package.json"] = package_payload + expected_rows = [ + { + "path": join_path(root, "final", rel), "raw_sha256": digest(payload), + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, + } + for rel, payload in sorted(final_payloads.items()) + ] + intent_core = { + "schema_version": "stage2_s2_40_commit_intent.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "candidate_attempt_id": request["candidate_attempt_id"], + "candidate_manifest_core_sha256": digest(material["manifest_core"]), + "validation_report_sha256": validation_hash, + "review_subject_digest": review_subject_digest, + "review_receipt_sha256s": receipt_hashes, + "stage2_package_sha256": stage2_package_sha256, + "expected_artifacts": expected_rows, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "request_sha256": request["_request_sha256"], + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + } + intent = {**intent_core, "intent_digest": digest(intent_core)} + validate_schema_instance( + intent, "schemas/deployment.schema.json#/$defs/s2_40_commit_intent", + material["schema_store"], code="GENERATED_COMMIT_INTENT_SCHEMA", + ) + intent_path = join_path(root, "commit/commit_intent.json") + commit_intent_sha256 = client.write_immutable(intent_path, canonical_bytes(intent)) + final_rows: list[dict[str, Any]] = [] + for rel, payload in sorted(final_payloads.items()): + path = join_path(root, "final", rel) + observed = client.write_immutable(path, payload) + final_rows.append({ + "path": path, "raw_sha256": observed, + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, + }) + if final_rows != expected_rows: + raise S240Error("COMMIT_EXPECTED_ROWS", "written final rows differ from commit intent") + artifact_set_digest = digest(final_rows) + result_core = { + "schema_version": "stage2_s2_40_commit_result.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "commit_intent_sha256": commit_intent_sha256, + "artifact_set_digest": artifact_set_digest, + "artifact_rows": final_rows, + "readback_status": "PASS", "conflicting_target_count": 0, + "missing_target_count_after_write": 0, + } + result = {**result_core, "commit_result_digest": digest(result_core)} + validate_schema_instance( + result, "schemas/deployment.schema.json#/$defs/s2_40_commit_result", + material["schema_store"], code="GENERATED_COMMIT_RESULT_SCHEMA", + ) + commit_result_sha256 = client.write_immutable( + join_path(root, "commit/stage2_commit_result.json"), canonical_bytes(result), + ) + phase, route = "COMMITTED", "PACKAGE_COMMITTED" + aggregate = aggregate_validation(validation_rows) + if aggregate["run_technical_status"] == "TECHNICAL_INCOMPLETE": + artifact_status, legal_readiness = "NOT_PRODUCED", "NOT_ASSESSED" + else: + artifact_status = aggregate["artifact_technical_status"] + legal_readiness = "READY_FOR_LAWYER_FILING_DECISION" if full_production_gates else "LAWYER_REVIEW_REQUIRED" + return write_terminal_status( + client, request, workflow_phase=phase, route=route, + candidate_content_digest=candidate_digest, + run_technical_status=aggregate["run_technical_status"], + artifact_technical_status=artifact_status, legal_readiness=legal_readiness, + validation_report_sha256=validation_hash, + review_subject_digest=review_subject_digest, + review_receipt_sha256s=receipt_hashes, + stage2_package_sha256=stage2_package_sha256, + artifact_set_digest=artifact_set_digest, + commit_intent_sha256=commit_intent_sha256, + commit_result_sha256=commit_result_sha256, + schema_store=material["schema_store"], + ) + + + def verify_frozen_candidate_digest_chain( + expected: str, + manifest: Mapping[str, Any], + envelope: Mapping[str, Any], + pre_payloads: Mapping[str, tuple[bytes, str | None, str]], + documents: Mapping[str, bytes], + validation_core: Mapping[str, Any], + ) -> dict[str, Any]: + """Recompute every pre-review candidate digest edge from frozen bytes.""" + def payload_json(name: str) -> Any: + if name not in pre_payloads: + raise S240Error("RESUME_REQUIRED_ARTIFACT", f"required frozen artifact missing: {name}") + raw = pre_payloads[name][0] + value = load_json(raw, label=name) + if canonical_bytes(value) != raw: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {name}") + return value + + dependency = require_object(manifest.get("dependency_snapshot"), code="RESUME_DEPENDENCY_SNAPSHOT") + persisted_dependency = require_object( + payload_json("upstream_dependency_snapshot.json"), code="RESUME_PERSISTED_DEPENDENCY", + ) + if persisted_dependency != dependency: + raise S240Error("RESUME_DEPENDENCY_SNAPSHOT_DRIFT", "embedded and persisted dependency snapshots differ") + ordered_preimage = require_object( + payload_json("ordered_source_snapshot_preimage.json"), code="RESUME_ORDERED_SOURCE_PREIMAGE", + ) + ordered_hashes = require_list(ordered_preimage.get("ordered_sha256s"), code="RESUME_ORDERED_SOURCE_HASHES") + for value in ordered_hashes: + require_hex(value, code="RESUME_ORDERED_SOURCE_HASH") + ordered_digest = digest(ordered_hashes) + if ( + ordered_preimage.get("snapshot_digest") != ordered_digest + or dependency.get("ordered_source_digest") != ordered_digest + ): + raise S240Error("RESUME_ORDERED_SOURCE_DIGEST", "ordered source preimage digest differs") + worknotes_core = require_object( + payload_json("attorney_worknotes.core.json"), code="RESUME_WORKNOTES_CORE", + ) + ledger = require_object(payload_json("issue_ledger.final.json"), code="RESUME_FINAL_ISSUE_LEDGER") + assumptions = require_object(payload_json("assumption_ledger.json"), code="RESUME_ASSUMPTION_LEDGER") + document_sha256s = { + "claim_relief": digest(documents.get("claim_relief.md", b"")), + "claim_cause": digest(documents.get("claim_cause.md", b"")), + "pleading_draft": digest(documents.get("pleading_draft.md", b"")), + } + digest_core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + "run_binding_digest": manifest.get("run_binding_digest"), + "dependency_snapshot_sha256": digest(dependency), + "candidate_manifest_core_sha256": digest(manifest), + "document_sha256s": document_sha256s, + "attorney_worknotes_core_sha256": digest(worknotes_core), + "final_issue_ledger_sha256": digest(ledger), + "assumption_ledger_sha256": digest(assumptions), + "validation_core_sha256": digest(validation_core), + "ordered_source_dependency_snapshot_digest": ordered_digest, + } + recomputed = digest(digest_core) + if recomputed != expected or envelope != {**digest_core, "candidate_content_digest": recomputed}: + raise S240Error("RESUME_CANDIDATE_DIGEST_CHAIN", "frozen candidate digest chain does not recompute exactly") + return { + "dependency": dependency, "ordered_source_preimage": ordered_preimage, + "worknotes_core": worknotes_core, "ledger": ledger, "assumptions": assumptions, + } + + + def hydrate_frozen_candidate(client: McpClient, request: Mapping[str, Any]) -> dict[str, Any]: + """RESUME validates and re-derives the frozen candidate without upstream rerendering.""" + root = request["stage2_run_root_ref"] + expected = require_hex(request["expected_candidate_content_digest"], code="RESUME_CANDIDATE_HASH") + schema_store = load_output_schema_store(client) + + def canonical_bound_json(path: str, expected_sha256: str | None = None) -> tuple[dict[str, Any], bytes]: + value, raw = read_bound_json(client, path, expected_sha256) + if canonical_bytes(value) != raw: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {path}") + return value, raw + + previous, _ = canonical_bound_json( + join_path(root, "control/run_status.json"), request["expected_previous_run_status_sha256"], + ) + validate_schema_instance( + previous, "schemas/review_status.schema.json#/$defs/run_status", + schema_store, code="RESUME_PREVIOUS_STATUS_SCHEMA", + ) + if ( + previous.get("candidate_content_digest") != expected + or previous.get("workflow_phase") != "AWAITING_EXTERNAL_REVIEW" + or previous.get("compile_mode") != request["compile_mode"] + or previous.get("run_binding_digest") != request["run_binding_digest"] + or previous.get("candidate_attempt_id") != request["candidate_attempt_id"] + ): + raise S240Error("RESUME_CHECKPOINT", "previous status does not bind the frozen candidate") + candidate_root = join_path(root, "candidates/by-content-digest", expected) + if PurePosixPath(candidate_root).name != expected: + raise S240Error("RESUME_CANDIDATE_DIRECTORY", "candidate directory basename differs from expected digest") + manifest, _ = canonical_bound_json(join_path(candidate_root, "candidate_package_manifest.json")) + envelope, _ = canonical_bound_json(join_path(candidate_root, "candidate_content_digest.json")) + validate_schema_instance( + manifest, "schemas/package.schema.json#/$defs/candidate_manifest_core", + schema_store, code="RESUME_CANDIDATE_MANIFEST_SCHEMA", + ) + validate_schema_instance( + envelope, "schemas/package.schema.json#/$defs/candidate_digest_envelope", + schema_store, code="RESUME_CANDIDATE_ENVELOPE_SCHEMA", + ) + expected_upstream = [ + request["expected_ingress_status_sha256"], request["expected_s2_10_publish_status_sha256"], + request["expected_plan_publish_status_sha256"], request["expected_s2_30_publish_status_sha256"], + ] + dependency = require_object(manifest.get("dependency_snapshot"), code="RESUME_DEPENDENCY_SNAPSHOT") + if ( + manifest.get("producer_id") != "S2_40" + or manifest.get("run_binding_digest") != request["run_binding_digest"] + or manifest.get("compile_mode") != request["compile_mode"] + or manifest.get("candidate_attempt_id") != request["candidate_attempt_id"] + or dependency.get("parent_release_sha256") != request["expected_parent_stage2_release_sha256"] + or dependency.get("upstream_barrier_sha256s") != expected_upstream + ): + raise S240Error("RESUME_DEPENDENCY_DRIFT", "RESUME request differs from the frozen dependency snapshot") + pre_payloads: dict[str, tuple[bytes, str | None, str]] = {} + documents: dict[str, bytes] = {} + artifact_rows = require_list(manifest.get("artifacts"), code="RESUME_ARTIFACT_ROWS") + artifact_paths = [safe_path(row.get("path"), code="RESUME_ARTIFACT_PATH") for row in artifact_rows if isinstance(row, dict)] + if len(artifact_paths) != len(artifact_rows) or artifact_paths != sorted(artifact_paths) or len(set(artifact_paths)) != len(artifact_paths): + raise S240Error("RESUME_ARTIFACT_SET", "candidate artifact paths must be unique and sorted") + for row in artifact_rows: + row = require_object(row, code="RESUME_ARTIFACT_ROW") + rel = safe_path(row.get("path"), code="RESUME_ARTIFACT_PATH") + raw_a = client.read_binary(join_path(candidate_root, rel)) + raw_b = client.read_binary(join_path(candidate_root, rel)) + if raw_a != raw_b: + raise S240Error("RESUME_ARTIFACT_TOCTOU", f"frozen candidate artifact changed: {rel}") + if digest(raw_a) != require_hex(row.get("raw_sha256"), code="RESUME_ARTIFACT_HASH") or len(raw_a) != row.get("size_bytes"): + raise S240Error("RESUME_ARTIFACT_DRIFT", f"frozen candidate artifact differs: {rel}") + content_type = str(row.get("content_type")) + schema_ref = row.get("schema_ref") + if content_type.startswith("text/markdown"): + if schema_ref is not None: + raise S240Error("RESUME_MARKDOWN_SCHEMA_REF", f"markdown must not declare JSON schema: {rel}") + documents[rel] = raw_a + else: + if not isinstance(schema_ref, str): + raise S240Error("RESUME_JSON_SCHEMA_REF", f"JSON artifact lacks schema binding: {rel}") + value = load_json(raw_a, label=rel) + if canonical_bytes(value) != raw_a: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {rel}") + validate_schema_instance(value, schema_ref, schema_store, code="RESUME_ARTIFACT_SCHEMA") + pre_payloads[rel] = (raw_a, schema_ref, content_type) + + def auxiliary_json(name: str, schema_ref: str) -> dict[str, Any]: + value, _ = canonical_bound_json(join_path(candidate_root, name)) + validate_schema_instance(value, schema_ref, schema_store, code="RESUME_AUXILIARY_SCHEMA") + return value + + validation_core = auxiliary_json("validation_core.json", "schemas/package.schema.json#/$defs/validation_core") + packet = auxiliary_json("lawyer_review_packet.json", "schemas/package.schema.json#/$defs/lawyer_review_packet") + worknotes = auxiliary_json("attorney_worknotes.json", "schemas/package.schema.json#/$defs/attorney_worknotes") + validation_envelope = auxiliary_json("validation_envelope.json", "schemas/package.schema.json#/$defs/validation_envelope") + stored_subject = auxiliary_json("review_subject.json", "schemas/package.schema.json#/$defs/review_subject") + chain = verify_frozen_candidate_digest_chain( + expected, manifest, envelope, pre_payloads, documents, validation_core, + ) + if ( + worknotes.get("candidate_content_digest") != expected + or worknotes.get("rows") != chain["worknotes_core"].get("rows") + or packet.get("lawyer_review_packet_core_sha256") != digest(packet.get("lawyer_review_packet_core")) + or validation_envelope.get("validation_envelope_core_sha256") != digest(validation_envelope.get("validation_envelope_core")) + or validation_envelope.get("validation_envelope_core", {}).get("validation_core_sha256") != digest(validation_core) + ): + raise S240Error("RESUME_AUXILIARY_DIGEST_CHAIN", "frozen auxiliary candidate objects do not recompute") + review_basis = require_object( + load_json(pre_payloads["review_request_basis.json"][0], label="review_request_basis"), + code="RESUME_REVIEW_BASIS", + ) + rebuilt_review = review_subject( + expected, packet["lawyer_review_packet_core_sha256"], + validation_envelope["validation_envelope_core_sha256"], review_basis, + ) + if ( + rebuilt_review["subject"] != stored_subject + or packet.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + or validation_envelope.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + or previous.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + ): + raise S240Error("RESUME_REVIEW_SUBJECT", "frozen review subject does not re-derive exactly") + for request_row in rebuilt_review["requests"]: + request_path = join_path(root, "review/review_requests", f"{request_row['request_id']}.json") + review_request, _ = canonical_bound_json(request_path) + validate_schema_instance( + review_request, "schemas/review_status.schema.json#/$defs/review_request", + schema_store, code="RESUME_REVIEW_REQUEST_SCHEMA", + ) + expected_request = { + "schema_version": "stage2_s2_40_review_request.v1", + "request_id": request_row["request_id"], + "review_request_core": request_row["core"], + "review_request_core_sha256": request_row["core_sha256"], + "review_subject_digest": request_row["review_subject_digest"], + } + if review_request != expected_request: + raise S240Error("RESUME_REVIEW_REQUEST_DRIFT", f"frozen review request differs: {request_row['receipt_type']}") + review_policy_core = require_object( + load_json(pre_payloads["review_policy_core.json"][0], label="review_policy_core"), + code="RESUME_REVIEW_POLICY_CORE", + ) + policy_result = { + "schema_version": "stage2_s2_40_review_policy_result.v1", + "candidate_content_digest": expected, + "policy_registry_sha256": review_policy_core.get("policy_registry_sha256"), + "base_policy": review_policy_core.get("base_policy"), + "active_tags": review_policy_core.get("active_tags"), + "runtime_triggers": review_policy_core.get("runtime_triggers"), + "required_receipt_types": review_policy_core.get("required_receipt_types"), + "ready_eligible": review_policy_core.get("pre_receipt_ready_eligible") is True, + } + validate_schema_instance( + policy_result, "schemas/review_status.schema.json#/$defs/review_policy_result", + schema_store, code="RESUME_REVIEW_POLICY_RESULT_SCHEMA", + ) + frozen_sources = require_list( + load_json(pre_payloads["frozen_source_rows.json"][0], label="frozen_source_rows"), + code="RESUME_FROZEN_SOURCE_ROWS", + ) + manifest_rows = [ + row for row in frozen_sources if isinstance(row, dict) + and row.get("path") == "map_s2_30/artifact_manifest.json" + and row.get("ref_family") == "upstream_manifest" + ] + if len(manifest_rows) != 1 or manifest_rows[0].get("sha256") != request["expected_s2_30_artifact_manifest_sha256"]: + raise S240Error("RESUME_MANIFEST_DRIFT", "RESUME request differs from frozen S2_30 artifact manifest") + legal_gates = require_object( + load_json(pre_payloads["legal_gate_snapshot.json"][0], label="legal_gate_snapshot"), + code="RESUME_LEGAL_GATES", + ) + return { + "documents": documents, "pre_payloads": pre_payloads, + "manifest_core": manifest, "candidate_digest_envelope": envelope, + "candidate_digest": expected, "validation_core": validation_core, + "packet": packet, "worknotes": worknotes, "legal_gates": legal_gates, + "review_policy_result": policy_result, "review": rebuilt_review, + "schema_store": schema_store, + } + + + def normal_route(client: McpClient, request: Mapping[str, Any], preflight_digest: str) -> dict[str, Any]: + if request["requested_transition"] == "RESUME": + inputs: dict[str, Any] = {} + material = hydrate_frozen_candidate(client, request) + publication: dict[str, Any] = {"resume_reused_frozen_candidate": True} + else: + inputs = hydrate_normal(client, request) + reduced = reduce_and_render(inputs, request) + validation = invariant_results(inputs, reduced, request) + material = candidate_material(inputs, reduced, validation, request) + publication = publish_candidate(client, request, material) + approved, content_change, review_rows = validate_review_receipts(client, request, material) + return final_status(client, request, preflight_digest, inputs, material, publication, approved, content_change, review_rows) + + + def publish_post_preflight_failure( + client: McpClient, request: Mapping[str, Any], preflight_digest: str, error: Mapping[str, Any], + ) -> dict[str, Any]: + """Preserve a closed diagnostic, then publish the failure barrier last.""" + root = request["stage2_run_root_ref"] + diagnostic = { + "schema_version": "stage2_s2_40_technical_diagnostic.v1", + "writer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "reason_codes": [str(error.get("code", "INLINE_RUNTIME_ERROR"))], + "error": dict(error), "preflight_snapshot_digest": preflight_digest, + } + diagnostic_id = digest(diagnostic) + client.write_immutable( + join_path(root, "diagnostic", f"failure-{diagnostic_id}.json"), + canonical_bytes(diagnostic), + ) + return write_terminal_status( + client, request, workflow_phase="DIAGNOSTIC_ONLY", + route="STOP_TECHNICAL_INCOMPLETE", candidate_content_digest=None, + run_technical_status="TECHNICAL_INCOMPLETE", + artifact_technical_status="NOT_PRODUCED", legal_readiness="NOT_ASSESSED", + ) + + + def run() -> int: + localdocs: McpClient | None = None + request: dict[str, Any] | None = None + receipt: dict[str, Any] + exit_code = 0 + preflight_digest: str | None = None + output_schema_store: dict[str, Mapping[str, Any]] | None = None + try: + with contextlib.redirect_stdout(io.StringIO()): + if HEX64.fullmatch(INLINE_USER_HASH) is None or HEX64.fullmatch(INLINE_WORKSPACE_HASH) is None: + raise S240Error("INLINE_CONTEXT_UNBOUND", "AgentBackend user/workspace substitutions are required") + localdocs = McpClient(LOCALDOCS_URL, "localdocs") + localdocs.initialize() + request_raw = localdocs.read_binary(REQUEST_PATH) + request = validate_request(request_raw) + request["_request_sha256"] = digest(request_raw) + preflight_digest = preflight(localdocs, request) + output_schema_store = load_output_schema_store(localdocs) + publication = status_only(localdocs, request, preflight_digest) if request["entry_route"] == "TO_S2_40_STATUS_ONLY" else normal_route(localdocs, request, preflight_digest) + status = publication["status"] + receipt = { + "schema_version": "stage2_s2_40_execution_receipt.v1", + "ok": True, + "workflow_id": WORKFLOW_ID, + "request_id": request["request_id"], + "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "requested_transition": request["requested_transition"], + "workflow_phase": status["workflow_phase"], + "candidate_content_digest": status["candidate_content_digest"], + "route": status["route"], + "run_status_path": publication["status_path"], + "run_status_sha256": publication["status_sha256"], + "error": None, + } + except Exception as exc: + error = exc.as_dict() if isinstance(exc, S240Error) else {"code": "INLINE_RUNTIME_ERROR", "message": str(exc)} + failure_publication: dict[str, Any] | None = None + if localdocs is not None and request is not None and preflight_digest is not None: + try: + failure_publication = publish_post_preflight_failure(localdocs, request, preflight_digest, error) + except Exception as close_exc: + error = { + "code": "POST_PREFLIGHT_FAILURE_AND_SAFE_CLOSE_FAILED", + "message": str(exc), + "safe_close_error": close_exc.as_dict() if isinstance(close_exc, S240Error) else {"message": str(close_exc)}, + } + fallback_binding = request["run_binding_digest"] if request is not None else "0" * 64 + receipt = { + "schema_version": "stage2_s2_40_execution_receipt.v1", + "ok": False, + "workflow_id": WORKFLOW_ID, + "request_id": request["request_id"] if request is not None else "UNBOUND", + "run_binding_digest": fallback_binding, + "candidate_attempt_id": request["candidate_attempt_id"] if request is not None else "UNBOUND", + "requested_transition": request["requested_transition"] if request is not None else "FREEZE", + "workflow_phase": "DIAGNOSTIC_ONLY", + "candidate_content_digest": None, + "route": "STOP_TECHNICAL_INCOMPLETE", + "run_status_path": failure_publication["status_path"] if failure_publication is not None else None, + "run_status_sha256": failure_publication["status_sha256"] if failure_publication is not None else None, + "error": error, + } + exit_code = 2 + finally: + if localdocs is not None: + localdocs.close() + if output_schema_store is not None: + validate_schema_instance( + receipt, "schemas/deployment.schema.json#/$defs/s2_40_execution_receipt", + output_schema_store, code="GENERATED_EXECUTION_RECEIPT_SCHEMA", + ) + sys.stdout.buffer.write(canonical_bytes(receipt)) + return exit_code + + + if __name__ == "__main__": + raise SystemExit(run()) + task_procedure: + IN: + nexts: + - Task_S2_40_deterministic_finalizer + wait_until: [] + Task_S2_40_deterministic_finalizer: + nexts: + - OUT + wait_until: + - IN + OUT: + nexts: [] + wait_until: + - Task_S2_40_deterministic_finalizer diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_code_executor_binding.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_code_executor_binding.yml index 84266608..821c3e3c 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_code_executor_binding.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_code_executor_binding.yml @@ -9,7 +9,7 @@ stage_bindings: agent_script_ref: asset_id: AGENT-S2_00-INLINE path: agent_scripts/Stage_2_S2_00.yml - sha256: 8d9583ce7b039ef848abfcbcdb27ac50a2e8a4e279a745b4779bcd90fc17cf64 + sha256: 94c2744d71d222cfb5cc1b2a0d33a6cda20079439823de431eef378a2fa5c943 schema_id: liti_agent_yaml.v1 binding_status: BOUND workflow_contract_ref: @@ -21,18 +21,18 @@ stage_bindings: inline_code_receipt_ref: asset_id: RECEIPT-S2_00-INLINE-CODE path: manifest/s2_00_inline_code_receipt.json - sha256: ced01ef57a2e5341b1f7ddbf810ff3c6fb85fbb3cf7cf80836328a8a971835b4 + sha256: 36af21949e5ef53a3d39df8ea9491c64da43abcc4f5e42e13db9bb391da843b8 schema_id: stage2_s2_00_inline_code_receipt.v2 binding_status: BOUND stage2_release_ref: asset_id: RELEASE-STAGE2-CLEAN path: manifest/stage2_release.json - sha256: 579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81 + sha256: 9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53 schema_id: stage2_release.v2 binding_status: BOUND - expected_release_sha256: 579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81 - agent_script_sha256: 8d9583ce7b039ef848abfcbcdb27ac50a2e8a4e279a745b4779bcd90fc17cf64 - canonical_code_sha256: 612bf08c26a2b96c827a774d79789a9902ffbf18fdd181a157dae40e25b5f8ca + expected_release_sha256: 9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53 + agent_script_sha256: 94c2744d71d222cfb5cc1b2a0d33a6cda20079439823de431eef378a2fa5c943 + canonical_code_sha256: e3f87725d5a6496189e7c411ef940dd8a7b3a9ff5b00535803bf98fa0cc4373e mcp_server_id: code-executor tool_name: run_code language: python @@ -73,7 +73,7 @@ stage_bindings: agent_path: agent_scripts/Stage_2_S2_10.yml s2_10_agent_sha256: 122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272 llm_binding_path: deployment/stage2_s2_10_llm_binding.yml - s2_10_llm_binding_sha256: 9d20b264e753c2f52e8d096edab363ace0fecf2ec8357605d1a9cb47c9c2b930 + s2_10_llm_binding_sha256: 9b5d69f1316a0b9fba7b41097ee92142cf42485c8deb0be876d9e9329c317a04 owner_binding_status: HASH_BOUND_LIVE_ADMISSION_PENDING s2_00_override_allowed: false live_admission_status: PENDING_SECRET_BINDING @@ -86,7 +86,7 @@ stage_bindings: agent_script_ref: asset_id: AGENT-S2_20-INLINE path: agent_scripts/Stage_2_S2_20.yml - sha256: ac81d164309e5301083d0971e1736d128691fd9b18558ac4ade3f0246a43c2d7 + sha256: 3c4e6a7404f5b6a6b2403824c3cd9e71db566d4f2865bd4de3e6fd9d07824bd6 schema_id: liti_agent_yaml.v1 binding_status: BOUND workflow_contract_ref: @@ -98,18 +98,18 @@ stage_bindings: inline_code_receipt_ref: asset_id: RECEIPT-S2_20-INLINE-CODE path: manifest/s2_20_inline_code_receipt.json - sha256: 60000d2412a757e9b2ab2525eedb08ebda20ec02a49f5b1b0c4e89e6a0aeca2b + sha256: 65e29f10f065cdd77281aa47acaf341edb38b0595aab0aa9f04bbee3a4718608 schema_id: stage2_s2_20_inline_code_receipt.v1 binding_status: BOUND stage2_release_ref: asset_id: RELEASE-STAGE2-CLEAN path: manifest/stage2_release.json - sha256: 579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81 + sha256: 9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53 schema_id: stage2_release.v2 binding_status: BOUND - expected_release_sha256: 579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81 - agent_script_sha256: ac81d164309e5301083d0971e1736d128691fd9b18558ac4ade3f0246a43c2d7 - canonical_code_sha256: eeb353b837cf5c2ecfb07fc7375eca03ac4e5c3df9254266d5690cbf14df7138 + expected_release_sha256: 9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53 + agent_script_sha256: 3c4e6a7404f5b6a6b2403824c3cd9e71db566d4f2865bd4de3e6fd9d07824bd6 + canonical_code_sha256: 6f1f503378242cf64cf8f0838af2164ab1103bc7031c8a6873f4ee89be66f7fd mcp_server_id: code-executor tool_name: run_code language: python @@ -229,6 +229,87 @@ stage_bindings: downstream_handoff_owner: null live_admission_status: PENDING_SECRET_BINDING legacy_fallbacks: [] +- stage_id: S2_40 + binding_id: S2-BINDING-S2_40-CODE-EXECUTOR-V1 + workflow_id: S2_40 + execution_class: NON-LLM-DETERMINISTIC + active_runtime_authority: false + agent_script_ref: + asset_id: AGENT-S2_40-INLINE + path: agent_scripts/Stage_2_S2_40.yml + sha256: 5cbe2ac9aa73d95a5fa4e6cf71d7d8f0ad83aa05536f573c13e42505ef5d46f7 + schema_id: liti_agent_yaml.v1 + binding_status: BOUND + workflow_contract_ref: + asset_id: WF-S2_40 + path: workflows/S2_40_final_review_render_and_commit.yml + sha256: ab1e5f593db41c1f26f9510c00d657221da53d08f011b2c4cf341a764a18d874 + schema_id: stage2_s2_40_final_review_render_and_commit.v1 + binding_status: BOUND + inline_code_receipt_ref: + asset_id: RECEIPT-S2_40-INLINE-CODE + path: manifest/s2_40_inline_code_receipt.json + sha256: 9bd0cfaee8d9e78480ab80a2fa541414c7ad0565439fa0f4661701fcdfde6526 + schema_id: stage2_s2_40_inline_code_receipt.v1 + binding_status: BOUND + stage2_release_ref: + asset_id: RELEASE-STAGE2-CLEAN + path: manifest/stage2_release.json + sha256: 9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53 + schema_id: stage2_release.v2 + binding_status: BOUND + expected_release_sha256: 9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53 + agent_script_sha256: 5cbe2ac9aa73d95a5fa4e6cf71d7d8f0ad83aa05536f573c13e42505ef5d46f7 + canonical_code_sha256: e521e1a65294a769cd6bf20edb159f8720c105b60cb769885aa416c8c763dcef + 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_40_request.json + read_path_allowlist: + - stage2_control/s2_40_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/manifest/stage2_deterministic_admission_receipt.json + - Default_Agent/Stage_2_Clean/manifest/s2_40_inline_code_receipt.json + - Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml + - Default_Agent/Stage_2_Clean/deployment/stage2_code_executor_binding.yml + - Default_Agent/Stage_2_Clean/schemas/ingress.schema.json + - Default_Agent/Stage_2_Clean/schemas/context.schema.json + - Default_Agent/Stage_2_Clean/schemas/s2_10.schema.json + - Default_Agent/Stage_2_Clean/schemas/domain_verdict.schema.json + - Default_Agent/Stage_2_Clean/schemas/relief_plan.schema.json + - Default_Agent/Stage_2_Clean/schemas/binding_retrieval.schema.json + - Default_Agent/Stage_2_Clean/schemas/calculation.schema.json + - Default_Agent/Stage_2_Clean/schemas/draft_atoms.schema.json + - Default_Agent/Stage_2_Clean/schemas/review_status.schema.json + - Default_Agent/Stage_2_Clean/schemas/package.schema.json + - Default_Agent/Stage_2_Clean/registry/review/review_policy_registry.yml + - Default_Agent/Stage_2_Clean/renderers/.yml + - stage2_runs/by-binding// + - stage2_runs/by-binding//review/receipts/.json + - stage2_runs/by-binding//control/run_status.json + write_root_rule: stage2_runs/by-binding// + external_mcp_contract: null + egress_profile_id: S2_40_LOCALDOCS_ONLY_V1 + egress_profile_status: PENDING_LIVE_VERIFICATION + downstream_handoff_owner: null + live_admission_status: PENDING_SECRET_BINDING + legacy_fallbacks: [] legacy_fallbacks: [] embedded_task_bindings: - execution_unit_id: S2_30::Task_S2_30_dispatch_planner @@ -242,30 +323,30 @@ embedded_task_bindings: agent_script_ref: asset_id: AGENT-S2_30-INLINE path: agent_scripts/Stage_2_S2_30.yml - sha256: 6da21b319d10268e5f1959d085173d22017e4910c7222fd5e6daf72628629773 + sha256: d0804526941207395c9b64a314b124ff8e919c6852e828d829dc45a9feb3ccdd schema_id: liti_agent_yaml.v1 binding_status: BOUND workflow_contract_ref: asset_id: WF-S2_30 path: workflows/S2_30_claim_group_draft_map.yml - sha256: 498715993d796f82a8c9e790a62bee6885c05813488fd0a11200f46c07665162 + sha256: b266e7b7ae8939b087bfdb7b34fff8b9c6011c835560ab690991d856ced0cc15 schema_id: stage2_s2_30_claim_group_draft_map.v1 binding_status: BOUND inline_code_receipt_ref: asset_id: RECEIPT-S2_30-INLINE-CODE path: manifest/s2_30_inline_code_receipt.json - sha256: 78fb197d50ec706be35cf1766bb9e9fee1767a8e61109603313821dd6040f552 + sha256: 8d1618771cf1f72aa3c6a5a4544fe6b6e949ccc7ecfef56f166561971beee896 schema_id: stage2_s2_30_inline_code_receipt.v1 binding_status: BOUND stage2_release_ref: asset_id: RELEASE-STAGE2-CLEAN path: manifest/stage2_release.json - sha256: 579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81 + sha256: 9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53 schema_id: stage2_release.v2 binding_status: BOUND - expected_release_sha256: 579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81 - agent_script_sha256: 6da21b319d10268e5f1959d085173d22017e4910c7222fd5e6daf72628629773 - canonical_code_sha256: 7814e64bfdbf5992d8009556b5a81268d99a0300d0b8f419c8c6384d90a906c9 + expected_release_sha256: 9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53 + agent_script_sha256: d0804526941207395c9b64a314b124ff8e919c6852e828d829dc45a9feb3ccdd + canonical_code_sha256: 1f7f3b842afbd3f1034f094d6341288effc9804a03920ada4bf8cfd512464e4c mcp_server_id: code-executor tool_name: run_code language: python diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_s2_10_llm_binding.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_s2_10_llm_binding.yml index 764eaf78..d7befebc 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_s2_10_llm_binding.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_s2_10_llm_binding.yml @@ -51,7 +51,7 @@ prompt_contract: selected_context_wrapper_sha256: c43c88cad59f2e9c88d944d4997551063e133207398dee0633af53e2bc5bcab6 cluster_payload_wrapper_sha256: aaffb47bb21a975a13075901f3152d7a41b6e1661fa1626f42e678ba8abfdda8 projection_receipt_path: manifest/s2_10_inline_prompt_projection_receipt.json - projection_receipt_sha256: 7f64a192e7edda7c0e4025b9f1995dcd21c38aba15a018d232f9f05bcba35863 + projection_receipt_sha256: b7fdef2ad05f251bdede9473d3b69c0f169ab7f4a059b393429ff76f739f703e canonical_source_paths: - prompts/P00_system_and_safety_contract.md - prompts/P10_legal_resolution_contract.md diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_s2_30_llm_binding.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_s2_30_llm_binding.yml index e4a19813..6a447ce4 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_s2_30_llm_binding.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/deployment/stage2_s2_30_llm_binding.yml @@ -2,18 +2,18 @@ schema_version: stage2_s2_30_llm_binding.v1 binding_status: PENDING_EXTERNAL_PLATFORM_BINDING agent_ref: path: agent_scripts/Stage_2_S2_30.yml - sha256: 6da21b319d10268e5f1959d085173d22017e4910c7222fd5e6daf72628629773 + sha256: d0804526941207395c9b64a314b124ff8e919c6852e828d829dc45a9feb3ccdd workflow_ref: path: workflows/S2_30_claim_group_draft_map.yml - sha256: 498715993d796f82a8c9e790a62bee6885c05813488fd0a11200f46c07665162 - size_bytes: 12932 + sha256: b266e7b7ae8939b087bfdb7b34fff8b9c6011c835560ab690991d856ced0cc15 + size_bytes: 15221 schema_ref: path: schemas/draft_atoms.schema.json - sha256: 6cbb81f8cc857173efda0ef3a95c3d39c64f057a64ab1927cf6a5967c592d9ce - size_bytes: 57750 + sha256: 5107b64f01ffb3633a829c10652747760a5035c9cc07227c546e3f543005eda9 + size_bytes: 68470 planner_ref: path: runtime/s2_30_dispatch_planner.py - sha256: 7814e64bfdbf5992d8009556b5a81268d99a0300d0b8f419c8c6384d90a906c9 + sha256: 1f7f3b842afbd3f1034f094d6341288effc9804a03920ada4bf8cfd512464e4c model: provider: openai model_id: gpt-5.6-sol @@ -30,10 +30,10 @@ prompt_contract: - S30 inline_common_prompt_sha256: a90ac95f0b24ea938a16699f34ef7f17eb870edcbd8964ba4f6709e36e1bbcc0 inline_static_prompt_sha256: 577efa2c3334298ec60188b9f0066f834e072dc99f785b3c6ab4d05a47fac18a - projection_receipt_sha256: 2ea4d273eb3aa23550159dc4f821e1c3863fc457a48ed429a7c9522bfa293eac + projection_receipt_sha256: 1aa650d3c389ba27ce43e514295c7c2ce629583dc96220618fd97dea399d0757 runtime_external_prompt_read_allowed: false planner_contract: - inline_code_receipt_sha256: 78fb197d50ec706be35cf1766bb9e9fee1767a8e61109603313821dd6040f552 + inline_code_receipt_sha256: 8d1618771cf1f72aa3c6a5a4544fe6b6e949ccc7ecfef56f166561971beee896 legal_reasoning_allowed: false persistent_write_allowed: false native_adapter: @@ -55,14 +55,14 @@ native_adapter: producer_contract: material: algorithm_id: S2_30-PRODUCER-CONTRACT-PROJECTION-V1 - raw_model_output_schema_sha256: 6cbb81f8cc857173efda0ef3a95c3d39c64f057a64ab1927cf6a5967c592d9ce - strict_validator_sha256: 30dff7cc1717c792a6da9bcbd3533c82c9bf3902f09fc9fe92a086c2e13694c6 + raw_model_output_schema_sha256: 5107b64f01ffb3633a829c10652747760a5035c9cc07227c546e3f543005eda9 + strict_validator_sha256: 14e4eefb73d40d004c95017c82cdc23ac1c1c0a54ea34562dcf322f6364ae27a strict_validator_algorithm_id: S2_30-OFFLINE-NATIVE-ADAPTER-ORACLE-V1 atom_id_algorithm_id: S2_30-DETERMINISTIC-ATOM-ID-V1 two_pass_rewrite_algorithm_id: S2_30-TWO-PASS-LOCAL-REF-REWRITE-V1 context_materializer_algorithm_id: S2_30-EXACT-REF-MATERIALIZER-V1 native_capability_projection_sha256: b284d20dc950db8b8fe015578d10657beda479a55665d34d77319d4f81fa4a68 - s2_30_producer_contract_digest: 337fd978acb335e89ef3ee859bf2333403858b370cbc5466d601317ba027fe4a + s2_30_producer_contract_digest: b0d7e781e8a59ebd9e9ed8db6d04973640b2a127440f32b7bff605103cbc23e0 whole_binding_hash_in_material: false parent_or_child_hash_in_material: false self_referential_digest_fields_excluded: true diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/module_manifest.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/module_manifest.json index 7b700ba8..a037cc14 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/module_manifest.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/module_manifest.json @@ -1 +1 @@ -{"closure_summary":{"build_tool_module_count":1,"cycle_breaking_contract":"AGENT_CODE_RECEIPT_AND_EXECUTOR_BINDING_EXTERNALLY_BIND_RELEASE_RAW_HASH","documentation_mirror_count":46,"executable_agent_hash_included":false,"executor_binding_hash_included":false,"fixture_closure_ref":"tests/fixtures/regression_manifest.json","fixture_descriptor_count":60,"inline_runtime_code_hash_included":false,"module_count":191,"profile_module_count":45,"prompt_module_count":2,"runtime_code_hash_included":false,"s2_20_generic_module_count":115,"self_hash_included":false,"stage2_release_hash_included":false,"test_module_count":48},"documentation_mirrors":[{"byte_identical":true,"mirror_path":"offline_build/build_authority_law_value_release.txt","mirror_sha256":"8c1d9b2f05fa752d50349ed1a4479aafcb17c2f574fa1ebe6b19d2bedc21ffeb","mirror_size_bytes":7213,"runtime_import_allowed":false,"source_path":"offline_build/build_authority_law_value_release.py","source_sha256":"8c1d9b2f05fa752d50349ed1a4479aafcb17c2f574fa1ebe6b19d2bedc21ffeb","source_size_bytes":7213},{"byte_identical":true,"mirror_path":"offline_build/build_corpus_snapshot.txt","mirror_sha256":"96feead66f24d375b9ac379f459de040a9ae1f368e9c05d2911c5b0da54c02c2","mirror_size_bytes":9781,"runtime_import_allowed":false,"source_path":"offline_build/build_corpus_snapshot.py","source_sha256":"96feead66f24d375b9ac379f459de040a9ae1f368e9c05d2911c5b0da54c02c2","source_size_bytes":9781},{"byte_identical":true,"mirror_path":"offline_build/build_release_manifests.txt","mirror_sha256":"c2bf201fe61490b79d1e2d199132d24c1285bda52685b22048d085e1289e8b50","mirror_size_bytes":20196,"runtime_import_allowed":false,"source_path":"offline_build/build_release_manifests.py","source_sha256":"c2bf201fe61490b79d1e2d199132d24c1285bda52685b22048d085e1289e8b50","source_size_bytes":20196},{"byte_identical":true,"mirror_path":"offline_build/build_s2_00_inline_projection.txt","mirror_sha256":"31c96b6abe2eb0ed1f9c9e571e1f4f326307225dfddf40a6670e2d3073ed2ab4","mirror_size_bytes":35198,"runtime_import_allowed":false,"source_path":"offline_build/build_s2_00_inline_projection.py","source_sha256":"31c96b6abe2eb0ed1f9c9e571e1f4f326307225dfddf40a6670e2d3073ed2ab4","source_size_bytes":35198},{"byte_identical":true,"mirror_path":"offline_build/build_s2_10_agent_projection.txt","mirror_sha256":"4359364816c8a58eb414bafae8ccf24fc3766dc611d15f1aa09e48c8fedc8f88","mirror_size_bytes":61930,"runtime_import_allowed":false,"source_path":"offline_build/build_s2_10_agent_projection.py","source_sha256":"4359364816c8a58eb414bafae8ccf24fc3766dc611d15f1aa09e48c8fedc8f88","source_size_bytes":61930},{"byte_identical":true,"mirror_path":"offline_build/build_s2_20_inline_projection.txt","mirror_sha256":"b5c035251621920dd848d672dc6cf840500ce2b60e1e6656f021855681f6fc58","mirror_size_bytes":27865,"runtime_import_allowed":false,"source_path":"offline_build/build_s2_20_inline_projection.py","source_sha256":"b5c035251621920dd848d672dc6cf840500ce2b60e1e6656f021855681f6fc58","source_size_bytes":27865},{"byte_identical":true,"mirror_path":"offline_build/build_s2_30_agent_projection.txt","mirror_sha256":"3ee27b6edee4338ca0d0bd76f5e192d6d1043ea1df3950cb3c8d3b6af5b6433b","mirror_size_bytes":50879,"runtime_import_allowed":false,"source_path":"offline_build/build_s2_30_agent_projection.py","source_sha256":"3ee27b6edee4338ca0d0bd76f5e192d6d1043ea1df3950cb3c8d3b6af5b6433b","source_size_bytes":50879},{"byte_identical":true,"mirror_path":"offline_build/compile_case_type_registry.txt","mirror_sha256":"e415b5179e53f5a7e35e5e1b7749706c783fbf296bf0bf40103e9450df0b2f0c","mirror_size_bytes":9658,"runtime_import_allowed":false,"source_path":"offline_build/compile_case_type_registry.py","source_sha256":"e415b5179e53f5a7e35e5e1b7749706c783fbf296bf0bf40103e9450df0b2f0c","source_size_bytes":9658},{"byte_identical":true,"mirror_path":"offline_build/compile_relief_rule_projection.txt","mirror_sha256":"8412f2ad7b8de4738fbb86a7596def90dbc9d34d4e2f24854e964df476589c2f","mirror_size_bytes":42682,"runtime_import_allowed":false,"source_path":"offline_build/compile_relief_rule_projection.py","source_sha256":"8412f2ad7b8de4738fbb86a7596def90dbc9d34d4e2f24854e964df476589c2f","source_size_bytes":42682},{"byte_identical":true,"mirror_path":"offline_build/validate_s2_10_contract.txt","mirror_sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","mirror_size_bytes":63811,"runtime_import_allowed":false,"source_path":"offline_build/validate_s2_10_contract.py","source_sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","source_size_bytes":63811},{"byte_identical":true,"mirror_path":"offline_build/validate_s2_30_contract.txt","mirror_sha256":"30dff7cc1717c792a6da9bcbd3533c82c9bf3902f09fc9fe92a086c2e13694c6","mirror_size_bytes":90323,"runtime_import_allowed":false,"source_path":"offline_build/validate_s2_30_contract.py","source_sha256":"30dff7cc1717c792a6da9bcbd3533c82c9bf3902f09fc9fe92a086c2e13694c6","source_size_bytes":90323},{"byte_identical":true,"mirror_path":"release_ops/canary_rollback.txt","mirror_sha256":"327356b4f59bb850fcfb680d5caf13038025e3042689f11e1018731058d15241","mirror_size_bytes":1345,"runtime_import_allowed":false,"source_path":"release_ops/canary_rollback.py","source_sha256":"327356b4f59bb850fcfb680d5caf13038025e3042689f11e1018731058d15241","source_size_bytes":1345},{"byte_identical":true,"mirror_path":"release_ops/release_validator.txt","mirror_sha256":"45095d7921f9df600e4331d833057e54d26da68e79dc43e4733bb94fa7da1684","mirror_size_bytes":30130,"runtime_import_allowed":false,"source_path":"release_ops/release_validator.py","source_sha256":"45095d7921f9df600e4331d833057e54d26da68e79dc43e4733bb94fa7da1684","source_size_bytes":30130},{"byte_identical":true,"mirror_path":"runtime/authority/authority_preflight.txt","mirror_sha256":"ffa513bdc7ddb1de895b4e813de9e107c94c36a5955166c7d5cee745584d0dda","mirror_size_bytes":2115,"runtime_import_allowed":false,"source_path":"runtime/authority/authority_preflight.py","source_sha256":"ffa513bdc7ddb1de895b4e813de9e107c94c36a5955166c7d5cee745584d0dda","source_size_bytes":2115},{"byte_identical":true,"mirror_path":"runtime/binding_signature_projection.txt","mirror_sha256":"0ea048355b4abf8cf261bc60735a557ab09d84e325aa42bd4d7acb58f589c6b5","mirror_size_bytes":5843,"runtime_import_allowed":false,"source_path":"runtime/binding_signature_projection.py","source_sha256":"0ea048355b4abf8cf261bc60735a557ab09d84e325aa42bd4d7acb58f589c6b5","source_size_bytes":5843},{"byte_identical":true,"mirror_path":"runtime/c25_case_type_bind.txt","mirror_sha256":"7cda9812225379ef92c34b8ca383aa35bdcbac6afc30b3a21245f5e3ad6aa3af","mirror_size_bytes":3471,"runtime_import_allowed":false,"source_path":"runtime/c25_case_type_bind.py","source_sha256":"7cda9812225379ef92c34b8ca383aa35bdcbac6afc30b3a21245f5e3ad6aa3af","source_size_bytes":3471},{"byte_identical":true,"mirror_path":"runtime/c26_rule_branch_bind.txt","mirror_sha256":"f6d6fb87b005b0a155e24ae93c7550640bfdaa221063af034c3d3e20b46cc6b6","mirror_size_bytes":5089,"runtime_import_allowed":false,"source_path":"runtime/c26_rule_branch_bind.py","source_sha256":"f6d6fb87b005b0a155e24ae93c7550640bfdaa221063af034c3d3e20b46cc6b6","source_size_bytes":5089},{"byte_identical":true,"mirror_path":"runtime/c27_query_plan.txt","mirror_sha256":"d7fe404438e185b2e0351b8b5ac8fc7bd911a63544e71c7c16ffb313dc566777","mirror_size_bytes":6553,"runtime_import_allowed":false,"source_path":"runtime/c27_query_plan.py","source_sha256":"d7fe404438e185b2e0351b8b5ac8fc7bd911a63544e71c7c16ffb313dc566777","source_size_bytes":6553},{"byte_identical":true,"mirror_path":"runtime/c28_weaviate_retrieve.txt","mirror_sha256":"9634c80dd1b77ab652185ef5bd2b67ccbb7d355d2b4661f67d86fa78d0ee6395","mirror_size_bytes":12083,"runtime_import_allowed":false,"source_path":"runtime/c28_weaviate_retrieve.py","source_sha256":"9634c80dd1b77ab652185ef5bd2b67ccbb7d355d2b4661f67d86fa78d0ee6395","source_size_bytes":12083},{"byte_identical":true,"mirror_path":"runtime/c29_pack_verify.txt","mirror_sha256":"4318f95c9c38391a455613b7411cee923288d19748f3c0946e86c588be718b9d","mirror_size_bytes":5721,"runtime_import_allowed":false,"source_path":"runtime/c29_pack_verify.py","source_sha256":"4318f95c9c38391a455613b7411cee923288d19748f3c0946e86c588be718b9d","source_size_bytes":5721},{"byte_identical":true,"mirror_path":"runtime/calculators/registry_engine.txt","mirror_sha256":"173da5185caa6d4a82a7735018c9121ef42481cad8d83b9574c9f432912c556d","mirror_size_bytes":11417,"runtime_import_allowed":false,"source_path":"runtime/calculators/registry_engine.py","source_sha256":"173da5185caa6d4a82a7735018c9121ef42481cad8d83b9574c9f432912c556d","source_size_bytes":11417},{"byte_identical":true,"mirror_path":"tests/s2_00/test_canonical_ids.txt","mirror_sha256":"c463506a90859daeef7eafddc4a6c08c563e2ae73200d921c1f00efb7bc24361","mirror_size_bytes":2275,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_canonical_ids.py","source_sha256":"c463506a90859daeef7eafddc4a6c08c563e2ae73200d921c1f00efb7bc24361","source_size_bytes":2275},{"byte_identical":true,"mirror_path":"tests/s2_00/test_cluster_bundle_compile.txt","mirror_sha256":"aa31cc87246a5c8f6b82e98b9f86dd654bc9306dfc7849af19ec16cfd5137a2a","mirror_size_bytes":25557,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_cluster_bundle_compile.py","source_sha256":"aa31cc87246a5c8f6b82e98b9f86dd654bc9306dfc7849af19ec16cfd5137a2a","source_size_bytes":25557},{"byte_identical":true,"mirror_path":"tests/s2_00/test_conservation.txt","mirror_sha256":"c906dff7e11678a60556818d1baf24e66844d9c982c9d333ec339d2ed9ca6061","mirror_size_bytes":5562,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_conservation.py","source_sha256":"c906dff7e11678a60556818d1baf24e66844d9c982c9d333ec339d2ed9ca6061","source_size_bytes":5562},{"byte_identical":true,"mirror_path":"tests/s2_00/test_failure_and_atomic_publish.txt","mirror_sha256":"128a82b4e413132c0ff4a61ae2dc7f85b6c1c050ea33ccf4e53f23ccc993aba6","mirror_size_bytes":25922,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_failure_and_atomic_publish.py","source_sha256":"128a82b4e413132c0ff4a61ae2dc7f85b6c1c050ea33ccf4e53f23ccc993aba6","source_size_bytes":25922},{"byte_identical":true,"mirror_path":"tests/s2_00/test_inline_code_parity.txt","mirror_sha256":"8f0f55e8e1b970de572129946ab8bf34967c7fd84e316a9193509cab07a455ed","mirror_size_bytes":15928,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_inline_code_parity.py","source_sha256":"8f0f55e8e1b970de572129946ab8bf34967c7fd84e316a9193509cab07a455ed","source_size_bytes":15928},{"byte_identical":true,"mirror_path":"tests/s2_00/test_resolver_source_lock.txt","mirror_sha256":"51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e","mirror_size_bytes":14423,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_resolver_source_lock.py","source_sha256":"51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e","source_size_bytes":14423},{"byte_identical":true,"mirror_path":"tests/s2_00/test_schema_hash_and_signals.txt","mirror_sha256":"14207eedd80caaf24d85377617fb754bdeecc80ba9b2a291d6ac5d09ab0a6191","mirror_size_bytes":12842,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_schema_hash_and_signals.py","source_sha256":"14207eedd80caaf24d85377617fb754bdeecc80ba9b2a291d6ac5d09ab0a6191","source_size_bytes":12842},{"byte_identical":true,"mirror_path":"tests/s2_10/test_agent_contract.txt","mirror_sha256":"0a7b41894733b743d11ff88f0817a87bdbc98be317d8b3410baa8e9401b5b7bd","mirror_size_bytes":8076,"runtime_import_allowed":false,"source_path":"tests/s2_10/test_agent_contract.py","source_sha256":"0a7b41894733b743d11ff88f0817a87bdbc98be317d8b3410baa8e9401b5b7bd","source_size_bytes":8076},{"byte_identical":true,"mirror_path":"tests/s2_10/test_domain_verdict_contract.txt","mirror_sha256":"9f2547a8c590b7df2aa09d0c3808766bf16be321a448742020d9a3476e7d837f","mirror_size_bytes":10242,"runtime_import_allowed":false,"source_path":"tests/s2_10/test_domain_verdict_contract.py","source_sha256":"9f2547a8c590b7df2aa09d0c3808766bf16be321a448742020d9a3476e7d837f","source_size_bytes":10242},{"byte_identical":true,"mirror_path":"tests/s2_10/test_prompt_cache_and_boundaries.txt","mirror_sha256":"b77e63b19ba5a843df88180a5e7ac0441256682ea9aa92dc490415a75f1dcee5","mirror_size_bytes":11365,"runtime_import_allowed":false,"source_path":"tests/s2_10/test_prompt_cache_and_boundaries.py","source_sha256":"b77e63b19ba5a843df88180a5e7ac0441256682ea9aa92dc490415a75f1dcee5","source_size_bytes":11365},{"byte_identical":true,"mirror_path":"tests/s2_10/test_release_adapter_retry.txt","mirror_sha256":"16b7b1419550b553bbbd42dbcba7e8418124ba5c41adfcae59639d3db9347c0b","mirror_size_bytes":7757,"runtime_import_allowed":false,"source_path":"tests/s2_10/test_release_adapter_retry.py","source_sha256":"16b7b1419550b553bbbd42dbcba7e8418124ba5c41adfcae59639d3db9347c0b","source_size_bytes":7757},{"byte_identical":true,"mirror_path":"tests/s2_10/test_wave_dispatch.txt","mirror_sha256":"f7e59189ed93585c16c55943f7cc3ed464091fb23a9ea086e6e209cf14677a48","mirror_size_bytes":9894,"runtime_import_allowed":false,"source_path":"tests/s2_10/test_wave_dispatch.py","source_sha256":"f7e59189ed93585c16c55943f7cc3ed464091fb23a9ea086e6e209cf14677a48","source_size_bytes":9894},{"byte_identical":true,"mirror_path":"tests/s2_20/test_agent_and_inline_parity.txt","mirror_sha256":"0f73c112b28088be191b6717cb24cac468762cc286f8dc806bf65d98a95bf262","mirror_size_bytes":2773,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_agent_and_inline_parity.py","source_sha256":"0f73c112b28088be191b6717cb24cac468762cc286f8dc806bf65d98a95bf262","source_size_bytes":2773},{"byte_identical":true,"mirror_path":"tests/s2_20/test_calculation_and_reports.txt","mirror_sha256":"c1bd36c351173d25e6d8e68d1a90d738b90aabb51b201ca13f4370654e584e00","mirror_size_bytes":3199,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_calculation_and_reports.py","source_sha256":"c1bd36c351173d25e6d8e68d1a90d738b90aabb51b201ca13f4370654e584e00","source_size_bytes":3199},{"byte_identical":true,"mirror_path":"tests/s2_20/test_inline_output_schema.txt","mirror_sha256":"e2cb938dd639874a4b150997d66eacd89b22016c8fd3385a243edf781cd3e85b","mirror_size_bytes":43574,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_inline_output_schema.py","source_sha256":"e2cb938dd639874a4b150997d66eacd89b22016c8fd3385a243edf781cd3e85b","source_size_bytes":43574},{"byte_identical":true,"mirror_path":"tests/s2_20/test_offline_compilers.txt","mirror_sha256":"5e75f659a9e5add1345f1596c92c0b143cb1e48110c746a8785fb5b38f1371af","mirror_size_bytes":20252,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_offline_compilers.py","source_sha256":"5e75f659a9e5add1345f1596c92c0b143cb1e48110c746a8785fb5b38f1371af","source_size_bytes":20252},{"byte_identical":true,"mirror_path":"tests/s2_20/test_option_group_and_binding.txt","mirror_sha256":"6021d93fb47377cf6c00ccb5a880a7e85987ec5a1ed7976a84baca2d7fb39985","mirror_size_bytes":6171,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_option_group_and_binding.py","source_sha256":"6021d93fb47377cf6c00ccb5a880a7e85987ec5a1ed7976a84baca2d7fb39985","source_size_bytes":6171},{"byte_identical":true,"mirror_path":"tests/s2_20/test_plan_publish_and_release.txt","mirror_sha256":"eb5a96109d95d4b78473f79129c441f9be9b015bba1157dfa4d4d3616d03525e","mirror_size_bytes":13734,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_plan_publish_and_release.py","source_sha256":"eb5a96109d95d4b78473f79129c441f9be9b015bba1157dfa4d4d3616d03525e","source_size_bytes":13734},{"byte_identical":true,"mirror_path":"tests/s2_20/test_regression_manifest_closure.txt","mirror_sha256":"886ae584a7846acdb5499d52e1ae8ec177e8d1dc34aa1d43e99dbebafa255516","mirror_size_bytes":8493,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_regression_manifest_closure.py","source_sha256":"886ae584a7846acdb5499d52e1ae8ec177e8d1dc34aa1d43e99dbebafa255516","source_size_bytes":8493},{"byte_identical":true,"mirror_path":"tests/s2_20/test_retrieval_and_pack.txt","mirror_sha256":"c314cf27511b0fe065b8961196084a28b1c7c5cb2fed3dd5c8765172ba40462f","mirror_size_bytes":6654,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_retrieval_and_pack.py","source_sha256":"c314cf27511b0fe065b8961196084a28b1c7c5cb2fed3dd5c8765172ba40462f","source_size_bytes":6654},{"byte_identical":true,"mirror_path":"tests/s2_30/test_agent_contract.txt","mirror_sha256":"e7d0f069f8c60ff5c5194a9ea9289376e2fd81a50d1b4b18b1b6abf5f2827529","mirror_size_bytes":11630,"runtime_import_allowed":false,"source_path":"tests/s2_30/test_agent_contract.py","source_sha256":"e7d0f069f8c60ff5c5194a9ea9289376e2fd81a50d1b4b18b1b6abf5f2827529","source_size_bytes":11630},{"byte_identical":true,"mirror_path":"tests/s2_30/test_dispatch_materialization.txt","mirror_sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","mirror_size_bytes":13911,"runtime_import_allowed":false,"source_path":"tests/s2_30/test_dispatch_materialization.py","source_sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","source_size_bytes":13911},{"byte_identical":true,"mirror_path":"tests/s2_30/test_draft_atom_contract.txt","mirror_sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","mirror_size_bytes":10484,"runtime_import_allowed":false,"source_path":"tests/s2_30/test_draft_atom_contract.py","source_sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","source_size_bytes":10484},{"byte_identical":true,"mirror_path":"tests/s2_30/test_prompt_cache_and_boundaries.txt","mirror_sha256":"9063ca0a247cf06f55e94e586a7ab8ac21facd9f6c607ce4799047aea365e287","mirror_size_bytes":5142,"runtime_import_allowed":false,"source_path":"tests/s2_30/test_prompt_cache_and_boundaries.py","source_sha256":"9063ca0a247cf06f55e94e586a7ab8ac21facd9f6c607ce4799047aea365e287","source_size_bytes":5142},{"byte_identical":true,"mirror_path":"tests/s2_30/test_release_adapter_retry.txt","mirror_sha256":"b15505567db55689527056d608a1cb12d3c605e9df860afba607a6e3e276a0ef","mirror_size_bytes":9241,"runtime_import_allowed":false,"source_path":"tests/s2_30/test_release_adapter_retry.py","source_sha256":"b15505567db55689527056d608a1cb12d3c605e9df860afba607a6e3e276a0ef","source_size_bytes":9241}],"forbidden_contract_registry":[{"code":"LEGACY-STAGE2-V0-V3","legacy_runtime_dependency_allowed":false,"meaning":"The clean S2_00 workflow and runtime must not read or execute legacy Stage 2 v.0-v.3 specifications."},{"code":"LEGACY-STAGE2-LOADER","legacy_runtime_dependency_allowed":false,"meaning":"The historical host loader and loader binding are reference-only and cannot authorize, execute, or provide fallback for S2_00."},{"code":"RAW-STAGE1-REREAD","legacy_runtime_dependency_allowed":false,"meaning":"S2_10 must consume immutable bounded cluster projections and must not rediscover raw Stage 1 inputs."},{"code":"S2_40-PLEADING-RENDER-IN-STATUS-ONLY","legacy_runtime_dependency_allowed":false,"meaning":"The S2_40 status-only entrypoint must not render or commit pleading text."}],"implementation_status":"OFFLINE_HYBRID_RESEAL_COMPLETE_LIVE_ADMISSION_PENDING","manifest_digest":"6167e721c43ab0819c68d17bd45d10e5044caf76dc80f0bf4d35f14803b2ba68","manifest_digest_contract":{"algorithm_id":"STAGE2-MODULE-MANIFEST-DIGEST-V1","array_order":"PRESERVE_DECLARED_ORDER","canonicalization_algorithm_id":"STAGE2-CANONICAL-JSON-V1","digest_algorithm":"sha256","digest_scope":"ENTIRE_DOCUMENT_AFTER_REMOVING_TOP_LEVEL_MANIFEST_DIGEST","encoding":"UTF-8","line_termination":"LF_ONE_TRAILING_NEWLINE","non_finite_numbers_allowed":false,"object_key_order":"SORT_CODEPOINT","verification_status":"DEV_VERIFIED"},"manifest_id":"STAGE2-CLEAN-S2_00-STRUCTURED-HANDOFF-V2-INLINE","manifest_scope":"S2_00_STRUCTURED_CONTEXT_HANDOFF_AND_SHARED_CONTRACTS","manifest_status":"DEV_HASH_BOUND_DOWNSTREAM_HYBRID_RELEASE_PENDING","modules":[{"asset_version":"s2_00.1.2","authority_ids":[],"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.v2.json","https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json"],"dependency_module_ids":["SCHEMA-INGRESS","SCHEMA-CONTEXT","SCHEMA-REVIEW-STATUS"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"IMPLEMENTED_DECLARATIVE_CONTRACT","incompatible_module_ids":[],"inputs":["STAGE1-ALLOWLIST-V1","STAGE1-DEPLOYMENT-CLOSURE-2026-08-29"],"module_id":"WF-S2_00","module_kind":"WORKFLOW","outputs":["S2_00-NORMAL-BRANCH","S2_00-DIAGNOSTIC-BRANCH"],"owner":"Stage_2_workflow_maintainer","path":"workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml","produced_schema_ids":[],"schema_version":"stage2_workflow_contract.v1.2","scope_predicate":"workflow_id == S2_00","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"3d7ceb86b236668c8c372136f1d1b43a5d0a79d3fb05fd1ef4342bb638190f68","size_bytes":17351},{"asset_version":"s2_00.schema.1.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":[],"module_id":"SCHEMA-INGRESS","module_kind":"JSON_SCHEMA","outputs":["INGRESS-SCHEMA-DEFS"],"owner":"Stage_2_schema_owner","path":"schemas/ingress.schema.json","produced_schema_ids":["https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json"],"schema_version":"stage2_s2_00_ingress.v1.1","scope_predicate":"artifact_family == ingress","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"8fd7b76015b7d7dfbbe056e08999dda7ea8e1012bb16cec50634b08f7ea97302","size_bytes":33444},{"asset_version":"s2_00.schema.2","authority_ids":[],"consumed_schema_ids":["https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json"],"dependency_module_ids":["SCHEMA-REVIEW-STATUS"],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":[],"module_id":"SCHEMA-CONTEXT","module_kind":"JSON_SCHEMA","outputs":["CONTEXT-SCHEMA-DEFS"],"owner":"Stage_2_schema_owner","path":"schemas/context.schema.json","produced_schema_ids":["https://schemas.liti-agent.local/stage2/s2_00/context.schema.v2.json"],"schema_version":"stage2_s2_00_context.v2","scope_predicate":"artifact_family == context","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"29073ffa847d74304228d61306503c0c3798da7db8b5717b1ad6d5b2da98aa92","size_bytes":39054},{"asset_version":"stage2.shared.2","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":[],"module_id":"SCHEMA-DEPLOYMENT","module_kind":"JSON_SCHEMA","outputs":["DEPLOYMENT-SCHEMA-DEFS"],"owner":"Stage_2_deployment_schema_owner","path":"schemas/deployment.schema.json","produced_schema_ids":["https://schemas.liti-agent.local/stage2/shared/deployment.schema.v2.json"],"schema_version":"stage2_deployment.v2","scope_predicate":"artifact_family == deployment","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"573ff946cb5057727fec52d6842c6308d2b3c189c905e40fcb1618dfa08827f9","size_bytes":72345},{"asset_version":"stage2.shared.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":[],"module_id":"SCHEMA-REVIEW-STATUS","module_kind":"JSON_SCHEMA","outputs":["REVIEW-STATUS-SCHEMA-DEFS"],"owner":"Stage_2_review_schema_owner","path":"schemas/review_status.schema.json","produced_schema_ids":["https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json"],"schema_version":"stage2_review_status.v1","scope_predicate":"artifact_family == review_status","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"13f6f1f06946d4074f3d85959f82763e489b2f87cd7bfadb14b594d6223b02e9","size_bytes":11169},{"asset_version":"stage2.cache.2","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["SCHEMA-CONTEXT"],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["RELEASE-SELECTED-CONTEXT-ORDERED-REFS","S2_00-COHORT-MEMBERSHIP","S2_00-MEMBER-SLICE-REF-SET"],"module_id":"CACHE-POLICY-STRUCTURED-CONTEXT-HANDOFF","module_kind":"CACHE_POLICY","outputs":["S2_00-CONTEXT-MATERIALIZATION-RECEIPT","S2_10-CACHE-IDENTITY-INPUT"],"owner":"Stage_2_cache_policy_owner","path":"registry/cache/prompt_cache_policy.yml","produced_schema_ids":[],"schema_version":"stage2_prompt_cache_policy.v2","scope_predicate":"consumer == S2_10","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"32b638073b721a9f395d3476105e57236be4e076be81fd6e93f1475b29b93e2a","size_bytes":7527},{"asset_version":"s2_00.test.1.2","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"module_id":"REGRESSION-MANIFEST-S2_00","module_kind":"TEST_MANIFEST","outputs":["FIXTURE-RESULT-DIGEST"],"owner":"Stage_2_regression_owner","path":"tests/fixtures/regression_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_00_regression_manifest.v1","scope_predicate":"workflow_id == S2_00","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"bf810812dc5915273272d898e8383fc20f7c4b2a082d6b65e9dd0ff3ab34d947","size_bytes":53447},{"asset_version":"s2_40.status_only.1","authority_ids":[],"consumed_schema_ids":["https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json","https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json"],"dependency_module_ids":["WF-S2_00","SCHEMA-REVIEW-STATUS"],"forbidden_contract_codes":["S2_40-PLEADING-RENDER-IN-STATUS-ONLY"],"implementation_status":"DRAFT_HANDOFF_STUB_HASH_BOUND","incompatible_module_ids":[],"inputs":["ingress/ingress_status.json","ingress/technical_diagnostic.json","ingress/stage1_input_manifest.json","ingress/intake_report.json","review/issue_ledger.base.json"],"module_id":"WF-S2_40-STATUS-ONLY","module_kind":"WORKFLOW","outputs":["control/run_status.json"],"owner":"Stage_2_S2_40_owner","path":"workflows/S2_40_final_review_render_and_commit.yml","produced_schema_ids":["stage2_status_only_commit.v1"],"schema_version":"stage2_workflow_contract.v1","scope_predicate":"entrypoint_id == S2_40_STATUS_ONLY","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"b7d83b56771d005e6185746c3469d42f7781927522b8a8d42648301eceaadadd","size_bytes":3685},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_resolver_source_lock.txt","mirror_sha256":"51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e","mirror_size_bytes":14423,"module_id":"TEST-S2_00-RESOLVER-SOURCE-LOCK","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_resolver_source_lock.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == resolver_source_lock","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e","size_bytes":14423},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_schema_hash_and_signals.txt","mirror_sha256":"14207eedd80caaf24d85377617fb754bdeecc80ba9b2a291d6ac5d09ab0a6191","mirror_size_bytes":12842,"module_id":"TEST-S2_00-SCHEMA-HASH-SIGNALS","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_schema_hash_and_signals.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == schema_hash_signals","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"14207eedd80caaf24d85377617fb754bdeecc80ba9b2a291d6ac5d09ab0a6191","size_bytes":12842},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_conservation.txt","mirror_sha256":"c906dff7e11678a60556818d1baf24e66844d9c982c9d333ec339d2ed9ca6061","mirror_size_bytes":5562,"module_id":"TEST-S2_00-CONSERVATION","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_conservation.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == conservation","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"c906dff7e11678a60556818d1baf24e66844d9c982c9d333ec339d2ed9ca6061","size_bytes":5562},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_canonical_ids.txt","mirror_sha256":"c463506a90859daeef7eafddc4a6c08c563e2ae73200d921c1f00efb7bc24361","mirror_size_bytes":2275,"module_id":"TEST-S2_00-CANONICAL-IDS","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_canonical_ids.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == canonical_ids","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"c463506a90859daeef7eafddc4a6c08c563e2ae73200d921c1f00efb7bc24361","size_bytes":2275},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_cluster_bundle_compile.txt","mirror_sha256":"aa31cc87246a5c8f6b82e98b9f86dd654bc9306dfc7849af19ec16cfd5137a2a","mirror_size_bytes":25557,"module_id":"TEST-S2_00-CLUSTER-BUNDLE","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_cluster_bundle_compile.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == cluster_bundle_compile","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"aa31cc87246a5c8f6b82e98b9f86dd654bc9306dfc7849af19ec16cfd5137a2a","size_bytes":25557},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_failure_and_atomic_publish.txt","mirror_sha256":"128a82b4e413132c0ff4a61ae2dc7f85b6c1c050ea33ccf4e53f23ccc993aba6","mirror_size_bytes":25922,"module_id":"TEST-S2_00-FAILURE-ATOMIC-PUBLISH","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_failure_and_atomic_publish.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == failure_atomic_publish","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"128a82b4e413132c0ff4a61ae2dc7f85b6c1c050ea33ccf4e53f23ccc993aba6","size_bytes":25922},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":[],"module_id":"P00","module_kind":"LLM_PROMPT_CONTRACT","outputs":["STATIC_PREFIX_SEGMENT"],"owner":"Stage_2_prompt_owner","path":"prompts/P00_system_and_safety_contract.md","produced_schema_ids":[],"schema_version":"stage2.prompt_contract.v1","scope_predicate":"static_prefix_segment == P00","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e","size_bytes":7304},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P00"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P00"],"module_id":"P10","module_kind":"LLM_PROMPT_CONTRACT","outputs":["STATIC_PREFIX_SEGMENT"],"owner":"Stage_2_prompt_owner","path":"prompts/P10_legal_resolution_contract.md","produced_schema_ids":[],"schema_version":"stage2.prompt_contract.v1","scope_predicate":"static_prefix_segment == P10","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","size_bytes":8712},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-EC-00_CONTRACT_GENERAL","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/EC-00_contract_general.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/EC-00_contract_general.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"a4f7abd9957b3a9e58d05dd559c3c869bf96fd88ea18968a363c6e606e3c0aa8","size_bytes":3789},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-01_JURISTIC_ACT_VALIDITY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-01_juristic_act_validity.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-01_juristic_act_validity.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"0a0d2676f96be321a7bb974b8e4fb1981ab43773f271c99dc86a70cb17d27c99","size_bytes":3808},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-02_CONTRACT_MONEY_CLAIM","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-02_contract_money_claim.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-02_contract_money_claim.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"08e252bccc718ccc44a258bc540afc2567e509239399f4017550df32bac97824","size_bytes":3784},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-03_PARTIES_LIABILITY_SUCCESSION","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-03_parties_liability_succession.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-03_parties_liability_succession.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"4e841d5f640b06a1b52060b82dda39605369cbe26d81655b7918673437e4519c","size_bytes":3799},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-04_UNJUST_ENRICHMENT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-04_unjust_enrichment.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-04_unjust_enrichment.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"31a5966d4c14940e810f870bf4382f1be642f7716ebaaa35193ef32e9b9d95c7","size_bytes":3725},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-05_TORT_GENERAL","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-05_tort_general.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-05_tort_general.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"fe6ea92fc10c4196e0ac83b990bf2606e24024030e7b0002fecdae9f8f50221a","size_bytes":3694},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-06_PROFESSIONAL_LIABILITY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-06_professional_liability.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-06_professional_liability.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"efa7a4f6cda90c04a06558a9d0e1efe13b25169d55d03e36d55d72fcdd096a15","size_bytes":3724},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-07_CONSTRUCTION_DEFECT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-07_construction_defect.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-07_construction_defect.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"78c76cb0485a4acf741109aee05f634f51c3a6904044c613080b21c3978a09f9","size_bytes":3710},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-08_LEASE_DEPOSIT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-08_lease_deposit.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-08_lease_deposit.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"dbe1886671edff49b8b0251eed567d1b3e4e5d748456434262286ca7acf990db","size_bytes":3678},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-09_REGISTRY_TRANSFER_CLAIMS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-09_registry_transfer_claims.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-09_registry_transfer_claims.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"d18946322a8cb528146ac0aa0a2880c41ac2056671fd237b928341ceb8561002","size_bytes":3800},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-10_SECURED_REGISTRY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-10_secured_registry.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-10_secured_registry.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"5819c26ec8478e12a12e340c93a9d23cc410833e1192c2315a1986c9d48a1eba","size_bytes":3757},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-11_POSSESSION_VINDICATION","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-11_possession_vindication.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-11_possession_vindication.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"5e6d6460be4ec0f2ba0096305b9ae39f5f430d107337d0d7e07aac1a9d599aaf","size_bytes":3724},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-12_CO_OWNERSHIP_BOUNDARY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-12_co_ownership_boundary.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-12_co_ownership_boundary.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"62cfbf6a6c5c5edc8b912e348be1c4d4f7dd4c20c722e57e5554058f0caafb4a","size_bytes":3712},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-13_CREDITOR_PRESERVATION","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-13_creditor_preservation.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-13_creditor_preservation.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"c60e6d67c7e3985d1f6ce44027726282f931934e3e66b44f06ccd26845ca2f45","size_bytes":3826},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-14_EXECUTION_LINKED_CLAIMS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-14_execution_linked_claims.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-14_execution_linked_claims.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"45d4b3ab46e1c8834c3b3eec72a28d05e39cb78a9ec2c2de07b5e55e81aeebd7","size_bytes":3787},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-15_SUCCESSION_FAMILY_PROPERTY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-15_succession_family_property.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-15_succession_family_property.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"f691b67295ad8e634b34519cf71156caf6eaf73cef54577615ab79462f8aa766","size_bytes":3763},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-16_NEGOTIABLE_INSTRUMENTS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-16_negotiable_instruments.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-16_negotiable_instruments.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"7720d83b64e7a44720788f6ff3c7cc8ceaf5195377a1e61b52de2144989a1194","size_bytes":3738},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-17_LABOR_WAGE_CLAIMS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-17_labor_wage_claims.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-17_labor_wage_claims.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"168ce5e41104937cf7ab946944f060b82cfe16066425897f07bb9e837b8689ea","size_bytes":3728},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-18_ORG_RESOLUTION_STATUS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-18_org_resolution_status.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-18_org_resolution_status.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"59cf689f886dfaf4ad00dbe6142f5b11c37d0062660f7467aa43427462aa075f","size_bytes":3763},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-19_INSURANCE_CLAIMS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-19_insurance_claims.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-19_insurance_claims.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"0fb4793446c155e7a0b4469c9b8c1be1323112eef55ca4c495307c1af56e754c","size_bytes":3685},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-20_IP_CLAIMS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-20_ip_claims.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-20_ip_claims.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"fe07f20d149a2c4deac2e46de299cd78f0bf829f58c615a86c45f542d30804e1","size_bytes":3654},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-21_MEDIA_PERSONALITY_RIGHTS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-21_media_personality_rights.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-21_media_personality_rights.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"951260bbe8ef116d682f49f3679106c7144ca68f8078f5c10b3459667c1f5b2c","size_bytes":3803},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-00_RESIDUAL_UNROUTED","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/crosscut/E-00_residual_unrouted.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/crosscut/E-00_residual_unrouted.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"639e507147a6132f9e41ccd0b00d1b5450d6a9629991629b173d5bcaf5b6df39","size_bytes":3752},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-X1_NOTICE_LIFECYCLE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/crosscut/X1_notice_lifecycle.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/crosscut/X1_notice_lifecycle.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"9af8b5b5f3a8196a10308d1ee34e0788d9adeac7a99e142e449490d14316faef","size_bytes":3693},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-X2_ASSET_IDENTITY_LINEAGE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/crosscut/X2_asset_identity_lineage.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/crosscut/X2_asset_identity_lineage.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"6c1e437944b3a62b60ee7acad5ec9177fefac2991fe970338acc27efcc8a13ad","size_bytes":3742},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-X3_PROCEDURE_STANDING_RELIEF","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/crosscut/X3_procedure_standing_relief.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/crosscut/X3_procedure_standing_relief.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"f3b794bef82566e569232ba02c63ae148099143d8d1ab84de1c4fb76105e65df","size_bytes":3788},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-X4_RESPONSE_ADMISSION_DEFENSE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/crosscut/X4_response_admission_defense.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/crosscut/X4_response_admission_defense.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"57851ed55b3351a8139df29224d74b7cb8427708bbf6de00ecd27c44089df32e","size_bytes":3793},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-AUTO_MOTOR_VEHICLE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-AUTO_motor_vehicle.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-AUTO_motor_vehicle.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"7234a7ab890f242e6b7aa811528e34c0c85779007cffbf135da0bfff36d61d91","size_bytes":3762},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-INDUSTRIAL_ACCIDENT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-INDUSTRIAL_ACCIDENT.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-INDUSTRIAL_ACCIDENT.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"10d78b8031df7d89f835afc9ca60fab36648e561c729780204c80885f4dd097f","size_bytes":3750},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-PRODUCT_LIABILITY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-PRODUCT_LIABILITY.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-PRODUCT_LIABILITY.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"1d5ee8eddcf005fdb33df58f591a8948aa3e891a3a5656d919394ff0b39eea53","size_bytes":3737},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-RESIDENTIAL_LEASE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-RESIDENTIAL_LEASE.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-RESIDENTIAL_LEASE.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"3e2efd1b3c0524a305eafedc5ec91e05be989a6e55c1501ed161a9b8f8151fd7","size_bytes":3739},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-COMMERCIAL_LEASE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-COMMERCIAL_LEASE.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-COMMERCIAL_LEASE.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"5aebed9ab56bc00eb7e0511f9fe5db8c3a42f1e81b28d58c38d487aa91cbab3e","size_bytes":3769},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-LABOR","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-LABOR.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-LABOR.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"6b2542bb64f4c1d164b1ccd2ce5099fad29bcea4333d9e34bd0fb1667b9ced4a","size_bytes":3694},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-STATE_LIABILITY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-STATE_LIABILITY.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-STATE_LIABILITY.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"5b2fe6d57b918384a619efbd04360ddfaf7720d384136f69d359ccb0b6c853d3","size_bytes":3747},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-IP-PATENT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-IP-PATENT.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-IP-PATENT.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"d0651a8a50d0b18d25931063314ecec284988c5a18fab68d08a317d725bb3066","size_bytes":3709},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-IP-COPYRIGHT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-IP-COPYRIGHT.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-IP-COPYRIGHT.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"d4349677f68346f79709ea23a05957262f6426f976388bba45f05c617035eb78","size_bytes":3728},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-IP-OTHER","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-IP-OTHER.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-IP-OTHER.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"fc3e2772252a3a90571663ebcfbc8e18dbf526977f4a3d77c4705ef8aa8dd6a8","size_bytes":3746},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-MEDIA","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-MEDIA.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-MEDIA.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"e0d5d287befd1578a06c64a265d5c4426af5772b6764018f6a15f00aac3b498c","size_bytes":3705},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-TRANSPORT_MARITIME","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-TRANSPORT_MARITIME.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-TRANSPORT_MARITIME.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"6e87a77c25f8c358f1d7d35ca165b1229c2cb422a440c91768ad80e520d35456","size_bytes":3835},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-CONSUMER_CONTRACT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-CONSUMER_CONTRACT.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-CONSUMER_CONTRACT.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"afd8bbba102614d8d08f2e7a5384f6ca24e1309c1f52feb13906613f2ced51b7","size_bytes":3797},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-ACTIO-MORTGAGE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/overlays/ACTIO-MORTGAGE.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/overlays/ACTIO-MORTGAGE.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"7e584f7b4e4d19132e9575071f87d05965fb77fa2ca870911fe9974a7c511c4d","size_bytes":3739},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-ACTIO-MORTGAGE-CREATION","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/overlays/ACTIO-MORTGAGE-CREATION.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/overlays/ACTIO-MORTGAGE-CREATION.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"e727690ee23883e011d49eba01cfd87abc5482641c2bda519c0a39518e1769ee","size_bytes":3771},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-ACTIO-ENCUMBERED-TRANSFER","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/overlays/ACTIO-ENCUMBERED-TRANSFER.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/overlays/ACTIO-ENCUMBERED-TRANSFER.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"fa950393a572829ba7e296c20cd08ff19a063b0f8441f950130fd677b1e38179","size_bytes":3828},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-ACTIO-PRESERVED-CLAIM-BUNDLE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/overlays/ACTIO-PRESERVED-CLAIM-BUNDLE.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/overlays/ACTIO-PRESERVED-CLAIM-BUNDLE.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"fbd99f029438c1c278f93d88d18a703db72e78f20c7049f344e5748c108f94c5","size_bytes":3816},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-ACTIO-DEFENSE-MAP","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/overlays/ACTIO-DEFENSE-MAP.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/overlays/ACTIO-DEFENSE-MAP.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"05348c493e6046a3e5c55f9b516c0e862fe5aa753e1b2fc71624bb2b11f0c191","size_bytes":3810},{"asset_version":"s2_00.build.1.2","authority_ids":[],"consumed_schema_ids":["https://schemas.liti-agent.local/stage2/shared/deployment.schema.v2.json"],"dependency_module_ids":["SCHEMA-DEPLOYMENT"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":["AUTHORING-AGENT-YAML"],"mirror_byte_parity":true,"mirror_path":"offline_build/build_s2_00_inline_projection.txt","mirror_sha256":"31c96b6abe2eb0ed1f9c9e571e1f4f326307225dfddf40a6670e2d3073ed2ab4","mirror_size_bytes":35198,"module_id":"BUILD-S2_00-INLINE-PROJECTION","module_kind":"BUILD_TOOL","outputs":["DEPLOYMENT-AGENT-PROJECTION","FULL-CODE-MIRRORS","INLINE-CODE-RECEIPT"],"owner":"Stage_2_release_build_owner","path":"offline_build/build_s2_00_inline_projection.py","produced_schema_ids":["stage2_s2_00_inline_code_receipt.v2"],"schema_version":"offline_projection_builder.v1","scope_predicate":"build_target == S2_00_INLINE_AGENT","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"31c96b6abe2eb0ed1f9c9e571e1f4f326307225dfddf40a6670e2d3073ed2ab4","size_bytes":35198},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":["https://schemas.liti-agent.local/stage2/shared/deployment.schema.v2.json"],"dependency_module_ids":["BUILD-S2_00-INLINE-PROJECTION","SCHEMA-DEPLOYMENT","WF-S2_00"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["AUTHORING-AGENT-YAML","DEPLOYMENT-AGENT-PROJECTION","FULL-CODE-MIRRORS"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_inline_code_parity.txt","mirror_sha256":"8f0f55e8e1b970de572129946ab8bf34967c7fd84e316a9193509cab07a455ed","mirror_size_bytes":15928,"module_id":"TEST-S2_00-INLINE-CODE-PARITY","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_inline_code_parity.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == inline_code_parity","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"8f0f55e8e1b970de572129946ab8bf34967c7fd84e316a9193509cab07a455ed","size_bytes":15928},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"WF-S2_10","module_kind":"WORKFLOW","outputs":["WF-S2_10"],"owner":"Stage_2_S2_10_owner","path":"workflows/S2_10_domain_relief_resolution_map.yml","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f0fba48f1760cf4e233d7d698fd19090f96ffb89cabe4b2e2cae9af7c616be0f","size_bytes":15320},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["WF-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"AGENT-S2_10-HYBRID","module_kind":"LLM_AGENT","outputs":["AGENT-S2_10-HYBRID"],"owner":"Stage_2_S2_10_owner","path":"agent_scripts/Stage_2_S2_10.yml","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"SCHEMA-S2_10","module_kind":"JSON_SCHEMA","outputs":["SCHEMA-S2_10"],"owner":"Stage_2_S2_10_owner","path":"schemas/s2_10.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5233afde9ddb3c5868b9101816e8b3830a90b1399e3e5e89d9d7c7bf5beacaee","size_bytes":82703},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["AGENT-S2_10-HYBRID","SCHEMA-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"BINDING-S2_10-HYBRID","module_kind":"DEPLOYMENT_BINDING","outputs":["BINDING-S2_10-HYBRID"],"owner":"Stage_2_S2_10_owner","path":"deployment/stage2_s2_10_llm_binding.yml","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9d20b264e753c2f52e8d096edab363ace0fecf2ec8357605d1a9cb47c9c2b930","size_bytes":7287},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["AGENT-S2_10-HYBRID","P00","P10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"PROMPT-PROJECTION-S2_10","module_kind":"BUILD_RECEIPT","outputs":["PROMPT-PROJECTION-S2_10"],"owner":"Stage_2_S2_10_owner","path":"manifest/s2_10_inline_prompt_projection_receipt.json","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"7f64a192e7edda7c0e4025b9f1995dcd21c38aba15a018d232f9f05bcba35863","size_bytes":2659},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"offline_build/build_s2_10_agent_projection.txt","mirror_sha256":"4359364816c8a58eb414bafae8ccf24fc3766dc611d15f1aa09e48c8fedc8f88","mirror_size_bytes":61930,"module_id":"BUILD-S2_10-HYBRID","module_kind":"BUILD_ONLY","outputs":["BUILD-S2_10-HYBRID"],"owner":"Stage_2_S2_10_owner","path":"offline_build/build_s2_10_agent_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"4359364816c8a58eb414bafae8ccf24fc3766dc611d15f1aa09e48c8fedc8f88","size_bytes":61930},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["SCHEMA-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"offline_build/validate_s2_10_contract.txt","mirror_sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","mirror_size_bytes":63811,"module_id":"VALIDATOR-S2_10","module_kind":"BUILD_ONLY","outputs":["VALIDATOR-S2_10"],"owner":"Stage_2_S2_10_owner","path":"offline_build/validate_s2_10_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","size_bytes":63811},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"tests/s2_10/test_agent_contract.txt","mirror_sha256":"0a7b41894733b743d11ff88f0817a87bdbc98be317d8b3410baa8e9401b5b7bd","mirror_size_bytes":8076,"module_id":"TEST-S2_10-AGENT","module_kind":"TEST","outputs":["TEST-S2_10-AGENT"],"owner":"Stage_2_S2_10_owner","path":"tests/s2_10/test_agent_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0a7b41894733b743d11ff88f0817a87bdbc98be317d8b3410baa8e9401b5b7bd","size_bytes":8076},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["SCHEMA-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"tests/s2_10/test_wave_dispatch.txt","mirror_sha256":"f7e59189ed93585c16c55943f7cc3ed464091fb23a9ea086e6e209cf14677a48","mirror_size_bytes":9894,"module_id":"TEST-S2_10-DISPATCH","module_kind":"TEST","outputs":["TEST-S2_10-DISPATCH"],"owner":"Stage_2_S2_10_owner","path":"tests/s2_10/test_wave_dispatch.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f7e59189ed93585c16c55943f7cc3ed464091fb23a9ea086e6e209cf14677a48","size_bytes":9894},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["SCHEMA-S2_10","VALIDATOR-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"tests/s2_10/test_domain_verdict_contract.txt","mirror_sha256":"9f2547a8c590b7df2aa09d0c3808766bf16be321a448742020d9a3476e7d837f","mirror_size_bytes":10242,"module_id":"TEST-S2_10-DOMAIN","module_kind":"TEST","outputs":["TEST-S2_10-DOMAIN"],"owner":"Stage_2_S2_10_owner","path":"tests/s2_10/test_domain_verdict_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9f2547a8c590b7df2aa09d0c3808766bf16be321a448742020d9a3476e7d837f","size_bytes":10242},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["PROMPT-PROJECTION-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"tests/s2_10/test_prompt_cache_and_boundaries.txt","mirror_sha256":"b77e63b19ba5a843df88180a5e7ac0441256682ea9aa92dc490415a75f1dcee5","mirror_size_bytes":11365,"module_id":"TEST-S2_10-PROMPT","module_kind":"TEST","outputs":["TEST-S2_10-PROMPT"],"owner":"Stage_2_S2_10_owner","path":"tests/s2_10/test_prompt_cache_and_boundaries.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"b77e63b19ba5a843df88180a5e7ac0441256682ea9aa92dc490415a75f1dcee5","size_bytes":11365},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["BINDING-S2_10-HYBRID"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"tests/s2_10/test_release_adapter_retry.txt","mirror_sha256":"16b7b1419550b553bbbd42dbcba7e8418124ba5c41adfcae59639d3db9347c0b","mirror_size_bytes":7757,"module_id":"TEST-S2_10-RELEASE","module_kind":"TEST","outputs":["TEST-S2_10-RELEASE"],"owner":"Stage_2_S2_10_owner","path":"tests/s2_10/test_release_adapter_retry.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"16b7b1419550b553bbbd42dbcba7e8418124ba5c41adfcae59639d3db9347c0b","size_bytes":7757},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"REGRESSION-MANIFEST-S2_10","module_kind":"TEST_MANIFEST","outputs":["REGRESSION-MANIFEST-S2_10"],"owner":"Stage_2_S2_10_owner","path":"tests/fixtures/s2_10/regression_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6fe7bac0fb2b87e4ff3535c9bfa78531aff91af4cc1142a09035225b95581e3d","size_bytes":2572},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-F82ABBC2137A8ABF","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"corpus/build_receipt.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"57fbf8c3f5f86f00db668c425c3e07de74e9d5820b71975c4da3a3bff32e036d","size_bytes":1871},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-F8EF2F640FB77AD1","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"corpus/chunk_manifest.jsonl","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"fd3e1ba067b5960e1d3dba1b5107de913d45ba2b3732a28c3870b10105761b67","size_bytes":620},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-787106ABBFAF8931","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"corpus/source_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ce3ce207ed274292499630a0813d4bdb6a66baf26710fb0e883c2e405adb9a67","size_bytes":807},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-3CD8C31D78EBF47F","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"corpus/weaviate_collection.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f29b287e99d29dbd6d3008d1ad68e3960f9cc2c72459f04316f0311cd3e9a47d","size_bytes":18104},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E852EAB9373DF086","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"law_values/court_fee_values.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"d1213e58b0de3b728945134e0a00a71565fee6db9077c932d7ee99da506c1115","size_bytes":912},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-309310FEC8A6178F","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"law_values/general_law_values.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"45ad98e9e93090fbc5e5c7037f404bd86ff89b73a4aaf8c3449d226bd2aacd1c","size_bytes":843},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-060B74A3C012D23C","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/authority_release.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"cc683958377eea44756de6e9c74fc925da66dd60cc84363f5bec36584f5b2967","size_bytes":1068},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B51F7A86E15908DD","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/case_type_coverage.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"34d6f758fc1486fa7330ede376e65b9448a6eaa971bd21472b0e4b7d9a5b8cba","size_bytes":143780},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-16A7CA30B83DD493","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/case_type_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6462217f08ced21693e8cfc812182cfc1da593d52e719e5cd11ef30409ffd00e","size_bytes":80525},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-34A6FBBE9101F1E8","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/case_type_rule_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ef42e873f497e1e2cfdf9440207f7caaa1f55462a3d47dc207b3c20f9c102793","size_bytes":56945},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-3051DBC07D975B39","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/corpus_release.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"27d0c83e7a95342efdbe5be675b6d5b7d0ff8695eeec022ebc5aded3359fc981","size_bytes":920},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-98D409BCD1DE68FA","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/s2_20_parent_member_paths.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"19822af8fd0245c84b303955106c99ebdfcb5bbce06e76602178c90d4ecf6e82","size_bytes":5443},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-672D5EBD9C1F8AE0","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"migration/actio_assets_receipt.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0d1a3b5eaa7ea670f76db0baa8c30e23b4367904c3f715145737f1dff22f9204","size_bytes":10407},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-2B7093A6A3B291AF","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"migration/legacy_asset_disposition.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"1b0c6b3bafd8bb11ec90e809d0fce057fec83fb12b1f9976471f8952ce073f2c","size_bytes":6039},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_authority_law_value_release.txt","mirror_sha256":"8c1d9b2f05fa752d50349ed1a4479aafcb17c2f574fa1ebe6b19d2bedc21ffeb","mirror_size_bytes":7213,"module_id":"S2_20-ASSET-E3CE7EC9216DDBD3","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/build_authority_law_value_release.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"8c1d9b2f05fa752d50349ed1a4479aafcb17c2f574fa1ebe6b19d2bedc21ffeb","size_bytes":7213},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_corpus_snapshot.txt","mirror_sha256":"96feead66f24d375b9ac379f459de040a9ae1f368e9c05d2911c5b0da54c02c2","mirror_size_bytes":9781,"module_id":"S2_20-ASSET-5F7DB1273D883DE5","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/build_corpus_snapshot.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"96feead66f24d375b9ac379f459de040a9ae1f368e9c05d2911c5b0da54c02c2","size_bytes":9781},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_release_manifests.txt","mirror_sha256":"c2bf201fe61490b79d1e2d199132d24c1285bda52685b22048d085e1289e8b50","mirror_size_bytes":20196,"module_id":"S2_20-ASSET-6CE2AD14244F5B49","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/build_release_manifests.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"c2bf201fe61490b79d1e2d199132d24c1285bda52685b22048d085e1289e8b50","size_bytes":20196},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_s2_20_inline_projection.txt","mirror_sha256":"b5c035251621920dd848d672dc6cf840500ce2b60e1e6656f021855681f6fc58","mirror_size_bytes":27865,"module_id":"S2_20-ASSET-86DCA2BCA2270252","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/build_s2_20_inline_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"b5c035251621920dd848d672dc6cf840500ce2b60e1e6656f021855681f6fc58","size_bytes":27865},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/compile_case_type_registry.txt","mirror_sha256":"e415b5179e53f5a7e35e5e1b7749706c783fbf296bf0bf40103e9450df0b2f0c","mirror_size_bytes":9658,"module_id":"S2_20-ASSET-A360A270415B6E16","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/compile_case_type_registry.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e415b5179e53f5a7e35e5e1b7749706c783fbf296bf0bf40103e9450df0b2f0c","size_bytes":9658},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/compile_relief_rule_projection.txt","mirror_sha256":"8412f2ad7b8de4738fbb86a7596def90dbc9d34d4e2f24854e964df476589c2f","mirror_size_bytes":42682,"module_id":"S2_20-ASSET-B57CC23FD4D06275","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/compile_relief_rule_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"8412f2ad7b8de4738fbb86a7596def90dbc9d34d4e2f24854e964df476589c2f","size_bytes":42682},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-DDC65130DFBDBA55","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/binding/binding_signature_projection.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"b4317d0a5adc3f2bc70214c3e98c4f885ecfd26e36d8242221db4971b6f53142","size_bytes":835},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-AA1E72AB254FE6DC","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-01_interest_delay.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"d0d180a8f8af72d7dda5134b521122827fd2d1f9055c10d35ef5881d7d8cea53","size_bytes":1503},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-45939B38FC8F0B28","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-02_allocation_setoff_balance.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"19a6a32b5879f20ed36df149cdbfb40ec2b5835152579e90a396f745e6299772","size_bytes":1511},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-A4DAC30C3F1AC365","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-03_limitation_deadline.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"1dc66a75034576a41be43058ac421f5c8188288da9928df4d5b9cf616a819ea7","size_bytes":1515},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-D9EEBF8449D85E04","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-04_valuation.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e83044bfd16167cc6c1028afa06b0dc041e0114cee72379563047cff9fbeba11","size_bytes":1483},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-BC815891D9220145","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-05_personal_injury.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0f197813d298f87010545d6eb09c4107c13303b6eb83d276e0130e25abaa7b00","size_bytes":1512},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-2A85ED56A7C1242A","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-06_construction_defect.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"1626c6673b7381e00fa61b7724ae63c8b10cb2ddd932040edc5f69889ffe5ab3","size_bytes":1522},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-6E799BF3C28471BC","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-07_lease_use_gain.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f05c94ad80280607664a1ddcbd29367d0164333888c0d744dd674bf21cee3fad","size_bytes":1488},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-3F219FD043EF4AE1","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-08_inheritance_reserved_share.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"330a1e5f72e4a4e4b7da096ceae554312ca2f828363b761ed37af37abf281818","size_bytes":1518},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-BCAEF55DAB2126D1","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-09_wage_severance.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"dba73da63069e89f95550419d989da78f8fe10196b052c49f050466a0dcda5b9","size_bytes":1489},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-81B84BD832C992EF","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-10_actio_insolvency_value.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"c8710d3e9292b95e53d834006e784b13669b9023149e26628d0abaff074c1c85","size_bytes":1532},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-2852DF1EC788C440","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-11_distribution_share_division.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"4b3c8161ae779628575e122f1f602d6bee40b387c402c5ce642692796e1ab369","size_bytes":1512},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-FD4E3378C53FDCB5","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-12_insurance.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"66d58d2043e45966df9db6c89e980f3c91cbdd6fcf4a4d96944fc203abedf532","size_bytes":1503},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-22371F1936240951","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-13_court_value_cost.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6f914553fd25a9ecb28d85070c2c0ddbf41178906f9075092f9d174977073824","size_bytes":1539},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-711DD22CD3721D81","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-R1_ip_damage.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"d33b7963d68cee10281da86e465caed152e3f69493728a563bca69c6dfb18c2b","size_bytes":1482},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B585B054934C1C1D","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-R2_org_liquidation.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"3bb03e07ba28a01d8c9e3944df55fbc43b21e17435bfa5e84ec60ef7b1540991","size_bytes":1513},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E032EAE75B122995","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-R3_transport_maritime.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e64e808a4d1637c991f1ab512fad25f51637ecba3b2b0dfa66abb7efb8504c7e","size_bytes":1508},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-ED6526C35FE96ACC","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-R4_financial_instrument.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0198a5d09f9b75dd3b6978a01c9a8a3e468c8dd305c49721ae04ce93954b72d3","size_bytes":1510},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B0A8A8F08ECBF0AA","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/calculation_activation_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"1a152af7e0ed4ee2ce10ab93bf3be343122f95e9f276585433449bde27c46e55","size_bytes":5540},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-69ADD915C1858F49","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/corpus/requirement_fact_scope.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6b38306dd4657df2c929caeb1b71bf78838f628e99018fff4692bacf4d49e2c1","size_bytes":216},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-A416DC6DB820828C","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/drafting/case_type_relief_rules.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"01f95c0c1a95f80bfde1ee9c166ffb3ab1f22339ee035f5c322e2637329b8214","size_bytes":1416},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B8BE6EC64CED552C","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/drafting/counter_performance_rules.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5c9e274f38fcfa4e8bfcb0938d2274b8dd83a6f8dac874de3c237b7a2608ab43","size_bytes":857},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-5FDE95EE5314FCA7","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/drafting/forbidden_relief_rules.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"fb51bec7b741e983a5e6f59f8265f3818c49f8067323e9b2090673a832eaae22","size_bytes":852},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-8CDFE6C311F7F7D3","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/drafting/procedural_declaration_rules.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"3328d71a3fb020024fa8a0f8592788d409845d5ca0e2ca9a2b6c63ed3530147c","size_bytes":864},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-4414670A81E95DEA","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/party/party_set_rules.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"92b1b8b76a396008629f534fdcd63995733ccdd71d6b2d9f9c4ad7360daf0c0a","size_bytes":225},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E1D9BDC792A7848D","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/planning/option_disposition_policy.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f3a656c3c1c0eabd22d26e4d3c9f541459af05727f595646a2f7a59d5c5e7658","size_bytes":426},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-CD373B0725950922","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/regression/finding_fixture_map.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"1b719bf6603a2800d9d7bd97347ac16afdc216be87ca282c6b215dd95512c438","size_bytes":1351},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-809C3C709B4F2295","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/review/review_policy_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"960b52019aa947f19c63101a75105a9e155004e4ea8fdcf5546072a9ddad0b96","size_bytes":939},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-8EC84AB1A8C873B2","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/temporal/inheritance_reserved_share.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ca37eb894d04dcba604fe4656f941c44d76fafa1c221f4ffcdd988419a81d7a0","size_bytes":928},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"release_ops/canary_rollback.txt","mirror_sha256":"327356b4f59bb850fcfb680d5caf13038025e3042689f11e1018731058d15241","mirror_size_bytes":1345,"module_id":"S2_20-ASSET-2040ED84718FA22C","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"release_ops/canary_rollback.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"327356b4f59bb850fcfb680d5caf13038025e3042689f11e1018731058d15241","size_bytes":1345},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"release_ops/release_validator.txt","mirror_sha256":"45095d7921f9df600e4331d833057e54d26da68e79dc43e4733bb94fa7da1684","mirror_size_bytes":30130,"module_id":"S2_20-ASSET-DBB6C2CCD4AB3FA2","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"release_ops/release_validator.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"45095d7921f9df600e4331d833057e54d26da68e79dc43e4733bb94fa7da1684","size_bytes":30130},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-52C4FB90CB0F9E68","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R01_money_payment.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"af1860eab21bd6551bb9570e267df2ddf043b71f57c83b55dfe2a32a1c96b7d0","size_bytes":977},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B031219CDF7A06DF","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R02_delivery_possession.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"a3879c0b43f04b952e8eb326a491836678e4490ad3c0a5ebe2c3d592b8c75162","size_bytes":968},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-7BEB573DD33365A1","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R03_declaration_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"239e060a870541166c0b164937ad8b349caf81a4713e1bc53fbcd71a73823843","size_bytes":977},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-769585D81F81F620","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R04_special_nonmoney_performance.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"32295e7cdacabf348102e1bbf500457f599513213022c6a70137d6465118958f","size_bytes":989},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-04C3EF62029B522C","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R05_declaratory.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9e265ce00d3fbb245efb2c82264dd39238ca0406efb04562a4c5e09932910833","size_bytes":976},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-BFC589A870A04F07","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R06_constitutive_judgment_challenge.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"7d54a7657c49671f79acb7bead6cb33c46c78eab93d9c5927c1b8795913cf24c","size_bytes":996},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B2C88C2FFDE4487E","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"routing/actio_pauliana_mortgage_route.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"209fce4f610e7eb6c6ddc2995163de59537ca546752187c23dd1b417e2b117ec","size_bytes":721},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-DD9ABC431EB1B8BC","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"routing/actio_pauliana_route_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f30550aca6ce2a453bd39498d81653eb257cffcd6c693ba56b62f698a510427c","size_bytes":906},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/authority/authority_preflight.txt","mirror_sha256":"ffa513bdc7ddb1de895b4e813de9e107c94c36a5955166c7d5cee745584d0dda","mirror_size_bytes":2115,"module_id":"S2_20-ASSET-2317885DE36C87BB","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/authority/authority_preflight.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ffa513bdc7ddb1de895b4e813de9e107c94c36a5955166c7d5cee745584d0dda","size_bytes":2115},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/binding_signature_projection.txt","mirror_sha256":"0ea048355b4abf8cf261bc60735a557ab09d84e325aa42bd4d7acb58f589c6b5","mirror_size_bytes":5843,"module_id":"S2_20-ASSET-2B67B561F6C4FD3B","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/binding_signature_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0ea048355b4abf8cf261bc60735a557ab09d84e325aa42bd4d7acb58f589c6b5","size_bytes":5843},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c25_case_type_bind.txt","mirror_sha256":"7cda9812225379ef92c34b8ca383aa35bdcbac6afc30b3a21245f5e3ad6aa3af","mirror_size_bytes":3471,"module_id":"S2_20-ASSET-2EABAE08AAE777EA","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/c25_case_type_bind.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"7cda9812225379ef92c34b8ca383aa35bdcbac6afc30b3a21245f5e3ad6aa3af","size_bytes":3471},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c26_rule_branch_bind.txt","mirror_sha256":"f6d6fb87b005b0a155e24ae93c7550640bfdaa221063af034c3d3e20b46cc6b6","mirror_size_bytes":5089,"module_id":"S2_20-ASSET-FCA7B87C74F0BB44","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/c26_rule_branch_bind.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f6d6fb87b005b0a155e24ae93c7550640bfdaa221063af034c3d3e20b46cc6b6","size_bytes":5089},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c27_query_plan.txt","mirror_sha256":"d7fe404438e185b2e0351b8b5ac8fc7bd911a63544e71c7c16ffb313dc566777","mirror_size_bytes":6553,"module_id":"S2_20-ASSET-1327E50515C73062","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/c27_query_plan.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"d7fe404438e185b2e0351b8b5ac8fc7bd911a63544e71c7c16ffb313dc566777","size_bytes":6553},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c28_weaviate_retrieve.txt","mirror_sha256":"9634c80dd1b77ab652185ef5bd2b67ccbb7d355d2b4661f67d86fa78d0ee6395","mirror_size_bytes":12083,"module_id":"S2_20-ASSET-4AE83266D12B501B","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/c28_weaviate_retrieve.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9634c80dd1b77ab652185ef5bd2b67ccbb7d355d2b4661f67d86fa78d0ee6395","size_bytes":12083},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c29_pack_verify.txt","mirror_sha256":"4318f95c9c38391a455613b7411cee923288d19748f3c0946e86c588be718b9d","mirror_size_bytes":5721,"module_id":"S2_20-ASSET-0A121BEB45A15E4D","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/c29_pack_verify.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"4318f95c9c38391a455613b7411cee923288d19748f3c0946e86c588be718b9d","size_bytes":5721},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/calculators/registry_engine.txt","mirror_sha256":"173da5185caa6d4a82a7735018c9121ef42481cad8d83b9574c9f432912c556d","mirror_size_bytes":11417,"module_id":"S2_20-ASSET-FE154EB4E8F19440","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/calculators/registry_engine.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"173da5185caa6d4a82a7735018c9121ef42481cad8d83b9574c9f432912c556d","size_bytes":11417},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E82839694073D431","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_20_owner","path":"schemas/binding_retrieval.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"25df409822a45fd26d0c5cf46e4afb55af100765c86afa148046354b2f02c8dc","size_bytes":47811},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-C9FC917D8CBF920E","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_20_owner","path":"schemas/calculation.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"7036793fe6c8d3550ca22486c281b1ffdbb915995dbe17c92d98a3f9a8f194ce","size_bytes":33698},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-5D843BA99044953C","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_20_owner","path":"schemas/domain_verdict.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5fec56a0661e2ab2351d92939c4fbdedc8ac4c7e8699dc92caae7dd359c7eb16","size_bytes":1262},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-FF1F03B3FC56E579","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_20_owner","path":"schemas/relief_plan.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ef5d271e981390421fa7a188c01e52b390ab138bfc32203056f59d7ab6dfc8f2","size_bytes":31558},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-9A06594587743420","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/actio_route_cap_matrix.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f922b3ec10cc1da44c62d6ca5cf9c8ec5a53f5328b1eaabf236db46448907ca8","size_bytes":572},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-3ECDA3121E0AE910","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/calculation_temporal_boundaries.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"a31af03c418466b1dfc05f47ea05b58109fe142b813da2b3a8863e9d5f71004d","size_bytes":1612},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-5EB4DEF644C02B9D","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/case_type_rule_binding_matrix.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"45e0f7470e2907d20d6359d192fe8320051bf8a278f8eaa8153fbe964819685c","size_bytes":1042},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-60AF7FED54CBA5C1","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/case_type_zero_multi_hash_mutations.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0fbe5f68f4e60dfdd4fd03b9f6f076526f1b3d273b328ec853e69b4f9c315180","size_bytes":1123},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-49D464EEB3D65FFB","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/minimal_supported_portfolio.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"4bcbcf19019e086e4eb4772cb55e87832c3a68c4829f67d50c6a7318dda79c86","size_bytes":733},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-97F26683DEAEA7F7","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/mixed_option_dispositions.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"509f3f436c8107c03033324413560b706487279bf91f2e231bd43bbc5c86b8e0","size_bytes":1457},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-8A3BBD97738BC0BF","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/plan_publish_barrier_failure.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"29afbbdfa609234b06473542c35df7083ca6313155456cc6d1ec311fd50ea275","size_bytes":1640},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-47A96BFDC0754003","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/regression_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"2a1a163d62a041990d71feaef54f3c56753ea3aa02666d3dc4c631552f7ee746","size_bytes":15014},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B42FA1C2AD23D1BA","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/retrieval_replay_injection.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"8fbed161a30d52d8f5018f238dbf2cd01e0dd84162c97e3293df62d82a7ca804","size_bytes":1338},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_agent_and_inline_parity.txt","mirror_sha256":"0f73c112b28088be191b6717cb24cac468762cc286f8dc806bf65d98a95bf262","mirror_size_bytes":2773,"module_id":"S2_20-ASSET-E1B1709F62DB7D8A","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_agent_and_inline_parity.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0f73c112b28088be191b6717cb24cac468762cc286f8dc806bf65d98a95bf262","size_bytes":2773},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_calculation_and_reports.txt","mirror_sha256":"c1bd36c351173d25e6d8e68d1a90d738b90aabb51b201ca13f4370654e584e00","mirror_size_bytes":3199,"module_id":"S2_20-ASSET-1D1B579AA031EC90","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_calculation_and_reports.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"c1bd36c351173d25e6d8e68d1a90d738b90aabb51b201ca13f4370654e584e00","size_bytes":3199},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_inline_output_schema.txt","mirror_sha256":"e2cb938dd639874a4b150997d66eacd89b22016c8fd3385a243edf781cd3e85b","mirror_size_bytes":43574,"module_id":"S2_20-ASSET-22C24679226830D0","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_inline_output_schema.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e2cb938dd639874a4b150997d66eacd89b22016c8fd3385a243edf781cd3e85b","size_bytes":43574},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_offline_compilers.txt","mirror_sha256":"5e75f659a9e5add1345f1596c92c0b143cb1e48110c746a8785fb5b38f1371af","mirror_size_bytes":20252,"module_id":"S2_20-ASSET-6FFF0ED2C88404C2","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_offline_compilers.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5e75f659a9e5add1345f1596c92c0b143cb1e48110c746a8785fb5b38f1371af","size_bytes":20252},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_option_group_and_binding.txt","mirror_sha256":"6021d93fb47377cf6c00ccb5a880a7e85987ec5a1ed7976a84baca2d7fb39985","mirror_size_bytes":6171,"module_id":"S2_20-ASSET-E56589B5CCA0246C","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_option_group_and_binding.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6021d93fb47377cf6c00ccb5a880a7e85987ec5a1ed7976a84baca2d7fb39985","size_bytes":6171},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_plan_publish_and_release.txt","mirror_sha256":"eb5a96109d95d4b78473f79129c441f9be9b015bba1157dfa4d4d3616d03525e","mirror_size_bytes":13734,"module_id":"S2_20-ASSET-2868A4B922737A76","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_plan_publish_and_release.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"eb5a96109d95d4b78473f79129c441f9be9b015bba1157dfa4d4d3616d03525e","size_bytes":13734},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_regression_manifest_closure.txt","mirror_sha256":"886ae584a7846acdb5499d52e1ae8ec177e8d1dc34aa1d43e99dbebafa255516","mirror_size_bytes":8493,"module_id":"S2_20-ASSET-0C03601E14F2D714","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_regression_manifest_closure.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"886ae584a7846acdb5499d52e1ae8ec177e8d1dc34aa1d43e99dbebafa255516","size_bytes":8493},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_retrieval_and_pack.txt","mirror_sha256":"c314cf27511b0fe065b8961196084a28b1c7c5cb2fed3dd5c8765172ba40462f","mirror_size_bytes":6654,"module_id":"S2_20-ASSET-A24AC597CB6DF548","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_retrieval_and_pack.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"c314cf27511b0fe065b8961196084a28b1c7c5cb2fed3dd5c8765172ba40462f","size_bytes":6654},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-CAB87BA40B475A9D","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"validators/actio_value_compensation_invariants.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"591182a8869f3c0c0e03e9b32f5f0d9b856361b3f5f77f1e6e87eb0188f1ef22","size_bytes":983},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-AA40CF5140DE8790","module_kind":"WORKFLOW","outputs":[],"owner":"Stage_2_S2_20_owner","path":"workflows/S2_20_canonical_relief_plan_reduce.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"da56152af502fe432cb2ebaa593a4e389b7f2cd4d0b8f3be29e49717cff0544a","size_bytes":2443},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-871DF298A294D7DC","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/s2_30_parent_member_paths.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"160fd65d43ce37045e4c7000e442433f1ffe2d8dd37ab92d1b859f46457955ca","size_bytes":1551},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_s2_30_agent_projection.txt","mirror_sha256":"3ee27b6edee4338ca0d0bd76f5e192d6d1043ea1df3950cb3c8d3b6af5b6433b","mirror_size_bytes":50879,"module_id":"S2_20-ASSET-66EF7EC35105D464","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/build_s2_30_agent_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"3ee27b6edee4338ca0d0bd76f5e192d6d1043ea1df3950cb3c8d3b6af5b6433b","size_bytes":50879},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/validate_s2_30_contract.txt","mirror_sha256":"30dff7cc1717c792a6da9bcbd3533c82c9bf3902f09fc9fe92a086c2e13694c6","mirror_size_bytes":90323,"module_id":"S2_20-ASSET-7E89202630AA3B4A","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/validate_s2_30_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"30dff7cc1717c792a6da9bcbd3533c82c9bf3902f09fc9fe92a086c2e13694c6","size_bytes":90323},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E83A5821C44AAF21","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"prompts/P30_joint_drafting_contract.md","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5d790fccdacd1b7ce27e25cd52e4c301dbce24ba276def18bca608b5b16362aa","size_bytes":13681},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-6A9B1F5EC854740E","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_20_owner","path":"schemas/draft_atoms.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6cbb81f8cc857173efda0ef3a95c3d39c64f057a64ab1927cf6a5967c592d9ce","size_bytes":57750},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-546763E72E7A932F","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/adverse_fact_worknote_policy.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5b8e9101385f8d65b0332c3be63cb9a22063920675cc86aee51e04da7820aef7","size_bytes":3444},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-47ECD04400C72037","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/cache_prefix_drift.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"845b44cfeb1246f16cd3458965683247efc360b166b31133e3286be400325f98","size_bytes":2109},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-9C7A8A9DC09BB101","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/context_reference_envelope.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"a1d6ba9752b9d4fb479dfaaa763174988f38d87890db9487db9de556d3eade60","size_bytes":4804},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-0DA94639658F5DB2","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/counter_performance_and_declaration.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"cfa3a8439ca938b05768798dfee39a3cc1e4980d5550526c787843622516da90","size_bytes":3322},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-CA60AEE03DF32752","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/follower_batch_dispatch.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"3dffaf9862e15f2fe906ca63abb3be61e49177fb58abb4c4a7a8b25db4e4493b","size_bytes":2832},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-18231E85556C3220","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/invalid_forbidden_output.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"a2308629fc09f75ab226b89374c78323f62a9dbe296aebdd83170a0cfb926e09","size_bytes":2741},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-8265AF415D892AB3","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/invalid_preassembled_prompt_item.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6655402c669e5b40f2e7028a5c0c89571d8e1597dbdef567b4c9d8e2eed15a79","size_bytes":2204},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-A7A8934E5BF55C76","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/invalid_reference_output.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"eb2982a09f4948baadc27ae49c4f125426074333ea4a626e9c56ddc5c24ce273","size_bytes":2663},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-D8A8B0F06569C1F0","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/owner_singleton_dispatch.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"38f9c364591fcdfe60d0dea9f69eb86b2f3b883929f6d60d06a7c35ff376fca6","size_bytes":8448},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-7D7984D0B44475DA","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/partial_write_publish_barrier.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"89f8318c7dbec7bf0095e34194f0a585ea5f4cbce9826af64c30d370612fa1f5","size_bytes":3999},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B1A866CA34AFBC11","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/regression_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"a4741c9eeff95d50a84ad7ba6c2d80b10bdb6ffd40a15fd90b2413ab4ac7abd3","size_bytes":3380},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E696214E5807E29A","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/rule_requirement_admission_gap.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"27dfad63f3508c5d40521270707d84b2bc0c58f035f47d0cde1ae2abc54f9a15","size_bytes":4298},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-C8F5D82811189C0F","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/technical_failure.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"bdcc6410e7515edc73d6b154d5b618b3ec34273ddc7269dc3e3ce55a6eb35fa6","size_bytes":2719},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-77E545820FEC15EC","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_30/valid_joint_draft_output.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0135616c9375602693af8e12c3c16cf2031eaf3d9b74783bec9b5065846327e8","size_bytes":12982},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_30/test_agent_contract.txt","mirror_sha256":"e7d0f069f8c60ff5c5194a9ea9289376e2fd81a50d1b4b18b1b6abf5f2827529","mirror_size_bytes":11630,"module_id":"S2_20-ASSET-97349E7C166EE517","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_30/test_agent_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e7d0f069f8c60ff5c5194a9ea9289376e2fd81a50d1b4b18b1b6abf5f2827529","size_bytes":11630},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_30/test_dispatch_materialization.txt","mirror_sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","mirror_size_bytes":13911,"module_id":"S2_20-ASSET-748AB3E90AD4378F","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_30/test_dispatch_materialization.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","size_bytes":13911},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_30/test_draft_atom_contract.txt","mirror_sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","mirror_size_bytes":10484,"module_id":"S2_20-ASSET-5165C83A0FB3CDEE","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_30/test_draft_atom_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","size_bytes":10484},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_30/test_prompt_cache_and_boundaries.txt","mirror_sha256":"9063ca0a247cf06f55e94e586a7ab8ac21facd9f6c607ce4799047aea365e287","mirror_size_bytes":5142,"module_id":"S2_20-ASSET-30A7574DB26A7700","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_30/test_prompt_cache_and_boundaries.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9063ca0a247cf06f55e94e586a7ab8ac21facd9f6c607ce4799047aea365e287","size_bytes":5142},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_30/test_release_adapter_retry.txt","mirror_sha256":"b15505567db55689527056d608a1cb12d3c605e9df860afba607a6e3e276a0ef","mirror_size_bytes":9241,"module_id":"S2_20-ASSET-A9BE2C9D380E8C50","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_30/test_release_adapter_retry.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"b15505567db55689527056d608a1cb12d3c605e9df860afba607a6e3e276a0ef","size_bytes":9241},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E1FCF8BD63300F4D","module_kind":"WORKFLOW","outputs":[],"owner":"Stage_2_S2_20_owner","path":"workflows/S2_30_claim_group_draft_map.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"498715993d796f82a8c9e790a62bee6885c05813488fd0a11200f46c07665162","size_bytes":12932}],"producer_aliases":[{"alias_id":"PA-SG-COMPILER-001","bidirectional_match_allowed":true,"contract_status":"CLOSED_DECISION_FIXTURE_PENDING","global_alias_allowed":false,"orchestration_producer_id":"Task_C_BO_S0_signal_bundle_writer","schema_writer_id":"Task_C_BO_S0_canonical_signal_compiler","scope":"STAGE1_PART2_SIGNAL_TRANSACTION_ONLY"}],"schema_version":"stage2_module_manifest.v1"} +{"closure_summary":{"build_tool_module_count":1,"cycle_breaking_contract":"AGENT_CODE_RECEIPT_AND_EXECUTOR_BINDING_EXTERNALLY_BIND_RELEASE_RAW_HASH","documentation_mirror_count":57,"executable_agent_hash_included":false,"executor_binding_hash_included":false,"fixture_closure_ref":"tests/fixtures/regression_manifest.json","fixture_descriptor_count":60,"generic_module_counts_by_stage":{"S2_20":90,"S2_30":26,"S2_40":30},"inline_runtime_code_hash_included":false,"module_count":222,"profile_module_count":45,"prompt_module_count":2,"runtime_code_hash_included":false,"s2_20_generic_module_count":90,"s2_30_generic_module_count":26,"s2_40_generic_module_count":30,"self_hash_included":false,"stage2_release_hash_included":false,"test_module_count":72},"documentation_mirrors":[{"byte_identical":true,"mirror_path":"offline_build/build_authority_law_value_release.txt","mirror_sha256":"8c1d9b2f05fa752d50349ed1a4479aafcb17c2f574fa1ebe6b19d2bedc21ffeb","mirror_size_bytes":7213,"runtime_import_allowed":false,"source_path":"offline_build/build_authority_law_value_release.py","source_sha256":"8c1d9b2f05fa752d50349ed1a4479aafcb17c2f574fa1ebe6b19d2bedc21ffeb","source_size_bytes":7213},{"byte_identical":true,"mirror_path":"offline_build/build_corpus_snapshot.txt","mirror_sha256":"96feead66f24d375b9ac379f459de040a9ae1f368e9c05d2911c5b0da54c02c2","mirror_size_bytes":9781,"runtime_import_allowed":false,"source_path":"offline_build/build_corpus_snapshot.py","source_sha256":"96feead66f24d375b9ac379f459de040a9ae1f368e9c05d2911c5b0da54c02c2","source_size_bytes":9781},{"byte_identical":true,"mirror_path":"offline_build/build_release_manifests.txt","mirror_sha256":"9356d18267375e731e878ab301dcec01a728d73761df0dd65829599c00ccfcd5","mirror_size_bytes":30698,"runtime_import_allowed":false,"source_path":"offline_build/build_release_manifests.py","source_sha256":"9356d18267375e731e878ab301dcec01a728d73761df0dd65829599c00ccfcd5","source_size_bytes":30698},{"byte_identical":true,"mirror_path":"offline_build/build_s2_00_inline_projection.txt","mirror_sha256":"31c96b6abe2eb0ed1f9c9e571e1f4f326307225dfddf40a6670e2d3073ed2ab4","mirror_size_bytes":35198,"runtime_import_allowed":false,"source_path":"offline_build/build_s2_00_inline_projection.py","source_sha256":"31c96b6abe2eb0ed1f9c9e571e1f4f326307225dfddf40a6670e2d3073ed2ab4","source_size_bytes":35198},{"byte_identical":true,"mirror_path":"offline_build/build_s2_10_agent_projection.txt","mirror_sha256":"efdde6d70c723e9386f2ba1828119af7e68f7956c29bd3ba05370242a70ab62d","mirror_size_bytes":68381,"runtime_import_allowed":false,"source_path":"offline_build/build_s2_10_agent_projection.py","source_sha256":"efdde6d70c723e9386f2ba1828119af7e68f7956c29bd3ba05370242a70ab62d","source_size_bytes":68381},{"byte_identical":true,"mirror_path":"offline_build/build_s2_20_inline_projection.txt","mirror_sha256":"b5c035251621920dd848d672dc6cf840500ce2b60e1e6656f021855681f6fc58","mirror_size_bytes":27865,"runtime_import_allowed":false,"source_path":"offline_build/build_s2_20_inline_projection.py","source_sha256":"b5c035251621920dd848d672dc6cf840500ce2b60e1e6656f021855681f6fc58","source_size_bytes":27865},{"byte_identical":true,"mirror_path":"offline_build/build_s2_30_agent_projection.txt","mirror_sha256":"665b6f00bae567ea67e3758be047f594fedae2c22a5047b30009fcd5d2c495b2","mirror_size_bytes":56585,"runtime_import_allowed":false,"source_path":"offline_build/build_s2_30_agent_projection.py","source_sha256":"665b6f00bae567ea67e3758be047f594fedae2c22a5047b30009fcd5d2c495b2","source_size_bytes":56585},{"byte_identical":true,"mirror_path":"offline_build/build_s2_40_inline_projection.txt","mirror_sha256":"c6dee2c30d4b23fa3e6aaf2cded4f933dae6e642c71eeff8534c4e53a12bdfe0","mirror_size_bytes":36098,"runtime_import_allowed":false,"source_path":"offline_build/build_s2_40_inline_projection.py","source_sha256":"c6dee2c30d4b23fa3e6aaf2cded4f933dae6e642c71eeff8534c4e53a12bdfe0","source_size_bytes":36098},{"byte_identical":true,"mirror_path":"offline_build/compile_case_type_registry.txt","mirror_sha256":"e415b5179e53f5a7e35e5e1b7749706c783fbf296bf0bf40103e9450df0b2f0c","mirror_size_bytes":9658,"runtime_import_allowed":false,"source_path":"offline_build/compile_case_type_registry.py","source_sha256":"e415b5179e53f5a7e35e5e1b7749706c783fbf296bf0bf40103e9450df0b2f0c","source_size_bytes":9658},{"byte_identical":true,"mirror_path":"offline_build/compile_relief_rule_projection.txt","mirror_sha256":"8412f2ad7b8de4738fbb86a7596def90dbc9d34d4e2f24854e964df476589c2f","mirror_size_bytes":42682,"runtime_import_allowed":false,"source_path":"offline_build/compile_relief_rule_projection.py","source_sha256":"8412f2ad7b8de4738fbb86a7596def90dbc9d34d4e2f24854e964df476589c2f","source_size_bytes":42682},{"byte_identical":true,"mirror_path":"offline_build/validate_s2_10_contract.txt","mirror_sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","mirror_size_bytes":63811,"runtime_import_allowed":false,"source_path":"offline_build/validate_s2_10_contract.py","source_sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","source_size_bytes":63811},{"byte_identical":true,"mirror_path":"offline_build/validate_s2_30_contract.txt","mirror_sha256":"14e4eefb73d40d004c95017c82cdc23ac1c1c0a54ea34562dcf322f6364ae27a","mirror_size_bytes":104292,"runtime_import_allowed":false,"source_path":"offline_build/validate_s2_30_contract.py","source_sha256":"14e4eefb73d40d004c95017c82cdc23ac1c1c0a54ea34562dcf322f6364ae27a","source_size_bytes":104292},{"byte_identical":true,"mirror_path":"release_ops/canary_rollback.txt","mirror_sha256":"327356b4f59bb850fcfb680d5caf13038025e3042689f11e1018731058d15241","mirror_size_bytes":1345,"runtime_import_allowed":false,"source_path":"release_ops/canary_rollback.py","source_sha256":"327356b4f59bb850fcfb680d5caf13038025e3042689f11e1018731058d15241","source_size_bytes":1345},{"byte_identical":true,"mirror_path":"release_ops/release_validator.txt","mirror_sha256":"5c962c0ca084ce08a622764c874749bd837534b7b0a3af4ba9f879b975a0f866","mirror_size_bytes":55260,"runtime_import_allowed":false,"source_path":"release_ops/release_validator.py","source_sha256":"5c962c0ca084ce08a622764c874749bd837534b7b0a3af4ba9f879b975a0f866","source_size_bytes":55260},{"byte_identical":true,"mirror_path":"runtime/authority/authority_preflight.txt","mirror_sha256":"ffa513bdc7ddb1de895b4e813de9e107c94c36a5955166c7d5cee745584d0dda","mirror_size_bytes":2115,"runtime_import_allowed":false,"source_path":"runtime/authority/authority_preflight.py","source_sha256":"ffa513bdc7ddb1de895b4e813de9e107c94c36a5955166c7d5cee745584d0dda","source_size_bytes":2115},{"byte_identical":true,"mirror_path":"runtime/binding_signature_projection.txt","mirror_sha256":"0ea048355b4abf8cf261bc60735a557ab09d84e325aa42bd4d7acb58f589c6b5","mirror_size_bytes":5843,"runtime_import_allowed":false,"source_path":"runtime/binding_signature_projection.py","source_sha256":"0ea048355b4abf8cf261bc60735a557ab09d84e325aa42bd4d7acb58f589c6b5","source_size_bytes":5843},{"byte_identical":true,"mirror_path":"runtime/c25_case_type_bind.txt","mirror_sha256":"7cda9812225379ef92c34b8ca383aa35bdcbac6afc30b3a21245f5e3ad6aa3af","mirror_size_bytes":3471,"runtime_import_allowed":false,"source_path":"runtime/c25_case_type_bind.py","source_sha256":"7cda9812225379ef92c34b8ca383aa35bdcbac6afc30b3a21245f5e3ad6aa3af","source_size_bytes":3471},{"byte_identical":true,"mirror_path":"runtime/c26_rule_branch_bind.txt","mirror_sha256":"f6d6fb87b005b0a155e24ae93c7550640bfdaa221063af034c3d3e20b46cc6b6","mirror_size_bytes":5089,"runtime_import_allowed":false,"source_path":"runtime/c26_rule_branch_bind.py","source_sha256":"f6d6fb87b005b0a155e24ae93c7550640bfdaa221063af034c3d3e20b46cc6b6","source_size_bytes":5089},{"byte_identical":true,"mirror_path":"runtime/c27_query_plan.txt","mirror_sha256":"d7fe404438e185b2e0351b8b5ac8fc7bd911a63544e71c7c16ffb313dc566777","mirror_size_bytes":6553,"runtime_import_allowed":false,"source_path":"runtime/c27_query_plan.py","source_sha256":"d7fe404438e185b2e0351b8b5ac8fc7bd911a63544e71c7c16ffb313dc566777","source_size_bytes":6553},{"byte_identical":true,"mirror_path":"runtime/c28_weaviate_retrieve.txt","mirror_sha256":"9634c80dd1b77ab652185ef5bd2b67ccbb7d355d2b4661f67d86fa78d0ee6395","mirror_size_bytes":12083,"runtime_import_allowed":false,"source_path":"runtime/c28_weaviate_retrieve.py","source_sha256":"9634c80dd1b77ab652185ef5bd2b67ccbb7d355d2b4661f67d86fa78d0ee6395","source_size_bytes":12083},{"byte_identical":true,"mirror_path":"runtime/c29_pack_verify.txt","mirror_sha256":"4318f95c9c38391a455613b7411cee923288d19748f3c0946e86c588be718b9d","mirror_size_bytes":5721,"runtime_import_allowed":false,"source_path":"runtime/c29_pack_verify.py","source_sha256":"4318f95c9c38391a455613b7411cee923288d19748f3c0946e86c588be718b9d","source_size_bytes":5721},{"byte_identical":true,"mirror_path":"runtime/c45_document_assembler.txt","mirror_sha256":"93135e69189a335f34be7c383cef2b5ca9f12ea899266b0d8ecc4bd85237647e","mirror_size_bytes":11992,"runtime_import_allowed":false,"source_path":"runtime/c45_document_assembler.py","source_sha256":"93135e69189a335f34be7c383cef2b5ca9f12ea899266b0d8ecc4bd85237647e","source_size_bytes":11992},{"byte_identical":true,"mirror_path":"runtime/calculators/registry_engine.txt","mirror_sha256":"173da5185caa6d4a82a7735018c9121ef42481cad8d83b9574c9f432912c556d","mirror_size_bytes":11417,"runtime_import_allowed":false,"source_path":"runtime/calculators/registry_engine.py","source_sha256":"173da5185caa6d4a82a7735018c9121ef42481cad8d83b9574c9f432912c556d","source_size_bytes":11417},{"byte_identical":true,"mirror_path":"runtime/rendering/closed_renderer.txt","mirror_sha256":"21acbee2e5456de2b647b5c235c4e8293b77a864af9bc365c75c8346d34070cd","mirror_size_bytes":10559,"runtime_import_allowed":false,"source_path":"runtime/rendering/closed_renderer.py","source_sha256":"21acbee2e5456de2b647b5c235c4e8293b77a864af9bc365c75c8346d34070cd","source_size_bytes":10559},{"byte_identical":true,"mirror_path":"runtime/validation/invariant_runner.txt","mirror_sha256":"67d2ff35d66079fa7fe5e8f312f18ed68b16da5eb4f9f85780d11bd45b54009c","mirror_size_bytes":30951,"runtime_import_allowed":false,"source_path":"runtime/validation/invariant_runner.py","source_sha256":"67d2ff35d66079fa7fe5e8f312f18ed68b16da5eb4f9f85780d11bd45b54009c","source_size_bytes":30951},{"byte_identical":true,"mirror_path":"tests/s2_00/test_canonical_ids.txt","mirror_sha256":"c463506a90859daeef7eafddc4a6c08c563e2ae73200d921c1f00efb7bc24361","mirror_size_bytes":2275,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_canonical_ids.py","source_sha256":"c463506a90859daeef7eafddc4a6c08c563e2ae73200d921c1f00efb7bc24361","source_size_bytes":2275},{"byte_identical":true,"mirror_path":"tests/s2_00/test_cluster_bundle_compile.txt","mirror_sha256":"b643d2d4018ebe3349c64304063edf7ba0194fc92fb1fe9337eca3f384ae794a","mirror_size_bytes":25690,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_cluster_bundle_compile.py","source_sha256":"b643d2d4018ebe3349c64304063edf7ba0194fc92fb1fe9337eca3f384ae794a","source_size_bytes":25690},{"byte_identical":true,"mirror_path":"tests/s2_00/test_conservation.txt","mirror_sha256":"c906dff7e11678a60556818d1baf24e66844d9c982c9d333ec339d2ed9ca6061","mirror_size_bytes":5562,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_conservation.py","source_sha256":"c906dff7e11678a60556818d1baf24e66844d9c982c9d333ec339d2ed9ca6061","source_size_bytes":5562},{"byte_identical":true,"mirror_path":"tests/s2_00/test_failure_and_atomic_publish.txt","mirror_sha256":"613f0c1b32dc26c302365fc62f36c8ede7204e1ced4920e797a1651af8354527","mirror_size_bytes":25937,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_failure_and_atomic_publish.py","source_sha256":"613f0c1b32dc26c302365fc62f36c8ede7204e1ced4920e797a1651af8354527","source_size_bytes":25937},{"byte_identical":true,"mirror_path":"tests/s2_00/test_inline_code_parity.txt","mirror_sha256":"8f0f55e8e1b970de572129946ab8bf34967c7fd84e316a9193509cab07a455ed","mirror_size_bytes":15928,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_inline_code_parity.py","source_sha256":"8f0f55e8e1b970de572129946ab8bf34967c7fd84e316a9193509cab07a455ed","source_size_bytes":15928},{"byte_identical":true,"mirror_path":"tests/s2_00/test_resolver_source_lock.txt","mirror_sha256":"51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e","mirror_size_bytes":14423,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_resolver_source_lock.py","source_sha256":"51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e","source_size_bytes":14423},{"byte_identical":true,"mirror_path":"tests/s2_00/test_schema_hash_and_signals.txt","mirror_sha256":"14207eedd80caaf24d85377617fb754bdeecc80ba9b2a291d6ac5d09ab0a6191","mirror_size_bytes":12842,"runtime_import_allowed":false,"source_path":"tests/s2_00/test_schema_hash_and_signals.py","source_sha256":"14207eedd80caaf24d85377617fb754bdeecc80ba9b2a291d6ac5d09ab0a6191","source_size_bytes":12842},{"byte_identical":true,"mirror_path":"tests/s2_10/test_agent_contract.txt","mirror_sha256":"0a7b41894733b743d11ff88f0817a87bdbc98be317d8b3410baa8e9401b5b7bd","mirror_size_bytes":8076,"runtime_import_allowed":false,"source_path":"tests/s2_10/test_agent_contract.py","source_sha256":"0a7b41894733b743d11ff88f0817a87bdbc98be317d8b3410baa8e9401b5b7bd","source_size_bytes":8076},{"byte_identical":true,"mirror_path":"tests/s2_10/test_domain_verdict_contract.txt","mirror_sha256":"9f2547a8c590b7df2aa09d0c3808766bf16be321a448742020d9a3476e7d837f","mirror_size_bytes":10242,"runtime_import_allowed":false,"source_path":"tests/s2_10/test_domain_verdict_contract.py","source_sha256":"9f2547a8c590b7df2aa09d0c3808766bf16be321a448742020d9a3476e7d837f","source_size_bytes":10242},{"byte_identical":true,"mirror_path":"tests/s2_10/test_prompt_cache_and_boundaries.txt","mirror_sha256":"b77e63b19ba5a843df88180a5e7ac0441256682ea9aa92dc490415a75f1dcee5","mirror_size_bytes":11365,"runtime_import_allowed":false,"source_path":"tests/s2_10/test_prompt_cache_and_boundaries.py","source_sha256":"b77e63b19ba5a843df88180a5e7ac0441256682ea9aa92dc490415a75f1dcee5","source_size_bytes":11365},{"byte_identical":true,"mirror_path":"tests/s2_10/test_release_adapter_retry.txt","mirror_sha256":"2a6a3119608b6063137575d66b8552623f164dbdd0952bc97074d6f687fb32e0","mirror_size_bytes":10848,"runtime_import_allowed":false,"source_path":"tests/s2_10/test_release_adapter_retry.py","source_sha256":"2a6a3119608b6063137575d66b8552623f164dbdd0952bc97074d6f687fb32e0","source_size_bytes":10848},{"byte_identical":true,"mirror_path":"tests/s2_10/test_wave_dispatch.txt","mirror_sha256":"f7e59189ed93585c16c55943f7cc3ed464091fb23a9ea086e6e209cf14677a48","mirror_size_bytes":9894,"runtime_import_allowed":false,"source_path":"tests/s2_10/test_wave_dispatch.py","source_sha256":"f7e59189ed93585c16c55943f7cc3ed464091fb23a9ea086e6e209cf14677a48","source_size_bytes":9894},{"byte_identical":true,"mirror_path":"tests/s2_20/test_agent_and_inline_parity.txt","mirror_sha256":"0f73c112b28088be191b6717cb24cac468762cc286f8dc806bf65d98a95bf262","mirror_size_bytes":2773,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_agent_and_inline_parity.py","source_sha256":"0f73c112b28088be191b6717cb24cac468762cc286f8dc806bf65d98a95bf262","source_size_bytes":2773},{"byte_identical":true,"mirror_path":"tests/s2_20/test_calculation_and_reports.txt","mirror_sha256":"c1bd36c351173d25e6d8e68d1a90d738b90aabb51b201ca13f4370654e584e00","mirror_size_bytes":3199,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_calculation_and_reports.py","source_sha256":"c1bd36c351173d25e6d8e68d1a90d738b90aabb51b201ca13f4370654e584e00","source_size_bytes":3199},{"byte_identical":true,"mirror_path":"tests/s2_20/test_inline_output_schema.txt","mirror_sha256":"e2cb938dd639874a4b150997d66eacd89b22016c8fd3385a243edf781cd3e85b","mirror_size_bytes":43574,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_inline_output_schema.py","source_sha256":"e2cb938dd639874a4b150997d66eacd89b22016c8fd3385a243edf781cd3e85b","source_size_bytes":43574},{"byte_identical":true,"mirror_path":"tests/s2_20/test_offline_compilers.txt","mirror_sha256":"5e75f659a9e5add1345f1596c92c0b143cb1e48110c746a8785fb5b38f1371af","mirror_size_bytes":20252,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_offline_compilers.py","source_sha256":"5e75f659a9e5add1345f1596c92c0b143cb1e48110c746a8785fb5b38f1371af","source_size_bytes":20252},{"byte_identical":true,"mirror_path":"tests/s2_20/test_option_group_and_binding.txt","mirror_sha256":"6021d93fb47377cf6c00ccb5a880a7e85987ec5a1ed7976a84baca2d7fb39985","mirror_size_bytes":6171,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_option_group_and_binding.py","source_sha256":"6021d93fb47377cf6c00ccb5a880a7e85987ec5a1ed7976a84baca2d7fb39985","source_size_bytes":6171},{"byte_identical":true,"mirror_path":"tests/s2_20/test_plan_publish_and_release.txt","mirror_sha256":"ce0dc52cca2c6744be1051346ebecabac8c4ccbd97d697f7645eadd35aebd1e8","mirror_size_bytes":13950,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_plan_publish_and_release.py","source_sha256":"ce0dc52cca2c6744be1051346ebecabac8c4ccbd97d697f7645eadd35aebd1e8","source_size_bytes":13950},{"byte_identical":true,"mirror_path":"tests/s2_20/test_regression_manifest_closure.txt","mirror_sha256":"01ac49ab1ba79f158da9da78313407e3a67a95cf539113c617701a74c29b463f","mirror_size_bytes":10028,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_regression_manifest_closure.py","source_sha256":"01ac49ab1ba79f158da9da78313407e3a67a95cf539113c617701a74c29b463f","source_size_bytes":10028},{"byte_identical":true,"mirror_path":"tests/s2_20/test_retrieval_and_pack.txt","mirror_sha256":"c314cf27511b0fe065b8961196084a28b1c7c5cb2fed3dd5c8765172ba40462f","mirror_size_bytes":6654,"runtime_import_allowed":false,"source_path":"tests/s2_20/test_retrieval_and_pack.py","source_sha256":"c314cf27511b0fe065b8961196084a28b1c7c5cb2fed3dd5c8765172ba40462f","source_size_bytes":6654},{"byte_identical":true,"mirror_path":"tests/s2_30/test_agent_contract.txt","mirror_sha256":"26a37b0b5fa6c4273ed7deff6b0429e3223869533fc2384f4c364fe88d554da5","mirror_size_bytes":12199,"runtime_import_allowed":false,"source_path":"tests/s2_30/test_agent_contract.py","source_sha256":"26a37b0b5fa6c4273ed7deff6b0429e3223869533fc2384f4c364fe88d554da5","source_size_bytes":12199},{"byte_identical":true,"mirror_path":"tests/s2_30/test_dispatch_materialization.txt","mirror_sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","mirror_size_bytes":13911,"runtime_import_allowed":false,"source_path":"tests/s2_30/test_dispatch_materialization.py","source_sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","source_size_bytes":13911},{"byte_identical":true,"mirror_path":"tests/s2_30/test_draft_atom_contract.txt","mirror_sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","mirror_size_bytes":10484,"runtime_import_allowed":false,"source_path":"tests/s2_30/test_draft_atom_contract.py","source_sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","source_size_bytes":10484},{"byte_identical":true,"mirror_path":"tests/s2_30/test_prompt_cache_and_boundaries.txt","mirror_sha256":"1b9b562418bc24be6db09dc1d35f71845033adbc693aeb41fbba07be16fa7c9d","mirror_size_bytes":6284,"runtime_import_allowed":false,"source_path":"tests/s2_30/test_prompt_cache_and_boundaries.py","source_sha256":"1b9b562418bc24be6db09dc1d35f71845033adbc693aeb41fbba07be16fa7c9d","source_size_bytes":6284},{"byte_identical":true,"mirror_path":"tests/s2_30/test_release_adapter_retry.txt","mirror_sha256":"e5af75d54f236eb8ba99b194a06aa31f02fddd5c6aa9ff7385401905359b292c","mirror_size_bytes":18566,"runtime_import_allowed":false,"source_path":"tests/s2_30/test_release_adapter_retry.py","source_sha256":"e5af75d54f236eb8ba99b194a06aa31f02fddd5c6aa9ff7385401905359b292c","source_size_bytes":18566},{"byte_identical":true,"mirror_path":"tests/s2_40/test_agent_and_inline_parity.txt","mirror_sha256":"04cc4a14790eceea6ec8a9331212ca6e767ef96994b5b26483392d23145417ae","mirror_size_bytes":32947,"runtime_import_allowed":false,"source_path":"tests/s2_40/test_agent_and_inline_parity.py","source_sha256":"04cc4a14790eceea6ec8a9331212ca6e767ef96994b5b26483392d23145417ae","source_size_bytes":32947},{"byte_identical":true,"mirror_path":"tests/s2_40/test_c40_reduce_and_conservation.txt","mirror_sha256":"f610eced056420277c67294cdfe76d559073d88a6f42d3e8c5dae8f219fa82d9","mirror_size_bytes":3032,"runtime_import_allowed":false,"source_path":"tests/s2_40/test_c40_reduce_and_conservation.py","source_sha256":"f610eced056420277c67294cdfe76d559073d88a6f42d3e8c5dae8f219fa82d9","source_size_bytes":3032},{"byte_identical":true,"mirror_path":"tests/s2_40/test_c45_closed_render.txt","mirror_sha256":"b7cad96735b1a0158644f41703b4f279fdd8b6bc68438f0d7d773b8415ebb460","mirror_size_bytes":7855,"runtime_import_allowed":false,"source_path":"tests/s2_40/test_c45_closed_render.py","source_sha256":"b7cad96735b1a0158644f41703b4f279fdd8b6bc68438f0d7d773b8415ebb460","source_size_bytes":7855},{"byte_identical":true,"mirror_path":"tests/s2_40/test_commit_barrier_and_idempotence.txt","mirror_sha256":"714e2f05397d5dcc31159739363f11c9bbaf5a091de55b465e0b474c21f90ea0","mirror_size_bytes":8228,"runtime_import_allowed":false,"source_path":"tests/s2_40/test_commit_barrier_and_idempotence.py","source_sha256":"714e2f05397d5dcc31159739363f11c9bbaf5a091de55b465e0b474c21f90ea0","source_size_bytes":8228},{"byte_identical":true,"mirror_path":"tests/s2_40/test_release_closure.txt","mirror_sha256":"89139e0286facd52c3ce91a1c7b382a584dfc3e6bc337fcb55fbc8eed59f5933","mirror_size_bytes":12692,"runtime_import_allowed":false,"source_path":"tests/s2_40/test_release_closure.py","source_sha256":"89139e0286facd52c3ce91a1c7b382a584dfc3e6bc337fcb55fbc8eed59f5933","source_size_bytes":12692},{"byte_identical":true,"mirror_path":"tests/s2_40/test_review_state_machine.txt","mirror_sha256":"f4dab9bb651b4a3c818c73162b972c8ac3df0f50fbe056e392a12673139b9b4a","mirror_size_bytes":8373,"runtime_import_allowed":false,"source_path":"tests/s2_40/test_review_state_machine.py","source_sha256":"f4dab9bb651b4a3c818c73162b972c8ac3df0f50fbe056e392a12673139b9b4a","source_size_bytes":8373},{"byte_identical":true,"mirror_path":"tests/s2_40/test_v01_v18.txt","mirror_sha256":"72be88be1aa9d495b5c9387e45b75e86f44ac76ffe15c04b5ba33ba21fa8943f","mirror_size_bytes":3853,"runtime_import_allowed":false,"source_path":"tests/s2_40/test_v01_v18.py","source_sha256":"72be88be1aa9d495b5c9387e45b75e86f44ac76ffe15c04b5ba33ba21fa8943f","source_size_bytes":3853}],"forbidden_contract_registry":[{"code":"LEGACY-STAGE2-V0-V3","legacy_runtime_dependency_allowed":false,"meaning":"The clean S2_00 workflow and runtime must not read or execute legacy Stage 2 v.0-v.3 specifications."},{"code":"LEGACY-STAGE2-LOADER","legacy_runtime_dependency_allowed":false,"meaning":"The historical host loader and loader binding are reference-only and cannot authorize, execute, or provide fallback for S2_00."},{"code":"RAW-STAGE1-REREAD","legacy_runtime_dependency_allowed":false,"meaning":"S2_10 must consume immutable bounded cluster projections and must not rediscover raw Stage 1 inputs."},{"code":"S2_40-PLEADING-RENDER-IN-STATUS-ONLY","legacy_runtime_dependency_allowed":false,"meaning":"The S2_40 status-only entrypoint must not render or commit pleading text."}],"implementation_status":"OFFLINE_HYBRID_RESEAL_COMPLETE_LIVE_ADMISSION_PENDING","manifest_digest":"6fda5bad6b43cedd593c7066ea0e6565dfd55457377b26035b594adfb85db266","manifest_digest_contract":{"algorithm_id":"STAGE2-MODULE-MANIFEST-DIGEST-V1","array_order":"PRESERVE_DECLARED_ORDER","canonicalization_algorithm_id":"STAGE2-CANONICAL-JSON-V1","digest_algorithm":"sha256","digest_scope":"ENTIRE_DOCUMENT_AFTER_REMOVING_TOP_LEVEL_MANIFEST_DIGEST","encoding":"UTF-8","line_termination":"LF_ONE_TRAILING_NEWLINE","non_finite_numbers_allowed":false,"object_key_order":"SORT_CODEPOINT","verification_status":"DEV_VERIFIED"},"manifest_id":"STAGE2-CLEAN-S2_00-STRUCTURED-HANDOFF-V2-INLINE","manifest_scope":"S2_00_STRUCTURED_CONTEXT_HANDOFF_AND_SHARED_CONTRACTS","manifest_status":"DEV_HASH_BOUND_DOWNSTREAM_HYBRID_RELEASE_PENDING","modules":[{"asset_version":"s2_00.1.2","authority_ids":[],"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.v2.json","https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json"],"dependency_module_ids":["SCHEMA-INGRESS","SCHEMA-CONTEXT","SCHEMA-REVIEW-STATUS"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"IMPLEMENTED_DECLARATIVE_CONTRACT","incompatible_module_ids":[],"inputs":["STAGE1-ALLOWLIST-V1","STAGE1-DEPLOYMENT-CLOSURE-2026-08-29"],"module_id":"WF-S2_00","module_kind":"WORKFLOW","outputs":["S2_00-NORMAL-BRANCH","S2_00-DIAGNOSTIC-BRANCH"],"owner":"Stage_2_workflow_maintainer","path":"workflows/S2_00_stage1_ingress_normalize_and_bundle_compile.yml","produced_schema_ids":[],"schema_version":"stage2_workflow_contract.v1.2","scope_predicate":"workflow_id == S2_00","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"3d7ceb86b236668c8c372136f1d1b43a5d0a79d3fb05fd1ef4342bb638190f68","size_bytes":17351},{"asset_version":"s2_00.schema.1.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":[],"module_id":"SCHEMA-INGRESS","module_kind":"JSON_SCHEMA","outputs":["INGRESS-SCHEMA-DEFS"],"owner":"Stage_2_schema_owner","path":"schemas/ingress.schema.json","produced_schema_ids":["https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json"],"schema_version":"stage2_s2_00_ingress.v1.1","scope_predicate":"artifact_family == ingress","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"8fd7b76015b7d7dfbbe056e08999dda7ea8e1012bb16cec50634b08f7ea97302","size_bytes":33444},{"asset_version":"s2_00.schema.2","authority_ids":[],"consumed_schema_ids":["https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json"],"dependency_module_ids":["SCHEMA-REVIEW-STATUS"],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":[],"module_id":"SCHEMA-CONTEXT","module_kind":"JSON_SCHEMA","outputs":["CONTEXT-SCHEMA-DEFS"],"owner":"Stage_2_schema_owner","path":"schemas/context.schema.json","produced_schema_ids":["https://schemas.liti-agent.local/stage2/s2_00/context.schema.v2.json"],"schema_version":"stage2_s2_00_context.v2","scope_predicate":"artifact_family == context","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"29073ffa847d74304228d61306503c0c3798da7db8b5717b1ad6d5b2da98aa92","size_bytes":39054},{"asset_version":"stage2.shared.2","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":[],"module_id":"SCHEMA-DEPLOYMENT","module_kind":"JSON_SCHEMA","outputs":["DEPLOYMENT-SCHEMA-DEFS"],"owner":"Stage_2_deployment_schema_owner","path":"schemas/deployment.schema.json","produced_schema_ids":["https://schemas.liti-agent.local/stage2/shared/deployment.schema.v2.json"],"schema_version":"stage2_deployment.v2","scope_predicate":"artifact_family == deployment","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"a4e76d674c0fcc3afb2f99c35fbdbfdde0c6ee6a6e2be63ed26470e5d5c7d003","size_bytes":92638},{"asset_version":"stage2.shared.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":[],"module_id":"SCHEMA-REVIEW-STATUS","module_kind":"JSON_SCHEMA","outputs":["REVIEW-STATUS-SCHEMA-DEFS"],"owner":"Stage_2_review_schema_owner","path":"schemas/review_status.schema.json","produced_schema_ids":["https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json"],"schema_version":"stage2_review_status.v1","scope_predicate":"artifact_family == review_status","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"dbf559cae183b9e9878a56ff9364ddfe68f7bf6ba1e00e595ec8876f2fc01d95","size_bytes":27241},{"asset_version":"stage2.cache.2","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["SCHEMA-CONTEXT"],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["RELEASE-SELECTED-CONTEXT-ORDERED-REFS","S2_00-COHORT-MEMBERSHIP","S2_00-MEMBER-SLICE-REF-SET"],"module_id":"CACHE-POLICY-STRUCTURED-CONTEXT-HANDOFF","module_kind":"CACHE_POLICY","outputs":["S2_00-CONTEXT-MATERIALIZATION-RECEIPT","S2_10-CACHE-IDENTITY-INPUT"],"owner":"Stage_2_cache_policy_owner","path":"registry/cache/prompt_cache_policy.yml","produced_schema_ids":[],"schema_version":"stage2_prompt_cache_policy.v2","scope_predicate":"consumer == S2_10","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"32b638073b721a9f395d3476105e57236be4e076be81fd6e93f1475b29b93e2a","size_bytes":7527},{"asset_version":"s2_00.test.1.2","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"module_id":"REGRESSION-MANIFEST-S2_00","module_kind":"TEST_MANIFEST","outputs":["FIXTURE-RESULT-DIGEST"],"owner":"Stage_2_regression_owner","path":"tests/fixtures/regression_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_00_regression_manifest.v1","scope_predicate":"workflow_id == S2_00","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"734b70ab4ae7ef5b4d65129ae33eef1677b647fadacbafb479f64fae1978c0ac","size_bytes":58019},{"asset_version":"s2_40.finalizer.1","authority_ids":[],"consumed_schema_ids":["https://schemas.liti-agent.local/stage2/s2_00/context.schema.v2.json","https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json","https://schemas.liti-agent.local/stage2/s2_10/s2_10.schema.v2.json","https://schemas.liti-agent.local/stage2/s2_20/binding_retrieval.schema.v1.json","https://schemas.liti-agent.local/stage2/s2_20/calculation.schema.v1.json","https://schemas.liti-agent.local/stage2/s2_20/relief_plan.schema.v1.json","https://schemas.liti-agent.local/stage2/s2_30/draft_atoms.schema.v1.json","https://schemas.liti-agent.local/stage2/s2_40/package.schema.v1.json","https://schemas.liti-agent.local/stage2/shared/deployment.schema.v3.json","https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json"],"dependency_module_ids":["SCHEMA-CONTEXT","SCHEMA-DEPLOYMENT","SCHEMA-INGRESS","SCHEMA-REVIEW-STATUS","SCHEMA-S2_10","S2_20-ASSET-809C3C709B4F2295","S2_20-ASSET-AA40CF5140DE8790","S2_20-ASSET-C9FC917D8CBF920E","S2_20-ASSET-E82839694073D431","S2_20-ASSET-FF1F03B3FC56E579","S2_30-ASSET-6A9B1F5EC854740E","S2_30-ASSET-E1FCF8BD63300F4D","S2_40-ASSET-5C4CAFFAB8D2F982","WF-S2_00","WF-S2_10"],"entry_routes":["TO_S2_40","TO_S2_40_STATUS_ONLY"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","S2_40-DIRECTORY-SCAN","S2_40-FREE-TEXT-RENDER-FALLBACK","S2_40-LLM-CALL","S2_40-RUN-STATUS-NOT-LAST","S2_40-UNVERIFIED-READY"],"implementation_status":"IMPLEMENTED_OFFLINE_CONTRACT_LIVE_ADMISSION_PENDING","incompatible_module_ids":[],"inputs":["ingress/ingress_status.json","ingress/technical_diagnostic.json","ingress/stage1_input_manifest.json","ingress/intake_report.json","review/issue_ledger.base.json","map_s2_10/s2_10_publish_status.json","plan/plan_publish_status.json","plan/canonical_relief_plan.json","plan/claim_groups.json","plan/case_type_bindings.json","map_s2_30/s2_30_publish_status.json","map_s2_30/artifact_manifest.json","map_s2_30/{draft_parts,issue_patches,worknote_parts,usage_parts}/.json","review/review_receipts/.json","review/lawyer_judgment_record.json"],"legal_admission_status":"PENDING","live_admission_status":"PENDING","module_id":"WF-S2_40","module_kind":"WORKFLOW","outputs":["review/issue_ledger.final.json","review/assumption_ledger.json","review/llm_usage.jsonl","candidates/by-content-digest//","review/review_requests/.json","final/claim_relief.md","final/claim_cause.md","final/pleading_draft.md","final/stage2_package.json","commit/commit_intent.json","commit/stage2_commit_result.json","control/run_status.json"],"owner":"Stage_2_S2_40_owner","path":"workflows/S2_40_final_review_render_and_commit.yml","produced_schema_ids":["stage2_s2_40_candidate_manifest.v1","stage2_s2_40_commit_intent.v1","stage2_s2_40_commit_result.v1","stage2_s2_40_package.v1","stage2_s2_40_run_status.v1"],"schema_version":"stage2_workflow_contract.v1","scope_predicate":"workflow_id == S2_40 and entry_route in {TO_S2_40,TO_S2_40_STATUS_ONLY}","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ab1e5f593db41c1f26f9510c00d657221da53d08f011b2c4cf341a764a18d874","size_bytes":4415,"status_only_exact_inputs":["ingress/ingress_status.json","ingress/technical_diagnostic.json","ingress/stage1_input_manifest.json","ingress/intake_report.json","review/issue_ledger.base.json"]},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_resolver_source_lock.txt","mirror_sha256":"51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e","mirror_size_bytes":14423,"module_id":"TEST-S2_00-RESOLVER-SOURCE-LOCK","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_resolver_source_lock.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == resolver_source_lock","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"51bc1b310d40f5068df0a66446e5b96b00ea9b5b0137ddaf563caadf9f8fc51e","size_bytes":14423},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_schema_hash_and_signals.txt","mirror_sha256":"14207eedd80caaf24d85377617fb754bdeecc80ba9b2a291d6ac5d09ab0a6191","mirror_size_bytes":12842,"module_id":"TEST-S2_00-SCHEMA-HASH-SIGNALS","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_schema_hash_and_signals.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == schema_hash_signals","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"14207eedd80caaf24d85377617fb754bdeecc80ba9b2a291d6ac5d09ab0a6191","size_bytes":12842},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_conservation.txt","mirror_sha256":"c906dff7e11678a60556818d1baf24e66844d9c982c9d333ec339d2ed9ca6061","mirror_size_bytes":5562,"module_id":"TEST-S2_00-CONSERVATION","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_conservation.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == conservation","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"c906dff7e11678a60556818d1baf24e66844d9c982c9d333ec339d2ed9ca6061","size_bytes":5562},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_canonical_ids.txt","mirror_sha256":"c463506a90859daeef7eafddc4a6c08c563e2ae73200d921c1f00efb7bc24361","mirror_size_bytes":2275,"module_id":"TEST-S2_00-CANONICAL-IDS","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_canonical_ids.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == canonical_ids","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"c463506a90859daeef7eafddc4a6c08c563e2ae73200d921c1f00efb7bc24361","size_bytes":2275},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_cluster_bundle_compile.txt","mirror_sha256":"b643d2d4018ebe3349c64304063edf7ba0194fc92fb1fe9337eca3f384ae794a","mirror_size_bytes":25690,"module_id":"TEST-S2_00-CLUSTER-BUNDLE","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_cluster_bundle_compile.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == cluster_bundle_compile","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"b643d2d4018ebe3349c64304063edf7ba0194fc92fb1fe9337eca3f384ae794a","size_bytes":25690},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["FIXTURE-FAMILY"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_failure_and_atomic_publish.txt","mirror_sha256":"613f0c1b32dc26c302365fc62f36c8ede7204e1ced4920e797a1651af8354527","mirror_size_bytes":25937,"module_id":"TEST-S2_00-FAILURE-ATOMIC-PUBLISH","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_failure_and_atomic_publish.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == failure_atomic_publish","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"613f0c1b32dc26c302365fc62f36c8ede7204e1ced4920e797a1651af8354527","size_bytes":25937},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":[],"module_id":"P00","module_kind":"LLM_PROMPT_CONTRACT","outputs":["STATIC_PREFIX_SEGMENT"],"owner":"Stage_2_prompt_owner","path":"prompts/P00_system_and_safety_contract.md","produced_schema_ids":[],"schema_version":"stage2.prompt_contract.v1","scope_predicate":"static_prefix_segment == P00","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e","size_bytes":7304},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P00"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P00"],"module_id":"P10","module_kind":"LLM_PROMPT_CONTRACT","outputs":["STATIC_PREFIX_SEGMENT"],"owner":"Stage_2_prompt_owner","path":"prompts/P10_legal_resolution_contract.md","produced_schema_ids":[],"schema_version":"stage2.prompt_contract.v1","scope_predicate":"static_prefix_segment == P10","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","size_bytes":8712},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-EC-00_CONTRACT_GENERAL","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/EC-00_contract_general.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/EC-00_contract_general.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"a4f7abd9957b3a9e58d05dd559c3c869bf96fd88ea18968a363c6e606e3c0aa8","size_bytes":3789},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-01_JURISTIC_ACT_VALIDITY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-01_juristic_act_validity.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-01_juristic_act_validity.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"0a0d2676f96be321a7bb974b8e4fb1981ab43773f271c99dc86a70cb17d27c99","size_bytes":3808},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-02_CONTRACT_MONEY_CLAIM","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-02_contract_money_claim.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-02_contract_money_claim.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"08e252bccc718ccc44a258bc540afc2567e509239399f4017550df32bac97824","size_bytes":3784},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-03_PARTIES_LIABILITY_SUCCESSION","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-03_parties_liability_succession.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-03_parties_liability_succession.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"4e841d5f640b06a1b52060b82dda39605369cbe26d81655b7918673437e4519c","size_bytes":3799},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-04_UNJUST_ENRICHMENT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-04_unjust_enrichment.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-04_unjust_enrichment.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"31a5966d4c14940e810f870bf4382f1be642f7716ebaaa35193ef32e9b9d95c7","size_bytes":3725},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-05_TORT_GENERAL","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-05_tort_general.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-05_tort_general.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"fe6ea92fc10c4196e0ac83b990bf2606e24024030e7b0002fecdae9f8f50221a","size_bytes":3694},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-06_PROFESSIONAL_LIABILITY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-06_professional_liability.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-06_professional_liability.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"efa7a4f6cda90c04a06558a9d0e1efe13b25169d55d03e36d55d72fcdd096a15","size_bytes":3724},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-07_CONSTRUCTION_DEFECT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-07_construction_defect.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-07_construction_defect.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"78c76cb0485a4acf741109aee05f634f51c3a6904044c613080b21c3978a09f9","size_bytes":3710},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-08_LEASE_DEPOSIT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-08_lease_deposit.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-08_lease_deposit.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"dbe1886671edff49b8b0251eed567d1b3e4e5d748456434262286ca7acf990db","size_bytes":3678},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-09_REGISTRY_TRANSFER_CLAIMS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-09_registry_transfer_claims.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-09_registry_transfer_claims.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"d18946322a8cb528146ac0aa0a2880c41ac2056671fd237b928341ceb8561002","size_bytes":3800},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-10_SECURED_REGISTRY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-10_secured_registry.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-10_secured_registry.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"5819c26ec8478e12a12e340c93a9d23cc410833e1192c2315a1986c9d48a1eba","size_bytes":3757},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-11_POSSESSION_VINDICATION","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-11_possession_vindication.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-11_possession_vindication.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"5e6d6460be4ec0f2ba0096305b9ae39f5f430d107337d0d7e07aac1a9d599aaf","size_bytes":3724},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-12_CO_OWNERSHIP_BOUNDARY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-12_co_ownership_boundary.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-12_co_ownership_boundary.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"62cfbf6a6c5c5edc8b912e348be1c4d4f7dd4c20c722e57e5554058f0caafb4a","size_bytes":3712},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-13_CREDITOR_PRESERVATION","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-13_creditor_preservation.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-13_creditor_preservation.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"c60e6d67c7e3985d1f6ce44027726282f931934e3e66b44f06ccd26845ca2f45","size_bytes":3826},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-14_EXECUTION_LINKED_CLAIMS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-14_execution_linked_claims.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-14_execution_linked_claims.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"45d4b3ab46e1c8834c3b3eec72a28d05e39cb78a9ec2c2de07b5e55e81aeebd7","size_bytes":3787},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-15_SUCCESSION_FAMILY_PROPERTY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-15_succession_family_property.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-15_succession_family_property.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"f691b67295ad8e634b34519cf71156caf6eaf73cef54577615ab79462f8aa766","size_bytes":3763},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-16_NEGOTIABLE_INSTRUMENTS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-16_negotiable_instruments.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-16_negotiable_instruments.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"7720d83b64e7a44720788f6ff3c7cc8ceaf5195377a1e61b52de2144989a1194","size_bytes":3738},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-17_LABOR_WAGE_CLAIMS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-17_labor_wage_claims.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-17_labor_wage_claims.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"168ce5e41104937cf7ab946944f060b82cfe16066425897f07bb9e837b8689ea","size_bytes":3728},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-18_ORG_RESOLUTION_STATUS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-18_org_resolution_status.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-18_org_resolution_status.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"59cf689f886dfaf4ad00dbe6142f5b11c37d0062660f7467aa43427462aa075f","size_bytes":3763},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-19_INSURANCE_CLAIMS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-19_insurance_claims.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-19_insurance_claims.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"0fb4793446c155e7a0b4469c9b8c1be1323112eef55ca4c495307c1af56e754c","size_bytes":3685},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-20_IP_CLAIMS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-20_ip_claims.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-20_ip_claims.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"fe07f20d149a2c4deac2e46de299cd78f0bf829f58c615a86c45f542d30804e1","size_bytes":3654},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-21_MEDIA_PERSONALITY_RIGHTS","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"registry/substantive/E-21_media_personality_rights.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == registry/substantive/E-21_media_personality_rights.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"951260bbe8ef116d682f49f3679106c7144ca68f8078f5c10b3459667c1f5b2c","size_bytes":3803},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-E-00_RESIDUAL_UNROUTED","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/crosscut/E-00_residual_unrouted.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/crosscut/E-00_residual_unrouted.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"639e507147a6132f9e41ccd0b00d1b5450d6a9629991629b173d5bcaf5b6df39","size_bytes":3752},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-X1_NOTICE_LIFECYCLE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/crosscut/X1_notice_lifecycle.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/crosscut/X1_notice_lifecycle.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"9af8b5b5f3a8196a10308d1ee34e0788d9adeac7a99e142e449490d14316faef","size_bytes":3693},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-X2_ASSET_IDENTITY_LINEAGE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/crosscut/X2_asset_identity_lineage.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/crosscut/X2_asset_identity_lineage.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"6c1e437944b3a62b60ee7acad5ec9177fefac2991fe970338acc27efcc8a13ad","size_bytes":3742},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-X3_PROCEDURE_STANDING_RELIEF","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/crosscut/X3_procedure_standing_relief.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/crosscut/X3_procedure_standing_relief.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"f3b794bef82566e569232ba02c63ae148099143d8d1ab84de1c4fb76105e65df","size_bytes":3788},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-X4_RESPONSE_ADMISSION_DEFENSE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/crosscut/X4_response_admission_defense.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/crosscut/X4_response_admission_defense.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"57851ed55b3351a8139df29224d74b7cb8427708bbf6de00ecd27c44089df32e","size_bytes":3793},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-AUTO_MOTOR_VEHICLE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-AUTO_motor_vehicle.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-AUTO_motor_vehicle.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"7234a7ab890f242e6b7aa811528e34c0c85779007cffbf135da0bfff36d61d91","size_bytes":3762},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-INDUSTRIAL_ACCIDENT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-INDUSTRIAL_ACCIDENT.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-INDUSTRIAL_ACCIDENT.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"10d78b8031df7d89f835afc9ca60fab36648e561c729780204c80885f4dd097f","size_bytes":3750},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-PRODUCT_LIABILITY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-PRODUCT_LIABILITY.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-PRODUCT_LIABILITY.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"1d5ee8eddcf005fdb33df58f591a8948aa3e891a3a5656d919394ff0b39eea53","size_bytes":3737},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-RESIDENTIAL_LEASE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-RESIDENTIAL_LEASE.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-RESIDENTIAL_LEASE.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"3e2efd1b3c0524a305eafedc5ec91e05be989a6e55c1501ed161a9b8f8151fd7","size_bytes":3739},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-COMMERCIAL_LEASE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-COMMERCIAL_LEASE.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-COMMERCIAL_LEASE.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"5aebed9ab56bc00eb7e0511f9fe5db8c3a42f1e81b28d58c38d487aa91cbab3e","size_bytes":3769},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-LABOR","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-LABOR.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-LABOR.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"6b2542bb64f4c1d164b1ccd2ce5099fad29bcea4333d9e34bd0fb1667b9ced4a","size_bytes":3694},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-STATE_LIABILITY","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-STATE_LIABILITY.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-STATE_LIABILITY.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"5b2fe6d57b918384a619efbd04360ddfaf7720d384136f69d359ccb0b6c853d3","size_bytes":3747},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-IP-PATENT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-IP-PATENT.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-IP-PATENT.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"d0651a8a50d0b18d25931063314ecec284988c5a18fab68d08a317d725bb3066","size_bytes":3709},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-IP-COPYRIGHT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-IP-COPYRIGHT.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-IP-COPYRIGHT.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"d4349677f68346f79709ea23a05957262f6426f976388bba45f05c617035eb78","size_bytes":3728},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-IP-OTHER","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-IP-OTHER.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-IP-OTHER.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"fc3e2772252a3a90571663ebcfbc8e18dbf526977f4a3d77c4705ef8aa8dd6a8","size_bytes":3746},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-MEDIA","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-MEDIA.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-MEDIA.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"e0d5d287befd1578a06c64a265d5c4426af5772b6764018f6a15f00aac3b498c","size_bytes":3705},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-TRANSPORT_MARITIME","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-TRANSPORT_MARITIME.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-TRANSPORT_MARITIME.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"6e87a77c25f8c358f1d7d35ca165b1229c2cb422a440c91768ad80e520d35456","size_bytes":3835},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-SL-CONSUMER_CONTRACT","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/special_law/SL-CONSUMER_CONTRACT.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/special_law/SL-CONSUMER_CONTRACT.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"afd8bbba102614d8d08f2e7a5384f6ca24e1309c1f52feb13906613f2ced51b7","size_bytes":3797},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-ACTIO-MORTGAGE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/overlays/ACTIO-MORTGAGE.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/overlays/ACTIO-MORTGAGE.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"7e584f7b4e4d19132e9575071f87d05965fb77fa2ca870911fe9974a7c511c4d","size_bytes":3739},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-ACTIO-MORTGAGE-CREATION","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/overlays/ACTIO-MORTGAGE-CREATION.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/overlays/ACTIO-MORTGAGE-CREATION.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"e727690ee23883e011d49eba01cfd87abc5482641c2bda519c0a39518e1769ee","size_bytes":3771},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-ACTIO-ENCUMBERED-TRANSFER","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/overlays/ACTIO-ENCUMBERED-TRANSFER.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/overlays/ACTIO-ENCUMBERED-TRANSFER.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"fa950393a572829ba7e296c20cd08ff19a063b0f8441f950130fd677b1e38179","size_bytes":3828},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-ACTIO-PRESERVED-CLAIM-BUNDLE","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/overlays/ACTIO-PRESERVED-CLAIM-BUNDLE.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/overlays/ACTIO-PRESERVED-CLAIM-BUNDLE.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"fbd99f029438c1c278f93d88d18a703db72e78f20c7049f344e5748c108f94c5","size_bytes":3816},{"asset_version":"stage2.bundle.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["P10"],"implementation_status":"DRAFT_UNVERIFIED_HASH_BOUND","incompatible_module_ids":[],"inputs":["P10","TYPED_STAGE1_CONTEXT"],"module_id":"PROFILE-ACTIO-DEFENSE-MAP","module_kind":"LLM_CONTEXT_PROFILE","outputs":["ACTIVE_PROFILE_CONTEXT"],"owner":"Stage_2_profile_owner","path":"profiles/overlays/ACTIO-DEFENSE-MAP.yml","produced_schema_ids":[],"schema_version":"stage2.llm_context_profile.v1","scope_predicate":"release_selected_profile_path == profiles/overlays/ACTIO-DEFENSE-MAP.yml","semantic_review_status":"PENDING_LEGAL_REVIEW","sha256":"05348c493e6046a3e5c55f9b516c0e862fe5aa753e1b2fc71624bb2b11f0c191","size_bytes":3810},{"asset_version":"s2_00.build.1.2","authority_ids":[],"consumed_schema_ids":["https://schemas.liti-agent.local/stage2/shared/deployment.schema.v2.json"],"dependency_module_ids":["SCHEMA-DEPLOYMENT"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":["AUTHORING-AGENT-YAML"],"mirror_byte_parity":true,"mirror_path":"offline_build/build_s2_00_inline_projection.txt","mirror_sha256":"31c96b6abe2eb0ed1f9c9e571e1f4f326307225dfddf40a6670e2d3073ed2ab4","mirror_size_bytes":35198,"module_id":"BUILD-S2_00-INLINE-PROJECTION","module_kind":"BUILD_TOOL","outputs":["DEPLOYMENT-AGENT-PROJECTION","FULL-CODE-MIRRORS","INLINE-CODE-RECEIPT"],"owner":"Stage_2_release_build_owner","path":"offline_build/build_s2_00_inline_projection.py","produced_schema_ids":["stage2_s2_00_inline_code_receipt.v2"],"schema_version":"offline_projection_builder.v1","scope_predicate":"build_target == S2_00_INLINE_AGENT","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"31c96b6abe2eb0ed1f9c9e571e1f4f326307225dfddf40a6670e2d3073ed2ab4","size_bytes":35198},{"asset_version":"s2_00.test.1","authority_ids":[],"consumed_schema_ids":["https://schemas.liti-agent.local/stage2/shared/deployment.schema.v2.json"],"dependency_module_ids":["BUILD-S2_00-INLINE-PROJECTION","SCHEMA-DEPLOYMENT","WF-S2_00"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND","incompatible_module_ids":[],"inputs":["AUTHORING-AGENT-YAML","DEPLOYMENT-AGENT-PROJECTION","FULL-CODE-MIRRORS"],"mirror_byte_parity":true,"mirror_path":"tests/s2_00/test_inline_code_parity.txt","mirror_sha256":"8f0f55e8e1b970de572129946ab8bf34967c7fd84e316a9193509cab07a455ed","mirror_size_bytes":15928,"module_id":"TEST-S2_00-INLINE-CODE-PARITY","module_kind":"TEST","outputs":["TEST-RECEIPT"],"owner":"Stage_2_test_owner","path":"tests/s2_00/test_inline_code_parity.py","produced_schema_ids":[],"schema_version":"pytest.v1","scope_predicate":"test_axis == inline_code_parity","semantic_review_status":"PENDING_CROSS_AUDIT","sha256":"8f0f55e8e1b970de572129946ab8bf34967c7fd84e316a9193509cab07a455ed","size_bytes":15928},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"WF-S2_10","module_kind":"WORKFLOW","outputs":["WF-S2_10"],"owner":"Stage_2_S2_10_owner","path":"workflows/S2_10_domain_relief_resolution_map.yml","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f0fba48f1760cf4e233d7d698fd19090f96ffb89cabe4b2e2cae9af7c616be0f","size_bytes":15320},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["WF-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"AGENT-S2_10-HYBRID","module_kind":"LLM_AGENT","outputs":["AGENT-S2_10-HYBRID"],"owner":"Stage_2_S2_10_owner","path":"agent_scripts/Stage_2_S2_10.yml","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"SCHEMA-S2_10","module_kind":"JSON_SCHEMA","outputs":["SCHEMA-S2_10"],"owner":"Stage_2_S2_10_owner","path":"schemas/s2_10.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5233afde9ddb3c5868b9101816e8b3830a90b1399e3e5e89d9d7c7bf5beacaee","size_bytes":82703},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["AGENT-S2_10-HYBRID","SCHEMA-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"BINDING-S2_10-HYBRID","module_kind":"DEPLOYMENT_BINDING","outputs":["BINDING-S2_10-HYBRID"],"owner":"Stage_2_S2_10_owner","path":"deployment/stage2_s2_10_llm_binding.yml","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9b5d69f1316a0b9fba7b41097ee92142cf42485c8deb0be876d9e9329c317a04","size_bytes":7287},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["AGENT-S2_10-HYBRID","P00","P10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"PROMPT-PROJECTION-S2_10","module_kind":"BUILD_RECEIPT","outputs":["PROMPT-PROJECTION-S2_10"],"owner":"Stage_2_S2_10_owner","path":"manifest/s2_10_inline_prompt_projection_receipt.json","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"b7fdef2ad05f251bdede9473d3b69c0f169ab7f4a059b393429ff76f739f703e","size_bytes":2659},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"offline_build/build_s2_10_agent_projection.txt","mirror_sha256":"efdde6d70c723e9386f2ba1828119af7e68f7956c29bd3ba05370242a70ab62d","mirror_size_bytes":68381,"module_id":"BUILD-S2_10-HYBRID","module_kind":"BUILD_ONLY","outputs":["BUILD-S2_10-HYBRID"],"owner":"Stage_2_S2_10_owner","path":"offline_build/build_s2_10_agent_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"efdde6d70c723e9386f2ba1828119af7e68f7956c29bd3ba05370242a70ab62d","size_bytes":68381},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["SCHEMA-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"offline_build/validate_s2_10_contract.txt","mirror_sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","mirror_size_bytes":63811,"module_id":"VALIDATOR-S2_10","module_kind":"BUILD_ONLY","outputs":["VALIDATOR-S2_10"],"owner":"Stage_2_S2_10_owner","path":"offline_build/validate_s2_10_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","size_bytes":63811},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"tests/s2_10/test_agent_contract.txt","mirror_sha256":"0a7b41894733b743d11ff88f0817a87bdbc98be317d8b3410baa8e9401b5b7bd","mirror_size_bytes":8076,"module_id":"TEST-S2_10-AGENT","module_kind":"TEST","outputs":["TEST-S2_10-AGENT"],"owner":"Stage_2_S2_10_owner","path":"tests/s2_10/test_agent_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0a7b41894733b743d11ff88f0817a87bdbc98be317d8b3410baa8e9401b5b7bd","size_bytes":8076},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["SCHEMA-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"tests/s2_10/test_wave_dispatch.txt","mirror_sha256":"f7e59189ed93585c16c55943f7cc3ed464091fb23a9ea086e6e209cf14677a48","mirror_size_bytes":9894,"module_id":"TEST-S2_10-DISPATCH","module_kind":"TEST","outputs":["TEST-S2_10-DISPATCH"],"owner":"Stage_2_S2_10_owner","path":"tests/s2_10/test_wave_dispatch.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f7e59189ed93585c16c55943f7cc3ed464091fb23a9ea086e6e209cf14677a48","size_bytes":9894},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["SCHEMA-S2_10","VALIDATOR-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"tests/s2_10/test_domain_verdict_contract.txt","mirror_sha256":"9f2547a8c590b7df2aa09d0c3808766bf16be321a448742020d9a3476e7d837f","mirror_size_bytes":10242,"module_id":"TEST-S2_10-DOMAIN","module_kind":"TEST","outputs":["TEST-S2_10-DOMAIN"],"owner":"Stage_2_S2_10_owner","path":"tests/s2_10/test_domain_verdict_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9f2547a8c590b7df2aa09d0c3808766bf16be321a448742020d9a3476e7d837f","size_bytes":10242},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["PROMPT-PROJECTION-S2_10"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"tests/s2_10/test_prompt_cache_and_boundaries.txt","mirror_sha256":"b77e63b19ba5a843df88180a5e7ac0441256682ea9aa92dc490415a75f1dcee5","mirror_size_bytes":11365,"module_id":"TEST-S2_10-PROMPT","module_kind":"TEST","outputs":["TEST-S2_10-PROMPT"],"owner":"Stage_2_S2_10_owner","path":"tests/s2_10/test_prompt_cache_and_boundaries.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"b77e63b19ba5a843df88180a5e7ac0441256682ea9aa92dc490415a75f1dcee5","size_bytes":11365},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":["BINDING-S2_10-HYBRID"],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"mirror_byte_parity":true,"mirror_path":"tests/s2_10/test_release_adapter_retry.txt","mirror_sha256":"2a6a3119608b6063137575d66b8552623f164dbdd0952bc97074d6f687fb32e0","mirror_size_bytes":10848,"module_id":"TEST-S2_10-RELEASE","module_kind":"TEST","outputs":["TEST-S2_10-RELEASE"],"owner":"Stage_2_S2_10_owner","path":"tests/s2_10/test_release_adapter_retry.py","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"2a6a3119608b6063137575d66b8552623f164dbdd0952bc97074d6f687fb32e0","size_bytes":10848},{"asset_version":"s2_10.hybrid.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3","RAW-STAGE1-REREAD"],"implementation_status":"IMPLEMENTED_OFFLINE_VERIFIED","incompatible_module_ids":[],"inputs":["S2_10-HYBRID-CONTRACT"],"module_id":"REGRESSION-MANIFEST-S2_10","module_kind":"TEST_MANIFEST","outputs":["REGRESSION-MANIFEST-S2_10"],"owner":"Stage_2_S2_10_owner","path":"tests/fixtures/s2_10/regression_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_10_hybrid_asset.v1","scope_predicate":"workflow_id == S2_10","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6fe7bac0fb2b87e4ff3535c9bfa78531aff91af4cc1142a09035225b95581e3d","size_bytes":2572},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-F82ABBC2137A8ABF","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"corpus/build_receipt.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"57fbf8c3f5f86f00db668c425c3e07de74e9d5820b71975c4da3a3bff32e036d","size_bytes":1871},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-F8EF2F640FB77AD1","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"corpus/chunk_manifest.jsonl","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"fd3e1ba067b5960e1d3dba1b5107de913d45ba2b3732a28c3870b10105761b67","size_bytes":620},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-787106ABBFAF8931","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"corpus/source_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ce3ce207ed274292499630a0813d4bdb6a66baf26710fb0e883c2e405adb9a67","size_bytes":807},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-3CD8C31D78EBF47F","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"corpus/weaviate_collection.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f29b287e99d29dbd6d3008d1ad68e3960f9cc2c72459f04316f0311cd3e9a47d","size_bytes":18104},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E852EAB9373DF086","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"law_values/court_fee_values.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"d1213e58b0de3b728945134e0a00a71565fee6db9077c932d7ee99da506c1115","size_bytes":912},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-309310FEC8A6178F","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"law_values/general_law_values.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"45ad98e9e93090fbc5e5c7037f404bd86ff89b73a4aaf8c3449d226bd2aacd1c","size_bytes":843},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-060B74A3C012D23C","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/authority_release.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"cc683958377eea44756de6e9c74fc925da66dd60cc84363f5bec36584f5b2967","size_bytes":1068},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B51F7A86E15908DD","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/case_type_coverage.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"34d6f758fc1486fa7330ede376e65b9448a6eaa971bd21472b0e4b7d9a5b8cba","size_bytes":143780},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-16A7CA30B83DD493","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/case_type_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6462217f08ced21693e8cfc812182cfc1da593d52e719e5cd11ef30409ffd00e","size_bytes":80525},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-34A6FBBE9101F1E8","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/case_type_rule_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ef42e873f497e1e2cfdf9440207f7caaa1f55462a3d47dc207b3c20f9c102793","size_bytes":56945},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-3051DBC07D975B39","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/corpus_release.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"27d0c83e7a95342efdbe5be675b6d5b7d0ff8695eeec022ebc5aded3359fc981","size_bytes":920},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-98D409BCD1DE68FA","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"manifest/s2_20_parent_member_paths.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"19822af8fd0245c84b303955106c99ebdfcb5bbce06e76602178c90d4ecf6e82","size_bytes":5443},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-672D5EBD9C1F8AE0","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"migration/actio_assets_receipt.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0d1a3b5eaa7ea670f76db0baa8c30e23b4367904c3f715145737f1dff22f9204","size_bytes":10407},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-2B7093A6A3B291AF","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"migration/legacy_asset_disposition.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"1b0c6b3bafd8bb11ec90e809d0fce057fec83fb12b1f9976471f8952ce073f2c","size_bytes":6039},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_authority_law_value_release.txt","mirror_sha256":"8c1d9b2f05fa752d50349ed1a4479aafcb17c2f574fa1ebe6b19d2bedc21ffeb","mirror_size_bytes":7213,"module_id":"S2_20-ASSET-E3CE7EC9216DDBD3","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/build_authority_law_value_release.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"8c1d9b2f05fa752d50349ed1a4479aafcb17c2f574fa1ebe6b19d2bedc21ffeb","size_bytes":7213},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_corpus_snapshot.txt","mirror_sha256":"96feead66f24d375b9ac379f459de040a9ae1f368e9c05d2911c5b0da54c02c2","mirror_size_bytes":9781,"module_id":"S2_20-ASSET-5F7DB1273D883DE5","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/build_corpus_snapshot.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"96feead66f24d375b9ac379f459de040a9ae1f368e9c05d2911c5b0da54c02c2","size_bytes":9781},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_release_manifests.txt","mirror_sha256":"9356d18267375e731e878ab301dcec01a728d73761df0dd65829599c00ccfcd5","mirror_size_bytes":30698,"module_id":"S2_20-ASSET-6CE2AD14244F5B49","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/build_release_manifests.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9356d18267375e731e878ab301dcec01a728d73761df0dd65829599c00ccfcd5","size_bytes":30698},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_s2_20_inline_projection.txt","mirror_sha256":"b5c035251621920dd848d672dc6cf840500ce2b60e1e6656f021855681f6fc58","mirror_size_bytes":27865,"module_id":"S2_20-ASSET-86DCA2BCA2270252","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/build_s2_20_inline_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"b5c035251621920dd848d672dc6cf840500ce2b60e1e6656f021855681f6fc58","size_bytes":27865},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/compile_case_type_registry.txt","mirror_sha256":"e415b5179e53f5a7e35e5e1b7749706c783fbf296bf0bf40103e9450df0b2f0c","mirror_size_bytes":9658,"module_id":"S2_20-ASSET-A360A270415B6E16","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/compile_case_type_registry.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e415b5179e53f5a7e35e5e1b7749706c783fbf296bf0bf40103e9450df0b2f0c","size_bytes":9658},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/compile_relief_rule_projection.txt","mirror_sha256":"8412f2ad7b8de4738fbb86a7596def90dbc9d34d4e2f24854e964df476589c2f","mirror_size_bytes":42682,"module_id":"S2_20-ASSET-B57CC23FD4D06275","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"offline_build/compile_relief_rule_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"8412f2ad7b8de4738fbb86a7596def90dbc9d34d4e2f24854e964df476589c2f","size_bytes":42682},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-DDC65130DFBDBA55","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/binding/binding_signature_projection.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"b4317d0a5adc3f2bc70214c3e98c4f885ecfd26e36d8242221db4971b6f53142","size_bytes":835},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-AA1E72AB254FE6DC","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-01_interest_delay.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"d0d180a8f8af72d7dda5134b521122827fd2d1f9055c10d35ef5881d7d8cea53","size_bytes":1503},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-45939B38FC8F0B28","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-02_allocation_setoff_balance.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"19a6a32b5879f20ed36df149cdbfb40ec2b5835152579e90a396f745e6299772","size_bytes":1511},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-A4DAC30C3F1AC365","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-03_limitation_deadline.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"1dc66a75034576a41be43058ac421f5c8188288da9928df4d5b9cf616a819ea7","size_bytes":1515},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-D9EEBF8449D85E04","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-04_valuation.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e83044bfd16167cc6c1028afa06b0dc041e0114cee72379563047cff9fbeba11","size_bytes":1483},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-BC815891D9220145","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-05_personal_injury.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0f197813d298f87010545d6eb09c4107c13303b6eb83d276e0130e25abaa7b00","size_bytes":1512},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-2A85ED56A7C1242A","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-06_construction_defect.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"1626c6673b7381e00fa61b7724ae63c8b10cb2ddd932040edc5f69889ffe5ab3","size_bytes":1522},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-6E799BF3C28471BC","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-07_lease_use_gain.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f05c94ad80280607664a1ddcbd29367d0164333888c0d744dd674bf21cee3fad","size_bytes":1488},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-3F219FD043EF4AE1","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-08_inheritance_reserved_share.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"330a1e5f72e4a4e4b7da096ceae554312ca2f828363b761ed37af37abf281818","size_bytes":1518},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-BCAEF55DAB2126D1","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-09_wage_severance.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"dba73da63069e89f95550419d989da78f8fe10196b052c49f050466a0dcda5b9","size_bytes":1489},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-81B84BD832C992EF","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-10_actio_insolvency_value.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"c8710d3e9292b95e53d834006e784b13669b9023149e26628d0abaff074c1c85","size_bytes":1532},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-2852DF1EC788C440","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-11_distribution_share_division.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"4b3c8161ae779628575e122f1f602d6bee40b387c402c5ce642692796e1ab369","size_bytes":1512},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-FD4E3378C53FDCB5","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-12_insurance.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"66d58d2043e45966df9db6c89e980f3c91cbdd6fcf4a4d96944fc203abedf532","size_bytes":1503},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-22371F1936240951","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-13_court_value_cost.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6f914553fd25a9ecb28d85070c2c0ddbf41178906f9075092f9d174977073824","size_bytes":1539},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-711DD22CD3721D81","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-R1_ip_damage.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"d33b7963d68cee10281da86e465caed152e3f69493728a563bca69c6dfb18c2b","size_bytes":1482},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B585B054934C1C1D","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-R2_org_liquidation.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"3bb03e07ba28a01d8c9e3944df55fbc43b21e17435bfa5e84ec60ef7b1540991","size_bytes":1513},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E032EAE75B122995","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-R3_transport_maritime.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e64e808a4d1637c991f1ab512fad25f51637ecba3b2b0dfa66abb7efb8504c7e","size_bytes":1508},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-ED6526C35FE96ACC","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/CE-R4_financial_instrument.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0198a5d09f9b75dd3b6978a01c9a8a3e468c8dd305c49721ae04ce93954b72d3","size_bytes":1510},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B0A8A8F08ECBF0AA","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/calculations/calculation_activation_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"1a152af7e0ed4ee2ce10ab93bf3be343122f95e9f276585433449bde27c46e55","size_bytes":5540},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-69ADD915C1858F49","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/corpus/requirement_fact_scope.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6b38306dd4657df2c929caeb1b71bf78838f628e99018fff4692bacf4d49e2c1","size_bytes":216},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-A416DC6DB820828C","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/drafting/case_type_relief_rules.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"01f95c0c1a95f80bfde1ee9c166ffb3ab1f22339ee035f5c322e2637329b8214","size_bytes":1416},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B8BE6EC64CED552C","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/drafting/counter_performance_rules.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5c9e274f38fcfa4e8bfcb0938d2274b8dd83a6f8dac874de3c237b7a2608ab43","size_bytes":857},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-5FDE95EE5314FCA7","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/drafting/forbidden_relief_rules.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"fb51bec7b741e983a5e6f59f8265f3818c49f8067323e9b2090673a832eaae22","size_bytes":852},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-8CDFE6C311F7F7D3","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/drafting/procedural_declaration_rules.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"3328d71a3fb020024fa8a0f8592788d409845d5ca0e2ca9a2b6c63ed3530147c","size_bytes":864},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-4414670A81E95DEA","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/party/party_set_rules.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"92b1b8b76a396008629f534fdcd63995733ccdd71d6b2d9f9c4ad7360daf0c0a","size_bytes":225},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E1D9BDC792A7848D","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/planning/option_disposition_policy.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f3a656c3c1c0eabd22d26e4d3c9f541459af05727f595646a2f7a59d5c5e7658","size_bytes":426},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-CD373B0725950922","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/regression/finding_fixture_map.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"53c92c6b77c85d280aaa37ae5cc4fc355b3ee3e76c55bd87852bd25636f22992","size_bytes":8520},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-809C3C709B4F2295","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/review/review_policy_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"15b3181f7236f9500aea4699a95c71811761add2712eb4a5c4f8cbce11d4ef87","size_bytes":2301},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-8EC84AB1A8C873B2","module_kind":"DECLARATIVE_REGISTRY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"registry/temporal/inheritance_reserved_share.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ca37eb894d04dcba604fe4656f941c44d76fafa1c221f4ffcdd988419a81d7a0","size_bytes":928},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"release_ops/canary_rollback.txt","mirror_sha256":"327356b4f59bb850fcfb680d5caf13038025e3042689f11e1018731058d15241","mirror_size_bytes":1345,"module_id":"S2_20-ASSET-2040ED84718FA22C","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"release_ops/canary_rollback.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"327356b4f59bb850fcfb680d5caf13038025e3042689f11e1018731058d15241","size_bytes":1345},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"release_ops/release_validator.txt","mirror_sha256":"5c962c0ca084ce08a622764c874749bd837534b7b0a3af4ba9f879b975a0f866","mirror_size_bytes":55260,"module_id":"S2_20-ASSET-DBB6C2CCD4AB3FA2","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_20_owner","path":"release_ops/release_validator.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5c962c0ca084ce08a622764c874749bd837534b7b0a3af4ba9f879b975a0f866","size_bytes":55260},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-52C4FB90CB0F9E68","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R01_money_payment.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"98f06696a8c090078b2b4b72e8f25c6ecac342fbdafecfa4024d9f1bef7d6bbf","size_bytes":1844},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B031219CDF7A06DF","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R02_delivery_possession.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"42d9654604aedd4dcbd6724b7960b0c42d281ec775c3a6c635941dd06abc564d","size_bytes":1781},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-7BEB573DD33365A1","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R03_declaration_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ff0e90951b373b662fafe70aa28fdff001b6c3a571180bb2d7537c23a0e4b641","size_bytes":1813},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-769585D81F81F620","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R04_special_nonmoney_performance.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"d1368fab9b91fadf3da0e864941708b7d82a39cda7110723f6a712489b9f014a","size_bytes":1875},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-04C3EF62029B522C","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R05_declaratory.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e903cd34bdf2e48479e5248a9ac120885dc612b27e34b5c9e2b6ce29c8cb89f5","size_bytes":1802},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-BFC589A870A04F07","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"renderers/R06_constitutive_judgment_challenge.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ada485d34b696a8d4e59d85d9e0d22a9f510448813ffa7985700b778581fcaaf","size_bytes":1840},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B2C88C2FFDE4487E","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"routing/actio_pauliana_mortgage_route.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"209fce4f610e7eb6c6ddc2995163de59537ca546752187c23dd1b417e2b117ec","size_bytes":721},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-DD9ABC431EB1B8BC","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"routing/actio_pauliana_route_registry.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f30550aca6ce2a453bd39498d81653eb257cffcd6c693ba56b62f698a510427c","size_bytes":906},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/authority/authority_preflight.txt","mirror_sha256":"ffa513bdc7ddb1de895b4e813de9e107c94c36a5955166c7d5cee745584d0dda","mirror_size_bytes":2115,"module_id":"S2_20-ASSET-2317885DE36C87BB","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/authority/authority_preflight.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ffa513bdc7ddb1de895b4e813de9e107c94c36a5955166c7d5cee745584d0dda","size_bytes":2115},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/binding_signature_projection.txt","mirror_sha256":"0ea048355b4abf8cf261bc60735a557ab09d84e325aa42bd4d7acb58f589c6b5","mirror_size_bytes":5843,"module_id":"S2_20-ASSET-2B67B561F6C4FD3B","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/binding_signature_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0ea048355b4abf8cf261bc60735a557ab09d84e325aa42bd4d7acb58f589c6b5","size_bytes":5843},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c25_case_type_bind.txt","mirror_sha256":"7cda9812225379ef92c34b8ca383aa35bdcbac6afc30b3a21245f5e3ad6aa3af","mirror_size_bytes":3471,"module_id":"S2_20-ASSET-2EABAE08AAE777EA","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/c25_case_type_bind.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"7cda9812225379ef92c34b8ca383aa35bdcbac6afc30b3a21245f5e3ad6aa3af","size_bytes":3471},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c26_rule_branch_bind.txt","mirror_sha256":"f6d6fb87b005b0a155e24ae93c7550640bfdaa221063af034c3d3e20b46cc6b6","mirror_size_bytes":5089,"module_id":"S2_20-ASSET-FCA7B87C74F0BB44","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/c26_rule_branch_bind.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f6d6fb87b005b0a155e24ae93c7550640bfdaa221063af034c3d3e20b46cc6b6","size_bytes":5089},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c27_query_plan.txt","mirror_sha256":"d7fe404438e185b2e0351b8b5ac8fc7bd911a63544e71c7c16ffb313dc566777","mirror_size_bytes":6553,"module_id":"S2_20-ASSET-1327E50515C73062","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/c27_query_plan.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"d7fe404438e185b2e0351b8b5ac8fc7bd911a63544e71c7c16ffb313dc566777","size_bytes":6553},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c28_weaviate_retrieve.txt","mirror_sha256":"9634c80dd1b77ab652185ef5bd2b67ccbb7d355d2b4661f67d86fa78d0ee6395","mirror_size_bytes":12083,"module_id":"S2_20-ASSET-4AE83266D12B501B","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/c28_weaviate_retrieve.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9634c80dd1b77ab652185ef5bd2b67ccbb7d355d2b4661f67d86fa78d0ee6395","size_bytes":12083},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c29_pack_verify.txt","mirror_sha256":"4318f95c9c38391a455613b7411cee923288d19748f3c0946e86c588be718b9d","mirror_size_bytes":5721,"module_id":"S2_20-ASSET-0A121BEB45A15E4D","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/c29_pack_verify.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"4318f95c9c38391a455613b7411cee923288d19748f3c0946e86c588be718b9d","size_bytes":5721},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/calculators/registry_engine.txt","mirror_sha256":"173da5185caa6d4a82a7735018c9121ef42481cad8d83b9574c9f432912c556d","mirror_size_bytes":11417,"module_id":"S2_20-ASSET-FE154EB4E8F19440","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_20_owner","path":"runtime/calculators/registry_engine.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"173da5185caa6d4a82a7735018c9121ef42481cad8d83b9574c9f432912c556d","size_bytes":11417},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-E82839694073D431","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_20_owner","path":"schemas/binding_retrieval.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"25df409822a45fd26d0c5cf46e4afb55af100765c86afa148046354b2f02c8dc","size_bytes":47811},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-C9FC917D8CBF920E","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_20_owner","path":"schemas/calculation.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"7036793fe6c8d3550ca22486c281b1ffdbb915995dbe17c92d98a3f9a8f194ce","size_bytes":33698},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-5D843BA99044953C","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_20_owner","path":"schemas/domain_verdict.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5fec56a0661e2ab2351d92939c4fbdedc8ac4c7e8699dc92caae7dd359c7eb16","size_bytes":1262},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-FF1F03B3FC56E579","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_20_owner","path":"schemas/relief_plan.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ef5d271e981390421fa7a188c01e52b390ab138bfc32203056f59d7ab6dfc8f2","size_bytes":31558},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-9A06594587743420","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/actio_route_cap_matrix.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f922b3ec10cc1da44c62d6ca5cf9c8ec5a53f5328b1eaabf236db46448907ca8","size_bytes":572},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-3ECDA3121E0AE910","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/calculation_temporal_boundaries.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"a31af03c418466b1dfc05f47ea05b58109fe142b813da2b3a8863e9d5f71004d","size_bytes":1612},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-5EB4DEF644C02B9D","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/case_type_rule_binding_matrix.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"45e0f7470e2907d20d6359d192fe8320051bf8a278f8eaa8153fbe964819685c","size_bytes":1042},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-60AF7FED54CBA5C1","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/case_type_zero_multi_hash_mutations.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0fbe5f68f4e60dfdd4fd03b9f6f076526f1b3d273b328ec853e69b4f9c315180","size_bytes":1123},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-49D464EEB3D65FFB","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/minimal_supported_portfolio.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"4bcbcf19019e086e4eb4772cb55e87832c3a68c4829f67d50c6a7318dda79c86","size_bytes":733},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-97F26683DEAEA7F7","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/mixed_option_dispositions.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"509f3f436c8107c03033324413560b706487279bf91f2e231bd43bbc5c86b8e0","size_bytes":1457},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-8A3BBD97738BC0BF","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/plan_publish_barrier_failure.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"29afbbdfa609234b06473542c35df7083ca6313155456cc6d1ec311fd50ea275","size_bytes":1640},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-47A96BFDC0754003","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/regression_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"2a1a163d62a041990d71feaef54f3c56753ea3aa02666d3dc4c631552f7ee746","size_bytes":15014},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-B42FA1C2AD23D1BA","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/fixtures/s2_20/retrieval_replay_injection.json","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"8fbed161a30d52d8f5018f238dbf2cd01e0dd84162c97e3293df62d82a7ca804","size_bytes":1338},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_agent_and_inline_parity.txt","mirror_sha256":"0f73c112b28088be191b6717cb24cac468762cc286f8dc806bf65d98a95bf262","mirror_size_bytes":2773,"module_id":"S2_20-ASSET-E1B1709F62DB7D8A","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_agent_and_inline_parity.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0f73c112b28088be191b6717cb24cac468762cc286f8dc806bf65d98a95bf262","size_bytes":2773},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_calculation_and_reports.txt","mirror_sha256":"c1bd36c351173d25e6d8e68d1a90d738b90aabb51b201ca13f4370654e584e00","mirror_size_bytes":3199,"module_id":"S2_20-ASSET-1D1B579AA031EC90","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_calculation_and_reports.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"c1bd36c351173d25e6d8e68d1a90d738b90aabb51b201ca13f4370654e584e00","size_bytes":3199},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_inline_output_schema.txt","mirror_sha256":"e2cb938dd639874a4b150997d66eacd89b22016c8fd3385a243edf781cd3e85b","mirror_size_bytes":43574,"module_id":"S2_20-ASSET-22C24679226830D0","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_inline_output_schema.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e2cb938dd639874a4b150997d66eacd89b22016c8fd3385a243edf781cd3e85b","size_bytes":43574},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_offline_compilers.txt","mirror_sha256":"5e75f659a9e5add1345f1596c92c0b143cb1e48110c746a8785fb5b38f1371af","mirror_size_bytes":20252,"module_id":"S2_20-ASSET-6FFF0ED2C88404C2","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_offline_compilers.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5e75f659a9e5add1345f1596c92c0b143cb1e48110c746a8785fb5b38f1371af","size_bytes":20252},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_option_group_and_binding.txt","mirror_sha256":"6021d93fb47377cf6c00ccb5a880a7e85987ec5a1ed7976a84baca2d7fb39985","mirror_size_bytes":6171,"module_id":"S2_20-ASSET-E56589B5CCA0246C","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_option_group_and_binding.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6021d93fb47377cf6c00ccb5a880a7e85987ec5a1ed7976a84baca2d7fb39985","size_bytes":6171},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_plan_publish_and_release.txt","mirror_sha256":"ce0dc52cca2c6744be1051346ebecabac8c4ccbd97d697f7645eadd35aebd1e8","mirror_size_bytes":13950,"module_id":"S2_20-ASSET-2868A4B922737A76","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_plan_publish_and_release.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ce0dc52cca2c6744be1051346ebecabac8c4ccbd97d697f7645eadd35aebd1e8","size_bytes":13950},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_regression_manifest_closure.txt","mirror_sha256":"01ac49ab1ba79f158da9da78313407e3a67a95cf539113c617701a74c29b463f","mirror_size_bytes":10028,"module_id":"S2_20-ASSET-0C03601E14F2D714","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_regression_manifest_closure.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"01ac49ab1ba79f158da9da78313407e3a67a95cf539113c617701a74c29b463f","size_bytes":10028},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_20/test_retrieval_and_pack.txt","mirror_sha256":"c314cf27511b0fe065b8961196084a28b1c7c5cb2fed3dd5c8765172ba40462f","mirror_size_bytes":6654,"module_id":"S2_20-ASSET-A24AC597CB6DF548","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_20_owner","path":"tests/s2_20/test_retrieval_and_pack.py","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"c314cf27511b0fe065b8961196084a28b1c7c5cb2fed3dd5c8765172ba40462f","size_bytes":6654},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-CAB87BA40B475A9D","module_kind":"S2_20_ASSET","outputs":[],"owner":"Stage_2_S2_20_owner","path":"validators/actio_value_compensation_invariants.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"591182a8869f3c0c0e03e9b32f5f0d9b856361b3f5f77f1e6e87eb0188f1ef22","size_bytes":983},{"asset_version":"s2_20.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_20-ASSET-AA40CF5140DE8790","module_kind":"WORKFLOW","outputs":[],"owner":"Stage_2_S2_20_owner","path":"workflows/S2_20_canonical_relief_plan_reduce.yml","produced_schema_ids":[],"schema_version":"stage2_s2_20_generic_asset.v1","scope_predicate":"workflow_id == S2_20","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"da56152af502fe432cb2ebaa593a4e389b7f2cd4d0b8f3be29e49717cff0544a","size_bytes":2443},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-871DF298A294D7DC","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"manifest/s2_30_parent_member_paths.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e4b734e354f4184dabe5984ed419f64636fc8a8daef12f6542ff960b2c7ab749","size_bytes":1603},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_s2_30_agent_projection.txt","mirror_sha256":"665b6f00bae567ea67e3758be047f594fedae2c22a5047b30009fcd5d2c495b2","mirror_size_bytes":56585,"module_id":"S2_30-ASSET-66EF7EC35105D464","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_30_owner","path":"offline_build/build_s2_30_agent_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"665b6f00bae567ea67e3758be047f594fedae2c22a5047b30009fcd5d2c495b2","size_bytes":56585},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/validate_s2_30_contract.txt","mirror_sha256":"14e4eefb73d40d004c95017c82cdc23ac1c1c0a54ea34562dcf322f6364ae27a","mirror_size_bytes":104292,"module_id":"S2_30-ASSET-7E89202630AA3B4A","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_30_owner","path":"offline_build/validate_s2_30_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"14e4eefb73d40d004c95017c82cdc23ac1c1c0a54ea34562dcf322f6364ae27a","size_bytes":104292},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-E83A5821C44AAF21","module_kind":"S2_30_ASSET","outputs":[],"owner":"Stage_2_S2_30_owner","path":"prompts/P30_joint_drafting_contract.md","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5d790fccdacd1b7ce27e25cd52e4c301dbce24ba276def18bca608b5b16362aa","size_bytes":13681},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-6A9B1F5EC854740E","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_30_owner","path":"schemas/draft_atoms.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5107b64f01ffb3633a829c10652747760a5035c9cc07227c546e3f543005eda9","size_bytes":68470},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-546763E72E7A932F","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/adverse_fact_worknote_policy.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5b8e9101385f8d65b0332c3be63cb9a22063920675cc86aee51e04da7820aef7","size_bytes":3444},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-47ECD04400C72037","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/cache_prefix_drift.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"845b44cfeb1246f16cd3458965683247efc360b166b31133e3286be400325f98","size_bytes":2109},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-9C7A8A9DC09BB101","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/context_reference_envelope.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"a1d6ba9752b9d4fb479dfaaa763174988f38d87890db9487db9de556d3eade60","size_bytes":4804},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-0DA94639658F5DB2","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/counter_performance_and_declaration.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"cfa3a8439ca938b05768798dfee39a3cc1e4980d5550526c787843622516da90","size_bytes":3322},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-CA60AEE03DF32752","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/follower_batch_dispatch.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"3dffaf9862e15f2fe906ca63abb3be61e49177fb58abb4c4a7a8b25db4e4493b","size_bytes":2832},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-18231E85556C3220","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/invalid_forbidden_output.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"a2308629fc09f75ab226b89374c78323f62a9dbe296aebdd83170a0cfb926e09","size_bytes":2741},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-8265AF415D892AB3","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/invalid_preassembled_prompt_item.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"6655402c669e5b40f2e7028a5c0c89571d8e1597dbdef567b4c9d8e2eed15a79","size_bytes":2204},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-A7A8934E5BF55C76","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/invalid_reference_output.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"eb2982a09f4948baadc27ae49c4f125426074333ea4a626e9c56ddc5c24ce273","size_bytes":2663},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-D8A8B0F06569C1F0","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/owner_singleton_dispatch.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"38f9c364591fcdfe60d0dea9f69eb86b2f3b883929f6d60d06a7c35ff376fca6","size_bytes":8448},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-7D7984D0B44475DA","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/partial_write_publish_barrier.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0d878b946ebf810e8d0d8da74af33e56f35e164b04076a3867344b95d5f953eb","size_bytes":3352},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-B1A866CA34AFBC11","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/regression_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"43e5b20ef4389da9c03b8062ce8bfacf2cd880d2efa2a1cbe1e901f4111f64ea","size_bytes":3584},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-E696214E5807E29A","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/rule_requirement_admission_gap.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"27dfad63f3508c5d40521270707d84b2bc0c58f035f47d0cde1ae2abc54f9a15","size_bytes":4298},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-C8F5D82811189C0F","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/technical_failure.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"bdcc6410e7515edc73d6b154d5b618b3ec34273ddc7269dc3e3ce55a6eb35fa6","size_bytes":2719},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-77E545820FEC15EC","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/valid_joint_draft_output.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"0135616c9375602693af8e12c3c16cf2031eaf3d9b74783bec9b5065846327e8","size_bytes":12982},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_30/test_agent_contract.txt","mirror_sha256":"26a37b0b5fa6c4273ed7deff6b0429e3223869533fc2384f4c364fe88d554da5","mirror_size_bytes":12199,"module_id":"S2_30-ASSET-97349E7C166EE517","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/s2_30/test_agent_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"26a37b0b5fa6c4273ed7deff6b0429e3223869533fc2384f4c364fe88d554da5","size_bytes":12199},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_30/test_dispatch_materialization.txt","mirror_sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","mirror_size_bytes":13911,"module_id":"S2_30-ASSET-748AB3E90AD4378F","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/s2_30/test_dispatch_materialization.py","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","size_bytes":13911},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_30/test_draft_atom_contract.txt","mirror_sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","mirror_size_bytes":10484,"module_id":"S2_30-ASSET-5165C83A0FB3CDEE","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/s2_30/test_draft_atom_contract.py","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","size_bytes":10484},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_30/test_prompt_cache_and_boundaries.txt","mirror_sha256":"1b9b562418bc24be6db09dc1d35f71845033adbc693aeb41fbba07be16fa7c9d","mirror_size_bytes":6284,"module_id":"S2_30-ASSET-30A7574DB26A7700","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/s2_30/test_prompt_cache_and_boundaries.py","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"1b9b562418bc24be6db09dc1d35f71845033adbc693aeb41fbba07be16fa7c9d","size_bytes":6284},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_30/test_release_adapter_retry.txt","mirror_sha256":"e5af75d54f236eb8ba99b194a06aa31f02fddd5c6aa9ff7385401905359b292c","mirror_size_bytes":18566,"module_id":"S2_30-ASSET-A9BE2C9D380E8C50","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/s2_30/test_release_adapter_retry.py","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e5af75d54f236eb8ba99b194a06aa31f02fddd5c6aa9ff7385401905359b292c","size_bytes":18566},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-E1FCF8BD63300F4D","module_kind":"WORKFLOW","outputs":[],"owner":"Stage_2_S2_30_owner","path":"workflows/S2_30_claim_group_draft_map.yml","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"b266e7b7ae8939b087bfdb7b34fff8b9c6011c835560ab690991d856ced0cc15","size_bytes":15221},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-710AE87909AE0663","module_kind":"MANIFEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"manifest/s2_40_parent_member_paths.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"3ab6c0398f16d53542c115f2efa164f5ccfd1e64bf457b914a589c61321e8121","size_bytes":2257},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"offline_build/build_s2_40_inline_projection.txt","mirror_sha256":"c6dee2c30d4b23fa3e6aaf2cded4f933dae6e642c71eeff8534c4e53a12bdfe0","mirror_size_bytes":36098,"module_id":"S2_40-ASSET-1CF70696C9F630A8","module_kind":"BUILD_ONLY","outputs":[],"owner":"Stage_2_S2_40_owner","path":"offline_build/build_s2_40_inline_projection.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"c6dee2c30d4b23fa3e6aaf2cded4f933dae6e642c71eeff8534c4e53a12bdfe0","size_bytes":36098},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/c45_document_assembler.txt","mirror_sha256":"93135e69189a335f34be7c383cef2b5ca9f12ea899266b0d8ecc4bd85237647e","mirror_size_bytes":11992,"module_id":"S2_40-ASSET-5B0EE99ECD2C0599","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_40_owner","path":"runtime/c45_document_assembler.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"93135e69189a335f34be7c383cef2b5ca9f12ea899266b0d8ecc4bd85237647e","size_bytes":11992},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/rendering/closed_renderer.txt","mirror_sha256":"21acbee2e5456de2b647b5c235c4e8293b77a864af9bc365c75c8346d34070cd","mirror_size_bytes":10559,"module_id":"S2_40-ASSET-0B59F323E4EACA18","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_40_owner","path":"runtime/rendering/closed_renderer.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"21acbee2e5456de2b647b5c235c4e8293b77a864af9bc365c75c8346d34070cd","size_bytes":10559},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"runtime/validation/invariant_runner.txt","mirror_sha256":"67d2ff35d66079fa7fe5e8f312f18ed68b16da5eb4f9f85780d11bd45b54009c","mirror_size_bytes":30951,"module_id":"S2_40-ASSET-8217116B75E9550A","module_kind":"RUNTIME_CORE","outputs":[],"owner":"Stage_2_S2_40_owner","path":"runtime/validation/invariant_runner.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"67d2ff35d66079fa7fe5e8f312f18ed68b16da5eb4f9f85780d11bd45b54009c","size_bytes":30951},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-66B24FF9775426E0","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_40_owner","path":"schemas/migration_regression.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"775a186df990e3704391876926540da911d64c56f76b0bee6c0b97c6cdb38e58","size_bytes":4610},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-5C4CAFFAB8D2F982","module_kind":"JSON_SCHEMA","outputs":[],"owner":"Stage_2_S2_40_owner","path":"schemas/package.schema.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"c1cdf59d7273715276e38fe227c5dad5d7b825cc522118ff6ab2d1b3a342dd3c","size_bytes":19691},{"asset_version":"s2_30.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_30-ASSET-F261637CB908A41C","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_30_owner","path":"tests/fixtures/s2_30/persisted_handoff_chain.json","produced_schema_ids":[],"schema_version":"stage2_s2_30_generic_asset.v1","scope_predicate":"workflow_id == S2_30","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"54d6d781a60640744cba4b9c2f88a0013a6e58656c9c80a809e39fd4ba7c1097","size_bytes":2016},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-19CB23FB1E5F99DE","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/candidate_digest_noncycle.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"74885602909bd19ca1678de781cac26afd34c2f386e98fc0370fd6ff6fb7b8bf","size_bytes":798},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-9E10C878E97D6636","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/cost_provisional_execution_numbering.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"17c380492f5bc56ecf675cf9683784b2e463241c7d0589b7b496e7a381145c9b","size_bytes":2143},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-D73DC5121366E2DE","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/exhibit_object_party_title_completeness.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"40045822f45b2a57805504744e751ee420a6187d0790d5a0f442f529ffedcf7e","size_bytes":692},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-71BEFE2BDE251773","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/part_set_missing_duplicate_or_cross_group.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"379273497ee23d4a515135771ba4d3bb5ff0e38325ad40eb4e0a0008cd6b88f4","size_bytes":785},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-C245AA392434948E","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/partial_write_readback_barrier.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"467387c12a4cc6469d243de9f0a7948276adb558a99b3b661ccd74a5d17629cf","size_bytes":652},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-B77178D146E18FE6","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/regression_manifest.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"ac5d68c8d4061d789aa5c773cd1ffb37728c33c7725785a9dd1f4bea63ec88ce","size_bytes":7030},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-724CEBB85D0021D4","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/relief_cause_crossmatch_mutations.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e8d148fef61920039e36abd0cfb771cc6e2fe3aa1a9cc0b0b0502c38ddf70567","size_bytes":761},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-D8B6C423CA8B8343","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/renderer_ast_slot_branch_mutations.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e70ecac4e71de962dfe8bb025a42c73c7c03cfba32c29319523d19f49e8260d0","size_bytes":1800},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-ED81C6D9C14D5A6A","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/review_policy_state_aggregation.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"953fc301703ff353de4df3cf46ed4e90b6bf4ce8268b08705e16151ffc8c3a21","size_bytes":581},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-88DA222DF4B4AC40","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/review_receipt_approve_resume.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"c5b84e34358761750e8e9e7666de6532e0f22a31f32bf027f24efb256a1af5d5","size_bytes":983},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-45C755C76F2E9040","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/review_receipt_content_change_supersede.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"400d4aeb455e5c3ec26c75a552ea91e9af79cb2329998caa1ad72d1be18da8e7","size_bytes":627},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-60A3C7B6370B71D7","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/review_receipt_missing_or_invalid.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"a88645be90a9e0943358d83f7ea105193dd4b4dfebea4519702a17f69615dc65","size_bytes":688},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-010B031F043CFB13","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/same_binding_idempotence_and_commit_conflict.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5536793236fa44da601dc8cf65d94dac32b18ebc2e8dc525a6df92106add57ad","size_bytes":674},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-1FD9A637BC46671D","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/v01_v18_invariant_matrix.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e4c0a5476647fa1860cd685a15aad6d465a36b4f6b648c8e2a066c8747780eb8","size_bytes":9096},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-CDB97542A2A4F866","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/valid_full_candidate_and_commit.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"e98e8dc55ab60f8f875ad2f58c1aec35eb1da3882371c22c3e232e0e9ae46c2f","size_bytes":1221},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"module_id":"S2_40-ASSET-01E38009C9220C87","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/fixtures/s2_40/valid_status_only_diagnostic.json","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"5676088f5d79168cbae5e1481da4b7cfd9241d06c935378e06dd2af56aae6285","size_bytes":724},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_40/test_agent_and_inline_parity.txt","mirror_sha256":"04cc4a14790eceea6ec8a9331212ca6e767ef96994b5b26483392d23145417ae","mirror_size_bytes":32947,"module_id":"S2_40-ASSET-A6B20D5A9A6882F5","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/s2_40/test_agent_and_inline_parity.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"04cc4a14790eceea6ec8a9331212ca6e767ef96994b5b26483392d23145417ae","size_bytes":32947},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_40/test_c40_reduce_and_conservation.txt","mirror_sha256":"f610eced056420277c67294cdfe76d559073d88a6f42d3e8c5dae8f219fa82d9","mirror_size_bytes":3032,"module_id":"S2_40-ASSET-46C37B9570DE79C8","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/s2_40/test_c40_reduce_and_conservation.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f610eced056420277c67294cdfe76d559073d88a6f42d3e8c5dae8f219fa82d9","size_bytes":3032},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_40/test_c45_closed_render.txt","mirror_sha256":"b7cad96735b1a0158644f41703b4f279fdd8b6bc68438f0d7d773b8415ebb460","mirror_size_bytes":7855,"module_id":"S2_40-ASSET-A2E1E4DAA289FE95","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/s2_40/test_c45_closed_render.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"b7cad96735b1a0158644f41703b4f279fdd8b6bc68438f0d7d773b8415ebb460","size_bytes":7855},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_40/test_commit_barrier_and_idempotence.txt","mirror_sha256":"714e2f05397d5dcc31159739363f11c9bbaf5a091de55b465e0b474c21f90ea0","mirror_size_bytes":8228,"module_id":"S2_40-ASSET-6CFF5B81DB1AE376","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/s2_40/test_commit_barrier_and_idempotence.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"714e2f05397d5dcc31159739363f11c9bbaf5a091de55b465e0b474c21f90ea0","size_bytes":8228},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_40/test_release_closure.txt","mirror_sha256":"89139e0286facd52c3ce91a1c7b382a584dfc3e6bc337fcb55fbc8eed59f5933","mirror_size_bytes":12692,"module_id":"S2_40-ASSET-3309DF833726005D","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/s2_40/test_release_closure.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"89139e0286facd52c3ce91a1c7b382a584dfc3e6bc337fcb55fbc8eed59f5933","size_bytes":12692},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_40/test_review_state_machine.txt","mirror_sha256":"f4dab9bb651b4a3c818c73162b972c8ac3df0f50fbe056e392a12673139b9b4a","mirror_size_bytes":8373,"module_id":"S2_40-ASSET-EDD6AFC9610DFC1B","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/s2_40/test_review_state_machine.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"f4dab9bb651b4a3c818c73162b972c8ac3df0f50fbe056e392a12673139b9b4a","size_bytes":8373},{"asset_version":"s2_40.1","authority_ids":[],"consumed_schema_ids":[],"dependency_module_ids":[],"forbidden_contract_codes":["LEGACY-STAGE2-V0-V3"],"implementation_status":"DEV_HASH_BOUND_OFFLINE_ONLY","incompatible_module_ids":[],"inputs":[],"mirror_byte_parity":true,"mirror_path":"tests/s2_40/test_v01_v18.txt","mirror_sha256":"72be88be1aa9d495b5c9387e45b75e86f44ac76ffe15c04b5ba33ba21fa8943f","mirror_size_bytes":3853,"module_id":"S2_40-ASSET-A50D95FF51F9CA3C","module_kind":"TEST","outputs":[],"owner":"Stage_2_S2_40_owner","path":"tests/s2_40/test_v01_v18.py","produced_schema_ids":[],"schema_version":"stage2_s2_40_generic_asset.v1","scope_predicate":"workflow_id == S2_40","semantic_review_status":"PENDING_LEGAL_AND_LIVE_ADMISSION","sha256":"72be88be1aa9d495b5c9387e45b75e86f44ac76ffe15c04b5ba33ba21fa8943f","size_bytes":3853}],"producer_aliases":[{"alias_id":"PA-SG-COMPILER-001","bidirectional_match_allowed":true,"contract_status":"CLOSED_DECISION_FIXTURE_PENDING","global_alias_allowed":false,"orchestration_producer_id":"Task_C_BO_S0_signal_bundle_writer","schema_writer_id":"Task_C_BO_S0_canonical_signal_compiler","scope":"STAGE1_PART2_SIGNAL_TRANSACTION_ONLY"}],"schema_version":"stage2_module_manifest.v1"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_00_inline_code_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_00_inline_code_receipt.json index f4486b98..626a3493 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_00_inline_code_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_00_inline_code_receipt.json @@ -1 +1 @@ -{"authoring":{"path":"Stage_2_S2_00_v.2.yml","sha256":"8d9583ce7b039ef848abfcbcdb27ac50a2e8a4e279a745b4779bcd90fc17cf64","size_bytes":367573,"unique_key_parse":"PASS"},"authoring_rewritten":false,"build_kind":"OFFLINE_AUTHORING_PROJECTION","canonical_code":{"ast_status":"PASS","code_sha256":"612bf08c26a2b96c827a774d79789a9902ffbf18fdd181a157dae40e25b5f8ca","code_size_bytes":283196,"compile_status":"PASS","encoding":"UTF-8","external_python_source_ref_count":0,"external_url_count":0,"extraction_transform":"NONE","forbidden_dynamic_call_count":0,"forbidden_import_count":0,"imports":["__future__","argparse","base64","binascii","collections","contextlib","dataclasses","hashlib","httpx","io","itertools","json","math","os","pathlib","re","shutil","stat","sys","tempfile","typing","unicodedata"],"placeholder_count":0,"plaintext_secret_count":0,"yaml_pointer":"/Agent/Stages/0/tasks/0/parameters/code"},"deployment_projection":{"byte_identical_to_authoring":true,"canonical_task_semantics_sha256":"0ae62c60183e0cffbef198d8efce4a0fcbcaddef223133075b19ee19c50ea65d","path":"Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml","sha256":"8d9583ce7b039ef848abfcbcdb27ac50a2e8a4e279a745b4779bcd90fc17cf64","size_bytes":367573},"full_code_mirrors":[{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.py","sha256":"612bf08c26a2b96c827a774d79789a9902ffbf18fdd181a157dae40e25b5f8ca","size_bytes":283196},{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.txt","sha256":"612bf08c26a2b96c827a774d79789a9902ffbf18fdd181a157dae40e25b5f8ca","size_bytes":283196}],"parity_status":"PASS","schema_version":"stage2_s2_00_inline_code_receipt.v2","source_of_truth":"Stage_2_S2_00_v.2.yml","task_contract":{"agent":{"name":"Stage_2_S2_00_v2","version":"1.2.0"},"mcp_servers":{"code-executor":{"type":"streamable-http","url":"https://code-executor.mcp.eroomai.com/mcp"},"localdocs":{"type":"streamable-http","url":"http://mcp-localdocs:8012/mcp"}},"stage":{"name":"S2_00","nexts":[],"prevs":[]},"task":{"code_sha256":"612bf08c26a2b96c827a774d79789a9902ffbf18fdd181a157dae40e25b5f8ca","mcp":"code-executor","parameters":{"language":"python","network":"agent-network","requirements":"httpx==0.28.1","timeout":300},"task_name":"Task_S2_00_deterministic_ingress","tool_name":"run_code"},"task_procedure":{"IN":{"nexts":["Task_S2_00_deterministic_ingress"],"wait_until":[]},"OUT":{"nexts":[],"wait_until":["Task_S2_00_deterministic_ingress"]},"Task_S2_00_deterministic_ingress":{"nexts":["OUT"],"wait_until":["IN"]}}},"workflow_id":"S2_00"} +{"authoring":{"path":"Stage_2_S2_00_v.2.yml","sha256":"94c2744d71d222cfb5cc1b2a0d33a6cda20079439823de431eef378a2fa5c943","size_bytes":367573,"unique_key_parse":"PASS"},"authoring_rewritten":false,"build_kind":"OFFLINE_AUTHORING_PROJECTION","canonical_code":{"ast_status":"PASS","code_sha256":"e3f87725d5a6496189e7c411ef940dd8a7b3a9ff5b00535803bf98fa0cc4373e","code_size_bytes":283196,"compile_status":"PASS","encoding":"UTF-8","external_python_source_ref_count":0,"external_url_count":0,"extraction_transform":"NONE","forbidden_dynamic_call_count":0,"forbidden_import_count":0,"imports":["__future__","argparse","base64","binascii","collections","contextlib","dataclasses","hashlib","httpx","io","itertools","json","math","os","pathlib","re","shutil","stat","sys","tempfile","typing","unicodedata"],"placeholder_count":0,"plaintext_secret_count":0,"yaml_pointer":"/Agent/Stages/0/tasks/0/parameters/code"},"deployment_projection":{"byte_identical_to_authoring":true,"canonical_task_semantics_sha256":"a970635aa19b4ebca03819e30de32bb69f33ca455f7ecd6257a45636565b4e95","path":"Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_00.yml","sha256":"94c2744d71d222cfb5cc1b2a0d33a6cda20079439823de431eef378a2fa5c943","size_bytes":367573},"full_code_mirrors":[{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.py","sha256":"e3f87725d5a6496189e7c411ef940dd8a7b3a9ff5b00535803bf98fa0cc4373e","size_bytes":283196},{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.txt","sha256":"e3f87725d5a6496189e7c411ef940dd8a7b3a9ff5b00535803bf98fa0cc4373e","size_bytes":283196}],"parity_status":"PASS","schema_version":"stage2_s2_00_inline_code_receipt.v2","source_of_truth":"Stage_2_S2_00_v.2.yml","task_contract":{"agent":{"name":"Stage_2_S2_00_v2","version":"1.2.0"},"mcp_servers":{"code-executor":{"type":"streamable-http","url":"https://code-executor.mcp.eroomai.com/mcp"},"localdocs":{"type":"streamable-http","url":"http://mcp-localdocs:8012/mcp"}},"stage":{"name":"S2_00","nexts":[],"prevs":[]},"task":{"code_sha256":"e3f87725d5a6496189e7c411ef940dd8a7b3a9ff5b00535803bf98fa0cc4373e","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"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_agent_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_agent_receipt.json index 3b18b81a..8b4a26fa 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_agent_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_agent_receipt.json @@ -1 +1 @@ -{"agent_contract":{"agent_name":"Stage_2_S2_10","agent_version":"1.1.0","deterministic_task_count":0,"inline_common_prompt_sha256":"a90ac95f0b24ea938a16699f34ef7f17eb870edcbd8964ba4f6709e36e1bbcc0","inline_static_prompt_sha256":"894c30bedaa5f230aed117e81ef4cc06cac832928a1e29cd3ee8804cfd4dba1f","item_tokens":["{{item.selected_legal_context_json}}","{{item.cluster_case_payload_json}}"],"llm_task_count":1,"prompt_roles":["system","system","system","user"],"reduce_task_count":0,"stage_name":"S2_10","task_name":"Task_S2_10_resolve_cluster","tool_task_count":0},"authoring":{"path":"Stage_2_S2_10_v.1.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},"binding":{"path":"deployment/stage2_s2_10_llm_binding.yml","sha256":"9d20b264e753c2f52e8d096edab363ace0fecf2ec8357605d1a9cb47c9c2b930"},"child_release":{"path":"manifest/s2_10_release.json","release_digest":"262579cc93e89d1a90cd928bf24f21e820022226493ad0a05ae4dc44bef7debd","sha256":"73cf98c94117db12f04c298e5758431d5006c7a9ddb8dd46ff2e7b19313bdb9c"},"deployment":{"byte_parity":"PASS","path":"agent_scripts/Stage_2_S2_10.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},"external_admission_status":"PENDING","inline_prompt_receipt":{"path":"manifest/s2_10_inline_prompt_projection_receipt.json","sha256":"7f64a192e7edda7c0e4025b9f1995dcd21c38aba15a018d232f9f05bcba35863","size_bytes":2659},"receipt_digest":"32f7ba8b4fbe0502f9a44c6f13059ce2aba9855bb350c72ca22ba936cb552b60","receipt_status":"OFFLINE_AGENT_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","schema":{"path":"schemas/s2_10.schema.json","sha256":"5233afde9ddb3c5868b9101816e8b3830a90b1399e3e5e89d9d7c7bf5beacaee","size_bytes":82703},"schema_version":"stage2_s2_10_agent_receipt.v2","workflow":{"path":"workflows/S2_10_domain_relief_resolution_map.yml","sha256":"f0fba48f1760cf4e233d7d698fd19090f96ffb89cabe4b2e2cae9af7c616be0f","size_bytes":15320}} +{"agent_contract":{"agent_name":"Stage_2_S2_10","agent_version":"1.1.0","deterministic_task_count":0,"inline_common_prompt_sha256":"a90ac95f0b24ea938a16699f34ef7f17eb870edcbd8964ba4f6709e36e1bbcc0","inline_static_prompt_sha256":"894c30bedaa5f230aed117e81ef4cc06cac832928a1e29cd3ee8804cfd4dba1f","item_tokens":["{{item.selected_legal_context_json}}","{{item.cluster_case_payload_json}}"],"llm_task_count":1,"prompt_roles":["system","system","system","user"],"reduce_task_count":0,"stage_name":"S2_10","task_name":"Task_S2_10_resolve_cluster","tool_task_count":0},"authoring":{"path":"Stage_2_S2_10_v.1.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},"binding":{"path":"deployment/stage2_s2_10_llm_binding.yml","sha256":"9b5d69f1316a0b9fba7b41097ee92142cf42485c8deb0be876d9e9329c317a04"},"child_release":{"path":"manifest/s2_10_release.json","release_digest":"8cfc30a40ad53b35fb44c56e3c53f86605f777622399a4b1dcd0b2082eb6e197","sha256":"cb49a4501116e46d935933b739b6679b11d961ff8e36abefea35dab6b25508fb"},"deployment":{"byte_parity":"PASS","path":"agent_scripts/Stage_2_S2_10.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},"external_admission_status":"PENDING","inline_prompt_receipt":{"path":"manifest/s2_10_inline_prompt_projection_receipt.json","sha256":"b7fdef2ad05f251bdede9473d3b69c0f169ab7f4a059b393429ff76f739f703e","size_bytes":2659},"receipt_digest":"9bd92db101c0bf6f0c48764c71f5091e573dc65cce307ce3121b5d0271efc36c","receipt_status":"OFFLINE_AGENT_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","schema":{"path":"schemas/s2_10.schema.json","sha256":"5233afde9ddb3c5868b9101816e8b3830a90b1399e3e5e89d9d7c7bf5beacaee","size_bytes":82703},"schema_version":"stage2_s2_10_agent_receipt.v2","workflow":{"path":"workflows/S2_10_domain_relief_resolution_map.yml","sha256":"f0fba48f1760cf4e233d7d698fd19090f96ffb89cabe4b2e2cae9af7c616be0f","size_bytes":15320}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_inline_prompt_projection_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_inline_prompt_projection_receipt.json index 5d34595a..bfdae72c 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_inline_prompt_projection_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_inline_prompt_projection_receipt.json @@ -1 +1 @@ -{"authoring_agent":{"path":"Stage_2_S2_10_v.1.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},"builder":{"path":"offline_build/build_s2_10_agent_projection.py","sha256":"4359364816c8a58eb414bafae8ccf24fc3766dc611d15f1aa09e48c8fedc8f88","size_bytes":61930},"canonicalization_algorithm_id":"S2_10-NFC-LF-RTRIM-CLAUSE-PROJECTION-V1","deployment_agent":{"byte_parity":"PASS","path":"agent_scripts/Stage_2_S2_10.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},"inline_scalars":[{"raw_scalar_sha256":"a90ac95f0b24ea938a16699f34ef7f17eb870edcbd8964ba4f6709e36e1bbcc0","role":"system","size_bytes":7364,"wrapper":"stage_2_common_cache_prefix","yaml_pointer":"/Agent/Stages/0/map_reduce/map/tasks/0/prompts/0/content"},{"raw_scalar_sha256":"894c30bedaa5f230aed117e81ef4cc06cac832928a1e29cd3ee8804cfd4dba1f","role":"system","size_bytes":12261,"wrapper":"s2_10_legal_resolution_static_prompt","yaml_pointer":"/Agent/Stages/0/map_reduce/map/tasks/0/prompts/1/content"}],"message_order":["INLINE_COMMON_SYSTEM","INLINE_STATIC_LEGAL_SYSTEM","SELECTED_CONTEXT_SYSTEM_DATA","CLUSTER_CASE_USER_DATA"],"raw_scalar_hash_algorithm_id":"SHA256-UTF8-PARSED-YAML-SCALAR-V1","receipt_digest":"6c5e9504d5921ee552023d05bcd61ed9752c3ac02ab93f0b75ed360390b85313","receipt_status":"OFFLINE_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","schema_version":"stage2_s2_10_inline_prompt_projection_receipt.v1","source_projections":[{"inline_clause_projection_sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e","inline_wrapper":"stage_2_common_cache_prefix","parity":"PASS","source":{"path":"prompts/P00_system_and_safety_contract.md","sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e","size_bytes":7304},"source_clause_projection_sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e"},{"hybrid_supersession_required":true,"inline_clause_projection_sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","inline_wrapper":"s2_10_legal_resolution_static_prompt","parity":"PASS","source":{"path":"prompts/P10_legal_resolution_contract.md","sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","size_bytes":8712},"source_clause_projection_sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b"}],"validation":{"dynamic_item_tokens":["{{item.selected_legal_context_json}}","{{item.cluster_case_payload_json}}"],"normalized_clause_projection":"PASS","prompt_order":"PASS","static_item_token_count":0,"static_pii_scan":"PASS","wrapper_integrity":"PASS"}} +{"authoring_agent":{"path":"Stage_2_S2_10_v.1.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},"builder":{"path":"offline_build/build_s2_10_agent_projection.py","sha256":"efdde6d70c723e9386f2ba1828119af7e68f7956c29bd3ba05370242a70ab62d","size_bytes":68381},"canonicalization_algorithm_id":"S2_10-NFC-LF-RTRIM-CLAUSE-PROJECTION-V1","deployment_agent":{"byte_parity":"PASS","path":"agent_scripts/Stage_2_S2_10.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},"inline_scalars":[{"raw_scalar_sha256":"a90ac95f0b24ea938a16699f34ef7f17eb870edcbd8964ba4f6709e36e1bbcc0","role":"system","size_bytes":7364,"wrapper":"stage_2_common_cache_prefix","yaml_pointer":"/Agent/Stages/0/map_reduce/map/tasks/0/prompts/0/content"},{"raw_scalar_sha256":"894c30bedaa5f230aed117e81ef4cc06cac832928a1e29cd3ee8804cfd4dba1f","role":"system","size_bytes":12261,"wrapper":"s2_10_legal_resolution_static_prompt","yaml_pointer":"/Agent/Stages/0/map_reduce/map/tasks/0/prompts/1/content"}],"message_order":["INLINE_COMMON_SYSTEM","INLINE_STATIC_LEGAL_SYSTEM","SELECTED_CONTEXT_SYSTEM_DATA","CLUSTER_CASE_USER_DATA"],"raw_scalar_hash_algorithm_id":"SHA256-UTF8-PARSED-YAML-SCALAR-V1","receipt_digest":"096cedfb69f915cef492cc37b78f8605386a091c47da9b51c9a499859c2edb00","receipt_status":"OFFLINE_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","schema_version":"stage2_s2_10_inline_prompt_projection_receipt.v1","source_projections":[{"inline_clause_projection_sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e","inline_wrapper":"stage_2_common_cache_prefix","parity":"PASS","source":{"path":"prompts/P00_system_and_safety_contract.md","sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e","size_bytes":7304},"source_clause_projection_sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e"},{"hybrid_supersession_required":true,"inline_clause_projection_sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","inline_wrapper":"s2_10_legal_resolution_static_prompt","parity":"PASS","source":{"path":"prompts/P10_legal_resolution_contract.md","sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","size_bytes":8712},"source_clause_projection_sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b"}],"validation":{"dynamic_item_tokens":["{{item.selected_legal_context_json}}","{{item.cluster_case_payload_json}}"],"normalized_clause_projection":"PASS","prompt_order":"PASS","static_item_token_count":0,"static_pii_scan":"PASS","wrapper_integrity":"PASS"}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_legal_review_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_legal_review_receipt.json index 0b57c550..05aebd31 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_legal_review_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_legal_review_receipt.json @@ -1 +1 @@ -{"binding_sha256":"9d20b264e753c2f52e8d096edab363ace0fecf2ec8357605d1a9cb47c9c2b930","finding_ids":[],"inline_prompt_projection_sha256":"7f64a192e7edda7c0e4025b9f1995dcd21c38aba15a018d232f9f05bcba35863","receipt_digest":"ca74b98b8da5252ecb063f561d0aba62013d259a4c8cfe1fd1cf77401771f38a","review_id":"S2_10-HYBRID-LEGAL-REVIEW-PENDING","review_scope_digest":"b9396e8b25be70be35032de9f621f1ac9329a419f868f31619f5ae871a28f8e1","reviewer_role":"KOREAN_ATTORNEY","s2_10_release_sha256":"73cf98c94117db12f04c298e5758431d5006c7a9ddb8dd46ff2e7b19313bdb9c","schema_version":"stage2_s2_10_legal_review_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null,"status":"PENDING_KOREAN_LAWYER_REVIEW"} +{"binding_sha256":"9b5d69f1316a0b9fba7b41097ee92142cf42485c8deb0be876d9e9329c317a04","finding_ids":[],"inline_prompt_projection_sha256":"b7fdef2ad05f251bdede9473d3b69c0f169ab7f4a059b393429ff76f739f703e","receipt_digest":"18a29c299f5587993c17f5a40b1d2c60d03556e4b37306c23352d671c4dcbb7c","review_id":"S2_10-HYBRID-LEGAL-REVIEW-PENDING","review_scope_digest":"c8675e22ff50ba9599ab3ac3108f13718b412fc0de2425133f3f49981edf0735","reviewer_role":"KOREAN_ATTORNEY","s2_10_release_sha256":"cb49a4501116e46d935933b739b6679b11d961ff8e36abefea35dab6b25508fb","schema_version":"stage2_s2_10_legal_review_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null,"status":"PENDING_KOREAN_LAWYER_REVIEW"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_model_benchmark_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_model_benchmark_receipt.json index 08522774..b10e5b17 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_model_benchmark_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_model_benchmark_receipt.json @@ -1 +1 @@ -{"benchmark_id":"S2_10-HYBRID-MODEL-BENCHMARK-PENDING","binding_sha256":"9d20b264e753c2f52e8d096edab363ace0fecf2ec8357605d1a9cb47c9c2b930","cache_telemetry_observed":null,"endpoint":"responses","latency_p95_ms":null,"model":"gpt-5.6-sol","observed_fixture_refs":[],"reasoning_effort":"xhigh","receipt_digest":"ab4b1993b19b61d5de82756dfeb8eb0d853f50e09e7325624da5292c043149b8","s2_10_release_sha256":"73cf98c94117db12f04c298e5758431d5006c7a9ddb8dd46ff2e7b19313bdb9c","schema_pass_rate":null,"schema_version":"stage2_s2_10_model_benchmark_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null,"status":"PENDING_MODEL_BENCHMARK","usage_telemetry_observed":null,"verbosity":"medium"} +{"benchmark_id":"S2_10-HYBRID-MODEL-BENCHMARK-PENDING","binding_sha256":"9b5d69f1316a0b9fba7b41097ee92142cf42485c8deb0be876d9e9329c317a04","cache_telemetry_observed":null,"endpoint":"responses","latency_p95_ms":null,"model":"gpt-5.6-sol","observed_fixture_refs":[],"reasoning_effort":"xhigh","receipt_digest":"61f34770c1ebbc4c84c53ea925b07416b92f4baf4f1740294423eacbc17895ce","s2_10_release_sha256":"cb49a4501116e46d935933b739b6679b11d961ff8e36abefea35dab6b25508fb","schema_pass_rate":null,"schema_version":"stage2_s2_10_model_benchmark_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null,"status":"PENDING_MODEL_BENCHMARK","usage_telemetry_observed":null,"verbosity":"medium"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_platform_adapter_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_platform_adapter_receipt.json index b119727e..935724ea 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_platform_adapter_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_platform_adapter_receipt.json @@ -1 +1 @@ -{"adapter_contract_version":"S2_10_NATIVE_RESULT_ADAPTER_V2","binding_sha256":"9d20b264e753c2f52e8d096edab363ace0fecf2ec8357605d1a9cb47c9c2b930","capabilities":[{"activation_binding_ref":null,"capability_id":"HOST_ATOMIC_SINGLE_FLIGHT_CAS_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"AGENTBACKEND_MAP_SOURCE_ITEMS_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"AGENTBACKEND_NO_REDUCE_RESULT_ADAPTER_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_STRICT_SCHEMA_AND_REF_VALIDATOR_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_DETERMINISTIC_ID_AND_IMMUTABLE_PERSIST_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_ITEM_RETRY_CONTROLLER_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"}],"overall_status":"PENDING_EXTERNAL_PLATFORM_BINDING","parent_stage2_release_sha256":"579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81","receipt_digest":"d9d5aa86ba1f50a7ad6536c6907ab8faffee6f72a2f0f65f8422c8390a23c8d9","receipt_id":"S2_10-HYBRID-PLATFORM-ADAPTER-PENDING","s2_10_release_sha256":"73cf98c94117db12f04c298e5758431d5006c7a9ddb8dd46ff2e7b19313bdb9c","schema_version":"stage2_s2_10_platform_adapter_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null} +{"adapter_contract_version":"S2_10_NATIVE_RESULT_ADAPTER_V2","binding_sha256":"9b5d69f1316a0b9fba7b41097ee92142cf42485c8deb0be876d9e9329c317a04","capabilities":[{"activation_binding_ref":null,"capability_id":"HOST_ATOMIC_SINGLE_FLIGHT_CAS_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"AGENTBACKEND_MAP_SOURCE_ITEMS_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"AGENTBACKEND_NO_REDUCE_RESULT_ADAPTER_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_STRICT_SCHEMA_AND_REF_VALIDATOR_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_DETERMINISTIC_ID_AND_IMMUTABLE_PERSIST_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"activation_binding_ref":null,"capability_id":"S2_10_ITEM_RETRY_CONTROLLER_V1","failure_reason_codes":["PENDING_EXTERNAL_PLATFORM_BINDING"],"handler_digest":null,"handler_version":null,"implementation_ref":null,"live_evidence_refs":[],"status":"PENDING_EXTERNAL_PLATFORM_BINDING"}],"overall_status":"PENDING_EXTERNAL_PLATFORM_BINDING","parent_stage2_release_sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53","receipt_digest":"3c3a005c2ff658a53c37631e82e5dc536e038bd357cacaaefbd37453b2a99245","receipt_id":"S2_10-HYBRID-PLATFORM-ADAPTER-PENDING","s2_10_release_sha256":"cb49a4501116e46d935933b739b6679b11d961ff8e36abefea35dab6b25508fb","schema_version":"stage2_s2_10_platform_adapter_receipt.v2","signature_ref":null,"signed_at":null,"signed_by":null} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_release.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_release.json index f919a7ac..10d015a7 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_release.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_10_release.json @@ -1 +1 @@ -{"admission_status":{"legal_review":"PENDING_KOREAN_LAWYER_REVIEW","model_benchmark":"PENDING_MODEL_BENCHMARK","platform_adapter":"PENDING_EXTERNAL_PLATFORM_BINDING","production_execution":"BLOCKED","release_bound_canary":"SEPARATE_AUTHORIZATION_REQUIRED"},"authorization_status":"OFFLINE_VALIDATION_ONLY","constitution":{"deterministic_task_count":0,"dispatch_item_schema_version":"stage2_s2_10_dispatch_item.v2","llm_task_count":1,"prompt_contract_version":"S2_10_HYBRID_PROMPT_V1","raw_model_output_schema_version":"stage2_s2_10_model_output.v2","reduce_task_count":0,"runtime_python_asset_count":0,"tool_task_count":0},"external_admission_evidence":[{"path":"manifest/s2_10_platform_adapter_receipt.json","reason":"receipt attests this child release; reverse sealing would create a cycle","sealed_by_child_release":false},{"path":"manifest/s2_10_model_benchmark_receipt.json","reason":"generated only after a release-bound live canary","sealed_by_child_release":false},{"path":"manifest/s2_10_legal_review_receipt.json","reason":"generated only after release-bound Korean lawyer review","sealed_by_child_release":false}],"legacy_stage2_v0_v3_runtime_dependency_count":0,"model_binding":{"binding_status":"PENDING_MODEL_BENCHMARK","endpoint":"responses","model_id":"gpt-5.6-sol","provider":"openai","reasoning_effort":"xhigh","verbosity":"medium"},"parent_stage2_release_ref":{"declared_release_digest":"a2a1e2445b5d8e7baac20a616e6a182d5a6f0c16a791281eb177c59f5782eb20","declared_release_id":"STAGE2-CLEAN-DEV-DRAFT-S2_00-HYBRID-HANDOFF-2026-08-30","declared_release_status":"DRAFT_NOT_EXECUTABLE","path":"manifest/stage2_release.json","sha256":"579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81"},"producer_contract":{"material":{"algorithm_id":"S2_10-PRODUCER-CONTRACT-PROJECTION-V1","claim_option_id_mint_algorithm_id":"S2_10-CLAIM-OPTION-ID-V1","local_relation_rewrite_algorithm_id":"S2_10-TWO-PASS-LOCAL-REF-REWRITE-V1","native_adapter_capability_projection_sha256":"3f08caa2ad872802267fc333069ea2436a9f23ec3d312241d8ed26e3fbbf0525","raw_model_output_schema_closure_algorithm_id":"S2_10-RAW-MODEL-SCHEMA-CLOSURE-BY-FULL-FILE-SHA256-V1","raw_model_output_schema_projection_sha256":"5233afde9ddb3c5868b9101816e8b3830a90b1399e3e5e89d9d7c7bf5beacaee","strict_validator_algorithm_id":"S2_10-OFFLINE-NATIVE-ADAPTER-ORACLE-V2","strict_validator_sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b"},"s2_10_producer_contract_digest":"950da7b30a9799ad457118c2342854bf5cdc15990f382e1fd42c0e6cbc771dc2","self_referential_digest_fields_excluded":true,"whole_binding_hash_in_material":false},"prompt_binding":{"inline_common_prompt_sha256":"a90ac95f0b24ea938a16699f34ef7f17eb870edcbd8964ba4f6709e36e1bbcc0","inline_static_prompt_sha256":"894c30bedaa5f230aed117e81ef4cc06cac832928a1e29cd3ee8804cfd4dba1f","projection_receipt_sha256":"7f64a192e7edda7c0e4025b9f1995dcd21c38aba15a018d232f9f05bcba35863","runtime_external_prompt_read_allowed":false},"release_class":"CHILD_OFFLINE_CONTRACT_RELEASE","release_digest":"262579cc93e89d1a90cd928bf24f21e820022226493ad0a05ae4dc44bef7debd","release_digest_contract":{"algorithm_id":"S2_10-CHILD-RELEASE-DIGEST-V2","canonicalization_algorithm_id":"STAGE2-CANONICAL-JSON-V1","scope":"ENTIRE_DOCUMENT_AFTER_REMOVING_TOP_LEVEL_RELEASE_DIGEST"},"release_id":"STAGE2-S2_10-HYBRID-OFFLINE-CONTRACT-2026-08-30","release_status":"OFFLINE_CONTRACT_COMPLETE_LIVE_ADMISSION_PENDING","schema_version":"stage2_s2_10_release.v2","sealed_asset_count":63,"sealed_assets":[{"path":"Stage_2_S2_10_v.1.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},{"path":"agent_scripts/Stage_2_S2_10.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},{"path":"workflows/S2_10_domain_relief_resolution_map.yml","sha256":"f0fba48f1760cf4e233d7d698fd19090f96ffb89cabe4b2e2cae9af7c616be0f","size_bytes":15320},{"path":"schemas/s2_10.schema.json","sha256":"5233afde9ddb3c5868b9101816e8b3830a90b1399e3e5e89d9d7c7bf5beacaee","size_bytes":82703},{"path":"deployment/stage2_s2_10_llm_binding.yml","sha256":"9d20b264e753c2f52e8d096edab363ace0fecf2ec8357605d1a9cb47c9c2b930","size_bytes":7287},{"path":"manifest/s2_10_inline_prompt_projection_receipt.json","sha256":"7f64a192e7edda7c0e4025b9f1995dcd21c38aba15a018d232f9f05bcba35863","size_bytes":2659},{"path":"offline_build/build_s2_10_agent_projection.py","sha256":"4359364816c8a58eb414bafae8ccf24fc3766dc611d15f1aa09e48c8fedc8f88","size_bytes":61930},{"path":"offline_build/build_s2_10_agent_projection.txt","sha256":"4359364816c8a58eb414bafae8ccf24fc3766dc611d15f1aa09e48c8fedc8f88","size_bytes":61930},{"path":"offline_build/validate_s2_10_contract.py","sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","size_bytes":63811},{"path":"offline_build/validate_s2_10_contract.txt","sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","size_bytes":63811},{"path":"prompts/P00_system_and_safety_contract.md","sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e","size_bytes":7304},{"path":"prompts/P10_legal_resolution_contract.md","sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","size_bytes":8712},{"path":"registry/cache/prompt_cache_policy.yml","sha256":"32b638073b721a9f395d3476105e57236be4e076be81fd6e93f1475b29b93e2a","size_bytes":7527},{"path":"schemas/context.schema.json","sha256":"29073ffa847d74304228d61306503c0c3798da7db8b5717b1ad6d5b2da98aa92","size_bytes":39054},{"path":"schemas/review_status.schema.json","sha256":"13f6f1f06946d4074f3d85959f82763e489b2f87cd7bfadb14b594d6223b02e9","size_bytes":11169},{"path":"registry/authority/authority_registry.yml","sha256":"b4663610e18098cf650fbd5846f18dcbc96074b3012c68f03f67402509c7d142","size_bytes":1517},{"path":"manifest/authority_release.json","sha256":"cc683958377eea44756de6e9c74fc925da66dd60cc84363f5bec36584f5b2967","size_bytes":1068},{"path":"law_values/general_law_values.yml","sha256":"45ad98e9e93090fbc5e5c7037f404bd86ff89b73a4aaf8c3449d226bd2aacd1c","size_bytes":843},{"path":"registry/substantive/E-01_juristic_act_validity.yml","sha256":"0a0d2676f96be321a7bb974b8e4fb1981ab43773f271c99dc86a70cb17d27c99","size_bytes":3808},{"path":"registry/substantive/E-02_contract_money_claim.yml","sha256":"08e252bccc718ccc44a258bc540afc2567e509239399f4017550df32bac97824","size_bytes":3784},{"path":"registry/substantive/E-03_parties_liability_succession.yml","sha256":"4e841d5f640b06a1b52060b82dda39605369cbe26d81655b7918673437e4519c","size_bytes":3799},{"path":"registry/substantive/E-04_unjust_enrichment.yml","sha256":"31a5966d4c14940e810f870bf4382f1be642f7716ebaaa35193ef32e9b9d95c7","size_bytes":3725},{"path":"registry/substantive/E-05_tort_general.yml","sha256":"fe6ea92fc10c4196e0ac83b990bf2606e24024030e7b0002fecdae9f8f50221a","size_bytes":3694},{"path":"registry/substantive/E-06_professional_liability.yml","sha256":"efa7a4f6cda90c04a06558a9d0e1efe13b25169d55d03e36d55d72fcdd096a15","size_bytes":3724},{"path":"registry/substantive/E-07_construction_defect.yml","sha256":"78c76cb0485a4acf741109aee05f634f51c3a6904044c613080b21c3978a09f9","size_bytes":3710},{"path":"registry/substantive/E-08_lease_deposit.yml","sha256":"dbe1886671edff49b8b0251eed567d1b3e4e5d748456434262286ca7acf990db","size_bytes":3678},{"path":"registry/substantive/E-09_registry_transfer_claims.yml","sha256":"d18946322a8cb528146ac0aa0a2880c41ac2056671fd237b928341ceb8561002","size_bytes":3800},{"path":"registry/substantive/E-10_secured_registry.yml","sha256":"5819c26ec8478e12a12e340c93a9d23cc410833e1192c2315a1986c9d48a1eba","size_bytes":3757},{"path":"registry/substantive/E-11_possession_vindication.yml","sha256":"5e6d6460be4ec0f2ba0096305b9ae39f5f430d107337d0d7e07aac1a9d599aaf","size_bytes":3724},{"path":"registry/substantive/E-12_co_ownership_boundary.yml","sha256":"62cfbf6a6c5c5edc8b912e348be1c4d4f7dd4c20c722e57e5554058f0caafb4a","size_bytes":3712},{"path":"registry/substantive/E-13_creditor_preservation.yml","sha256":"c60e6d67c7e3985d1f6ce44027726282f931934e3e66b44f06ccd26845ca2f45","size_bytes":3826},{"path":"registry/substantive/E-14_execution_linked_claims.yml","sha256":"45d4b3ab46e1c8834c3b3eec72a28d05e39cb78a9ec2c2de07b5e55e81aeebd7","size_bytes":3787},{"path":"registry/substantive/E-15_succession_family_property.yml","sha256":"f691b67295ad8e634b34519cf71156caf6eaf73cef54577615ab79462f8aa766","size_bytes":3763},{"path":"registry/substantive/E-16_negotiable_instruments.yml","sha256":"7720d83b64e7a44720788f6ff3c7cc8ceaf5195377a1e61b52de2144989a1194","size_bytes":3738},{"path":"registry/substantive/E-17_labor_wage_claims.yml","sha256":"168ce5e41104937cf7ab946944f060b82cfe16066425897f07bb9e837b8689ea","size_bytes":3728},{"path":"registry/substantive/E-18_org_resolution_status.yml","sha256":"59cf689f886dfaf4ad00dbe6142f5b11c37d0062660f7467aa43427462aa075f","size_bytes":3763},{"path":"registry/substantive/E-19_insurance_claims.yml","sha256":"0fb4793446c155e7a0b4469c9b8c1be1323112eef55ca4c495307c1af56e754c","size_bytes":3685},{"path":"registry/substantive/E-20_ip_claims.yml","sha256":"fe07f20d149a2c4deac2e46de299cd78f0bf829f58c615a86c45f542d30804e1","size_bytes":3654},{"path":"registry/substantive/E-21_media_personality_rights.yml","sha256":"951260bbe8ef116d682f49f3679106c7144ca68f8078f5c10b3459667c1f5b2c","size_bytes":3803},{"path":"registry/substantive/EC-00_contract_general.yml","sha256":"a4f7abd9957b3a9e58d05dd559c3c869bf96fd88ea18968a363c6e606e3c0aa8","size_bytes":3789},{"path":"profiles/crosscut/E-00_residual_unrouted.yml","sha256":"639e507147a6132f9e41ccd0b00d1b5450d6a9629991629b173d5bcaf5b6df39","size_bytes":3752},{"path":"profiles/crosscut/X1_notice_lifecycle.yml","sha256":"9af8b5b5f3a8196a10308d1ee34e0788d9adeac7a99e142e449490d14316faef","size_bytes":3693},{"path":"profiles/crosscut/X2_asset_identity_lineage.yml","sha256":"6c1e437944b3a62b60ee7acad5ec9177fefac2991fe970338acc27efcc8a13ad","size_bytes":3742},{"path":"profiles/crosscut/X3_procedure_standing_relief.yml","sha256":"f3b794bef82566e569232ba02c63ae148099143d8d1ab84de1c4fb76105e65df","size_bytes":3788},{"path":"profiles/crosscut/X4_response_admission_defense.yml","sha256":"57851ed55b3351a8139df29224d74b7cb8427708bbf6de00ecd27c44089df32e","size_bytes":3793},{"path":"profiles/special_law/SL-AUTO_motor_vehicle.yml","sha256":"7234a7ab890f242e6b7aa811528e34c0c85779007cffbf135da0bfff36d61d91","size_bytes":3762},{"path":"profiles/special_law/SL-COMMERCIAL_LEASE.yml","sha256":"5aebed9ab56bc00eb7e0511f9fe5db8c3a42f1e81b28d58c38d487aa91cbab3e","size_bytes":3769},{"path":"profiles/special_law/SL-CONSUMER_CONTRACT.yml","sha256":"afd8bbba102614d8d08f2e7a5384f6ca24e1309c1f52feb13906613f2ced51b7","size_bytes":3797},{"path":"profiles/special_law/SL-INDUSTRIAL_ACCIDENT.yml","sha256":"10d78b8031df7d89f835afc9ca60fab36648e561c729780204c80885f4dd097f","size_bytes":3750},{"path":"profiles/special_law/SL-IP-COPYRIGHT.yml","sha256":"d4349677f68346f79709ea23a05957262f6426f976388bba45f05c617035eb78","size_bytes":3728},{"path":"profiles/special_law/SL-IP-OTHER.yml","sha256":"fc3e2772252a3a90571663ebcfbc8e18dbf526977f4a3d77c4705ef8aa8dd6a8","size_bytes":3746},{"path":"profiles/special_law/SL-IP-PATENT.yml","sha256":"d0651a8a50d0b18d25931063314ecec284988c5a18fab68d08a317d725bb3066","size_bytes":3709},{"path":"profiles/special_law/SL-LABOR.yml","sha256":"6b2542bb64f4c1d164b1ccd2ce5099fad29bcea4333d9e34bd0fb1667b9ced4a","size_bytes":3694},{"path":"profiles/special_law/SL-MEDIA.yml","sha256":"e0d5d287befd1578a06c64a265d5c4426af5772b6764018f6a15f00aac3b498c","size_bytes":3705},{"path":"profiles/special_law/SL-PRODUCT_LIABILITY.yml","sha256":"1d5ee8eddcf005fdb33df58f591a8948aa3e891a3a5656d919394ff0b39eea53","size_bytes":3737},{"path":"profiles/special_law/SL-RESIDENTIAL_LEASE.yml","sha256":"3e2efd1b3c0524a305eafedc5ec91e05be989a6e55c1501ed161a9b8f8151fd7","size_bytes":3739},{"path":"profiles/special_law/SL-STATE_LIABILITY.yml","sha256":"5b2fe6d57b918384a619efbd04360ddfaf7720d384136f69d359ccb0b6c853d3","size_bytes":3747},{"path":"profiles/special_law/SL-TRANSPORT_MARITIME.yml","sha256":"6e87a77c25f8c358f1d7d35ca165b1229c2cb422a440c91768ad80e520d35456","size_bytes":3835},{"path":"profiles/overlays/ACTIO-DEFENSE-MAP.yml","sha256":"05348c493e6046a3e5c55f9b516c0e862fe5aa753e1b2fc71624bb2b11f0c191","size_bytes":3810},{"path":"profiles/overlays/ACTIO-ENCUMBERED-TRANSFER.yml","sha256":"fa950393a572829ba7e296c20cd08ff19a063b0f8441f950130fd677b1e38179","size_bytes":3828},{"path":"profiles/overlays/ACTIO-MORTGAGE-CREATION.yml","sha256":"e727690ee23883e011d49eba01cfd87abc5482641c2bda519c0a39518e1769ee","size_bytes":3771},{"path":"profiles/overlays/ACTIO-MORTGAGE.yml","sha256":"7e584f7b4e4d19132e9575071f87d05965fb77fa2ca870911fe9974a7c511c4d","size_bytes":3739},{"path":"profiles/overlays/ACTIO-PRESERVED-CLAIM-BUNDLE.yml","sha256":"fbd99f029438c1c278f93d88d18a703db72e78f20c7049f344e5748c108f94c5","size_bytes":3816}]} +{"admission_status":{"legal_review":"PENDING_KOREAN_LAWYER_REVIEW","model_benchmark":"PENDING_MODEL_BENCHMARK","platform_adapter":"PENDING_EXTERNAL_PLATFORM_BINDING","production_execution":"BLOCKED","release_bound_canary":"SEPARATE_AUTHORIZATION_REQUIRED"},"authorization_status":"OFFLINE_VALIDATION_ONLY","constitution":{"deterministic_task_count":0,"dispatch_item_schema_version":"stage2_s2_10_dispatch_item.v2","llm_task_count":1,"prompt_contract_version":"S2_10_HYBRID_PROMPT_V1","raw_model_output_schema_version":"stage2_s2_10_model_output.v2","reduce_task_count":0,"runtime_python_asset_count":0,"tool_task_count":0},"external_admission_evidence":[{"path":"manifest/s2_10_platform_adapter_receipt.json","reason":"receipt attests this child release; reverse sealing would create a cycle","sealed_by_child_release":false},{"path":"manifest/s2_10_model_benchmark_receipt.json","reason":"generated only after a release-bound live canary","sealed_by_child_release":false},{"path":"manifest/s2_10_legal_review_receipt.json","reason":"generated only after release-bound Korean lawyer review","sealed_by_child_release":false}],"legacy_stage2_v0_v3_runtime_dependency_count":0,"model_binding":{"binding_status":"PENDING_MODEL_BENCHMARK","endpoint":"responses","model_id":"gpt-5.6-sol","provider":"openai","reasoning_effort":"xhigh","verbosity":"medium"},"parent_stage2_release_ref":{"declared_release_digest":"829be0e66d32a2bb0e07dca758faccfcfa7692333c1e116e631e11f7b4060815","declared_release_id":"STAGE2-CLEAN-DEV-DRAFT-S2_00-HYBRID-HANDOFF-2026-08-30","declared_release_status":"DRAFT_NOT_EXECUTABLE","path":"manifest/stage2_release.json","sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53"},"producer_contract":{"material":{"algorithm_id":"S2_10-PRODUCER-CONTRACT-PROJECTION-V1","claim_option_id_mint_algorithm_id":"S2_10-CLAIM-OPTION-ID-V1","local_relation_rewrite_algorithm_id":"S2_10-TWO-PASS-LOCAL-REF-REWRITE-V1","native_adapter_capability_projection_sha256":"3f08caa2ad872802267fc333069ea2436a9f23ec3d312241d8ed26e3fbbf0525","raw_model_output_schema_closure_algorithm_id":"S2_10-RAW-MODEL-SCHEMA-CLOSURE-BY-FULL-FILE-SHA256-V1","raw_model_output_schema_projection_sha256":"5233afde9ddb3c5868b9101816e8b3830a90b1399e3e5e89d9d7c7bf5beacaee","strict_validator_algorithm_id":"S2_10-OFFLINE-NATIVE-ADAPTER-ORACLE-V2","strict_validator_sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b"},"s2_10_producer_contract_digest":"950da7b30a9799ad457118c2342854bf5cdc15990f382e1fd42c0e6cbc771dc2","self_referential_digest_fields_excluded":true,"whole_binding_hash_in_material":false},"prompt_binding":{"inline_common_prompt_sha256":"a90ac95f0b24ea938a16699f34ef7f17eb870edcbd8964ba4f6709e36e1bbcc0","inline_static_prompt_sha256":"894c30bedaa5f230aed117e81ef4cc06cac832928a1e29cd3ee8804cfd4dba1f","projection_receipt_sha256":"b7fdef2ad05f251bdede9473d3b69c0f169ab7f4a059b393429ff76f739f703e","runtime_external_prompt_read_allowed":false},"release_class":"CHILD_OFFLINE_CONTRACT_RELEASE","release_digest":"8cfc30a40ad53b35fb44c56e3c53f86605f777622399a4b1dcd0b2082eb6e197","release_digest_contract":{"algorithm_id":"S2_10-CHILD-RELEASE-DIGEST-V2","canonicalization_algorithm_id":"STAGE2-CANONICAL-JSON-V1","scope":"ENTIRE_DOCUMENT_AFTER_REMOVING_TOP_LEVEL_RELEASE_DIGEST"},"release_id":"STAGE2-S2_10-HYBRID-OFFLINE-CONTRACT-2026-08-30","release_status":"OFFLINE_CONTRACT_COMPLETE_LIVE_ADMISSION_PENDING","schema_version":"stage2_s2_10_release.v2","sealed_asset_count":63,"sealed_assets":[{"path":"Stage_2_S2_10_v.1.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},{"path":"agent_scripts/Stage_2_S2_10.yml","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","size_bytes":30984},{"path":"workflows/S2_10_domain_relief_resolution_map.yml","sha256":"f0fba48f1760cf4e233d7d698fd19090f96ffb89cabe4b2e2cae9af7c616be0f","size_bytes":15320},{"path":"schemas/s2_10.schema.json","sha256":"5233afde9ddb3c5868b9101816e8b3830a90b1399e3e5e89d9d7c7bf5beacaee","size_bytes":82703},{"path":"deployment/stage2_s2_10_llm_binding.yml","sha256":"9b5d69f1316a0b9fba7b41097ee92142cf42485c8deb0be876d9e9329c317a04","size_bytes":7287},{"path":"manifest/s2_10_inline_prompt_projection_receipt.json","sha256":"b7fdef2ad05f251bdede9473d3b69c0f169ab7f4a059b393429ff76f739f703e","size_bytes":2659},{"path":"offline_build/build_s2_10_agent_projection.py","sha256":"efdde6d70c723e9386f2ba1828119af7e68f7956c29bd3ba05370242a70ab62d","size_bytes":68381},{"path":"offline_build/build_s2_10_agent_projection.txt","sha256":"efdde6d70c723e9386f2ba1828119af7e68f7956c29bd3ba05370242a70ab62d","size_bytes":68381},{"path":"offline_build/validate_s2_10_contract.py","sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","size_bytes":63811},{"path":"offline_build/validate_s2_10_contract.txt","sha256":"17996fb280435146ec0045a69c101c2d2088af27391cafc443a698eca70d5b0b","size_bytes":63811},{"path":"prompts/P00_system_and_safety_contract.md","sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e","size_bytes":7304},{"path":"prompts/P10_legal_resolution_contract.md","sha256":"cafaab3991b8bd4ef3c95e55ce4c0649794c6eed9479d46d8c7758a4b823569b","size_bytes":8712},{"path":"registry/cache/prompt_cache_policy.yml","sha256":"32b638073b721a9f395d3476105e57236be4e076be81fd6e93f1475b29b93e2a","size_bytes":7527},{"path":"schemas/context.schema.json","sha256":"29073ffa847d74304228d61306503c0c3798da7db8b5717b1ad6d5b2da98aa92","size_bytes":39054},{"path":"schemas/review_status.schema.json","sha256":"dbf559cae183b9e9878a56ff9364ddfe68f7bf6ba1e00e595ec8876f2fc01d95","size_bytes":27241},{"path":"registry/authority/authority_registry.yml","sha256":"b4663610e18098cf650fbd5846f18dcbc96074b3012c68f03f67402509c7d142","size_bytes":1517},{"path":"manifest/authority_release.json","sha256":"cc683958377eea44756de6e9c74fc925da66dd60cc84363f5bec36584f5b2967","size_bytes":1068},{"path":"law_values/general_law_values.yml","sha256":"45ad98e9e93090fbc5e5c7037f404bd86ff89b73a4aaf8c3449d226bd2aacd1c","size_bytes":843},{"path":"registry/substantive/E-01_juristic_act_validity.yml","sha256":"0a0d2676f96be321a7bb974b8e4fb1981ab43773f271c99dc86a70cb17d27c99","size_bytes":3808},{"path":"registry/substantive/E-02_contract_money_claim.yml","sha256":"08e252bccc718ccc44a258bc540afc2567e509239399f4017550df32bac97824","size_bytes":3784},{"path":"registry/substantive/E-03_parties_liability_succession.yml","sha256":"4e841d5f640b06a1b52060b82dda39605369cbe26d81655b7918673437e4519c","size_bytes":3799},{"path":"registry/substantive/E-04_unjust_enrichment.yml","sha256":"31a5966d4c14940e810f870bf4382f1be642f7716ebaaa35193ef32e9b9d95c7","size_bytes":3725},{"path":"registry/substantive/E-05_tort_general.yml","sha256":"fe6ea92fc10c4196e0ac83b990bf2606e24024030e7b0002fecdae9f8f50221a","size_bytes":3694},{"path":"registry/substantive/E-06_professional_liability.yml","sha256":"efa7a4f6cda90c04a06558a9d0e1efe13b25169d55d03e36d55d72fcdd096a15","size_bytes":3724},{"path":"registry/substantive/E-07_construction_defect.yml","sha256":"78c76cb0485a4acf741109aee05f634f51c3a6904044c613080b21c3978a09f9","size_bytes":3710},{"path":"registry/substantive/E-08_lease_deposit.yml","sha256":"dbe1886671edff49b8b0251eed567d1b3e4e5d748456434262286ca7acf990db","size_bytes":3678},{"path":"registry/substantive/E-09_registry_transfer_claims.yml","sha256":"d18946322a8cb528146ac0aa0a2880c41ac2056671fd237b928341ceb8561002","size_bytes":3800},{"path":"registry/substantive/E-10_secured_registry.yml","sha256":"5819c26ec8478e12a12e340c93a9d23cc410833e1192c2315a1986c9d48a1eba","size_bytes":3757},{"path":"registry/substantive/E-11_possession_vindication.yml","sha256":"5e6d6460be4ec0f2ba0096305b9ae39f5f430d107337d0d7e07aac1a9d599aaf","size_bytes":3724},{"path":"registry/substantive/E-12_co_ownership_boundary.yml","sha256":"62cfbf6a6c5c5edc8b912e348be1c4d4f7dd4c20c722e57e5554058f0caafb4a","size_bytes":3712},{"path":"registry/substantive/E-13_creditor_preservation.yml","sha256":"c60e6d67c7e3985d1f6ce44027726282f931934e3e66b44f06ccd26845ca2f45","size_bytes":3826},{"path":"registry/substantive/E-14_execution_linked_claims.yml","sha256":"45d4b3ab46e1c8834c3b3eec72a28d05e39cb78a9ec2c2de07b5e55e81aeebd7","size_bytes":3787},{"path":"registry/substantive/E-15_succession_family_property.yml","sha256":"f691b67295ad8e634b34519cf71156caf6eaf73cef54577615ab79462f8aa766","size_bytes":3763},{"path":"registry/substantive/E-16_negotiable_instruments.yml","sha256":"7720d83b64e7a44720788f6ff3c7cc8ceaf5195377a1e61b52de2144989a1194","size_bytes":3738},{"path":"registry/substantive/E-17_labor_wage_claims.yml","sha256":"168ce5e41104937cf7ab946944f060b82cfe16066425897f07bb9e837b8689ea","size_bytes":3728},{"path":"registry/substantive/E-18_org_resolution_status.yml","sha256":"59cf689f886dfaf4ad00dbe6142f5b11c37d0062660f7467aa43427462aa075f","size_bytes":3763},{"path":"registry/substantive/E-19_insurance_claims.yml","sha256":"0fb4793446c155e7a0b4469c9b8c1be1323112eef55ca4c495307c1af56e754c","size_bytes":3685},{"path":"registry/substantive/E-20_ip_claims.yml","sha256":"fe07f20d149a2c4deac2e46de299cd78f0bf829f58c615a86c45f542d30804e1","size_bytes":3654},{"path":"registry/substantive/E-21_media_personality_rights.yml","sha256":"951260bbe8ef116d682f49f3679106c7144ca68f8078f5c10b3459667c1f5b2c","size_bytes":3803},{"path":"registry/substantive/EC-00_contract_general.yml","sha256":"a4f7abd9957b3a9e58d05dd559c3c869bf96fd88ea18968a363c6e606e3c0aa8","size_bytes":3789},{"path":"profiles/crosscut/E-00_residual_unrouted.yml","sha256":"639e507147a6132f9e41ccd0b00d1b5450d6a9629991629b173d5bcaf5b6df39","size_bytes":3752},{"path":"profiles/crosscut/X1_notice_lifecycle.yml","sha256":"9af8b5b5f3a8196a10308d1ee34e0788d9adeac7a99e142e449490d14316faef","size_bytes":3693},{"path":"profiles/crosscut/X2_asset_identity_lineage.yml","sha256":"6c1e437944b3a62b60ee7acad5ec9177fefac2991fe970338acc27efcc8a13ad","size_bytes":3742},{"path":"profiles/crosscut/X3_procedure_standing_relief.yml","sha256":"f3b794bef82566e569232ba02c63ae148099143d8d1ab84de1c4fb76105e65df","size_bytes":3788},{"path":"profiles/crosscut/X4_response_admission_defense.yml","sha256":"57851ed55b3351a8139df29224d74b7cb8427708bbf6de00ecd27c44089df32e","size_bytes":3793},{"path":"profiles/special_law/SL-AUTO_motor_vehicle.yml","sha256":"7234a7ab890f242e6b7aa811528e34c0c85779007cffbf135da0bfff36d61d91","size_bytes":3762},{"path":"profiles/special_law/SL-COMMERCIAL_LEASE.yml","sha256":"5aebed9ab56bc00eb7e0511f9fe5db8c3a42f1e81b28d58c38d487aa91cbab3e","size_bytes":3769},{"path":"profiles/special_law/SL-CONSUMER_CONTRACT.yml","sha256":"afd8bbba102614d8d08f2e7a5384f6ca24e1309c1f52feb13906613f2ced51b7","size_bytes":3797},{"path":"profiles/special_law/SL-INDUSTRIAL_ACCIDENT.yml","sha256":"10d78b8031df7d89f835afc9ca60fab36648e561c729780204c80885f4dd097f","size_bytes":3750},{"path":"profiles/special_law/SL-IP-COPYRIGHT.yml","sha256":"d4349677f68346f79709ea23a05957262f6426f976388bba45f05c617035eb78","size_bytes":3728},{"path":"profiles/special_law/SL-IP-OTHER.yml","sha256":"fc3e2772252a3a90571663ebcfbc8e18dbf526977f4a3d77c4705ef8aa8dd6a8","size_bytes":3746},{"path":"profiles/special_law/SL-IP-PATENT.yml","sha256":"d0651a8a50d0b18d25931063314ecec284988c5a18fab68d08a317d725bb3066","size_bytes":3709},{"path":"profiles/special_law/SL-LABOR.yml","sha256":"6b2542bb64f4c1d164b1ccd2ce5099fad29bcea4333d9e34bd0fb1667b9ced4a","size_bytes":3694},{"path":"profiles/special_law/SL-MEDIA.yml","sha256":"e0d5d287befd1578a06c64a265d5c4426af5772b6764018f6a15f00aac3b498c","size_bytes":3705},{"path":"profiles/special_law/SL-PRODUCT_LIABILITY.yml","sha256":"1d5ee8eddcf005fdb33df58f591a8948aa3e891a3a5656d919394ff0b39eea53","size_bytes":3737},{"path":"profiles/special_law/SL-RESIDENTIAL_LEASE.yml","sha256":"3e2efd1b3c0524a305eafedc5ec91e05be989a6e55c1501ed161a9b8f8151fd7","size_bytes":3739},{"path":"profiles/special_law/SL-STATE_LIABILITY.yml","sha256":"5b2fe6d57b918384a619efbd04360ddfaf7720d384136f69d359ccb0b6c853d3","size_bytes":3747},{"path":"profiles/special_law/SL-TRANSPORT_MARITIME.yml","sha256":"6e87a77c25f8c358f1d7d35ca165b1229c2cb422a440c91768ad80e520d35456","size_bytes":3835},{"path":"profiles/overlays/ACTIO-DEFENSE-MAP.yml","sha256":"05348c493e6046a3e5c55f9b516c0e862fe5aa753e1b2fc71624bb2b11f0c191","size_bytes":3810},{"path":"profiles/overlays/ACTIO-ENCUMBERED-TRANSFER.yml","sha256":"fa950393a572829ba7e296c20cd08ff19a063b0f8441f950130fd677b1e38179","size_bytes":3828},{"path":"profiles/overlays/ACTIO-MORTGAGE-CREATION.yml","sha256":"e727690ee23883e011d49eba01cfd87abc5482641c2bda519c0a39518e1769ee","size_bytes":3771},{"path":"profiles/overlays/ACTIO-MORTGAGE.yml","sha256":"7e584f7b4e4d19132e9575071f87d05965fb77fa2ca870911fe9974a7c511c4d","size_bytes":3739},{"path":"profiles/overlays/ACTIO-PRESERVED-CLAIM-BUNDLE.yml","sha256":"fbd99f029438c1c278f93d88d18a703db72e78f20c7049f344e5748c108f94c5","size_bytes":3816}]} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_20_inline_code_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_20_inline_code_receipt.json index 6a89556b..82ce37ac 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_20_inline_code_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_20_inline_code_receipt.json @@ -1 +1 @@ -{"authoring":{"path":"Stage_2_S2_20.yml","sha256":"ac81d164309e5301083d0971e1736d128691fd9b18558ac4ade3f0246a43c2d7","size_bytes":254756},"canonical_code":{"ast_status":"PASS","code_sha256":"eeb353b837cf5c2ecfb07fc7375eca03ac4e5c3df9254266d5690cbf14df7138","code_size_bytes":200269,"compile_status":"PASS","encoding":"UTF-8","endpoint_literals":["http://mcp-localdocs:8012/mcp","https://weaviate.eroomai.com/mcp"],"expected_parent_stage2_release_sha256":"579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81","external_python_source_ref_count":0,"extraction_transform":"NONE","forbidden_dynamic_call_count":0,"forbidden_import_count":0,"imports":["__future__","base64","binascii","concurrent","contextlib","datetime","decimal","hashlib","httpx","io","itertools","json","pathlib","re","sys","typing","unicodedata"],"plaintext_secret_count":0,"yaml_pointer":"/Agent/Stages/0/tasks/0/parameters/code"},"deployment_projection":{"path":"Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml","sha256":"ac81d164309e5301083d0971e1736d128691fd9b18558ac4ade3f0246a43c2d7","size_bytes":254756},"full_code_mirrors":["Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.py","Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.txt"],"parity_status":"PASS","schema_version":"stage2_s2_20_inline_code_receipt.v1","task_contract":{"agent":{"name":"Stage_2_S2_20","version":"1.0.0"},"authoring_rewritten":false,"canonical_task_semantics_sha256":"460bd442ece9b2e39a45d1df5fd333db39d5267da49bc1a63192a580b90e7c0f","code_mirrors_byte_identical":true,"exactly_one_code_executor_run_code":true,"exactly_one_stage":true,"exactly_one_task":true,"expected_parent_stage2_release_sha256":"579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81","internal_dag":"(C20||C21)->C25->C26->(C22||(C27->C28->C29))->C30->C35","mcp_servers":{"code-executor":{"type":"streamable-http","url":"https://code-executor.mcp.eroomai.com/mcp"},"localdocs":{"type":"streamable-http","url":"http://mcp-localdocs:8012/mcp"}},"projection_byte_identical_to_authoring":true,"stage":{"name":"S2_20","nexts":[],"prevs":[],"skip_confirm":true},"task":{"code_sha256":"eeb353b837cf5c2ecfb07fc7375eca03ac4e5c3df9254266d5690cbf14df7138","mcp":"code-executor","parameters":{"language":"python","network":"agent-network","requirements":"httpx==0.28.1","timeout":300},"task_name":"Task_S2_20_deterministic_relief_plan","tool_name":"run_code"},"task_procedure":{"IN":{"nexts":["Task_S2_20_deterministic_relief_plan"],"wait_until":[]},"OUT":{"nexts":[],"wait_until":["Task_S2_20_deterministic_relief_plan"]},"Task_S2_20_deterministic_relief_plan":{"nexts":["OUT"],"wait_until":["IN"]}}},"workflow_id":"S2_20"} +{"authoring":{"path":"Stage_2_S2_20.yml","sha256":"3c4e6a7404f5b6a6b2403824c3cd9e71db566d4f2865bd4de3e6fd9d07824bd6","size_bytes":254756},"canonical_code":{"ast_status":"PASS","code_sha256":"6f1f503378242cf64cf8f0838af2164ab1103bc7031c8a6873f4ee89be66f7fd","code_size_bytes":200269,"compile_status":"PASS","encoding":"UTF-8","endpoint_literals":["http://mcp-localdocs:8012/mcp","https://weaviate.eroomai.com/mcp"],"expected_parent_stage2_release_sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53","external_python_source_ref_count":0,"extraction_transform":"NONE","forbidden_dynamic_call_count":0,"forbidden_import_count":0,"imports":["__future__","base64","binascii","concurrent","contextlib","datetime","decimal","hashlib","httpx","io","itertools","json","pathlib","re","sys","typing","unicodedata"],"plaintext_secret_count":0,"yaml_pointer":"/Agent/Stages/0/tasks/0/parameters/code"},"deployment_projection":{"path":"Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_20.yml","sha256":"3c4e6a7404f5b6a6b2403824c3cd9e71db566d4f2865bd4de3e6fd9d07824bd6","size_bytes":254756},"full_code_mirrors":["Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.py","Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.txt"],"parity_status":"PASS","schema_version":"stage2_s2_20_inline_code_receipt.v1","task_contract":{"agent":{"name":"Stage_2_S2_20","version":"1.0.0"},"authoring_rewritten":false,"canonical_task_semantics_sha256":"750bf364c9b73460349005590cbf65ae4c0235b5af0770937ccbbf669d159dd0","code_mirrors_byte_identical":true,"exactly_one_code_executor_run_code":true,"exactly_one_stage":true,"exactly_one_task":true,"expected_parent_stage2_release_sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53","internal_dag":"(C20||C21)->C25->C26->(C22||(C27->C28->C29))->C30->C35","mcp_servers":{"code-executor":{"type":"streamable-http","url":"https://code-executor.mcp.eroomai.com/mcp"},"localdocs":{"type":"streamable-http","url":"http://mcp-localdocs:8012/mcp"}},"projection_byte_identical_to_authoring":true,"stage":{"name":"S2_20","nexts":[],"prevs":[],"skip_confirm":true},"task":{"code_sha256":"6f1f503378242cf64cf8f0838af2164ab1103bc7031c8a6873f4ee89be66f7fd","mcp":"code-executor","parameters":{"language":"python","network":"agent-network","requirements":"httpx==0.28.1","timeout":300},"task_name":"Task_S2_20_deterministic_relief_plan","tool_name":"run_code"},"task_procedure":{"IN":{"nexts":["Task_S2_20_deterministic_relief_plan"],"wait_until":[]},"OUT":{"nexts":[],"wait_until":["Task_S2_20_deterministic_relief_plan"]},"Task_S2_20_deterministic_relief_plan":{"nexts":["OUT"],"wait_until":["IN"]}}},"workflow_id":"S2_20"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_agent_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_agent_receipt.json index a8a25b43..cee2819c 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_agent_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_agent_receipt.json @@ -1 +1 @@ -{"authoring_sha256":"6da21b319d10268e5f1959d085173d22017e4910c7222fd5e6daf72628629773","binding_sha256":"1d99d933aca1803a681b8fc70eab368fa3b11b5a4f7d384a6be6cd9cb5883512","byte_parity":"PASS","child_release_sha256":"90b96d0e00d0491f7dfafe3b9f2cec3a1055d64fe4979780fe00af849257e884","deployment_sha256":"6da21b319d10268e5f1959d085173d22017e4910c7222fd5e6daf72628629773","deterministic_helper_task_count":1,"llm_task_template_count":1,"receipt_digest":"5ee7d882c739ffc437e808b0d22580134ad4b3af0047fbe1e55eb46502f09ed0","receipt_status":"OFFLINE_AGENT_PROJECTION_VERIFIED","reduce_task_count":0,"schema_version":"stage2_s2_30_agent_receipt.v1","task_template_count":2} +{"authoring_sha256":"d0804526941207395c9b64a314b124ff8e919c6852e828d829dc45a9feb3ccdd","binding_sha256":"7cf19e7dd8d3ad58251e20edc56e11fde3bffb3936997538eb09301da06189dc","byte_parity":"PASS","child_release_sha256":"e6dd6abe44b39de462ea01f5e78aa39c70bbf47e0b75e08d224615a297d2135f","deployment_sha256":"d0804526941207395c9b64a314b124ff8e919c6852e828d829dc45a9feb3ccdd","deterministic_helper_task_count":1,"llm_task_template_count":1,"receipt_digest":"fac154c1a47a050c1d8cac98a6df7abd92b0410e024c9cb26664dcef4006f13d","receipt_status":"OFFLINE_AGENT_PROJECTION_VERIFIED","reduce_task_count":0,"schema_version":"stage2_s2_30_agent_receipt.v1","task_template_count":2} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_inline_code_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_inline_code_receipt.json index eb0598f2..63490f5e 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_inline_code_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_inline_code_receipt.json @@ -1 +1 @@ -{"ast_policy_status":"PASS","authoring_agent_sha256":"6da21b319d10268e5f1959d085173d22017e4910c7222fd5e6daf72628629773","compile_status":"PASS","inline_code_sha256":"7814e64bfdbf5992d8009556b5a81268d99a0300d0b8f419c8c6384d90a906c9","inline_code_size_bytes":67777,"planner_mirror_paths":["runtime/s2_30_dispatch_planner.py","runtime/s2_30_dispatch_planner.txt"],"receipt_digest":"e1d46ddf49865d69715ba2f0c0a20290e9b755b5753709018c65c95c7486547c","receipt_status":"OFFLINE_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","runtime_external_python_import_count":0,"schema_version":"stage2_s2_30_inline_code_receipt.v1"} +{"ast_policy_status":"PASS","authoring_agent_sha256":"d0804526941207395c9b64a314b124ff8e919c6852e828d829dc45a9feb3ccdd","compile_status":"PASS","inline_code_sha256":"1f7f3b842afbd3f1034f094d6341288effc9804a03920ada4bf8cfd512464e4c","inline_code_size_bytes":67777,"planner_mirror_paths":["runtime/s2_30_dispatch_planner.py","runtime/s2_30_dispatch_planner.txt"],"receipt_digest":"fe592796579be30899bde4006a0a3ba1d51b97b51a5b7049a3f67539158c71c9","receipt_status":"OFFLINE_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","runtime_external_python_import_count":0,"schema_version":"stage2_s2_30_inline_code_receipt.v1"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_inline_prompt_projection_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_inline_prompt_projection_receipt.json index e73f8337..ccba7041 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_inline_prompt_projection_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_inline_prompt_projection_receipt.json @@ -1 +1 @@ -{"authoring_agent":{"path":"Stage_2_S2_30.yml","sha256":"6da21b319d10268e5f1959d085173d22017e4910c7222fd5e6daf72628629773","size_bytes":117060},"dynamic_item_tokens":["{{item.p32_common_authority_json}}","{{item.p31_rule_and_pack_json}}","{{item.s30_group_slice_json}}","{{item.compile_mode}}","{{item.s30_group_slice_sha256}}"],"inline_scalars":[{"parity":"PASS","raw_scalar_sha256":"a90ac95f0b24ea938a16699f34ef7f17eb870edcbd8964ba4f6709e36e1bbcc0","source":{"path":"prompts/P00_system_and_safety_contract.md","sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e","size_bytes":7304},"wrapper":"stage_2_common_cache_prefix","yaml_pointer":"/Agent/Stages/0/tasks/1/prompts/0/content"},{"parity":"PASS","raw_scalar_sha256":"577efa2c3334298ec60188b9f0066f834e072dc99f785b3c6ab4d05a47fac18a","source":{"path":"prompts/P30_joint_drafting_contract.md","sha256":"5d790fccdacd1b7ce27e25cd52e4c301dbce24ba276def18bca608b5b16362aa","size_bytes":13681},"wrapper":"s2_30_joint_drafting_static_prompt","yaml_pointer":"/Agent/Stages/0/tasks/1/prompts/1/content"}],"message_order":["INLINE_COMMON_SYSTEM","INLINE_S2_30_STATIC_SYSTEM","P32_COMMON_AUTHORITY_SYSTEM_DATA","P31_RULE_AND_PACK_SYSTEM_DATA","S30_GROUP_CASE_USER_DATA"],"receipt_digest":"9dae633a55e091e5a8aa9173c2471b7ac24aaf3ddffda6cbd9ebbe6365d982d3","receipt_status":"OFFLINE_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","schema_version":"stage2_s2_30_inline_prompt_projection_receipt.v1"} +{"authoring_agent":{"path":"Stage_2_S2_30.yml","sha256":"d0804526941207395c9b64a314b124ff8e919c6852e828d829dc45a9feb3ccdd","size_bytes":117060},"dynamic_item_tokens":["{{item.p32_common_authority_json}}","{{item.p31_rule_and_pack_json}}","{{item.s30_group_slice_json}}","{{item.compile_mode}}","{{item.s30_group_slice_sha256}}"],"inline_scalars":[{"parity":"PASS","raw_scalar_sha256":"a90ac95f0b24ea938a16699f34ef7f17eb870edcbd8964ba4f6709e36e1bbcc0","source":{"path":"prompts/P00_system_and_safety_contract.md","sha256":"c82cfc0b61adb1af7759fd321f78bcf7bebf7e5d2fc3a9c01533a80736c6d80e","size_bytes":7304},"wrapper":"stage_2_common_cache_prefix","yaml_pointer":"/Agent/Stages/0/tasks/1/prompts/0/content"},{"parity":"PASS","raw_scalar_sha256":"577efa2c3334298ec60188b9f0066f834e072dc99f785b3c6ab4d05a47fac18a","source":{"path":"prompts/P30_joint_drafting_contract.md","sha256":"5d790fccdacd1b7ce27e25cd52e4c301dbce24ba276def18bca608b5b16362aa","size_bytes":13681},"wrapper":"s2_30_joint_drafting_static_prompt","yaml_pointer":"/Agent/Stages/0/tasks/1/prompts/1/content"}],"message_order":["INLINE_COMMON_SYSTEM","INLINE_S2_30_STATIC_SYSTEM","P32_COMMON_AUTHORITY_SYSTEM_DATA","P31_RULE_AND_PACK_SYSTEM_DATA","S30_GROUP_CASE_USER_DATA"],"receipt_digest":"13b89691392616f6f70b2cb1a92a24ee4d891480b56c8c1b41b5bdabe88bbad1","receipt_status":"OFFLINE_PROJECTION_VERIFIED","runtime_admission_effect":"NONE","schema_version":"stage2_s2_30_inline_prompt_projection_receipt.v1"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_legal_review_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_legal_review_receipt.json index 37a991c5..beb619d3 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_legal_review_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_legal_review_receipt.json @@ -1 +1 @@ -{"binding_sha256":"1d99d933aca1803a681b8fc70eab368fa3b11b5a4f7d384a6be6cd9cb5883512","child_release_sha256":"90b96d0e00d0491f7dfafe3b9f2cec3a1055d64fe4979780fe00af849257e884","evidence":[],"live_execution_attested":false,"parent_release_sha256":"579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81","receipt_digest":"6b97a3fd5bb2e3eb42a6e96296884e745f7c8feb2623a075c53b4b470da8ab41","runtime_admission_effect":"BLOCK_PRODUCTION","schema_version":"stage2_s2_30_legal_review_receipt.v1","status":"PENDING_KOREAN_LAWYER_REVIEW"} +{"binding_sha256":"7cf19e7dd8d3ad58251e20edc56e11fde3bffb3936997538eb09301da06189dc","child_release_sha256":"e6dd6abe44b39de462ea01f5e78aa39c70bbf47e0b75e08d224615a297d2135f","evidence":[],"live_execution_attested":false,"parent_release_sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53","receipt_digest":"6fc276d58d8613c0f7a2f4cb31dce0fc12c04e0239168a969f77e8a3b85437cb","runtime_admission_effect":"BLOCK_PRODUCTION","schema_version":"stage2_s2_30_legal_review_receipt.v1","status":"PENDING_KOREAN_LAWYER_REVIEW"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_model_benchmark_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_model_benchmark_receipt.json index 194f2dcc..17611d90 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_model_benchmark_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_model_benchmark_receipt.json @@ -1 +1 @@ -{"binding_sha256":"1d99d933aca1803a681b8fc70eab368fa3b11b5a4f7d384a6be6cd9cb5883512","child_release_sha256":"90b96d0e00d0491f7dfafe3b9f2cec3a1055d64fe4979780fe00af849257e884","evidence":[],"live_execution_attested":false,"parent_release_sha256":"579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81","receipt_digest":"0eaf5733b7605d8d2f79a99eea1cdd6d8447c0d679df41be00d04149ab699b3e","runtime_admission_effect":"BLOCK_PRODUCTION","schema_version":"stage2_s2_30_model_benchmark_receipt.v1","status":"PENDING_MODEL_BENCHMARK"} +{"binding_sha256":"7cf19e7dd8d3ad58251e20edc56e11fde3bffb3936997538eb09301da06189dc","child_release_sha256":"e6dd6abe44b39de462ea01f5e78aa39c70bbf47e0b75e08d224615a297d2135f","evidence":[],"live_execution_attested":false,"parent_release_sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53","receipt_digest":"d8d231359c086ae13fec794d233ebf0ba5854c207da569923ed72d8c6ca90abc","runtime_admission_effect":"BLOCK_PRODUCTION","schema_version":"stage2_s2_30_model_benchmark_receipt.v1","status":"PENDING_MODEL_BENCHMARK"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_parent_member_paths.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_parent_member_paths.json index c338fb44..d74b4f42 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_parent_member_paths.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_parent_member_paths.json @@ -1 +1 @@ -["manifest/s2_30_parent_member_paths.json","offline_build/build_s2_30_agent_projection.py","offline_build/build_s2_30_agent_projection.txt","offline_build/validate_s2_30_contract.py","offline_build/validate_s2_30_contract.txt","prompts/P30_joint_drafting_contract.md","schemas/draft_atoms.schema.json","tests/fixtures/s2_30/adverse_fact_worknote_policy.json","tests/fixtures/s2_30/cache_prefix_drift.json","tests/fixtures/s2_30/context_reference_envelope.json","tests/fixtures/s2_30/counter_performance_and_declaration.json","tests/fixtures/s2_30/follower_batch_dispatch.json","tests/fixtures/s2_30/invalid_forbidden_output.json","tests/fixtures/s2_30/invalid_preassembled_prompt_item.json","tests/fixtures/s2_30/invalid_reference_output.json","tests/fixtures/s2_30/owner_singleton_dispatch.json","tests/fixtures/s2_30/partial_write_publish_barrier.json","tests/fixtures/s2_30/regression_manifest.json","tests/fixtures/s2_30/rule_requirement_admission_gap.json","tests/fixtures/s2_30/technical_failure.json","tests/fixtures/s2_30/valid_joint_draft_output.json","tests/s2_30/test_agent_contract.py","tests/s2_30/test_agent_contract.txt","tests/s2_30/test_dispatch_materialization.py","tests/s2_30/test_dispatch_materialization.txt","tests/s2_30/test_draft_atom_contract.py","tests/s2_30/test_draft_atom_contract.txt","tests/s2_30/test_prompt_cache_and_boundaries.py","tests/s2_30/test_prompt_cache_and_boundaries.txt","tests/s2_30/test_release_adapter_retry.py","tests/s2_30/test_release_adapter_retry.txt","workflows/S2_30_claim_group_draft_map.yml"] +["manifest/s2_30_parent_member_paths.json","offline_build/build_s2_30_agent_projection.py","offline_build/build_s2_30_agent_projection.txt","offline_build/validate_s2_30_contract.py","offline_build/validate_s2_30_contract.txt","prompts/P30_joint_drafting_contract.md","schemas/draft_atoms.schema.json","tests/fixtures/s2_30/adverse_fact_worknote_policy.json","tests/fixtures/s2_30/cache_prefix_drift.json","tests/fixtures/s2_30/context_reference_envelope.json","tests/fixtures/s2_30/counter_performance_and_declaration.json","tests/fixtures/s2_30/follower_batch_dispatch.json","tests/fixtures/s2_30/invalid_forbidden_output.json","tests/fixtures/s2_30/invalid_preassembled_prompt_item.json","tests/fixtures/s2_30/invalid_reference_output.json","tests/fixtures/s2_30/owner_singleton_dispatch.json","tests/fixtures/s2_30/partial_write_publish_barrier.json","tests/fixtures/s2_30/persisted_handoff_chain.json","tests/fixtures/s2_30/regression_manifest.json","tests/fixtures/s2_30/rule_requirement_admission_gap.json","tests/fixtures/s2_30/technical_failure.json","tests/fixtures/s2_30/valid_joint_draft_output.json","tests/s2_30/test_agent_contract.py","tests/s2_30/test_agent_contract.txt","tests/s2_30/test_dispatch_materialization.py","tests/s2_30/test_dispatch_materialization.txt","tests/s2_30/test_draft_atom_contract.py","tests/s2_30/test_draft_atom_contract.txt","tests/s2_30/test_prompt_cache_and_boundaries.py","tests/s2_30/test_prompt_cache_and_boundaries.txt","tests/s2_30/test_release_adapter_retry.py","tests/s2_30/test_release_adapter_retry.txt","workflows/S2_30_claim_group_draft_map.yml"] diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_platform_adapter_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_platform_adapter_receipt.json index 59526eb6..2d9688d5 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_platform_adapter_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_platform_adapter_receipt.json @@ -1 +1 @@ -{"binding_sha256":"1d99d933aca1803a681b8fc70eab368fa3b11b5a4f7d384a6be6cd9cb5883512","capabilities":[{"capability_id":"HOST_ATOMIC_GROUP_DISPATCH_CAS_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"AGENTBACKEND_TASK_PROCEDURE_WILDCARD_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"AGENTBACKEND_WILDCARD_RESULT_ADAPTER_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_CONTEXT_MATERIALIZER_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_CACHE_OWNER_SEQUENCE_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_STRICT_SCHEMA_REF_PROVENANCE_VALIDATOR_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_DETERMINISTIC_ATOM_ID_TWO_PASS_PERSIST_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_GROUP_RETRY_CONTROLLER_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_GROUP_BARRIER_COORDINATOR_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_CANARY_AUTHORIZATION_SIGNATURE_VERIFY_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"}],"child_release_sha256":"90b96d0e00d0491f7dfafe3b9f2cec3a1055d64fe4979780fe00af849257e884","evidence":[],"live_execution_attested":false,"overall_status":"PENDING_EXTERNAL_PLATFORM_BINDING","parent_release_sha256":"579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81","receipt_digest":"19ce93ff7d086826739ef57bcb766135b00f53a070952b449528bcfe0d7310ae","runtime_admission_effect":"BLOCK_PRODUCTION","schema_version":"stage2_s2_30_platform_adapter_receipt.v1"} +{"binding_sha256":"7cf19e7dd8d3ad58251e20edc56e11fde3bffb3936997538eb09301da06189dc","capabilities":[{"capability_id":"HOST_ATOMIC_GROUP_DISPATCH_CAS_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"AGENTBACKEND_TASK_PROCEDURE_WILDCARD_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"AGENTBACKEND_WILDCARD_RESULT_ADAPTER_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_CONTEXT_MATERIALIZER_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_CACHE_OWNER_SEQUENCE_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_STRICT_SCHEMA_REF_PROVENANCE_VALIDATOR_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_DETERMINISTIC_ATOM_ID_TWO_PASS_PERSIST_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_GROUP_RETRY_CONTROLLER_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_GROUP_BARRIER_COORDINATOR_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"},{"capability_id":"S2_30_CANARY_AUTHORIZATION_SIGNATURE_VERIFY_V1","status":"PENDING_EXTERNAL_PLATFORM_BINDING"}],"child_release_sha256":"e6dd6abe44b39de462ea01f5e78aa39c70bbf47e0b75e08d224615a297d2135f","evidence":[],"live_execution_attested":false,"overall_status":"PENDING_EXTERNAL_PLATFORM_BINDING","parent_release_sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53","receipt_digest":"31b81bdbef3bea6712c6ca2921af4e6b55e264f69b2ed341e1d83c770d3df1c5","runtime_admission_effect":"BLOCK_PRODUCTION","schema_version":"stage2_s2_30_platform_adapter_receipt.v1"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_release.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_release.json index 8a48468b..3d28756f 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_release.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_30_release.json @@ -1 +1 @@ -{"admission_status":{"legal_review":"PENDING_KOREAN_LAWYER_REVIEW","model_benchmark":"PENDING_MODEL_BENCHMARK","platform_adapter":"PENDING_EXTERNAL_PLATFORM_BINDING","production_execution":"BLOCKED"},"authorization_status":"OFFLINE_VALIDATION_ONLY","external_admission_evidence":[{"path":"manifest/s2_30_platform_adapter_receipt.json","sealed_by_child_release":false},{"path":"manifest/s2_30_model_benchmark_receipt.json","sealed_by_child_release":false},{"path":"manifest/s2_30_legal_review_receipt.json","sealed_by_child_release":false}],"legacy_stage2_v0_v3_runtime_dependency_count":0,"parent_stage2_release_ref":{"path":"manifest/stage2_release.json","sha256":"579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81"},"release_class":"CHILD_OFFLINE_CONTRACT_RELEASE","release_digest":"6a3ae69aab5ef8d9390398d72627903c9f36042c5078fcad5f95ca7efb79bec0","release_id":"STAGE2-S2_30-OFFLINE-CONTRACT","release_status":"OFFLINE_CONTRACT_COMPLETE_LIVE_ADMISSION_PENDING","schema_version":"stage2_s2_30_release.v1","sealed_asset_count":38,"sealed_assets":[{"path":"Stage_2_S2_30.yml","sha256":"6da21b319d10268e5f1959d085173d22017e4910c7222fd5e6daf72628629773","size_bytes":117060},{"path":"agent_scripts/Stage_2_S2_30.yml","sha256":"6da21b319d10268e5f1959d085173d22017e4910c7222fd5e6daf72628629773","size_bytes":117060},{"path":"deployment/stage2_s2_30_llm_binding.yml","sha256":"1d99d933aca1803a681b8fc70eab368fa3b11b5a4f7d384a6be6cd9cb5883512","size_bytes":2893},{"path":"manifest/s2_30_inline_code_receipt.json","sha256":"78fb197d50ec706be35cf1766bb9e9fee1767a8e61109603313821dd6040f552","size_bytes":623},{"path":"manifest/s2_30_inline_prompt_projection_receipt.json","sha256":"2ea4d273eb3aa23550159dc4f821e1c3863fc457a48ed429a7c9522bfa293eac","size_bytes":1471},{"path":"offline_build/build_s2_30_agent_projection.py","sha256":"3ee27b6edee4338ca0d0bd76f5e192d6d1043ea1df3950cb3c8d3b6af5b6433b","size_bytes":50879},{"path":"offline_build/build_s2_30_agent_projection.txt","sha256":"3ee27b6edee4338ca0d0bd76f5e192d6d1043ea1df3950cb3c8d3b6af5b6433b","size_bytes":50879},{"path":"offline_build/validate_s2_30_contract.py","sha256":"30dff7cc1717c792a6da9bcbd3533c82c9bf3902f09fc9fe92a086c2e13694c6","size_bytes":90323},{"path":"offline_build/validate_s2_30_contract.txt","sha256":"30dff7cc1717c792a6da9bcbd3533c82c9bf3902f09fc9fe92a086c2e13694c6","size_bytes":90323},{"path":"prompts/P30_joint_drafting_contract.md","sha256":"5d790fccdacd1b7ce27e25cd52e4c301dbce24ba276def18bca608b5b16362aa","size_bytes":13681},{"path":"runtime/s2_30_dispatch_planner.py","sha256":"7814e64bfdbf5992d8009556b5a81268d99a0300d0b8f419c8c6384d90a906c9","size_bytes":67777},{"path":"runtime/s2_30_dispatch_planner.txt","sha256":"7814e64bfdbf5992d8009556b5a81268d99a0300d0b8f419c8c6384d90a906c9","size_bytes":67777},{"path":"schemas/draft_atoms.schema.json","sha256":"6cbb81f8cc857173efda0ef3a95c3d39c64f057a64ab1927cf6a5967c592d9ce","size_bytes":57750},{"path":"tests/fixtures/s2_30/adverse_fact_worknote_policy.json","sha256":"5b8e9101385f8d65b0332c3be63cb9a22063920675cc86aee51e04da7820aef7","size_bytes":3444},{"path":"tests/fixtures/s2_30/cache_prefix_drift.json","sha256":"845b44cfeb1246f16cd3458965683247efc360b166b31133e3286be400325f98","size_bytes":2109},{"path":"tests/fixtures/s2_30/context_reference_envelope.json","sha256":"a1d6ba9752b9d4fb479dfaaa763174988f38d87890db9487db9de556d3eade60","size_bytes":4804},{"path":"tests/fixtures/s2_30/counter_performance_and_declaration.json","sha256":"cfa3a8439ca938b05768798dfee39a3cc1e4980d5550526c787843622516da90","size_bytes":3322},{"path":"tests/fixtures/s2_30/follower_batch_dispatch.json","sha256":"3dffaf9862e15f2fe906ca63abb3be61e49177fb58abb4c4a7a8b25db4e4493b","size_bytes":2832},{"path":"tests/fixtures/s2_30/invalid_forbidden_output.json","sha256":"a2308629fc09f75ab226b89374c78323f62a9dbe296aebdd83170a0cfb926e09","size_bytes":2741},{"path":"tests/fixtures/s2_30/invalid_preassembled_prompt_item.json","sha256":"6655402c669e5b40f2e7028a5c0c89571d8e1597dbdef567b4c9d8e2eed15a79","size_bytes":2204},{"path":"tests/fixtures/s2_30/invalid_reference_output.json","sha256":"eb2982a09f4948baadc27ae49c4f125426074333ea4a626e9c56ddc5c24ce273","size_bytes":2663},{"path":"tests/fixtures/s2_30/owner_singleton_dispatch.json","sha256":"38f9c364591fcdfe60d0dea9f69eb86b2f3b883929f6d60d06a7c35ff376fca6","size_bytes":8448},{"path":"tests/fixtures/s2_30/partial_write_publish_barrier.json","sha256":"89f8318c7dbec7bf0095e34194f0a585ea5f4cbce9826af64c30d370612fa1f5","size_bytes":3999},{"path":"tests/fixtures/s2_30/regression_manifest.json","sha256":"a4741c9eeff95d50a84ad7ba6c2d80b10bdb6ffd40a15fd90b2413ab4ac7abd3","size_bytes":3380},{"path":"tests/fixtures/s2_30/rule_requirement_admission_gap.json","sha256":"27dfad63f3508c5d40521270707d84b2bc0c58f035f47d0cde1ae2abc54f9a15","size_bytes":4298},{"path":"tests/fixtures/s2_30/technical_failure.json","sha256":"bdcc6410e7515edc73d6b154d5b618b3ec34273ddc7269dc3e3ce55a6eb35fa6","size_bytes":2719},{"path":"tests/fixtures/s2_30/valid_joint_draft_output.json","sha256":"0135616c9375602693af8e12c3c16cf2031eaf3d9b74783bec9b5065846327e8","size_bytes":12982},{"path":"tests/s2_30/test_agent_contract.py","sha256":"e7d0f069f8c60ff5c5194a9ea9289376e2fd81a50d1b4b18b1b6abf5f2827529","size_bytes":11630},{"path":"tests/s2_30/test_agent_contract.txt","sha256":"e7d0f069f8c60ff5c5194a9ea9289376e2fd81a50d1b4b18b1b6abf5f2827529","size_bytes":11630},{"path":"tests/s2_30/test_dispatch_materialization.py","sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","size_bytes":13911},{"path":"tests/s2_30/test_dispatch_materialization.txt","sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","size_bytes":13911},{"path":"tests/s2_30/test_draft_atom_contract.py","sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","size_bytes":10484},{"path":"tests/s2_30/test_draft_atom_contract.txt","sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","size_bytes":10484},{"path":"tests/s2_30/test_prompt_cache_and_boundaries.py","sha256":"9063ca0a247cf06f55e94e586a7ab8ac21facd9f6c607ce4799047aea365e287","size_bytes":5142},{"path":"tests/s2_30/test_prompt_cache_and_boundaries.txt","sha256":"9063ca0a247cf06f55e94e586a7ab8ac21facd9f6c607ce4799047aea365e287","size_bytes":5142},{"path":"tests/s2_30/test_release_adapter_retry.py","sha256":"b15505567db55689527056d608a1cb12d3c605e9df860afba607a6e3e276a0ef","size_bytes":9241},{"path":"tests/s2_30/test_release_adapter_retry.txt","sha256":"b15505567db55689527056d608a1cb12d3c605e9df860afba607a6e3e276a0ef","size_bytes":9241},{"path":"workflows/S2_30_claim_group_draft_map.yml","sha256":"498715993d796f82a8c9e790a62bee6885c05813488fd0a11200f46c07665162","size_bytes":12932}]} +{"admission_status":{"legal_review":"PENDING_KOREAN_LAWYER_REVIEW","model_benchmark":"PENDING_MODEL_BENCHMARK","platform_adapter":"PENDING_EXTERNAL_PLATFORM_BINDING","production_execution":"BLOCKED"},"authorization_status":"OFFLINE_VALIDATION_ONLY","external_admission_evidence":[{"path":"manifest/s2_30_platform_adapter_receipt.json","sealed_by_child_release":false},{"path":"manifest/s2_30_model_benchmark_receipt.json","sealed_by_child_release":false},{"path":"manifest/s2_30_legal_review_receipt.json","sealed_by_child_release":false}],"legacy_stage2_v0_v3_runtime_dependency_count":0,"parent_stage2_release_ref":{"path":"manifest/stage2_release.json","sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53"},"release_class":"CHILD_OFFLINE_CONTRACT_RELEASE","release_digest":"723a738d2fd6c181fa4afc1a59a50e06f62561934ff7671ab18b080e5847e4b4","release_id":"STAGE2-S2_30-OFFLINE-CONTRACT","release_status":"OFFLINE_CONTRACT_COMPLETE_LIVE_ADMISSION_PENDING","schema_version":"stage2_s2_30_release.v1","sealed_asset_count":39,"sealed_assets":[{"path":"Stage_2_S2_30.yml","sha256":"d0804526941207395c9b64a314b124ff8e919c6852e828d829dc45a9feb3ccdd","size_bytes":117060},{"path":"agent_scripts/Stage_2_S2_30.yml","sha256":"d0804526941207395c9b64a314b124ff8e919c6852e828d829dc45a9feb3ccdd","size_bytes":117060},{"path":"deployment/stage2_s2_30_llm_binding.yml","sha256":"7cf19e7dd8d3ad58251e20edc56e11fde3bffb3936997538eb09301da06189dc","size_bytes":2893},{"path":"manifest/s2_30_inline_code_receipt.json","sha256":"8d1618771cf1f72aa3c6a5a4544fe6b6e949ccc7ecfef56f166561971beee896","size_bytes":623},{"path":"manifest/s2_30_inline_prompt_projection_receipt.json","sha256":"1aa650d3c389ba27ce43e514295c7c2ce629583dc96220618fd97dea399d0757","size_bytes":1471},{"path":"offline_build/build_s2_30_agent_projection.py","sha256":"665b6f00bae567ea67e3758be047f594fedae2c22a5047b30009fcd5d2c495b2","size_bytes":56585},{"path":"offline_build/build_s2_30_agent_projection.txt","sha256":"665b6f00bae567ea67e3758be047f594fedae2c22a5047b30009fcd5d2c495b2","size_bytes":56585},{"path":"offline_build/validate_s2_30_contract.py","sha256":"14e4eefb73d40d004c95017c82cdc23ac1c1c0a54ea34562dcf322f6364ae27a","size_bytes":104292},{"path":"offline_build/validate_s2_30_contract.txt","sha256":"14e4eefb73d40d004c95017c82cdc23ac1c1c0a54ea34562dcf322f6364ae27a","size_bytes":104292},{"path":"prompts/P30_joint_drafting_contract.md","sha256":"5d790fccdacd1b7ce27e25cd52e4c301dbce24ba276def18bca608b5b16362aa","size_bytes":13681},{"path":"runtime/s2_30_dispatch_planner.py","sha256":"1f7f3b842afbd3f1034f094d6341288effc9804a03920ada4bf8cfd512464e4c","size_bytes":67777},{"path":"runtime/s2_30_dispatch_planner.txt","sha256":"1f7f3b842afbd3f1034f094d6341288effc9804a03920ada4bf8cfd512464e4c","size_bytes":67777},{"path":"schemas/draft_atoms.schema.json","sha256":"5107b64f01ffb3633a829c10652747760a5035c9cc07227c546e3f543005eda9","size_bytes":68470},{"path":"tests/fixtures/s2_30/adverse_fact_worknote_policy.json","sha256":"5b8e9101385f8d65b0332c3be63cb9a22063920675cc86aee51e04da7820aef7","size_bytes":3444},{"path":"tests/fixtures/s2_30/cache_prefix_drift.json","sha256":"845b44cfeb1246f16cd3458965683247efc360b166b31133e3286be400325f98","size_bytes":2109},{"path":"tests/fixtures/s2_30/context_reference_envelope.json","sha256":"a1d6ba9752b9d4fb479dfaaa763174988f38d87890db9487db9de556d3eade60","size_bytes":4804},{"path":"tests/fixtures/s2_30/counter_performance_and_declaration.json","sha256":"cfa3a8439ca938b05768798dfee39a3cc1e4980d5550526c787843622516da90","size_bytes":3322},{"path":"tests/fixtures/s2_30/follower_batch_dispatch.json","sha256":"3dffaf9862e15f2fe906ca63abb3be61e49177fb58abb4c4a7a8b25db4e4493b","size_bytes":2832},{"path":"tests/fixtures/s2_30/invalid_forbidden_output.json","sha256":"a2308629fc09f75ab226b89374c78323f62a9dbe296aebdd83170a0cfb926e09","size_bytes":2741},{"path":"tests/fixtures/s2_30/invalid_preassembled_prompt_item.json","sha256":"6655402c669e5b40f2e7028a5c0c89571d8e1597dbdef567b4c9d8e2eed15a79","size_bytes":2204},{"path":"tests/fixtures/s2_30/invalid_reference_output.json","sha256":"eb2982a09f4948baadc27ae49c4f125426074333ea4a626e9c56ddc5c24ce273","size_bytes":2663},{"path":"tests/fixtures/s2_30/owner_singleton_dispatch.json","sha256":"38f9c364591fcdfe60d0dea9f69eb86b2f3b883929f6d60d06a7c35ff376fca6","size_bytes":8448},{"path":"tests/fixtures/s2_30/partial_write_publish_barrier.json","sha256":"0d878b946ebf810e8d0d8da74af33e56f35e164b04076a3867344b95d5f953eb","size_bytes":3352},{"path":"tests/fixtures/s2_30/persisted_handoff_chain.json","sha256":"54d6d781a60640744cba4b9c2f88a0013a6e58656c9c80a809e39fd4ba7c1097","size_bytes":2016},{"path":"tests/fixtures/s2_30/regression_manifest.json","sha256":"43e5b20ef4389da9c03b8062ce8bfacf2cd880d2efa2a1cbe1e901f4111f64ea","size_bytes":3584},{"path":"tests/fixtures/s2_30/rule_requirement_admission_gap.json","sha256":"27dfad63f3508c5d40521270707d84b2bc0c58f035f47d0cde1ae2abc54f9a15","size_bytes":4298},{"path":"tests/fixtures/s2_30/technical_failure.json","sha256":"bdcc6410e7515edc73d6b154d5b618b3ec34273ddc7269dc3e3ce55a6eb35fa6","size_bytes":2719},{"path":"tests/fixtures/s2_30/valid_joint_draft_output.json","sha256":"0135616c9375602693af8e12c3c16cf2031eaf3d9b74783bec9b5065846327e8","size_bytes":12982},{"path":"tests/s2_30/test_agent_contract.py","sha256":"26a37b0b5fa6c4273ed7deff6b0429e3223869533fc2384f4c364fe88d554da5","size_bytes":12199},{"path":"tests/s2_30/test_agent_contract.txt","sha256":"26a37b0b5fa6c4273ed7deff6b0429e3223869533fc2384f4c364fe88d554da5","size_bytes":12199},{"path":"tests/s2_30/test_dispatch_materialization.py","sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","size_bytes":13911},{"path":"tests/s2_30/test_dispatch_materialization.txt","sha256":"9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665","size_bytes":13911},{"path":"tests/s2_30/test_draft_atom_contract.py","sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","size_bytes":10484},{"path":"tests/s2_30/test_draft_atom_contract.txt","sha256":"cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923","size_bytes":10484},{"path":"tests/s2_30/test_prompt_cache_and_boundaries.py","sha256":"1b9b562418bc24be6db09dc1d35f71845033adbc693aeb41fbba07be16fa7c9d","size_bytes":6284},{"path":"tests/s2_30/test_prompt_cache_and_boundaries.txt","sha256":"1b9b562418bc24be6db09dc1d35f71845033adbc693aeb41fbba07be16fa7c9d","size_bytes":6284},{"path":"tests/s2_30/test_release_adapter_retry.py","sha256":"e5af75d54f236eb8ba99b194a06aa31f02fddd5c6aa9ff7385401905359b292c","size_bytes":18566},{"path":"tests/s2_30/test_release_adapter_retry.txt","sha256":"e5af75d54f236eb8ba99b194a06aa31f02fddd5c6aa9ff7385401905359b292c","size_bytes":18566},{"path":"workflows/S2_30_claim_group_draft_map.yml","sha256":"b266e7b7ae8939b087bfdb7b34fff8b9c6011c835560ab690991d856ced0cc15","size_bytes":15221}]} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_40_inline_code_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_40_inline_code_receipt.json new file mode 100644 index 00000000..69e8ab25 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_40_inline_code_receipt.json @@ -0,0 +1 @@ +{"authoring":{"path":"Stage_2_S2_40.yml","sha256":"5cbe2ac9aa73d95a5fa4e6cf71d7d8f0ad83aa05536f573c13e42505ef5d46f7","size_bytes":249967,"unique_key_parse":"PASS"},"authoring_rewritten":false,"build_kind":"OFFLINE_AUTHORING_PROJECTION","canonical_code":{"ast_status":"PASS","code_sha256":"e521e1a65294a769cd6bf20edb159f8720c105b60cb769885aa416c8c763dcef","code_size_bytes":200946,"compile_status":"PASS","encoding":"UTF-8","expected_parent_stage2_release_sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53","external_python_source_ref_count":0,"external_url_count":0,"extraction_transform":"NONE","forbidden_dynamic_call_count":0,"forbidden_import_count":0,"imports":["__future__","base64","binascii","contextlib","datetime","hashlib","httpx","io","itertools","json","pathlib","re","sys","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":"a8d6450b5a40308b3c2af5227fd3bc0c4f575dd8ea17b10b5bb7d6687ebc9d9e","path":"Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml","sha256":"5cbe2ac9aa73d95a5fa4e6cf71d7d8f0ad83aa05536f573c13e42505ef5d46f7","size_bytes":249967},"expected_parent_stage2_release_sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53","full_code_mirrors":[{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_40_commit.py","sha256":"e521e1a65294a769cd6bf20edb159f8720c105b60cb769885aa416c8c763dcef","size_bytes":200946},{"byte_identical_to_canonical_code":true,"path":"Default_Agent/Stage_2_Clean/runtime/s2_40_commit.txt","sha256":"e521e1a65294a769cd6bf20edb159f8720c105b60cb769885aa416c8c763dcef","size_bytes":200946}],"parity_status":"PASS","schema_version":"stage2_s2_40_inline_code_receipt.v1","source_of_truth":"Stage_2_S2_40.yml","task_contract":{"agent":{"name":"Stage_2_S2_40","version":"1.0.0"},"authoring_rewritten":false,"canonical_task_semantics_sha256":"a8d6450b5a40308b3c2af5227fd3bc0c4f575dd8ea17b10b5bb7d6687ebc9d9e","code_mirrors_byte_identical":true,"exactly_one_code_executor_run_code":true,"exactly_one_stage":true,"exactly_one_task":true,"mcp_servers":{"code-executor":{"type":"streamable-http","url":"https://code-executor.mcp.eroomai.com/mcp"},"localdocs":{"type":"streamable-http","url":"http://mcp-localdocs:8012/mcp"}},"projection_byte_identical_to_authoring":true,"stage":{"name":"S2_40","nexts":[],"prevs":[]},"task":{"code_sha256":"e521e1a65294a769cd6bf20edb159f8720c105b60cb769885aa416c8c763dcef","mcp":"code-executor","parameters":{"language":"python","network":"agent-network","requirements":"httpx==0.28.1","timeout":300},"task_name":"Task_S2_40_deterministic_finalizer","tool_name":"run_code"},"task_procedure":{"IN":{"nexts":["Task_S2_40_deterministic_finalizer"],"wait_until":[]},"OUT":{"nexts":[],"wait_until":["Task_S2_40_deterministic_finalizer"]},"Task_S2_40_deterministic_finalizer":{"nexts":["OUT"],"wait_until":["IN"]}}},"workflow_id":"S2_40"} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_40_parent_member_paths.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_40_parent_member_paths.json new file mode 100644 index 00000000..03a993fe --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/s2_40_parent_member_paths.json @@ -0,0 +1,45 @@ +[ + "manifest/s2_40_parent_member_paths.json", + "offline_build/build_s2_40_inline_projection.py", + "offline_build/build_s2_40_inline_projection.txt", + "runtime/c45_document_assembler.py", + "runtime/c45_document_assembler.txt", + "runtime/rendering/closed_renderer.py", + "runtime/rendering/closed_renderer.txt", + "runtime/validation/invariant_runner.py", + "runtime/validation/invariant_runner.txt", + "schemas/migration_regression.schema.json", + "schemas/package.schema.json", + "schemas/review_status.schema.json", + "tests/fixtures/s2_40/candidate_digest_noncycle.json", + "tests/fixtures/s2_40/cost_provisional_execution_numbering.json", + "tests/fixtures/s2_40/exhibit_object_party_title_completeness.json", + "tests/fixtures/s2_40/part_set_missing_duplicate_or_cross_group.json", + "tests/fixtures/s2_40/partial_write_readback_barrier.json", + "tests/fixtures/s2_40/regression_manifest.json", + "tests/fixtures/s2_40/relief_cause_crossmatch_mutations.json", + "tests/fixtures/s2_40/renderer_ast_slot_branch_mutations.json", + "tests/fixtures/s2_40/review_policy_state_aggregation.json", + "tests/fixtures/s2_40/review_receipt_approve_resume.json", + "tests/fixtures/s2_40/review_receipt_content_change_supersede.json", + "tests/fixtures/s2_40/review_receipt_missing_or_invalid.json", + "tests/fixtures/s2_40/same_binding_idempotence_and_commit_conflict.json", + "tests/fixtures/s2_40/v01_v18_invariant_matrix.json", + "tests/fixtures/s2_40/valid_full_candidate_and_commit.json", + "tests/fixtures/s2_40/valid_status_only_diagnostic.json", + "tests/s2_40/test_agent_and_inline_parity.py", + "tests/s2_40/test_agent_and_inline_parity.txt", + "tests/s2_40/test_c40_reduce_and_conservation.py", + "tests/s2_40/test_c40_reduce_and_conservation.txt", + "tests/s2_40/test_c45_closed_render.py", + "tests/s2_40/test_c45_closed_render.txt", + "tests/s2_40/test_commit_barrier_and_idempotence.py", + "tests/s2_40/test_commit_barrier_and_idempotence.txt", + "tests/s2_40/test_release_closure.py", + "tests/s2_40/test_release_closure.txt", + "tests/s2_40/test_review_state_machine.py", + "tests/s2_40/test_review_state_machine.txt", + "tests/s2_40/test_v01_v18.py", + "tests/s2_40/test_v01_v18.txt", + "workflows/S2_40_final_review_render_and_commit.yml" +] diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json index 410c9de9..249b6a20 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json @@ -1 +1 @@ -{"admission_status":"PENDING","backend_capability_receipt_sha256":"PENDING_SEQUENTIAL_BIND","embedded_task_admissions":[{"admission_scope":"CODE_EXECUTOR_HELPER_ONLY","binding_id":"S2-BINDING-S2_30-DISPATCH-PLANNER-V1","execution_unit_id":"S2_30::Task_S2_30_dispatch_planner","host_stage_id":"S2_30","inline_code_receipt_ref":{"asset_id":"RECEIPT-S2_30-INLINE-CODE","binding_status":"BOUND","path":"manifest/s2_30_inline_code_receipt.json","schema_id":"stage2_s2_30_inline_code_receipt.v1","sha256":"78fb197d50ec706be35cf1766bb9e9fee1767a8e61109603313821dd6040f552"},"task_name":"Task_S2_30_dispatch_planner"}],"executor_binding_sha256":"bfd84ddedb488e7391341041a739437d88372e3c9ed740e5dfb31ae3a138a936","parent_release_sha256":"579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81","present_deterministic_stage_ids":["S2_00","S2_20"],"schema_version":"stage2_deterministic_admission_receipt.v1","signature":"PENDING_EXTERNAL_SIGNATURE","signature_verification_status":"PENDING_EXTERNAL_SIGNATURE","signed_payload_sha256":"PENDING_SEQUENTIAL_BIND","stage_receipts":[{"asset_id":"RECEIPT-S2_00-INLINE-CODE","binding_status":"BOUND","path":"manifest/s2_00_inline_code_receipt.json","schema_id":"stage2_s2_00_inline_code_receipt.v2","sha256":"ced01ef57a2e5341b1f7ddbf810ff3c6fb85fbb3cf7cf80836328a8a971835b4"},{"asset_id":"RECEIPT-S2_20-INLINE-CODE","binding_status":"BOUND","path":"manifest/s2_20_inline_code_receipt.json","schema_id":"stage2_s2_20_inline_code_receipt.v1","sha256":"60000d2412a757e9b2ab2525eedb08ebda20ec02a49f5b1b0c4e89e6a0aeca2b"}]} +{"admission_status":"PENDING","backend_capability_receipt_sha256":"PENDING_SEQUENTIAL_BIND","embedded_task_admissions":[{"admission_scope":"CODE_EXECUTOR_HELPER_ONLY","binding_id":"S2-BINDING-S2_30-DISPATCH-PLANNER-V1","execution_unit_id":"S2_30::Task_S2_30_dispatch_planner","host_stage_id":"S2_30","inline_code_receipt_ref":{"asset_id":"RECEIPT-S2_30-INLINE-CODE","binding_status":"BOUND","path":"manifest/s2_30_inline_code_receipt.json","schema_id":"stage2_s2_30_inline_code_receipt.v1","sha256":"8d1618771cf1f72aa3c6a5a4544fe6b6e949ccc7ecfef56f166561971beee896"},"task_name":"Task_S2_30_dispatch_planner"}],"executor_binding_sha256":"a1062e9db242747c75a4362fb95eeba6c65f78ac647d4571ed774d2ee3af40f7","parent_release_sha256":"9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53","present_deterministic_stage_ids":["S2_00","S2_20","S2_40"],"schema_version":"stage2_deterministic_admission_receipt.v1","signature":"PENDING_EXTERNAL_SIGNATURE","signature_verification_status":"PENDING_EXTERNAL_SIGNATURE","signed_payload_sha256":"PENDING_SEQUENTIAL_BIND","stage_receipts":[{"asset_id":"RECEIPT-S2_00-INLINE-CODE","binding_status":"BOUND","path":"manifest/s2_00_inline_code_receipt.json","schema_id":"stage2_s2_00_inline_code_receipt.v2","sha256":"36af21949e5ef53a3d39df8ea9491c64da43abcc4f5e42e13db9bb391da843b8"},{"asset_id":"RECEIPT-S2_20-INLINE-CODE","binding_status":"BOUND","path":"manifest/s2_20_inline_code_receipt.json","schema_id":"stage2_s2_20_inline_code_receipt.v1","sha256":"65e29f10f065cdd77281aa47acaf341edb38b0595aab0aa9f04bbee3a4718608"},{"asset_id":"RECEIPT-S2_40-INLINE-CODE","binding_status":"BOUND","path":"manifest/s2_40_inline_code_receipt.json","schema_id":"stage2_s2_40_inline_code_receipt.v1","sha256":"9bd0cfaee8d9e78480ab80a2fa541414c7ad0565439fa0f4661701fcdfde6526"}]} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/stage2_release.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/stage2_release.json index 78d09ac1..edb1a98c 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/stage2_release.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/manifest/stage2_release.json @@ -1 +1 @@ -{"adapter_decisions":[{"adapter_id":"S2A-SIGNAL-ALL-V1","adapter_kind":"SIGNAL_ALL_EXPANSION","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"file_conservation_equation":"semantic_file_rows + integrity_only_file_rows = Counter(signal_manifest.files[])","global_signal_id_uniqueness_assumed":false,"integrity_only_kinds":["compatibility_view"],"manifest_selector":"/downstream_read_sets/stage2","physical_path_rule":"U/signals/","record_conservation_equation":"used_record_occurrences + unused_record_occurrences + unmapped_record_occurrences = records_from_semantic_files","record_occurrence_key":["manifest_transaction_id","file_path","record_ordinal","signal_id"],"row_order":"PRESERVE_MANIFEST_ORDER","row_source":"/files","semantic_kinds":["canonical","domain_signal"],"sentinel":["ALL"]},"schema_ref":"schemas/ingress.schema.json#/$defs/all_expansion_contract"},{"adapter_id":"S2A-DUAL-SG01-V1","adapter_kind":"DUAL_SG01_PROJECTION","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"comparison":"PARSED_CANONICAL_PROJECTION_EQUAL","payload_root":"/domain_activation_manifest","projection_json_pointers":["/schema_version","/signal_id","/status","/registry_version","/registry_index_sha256","/screening_sha256","/domain_entries","/active_domain_ids","/supporting_domain_ids","/monitor_domain_ids","/expected_runnable_domain_ids","/required_calculation_domains","/unrouted_material","/conservation_gate","/fail_open_policy","/review_items","/contract_guards"],"raw_hash_policy":"PRESERVE_AND_VERIFY_SEPARATELY","routing_path":"routing/domain_activation_manifest.json","set_semantics_json_pointers":["/active_domain_ids","/supporting_domain_ids","/monitor_domain_ids","/expected_runnable_domain_ids","/required_calculation_domains"],"signal_path":"signals/domain_activation_manifest.json"},"schema_ref":"schemas/ingress.schema.json#/$defs/dual_sg01_projection_contract"},{"adapter_id":"S2A-P1-HANDOFF-FLAT-V1","adapter_kind":"HANDOFF","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"count_field_required":false,"logical_input_id":"P1_REVIEW_HANDOFF","p1_digest_keys":["evidence_indexed_sha256","evidence_event_candidates_sha256","b1_gate_sha256","b2_gate_sha256","screening_sha256","activation_manifest_sha256","registry_index_sha256"],"review_items_json_pointer":"/review_items","schema_version":"stage1_part1_soft_gate_handoff.v1","seal_sources":["routing/domain_screening.json","routing/domain_activation_manifest.json","domains/_registry_index.json"],"source_stage":"P1","status_json_pointer":"/handoff_status","wrapper_json_pointer":""},"schema_ref":"schemas/ingress.schema.json#/$defs/handoff_adapter_contract"},{"adapter_id":"S2A-P2-HANDOFF-FLAT-V1","adapter_kind":"HANDOFF","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"count_field_required":false,"logical_input_id":"P2_REVIEW_HANDOFF","review_items_json_pointer":"/review_items","schema_version":"stage1_part2_review_handoff.v1","seal_sources":["BO.json","signals/signal_manifest.json"],"source_stage":"P2","status_json_pointer":"/status","wrapper_json_pointer":""},"schema_ref":"schemas/ingress.schema.json#/$defs/handoff_adapter_contract"},{"adapter_id":"S2A-P3-HANDOFF-WRAPPED-V1","adapter_kind":"HANDOFF","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"count_field_required":true,"logical_input_id":"P3_REVIEW_HANDOFF","review_items_json_pointer":"/review_items","schema_version":"stage1_part3_review_handoff.v1","seal_sources":["legal_effect_structures.json","validation_assets/routing/part3_receipt.json"],"source_stage":"P3","status_json_pointer":"/status","wrapper_json_pointer":"/stage1_part3_review_handoff"},"schema_ref":"schemas/ingress.schema.json#/$defs/handoff_adapter_contract"},{"adapter_id":"S2A-P4-HANDOFF-WRAPPED-V1","adapter_kind":"HANDOFF","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"count_field_required":true,"logical_input_id":"P4_REVIEW_HANDOFF","review_items_json_pointer":"/review_items","schema_version":"stage1_part4_review_handoff.v1","seal_sources":["Fact_Ledger_base.json","validation_assets/routing/part4_receipt.json","stage1_tmp/fact_ledger/fact_ledger_writer_report.json"],"source_stage":"P4","status_json_pointer":"/status","wrapper_json_pointer":"/stage1_part4_review_handoff"},"schema_ref":"schemas/ingress.schema.json#/$defs/handoff_adapter_contract"},{"adapter_id":"S2-REVIEW-MAP-V1","adapter_kind":"REVIEW_NORMALIZATION","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"aggregate_handoff_status_never_resolves_item":true,"handoff_status_mappings":[{"source_stage":"P1","source_value":"READY_NO_REVIEW","technical_disposition":"AVAILABLE"},{"source_stage":"P1","source_value":"READY_WITH_REVIEW","technical_disposition":"AVAILABLE_WITH_ISSUES"},{"source_stage":"P1","source_value":"BLOCKED","technical_disposition":"UNAVAILABLE"},{"source_stage":"P2","source_value":"PENDING_FINALIZE","technical_disposition":"AVAILABLE_WITH_ISSUES"},{"source_stage":"P2","source_value":"FINALIZED","technical_disposition":"AVAILABLE"},{"source_stage":"P3","source_value":"OPEN","technical_disposition":"AVAILABLE_WITH_ISSUES"},{"source_stage":"P3","source_value":"FINALIZED","technical_disposition":"AVAILABLE"},{"source_stage":"P4","source_value":"OPEN","technical_disposition":"AVAILABLE_WITH_ISSUES"},{"source_stage":"P4","source_value":"FINALIZED","technical_disposition":"AVAILABLE"}],"mappings":[{"mapping_id":"S2RM-001","normalized_partition":"SUPPORTED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"SUPPORTED","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-002","normalized_partition":"CONDITIONAL","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"CONDITIONAL","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-003","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"UNRESOLVED","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-004","normalized_partition":"EXCLUDED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"EXCLUDED","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-005","normalized_partition":"SUPPORTED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"observed","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-006","normalized_partition":"CONDITIONAL","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"inferred","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-007","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"contested","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-008","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"missing_required","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-009","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"review","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-010","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"NO_SUPPORT","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-011","normalized_partition":"CONDITIONAL","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"info","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-012","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"review","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-013","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"SOFT_WARNING","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-014","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"hard_warning","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-015","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"HARD_WARNING","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-016","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"block","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-017","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"BLOCK","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"}],"normalized_partitions":["SUPPORTED","CONDITIONAL","UNRESOLVED","EXCLUDED","UNMAPPED"],"resolution_inference_allowed":false,"unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},"schema_ref":"schemas/review_status.schema.json#/$defs/review_mapping_row"},{"adapter_id":"S2A-BO-V8-LIST-V1","adapter_kind":"PRODUCER_SHAPE","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"logical_input_id":"BO","open_source_fields_policy":"PRESERVE_UNMODELED_FIELDS_WITH_RAW_HASH","producer_id":"Task_C_BO_F0_final_bo_compiler_gate_writer","required_item_fields":["BO_ID","id","BOType","ActionType","JuristicAct","Action","Reason","PriorAct","ReasonRefs","Legal_Keywords","core_field_base","amount","EvidenceTitles","Evidence","source_evidence_indexes","provenance","downstream_seed_refs","extensions"],"required_root_fields":[],"root_shape":"ARRAY","schema_contract_version":null},"schema_ref":"schemas/ingress.schema.json#/$defs/producer_shape_adapter"},{"adapter_id":"S2A-EVIDENCE-V3-ENVELOPE-V1","adapter_kind":"PRODUCER_SHAPE","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"logical_input_id":"EVIDENCE_INDEXED","open_source_fields_policy":"PRESERVE_UNMODELED_FIELDS_WITH_RAW_HASH","producer_id":"Task_B1_quality_gate_evidence_indexed","required_root_fields":["schema_contract_version","items"],"root_shape":"OBJECT_ENVELOPE","schema_contract_version":"evidence_indexed.v3"},"schema_ref":"schemas/ingress.schema.json#/$defs/producer_shape_adapter"},{"adapter_id":"S2A-EVENTS-V1-ENVELOPE-V1","adapter_kind":"PRODUCER_SHAPE","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"logical_input_id":"EVIDENCE_EVENT_CANDIDATES","open_source_fields_policy":"PRESERVE_UNMODELED_FIELDS_WITH_RAW_HASH","producer_id":"Task_B2_quality_gate_event_candidates","required_root_fields":["schema_version","items"],"root_shape":"OBJECT_ENVELOPE","schema_contract_version":"evidence_event_candidates.v1"},"schema_ref":"schemas/ingress.schema.json#/$defs/producer_shape_adapter"},{"adapter_id":"S2A-DOMAIN-CONFIG-V1","adapter_kind":"DOMAIN_CONFIG","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"accepted_schema_version":"stage1_domain_config.v1","depends_on_legal_dependency_allowed":false,"rebuttal_slot_synthesis_allowed":false,"required_slot_fields":["element_slots","opposing_fact_slots","defense_map","calculation_bindings","emits_signals"],"undeclared_slot_policy":"PRESERVE_AS_PROPOSED_NEW_SLOT_ISSUE"},"schema_ref":"schemas/ingress.schema.json#/$defs/domain_config_adapter_contract"},{"adapter_id":"S2A-DOMAIN-CONFIG-V2","adapter_kind":"DOMAIN_CONFIG","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"accepted_schema_version":"stage1_domain_config.v2","depends_on_legal_dependency_allowed":false,"rebuttal_slot_synthesis_allowed":false,"required_slot_fields":["element_slots","opposing_fact_slots","defense_map","calculation_bindings","emits_signals"],"undeclared_slot_policy":"PRESERVE_AS_PROPOSED_NEW_SLOT_ISSUE"},"schema_ref":"schemas/ingress.schema.json#/$defs/domain_config_adapter_contract"},{"adapter_id":"S2A-FACT-LEDGER-CURRENT-V8-V1","adapter_kind":"FACT_LEDGER","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"bo_source_bo_id_multiset_equality_required":true,"fact_id_pattern":"^F-[0-9]{3,}$","legacy_adapter_status":"DISABLED_NO_APPROVED_ADAPTER","producer_generation":"CURRENT_V8","required_row_fields":["fact_id","source_bo_id","domain_effects","calculation_requests"],"root_shape":"ARRAY"},"schema_ref":"schemas/ingress.schema.json#/$defs/fact_ledger_adapter_contract"},{"adapter_id":"PA-SG-COMPILER-001","adapter_kind":"PRODUCER_ALIAS","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"bidirectional_match_allowed":true,"global_alias_allowed":false,"orchestration_producer_id":"Task_C_BO_S0_signal_bundle_writer","schema_writer_id":"Task_C_BO_S0_canonical_signal_compiler","scope":"STAGE1_PART2_SIGNAL_TRANSACTION_ONLY"},"schema_ref":"schemas/ingress.schema.json#/$defs/producer_alias_contract"}],"authoring_root":"Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean","authorization_status":"DEV_VALIDATION_ONLY","bundle":{"active_profile_policy":"CASE_RUN_EXACT_RELEASE_SELECTED_SUBSET_ONLY","authority_release_status":"DEV_UNAVAILABLE","context_cohort_policy_id":"S2-CACHE-STRUCTURED-CONTEXT-HANDOFF-V2","downstream_hybrid_status":"OFFLINE_HYBRID_IMPLEMENTED_LIVE_ADMISSION_PENDING","executable":false,"handoff_contract_version":"S2_00_STRUCTURED_CONTEXT_HANDOFF_V2","mode":"STRUCTURAL_FIXTURE","reason_codes":["STRUCTURAL_FIXTURE_NOT_EXECUTABLE","AUTHORITY_RELEASE_UNAVAILABLE","S2_10_PLATFORM_MODEL_AND_LEGAL_ADMISSION_PENDING","DIRECT_MCP_LIVE_ADMISSION_PENDING"],"s2_10_agent_ref":{"asset_id":"AGENT-S2_10-HYBRID-OPAQUE","binding_status":"BOUND","path":"agent_scripts/Stage_2_S2_10.yml","schema_id":"liti_agent_yaml.v1","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272"},"s2_10_agent_sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","s2_10_llm_binding_ref":{"asset_id":"BINDING-S2_10-LLM-OPAQUE","binding_status":"BOUND","path":"deployment/stage2_s2_10_llm_binding.yml","schema_id":"stage2_s2_10_llm_binding.v2","sha256":"9d20b264e753c2f52e8d096edab363ace0fecf2ec8357605d1a9cb47c9c2b930"},"s2_10_llm_binding_sha256":"9d20b264e753c2f52e8d096edab363ace0fecf2ec8357605d1a9cb47c9c2b930","selected_context_ordered_refs_sha256":"37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570","selected_context_refs":[]},"dependency_locks":{"downstream_availability":[{"asset_id":"CASE-TYPE-COVERAGE","binding_status":"BOUND","path":"manifest/case_type_coverage.json","schema_id":"stage2.case_type_coverage.v1","sha256":"34d6f758fc1486fa7330ede376e65b9448a6eaa971bd21472b0e4b7d9a5b8cba"},{"asset_id":"CORPUS-RELEASE","binding_status":"BOUND","path":"manifest/corpus_release.json","schema_id":"stage2.corpus_release.v1","sha256":"27d0c83e7a95342efdbe5be675b6d5b7d0ff8695eeec022ebc5aded3359fc981"}],"stage1":{"closure_scope":"REFERENCED_55_ONLY_NOT_FULL_STAGE1_RUNTIME_RELEASE","closure_snapshot_date":"2026-08-29","concrete_paths":[{"binding_status":"BOUND","lock_id":"S1-DEPLOY-001","path":"runtime_manifest.json","schema_id":"stage1_runtime_manifest.v1","sha256":"8964593a64a9b1bc90122054bb09eb3911827a06ed62dab0d6b7c745e7e18f54","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-002","path":"domains/_registry_index.json","schema_id":null,"sha256":"9f177ebf8860e20e05483967a2037f3baa09c2ac92c69ddeb260c04ca31ebf39","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-003","path":"signals/signal_registry.v2.json","schema_id":"signal_registry.v2","sha256":"4392b40da458102f8dd11b40b40ae3f694b7b5911849b050e2e4118c569e5ab0","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-004","path":"domains/E-00/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"5919f7ea1d7be02666b0c48aa6a66445e6d454fc2fbb21d7fe5154b0a1e68f6f","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-005","path":"domains/E-01/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"b557e92cd1b093bf31792dbcf5b62cab8ad064a65c4421e79f141e06b4cc2192","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-006","path":"domains/E-02/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"be407c980c28226a15406f85b5861b04a4e19a13870513ac6626349fc05ac434","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-007","path":"domains/E-03/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"7d3814f9b50cd5b33ef65a4eb778693552b3685bd369e765e9ac032734ebe23e","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-008","path":"domains/E-04/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"95a8c600cdce5a687f766788af0f763ee1b6a895e6ed80934afd28fe9a107e25","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-009","path":"domains/E-05/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"e50541018f47aa27de2f8b13ec3fa52210cf8456a6feed8356af78c1f1da144a","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-010","path":"domains/E-06/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"1e2bee36cb3c24dd37fc3beb3cf70236d531126c4f62ee97b5b42e55f4b0745c","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-011","path":"domains/E-07/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"22ac562084b1ce231b7257d099c18b6a4619defa2fc42504d590e0bcc494c5f8","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-012","path":"domains/E-08/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"4d545306d42120e8552dd953d4336ef6de828ea827779944ba73acfda3d3a8bb","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-013","path":"domains/E-09/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"7ef7340750094efeb372c397eb3134e21d62dda6988b1f6fa0a197b9963868e0","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-014","path":"domains/E-10/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"e8d4f45fa76ea9e09333256dd4ea36cd3dd963bf60c04814a2cb8dc90d152f0a","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-015","path":"domains/E-11/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"eb78d0188a0a2400307b1c34c8f8703c54cd86dd06b942c1709c44a8630a68e1","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-016","path":"domains/E-12/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"f336accdc6de10cdcc28c1190328054bca402fb77a2a9859d59fbaf5e84dd170","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-017","path":"domains/E-13/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"e27e2e3855b5868a3ec12c7093b872434702f2e465b73c0bfc948b516aa0fc35","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-018","path":"domains/E-14/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"a273148cc17f07d90cda500fa5cb7df30c9cd253f7b86048cf4f63495d36a156","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-019","path":"domains/E-15/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"7f37edddc101a08ed8a0e25f3a2c638e72571edc212ac91d96c1e33c51202a69","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-020","path":"domains/E-16/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"ae9af46ee31b6ef0dafedd35ccd7959a941d67d1a3dcc70e0b13647896873323","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-021","path":"domains/E-17/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"5c61f4486bdc968e4b30734b3c045404f0a711f47ea3abbe6c5c64652fb7f68c","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-022","path":"domains/E-18/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"74ff76148d175929bdeeeced77e9a9922d29b51ad3d00ae6711c43c55717692c","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-023","path":"domains/E-19/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"a8578f54a3fead3bbd35c62d7199b0f8aafb77f5d409a87236a55d2550fbfd37","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-024","path":"domains/E-20/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"29ee14cfe7789f004e6b6978d5360cf1bebe33bf88715df0cb47257993a11d00","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-025","path":"domains/E-21/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"4e1684a843d9e0c5af82f45332ad85abe94eda0c3ff0d578235d892aee39b908","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-026","path":"domains/EC-00/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"fe74de112b73289485dcead7e0fc7d270c794b3cf8a29ee00fab1eb64ba13861","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-027","path":"domains/X1/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"ad2fee7d206018f9a1f66e5fdf40dd67b686f6938099bad1ffc5d538db14ac57","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-028","path":"domains/X2/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"eba7d4671546bd66f1350d144ae0884f8beffb0dffdc147b45b9d5292676d46f","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-029","path":"domains/X3/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"8b67a638ae4a86aca3a2216974242b11ec39790162c9f366edfa91b02c3d270a","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-030","path":"platform/schemas/client_goal_domain_profiles.schema.json","schema_id":null,"sha256":"ae2bfe0d754a09cbae16b2c15bf1518fc23f9e1bda8fa1f5f949606c8e42c010","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-031","path":"platform/schemas/domain_fanout_plan.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s1/domain_fanout_plan.schema.json","sha256":"3b0948613a5996028b9c030a99f0b51d682f6035e019557756b1a15d43971113","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-032","path":"platform/schemas/domain_seed_output.schema.v3.json","schema_id":"https://schemas.liti-agent.local/stage1/s1/domain_seed_output.schema.v3.json","sha256":"992acf05dbccb34c65ead4e8c592f424e3b91672dc109cbd1bfa76a0a71a13c9","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-033","path":"platform/schemas/domain_slice.schema.v2.json","schema_id":"https://schemas.liti-agent.local/stage1/s1/domain_slice.schema.v2.json","sha256":"212a405088e7cf7ba2c65528a1c716938c946df7fe3bae3256b613051ed31aa3","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-034","path":"platform/schemas/fact_exception_pack.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/part4/fact_exception_pack.schema.json","sha256":"4eba7e51ed46a99e3704bc2333169749f4a16935de26a8c8027c1cac98ea58cf","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-035","path":"platform/schemas/fact_ledger_base.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/part4/fact_ledger_base.schema.json","sha256":"b3f0e79ecb4c2f720f3e07e89154aadbd2327e4129cc703569fb5635240d2fe8","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-036","path":"platform/schemas/fact_ledger_candidate_bundle.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/part4/fact_ledger_candidate_bundle.schema.json","sha256":"4e481504fb795b2be510680a8fa88124f5763a8124462f7870be4125ed9a7730","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-037","path":"platform/schemas/legal_effect_structures.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/part3/legal_effect_structures.schema.json","sha256":"fc962e8ae39f9bede64ba017297eded6413689204a065e00c3b3bdca8f1854df","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-038","path":"platform/schemas/structure_seed_bundle.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/part3/structure_seed_bundle.schema.json","sha256":"b7af9e422b6ac3876cffea39ec4f617eea76a631a57dfdfcd57d3785a83c667a","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-039","path":"signals/_common/evidence_slot_status.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/evidence_slot_status.schema.json","sha256":"292b03960b187cef668b8635a8d7539fde7c31f0c20d01af52c4f6ff8519d7b1","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-040","path":"signals/_common/signal_item.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/signal_item.schema.json","sha256":"de8695f98041c06cf50c0d8d2ebc31e7b3c518ca9d39a27da940438704c58bb1","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-041","path":"signals/schemas/domain_activation_manifest.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/domain_activation_manifest.schema.json","sha256":"013a6ebd230ebe46dda665af9f6c4448b267444b44e7b8f701f2fae80a2ee92a","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-042","path":"signals/schemas/procedural_posture_relief_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/procedural_posture_relief_signals.schema.json","sha256":"fefb4317ad63088919b61777c71fe75ee6aa507b9f599dcf455d2af63dfc5e0d","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-043","path":"signals/schemas/party_capacity_standing_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/party_capacity_standing_signals.schema.json","sha256":"66de89ac53964166f6caabd50cbc03eb82dede0acf702d5e6d825c1d82ef81d0","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-044","path":"signals/schemas/governing_law_version_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/governing_law_version_signals.schema.json","sha256":"13a3f62f03356090d2cb24de2da0ba217928dfe8eb3c111d0f5e87c7df3119ee","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-045","path":"signals/schemas/legal_relation_lifecycle_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/legal_relation_lifecycle_signals.schema.json","sha256":"420613a5900c4360487b89b978efedde58f5ddc61644130e4b9e63ef8ab33d8b","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-046","path":"signals/schemas/timeline_notice_condition_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/timeline_notice_condition_signals.schema.json","sha256":"99c66208524155cea6bbd5e24fd26998cc9b653c89b24b569c793e36f1623d35","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-047","path":"signals/schemas/asset_right_state_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/asset_right_state_signals.schema.json","sha256":"fc34fbb3d33a284c3d57f3c278cbda8b3555ef26ee2f06b803fd2410ebce38b6","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-048","path":"signals/schemas/liability_causation_damage_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/liability_causation_damage_signals.schema.json","sha256":"34102cb8eeda80773eb62a5ee61e3d714bf90424ed5350dcac4b7bf873a72c5a","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-049","path":"signals/schemas/defense_exception_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/defense_exception_signals.schema.json","sha256":"010148c15e60e4d112b142f80b1723c06e34ba22b3edefae9e4371f2353b053e","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-050","path":"signals/schemas/evidence_proof_conflict_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/evidence_proof_conflict_signals.schema.json","sha256":"c419f568e28c06c629bc715aff7b0737b77e9c4871c91d4fae8f6ecf04196390","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-051","path":"signals/schemas/calculation_requirements.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/calculation_requirements.schema.json","sha256":"7fdb5ef0f50d7af22ac417abc4022cd238f5ab0dc942866420616729a9e3571f","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-052","path":"signals/schemas/remedy_enforcement_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/remedy_enforcement_signals.schema.json","sha256":"999e1969b983748f209e9b5239f7edd0ec43bc642d9ea8fd7edbf34f9ce653f3","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-053","path":"signals/schemas/legal_effect_routes.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/legal_effect_routes.schema.json","sha256":"c24cb740c370aa2477199a0225be8291164ef5c787601fd962a370c642cc3cc0","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-054","path":"signals/schemas/domain_signal_envelope.schema.v2.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/domain_signal_envelope.schema.v2.json","sha256":"1483d6c5f98083f59172feff9b7c15b44d3ed789db5b6172d0de05f06e9d3fbc","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-055","path":"signals/schemas/signal_manifest.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/signal_manifest.schema.json","sha256":"5e72084780b82b29582c9ffcf48f3e4894d7c0b152e5ce8df394583c07dde681","source_manifest":"signals/signal_registry.v2.json"}],"contract_manifest_ref":{"mode":"CONDITIONAL_RELOCATION_ONLY","path":null,"sha256":null,"status":"NOT_REQUIRED_DEFAULT_PATHS"},"expected_concrete_path_count":55,"full_stage1_runtime_release_status":"STAGE1_NOT_RELEASE_READY"},"stage2_direct":[{"asset_id":"AGENT-S2_10-HYBRID-OPAQUE","binding_status":"BOUND","path":"agent_scripts/Stage_2_S2_10.yml","schema_id":"liti_agent_yaml.v1","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272"},{"asset_id":"BINDING-S2_10-LLM-OPAQUE","binding_status":"BOUND","path":"deployment/stage2_s2_10_llm_binding.yml","schema_id":"stage2_s2_10_llm_binding.v2","sha256":"9d20b264e753c2f52e8d096edab363ace0fecf2ec8357605d1a9cb47c9c2b930"},{"asset_id":"AUTHORITY-REGISTRY","binding_status":"BOUND","path":"registry/authority/authority_registry.yml","schema_id":"stage2.authority_registry.v1","sha256":"b4663610e18098cf650fbd5846f18dcbc96074b3012c68f03f67402509c7d142"},{"asset_id":"AUTHORITY-RELEASE","binding_status":"BOUND","path":"manifest/authority_release.json","schema_id":"stage2.authority_release.v1","sha256":"cc683958377eea44756de6e9c74fc925da66dd60cc84363f5bec36584f5b2967"},{"asset_id":"PROFILE-EC-00_CONTRACT_GENERAL","binding_status":"BOUND","path":"registry/substantive/EC-00_contract_general.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"a4f7abd9957b3a9e58d05dd559c3c869bf96fd88ea18968a363c6e606e3c0aa8"},{"asset_id":"PROFILE-E-01_JURISTIC_ACT_VALIDITY","binding_status":"BOUND","path":"registry/substantive/E-01_juristic_act_validity.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"0a0d2676f96be321a7bb974b8e4fb1981ab43773f271c99dc86a70cb17d27c99"},{"asset_id":"PROFILE-E-02_CONTRACT_MONEY_CLAIM","binding_status":"BOUND","path":"registry/substantive/E-02_contract_money_claim.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"08e252bccc718ccc44a258bc540afc2567e509239399f4017550df32bac97824"},{"asset_id":"PROFILE-E-03_PARTIES_LIABILITY_SUCCESSION","binding_status":"BOUND","path":"registry/substantive/E-03_parties_liability_succession.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"4e841d5f640b06a1b52060b82dda39605369cbe26d81655b7918673437e4519c"},{"asset_id":"PROFILE-E-04_UNJUST_ENRICHMENT","binding_status":"BOUND","path":"registry/substantive/E-04_unjust_enrichment.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"31a5966d4c14940e810f870bf4382f1be642f7716ebaaa35193ef32e9b9d95c7"},{"asset_id":"PROFILE-E-05_TORT_GENERAL","binding_status":"BOUND","path":"registry/substantive/E-05_tort_general.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"fe6ea92fc10c4196e0ac83b990bf2606e24024030e7b0002fecdae9f8f50221a"},{"asset_id":"PROFILE-E-06_PROFESSIONAL_LIABILITY","binding_status":"BOUND","path":"registry/substantive/E-06_professional_liability.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"efa7a4f6cda90c04a06558a9d0e1efe13b25169d55d03e36d55d72fcdd096a15"},{"asset_id":"PROFILE-E-07_CONSTRUCTION_DEFECT","binding_status":"BOUND","path":"registry/substantive/E-07_construction_defect.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"78c76cb0485a4acf741109aee05f634f51c3a6904044c613080b21c3978a09f9"},{"asset_id":"PROFILE-E-08_LEASE_DEPOSIT","binding_status":"BOUND","path":"registry/substantive/E-08_lease_deposit.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"dbe1886671edff49b8b0251eed567d1b3e4e5d748456434262286ca7acf990db"},{"asset_id":"PROFILE-E-09_REGISTRY_TRANSFER_CLAIMS","binding_status":"BOUND","path":"registry/substantive/E-09_registry_transfer_claims.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"d18946322a8cb528146ac0aa0a2880c41ac2056671fd237b928341ceb8561002"},{"asset_id":"PROFILE-E-10_SECURED_REGISTRY","binding_status":"BOUND","path":"registry/substantive/E-10_secured_registry.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"5819c26ec8478e12a12e340c93a9d23cc410833e1192c2315a1986c9d48a1eba"},{"asset_id":"PROFILE-E-11_POSSESSION_VINDICATION","binding_status":"BOUND","path":"registry/substantive/E-11_possession_vindication.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"5e6d6460be4ec0f2ba0096305b9ae39f5f430d107337d0d7e07aac1a9d599aaf"},{"asset_id":"PROFILE-E-12_CO_OWNERSHIP_BOUNDARY","binding_status":"BOUND","path":"registry/substantive/E-12_co_ownership_boundary.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"62cfbf6a6c5c5edc8b912e348be1c4d4f7dd4c20c722e57e5554058f0caafb4a"},{"asset_id":"PROFILE-E-13_CREDITOR_PRESERVATION","binding_status":"BOUND","path":"registry/substantive/E-13_creditor_preservation.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"c60e6d67c7e3985d1f6ce44027726282f931934e3e66b44f06ccd26845ca2f45"},{"asset_id":"PROFILE-E-14_EXECUTION_LINKED_CLAIMS","binding_status":"BOUND","path":"registry/substantive/E-14_execution_linked_claims.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"45d4b3ab46e1c8834c3b3eec72a28d05e39cb78a9ec2c2de07b5e55e81aeebd7"},{"asset_id":"PROFILE-E-15_SUCCESSION_FAMILY_PROPERTY","binding_status":"BOUND","path":"registry/substantive/E-15_succession_family_property.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"f691b67295ad8e634b34519cf71156caf6eaf73cef54577615ab79462f8aa766"},{"asset_id":"PROFILE-E-16_NEGOTIABLE_INSTRUMENTS","binding_status":"BOUND","path":"registry/substantive/E-16_negotiable_instruments.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"7720d83b64e7a44720788f6ff3c7cc8ceaf5195377a1e61b52de2144989a1194"},{"asset_id":"PROFILE-E-17_LABOR_WAGE_CLAIMS","binding_status":"BOUND","path":"registry/substantive/E-17_labor_wage_claims.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"168ce5e41104937cf7ab946944f060b82cfe16066425897f07bb9e837b8689ea"},{"asset_id":"PROFILE-E-18_ORG_RESOLUTION_STATUS","binding_status":"BOUND","path":"registry/substantive/E-18_org_resolution_status.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"59cf689f886dfaf4ad00dbe6142f5b11c37d0062660f7467aa43427462aa075f"},{"asset_id":"PROFILE-E-19_INSURANCE_CLAIMS","binding_status":"BOUND","path":"registry/substantive/E-19_insurance_claims.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"0fb4793446c155e7a0b4469c9b8c1be1323112eef55ca4c495307c1af56e754c"},{"asset_id":"PROFILE-E-20_IP_CLAIMS","binding_status":"BOUND","path":"registry/substantive/E-20_ip_claims.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"fe07f20d149a2c4deac2e46de299cd78f0bf829f58c615a86c45f542d30804e1"},{"asset_id":"PROFILE-E-21_MEDIA_PERSONALITY_RIGHTS","binding_status":"BOUND","path":"registry/substantive/E-21_media_personality_rights.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"951260bbe8ef116d682f49f3679106c7144ca68f8078f5c10b3459667c1f5b2c"},{"asset_id":"PROFILE-E-00_RESIDUAL_UNROUTED","binding_status":"BOUND","path":"profiles/crosscut/E-00_residual_unrouted.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"639e507147a6132f9e41ccd0b00d1b5450d6a9629991629b173d5bcaf5b6df39"},{"asset_id":"PROFILE-X1_NOTICE_LIFECYCLE","binding_status":"BOUND","path":"profiles/crosscut/X1_notice_lifecycle.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"9af8b5b5f3a8196a10308d1ee34e0788d9adeac7a99e142e449490d14316faef"},{"asset_id":"PROFILE-X2_ASSET_IDENTITY_LINEAGE","binding_status":"BOUND","path":"profiles/crosscut/X2_asset_identity_lineage.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"6c1e437944b3a62b60ee7acad5ec9177fefac2991fe970338acc27efcc8a13ad"},{"asset_id":"PROFILE-X3_PROCEDURE_STANDING_RELIEF","binding_status":"BOUND","path":"profiles/crosscut/X3_procedure_standing_relief.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"f3b794bef82566e569232ba02c63ae148099143d8d1ab84de1c4fb76105e65df"},{"asset_id":"PROFILE-X4_RESPONSE_ADMISSION_DEFENSE","binding_status":"BOUND","path":"profiles/crosscut/X4_response_admission_defense.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"57851ed55b3351a8139df29224d74b7cb8427708bbf6de00ecd27c44089df32e"},{"asset_id":"PROFILE-SL-AUTO_MOTOR_VEHICLE","binding_status":"BOUND","path":"profiles/special_law/SL-AUTO_motor_vehicle.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"7234a7ab890f242e6b7aa811528e34c0c85779007cffbf135da0bfff36d61d91"},{"asset_id":"PROFILE-SL-INDUSTRIAL_ACCIDENT","binding_status":"BOUND","path":"profiles/special_law/SL-INDUSTRIAL_ACCIDENT.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"10d78b8031df7d89f835afc9ca60fab36648e561c729780204c80885f4dd097f"},{"asset_id":"PROFILE-SL-PRODUCT_LIABILITY","binding_status":"BOUND","path":"profiles/special_law/SL-PRODUCT_LIABILITY.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"1d5ee8eddcf005fdb33df58f591a8948aa3e891a3a5656d919394ff0b39eea53"},{"asset_id":"PROFILE-SL-RESIDENTIAL_LEASE","binding_status":"BOUND","path":"profiles/special_law/SL-RESIDENTIAL_LEASE.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"3e2efd1b3c0524a305eafedc5ec91e05be989a6e55c1501ed161a9b8f8151fd7"},{"asset_id":"PROFILE-SL-COMMERCIAL_LEASE","binding_status":"BOUND","path":"profiles/special_law/SL-COMMERCIAL_LEASE.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"5aebed9ab56bc00eb7e0511f9fe5db8c3a42f1e81b28d58c38d487aa91cbab3e"},{"asset_id":"PROFILE-SL-LABOR","binding_status":"BOUND","path":"profiles/special_law/SL-LABOR.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"6b2542bb64f4c1d164b1ccd2ce5099fad29bcea4333d9e34bd0fb1667b9ced4a"},{"asset_id":"PROFILE-SL-STATE_LIABILITY","binding_status":"BOUND","path":"profiles/special_law/SL-STATE_LIABILITY.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"5b2fe6d57b918384a619efbd04360ddfaf7720d384136f69d359ccb0b6c853d3"},{"asset_id":"PROFILE-SL-IP-PATENT","binding_status":"BOUND","path":"profiles/special_law/SL-IP-PATENT.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"d0651a8a50d0b18d25931063314ecec284988c5a18fab68d08a317d725bb3066"},{"asset_id":"PROFILE-SL-IP-COPYRIGHT","binding_status":"BOUND","path":"profiles/special_law/SL-IP-COPYRIGHT.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"d4349677f68346f79709ea23a05957262f6426f976388bba45f05c617035eb78"},{"asset_id":"PROFILE-SL-IP-OTHER","binding_status":"BOUND","path":"profiles/special_law/SL-IP-OTHER.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"fc3e2772252a3a90571663ebcfbc8e18dbf526977f4a3d77c4705ef8aa8dd6a8"},{"asset_id":"PROFILE-SL-MEDIA","binding_status":"BOUND","path":"profiles/special_law/SL-MEDIA.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"e0d5d287befd1578a06c64a265d5c4426af5772b6764018f6a15f00aac3b498c"},{"asset_id":"PROFILE-SL-TRANSPORT_MARITIME","binding_status":"BOUND","path":"profiles/special_law/SL-TRANSPORT_MARITIME.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"6e87a77c25f8c358f1d7d35ca165b1229c2cb422a440c91768ad80e520d35456"},{"asset_id":"PROFILE-SL-CONSUMER_CONTRACT","binding_status":"BOUND","path":"profiles/special_law/SL-CONSUMER_CONTRACT.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"afd8bbba102614d8d08f2e7a5384f6ca24e1309c1f52feb13906613f2ced51b7"},{"asset_id":"PROFILE-ACTIO-MORTGAGE","binding_status":"BOUND","path":"profiles/overlays/ACTIO-MORTGAGE.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"7e584f7b4e4d19132e9575071f87d05965fb77fa2ca870911fe9974a7c511c4d"},{"asset_id":"PROFILE-ACTIO-MORTGAGE-CREATION","binding_status":"BOUND","path":"profiles/overlays/ACTIO-MORTGAGE-CREATION.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"e727690ee23883e011d49eba01cfd87abc5482641c2bda519c0a39518e1769ee"},{"asset_id":"PROFILE-ACTIO-ENCUMBERED-TRANSFER","binding_status":"BOUND","path":"profiles/overlays/ACTIO-ENCUMBERED-TRANSFER.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"fa950393a572829ba7e296c20cd08ff19a063b0f8441f950130fd677b1e38179"},{"asset_id":"PROFILE-ACTIO-PRESERVED-CLAIM-BUNDLE","binding_status":"BOUND","path":"profiles/overlays/ACTIO-PRESERVED-CLAIM-BUNDLE.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"fbd99f029438c1c278f93d88d18a703db72e78f20c7049f344e5748c108f94c5"},{"asset_id":"PROFILE-ACTIO-DEFENSE-MAP","binding_status":"BOUND","path":"profiles/overlays/ACTIO-DEFENSE-MAP.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"05348c493e6046a3e5c55f9b516c0e862fe5aa753e1b2fc71624bb2b11f0c191"}]},"executor_binding_ref":{"asset_id":"BINDING-S2_00-CODE-EXECUTOR","binding_status":"EXTERNAL_TRUST_ROOT_PENDING_LIVE_ADMISSION","path":"deployment/stage2_code_executor_binding.yml","schema_id":"stage2_code_executor_binding.v3"},"loader_binding_ref":{"asset_id":"BINDING-S2_00-LEGACY-REFERENCE","binding_status":"BOUND","path":"deployment/stage2_loader_binding.yml","schema_id":"stage2_loader_binding.reference.v1","sha256":"120313754c597541680a8dc7d9d59c6f8b2438c053553f030ef89171709dd23a"},"module_manifest_ref":{"asset_id":"MANIFEST-MODULE","binding_status":"BOUND","path":"manifest/module_manifest.json","schema_id":"stage2_module_manifest.v1","sha256":"5482e529dac63da574cb85dbfe73c954ea6cfacbb516cb70ff89df5448626c89"},"open_items":[{"open_id":"O-07","owner":"release_operator","required_evidence":"signed canary or production admission with current Stage 1 integrity closure","status":"OPEN_RELEASE_AUTHORIZATION"},{"open_id":"CEG-02-DIRECT-MCP-LIVE","owner":"AgentBackend_owner","required_evidence":"live code-executor.run_code outer result and inner single-JSON receipt with exact Agent/code/release binding","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-03-SECRET-INJECTION","owner":"AgentBackend_owner","required_evidence":"backend-injected or pre-registered Code Executor authentication with no plaintext credential in YAML or code","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-04-RUNTIME-IMAGE-PIN","owner":"Code_Executor_owner","required_evidence":"verified Python runtime image digest compatible with the bound httpx dependency","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-05-REQUEST-SIZE-TIMEOUT","owner":"Code_Executor_owner","required_evidence":"representative S2_00 Agent request accepted and completed within backend request-size and 300-second limits","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-06-BINARY-LOCALDOCS","owner":"localdocs_owner","required_evidence":"live read_binary_doc and write_binary_file byte-preservation receipt over the approved path set","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-07-ISOLATION-EGRESS","owner":"AgentBackend_security_owner","required_evidence":"workspace identity substitution and backend-enforced S2_00_LOCALDOCS_ONLY_V1 egress verification","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-08-BARRIER-ROUTE","owner":"Stage_2_integration_owner","required_evidence":"live status-last logical publish and exactly-one downstream route receipt","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"DEV-DETACHED-RELEASE-ENVELOPE","owner":"release_operator","required_evidence":"detached signed envelope admits the release and executor binding without a cross-file hash cycle","status":"OPEN_RELEASE_AUTHORIZATION"},{"open_id":"DOWNSTREAM-CASE-TYPE-REGISTRY","owner":"S2_20_case_type_registry_owner","required_evidence":"manifest/case_type_registry.yml exact path/hash and 137-row sign-off; not a direct S2_00 executable dependency","status":"PENDING_SEQUENTIAL_BIND"}],"release_class":"DEV_FIXTURE_RELEASE","release_digest":"a2a1e2445b5d8e7baac20a616e6a182d5a6f0c16a791281eb177c59f5782eb20","release_digest_contract":{"algorithm_id":"STAGE2-RELEASE-DIGEST-V1","array_order":"PRESERVE_DECLARED_ORDER","canonicalization_algorithm_id":"STAGE2-CANONICAL-JSON-V1","digest_algorithm":"sha256","digest_scope":"ENTIRE_DOCUMENT_AFTER_REMOVING_TOP_LEVEL_RELEASE_DIGEST","encoding":"UTF-8","line_termination":"LF_ONE_TRAILING_NEWLINE","non_finite_numbers_allowed":false,"object_key_order":"SORT_CODEPOINT"},"release_evidence":[{"evidence_id":"DEV-DRAFT-UNSIGNED-001","input_digest":"c2c6949b6ddfa1b74a048c633413f3452967155bcaa1110bcd41cde3aeceba8b","release_class":"DEV_FIXTURE_RELEASE","scope":"INLINE_CODE_EXECUTOR_AND_STRUCTURED_HANDOFF_OFFLINE_HASH_BOUND_VALIDATION_ONLY","signature":"PENDING_SEQUENTIAL_BIND","signer_id":"UNSIGNED_DRAFT","status":"PENDING_SEQUENTIAL_BIND"}],"release_id":"STAGE2-CLEAN-DEV-DRAFT-S2_00-HYBRID-HANDOFF-2026-08-30","release_status":"DRAFT_NOT_EXECUTABLE","retry_policies":[{"backoff_seconds":[0,1,3],"max_attempts":3,"non_retryable_classes":["HASH","SCHEMA","PRODUCER","CONSERVATION","RUN_BINDING"],"retry_policy_id":"S2-RETRY-TRANSIENT-READ-V1","retryable_codes":["TRANSIENT_READ_ERROR","TRANSIENT_LOCK_ERROR"]}],"schema_version":"stage2_release.v2","signature":"PENDING_SEQUENTIAL_BIND","stage1_sources":[{"adapter_id":"S2A-EVIDENCE-V3-ENVELOPE-V1","logical_input_id":"evidence_indexed","path":"evidence_indexed.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_B1_quality_gate_evidence_indexed","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_contract_version","items"],"requirement_class":"EVIDENCE_EVENT_SCOPE","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-EVENTS-V1-ENVELOPE-V1","logical_input_id":"evidence_event_candidates","path":"evidence_event_candidates.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_B2_quality_gate_event_candidates","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_version","items"],"requirement_class":"EVIDENCE_EVENT_SCOPE","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-CLIENT-GOAL-V8-V1","logical_input_id":"client_goal","path":"client_goal.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_A_client_goal","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["primary_goal","constraints","parties"],"requirement_class":"OPTIMIZATION_CONTEXT","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-DOMAIN-SCREENING-V1","logical_input_id":"domain_screening","path":"routing/domain_screening.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_A0_domain_screener_02","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["domain_screening"],"requirement_class":"ROUTING_PROFILE_BACKBONE","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-DUAL-SG01-V1","logical_input_id":"domain_activation_manifest","path":"routing/domain_activation_manifest.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_D0_domain_activation_gate","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["domain_activation_manifest"],"requirement_class":"ROUTING_PROFILE_BACKBONE","run_identity_pointer":null,"schema_ref":{"$id":"https://schemas.liti-agent.local/stage1/s5/domain_activation_manifest.schema.json","path":"signals/schemas/domain_activation_manifest.schema.json","sha256":"013a6ebd230ebe46dda665af9f6c4448b267444b44e7b8f701f2fae80a2ee92a"},"transaction_identity_pointer":null},{"adapter_id":"S2A-B1-GATE-V1","logical_input_id":"b1_evidence_indexed_gate","path":"quality_gates/B1_evidence_indexed_gate.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_B12_gate_audit_finalizer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_contract_version","gate_id","overall_severity","hard_gate_findings","review_findings","stage2_auto_progression_allowed"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-B2-GATE-V1","logical_input_id":"b2_event_candidates_gate","path":"quality_gates/B2_event_candidates_gate.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_B12_gate_audit_finalizer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_contract_version","gate_id","overall_severity","hard_gate_findings","review_findings","stage2_auto_progression_allowed"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-P1-HANDOFF-FLAT-V1","logical_input_id":"stage1_part1_soft_gate_handoff","path":"quality_gates/stage1_part1_soft_gate_handoff.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_B2_SHA256_soft_gate_handoff_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_version","handoff_status","review_items","stage2_auto_progression_allowed","hard_gate_summary","review_item_conservation","digest_guard"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-BO-V8-LIST-V1","logical_input_id":"bo","path":"BO.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_BO_F0_final_bo_compiler_gate_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":[],"requirement_class":"IDENTITY_BACKBONE","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-SIGNAL-ALL-V1","logical_input_id":"signal_manifest","path":"signals/signal_manifest.json","path_rule":null,"producer_alias_id":"PA-SG-COMPILER-001","producer_id":"Task_C_BO_S0_signal_bundle_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["files","downstream_read_sets"],"requirement_class":"ROUTING_PROFILE_BACKBONE","run_identity_pointer":null,"schema_ref":{"$id":"https://schemas.liti-agent.local/stage1/s5/signal_manifest.schema.json","path":"signals/schemas/signal_manifest.schema.json","sha256":"5e72084780b82b29582c9ffcf48f3e4894d7c0b152e5ce8df394583c07dde681"},"transaction_identity_pointer":"/transaction_id"},{"adapter_id":"S2A-P2-HANDOFF-FLAT-V1","logical_input_id":"stage1_part2_review_handoff","path":"quality_gates/stage1_part2_review_handoff.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_BO_F0_final_bo_compiler_gate_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_version","status","review_items"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-LES-CURRENT-V8-V1","logical_input_id":"legal_effect_structures","path":"legal_effect_structures.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_LE_L2_final_structure_index_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":[],"requirement_class":"ROUTING_PROFILE_BACKBONE","run_identity_pointer":null,"schema_ref":{"$id":"https://schemas.liti-agent.local/stage1/part3/legal_effect_structures.schema.json","path":"platform/schemas/legal_effect_structures.schema.json","sha256":"fc962e8ae39f9bede64ba017297eded6413689204a065e00c3b3bdca8f1854df"},"transaction_identity_pointer":"/signal_manifest_transaction_id"},{"adapter_id":"S2A-P3-HANDOFF-WRAPPED-V1","logical_input_id":"stage1_part3_review_handoff","path":"quality_gates/stage1_part3_review_handoff.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_LE_L2_final_structure_index_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["stage1_part3_review_handoff"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-FACT-LEDGER-CURRENT-V8-V1","logical_input_id":"fact_ledger_base","path":"Fact_Ledger_base.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_FL_F2_final_fact_ledger_gate_and_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":[],"requirement_class":"IDENTITY_BACKBONE","run_identity_pointer":null,"schema_ref":{"$id":"https://schemas.liti-agent.local/stage1/part4/fact_ledger_base.schema.json","path":"platform/schemas/fact_ledger_base.schema.json","sha256":"b3f0e79ecb4c2f720f3e07e89154aadbd2327e4129cc703569fb5635240d2fe8"},"transaction_identity_pointer":null},{"adapter_id":"S2A-FACT-LEDGER-WRITER-REPORT-V1","logical_input_id":"fact_ledger_writer_report","path":"stage1_tmp/fact_ledger/fact_ledger_writer_report.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_FL_F2_final_fact_ledger_gate_and_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_version"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-P4-HANDOFF-WRAPPED-V1","logical_input_id":"stage1_part4_review_handoff","path":"quality_gates/stage1_part4_review_handoff.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_FL_F2_final_fact_ledger_gate_and_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["stage1_part4_review_handoff"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-SIGNAL-ALL-V1","logical_input_id":"signal_payload_family","path":null,"path_rule":"signals/","producer_alias_id":"PA-SG-COMPILER-001","producer_id":"Task_C_BO_S0_signal_bundle_writer","raw_hash_source":"MANIFEST_ROW","required_keys":[],"requirement_class":"SIGNAL_PAYLOAD","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null}]} +{"adapter_decisions":[{"adapter_id":"S2A-SIGNAL-ALL-V1","adapter_kind":"SIGNAL_ALL_EXPANSION","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"file_conservation_equation":"semantic_file_rows + integrity_only_file_rows = Counter(signal_manifest.files[])","global_signal_id_uniqueness_assumed":false,"integrity_only_kinds":["compatibility_view"],"manifest_selector":"/downstream_read_sets/stage2","physical_path_rule":"U/signals/","record_conservation_equation":"used_record_occurrences + unused_record_occurrences + unmapped_record_occurrences = records_from_semantic_files","record_occurrence_key":["manifest_transaction_id","file_path","record_ordinal","signal_id"],"row_order":"PRESERVE_MANIFEST_ORDER","row_source":"/files","semantic_kinds":["canonical","domain_signal"],"sentinel":["ALL"]},"schema_ref":"schemas/ingress.schema.json#/$defs/all_expansion_contract"},{"adapter_id":"S2A-DUAL-SG01-V1","adapter_kind":"DUAL_SG01_PROJECTION","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"comparison":"PARSED_CANONICAL_PROJECTION_EQUAL","payload_root":"/domain_activation_manifest","projection_json_pointers":["/schema_version","/signal_id","/status","/registry_version","/registry_index_sha256","/screening_sha256","/domain_entries","/active_domain_ids","/supporting_domain_ids","/monitor_domain_ids","/expected_runnable_domain_ids","/required_calculation_domains","/unrouted_material","/conservation_gate","/fail_open_policy","/review_items","/contract_guards"],"raw_hash_policy":"PRESERVE_AND_VERIFY_SEPARATELY","routing_path":"routing/domain_activation_manifest.json","set_semantics_json_pointers":["/active_domain_ids","/supporting_domain_ids","/monitor_domain_ids","/expected_runnable_domain_ids","/required_calculation_domains"],"signal_path":"signals/domain_activation_manifest.json"},"schema_ref":"schemas/ingress.schema.json#/$defs/dual_sg01_projection_contract"},{"adapter_id":"S2A-P1-HANDOFF-FLAT-V1","adapter_kind":"HANDOFF","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"count_field_required":false,"logical_input_id":"P1_REVIEW_HANDOFF","p1_digest_keys":["evidence_indexed_sha256","evidence_event_candidates_sha256","b1_gate_sha256","b2_gate_sha256","screening_sha256","activation_manifest_sha256","registry_index_sha256"],"review_items_json_pointer":"/review_items","schema_version":"stage1_part1_soft_gate_handoff.v1","seal_sources":["routing/domain_screening.json","routing/domain_activation_manifest.json","domains/_registry_index.json"],"source_stage":"P1","status_json_pointer":"/handoff_status","wrapper_json_pointer":""},"schema_ref":"schemas/ingress.schema.json#/$defs/handoff_adapter_contract"},{"adapter_id":"S2A-P2-HANDOFF-FLAT-V1","adapter_kind":"HANDOFF","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"count_field_required":false,"logical_input_id":"P2_REVIEW_HANDOFF","review_items_json_pointer":"/review_items","schema_version":"stage1_part2_review_handoff.v1","seal_sources":["BO.json","signals/signal_manifest.json"],"source_stage":"P2","status_json_pointer":"/status","wrapper_json_pointer":""},"schema_ref":"schemas/ingress.schema.json#/$defs/handoff_adapter_contract"},{"adapter_id":"S2A-P3-HANDOFF-WRAPPED-V1","adapter_kind":"HANDOFF","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"count_field_required":true,"logical_input_id":"P3_REVIEW_HANDOFF","review_items_json_pointer":"/review_items","schema_version":"stage1_part3_review_handoff.v1","seal_sources":["legal_effect_structures.json","validation_assets/routing/part3_receipt.json"],"source_stage":"P3","status_json_pointer":"/status","wrapper_json_pointer":"/stage1_part3_review_handoff"},"schema_ref":"schemas/ingress.schema.json#/$defs/handoff_adapter_contract"},{"adapter_id":"S2A-P4-HANDOFF-WRAPPED-V1","adapter_kind":"HANDOFF","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"count_field_required":true,"logical_input_id":"P4_REVIEW_HANDOFF","review_items_json_pointer":"/review_items","schema_version":"stage1_part4_review_handoff.v1","seal_sources":["Fact_Ledger_base.json","validation_assets/routing/part4_receipt.json","stage1_tmp/fact_ledger/fact_ledger_writer_report.json"],"source_stage":"P4","status_json_pointer":"/status","wrapper_json_pointer":"/stage1_part4_review_handoff"},"schema_ref":"schemas/ingress.schema.json#/$defs/handoff_adapter_contract"},{"adapter_id":"S2-REVIEW-MAP-V1","adapter_kind":"REVIEW_NORMALIZATION","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"aggregate_handoff_status_never_resolves_item":true,"handoff_status_mappings":[{"source_stage":"P1","source_value":"READY_NO_REVIEW","technical_disposition":"AVAILABLE"},{"source_stage":"P1","source_value":"READY_WITH_REVIEW","technical_disposition":"AVAILABLE_WITH_ISSUES"},{"source_stage":"P1","source_value":"BLOCKED","technical_disposition":"UNAVAILABLE"},{"source_stage":"P2","source_value":"PENDING_FINALIZE","technical_disposition":"AVAILABLE_WITH_ISSUES"},{"source_stage":"P2","source_value":"FINALIZED","technical_disposition":"AVAILABLE"},{"source_stage":"P3","source_value":"OPEN","technical_disposition":"AVAILABLE_WITH_ISSUES"},{"source_stage":"P3","source_value":"FINALIZED","technical_disposition":"AVAILABLE"},{"source_stage":"P4","source_value":"OPEN","technical_disposition":"AVAILABLE_WITH_ISSUES"},{"source_stage":"P4","source_value":"FINALIZED","technical_disposition":"AVAILABLE"}],"mappings":[{"mapping_id":"S2RM-001","normalized_partition":"SUPPORTED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"SUPPORTED","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-002","normalized_partition":"CONDITIONAL","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"CONDITIONAL","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-003","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"UNRESOLVED","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-004","normalized_partition":"EXCLUDED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"EXCLUDED","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-005","normalized_partition":"SUPPORTED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"observed","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-006","normalized_partition":"CONDITIONAL","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"inferred","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-007","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"contested","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-008","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"missing_required","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-009","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"review","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-010","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_STATUS","source_stage":"ANY","source_value":"NO_SUPPORT","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-011","normalized_partition":"CONDITIONAL","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"info","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-012","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"review","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-013","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"SOFT_WARNING","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-014","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"hard_warning","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-015","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"HARD_WARNING","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-016","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"block","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},{"mapping_id":"S2RM-017","normalized_partition":"UNRESOLVED","resolution_inference_allowed":false,"source_field_kind":"REVIEW_ITEM_SEVERITY","source_stage":"ANY","source_value":"BLOCK","unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"}],"normalized_partitions":["SUPPORTED","CONDITIONAL","UNRESOLVED","EXCLUDED","UNMAPPED"],"resolution_inference_allowed":false,"unknown_value_policy":"MAP_TO_UNMAPPED_AND_ISSUE"},"schema_ref":"schemas/review_status.schema.json#/$defs/review_mapping_row"},{"adapter_id":"S2A-BO-V8-LIST-V1","adapter_kind":"PRODUCER_SHAPE","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"logical_input_id":"BO","open_source_fields_policy":"PRESERVE_UNMODELED_FIELDS_WITH_RAW_HASH","producer_id":"Task_C_BO_F0_final_bo_compiler_gate_writer","required_item_fields":["BO_ID","id","BOType","ActionType","JuristicAct","Action","Reason","PriorAct","ReasonRefs","Legal_Keywords","core_field_base","amount","EvidenceTitles","Evidence","source_evidence_indexes","provenance","downstream_seed_refs","extensions"],"required_root_fields":[],"root_shape":"ARRAY","schema_contract_version":null},"schema_ref":"schemas/ingress.schema.json#/$defs/producer_shape_adapter"},{"adapter_id":"S2A-EVIDENCE-V3-ENVELOPE-V1","adapter_kind":"PRODUCER_SHAPE","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"logical_input_id":"EVIDENCE_INDEXED","open_source_fields_policy":"PRESERVE_UNMODELED_FIELDS_WITH_RAW_HASH","producer_id":"Task_B1_quality_gate_evidence_indexed","required_root_fields":["schema_contract_version","items"],"root_shape":"OBJECT_ENVELOPE","schema_contract_version":"evidence_indexed.v3"},"schema_ref":"schemas/ingress.schema.json#/$defs/producer_shape_adapter"},{"adapter_id":"S2A-EVENTS-V1-ENVELOPE-V1","adapter_kind":"PRODUCER_SHAPE","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"logical_input_id":"EVIDENCE_EVENT_CANDIDATES","open_source_fields_policy":"PRESERVE_UNMODELED_FIELDS_WITH_RAW_HASH","producer_id":"Task_B2_quality_gate_event_candidates","required_root_fields":["schema_version","items"],"root_shape":"OBJECT_ENVELOPE","schema_contract_version":"evidence_event_candidates.v1"},"schema_ref":"schemas/ingress.schema.json#/$defs/producer_shape_adapter"},{"adapter_id":"S2A-DOMAIN-CONFIG-V1","adapter_kind":"DOMAIN_CONFIG","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"accepted_schema_version":"stage1_domain_config.v1","depends_on_legal_dependency_allowed":false,"rebuttal_slot_synthesis_allowed":false,"required_slot_fields":["element_slots","opposing_fact_slots","defense_map","calculation_bindings","emits_signals"],"undeclared_slot_policy":"PRESERVE_AS_PROPOSED_NEW_SLOT_ISSUE"},"schema_ref":"schemas/ingress.schema.json#/$defs/domain_config_adapter_contract"},{"adapter_id":"S2A-DOMAIN-CONFIG-V2","adapter_kind":"DOMAIN_CONFIG","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"accepted_schema_version":"stage1_domain_config.v2","depends_on_legal_dependency_allowed":false,"rebuttal_slot_synthesis_allowed":false,"required_slot_fields":["element_slots","opposing_fact_slots","defense_map","calculation_bindings","emits_signals"],"undeclared_slot_policy":"PRESERVE_AS_PROPOSED_NEW_SLOT_ISSUE"},"schema_ref":"schemas/ingress.schema.json#/$defs/domain_config_adapter_contract"},{"adapter_id":"S2A-FACT-LEDGER-CURRENT-V8-V1","adapter_kind":"FACT_LEDGER","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"bo_source_bo_id_multiset_equality_required":true,"fact_id_pattern":"^F-[0-9]{3,}$","legacy_adapter_status":"DISABLED_NO_APPROVED_ADAPTER","producer_generation":"CURRENT_V8","required_row_fields":["fact_id","source_bo_id","domain_effects","calculation_requests"],"root_shape":"ARRAY"},"schema_ref":"schemas/ingress.schema.json#/$defs/fact_ledger_adapter_contract"},{"adapter_id":"PA-SG-COMPILER-001","adapter_kind":"PRODUCER_ALIAS","contract_status":"CLOSED_DECISION_FIXTURE_PENDING","decision":{"bidirectional_match_allowed":true,"global_alias_allowed":false,"orchestration_producer_id":"Task_C_BO_S0_signal_bundle_writer","schema_writer_id":"Task_C_BO_S0_canonical_signal_compiler","scope":"STAGE1_PART2_SIGNAL_TRANSACTION_ONLY"},"schema_ref":"schemas/ingress.schema.json#/$defs/producer_alias_contract"}],"authoring_root":"Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean","authorization_status":"DEV_VALIDATION_ONLY","bundle":{"active_profile_policy":"CASE_RUN_EXACT_RELEASE_SELECTED_SUBSET_ONLY","authority_release_status":"DEV_UNAVAILABLE","context_cohort_policy_id":"S2-CACHE-STRUCTURED-CONTEXT-HANDOFF-V2","downstream_hybrid_status":"OFFLINE_HYBRID_IMPLEMENTED_LIVE_ADMISSION_PENDING","executable":false,"handoff_contract_version":"S2_00_STRUCTURED_CONTEXT_HANDOFF_V2","mode":"STRUCTURAL_FIXTURE","reason_codes":["STRUCTURAL_FIXTURE_NOT_EXECUTABLE","AUTHORITY_RELEASE_UNAVAILABLE","S2_10_PLATFORM_MODEL_AND_LEGAL_ADMISSION_PENDING","DIRECT_MCP_LIVE_ADMISSION_PENDING"],"s2_10_agent_ref":{"asset_id":"AGENT-S2_10-HYBRID-OPAQUE","binding_status":"BOUND","path":"agent_scripts/Stage_2_S2_10.yml","schema_id":"liti_agent_yaml.v1","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272"},"s2_10_agent_sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272","s2_10_llm_binding_ref":{"asset_id":"BINDING-S2_10-LLM-OPAQUE","binding_status":"BOUND","path":"deployment/stage2_s2_10_llm_binding.yml","schema_id":"stage2_s2_10_llm_binding.v2","sha256":"9b5d69f1316a0b9fba7b41097ee92142cf42485c8deb0be876d9e9329c317a04"},"s2_10_llm_binding_sha256":"9b5d69f1316a0b9fba7b41097ee92142cf42485c8deb0be876d9e9329c317a04","selected_context_ordered_refs_sha256":"37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570","selected_context_refs":[]},"dependency_locks":{"downstream_availability":[{"asset_id":"CASE-TYPE-COVERAGE","binding_status":"BOUND","path":"manifest/case_type_coverage.json","schema_id":"stage2.case_type_coverage.v1","sha256":"34d6f758fc1486fa7330ede376e65b9448a6eaa971bd21472b0e4b7d9a5b8cba"},{"asset_id":"CORPUS-RELEASE","binding_status":"BOUND","path":"manifest/corpus_release.json","schema_id":"stage2.corpus_release.v1","sha256":"27d0c83e7a95342efdbe5be675b6d5b7d0ff8695eeec022ebc5aded3359fc981"}],"stage1":{"closure_scope":"REFERENCED_55_ONLY_NOT_FULL_STAGE1_RUNTIME_RELEASE","closure_snapshot_date":"2026-08-29","concrete_paths":[{"binding_status":"BOUND","lock_id":"S1-DEPLOY-001","path":"runtime_manifest.json","schema_id":"stage1_runtime_manifest.v1","sha256":"8964593a64a9b1bc90122054bb09eb3911827a06ed62dab0d6b7c745e7e18f54","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-002","path":"domains/_registry_index.json","schema_id":null,"sha256":"9f177ebf8860e20e05483967a2037f3baa09c2ac92c69ddeb260c04ca31ebf39","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-003","path":"signals/signal_registry.v2.json","schema_id":"signal_registry.v2","sha256":"4392b40da458102f8dd11b40b40ae3f694b7b5911849b050e2e4118c569e5ab0","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-004","path":"domains/E-00/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"5919f7ea1d7be02666b0c48aa6a66445e6d454fc2fbb21d7fe5154b0a1e68f6f","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-005","path":"domains/E-01/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"b557e92cd1b093bf31792dbcf5b62cab8ad064a65c4421e79f141e06b4cc2192","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-006","path":"domains/E-02/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"be407c980c28226a15406f85b5861b04a4e19a13870513ac6626349fc05ac434","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-007","path":"domains/E-03/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"7d3814f9b50cd5b33ef65a4eb778693552b3685bd369e765e9ac032734ebe23e","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-008","path":"domains/E-04/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"95a8c600cdce5a687f766788af0f763ee1b6a895e6ed80934afd28fe9a107e25","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-009","path":"domains/E-05/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"e50541018f47aa27de2f8b13ec3fa52210cf8456a6feed8356af78c1f1da144a","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-010","path":"domains/E-06/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"1e2bee36cb3c24dd37fc3beb3cf70236d531126c4f62ee97b5b42e55f4b0745c","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-011","path":"domains/E-07/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"22ac562084b1ce231b7257d099c18b6a4619defa2fc42504d590e0bcc494c5f8","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-012","path":"domains/E-08/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"4d545306d42120e8552dd953d4336ef6de828ea827779944ba73acfda3d3a8bb","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-013","path":"domains/E-09/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"7ef7340750094efeb372c397eb3134e21d62dda6988b1f6fa0a197b9963868e0","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-014","path":"domains/E-10/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"e8d4f45fa76ea9e09333256dd4ea36cd3dd963bf60c04814a2cb8dc90d152f0a","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-015","path":"domains/E-11/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"eb78d0188a0a2400307b1c34c8f8703c54cd86dd06b942c1709c44a8630a68e1","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-016","path":"domains/E-12/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"f336accdc6de10cdcc28c1190328054bca402fb77a2a9859d59fbaf5e84dd170","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-017","path":"domains/E-13/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"e27e2e3855b5868a3ec12c7093b872434702f2e465b73c0bfc948b516aa0fc35","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-018","path":"domains/E-14/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"a273148cc17f07d90cda500fa5cb7df30c9cd253f7b86048cf4f63495d36a156","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-019","path":"domains/E-15/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"7f37edddc101a08ed8a0e25f3a2c638e72571edc212ac91d96c1e33c51202a69","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-020","path":"domains/E-16/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"ae9af46ee31b6ef0dafedd35ccd7959a941d67d1a3dcc70e0b13647896873323","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-021","path":"domains/E-17/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"5c61f4486bdc968e4b30734b3c045404f0a711f47ea3abbe6c5c64652fb7f68c","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-022","path":"domains/E-18/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"74ff76148d175929bdeeeced77e9a9922d29b51ad3d00ae6711c43c55717692c","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-023","path":"domains/E-19/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"a8578f54a3fead3bbd35c62d7199b0f8aafb77f5d409a87236a55d2550fbfd37","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-024","path":"domains/E-20/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"29ee14cfe7789f004e6b6978d5360cf1bebe33bf88715df0cb47257993a11d00","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-025","path":"domains/E-21/domain_config.json","schema_id":"stage1_domain_config.v2","sha256":"4e1684a843d9e0c5af82f45332ad85abe94eda0c3ff0d578235d892aee39b908","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-026","path":"domains/EC-00/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"fe74de112b73289485dcead7e0fc7d270c794b3cf8a29ee00fab1eb64ba13861","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-027","path":"domains/X1/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"ad2fee7d206018f9a1f66e5fdf40dd67b686f6938099bad1ffc5d538db14ac57","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-028","path":"domains/X2/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"eba7d4671546bd66f1350d144ae0884f8beffb0dffdc147b45b9d5292676d46f","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-029","path":"domains/X3/domain_config.json","schema_id":"stage1_domain_config.v1","sha256":"8b67a638ae4a86aca3a2216974242b11ec39790162c9f366edfa91b02c3d270a","source_manifest":"domains/_registry_index.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-030","path":"platform/schemas/client_goal_domain_profiles.schema.json","schema_id":null,"sha256":"ae2bfe0d754a09cbae16b2c15bf1518fc23f9e1bda8fa1f5f949606c8e42c010","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-031","path":"platform/schemas/domain_fanout_plan.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s1/domain_fanout_plan.schema.json","sha256":"3b0948613a5996028b9c030a99f0b51d682f6035e019557756b1a15d43971113","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-032","path":"platform/schemas/domain_seed_output.schema.v3.json","schema_id":"https://schemas.liti-agent.local/stage1/s1/domain_seed_output.schema.v3.json","sha256":"992acf05dbccb34c65ead4e8c592f424e3b91672dc109cbd1bfa76a0a71a13c9","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-033","path":"platform/schemas/domain_slice.schema.v2.json","schema_id":"https://schemas.liti-agent.local/stage1/s1/domain_slice.schema.v2.json","sha256":"212a405088e7cf7ba2c65528a1c716938c946df7fe3bae3256b613051ed31aa3","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-034","path":"platform/schemas/fact_exception_pack.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/part4/fact_exception_pack.schema.json","sha256":"4eba7e51ed46a99e3704bc2333169749f4a16935de26a8c8027c1cac98ea58cf","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-035","path":"platform/schemas/fact_ledger_base.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/part4/fact_ledger_base.schema.json","sha256":"b3f0e79ecb4c2f720f3e07e89154aadbd2327e4129cc703569fb5635240d2fe8","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-036","path":"platform/schemas/fact_ledger_candidate_bundle.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/part4/fact_ledger_candidate_bundle.schema.json","sha256":"4e481504fb795b2be510680a8fa88124f5763a8124462f7870be4125ed9a7730","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-037","path":"platform/schemas/legal_effect_structures.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/part3/legal_effect_structures.schema.json","sha256":"fc962e8ae39f9bede64ba017297eded6413689204a065e00c3b3bdca8f1854df","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-038","path":"platform/schemas/structure_seed_bundle.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/part3/structure_seed_bundle.schema.json","sha256":"b7af9e422b6ac3876cffea39ec4f617eea76a631a57dfdfcd57d3785a83c667a","source_manifest":"runtime_manifest.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-039","path":"signals/_common/evidence_slot_status.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/evidence_slot_status.schema.json","sha256":"292b03960b187cef668b8635a8d7539fde7c31f0c20d01af52c4f6ff8519d7b1","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-040","path":"signals/_common/signal_item.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/signal_item.schema.json","sha256":"de8695f98041c06cf50c0d8d2ebc31e7b3c518ca9d39a27da940438704c58bb1","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-041","path":"signals/schemas/domain_activation_manifest.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/domain_activation_manifest.schema.json","sha256":"013a6ebd230ebe46dda665af9f6c4448b267444b44e7b8f701f2fae80a2ee92a","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-042","path":"signals/schemas/procedural_posture_relief_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/procedural_posture_relief_signals.schema.json","sha256":"fefb4317ad63088919b61777c71fe75ee6aa507b9f599dcf455d2af63dfc5e0d","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-043","path":"signals/schemas/party_capacity_standing_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/party_capacity_standing_signals.schema.json","sha256":"66de89ac53964166f6caabd50cbc03eb82dede0acf702d5e6d825c1d82ef81d0","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-044","path":"signals/schemas/governing_law_version_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/governing_law_version_signals.schema.json","sha256":"13a3f62f03356090d2cb24de2da0ba217928dfe8eb3c111d0f5e87c7df3119ee","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-045","path":"signals/schemas/legal_relation_lifecycle_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/legal_relation_lifecycle_signals.schema.json","sha256":"420613a5900c4360487b89b978efedde58f5ddc61644130e4b9e63ef8ab33d8b","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-046","path":"signals/schemas/timeline_notice_condition_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/timeline_notice_condition_signals.schema.json","sha256":"99c66208524155cea6bbd5e24fd26998cc9b653c89b24b569c793e36f1623d35","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-047","path":"signals/schemas/asset_right_state_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/asset_right_state_signals.schema.json","sha256":"fc34fbb3d33a284c3d57f3c278cbda8b3555ef26ee2f06b803fd2410ebce38b6","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-048","path":"signals/schemas/liability_causation_damage_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/liability_causation_damage_signals.schema.json","sha256":"34102cb8eeda80773eb62a5ee61e3d714bf90424ed5350dcac4b7bf873a72c5a","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-049","path":"signals/schemas/defense_exception_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/defense_exception_signals.schema.json","sha256":"010148c15e60e4d112b142f80b1723c06e34ba22b3edefae9e4371f2353b053e","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-050","path":"signals/schemas/evidence_proof_conflict_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/evidence_proof_conflict_signals.schema.json","sha256":"c419f568e28c06c629bc715aff7b0737b77e9c4871c91d4fae8f6ecf04196390","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-051","path":"signals/schemas/calculation_requirements.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/calculation_requirements.schema.json","sha256":"7fdb5ef0f50d7af22ac417abc4022cd238f5ab0dc942866420616729a9e3571f","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-052","path":"signals/schemas/remedy_enforcement_signals.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/remedy_enforcement_signals.schema.json","sha256":"999e1969b983748f209e9b5239f7edd0ec43bc642d9ea8fd7edbf34f9ce653f3","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-053","path":"signals/schemas/legal_effect_routes.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/legal_effect_routes.schema.json","sha256":"c24cb740c370aa2477199a0225be8291164ef5c787601fd962a370c642cc3cc0","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-054","path":"signals/schemas/domain_signal_envelope.schema.v2.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/domain_signal_envelope.schema.v2.json","sha256":"1483d6c5f98083f59172feff9b7c15b44d3ed789db5b6172d0de05f06e9d3fbc","source_manifest":"signals/signal_registry.v2.json"},{"binding_status":"BOUND","lock_id":"S1-DEPLOY-055","path":"signals/schemas/signal_manifest.schema.json","schema_id":"https://schemas.liti-agent.local/stage1/s5/signal_manifest.schema.json","sha256":"5e72084780b82b29582c9ffcf48f3e4894d7c0b152e5ce8df394583c07dde681","source_manifest":"signals/signal_registry.v2.json"}],"contract_manifest_ref":{"mode":"CONDITIONAL_RELOCATION_ONLY","path":null,"sha256":null,"status":"NOT_REQUIRED_DEFAULT_PATHS"},"expected_concrete_path_count":55,"full_stage1_runtime_release_status":"STAGE1_NOT_RELEASE_READY"},"stage2_direct":[{"asset_id":"AGENT-S2_10-HYBRID-OPAQUE","binding_status":"BOUND","path":"agent_scripts/Stage_2_S2_10.yml","schema_id":"liti_agent_yaml.v1","sha256":"122fe890efb340ebbac299afe058bf9ad0ed87d4d0ccf2456393e9e5796ec272"},{"asset_id":"BINDING-S2_10-LLM-OPAQUE","binding_status":"BOUND","path":"deployment/stage2_s2_10_llm_binding.yml","schema_id":"stage2_s2_10_llm_binding.v2","sha256":"9b5d69f1316a0b9fba7b41097ee92142cf42485c8deb0be876d9e9329c317a04"},{"asset_id":"AUTHORITY-REGISTRY","binding_status":"BOUND","path":"registry/authority/authority_registry.yml","schema_id":"stage2.authority_registry.v1","sha256":"b4663610e18098cf650fbd5846f18dcbc96074b3012c68f03f67402509c7d142"},{"asset_id":"AUTHORITY-RELEASE","binding_status":"BOUND","path":"manifest/authority_release.json","schema_id":"stage2.authority_release.v1","sha256":"cc683958377eea44756de6e9c74fc925da66dd60cc84363f5bec36584f5b2967"},{"asset_id":"PROFILE-EC-00_CONTRACT_GENERAL","binding_status":"BOUND","path":"registry/substantive/EC-00_contract_general.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"a4f7abd9957b3a9e58d05dd559c3c869bf96fd88ea18968a363c6e606e3c0aa8"},{"asset_id":"PROFILE-E-01_JURISTIC_ACT_VALIDITY","binding_status":"BOUND","path":"registry/substantive/E-01_juristic_act_validity.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"0a0d2676f96be321a7bb974b8e4fb1981ab43773f271c99dc86a70cb17d27c99"},{"asset_id":"PROFILE-E-02_CONTRACT_MONEY_CLAIM","binding_status":"BOUND","path":"registry/substantive/E-02_contract_money_claim.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"08e252bccc718ccc44a258bc540afc2567e509239399f4017550df32bac97824"},{"asset_id":"PROFILE-E-03_PARTIES_LIABILITY_SUCCESSION","binding_status":"BOUND","path":"registry/substantive/E-03_parties_liability_succession.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"4e841d5f640b06a1b52060b82dda39605369cbe26d81655b7918673437e4519c"},{"asset_id":"PROFILE-E-04_UNJUST_ENRICHMENT","binding_status":"BOUND","path":"registry/substantive/E-04_unjust_enrichment.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"31a5966d4c14940e810f870bf4382f1be642f7716ebaaa35193ef32e9b9d95c7"},{"asset_id":"PROFILE-E-05_TORT_GENERAL","binding_status":"BOUND","path":"registry/substantive/E-05_tort_general.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"fe6ea92fc10c4196e0ac83b990bf2606e24024030e7b0002fecdae9f8f50221a"},{"asset_id":"PROFILE-E-06_PROFESSIONAL_LIABILITY","binding_status":"BOUND","path":"registry/substantive/E-06_professional_liability.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"efa7a4f6cda90c04a06558a9d0e1efe13b25169d55d03e36d55d72fcdd096a15"},{"asset_id":"PROFILE-E-07_CONSTRUCTION_DEFECT","binding_status":"BOUND","path":"registry/substantive/E-07_construction_defect.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"78c76cb0485a4acf741109aee05f634f51c3a6904044c613080b21c3978a09f9"},{"asset_id":"PROFILE-E-08_LEASE_DEPOSIT","binding_status":"BOUND","path":"registry/substantive/E-08_lease_deposit.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"dbe1886671edff49b8b0251eed567d1b3e4e5d748456434262286ca7acf990db"},{"asset_id":"PROFILE-E-09_REGISTRY_TRANSFER_CLAIMS","binding_status":"BOUND","path":"registry/substantive/E-09_registry_transfer_claims.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"d18946322a8cb528146ac0aa0a2880c41ac2056671fd237b928341ceb8561002"},{"asset_id":"PROFILE-E-10_SECURED_REGISTRY","binding_status":"BOUND","path":"registry/substantive/E-10_secured_registry.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"5819c26ec8478e12a12e340c93a9d23cc410833e1192c2315a1986c9d48a1eba"},{"asset_id":"PROFILE-E-11_POSSESSION_VINDICATION","binding_status":"BOUND","path":"registry/substantive/E-11_possession_vindication.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"5e6d6460be4ec0f2ba0096305b9ae39f5f430d107337d0d7e07aac1a9d599aaf"},{"asset_id":"PROFILE-E-12_CO_OWNERSHIP_BOUNDARY","binding_status":"BOUND","path":"registry/substantive/E-12_co_ownership_boundary.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"62cfbf6a6c5c5edc8b912e348be1c4d4f7dd4c20c722e57e5554058f0caafb4a"},{"asset_id":"PROFILE-E-13_CREDITOR_PRESERVATION","binding_status":"BOUND","path":"registry/substantive/E-13_creditor_preservation.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"c60e6d67c7e3985d1f6ce44027726282f931934e3e66b44f06ccd26845ca2f45"},{"asset_id":"PROFILE-E-14_EXECUTION_LINKED_CLAIMS","binding_status":"BOUND","path":"registry/substantive/E-14_execution_linked_claims.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"45d4b3ab46e1c8834c3b3eec72a28d05e39cb78a9ec2c2de07b5e55e81aeebd7"},{"asset_id":"PROFILE-E-15_SUCCESSION_FAMILY_PROPERTY","binding_status":"BOUND","path":"registry/substantive/E-15_succession_family_property.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"f691b67295ad8e634b34519cf71156caf6eaf73cef54577615ab79462f8aa766"},{"asset_id":"PROFILE-E-16_NEGOTIABLE_INSTRUMENTS","binding_status":"BOUND","path":"registry/substantive/E-16_negotiable_instruments.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"7720d83b64e7a44720788f6ff3c7cc8ceaf5195377a1e61b52de2144989a1194"},{"asset_id":"PROFILE-E-17_LABOR_WAGE_CLAIMS","binding_status":"BOUND","path":"registry/substantive/E-17_labor_wage_claims.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"168ce5e41104937cf7ab946944f060b82cfe16066425897f07bb9e837b8689ea"},{"asset_id":"PROFILE-E-18_ORG_RESOLUTION_STATUS","binding_status":"BOUND","path":"registry/substantive/E-18_org_resolution_status.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"59cf689f886dfaf4ad00dbe6142f5b11c37d0062660f7467aa43427462aa075f"},{"asset_id":"PROFILE-E-19_INSURANCE_CLAIMS","binding_status":"BOUND","path":"registry/substantive/E-19_insurance_claims.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"0fb4793446c155e7a0b4469c9b8c1be1323112eef55ca4c495307c1af56e754c"},{"asset_id":"PROFILE-E-20_IP_CLAIMS","binding_status":"BOUND","path":"registry/substantive/E-20_ip_claims.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"fe07f20d149a2c4deac2e46de299cd78f0bf829f58c615a86c45f542d30804e1"},{"asset_id":"PROFILE-E-21_MEDIA_PERSONALITY_RIGHTS","binding_status":"BOUND","path":"registry/substantive/E-21_media_personality_rights.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"951260bbe8ef116d682f49f3679106c7144ca68f8078f5c10b3459667c1f5b2c"},{"asset_id":"PROFILE-E-00_RESIDUAL_UNROUTED","binding_status":"BOUND","path":"profiles/crosscut/E-00_residual_unrouted.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"639e507147a6132f9e41ccd0b00d1b5450d6a9629991629b173d5bcaf5b6df39"},{"asset_id":"PROFILE-X1_NOTICE_LIFECYCLE","binding_status":"BOUND","path":"profiles/crosscut/X1_notice_lifecycle.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"9af8b5b5f3a8196a10308d1ee34e0788d9adeac7a99e142e449490d14316faef"},{"asset_id":"PROFILE-X2_ASSET_IDENTITY_LINEAGE","binding_status":"BOUND","path":"profiles/crosscut/X2_asset_identity_lineage.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"6c1e437944b3a62b60ee7acad5ec9177fefac2991fe970338acc27efcc8a13ad"},{"asset_id":"PROFILE-X3_PROCEDURE_STANDING_RELIEF","binding_status":"BOUND","path":"profiles/crosscut/X3_procedure_standing_relief.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"f3b794bef82566e569232ba02c63ae148099143d8d1ab84de1c4fb76105e65df"},{"asset_id":"PROFILE-X4_RESPONSE_ADMISSION_DEFENSE","binding_status":"BOUND","path":"profiles/crosscut/X4_response_admission_defense.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"57851ed55b3351a8139df29224d74b7cb8427708bbf6de00ecd27c44089df32e"},{"asset_id":"PROFILE-SL-AUTO_MOTOR_VEHICLE","binding_status":"BOUND","path":"profiles/special_law/SL-AUTO_motor_vehicle.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"7234a7ab890f242e6b7aa811528e34c0c85779007cffbf135da0bfff36d61d91"},{"asset_id":"PROFILE-SL-INDUSTRIAL_ACCIDENT","binding_status":"BOUND","path":"profiles/special_law/SL-INDUSTRIAL_ACCIDENT.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"10d78b8031df7d89f835afc9ca60fab36648e561c729780204c80885f4dd097f"},{"asset_id":"PROFILE-SL-PRODUCT_LIABILITY","binding_status":"BOUND","path":"profiles/special_law/SL-PRODUCT_LIABILITY.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"1d5ee8eddcf005fdb33df58f591a8948aa3e891a3a5656d919394ff0b39eea53"},{"asset_id":"PROFILE-SL-RESIDENTIAL_LEASE","binding_status":"BOUND","path":"profiles/special_law/SL-RESIDENTIAL_LEASE.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"3e2efd1b3c0524a305eafedc5ec91e05be989a6e55c1501ed161a9b8f8151fd7"},{"asset_id":"PROFILE-SL-COMMERCIAL_LEASE","binding_status":"BOUND","path":"profiles/special_law/SL-COMMERCIAL_LEASE.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"5aebed9ab56bc00eb7e0511f9fe5db8c3a42f1e81b28d58c38d487aa91cbab3e"},{"asset_id":"PROFILE-SL-LABOR","binding_status":"BOUND","path":"profiles/special_law/SL-LABOR.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"6b2542bb64f4c1d164b1ccd2ce5099fad29bcea4333d9e34bd0fb1667b9ced4a"},{"asset_id":"PROFILE-SL-STATE_LIABILITY","binding_status":"BOUND","path":"profiles/special_law/SL-STATE_LIABILITY.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"5b2fe6d57b918384a619efbd04360ddfaf7720d384136f69d359ccb0b6c853d3"},{"asset_id":"PROFILE-SL-IP-PATENT","binding_status":"BOUND","path":"profiles/special_law/SL-IP-PATENT.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"d0651a8a50d0b18d25931063314ecec284988c5a18fab68d08a317d725bb3066"},{"asset_id":"PROFILE-SL-IP-COPYRIGHT","binding_status":"BOUND","path":"profiles/special_law/SL-IP-COPYRIGHT.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"d4349677f68346f79709ea23a05957262f6426f976388bba45f05c617035eb78"},{"asset_id":"PROFILE-SL-IP-OTHER","binding_status":"BOUND","path":"profiles/special_law/SL-IP-OTHER.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"fc3e2772252a3a90571663ebcfbc8e18dbf526977f4a3d77c4705ef8aa8dd6a8"},{"asset_id":"PROFILE-SL-MEDIA","binding_status":"BOUND","path":"profiles/special_law/SL-MEDIA.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"e0d5d287befd1578a06c64a265d5c4426af5772b6764018f6a15f00aac3b498c"},{"asset_id":"PROFILE-SL-TRANSPORT_MARITIME","binding_status":"BOUND","path":"profiles/special_law/SL-TRANSPORT_MARITIME.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"6e87a77c25f8c358f1d7d35ca165b1229c2cb422a440c91768ad80e520d35456"},{"asset_id":"PROFILE-SL-CONSUMER_CONTRACT","binding_status":"BOUND","path":"profiles/special_law/SL-CONSUMER_CONTRACT.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"afd8bbba102614d8d08f2e7a5384f6ca24e1309c1f52feb13906613f2ced51b7"},{"asset_id":"PROFILE-ACTIO-MORTGAGE","binding_status":"BOUND","path":"profiles/overlays/ACTIO-MORTGAGE.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"7e584f7b4e4d19132e9575071f87d05965fb77fa2ca870911fe9974a7c511c4d"},{"asset_id":"PROFILE-ACTIO-MORTGAGE-CREATION","binding_status":"BOUND","path":"profiles/overlays/ACTIO-MORTGAGE-CREATION.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"e727690ee23883e011d49eba01cfd87abc5482641c2bda519c0a39518e1769ee"},{"asset_id":"PROFILE-ACTIO-ENCUMBERED-TRANSFER","binding_status":"BOUND","path":"profiles/overlays/ACTIO-ENCUMBERED-TRANSFER.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"fa950393a572829ba7e296c20cd08ff19a063b0f8441f950130fd677b1e38179"},{"asset_id":"PROFILE-ACTIO-PRESERVED-CLAIM-BUNDLE","binding_status":"BOUND","path":"profiles/overlays/ACTIO-PRESERVED-CLAIM-BUNDLE.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"fbd99f029438c1c278f93d88d18a703db72e78f20c7049f344e5748c108f94c5"},{"asset_id":"PROFILE-ACTIO-DEFENSE-MAP","binding_status":"BOUND","path":"profiles/overlays/ACTIO-DEFENSE-MAP.yml","schema_id":"stage2.llm_context_profile.v1","sha256":"05348c493e6046a3e5c55f9b516c0e862fe5aa753e1b2fc71624bb2b11f0c191"}]},"executor_binding_ref":{"asset_id":"BINDING-S2_00-CODE-EXECUTOR","binding_status":"EXTERNAL_TRUST_ROOT_PENDING_LIVE_ADMISSION","path":"deployment/stage2_code_executor_binding.yml","schema_id":"stage2_code_executor_binding.v3"},"loader_binding_ref":{"asset_id":"BINDING-S2_00-LEGACY-REFERENCE","binding_status":"BOUND","path":"deployment/stage2_loader_binding.yml","schema_id":"stage2_loader_binding.reference.v1","sha256":"120313754c597541680a8dc7d9d59c6f8b2438c053553f030ef89171709dd23a"},"module_manifest_ref":{"asset_id":"MANIFEST-MODULE","binding_status":"BOUND","path":"manifest/module_manifest.json","schema_id":"stage2_module_manifest.v1","sha256":"2041e150b1e78c06cb7f24cde1eeb3eaa5ca172a4b740f6b20c1e6dda99bfd38"},"open_items":[{"open_id":"O-07","owner":"release_operator","required_evidence":"signed canary or production admission with current Stage 1 integrity closure","status":"OPEN_RELEASE_AUTHORIZATION"},{"open_id":"CEG-02-DIRECT-MCP-LIVE","owner":"AgentBackend_owner","required_evidence":"live code-executor.run_code outer result and inner single-JSON receipt with exact Agent/code/release binding","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-03-SECRET-INJECTION","owner":"AgentBackend_owner","required_evidence":"backend-injected or pre-registered Code Executor authentication with no plaintext credential in YAML or code","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-04-RUNTIME-IMAGE-PIN","owner":"Code_Executor_owner","required_evidence":"verified Python runtime image digest compatible with the bound httpx dependency","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-05-REQUEST-SIZE-TIMEOUT","owner":"Code_Executor_owner","required_evidence":"representative S2_00 Agent request accepted and completed within backend request-size and 300-second limits","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-06-BINARY-LOCALDOCS","owner":"localdocs_owner","required_evidence":"live read_binary_doc and write_binary_file byte-preservation receipt over the approved path set","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-07-ISOLATION-EGRESS","owner":"AgentBackend_security_owner","required_evidence":"workspace identity substitution and backend-enforced S2_00_LOCALDOCS_ONLY_V1 egress verification","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"CEG-08-BARRIER-ROUTE","owner":"Stage_2_integration_owner","required_evidence":"live status-last logical publish and exactly-one downstream route receipt","status":"OPEN_EXTERNAL_BACKEND"},{"open_id":"DEV-DETACHED-RELEASE-ENVELOPE","owner":"release_operator","required_evidence":"detached signed envelope admits the release and executor binding without a cross-file hash cycle","status":"OPEN_RELEASE_AUTHORIZATION"},{"open_id":"DOWNSTREAM-CASE-TYPE-REGISTRY","owner":"S2_20_case_type_registry_owner","required_evidence":"manifest/case_type_registry.yml exact path/hash and 137-row sign-off; not a direct S2_00 executable dependency","status":"PENDING_SEQUENTIAL_BIND"}],"release_class":"DEV_FIXTURE_RELEASE","release_digest":"829be0e66d32a2bb0e07dca758faccfcfa7692333c1e116e631e11f7b4060815","release_digest_contract":{"algorithm_id":"STAGE2-RELEASE-DIGEST-V1","array_order":"PRESERVE_DECLARED_ORDER","canonicalization_algorithm_id":"STAGE2-CANONICAL-JSON-V1","digest_algorithm":"sha256","digest_scope":"ENTIRE_DOCUMENT_AFTER_REMOVING_TOP_LEVEL_RELEASE_DIGEST","encoding":"UTF-8","line_termination":"LF_ONE_TRAILING_NEWLINE","non_finite_numbers_allowed":false,"object_key_order":"SORT_CODEPOINT"},"release_evidence":[{"evidence_id":"DEV-DRAFT-UNSIGNED-001","input_digest":"c2c6949b6ddfa1b74a048c633413f3452967155bcaa1110bcd41cde3aeceba8b","release_class":"DEV_FIXTURE_RELEASE","scope":"INLINE_CODE_EXECUTOR_AND_STRUCTURED_HANDOFF_OFFLINE_HASH_BOUND_VALIDATION_ONLY","signature":"PENDING_SEQUENTIAL_BIND","signer_id":"UNSIGNED_DRAFT","status":"PENDING_SEQUENTIAL_BIND"}],"release_id":"STAGE2-CLEAN-DEV-DRAFT-S2_00-HYBRID-HANDOFF-2026-08-30","release_status":"DRAFT_NOT_EXECUTABLE","retry_policies":[{"backoff_seconds":[0,1,3],"max_attempts":3,"non_retryable_classes":["HASH","SCHEMA","PRODUCER","CONSERVATION","RUN_BINDING"],"retry_policy_id":"S2-RETRY-TRANSIENT-READ-V1","retryable_codes":["TRANSIENT_READ_ERROR","TRANSIENT_LOCK_ERROR"]}],"schema_version":"stage2_release.v2","signature":"PENDING_SEQUENTIAL_BIND","stage1_sources":[{"adapter_id":"S2A-EVIDENCE-V3-ENVELOPE-V1","logical_input_id":"evidence_indexed","path":"evidence_indexed.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_B1_quality_gate_evidence_indexed","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_contract_version","items"],"requirement_class":"EVIDENCE_EVENT_SCOPE","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-EVENTS-V1-ENVELOPE-V1","logical_input_id":"evidence_event_candidates","path":"evidence_event_candidates.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_B2_quality_gate_event_candidates","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_version","items"],"requirement_class":"EVIDENCE_EVENT_SCOPE","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-CLIENT-GOAL-V8-V1","logical_input_id":"client_goal","path":"client_goal.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_A_client_goal","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["primary_goal","constraints","parties"],"requirement_class":"OPTIMIZATION_CONTEXT","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-DOMAIN-SCREENING-V1","logical_input_id":"domain_screening","path":"routing/domain_screening.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_A0_domain_screener_02","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["domain_screening"],"requirement_class":"ROUTING_PROFILE_BACKBONE","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-DUAL-SG01-V1","logical_input_id":"domain_activation_manifest","path":"routing/domain_activation_manifest.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_D0_domain_activation_gate","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["domain_activation_manifest"],"requirement_class":"ROUTING_PROFILE_BACKBONE","run_identity_pointer":null,"schema_ref":{"$id":"https://schemas.liti-agent.local/stage1/s5/domain_activation_manifest.schema.json","path":"signals/schemas/domain_activation_manifest.schema.json","sha256":"013a6ebd230ebe46dda665af9f6c4448b267444b44e7b8f701f2fae80a2ee92a"},"transaction_identity_pointer":null},{"adapter_id":"S2A-B1-GATE-V1","logical_input_id":"b1_evidence_indexed_gate","path":"quality_gates/B1_evidence_indexed_gate.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_B12_gate_audit_finalizer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_contract_version","gate_id","overall_severity","hard_gate_findings","review_findings","stage2_auto_progression_allowed"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-B2-GATE-V1","logical_input_id":"b2_event_candidates_gate","path":"quality_gates/B2_event_candidates_gate.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_B12_gate_audit_finalizer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_contract_version","gate_id","overall_severity","hard_gate_findings","review_findings","stage2_auto_progression_allowed"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-P1-HANDOFF-FLAT-V1","logical_input_id":"stage1_part1_soft_gate_handoff","path":"quality_gates/stage1_part1_soft_gate_handoff.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_B2_SHA256_soft_gate_handoff_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_version","handoff_status","review_items","stage2_auto_progression_allowed","hard_gate_summary","review_item_conservation","digest_guard"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-BO-V8-LIST-V1","logical_input_id":"bo","path":"BO.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_BO_F0_final_bo_compiler_gate_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":[],"requirement_class":"IDENTITY_BACKBONE","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-SIGNAL-ALL-V1","logical_input_id":"signal_manifest","path":"signals/signal_manifest.json","path_rule":null,"producer_alias_id":"PA-SG-COMPILER-001","producer_id":"Task_C_BO_S0_signal_bundle_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["files","downstream_read_sets"],"requirement_class":"ROUTING_PROFILE_BACKBONE","run_identity_pointer":null,"schema_ref":{"$id":"https://schemas.liti-agent.local/stage1/s5/signal_manifest.schema.json","path":"signals/schemas/signal_manifest.schema.json","sha256":"5e72084780b82b29582c9ffcf48f3e4894d7c0b152e5ce8df394583c07dde681"},"transaction_identity_pointer":"/transaction_id"},{"adapter_id":"S2A-P2-HANDOFF-FLAT-V1","logical_input_id":"stage1_part2_review_handoff","path":"quality_gates/stage1_part2_review_handoff.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_BO_F0_final_bo_compiler_gate_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_version","status","review_items"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-LES-CURRENT-V8-V1","logical_input_id":"legal_effect_structures","path":"legal_effect_structures.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_LE_L2_final_structure_index_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":[],"requirement_class":"ROUTING_PROFILE_BACKBONE","run_identity_pointer":null,"schema_ref":{"$id":"https://schemas.liti-agent.local/stage1/part3/legal_effect_structures.schema.json","path":"platform/schemas/legal_effect_structures.schema.json","sha256":"fc962e8ae39f9bede64ba017297eded6413689204a065e00c3b3bdca8f1854df"},"transaction_identity_pointer":"/signal_manifest_transaction_id"},{"adapter_id":"S2A-P3-HANDOFF-WRAPPED-V1","logical_input_id":"stage1_part3_review_handoff","path":"quality_gates/stage1_part3_review_handoff.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_LE_L2_final_structure_index_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["stage1_part3_review_handoff"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-FACT-LEDGER-CURRENT-V8-V1","logical_input_id":"fact_ledger_base","path":"Fact_Ledger_base.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_FL_F2_final_fact_ledger_gate_and_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":[],"requirement_class":"IDENTITY_BACKBONE","run_identity_pointer":null,"schema_ref":{"$id":"https://schemas.liti-agent.local/stage1/part4/fact_ledger_base.schema.json","path":"platform/schemas/fact_ledger_base.schema.json","sha256":"b3f0e79ecb4c2f720f3e07e89154aadbd2327e4129cc703569fb5635240d2fe8"},"transaction_identity_pointer":null},{"adapter_id":"S2A-FACT-LEDGER-WRITER-REPORT-V1","logical_input_id":"fact_ledger_writer_report","path":"stage1_tmp/fact_ledger/fact_ledger_writer_report.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_FL_F2_final_fact_ledger_gate_and_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["schema_version"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-P4-HANDOFF-WRAPPED-V1","logical_input_id":"stage1_part4_review_handoff","path":"quality_gates/stage1_part4_review_handoff.json","path_rule":null,"producer_alias_id":null,"producer_id":"Task_C_FL_F2_final_fact_ledger_gate_and_writer","raw_hash_source":"UNAVAILABLE_DEV","required_keys":["stage1_part4_review_handoff"],"requirement_class":"INTEGRITY_CORROBORATOR","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null},{"adapter_id":"S2A-SIGNAL-ALL-V1","logical_input_id":"signal_payload_family","path":null,"path_rule":"signals/","producer_alias_id":"PA-SG-COMPILER-001","producer_id":"Task_C_BO_S0_signal_bundle_writer","raw_hash_source":"MANIFEST_ROW","required_keys":[],"requirement_class":"SIGNAL_PAYLOAD","run_identity_pointer":null,"schema_ref":null,"transaction_identity_pointer":null}]} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_release_manifests.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_release_manifests.py index cf4016fa..b3a45a11 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_release_manifests.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_release_manifests.py @@ -15,7 +15,8 @@ import hashlib import json import os from pathlib import Path, PurePosixPath -from typing import Any, Iterable +import re +from typing import Any, Iterable, Mapping MODULE_MANIFEST_SCHEMA = "stage2_module_manifest.v1" @@ -53,9 +54,145 @@ FORBIDDEN_PARENT_MEMBERS = frozenset( "manifest/s2_30_model_benchmark_receipt.json", "manifest/s2_30_legal_review_receipt.json", "manifest/s2_30_release.json", + "agent_scripts/Stage_2_S2_40.yml", + "runtime/s2_40_commit.py", + "runtime/s2_40_commit.txt", + "manifest/s2_40_inline_code_receipt.json", } ) +STAGE_GENERIC_METADATA = { + "S2_20": { + "asset_version": "s2_20.1", + "module_id_prefix": "S2_20-ASSET", + "owner": "Stage_2_S2_20_owner", + "schema_version": "stage2_s2_20_generic_asset.v1", + "scope_predicate": "workflow_id == S2_20", + }, + "S2_30": { + "asset_version": "s2_30.1", + "module_id_prefix": "S2_30-ASSET", + "owner": "Stage_2_S2_30_owner", + "schema_version": "stage2_s2_30_generic_asset.v1", + "scope_predicate": "workflow_id == S2_30", + }, + "S2_40": { + "asset_version": "s2_40.1", + "module_id_prefix": "S2_40-ASSET", + "owner": "Stage_2_S2_40_owner", + "schema_version": "stage2_s2_40_generic_asset.v1", + "scope_predicate": "workflow_id == S2_40", + }, +} + +S2_40_WORKFLOW_PATH = "workflows/S2_40_final_review_render_and_commit.yml" +S2_40_TRANSITIONED_STUB_VALUES = frozenset( + { + "WF-S2_40-STATUS-ONLY", + "s2_40.status_only.1", + "DRAFT_HANDOFF_STUB_HASH_BOUND", + "entrypoint_id == S2_40_STATUS_ONLY", + } +) +S2_40_WORKFLOW_METADATA: dict[str, Any] = { + "asset_version": "s2_40.finalizer.1", + "authority_ids": [], + "consumed_schema_ids": [ + "https://schemas.liti-agent.local/stage2/s2_00/context.schema.v2.json", + "https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_10/s2_10.schema.v2.json", + "https://schemas.liti-agent.local/stage2/s2_20/binding_retrieval.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_20/calculation.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_20/relief_plan.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_30/draft_atoms.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_40/package.schema.v1.json", + "https://schemas.liti-agent.local/stage2/shared/deployment.schema.v3.json", + "https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json", + ], + "dependency_module_ids": [ + "SCHEMA-CONTEXT", + "SCHEMA-DEPLOYMENT", + "SCHEMA-INGRESS", + "SCHEMA-REVIEW-STATUS", + "SCHEMA-S2_10", + "S2_20-ASSET-809C3C709B4F2295", + "S2_20-ASSET-AA40CF5140DE8790", + "S2_20-ASSET-C9FC917D8CBF920E", + "S2_20-ASSET-E82839694073D431", + "S2_20-ASSET-FF1F03B3FC56E579", + "S2_30-ASSET-6A9B1F5EC854740E", + "S2_30-ASSET-E1FCF8BD63300F4D", + "S2_40-ASSET-5C4CAFFAB8D2F982", + "WF-S2_00", + "WF-S2_10", + ], + "entry_routes": ["TO_S2_40", "TO_S2_40_STATUS_ONLY"], + "forbidden_contract_codes": [ + "LEGACY-STAGE2-V0-V3", + "S2_40-DIRECTORY-SCAN", + "S2_40-FREE-TEXT-RENDER-FALLBACK", + "S2_40-LLM-CALL", + "S2_40-RUN-STATUS-NOT-LAST", + "S2_40-UNVERIFIED-READY", + ], + "implementation_status": "IMPLEMENTED_OFFLINE_CONTRACT_LIVE_ADMISSION_PENDING", + "incompatible_module_ids": [], + "inputs": [ + "ingress/ingress_status.json", + "ingress/technical_diagnostic.json", + "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", + "review/issue_ledger.base.json", + "map_s2_10/s2_10_publish_status.json", + "plan/plan_publish_status.json", + "plan/canonical_relief_plan.json", + "plan/claim_groups.json", + "plan/case_type_bindings.json", + "map_s2_30/s2_30_publish_status.json", + "map_s2_30/artifact_manifest.json", + "map_s2_30/{draft_parts,issue_patches,worknote_parts,usage_parts}/.json", + "review/review_receipts/.json", + "review/lawyer_judgment_record.json", + ], + "legal_admission_status": "PENDING", + "live_admission_status": "PENDING", + "module_id": "WF-S2_40", + "module_kind": "WORKFLOW", + "outputs": [ + "review/issue_ledger.final.json", + "review/assumption_ledger.json", + "review/llm_usage.jsonl", + "candidates/by-content-digest//", + "review/review_requests/.json", + "final/claim_relief.md", + "final/claim_cause.md", + "final/pleading_draft.md", + "final/stage2_package.json", + "commit/commit_intent.json", + "commit/stage2_commit_result.json", + "control/run_status.json", + ], + "owner": "Stage_2_S2_40_owner", + "path": S2_40_WORKFLOW_PATH, + "produced_schema_ids": [ + "stage2_s2_40_candidate_manifest.v1", + "stage2_s2_40_commit_intent.v1", + "stage2_s2_40_commit_result.v1", + "stage2_s2_40_package.v1", + "stage2_s2_40_run_status.v1", + ], + "schema_version": "stage2_workflow_contract.v1", + "scope_predicate": "workflow_id == S2_40 and entry_route in {TO_S2_40,TO_S2_40_STATUS_ONLY}", + "semantic_review_status": "PENDING_LEGAL_AND_LIVE_ADMISSION", + "status_only_exact_inputs": [ + "ingress/ingress_status.json", + "ingress/technical_diagnostic.json", + "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", + "review/issue_ledger.base.json", + ], +} + class ReleaseBuildError(ValueError): """Raised when a release input violates the canonical closure contract.""" @@ -151,7 +288,7 @@ def _mirror_for(root: Path, source_path: str) -> tuple[str, bytes] | None: return mirror_path, mirror_raw -def _generic_kind(relative: str) -> str: +def _generic_kind(relative: str, owner_stage: str = "S2_20") -> str: if relative.startswith("tests/"): return "TEST" if relative.startswith("schemas/"): @@ -168,13 +305,16 @@ def _generic_kind(relative: str) -> str: return "MANIFEST" if relative.startswith("registry/"): return "DECLARATIVE_REGISTRY" - return "S2_20_ASSET" + return f"{owner_stage}_ASSET" -def _generic_module_row(relative: str) -> dict[str, Any]: +def _generic_module_row(relative: str, owner_stage: str = "S2_20") -> dict[str, Any]: + metadata = STAGE_GENERIC_METADATA.get(owner_stage) + if metadata is None: + raise ReleaseBuildError(f"UNSUPPORTED_PARENT_MEMBER_OWNER_STAGE:{owner_stage}") identity = hashlib.sha256(relative.encode("utf-8")).hexdigest()[:16].upper() return { - "asset_version": "s2_20.1", + "asset_version": metadata["asset_version"], "authority_ids": [], "consumed_schema_ids": [], "dependency_module_ids": [], @@ -182,18 +322,70 @@ def _generic_module_row(relative: str) -> dict[str, Any]: "implementation_status": "DEV_HASH_BOUND_OFFLINE_ONLY", "incompatible_module_ids": [], "inputs": [], - "module_id": f"S2_20-ASSET-{identity}", - "module_kind": _generic_kind(relative), + "module_id": f"{metadata['module_id_prefix']}-{identity}", + "module_kind": _generic_kind(relative, owner_stage), "outputs": [], - "owner": "Stage_2_S2_20_owner", + "owner": metadata["owner"], "path": relative, "produced_schema_ids": [], - "schema_version": "stage2_s2_20_generic_asset.v1", - "scope_predicate": "workflow_id == S2_20", + "schema_version": metadata["schema_version"], + "scope_predicate": metadata["scope_predicate"], "semantic_review_status": "PENDING_LEGAL_AND_LIVE_ADMISSION", } +def _s2_40_workflow_module_row() -> dict[str, Any]: + """Return the authoritative full S2_40 workflow row. + + The pre-S2_40 parent template carried a status-only stub row at the same + physical path. Preserving that semantic metadata while merely refreshing + its file hash would make the release closure describe a different workflow + than the bytes it seals. + """ + + return copy.deepcopy(S2_40_WORKFLOW_METADATA) + + +def _assert_no_transitioned_s2_40_stub(rows: Iterable[Mapping[str, Any]]) -> None: + for row in rows: + if row.get("path") != S2_40_WORKFLOW_PATH: + continue + observed = { + row.get("module_id"), + row.get("asset_version"), + row.get("implementation_status"), + row.get("scope_predicate"), + } + stale = sorted(str(value) for value in observed & S2_40_TRANSITIONED_STUB_VALUES) + if stale: + raise ReleaseBuildError(f"S2_40_TRANSITIONED_STUB_METADATA_FORBIDDEN:{stale}") + drift = { + key: {"expected": expected, "observed": row.get(key)} + for key, expected in S2_40_WORKFLOW_METADATA.items() + if row.get(key) != expected + } + if drift: + raise ReleaseBuildError( + "S2_40_WORKFLOW_METADATA_MISMATCH:" + + json.dumps(drift, ensure_ascii=False, sort_keys=True) + ) + + +def _is_generic_module_row(row: Mapping[str, Any]) -> bool: + schema_version = row.get("schema_version") + module_id = row.get("module_id") + return ( + schema_version in { + metadata["schema_version"] for metadata in STAGE_GENERIC_METADATA.values() + } + or isinstance(module_id, str) + and any( + module_id.startswith(f"{metadata['module_id_prefix']}-") + for metadata in STAGE_GENERIC_METADATA.values() + ) + ) + + def _refresh_module_row(root: Path, row: dict[str, Any]) -> dict[str, Any]: refreshed = copy.deepcopy(row) relative = _relative_path(refreshed.get("path")) @@ -234,8 +426,9 @@ def build_module_manifest( root: Path, template: dict[str, Any], explicit_paths: Iterable[str], + path_owners: Mapping[str, str] | None = None, ) -> dict[str, Any]: - """Preserve canonical rows, refresh physical bindings and append S2_20 rows.""" + """Refresh canonical rows and append stage-owned generic source rows.""" if template.get("schema_version") != MODULE_MANIFEST_SCHEMA: raise ReleaseBuildError("CANONICAL_MODULE_MANIFEST_V1_REQUIRED") @@ -249,6 +442,14 @@ def build_module_manifest( forbidden = sorted(set(normalized_explicit) & FORBIDDEN_PARENT_MEMBERS) if forbidden: raise ReleaseBuildError(f"NON_CYCLIC_PARENT_VIOLATION:{forbidden}") + normalized_owners: dict[str, str] = {} + for raw_path, owner_stage in (path_owners or {}).items(): + relative = _relative_path(raw_path) + if relative not in normalized_explicit: + raise ReleaseBuildError(f"OWNER_PATH_NOT_IN_EXPLICIT_CLOSURE:{relative}") + if owner_stage not in STAGE_GENERIC_METADATA: + raise ReleaseBuildError(f"UNSUPPORTED_PARENT_MEMBER_OWNER_STAGE:{owner_stage}") + normalized_owners[relative] = owner_stage result = copy.deepcopy(template) refreshed_rows: list[dict[str, Any]] = [] @@ -263,9 +464,28 @@ def build_module_manifest( raise ReleaseBuildError(f"MODULE_ID_INVALID_OR_DUPLICATE:{module_id!r}") if relative in seen_paths: raise ReleaseBuildError(f"MODULE_PATH_DUPLICATE:{relative}") - seen_ids.add(module_id) + owner_stage = normalized_owners.get(relative) + if relative == S2_40_WORKFLOW_PATH: + if owner_stage not in {None, "S2_40"}: + raise ReleaseBuildError( + f"S2_40_WORKFLOW_OWNER_STAGE_MISMATCH:{owner_stage}" + ) + candidate = _s2_40_workflow_module_row() + else: + candidate = ( + _generic_module_row(relative, owner_stage) + if owner_stage is not None and _is_generic_module_row(value) + else value + ) + refreshed = _refresh_module_row(root, candidate) + refreshed_id = refreshed.get("module_id") + if not isinstance(refreshed_id, str) or not refreshed_id: + raise ReleaseBuildError(f"MODULE_ID_INVALID_OR_DUPLICATE:{refreshed_id!r}") + if refreshed_id in seen_ids: + raise ReleaseBuildError(f"MODULE_ID_INVALID_OR_DUPLICATE:{refreshed_id!r}") + seen_ids.add(refreshed_id) seen_paths.add(relative) - refreshed_rows.append(_refresh_module_row(root, value)) + refreshed_rows.append(refreshed) explicit_set = set(normalized_explicit) for relative in sorted(normalized_explicit): @@ -278,13 +498,19 @@ def build_module_manifest( continue if relative in seen_paths: continue - row = _refresh_module_row(root, _generic_module_row(relative)) + candidate = ( + _s2_40_workflow_module_row() + if relative == S2_40_WORKFLOW_PATH + else _generic_module_row(relative, normalized_owners.get(relative, "S2_20")) + ) + row = _refresh_module_row(root, candidate) if row["module_id"] in seen_ids: raise ReleaseBuildError(f"GENERATED_MODULE_ID_COLLISION:{row['module_id']}") seen_ids.add(row["module_id"]) seen_paths.add(relative) refreshed_rows.append(row) + _assert_no_transitioned_s2_40_stub(refreshed_rows) result["modules"] = refreshed_rows mirrors = [entry for row in refreshed_rows if (entry := _documentation_mirror(row))] mirror_sources = [str(entry["source_path"]) for entry in mirrors] @@ -312,6 +538,24 @@ def build_module_manifest( for row in refreshed_rows if row.get("schema_version") == "stage2_s2_20_generic_asset.v1" ), + "s2_30_generic_module_count": sum( + 1 + for row in refreshed_rows + if row.get("schema_version") == "stage2_s2_30_generic_asset.v1" + ), + "s2_40_generic_module_count": sum( + 1 + for row in refreshed_rows + if row.get("schema_version") == "stage2_s2_40_generic_asset.v1" + ), + "generic_module_counts_by_stage": { + stage: sum( + 1 + for row in refreshed_rows + if row.get("schema_version") == metadata["schema_version"] + ) + for stage, metadata in sorted(STAGE_GENERIC_METADATA.items()) + }, "executable_agent_hash_included": False, "executor_binding_hash_included": False, "inline_runtime_code_hash_included": False, @@ -431,8 +675,14 @@ def build_release_package( path_list: list[str], module_template: dict[str, Any], parent_template: dict[str, Any], + path_owners: Mapping[str, str] | None = None, ) -> tuple[dict[str, Any], dict[str, Any]]: - module_manifest = build_module_manifest(root, module_template, path_list) + module_manifest = build_module_manifest( + root, + module_template, + path_list, + path_owners=path_owners, + ) module_raw = _canonical_bytes(module_manifest) parent_release = build_parent_release(root, parent_template, module_raw) return module_manifest, parent_release @@ -445,6 +695,13 @@ def _write_bytes(path: Path, raw: bytes) -> None: os.replace(temporary, path) +def _owner_stage_from_path_list(path: Path) -> str: + match = re.fullmatch(r"s2_(20|30|40)_parent_member_paths\.json", path.name) + if match is None: + raise ReleaseBuildError(f"PARENT_PATH_LIST_OWNER_UNRESOLVED:{path.as_posix()}") + return f"S2_{match.group(1)}" + + def main() -> int: parser = argparse.ArgumentParser( description="Reseal canonical Stage-2 module and parent release manifests" @@ -476,20 +733,22 @@ def main() -> int: ) args = parser.parse_args() - path_lists: list[list[str]] = [] + path_lists: list[tuple[str, list[str]]] = [] for source in [args.path_list, *args.additional_path_list]: loaded = _load_json(source) if not isinstance(loaded, list) or not all(isinstance(row, str) for row in loaded): raise ReleaseBuildError(f"PATH_LIST_MUST_BE_STRING_ARRAY:{source.as_posix()}") - path_lists.append(loaded) + path_lists.append((_owner_stage_from_path_list(source), loaded)) seen_paths: set[str] = set() path_list: list[str] = [] - for rows in path_lists: + path_owners: dict[str, str] = {} + for owner_stage, rows in path_lists: overlap = sorted(seen_paths & set(rows)) if overlap: raise ReleaseBuildError(f"PARENT_PATH_LISTS_MUST_BE_DISJOINT:{overlap}") seen_paths.update(rows) path_list.extend(rows) + path_owners.update({row: owner_stage for row in rows}) path_list.sort() module_template_path = args.module_template or args.root / "manifest/module_manifest.json" parent_template_path = args.parent_template or args.root / "manifest/stage2_release.json" @@ -499,6 +758,7 @@ def main() -> int: path_list, _load_json(module_template_path), _load_json(parent_template_path), + path_owners=path_owners, ) _write_bytes(args.output, _canonical_bytes(module_manifest)) _write_bytes(parent_output, _canonical_bytes(parent_release)) diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_release_manifests.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_release_manifests.txt index cf4016fa..b3a45a11 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_release_manifests.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_release_manifests.txt @@ -15,7 +15,8 @@ import hashlib import json import os from pathlib import Path, PurePosixPath -from typing import Any, Iterable +import re +from typing import Any, Iterable, Mapping MODULE_MANIFEST_SCHEMA = "stage2_module_manifest.v1" @@ -53,9 +54,145 @@ FORBIDDEN_PARENT_MEMBERS = frozenset( "manifest/s2_30_model_benchmark_receipt.json", "manifest/s2_30_legal_review_receipt.json", "manifest/s2_30_release.json", + "agent_scripts/Stage_2_S2_40.yml", + "runtime/s2_40_commit.py", + "runtime/s2_40_commit.txt", + "manifest/s2_40_inline_code_receipt.json", } ) +STAGE_GENERIC_METADATA = { + "S2_20": { + "asset_version": "s2_20.1", + "module_id_prefix": "S2_20-ASSET", + "owner": "Stage_2_S2_20_owner", + "schema_version": "stage2_s2_20_generic_asset.v1", + "scope_predicate": "workflow_id == S2_20", + }, + "S2_30": { + "asset_version": "s2_30.1", + "module_id_prefix": "S2_30-ASSET", + "owner": "Stage_2_S2_30_owner", + "schema_version": "stage2_s2_30_generic_asset.v1", + "scope_predicate": "workflow_id == S2_30", + }, + "S2_40": { + "asset_version": "s2_40.1", + "module_id_prefix": "S2_40-ASSET", + "owner": "Stage_2_S2_40_owner", + "schema_version": "stage2_s2_40_generic_asset.v1", + "scope_predicate": "workflow_id == S2_40", + }, +} + +S2_40_WORKFLOW_PATH = "workflows/S2_40_final_review_render_and_commit.yml" +S2_40_TRANSITIONED_STUB_VALUES = frozenset( + { + "WF-S2_40-STATUS-ONLY", + "s2_40.status_only.1", + "DRAFT_HANDOFF_STUB_HASH_BOUND", + "entrypoint_id == S2_40_STATUS_ONLY", + } +) +S2_40_WORKFLOW_METADATA: dict[str, Any] = { + "asset_version": "s2_40.finalizer.1", + "authority_ids": [], + "consumed_schema_ids": [ + "https://schemas.liti-agent.local/stage2/s2_00/context.schema.v2.json", + "https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_10/s2_10.schema.v2.json", + "https://schemas.liti-agent.local/stage2/s2_20/binding_retrieval.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_20/calculation.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_20/relief_plan.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_30/draft_atoms.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_40/package.schema.v1.json", + "https://schemas.liti-agent.local/stage2/shared/deployment.schema.v3.json", + "https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json", + ], + "dependency_module_ids": [ + "SCHEMA-CONTEXT", + "SCHEMA-DEPLOYMENT", + "SCHEMA-INGRESS", + "SCHEMA-REVIEW-STATUS", + "SCHEMA-S2_10", + "S2_20-ASSET-809C3C709B4F2295", + "S2_20-ASSET-AA40CF5140DE8790", + "S2_20-ASSET-C9FC917D8CBF920E", + "S2_20-ASSET-E82839694073D431", + "S2_20-ASSET-FF1F03B3FC56E579", + "S2_30-ASSET-6A9B1F5EC854740E", + "S2_30-ASSET-E1FCF8BD63300F4D", + "S2_40-ASSET-5C4CAFFAB8D2F982", + "WF-S2_00", + "WF-S2_10", + ], + "entry_routes": ["TO_S2_40", "TO_S2_40_STATUS_ONLY"], + "forbidden_contract_codes": [ + "LEGACY-STAGE2-V0-V3", + "S2_40-DIRECTORY-SCAN", + "S2_40-FREE-TEXT-RENDER-FALLBACK", + "S2_40-LLM-CALL", + "S2_40-RUN-STATUS-NOT-LAST", + "S2_40-UNVERIFIED-READY", + ], + "implementation_status": "IMPLEMENTED_OFFLINE_CONTRACT_LIVE_ADMISSION_PENDING", + "incompatible_module_ids": [], + "inputs": [ + "ingress/ingress_status.json", + "ingress/technical_diagnostic.json", + "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", + "review/issue_ledger.base.json", + "map_s2_10/s2_10_publish_status.json", + "plan/plan_publish_status.json", + "plan/canonical_relief_plan.json", + "plan/claim_groups.json", + "plan/case_type_bindings.json", + "map_s2_30/s2_30_publish_status.json", + "map_s2_30/artifact_manifest.json", + "map_s2_30/{draft_parts,issue_patches,worknote_parts,usage_parts}/.json", + "review/review_receipts/.json", + "review/lawyer_judgment_record.json", + ], + "legal_admission_status": "PENDING", + "live_admission_status": "PENDING", + "module_id": "WF-S2_40", + "module_kind": "WORKFLOW", + "outputs": [ + "review/issue_ledger.final.json", + "review/assumption_ledger.json", + "review/llm_usage.jsonl", + "candidates/by-content-digest//", + "review/review_requests/.json", + "final/claim_relief.md", + "final/claim_cause.md", + "final/pleading_draft.md", + "final/stage2_package.json", + "commit/commit_intent.json", + "commit/stage2_commit_result.json", + "control/run_status.json", + ], + "owner": "Stage_2_S2_40_owner", + "path": S2_40_WORKFLOW_PATH, + "produced_schema_ids": [ + "stage2_s2_40_candidate_manifest.v1", + "stage2_s2_40_commit_intent.v1", + "stage2_s2_40_commit_result.v1", + "stage2_s2_40_package.v1", + "stage2_s2_40_run_status.v1", + ], + "schema_version": "stage2_workflow_contract.v1", + "scope_predicate": "workflow_id == S2_40 and entry_route in {TO_S2_40,TO_S2_40_STATUS_ONLY}", + "semantic_review_status": "PENDING_LEGAL_AND_LIVE_ADMISSION", + "status_only_exact_inputs": [ + "ingress/ingress_status.json", + "ingress/technical_diagnostic.json", + "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", + "review/issue_ledger.base.json", + ], +} + class ReleaseBuildError(ValueError): """Raised when a release input violates the canonical closure contract.""" @@ -151,7 +288,7 @@ def _mirror_for(root: Path, source_path: str) -> tuple[str, bytes] | None: return mirror_path, mirror_raw -def _generic_kind(relative: str) -> str: +def _generic_kind(relative: str, owner_stage: str = "S2_20") -> str: if relative.startswith("tests/"): return "TEST" if relative.startswith("schemas/"): @@ -168,13 +305,16 @@ def _generic_kind(relative: str) -> str: return "MANIFEST" if relative.startswith("registry/"): return "DECLARATIVE_REGISTRY" - return "S2_20_ASSET" + return f"{owner_stage}_ASSET" -def _generic_module_row(relative: str) -> dict[str, Any]: +def _generic_module_row(relative: str, owner_stage: str = "S2_20") -> dict[str, Any]: + metadata = STAGE_GENERIC_METADATA.get(owner_stage) + if metadata is None: + raise ReleaseBuildError(f"UNSUPPORTED_PARENT_MEMBER_OWNER_STAGE:{owner_stage}") identity = hashlib.sha256(relative.encode("utf-8")).hexdigest()[:16].upper() return { - "asset_version": "s2_20.1", + "asset_version": metadata["asset_version"], "authority_ids": [], "consumed_schema_ids": [], "dependency_module_ids": [], @@ -182,18 +322,70 @@ def _generic_module_row(relative: str) -> dict[str, Any]: "implementation_status": "DEV_HASH_BOUND_OFFLINE_ONLY", "incompatible_module_ids": [], "inputs": [], - "module_id": f"S2_20-ASSET-{identity}", - "module_kind": _generic_kind(relative), + "module_id": f"{metadata['module_id_prefix']}-{identity}", + "module_kind": _generic_kind(relative, owner_stage), "outputs": [], - "owner": "Stage_2_S2_20_owner", + "owner": metadata["owner"], "path": relative, "produced_schema_ids": [], - "schema_version": "stage2_s2_20_generic_asset.v1", - "scope_predicate": "workflow_id == S2_20", + "schema_version": metadata["schema_version"], + "scope_predicate": metadata["scope_predicate"], "semantic_review_status": "PENDING_LEGAL_AND_LIVE_ADMISSION", } +def _s2_40_workflow_module_row() -> dict[str, Any]: + """Return the authoritative full S2_40 workflow row. + + The pre-S2_40 parent template carried a status-only stub row at the same + physical path. Preserving that semantic metadata while merely refreshing + its file hash would make the release closure describe a different workflow + than the bytes it seals. + """ + + return copy.deepcopy(S2_40_WORKFLOW_METADATA) + + +def _assert_no_transitioned_s2_40_stub(rows: Iterable[Mapping[str, Any]]) -> None: + for row in rows: + if row.get("path") != S2_40_WORKFLOW_PATH: + continue + observed = { + row.get("module_id"), + row.get("asset_version"), + row.get("implementation_status"), + row.get("scope_predicate"), + } + stale = sorted(str(value) for value in observed & S2_40_TRANSITIONED_STUB_VALUES) + if stale: + raise ReleaseBuildError(f"S2_40_TRANSITIONED_STUB_METADATA_FORBIDDEN:{stale}") + drift = { + key: {"expected": expected, "observed": row.get(key)} + for key, expected in S2_40_WORKFLOW_METADATA.items() + if row.get(key) != expected + } + if drift: + raise ReleaseBuildError( + "S2_40_WORKFLOW_METADATA_MISMATCH:" + + json.dumps(drift, ensure_ascii=False, sort_keys=True) + ) + + +def _is_generic_module_row(row: Mapping[str, Any]) -> bool: + schema_version = row.get("schema_version") + module_id = row.get("module_id") + return ( + schema_version in { + metadata["schema_version"] for metadata in STAGE_GENERIC_METADATA.values() + } + or isinstance(module_id, str) + and any( + module_id.startswith(f"{metadata['module_id_prefix']}-") + for metadata in STAGE_GENERIC_METADATA.values() + ) + ) + + def _refresh_module_row(root: Path, row: dict[str, Any]) -> dict[str, Any]: refreshed = copy.deepcopy(row) relative = _relative_path(refreshed.get("path")) @@ -234,8 +426,9 @@ def build_module_manifest( root: Path, template: dict[str, Any], explicit_paths: Iterable[str], + path_owners: Mapping[str, str] | None = None, ) -> dict[str, Any]: - """Preserve canonical rows, refresh physical bindings and append S2_20 rows.""" + """Refresh canonical rows and append stage-owned generic source rows.""" if template.get("schema_version") != MODULE_MANIFEST_SCHEMA: raise ReleaseBuildError("CANONICAL_MODULE_MANIFEST_V1_REQUIRED") @@ -249,6 +442,14 @@ def build_module_manifest( forbidden = sorted(set(normalized_explicit) & FORBIDDEN_PARENT_MEMBERS) if forbidden: raise ReleaseBuildError(f"NON_CYCLIC_PARENT_VIOLATION:{forbidden}") + normalized_owners: dict[str, str] = {} + for raw_path, owner_stage in (path_owners or {}).items(): + relative = _relative_path(raw_path) + if relative not in normalized_explicit: + raise ReleaseBuildError(f"OWNER_PATH_NOT_IN_EXPLICIT_CLOSURE:{relative}") + if owner_stage not in STAGE_GENERIC_METADATA: + raise ReleaseBuildError(f"UNSUPPORTED_PARENT_MEMBER_OWNER_STAGE:{owner_stage}") + normalized_owners[relative] = owner_stage result = copy.deepcopy(template) refreshed_rows: list[dict[str, Any]] = [] @@ -263,9 +464,28 @@ def build_module_manifest( raise ReleaseBuildError(f"MODULE_ID_INVALID_OR_DUPLICATE:{module_id!r}") if relative in seen_paths: raise ReleaseBuildError(f"MODULE_PATH_DUPLICATE:{relative}") - seen_ids.add(module_id) + owner_stage = normalized_owners.get(relative) + if relative == S2_40_WORKFLOW_PATH: + if owner_stage not in {None, "S2_40"}: + raise ReleaseBuildError( + f"S2_40_WORKFLOW_OWNER_STAGE_MISMATCH:{owner_stage}" + ) + candidate = _s2_40_workflow_module_row() + else: + candidate = ( + _generic_module_row(relative, owner_stage) + if owner_stage is not None and _is_generic_module_row(value) + else value + ) + refreshed = _refresh_module_row(root, candidate) + refreshed_id = refreshed.get("module_id") + if not isinstance(refreshed_id, str) or not refreshed_id: + raise ReleaseBuildError(f"MODULE_ID_INVALID_OR_DUPLICATE:{refreshed_id!r}") + if refreshed_id in seen_ids: + raise ReleaseBuildError(f"MODULE_ID_INVALID_OR_DUPLICATE:{refreshed_id!r}") + seen_ids.add(refreshed_id) seen_paths.add(relative) - refreshed_rows.append(_refresh_module_row(root, value)) + refreshed_rows.append(refreshed) explicit_set = set(normalized_explicit) for relative in sorted(normalized_explicit): @@ -278,13 +498,19 @@ def build_module_manifest( continue if relative in seen_paths: continue - row = _refresh_module_row(root, _generic_module_row(relative)) + candidate = ( + _s2_40_workflow_module_row() + if relative == S2_40_WORKFLOW_PATH + else _generic_module_row(relative, normalized_owners.get(relative, "S2_20")) + ) + row = _refresh_module_row(root, candidate) if row["module_id"] in seen_ids: raise ReleaseBuildError(f"GENERATED_MODULE_ID_COLLISION:{row['module_id']}") seen_ids.add(row["module_id"]) seen_paths.add(relative) refreshed_rows.append(row) + _assert_no_transitioned_s2_40_stub(refreshed_rows) result["modules"] = refreshed_rows mirrors = [entry for row in refreshed_rows if (entry := _documentation_mirror(row))] mirror_sources = [str(entry["source_path"]) for entry in mirrors] @@ -312,6 +538,24 @@ def build_module_manifest( for row in refreshed_rows if row.get("schema_version") == "stage2_s2_20_generic_asset.v1" ), + "s2_30_generic_module_count": sum( + 1 + for row in refreshed_rows + if row.get("schema_version") == "stage2_s2_30_generic_asset.v1" + ), + "s2_40_generic_module_count": sum( + 1 + for row in refreshed_rows + if row.get("schema_version") == "stage2_s2_40_generic_asset.v1" + ), + "generic_module_counts_by_stage": { + stage: sum( + 1 + for row in refreshed_rows + if row.get("schema_version") == metadata["schema_version"] + ) + for stage, metadata in sorted(STAGE_GENERIC_METADATA.items()) + }, "executable_agent_hash_included": False, "executor_binding_hash_included": False, "inline_runtime_code_hash_included": False, @@ -431,8 +675,14 @@ def build_release_package( path_list: list[str], module_template: dict[str, Any], parent_template: dict[str, Any], + path_owners: Mapping[str, str] | None = None, ) -> tuple[dict[str, Any], dict[str, Any]]: - module_manifest = build_module_manifest(root, module_template, path_list) + module_manifest = build_module_manifest( + root, + module_template, + path_list, + path_owners=path_owners, + ) module_raw = _canonical_bytes(module_manifest) parent_release = build_parent_release(root, parent_template, module_raw) return module_manifest, parent_release @@ -445,6 +695,13 @@ def _write_bytes(path: Path, raw: bytes) -> None: os.replace(temporary, path) +def _owner_stage_from_path_list(path: Path) -> str: + match = re.fullmatch(r"s2_(20|30|40)_parent_member_paths\.json", path.name) + if match is None: + raise ReleaseBuildError(f"PARENT_PATH_LIST_OWNER_UNRESOLVED:{path.as_posix()}") + return f"S2_{match.group(1)}" + + def main() -> int: parser = argparse.ArgumentParser( description="Reseal canonical Stage-2 module and parent release manifests" @@ -476,20 +733,22 @@ def main() -> int: ) args = parser.parse_args() - path_lists: list[list[str]] = [] + path_lists: list[tuple[str, list[str]]] = [] for source in [args.path_list, *args.additional_path_list]: loaded = _load_json(source) if not isinstance(loaded, list) or not all(isinstance(row, str) for row in loaded): raise ReleaseBuildError(f"PATH_LIST_MUST_BE_STRING_ARRAY:{source.as_posix()}") - path_lists.append(loaded) + path_lists.append((_owner_stage_from_path_list(source), loaded)) seen_paths: set[str] = set() path_list: list[str] = [] - for rows in path_lists: + path_owners: dict[str, str] = {} + for owner_stage, rows in path_lists: overlap = sorted(seen_paths & set(rows)) if overlap: raise ReleaseBuildError(f"PARENT_PATH_LISTS_MUST_BE_DISJOINT:{overlap}") seen_paths.update(rows) path_list.extend(rows) + path_owners.update({row: owner_stage for row in rows}) path_list.sort() module_template_path = args.module_template or args.root / "manifest/module_manifest.json" parent_template_path = args.parent_template or args.root / "manifest/stage2_release.json" @@ -499,6 +758,7 @@ def main() -> int: path_list, _load_json(module_template_path), _load_json(parent_template_path), + path_owners=path_owners, ) _write_bytes(args.output, _canonical_bytes(module_manifest)) _write_bytes(parent_output, _canonical_bytes(parent_release)) diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_10_agent_projection.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_10_agent_projection.py index 6e4b36c5..5de1550f 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_10_agent_projection.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_10_agent_projection.py @@ -12,6 +12,7 @@ from __future__ import annotations import argparse import hashlib +import importlib.util import json import os from pathlib import Path @@ -45,6 +46,12 @@ MODULE_MANIFEST_PATH = DEPLOYMENT_ROOT / "manifest" / "module_manifest.json" PLATFORM_RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_10_platform_adapter_receipt.json" MODEL_RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_10_model_benchmark_receipt.json" LEGAL_RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_10_legal_review_receipt.json" +RELEASE_BUILDER_PATH = DEPLOYMENT_ROOT / "offline_build" / "build_release_manifests.py" +CUMULATIVE_PARENT_PATH_LISTS = ( + ("S2_20", DEPLOYMENT_ROOT / "manifest" / "s2_20_parent_member_paths.json"), + ("S2_30", DEPLOYMENT_ROOT / "manifest" / "s2_30_parent_member_paths.json"), + ("S2_40", DEPLOYMENT_ROOT / "manifest" / "s2_40_parent_member_paths.json"), +) EXPECTED_AGENT_NAME = "Stage_2_S2_10" EXPECTED_STAGE_NAME = "S2_10" @@ -276,6 +283,75 @@ def _load_json(path: Path) -> dict[str, Any]: return value +def _load_release_builder() -> Any: + spec = importlib.util.spec_from_file_location( + "stage2_cumulative_release_builder", + RELEASE_BUILDER_PATH, + ) + if spec is None or spec.loader is None: + raise BuildError("CUMULATIVE_RELEASE_BUILDER_IMPORT_FAILED", _logical_path(RELEASE_BUILDER_PATH)) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def cumulative_parent_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: + """Recompute the current owner-aware cumulative parent in memory only. + + S2_10 no longer owns ``module_manifest.json`` or ``stage2_release.json``. + This oracle delegates to the canonical S2_20+S2_30+S2_40 builder and is + used solely to detect drift; it never writes either parent file. + """ + + release_builder = _load_release_builder() + combined: list[str] = [] + path_owners: dict[str, str] = {} + seen: set[str] = set() + counts: dict[str, int] = {} + for owner_stage, source in CUMULATIVE_PARENT_PATH_LISTS: + raw = _require_file(source) + try: + values = json.loads(raw.decode("utf-8")) + except json.JSONDecodeError as exc: + raise BuildError("CUMULATIVE_PARENT_PATH_LIST_INVALID", f"{_logical_path(source)}: {exc}") from exc + if not isinstance(values, list) or not all(isinstance(value, str) for value in values): + raise BuildError("CUMULATIVE_PARENT_PATH_LIST_INVALID", _logical_path(source)) + if values != sorted(values) or len(values) != len(set(values)): + raise BuildError("CUMULATIVE_PARENT_PATH_LIST_NOT_SORTED_UNIQUE", _logical_path(source)) + overlap = sorted(seen & set(values)) + if overlap: + raise BuildError("CUMULATIVE_PARENT_PATH_LIST_OVERLAP", repr(overlap)) + seen.update(values) + combined.extend(values) + path_owners.update({value: owner_stage for value in values}) + counts[owner_stage] = len(values) + combined.sort() + try: + module, parent = release_builder.build_release_package( + DEPLOYMENT_ROOT, + combined, + _load_json(MODULE_MANIFEST_PATH), + _load_json(PARENT_RELEASE_PATH), + path_owners=path_owners, + ) + except Exception as exc: + raise BuildError( + "CUMULATIVE_PARENT_ORACLE_FAILED", + f"{type(exc).__name__}:{exc}", + ) from exc + module_raw = release_builder._canonical_bytes(module) + parent_raw = release_builder._canonical_bytes(parent) + return { + MODULE_MANIFEST_PATH: module_raw, + PARENT_RELEASE_PATH: parent_raw, + }, { + "owner_path_counts": counts, + "module_count": len(module["modules"]), + "module_manifest_sha256": sha256_bytes(module_raw), + "parent_release_sha256": sha256_bytes(parent_raw), + } + + def _mapping(value: Any, code: str) -> dict[str, Any]: if not isinstance(value, dict): raise BuildError(code, repr(value)[:200]) @@ -1221,31 +1297,8 @@ def _atomic_write(path: Path, payload: bytes) -> None: temporary.unlink() -def build() -> dict[str, Any]: - # Phase 1 closes the authoring projection, inline receipt and binding. - outputs, report = expected_outputs() - for path, payload in outputs.items(): - _atomic_write(path, payload) - if report["phase"] in {"PREREQUISITE_PROJECTION", "PREREQUISITE_MODULE_MANIFEST"}: - outputs, report = expected_outputs() - for path, payload in outputs.items(): - _atomic_write(path, payload) - if report["phase"] == "PREREQUISITE_MODULE_MANIFEST": - outputs, report = expected_outputs() - for path, payload in outputs.items(): - _atomic_write(path, payload) - if report["phase"] != "COMPLETE": - raise BuildError("BUILD_DID_NOT_REACH_COMPLETE_PHASE", repr(report)) - return { - "status": "BUILT_OFFLINE_HYBRID_PACKAGE", - "written_paths": [_logical_path(path) for path in outputs], - **report, - } - - -def check() -> dict[str, Any]: - outputs, report = expected_outputs() - drift = [] +def _compare_outputs(outputs: Mapping[Path, bytes]) -> list[dict[str, Any]]: + drift: list[dict[str, Any]] = [] for path, expected in outputs.items(): observed = path.read_bytes() if path.is_file() and not path.is_symlink() else None if observed != expected: @@ -1256,31 +1309,100 @@ def check() -> dict[str, Any]: "observed_sha256": sha256_bytes(observed) if observed is not None else None, } ) - if report["phase"] != "COMPLETE" or drift: - raise BuildError("OFFLINE_PACKAGE_DRIFT", json.dumps({"report": report, "drift": drift}, ensure_ascii=False)) + return drift + + +def _current_cumulative_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: + """Return the complete S2_10-owned and cumulative downstream oracle. + + The owner-aware release builder is the sole producer of the cumulative + module manifest and parent release. The legacy ``expected_outputs`` + function remains only as a compatibility helper for older callers; the + default build/check path must never use its S2_10-only parent projection. + """ + + prerequisite, prerequisite_report = prerequisite_outputs() + parent, parent_report = cumulative_parent_outputs() + child, child_report = cumulative_child_outputs(prerequisite, parent) + overlap = (set(prerequisite) & set(parent)) | (set(prerequisite) & set(child)) | (set(parent) & set(child)) + if overlap: + raise BuildError( + "CUMULATIVE_OUTPUT_PATH_OVERLAP", + repr(sorted(_logical_path(path) for path in overlap)), + ) return { - "status": "OFFLINE_HYBRID_PACKAGE_CHECK_PASS", + **prerequisite, + **parent, + **child, + }, { + "prerequisite": prerequisite_report, + "cumulative_parent": parent_report, + "downstream_child": child_report, + } + + +def build() -> dict[str, Any]: + """Rebuild S2_10-owned artifacts without rewriting the cumulative parent. + + A cumulative parent drift requires the owner-aware release builder and its + explicit reseal sequence. Silently rebuilding an obsolete S2_10-only + parent here would discard downstream S2_20/S2_30/S2_40 closure. + """ + + prerequisite, prerequisite_report = prerequisite_outputs() + for path, payload in prerequisite.items(): + _atomic_write(path, payload) + + parent, parent_report = cumulative_parent_outputs() + parent_drift = _compare_outputs(parent) + if parent_drift: + raise BuildError( + "CUMULATIVE_PARENT_RESEAL_REQUIRED", + json.dumps( + {"report": parent_report, "drift": parent_drift}, + ensure_ascii=False, + sort_keys=True, + ), + ) + + child, child_report = child_only_outputs() + for path, payload in child.items(): + _atomic_write(path, payload) + return { + "status": "S2_10_OWNED_ARTIFACTS_REBUILT_CUMULATIVE_PARENT_PRESERVED", + "written_paths": [_logical_path(path) for path in {**prerequisite, **child}], + "prerequisite": prerequisite_report, + "cumulative_parent": parent_report, + "downstream_child": child_report, + } + + +def check() -> dict[str, Any]: + outputs, report = _current_cumulative_outputs() + drift = _compare_outputs(outputs) + if drift: + raise BuildError( + "OFFLINE_PACKAGE_DRIFT", + json.dumps({"report": report, "drift": drift}, ensure_ascii=False, sort_keys=True), + ) + return { + "status": "S2_10_CUMULATIVE_PACKAGE_CHECK_PASS", "checked_paths": [_logical_path(path) for path in outputs], **report, } -def child_only_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: - """Reseal only the downstream S2_10 child chain against a frozen parent. - - The canonical parent/module builder owns the raw parent closure. This mode - therefore never rewrites ``module_manifest.json``, ``stage2_release.json``, - the Agent projection, prompt receipt, or LLM binding. - """ - - authoring_raw = _require_file(AUTHORING_PATH) - if _require_file(PROJECTION_PATH) != authoring_raw: - raise BuildError("S2_10_AGENT_PROJECTION_DRIFT", _logical_path(PROJECTION_PATH)) - contract = extract_agent_contract(_load_yaml(authoring_raw, _logical_path(AUTHORING_PATH))) - binding_raw = _require_file(BINDING_PATH) +def _downstream_child_outputs( + *, + authoring_raw: bytes, + binding_raw: bytes, + inline_receipt_raw: bytes, + parent_raw: bytes, +) -> tuple[dict[Path, bytes], dict[str, Any]]: + contract = extract_agent_contract( + _load_yaml(authoring_raw, _logical_path(AUTHORING_PATH)) + ) binding = _load_yaml(binding_raw, _logical_path(BINDING_PATH)) - inline_receipt_raw = _require_file(INLINE_RECEIPT_PATH) - parent_raw = _require_file(PARENT_RELEASE_PATH) child = build_child_release(parent_raw, binding) child_raw = canonical_json_bytes(child) outputs = { @@ -1310,6 +1432,57 @@ def child_only_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: } +def cumulative_child_outputs( + prerequisite: Mapping[Path, bytes], + parent: Mapping[Path, bytes], +) -> tuple[dict[Path, bytes], dict[str, Any]]: + """Build downstream receipts from the expected current parent material. + + This is the critical distinction from the bounded ``--child-only`` mode: + the default ``--check`` validates the child chain that *would* result from + the current owner-aware cumulative parent and current prerequisite oracle, + not a self-consistent but obsolete child bound to observed stale bytes. + """ + + required = { + BINDING_PATH: prerequisite, + INLINE_RECEIPT_PATH: prerequisite, + PARENT_RELEASE_PATH: parent, + } + missing = [ + _logical_path(path) + for path, mapping in required.items() + if path not in mapping + ] + if missing: + raise BuildError("CUMULATIVE_CHILD_MATERIAL_MISSING", repr(sorted(missing))) + return _downstream_child_outputs( + authoring_raw=_require_file(AUTHORING_PATH), + binding_raw=prerequisite[BINDING_PATH], + inline_receipt_raw=prerequisite[INLINE_RECEIPT_PATH], + parent_raw=parent[PARENT_RELEASE_PATH], + ) + + +def child_only_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: + """Reseal only the downstream S2_10 child chain against a frozen parent. + + The canonical parent/module builder owns the raw parent closure. This mode + therefore never rewrites ``module_manifest.json``, ``stage2_release.json``, + the Agent projection, prompt receipt, or LLM binding. + """ + + authoring_raw = _require_file(AUTHORING_PATH) + if _require_file(PROJECTION_PATH) != authoring_raw: + raise BuildError("S2_10_AGENT_PROJECTION_DRIFT", _logical_path(PROJECTION_PATH)) + return _downstream_child_outputs( + authoring_raw=authoring_raw, + binding_raw=_require_file(BINDING_PATH), + inline_receipt_raw=_require_file(INLINE_RECEIPT_PATH), + parent_raw=_require_file(PARENT_RELEASE_PATH), + ) + + def prerequisite_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: """Build only the parent-owned S2_10 projection prerequisites.""" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_10_agent_projection.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_10_agent_projection.txt index 6e4b36c5..5de1550f 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_10_agent_projection.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_10_agent_projection.txt @@ -12,6 +12,7 @@ from __future__ import annotations import argparse import hashlib +import importlib.util import json import os from pathlib import Path @@ -45,6 +46,12 @@ MODULE_MANIFEST_PATH = DEPLOYMENT_ROOT / "manifest" / "module_manifest.json" PLATFORM_RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_10_platform_adapter_receipt.json" MODEL_RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_10_model_benchmark_receipt.json" LEGAL_RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_10_legal_review_receipt.json" +RELEASE_BUILDER_PATH = DEPLOYMENT_ROOT / "offline_build" / "build_release_manifests.py" +CUMULATIVE_PARENT_PATH_LISTS = ( + ("S2_20", DEPLOYMENT_ROOT / "manifest" / "s2_20_parent_member_paths.json"), + ("S2_30", DEPLOYMENT_ROOT / "manifest" / "s2_30_parent_member_paths.json"), + ("S2_40", DEPLOYMENT_ROOT / "manifest" / "s2_40_parent_member_paths.json"), +) EXPECTED_AGENT_NAME = "Stage_2_S2_10" EXPECTED_STAGE_NAME = "S2_10" @@ -276,6 +283,75 @@ def _load_json(path: Path) -> dict[str, Any]: return value +def _load_release_builder() -> Any: + spec = importlib.util.spec_from_file_location( + "stage2_cumulative_release_builder", + RELEASE_BUILDER_PATH, + ) + if spec is None or spec.loader is None: + raise BuildError("CUMULATIVE_RELEASE_BUILDER_IMPORT_FAILED", _logical_path(RELEASE_BUILDER_PATH)) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def cumulative_parent_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: + """Recompute the current owner-aware cumulative parent in memory only. + + S2_10 no longer owns ``module_manifest.json`` or ``stage2_release.json``. + This oracle delegates to the canonical S2_20+S2_30+S2_40 builder and is + used solely to detect drift; it never writes either parent file. + """ + + release_builder = _load_release_builder() + combined: list[str] = [] + path_owners: dict[str, str] = {} + seen: set[str] = set() + counts: dict[str, int] = {} + for owner_stage, source in CUMULATIVE_PARENT_PATH_LISTS: + raw = _require_file(source) + try: + values = json.loads(raw.decode("utf-8")) + except json.JSONDecodeError as exc: + raise BuildError("CUMULATIVE_PARENT_PATH_LIST_INVALID", f"{_logical_path(source)}: {exc}") from exc + if not isinstance(values, list) or not all(isinstance(value, str) for value in values): + raise BuildError("CUMULATIVE_PARENT_PATH_LIST_INVALID", _logical_path(source)) + if values != sorted(values) or len(values) != len(set(values)): + raise BuildError("CUMULATIVE_PARENT_PATH_LIST_NOT_SORTED_UNIQUE", _logical_path(source)) + overlap = sorted(seen & set(values)) + if overlap: + raise BuildError("CUMULATIVE_PARENT_PATH_LIST_OVERLAP", repr(overlap)) + seen.update(values) + combined.extend(values) + path_owners.update({value: owner_stage for value in values}) + counts[owner_stage] = len(values) + combined.sort() + try: + module, parent = release_builder.build_release_package( + DEPLOYMENT_ROOT, + combined, + _load_json(MODULE_MANIFEST_PATH), + _load_json(PARENT_RELEASE_PATH), + path_owners=path_owners, + ) + except Exception as exc: + raise BuildError( + "CUMULATIVE_PARENT_ORACLE_FAILED", + f"{type(exc).__name__}:{exc}", + ) from exc + module_raw = release_builder._canonical_bytes(module) + parent_raw = release_builder._canonical_bytes(parent) + return { + MODULE_MANIFEST_PATH: module_raw, + PARENT_RELEASE_PATH: parent_raw, + }, { + "owner_path_counts": counts, + "module_count": len(module["modules"]), + "module_manifest_sha256": sha256_bytes(module_raw), + "parent_release_sha256": sha256_bytes(parent_raw), + } + + def _mapping(value: Any, code: str) -> dict[str, Any]: if not isinstance(value, dict): raise BuildError(code, repr(value)[:200]) @@ -1221,31 +1297,8 @@ def _atomic_write(path: Path, payload: bytes) -> None: temporary.unlink() -def build() -> dict[str, Any]: - # Phase 1 closes the authoring projection, inline receipt and binding. - outputs, report = expected_outputs() - for path, payload in outputs.items(): - _atomic_write(path, payload) - if report["phase"] in {"PREREQUISITE_PROJECTION", "PREREQUISITE_MODULE_MANIFEST"}: - outputs, report = expected_outputs() - for path, payload in outputs.items(): - _atomic_write(path, payload) - if report["phase"] == "PREREQUISITE_MODULE_MANIFEST": - outputs, report = expected_outputs() - for path, payload in outputs.items(): - _atomic_write(path, payload) - if report["phase"] != "COMPLETE": - raise BuildError("BUILD_DID_NOT_REACH_COMPLETE_PHASE", repr(report)) - return { - "status": "BUILT_OFFLINE_HYBRID_PACKAGE", - "written_paths": [_logical_path(path) for path in outputs], - **report, - } - - -def check() -> dict[str, Any]: - outputs, report = expected_outputs() - drift = [] +def _compare_outputs(outputs: Mapping[Path, bytes]) -> list[dict[str, Any]]: + drift: list[dict[str, Any]] = [] for path, expected in outputs.items(): observed = path.read_bytes() if path.is_file() and not path.is_symlink() else None if observed != expected: @@ -1256,31 +1309,100 @@ def check() -> dict[str, Any]: "observed_sha256": sha256_bytes(observed) if observed is not None else None, } ) - if report["phase"] != "COMPLETE" or drift: - raise BuildError("OFFLINE_PACKAGE_DRIFT", json.dumps({"report": report, "drift": drift}, ensure_ascii=False)) + return drift + + +def _current_cumulative_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: + """Return the complete S2_10-owned and cumulative downstream oracle. + + The owner-aware release builder is the sole producer of the cumulative + module manifest and parent release. The legacy ``expected_outputs`` + function remains only as a compatibility helper for older callers; the + default build/check path must never use its S2_10-only parent projection. + """ + + prerequisite, prerequisite_report = prerequisite_outputs() + parent, parent_report = cumulative_parent_outputs() + child, child_report = cumulative_child_outputs(prerequisite, parent) + overlap = (set(prerequisite) & set(parent)) | (set(prerequisite) & set(child)) | (set(parent) & set(child)) + if overlap: + raise BuildError( + "CUMULATIVE_OUTPUT_PATH_OVERLAP", + repr(sorted(_logical_path(path) for path in overlap)), + ) return { - "status": "OFFLINE_HYBRID_PACKAGE_CHECK_PASS", + **prerequisite, + **parent, + **child, + }, { + "prerequisite": prerequisite_report, + "cumulative_parent": parent_report, + "downstream_child": child_report, + } + + +def build() -> dict[str, Any]: + """Rebuild S2_10-owned artifacts without rewriting the cumulative parent. + + A cumulative parent drift requires the owner-aware release builder and its + explicit reseal sequence. Silently rebuilding an obsolete S2_10-only + parent here would discard downstream S2_20/S2_30/S2_40 closure. + """ + + prerequisite, prerequisite_report = prerequisite_outputs() + for path, payload in prerequisite.items(): + _atomic_write(path, payload) + + parent, parent_report = cumulative_parent_outputs() + parent_drift = _compare_outputs(parent) + if parent_drift: + raise BuildError( + "CUMULATIVE_PARENT_RESEAL_REQUIRED", + json.dumps( + {"report": parent_report, "drift": parent_drift}, + ensure_ascii=False, + sort_keys=True, + ), + ) + + child, child_report = child_only_outputs() + for path, payload in child.items(): + _atomic_write(path, payload) + return { + "status": "S2_10_OWNED_ARTIFACTS_REBUILT_CUMULATIVE_PARENT_PRESERVED", + "written_paths": [_logical_path(path) for path in {**prerequisite, **child}], + "prerequisite": prerequisite_report, + "cumulative_parent": parent_report, + "downstream_child": child_report, + } + + +def check() -> dict[str, Any]: + outputs, report = _current_cumulative_outputs() + drift = _compare_outputs(outputs) + if drift: + raise BuildError( + "OFFLINE_PACKAGE_DRIFT", + json.dumps({"report": report, "drift": drift}, ensure_ascii=False, sort_keys=True), + ) + return { + "status": "S2_10_CUMULATIVE_PACKAGE_CHECK_PASS", "checked_paths": [_logical_path(path) for path in outputs], **report, } -def child_only_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: - """Reseal only the downstream S2_10 child chain against a frozen parent. - - The canonical parent/module builder owns the raw parent closure. This mode - therefore never rewrites ``module_manifest.json``, ``stage2_release.json``, - the Agent projection, prompt receipt, or LLM binding. - """ - - authoring_raw = _require_file(AUTHORING_PATH) - if _require_file(PROJECTION_PATH) != authoring_raw: - raise BuildError("S2_10_AGENT_PROJECTION_DRIFT", _logical_path(PROJECTION_PATH)) - contract = extract_agent_contract(_load_yaml(authoring_raw, _logical_path(AUTHORING_PATH))) - binding_raw = _require_file(BINDING_PATH) +def _downstream_child_outputs( + *, + authoring_raw: bytes, + binding_raw: bytes, + inline_receipt_raw: bytes, + parent_raw: bytes, +) -> tuple[dict[Path, bytes], dict[str, Any]]: + contract = extract_agent_contract( + _load_yaml(authoring_raw, _logical_path(AUTHORING_PATH)) + ) binding = _load_yaml(binding_raw, _logical_path(BINDING_PATH)) - inline_receipt_raw = _require_file(INLINE_RECEIPT_PATH) - parent_raw = _require_file(PARENT_RELEASE_PATH) child = build_child_release(parent_raw, binding) child_raw = canonical_json_bytes(child) outputs = { @@ -1310,6 +1432,57 @@ def child_only_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: } +def cumulative_child_outputs( + prerequisite: Mapping[Path, bytes], + parent: Mapping[Path, bytes], +) -> tuple[dict[Path, bytes], dict[str, Any]]: + """Build downstream receipts from the expected current parent material. + + This is the critical distinction from the bounded ``--child-only`` mode: + the default ``--check`` validates the child chain that *would* result from + the current owner-aware cumulative parent and current prerequisite oracle, + not a self-consistent but obsolete child bound to observed stale bytes. + """ + + required = { + BINDING_PATH: prerequisite, + INLINE_RECEIPT_PATH: prerequisite, + PARENT_RELEASE_PATH: parent, + } + missing = [ + _logical_path(path) + for path, mapping in required.items() + if path not in mapping + ] + if missing: + raise BuildError("CUMULATIVE_CHILD_MATERIAL_MISSING", repr(sorted(missing))) + return _downstream_child_outputs( + authoring_raw=_require_file(AUTHORING_PATH), + binding_raw=prerequisite[BINDING_PATH], + inline_receipt_raw=prerequisite[INLINE_RECEIPT_PATH], + parent_raw=parent[PARENT_RELEASE_PATH], + ) + + +def child_only_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: + """Reseal only the downstream S2_10 child chain against a frozen parent. + + The canonical parent/module builder owns the raw parent closure. This mode + therefore never rewrites ``module_manifest.json``, ``stage2_release.json``, + the Agent projection, prompt receipt, or LLM binding. + """ + + authoring_raw = _require_file(AUTHORING_PATH) + if _require_file(PROJECTION_PATH) != authoring_raw: + raise BuildError("S2_10_AGENT_PROJECTION_DRIFT", _logical_path(PROJECTION_PATH)) + return _downstream_child_outputs( + authoring_raw=authoring_raw, + binding_raw=_require_file(BINDING_PATH), + inline_receipt_raw=_require_file(INLINE_RECEIPT_PATH), + parent_raw=_require_file(PARENT_RELEASE_PATH), + ) + + def prerequisite_outputs() -> tuple[dict[Path, bytes], dict[str, Any]]: """Build only the parent-owned S2_10 projection prerequisites.""" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_30_agent_projection.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_30_agent_projection.py index 62b4ae99..64d6a036 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_30_agent_projection.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_30_agent_projection.py @@ -59,9 +59,9 @@ EXPECTED_BUILD_ORDER = ( "S2_10_PROJECTION_PREREQUISITES", "MODULE_MANIFEST", "PARENT_STAGE2_RELEASE", - "INJECT_PARENT_HASH_INTO_S2_30_S2_00_S2_20", + "INJECT_PARENT_HASH_INTO_S2_30_S2_00_S2_20_S2_40", "S2_30_AGENT_PROJECTION_PROMPT_CODE_RECEIPTS_BINDING", - "S2_00_S2_20_PARENT_HASH_PROJECTIONS", + "S2_00_S2_20_S2_40_PARENT_HASH_PROJECTIONS", "SHARED_CODE_EXECUTOR_BINDING", "S2_10_AND_S2_30_CHILD_RELEASES_AND_RECEIPTS", "CHECK_AND_REGRESSION", @@ -153,6 +153,7 @@ PARENT_INDEPENDENT_PATHS = ( "tests/fixtures/s2_30/context_reference_envelope.json", "tests/fixtures/s2_30/technical_failure.json", "tests/fixtures/s2_30/partial_write_publish_barrier.json", + "tests/fixtures/s2_30/persisted_handoff_chain.json", "tests/fixtures/s2_30/regression_manifest.json", "manifest/s2_30_parent_member_paths.json", ) @@ -919,6 +920,100 @@ def _bound_asset_ref( } +def _s2_40_stage_binding(parent_sha: str) -> dict[str, Any]: + """Build the detached, offline-only S2_40 deterministic-stage row.""" + + agent = ROOT / "agent_scripts" / "Stage_2_S2_40.yml" + workflow = ROOT / "workflows" / "S2_40_final_review_render_and_commit.yml" + receipt = ROOT / "manifest" / "s2_40_inline_code_receipt.json" + code = ROOT / "runtime" / "s2_40_commit.py" + return { + "stage_id": "S2_40", + "binding_id": "S2-BINDING-S2_40-CODE-EXECUTOR-V1", + "workflow_id": "S2_40", + "execution_class": "NON-LLM-DETERMINISTIC", + "active_runtime_authority": False, + "agent_script_ref": _bound_asset_ref( + "AGENT-S2_40-INLINE", + "agent_scripts/Stage_2_S2_40.yml", + agent, + "liti_agent_yaml.v1", + ), + "workflow_contract_ref": _bound_asset_ref( + "WF-S2_40", + "workflows/S2_40_final_review_render_and_commit.yml", + workflow, + "stage2_s2_40_final_review_render_and_commit.v1", + ), + "inline_code_receipt_ref": _bound_asset_ref( + "RECEIPT-S2_40-INLINE-CODE", + "manifest/s2_40_inline_code_receipt.json", + receipt, + "stage2_s2_40_inline_code_receipt.v1", + ), + "stage2_release_ref": { + "asset_id": "RELEASE-STAGE2-CLEAN", + "path": "manifest/stage2_release.json", + "sha256": parent_sha, + "schema_id": "stage2_release.v2", + "binding_status": "BOUND", + }, + "expected_release_sha256": parent_sha, + "agent_script_sha256": sha256_bytes(_require_file(agent)), + "canonical_code_sha256": sha256_bytes(_require_file(code)), + "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": sha256_bytes(b"httpx==0.28.1"), + "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_40_request.json", + "read_path_allowlist": [ + "stage2_control/s2_40_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/manifest/stage2_deterministic_admission_receipt.json", + "Default_Agent/Stage_2_Clean/manifest/s2_40_inline_code_receipt.json", + "Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml", + "Default_Agent/Stage_2_Clean/deployment/stage2_code_executor_binding.yml", + "Default_Agent/Stage_2_Clean/schemas/ingress.schema.json", + "Default_Agent/Stage_2_Clean/schemas/context.schema.json", + "Default_Agent/Stage_2_Clean/schemas/s2_10.schema.json", + "Default_Agent/Stage_2_Clean/schemas/domain_verdict.schema.json", + "Default_Agent/Stage_2_Clean/schemas/relief_plan.schema.json", + "Default_Agent/Stage_2_Clean/schemas/binding_retrieval.schema.json", + "Default_Agent/Stage_2_Clean/schemas/calculation.schema.json", + "Default_Agent/Stage_2_Clean/schemas/draft_atoms.schema.json", + "Default_Agent/Stage_2_Clean/schemas/review_status.schema.json", + "Default_Agent/Stage_2_Clean/schemas/package.schema.json", + "Default_Agent/Stage_2_Clean/registry/review/review_policy_registry.yml", + "Default_Agent/Stage_2_Clean/renderers/.yml", + "stage2_runs/by-binding//", + "stage2_runs/by-binding//review/receipts/.json", + "stage2_runs/by-binding//control/run_status.json", + ], + "write_root_rule": "stage2_runs/by-binding//", + }, + "external_mcp_contract": None, + "egress_profile_id": "S2_40_LOCALDOCS_ONLY_V1", + "egress_profile_status": "PENDING_LIVE_VERIFICATION", + "downstream_handoff_owner": None, + "live_admission_status": "PENDING_SECRET_BINDING", + "legacy_fallbacks": [], + } + + def shared_executor_outputs() -> dict[Path, bytes]: if yaml is None: raise BuildError("PYYAML_REQUIRED", "shared executor build") @@ -943,9 +1038,22 @@ def shared_executor_outputs() -> dict[Path, bytes]: "receipt": ROOT / "manifest" / "s2_20_inline_code_receipt.json", "code": ROOT / "runtime" / "s2_20_reduce.py", }, + "S2_40": { + "agent": ROOT / "agent_scripts" / "Stage_2_S2_40.yml", + "workflow": ROOT / "workflows" / "S2_40_final_review_render_and_commit.yml", + "receipt": ROOT / "manifest" / "s2_40_inline_code_receipt.json", + "code": ROOT / "runtime" / "s2_40_commit.py", + }, } - if {row.get("stage_id") for row in rows if isinstance(row, dict)} != set(stage_sources): + observed_stage_ids = [row.get("stage_id") for row in rows if isinstance(row, dict)] + if len(observed_stage_ids) != len(rows) or len(observed_stage_ids) != len(set(observed_stage_ids)): raise BuildError("SHARED_STAGE_BINDING_SET", repr(rows)) + if not set(observed_stage_ids).issubset(set(stage_sources)) or not {"S2_00", "S2_20"}.issubset(observed_stage_ids): + raise BuildError("SHARED_STAGE_BINDING_SET", repr(rows)) + rows = [row for row in rows if isinstance(row, dict) and row.get("stage_id") != "S2_40"] + rows.append(_s2_40_stage_binding(parent_sha)) + rows.sort(key=lambda row: str(row["stage_id"])) + wrapper["stage_bindings"] = rows for row in rows: if not isinstance(row, dict): raise BuildError("SHARED_STAGE_BINDING_ROW", repr(row)) @@ -1068,7 +1176,7 @@ def shared_executor_outputs() -> dict[Path, bytes]: "schema_version": "stage2_deterministic_admission_receipt.v1", "parent_release_sha256": parent_sha, "executor_binding_sha256": sha256_bytes(shared_raw), - "present_deterministic_stage_ids": ["S2_00", "S2_20"], + "present_deterministic_stage_ids": ["S2_00", "S2_20", "S2_40"], "stage_receipts": [row["inline_code_receipt_ref"] for row in rows], "embedded_task_admissions": [ { diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_30_agent_projection.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_30_agent_projection.txt index 62b4ae99..64d6a036 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_30_agent_projection.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_30_agent_projection.txt @@ -59,9 +59,9 @@ EXPECTED_BUILD_ORDER = ( "S2_10_PROJECTION_PREREQUISITES", "MODULE_MANIFEST", "PARENT_STAGE2_RELEASE", - "INJECT_PARENT_HASH_INTO_S2_30_S2_00_S2_20", + "INJECT_PARENT_HASH_INTO_S2_30_S2_00_S2_20_S2_40", "S2_30_AGENT_PROJECTION_PROMPT_CODE_RECEIPTS_BINDING", - "S2_00_S2_20_PARENT_HASH_PROJECTIONS", + "S2_00_S2_20_S2_40_PARENT_HASH_PROJECTIONS", "SHARED_CODE_EXECUTOR_BINDING", "S2_10_AND_S2_30_CHILD_RELEASES_AND_RECEIPTS", "CHECK_AND_REGRESSION", @@ -153,6 +153,7 @@ PARENT_INDEPENDENT_PATHS = ( "tests/fixtures/s2_30/context_reference_envelope.json", "tests/fixtures/s2_30/technical_failure.json", "tests/fixtures/s2_30/partial_write_publish_barrier.json", + "tests/fixtures/s2_30/persisted_handoff_chain.json", "tests/fixtures/s2_30/regression_manifest.json", "manifest/s2_30_parent_member_paths.json", ) @@ -919,6 +920,100 @@ def _bound_asset_ref( } +def _s2_40_stage_binding(parent_sha: str) -> dict[str, Any]: + """Build the detached, offline-only S2_40 deterministic-stage row.""" + + agent = ROOT / "agent_scripts" / "Stage_2_S2_40.yml" + workflow = ROOT / "workflows" / "S2_40_final_review_render_and_commit.yml" + receipt = ROOT / "manifest" / "s2_40_inline_code_receipt.json" + code = ROOT / "runtime" / "s2_40_commit.py" + return { + "stage_id": "S2_40", + "binding_id": "S2-BINDING-S2_40-CODE-EXECUTOR-V1", + "workflow_id": "S2_40", + "execution_class": "NON-LLM-DETERMINISTIC", + "active_runtime_authority": False, + "agent_script_ref": _bound_asset_ref( + "AGENT-S2_40-INLINE", + "agent_scripts/Stage_2_S2_40.yml", + agent, + "liti_agent_yaml.v1", + ), + "workflow_contract_ref": _bound_asset_ref( + "WF-S2_40", + "workflows/S2_40_final_review_render_and_commit.yml", + workflow, + "stage2_s2_40_final_review_render_and_commit.v1", + ), + "inline_code_receipt_ref": _bound_asset_ref( + "RECEIPT-S2_40-INLINE-CODE", + "manifest/s2_40_inline_code_receipt.json", + receipt, + "stage2_s2_40_inline_code_receipt.v1", + ), + "stage2_release_ref": { + "asset_id": "RELEASE-STAGE2-CLEAN", + "path": "manifest/stage2_release.json", + "sha256": parent_sha, + "schema_id": "stage2_release.v2", + "binding_status": "BOUND", + }, + "expected_release_sha256": parent_sha, + "agent_script_sha256": sha256_bytes(_require_file(agent)), + "canonical_code_sha256": sha256_bytes(_require_file(code)), + "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": sha256_bytes(b"httpx==0.28.1"), + "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_40_request.json", + "read_path_allowlist": [ + "stage2_control/s2_40_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/manifest/stage2_deterministic_admission_receipt.json", + "Default_Agent/Stage_2_Clean/manifest/s2_40_inline_code_receipt.json", + "Default_Agent/Stage_2_Clean/agent_scripts/Stage_2_S2_40.yml", + "Default_Agent/Stage_2_Clean/deployment/stage2_code_executor_binding.yml", + "Default_Agent/Stage_2_Clean/schemas/ingress.schema.json", + "Default_Agent/Stage_2_Clean/schemas/context.schema.json", + "Default_Agent/Stage_2_Clean/schemas/s2_10.schema.json", + "Default_Agent/Stage_2_Clean/schemas/domain_verdict.schema.json", + "Default_Agent/Stage_2_Clean/schemas/relief_plan.schema.json", + "Default_Agent/Stage_2_Clean/schemas/binding_retrieval.schema.json", + "Default_Agent/Stage_2_Clean/schemas/calculation.schema.json", + "Default_Agent/Stage_2_Clean/schemas/draft_atoms.schema.json", + "Default_Agent/Stage_2_Clean/schemas/review_status.schema.json", + "Default_Agent/Stage_2_Clean/schemas/package.schema.json", + "Default_Agent/Stage_2_Clean/registry/review/review_policy_registry.yml", + "Default_Agent/Stage_2_Clean/renderers/.yml", + "stage2_runs/by-binding//", + "stage2_runs/by-binding//review/receipts/.json", + "stage2_runs/by-binding//control/run_status.json", + ], + "write_root_rule": "stage2_runs/by-binding//", + }, + "external_mcp_contract": None, + "egress_profile_id": "S2_40_LOCALDOCS_ONLY_V1", + "egress_profile_status": "PENDING_LIVE_VERIFICATION", + "downstream_handoff_owner": None, + "live_admission_status": "PENDING_SECRET_BINDING", + "legacy_fallbacks": [], + } + + def shared_executor_outputs() -> dict[Path, bytes]: if yaml is None: raise BuildError("PYYAML_REQUIRED", "shared executor build") @@ -943,9 +1038,22 @@ def shared_executor_outputs() -> dict[Path, bytes]: "receipt": ROOT / "manifest" / "s2_20_inline_code_receipt.json", "code": ROOT / "runtime" / "s2_20_reduce.py", }, + "S2_40": { + "agent": ROOT / "agent_scripts" / "Stage_2_S2_40.yml", + "workflow": ROOT / "workflows" / "S2_40_final_review_render_and_commit.yml", + "receipt": ROOT / "manifest" / "s2_40_inline_code_receipt.json", + "code": ROOT / "runtime" / "s2_40_commit.py", + }, } - if {row.get("stage_id") for row in rows if isinstance(row, dict)} != set(stage_sources): + observed_stage_ids = [row.get("stage_id") for row in rows if isinstance(row, dict)] + if len(observed_stage_ids) != len(rows) or len(observed_stage_ids) != len(set(observed_stage_ids)): raise BuildError("SHARED_STAGE_BINDING_SET", repr(rows)) + if not set(observed_stage_ids).issubset(set(stage_sources)) or not {"S2_00", "S2_20"}.issubset(observed_stage_ids): + raise BuildError("SHARED_STAGE_BINDING_SET", repr(rows)) + rows = [row for row in rows if isinstance(row, dict) and row.get("stage_id") != "S2_40"] + rows.append(_s2_40_stage_binding(parent_sha)) + rows.sort(key=lambda row: str(row["stage_id"])) + wrapper["stage_bindings"] = rows for row in rows: if not isinstance(row, dict): raise BuildError("SHARED_STAGE_BINDING_ROW", repr(row)) @@ -1068,7 +1176,7 @@ def shared_executor_outputs() -> dict[Path, bytes]: "schema_version": "stage2_deterministic_admission_receipt.v1", "parent_release_sha256": parent_sha, "executor_binding_sha256": sha256_bytes(shared_raw), - "present_deterministic_stage_ids": ["S2_00", "S2_20"], + "present_deterministic_stage_ids": ["S2_00", "S2_20", "S2_40"], "stage_receipts": [row["inline_code_receipt_ref"] for row in rows], "embedded_task_admissions": [ { diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_40_inline_projection.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_40_inline_projection.py new file mode 100644 index 00000000..6b06b6c9 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_40_inline_projection.py @@ -0,0 +1,894 @@ +#!/usr/bin/env python3 +"""Build the version-free S2_40 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_40.yml" +PROJECTION_PATH = DEPLOYMENT_ROOT / "agent_scripts" / "Stage_2_S2_40.yml" +MIRROR_PY_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_40_commit.py" +MIRROR_TXT_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_40_commit.txt" +RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_40_inline_code_receipt.json" + +EXPECTED_TASK_NAME = "Task_S2_40_deterministic_finalizer" +EXPECTED_AGENT_NAME = "Stage_2_S2_40" +EXPECTED_AGENT_VERSION = "1.0.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", + "stage2_control/s2_40_request.json", + "run_status.json", + "reduce_and_render", + "invariant_results", + "candidate_material", + "publish_candidate", + "validate_review_receipts", + "final_status", +) +REQUIRED_CODE_TOKEN_ALTERNATIVES = ( + ("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", "open"}) +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"}) +HTTP_CLIENT_FACTORIES = frozenset({"Client", "AsyncClient"}) + + +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 = "") -> 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 _find_forbidden_model_fields(value: Any, pointer: str = "") -> list[str]: + forbidden = {"llm_provider", "llm_model", "llm_reasoning", "llm_verbosity", "prompt"} + findings: list[str] = [] + if isinstance(value, dict): + for key, child in value.items(): + child_pointer = f"{pointer}/{key}" + if key in forbidden: + findings.append(child_pointer) + findings.extend(_find_forbidden_model_fields(child, child_pointer)) + elif isinstance(value, list): + for index, child in enumerate(value): + findings.extend(_find_forbidden_model_fields(child, f"{pointer}/{index}")) + return findings + + +def extract_run_code_task(document: Mapping[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]: + agent = _require_mapping(document.get("Agent"), "AGENT_OBJECT_REQUIRED") + if agent.get("name") != EXPECTED_AGENT_NAME or agent.get("version") != EXPECTED_AGENT_VERSION: + raise ProjectionError( + "AGENT_IDENTITY_MISMATCH", + f"expected {EXPECTED_AGENT_NAME}/{EXPECTED_AGENT_VERSION}", + ) + forbidden_model_fields = _find_forbidden_model_fields(agent) + if forbidden_model_fields: + raise ProjectionError("LLM_OR_PROMPT_FIELD_FORBIDDEN", repr(forbidden_model_fields)) + stages = _require_list(agent.get("Stages"), "STAGES_ARRAY_REQUIRED") + if len(stages) != 1: + raise ProjectionError("EXACTLY_ONE_STAGE_REQUIRED", str(len(stages))) + stage = _require_mapping(stages[0], "STAGE_OBJECT_REQUIRED") + if stage.get("name") != "S2_40": + raise ProjectionError("S2_40_STAGE_NAME_REQUIRED", repr(stage.get("name"))) + if stage.get("skip_confirm") is not True: + raise ProjectionError( + "S2_40_SKIP_CONFIRM_TRUE_REQUIRED", + repr(stage.get("skip_confirm")), + ) + 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", + ) + if set(servers) != {"localdocs", "code-executor"}: + raise ProjectionError("MCP_SERVER_SET_MISMATCH", repr(sorted(servers))) + 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 + or isinstance(node, ast.Attribute) + and isinstance(node.value, ast.Name) + and node.value.id == "self" + and node.attr == "endpoint" + ) + + +def validate_inline_code(code: str) -> dict[str, Any]: + code_bytes = code.encode("utf-8") + try: + compile(code, "", "exec", dont_inherit=True) + tree = ast.parse(code, filename="", 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() + import_aliases: dict[str, str] = {} + forbidden_callable_aliases: set[str] = set() + mcp_client_endpoint_calls: list[ast.expr] = [] + self_endpoint_assignments: list[ast.expr] = [] + for candidate in ast.walk(tree): + if isinstance(candidate, ast.Import): + for alias in candidate.names: + import_aliases[alias.asname or _import_root(alias.name)] = _import_root(alias.name) + elif isinstance(candidate, ast.ImportFrom) and not candidate.level: + root = _import_root(candidate.module) + for alias in candidate.names: + local_name = alias.asname or alias.name + if root == "httpx" and ( + alias.name in HTTP_NETWORK_METHODS or alias.name in HTTP_CLIENT_FACTORIES + ): + forbidden_callable_aliases.add(local_name) + if root == "os" and ( + alias.name in {name for module, name in FORBIDDEN_ATTRIBUTE_CALLS if module == "os"} + or alias.name.startswith("exec") + ): + forbidden_callable_aliases.add(local_name) + if root == "builtins" and alias.name in FORBIDDEN_CALL_NAMES: + forbidden_callable_aliases.add(local_name) + + derived_client_names: set[str] = set() + release_constants: list[str] = [] + for candidate in ast.walk(tree): + if not isinstance(candidate, (ast.Assign, ast.AnnAssign)): + continue + value = candidate.value + targets = candidate.targets if isinstance(candidate, ast.Assign) else [candidate.target] + target_names = {target.id for target in targets if isinstance(target, ast.Name)} + if ( + "EXPECTED_STAGE2_RELEASE_SHA256" in target_names + and isinstance(value, ast.Constant) + and isinstance(value.value, str) + ): + release_constants.append(value.value) + if ( + isinstance(value, ast.Call) + and isinstance(value.func, ast.Attribute) + and isinstance(value.func.value, ast.Name) + and import_aliases.get(value.func.value.id, value.func.value.id) == "httpx" + and value.func.attr in HTTP_CLIENT_FACTORIES + ): + derived_client_names.update(target_names) + if isinstance(value, ast.Name) and ( + value.id in FORBIDDEN_CALL_NAMES or value.id in forbidden_callable_aliases + ): + forbidden_callable_aliases.update(target_names) + if isinstance(value, ast.Attribute) and isinstance(value.value, ast.Name): + module = import_aliases.get(value.value.id, value.value.id) + if (module, value.attr) in FORBIDDEN_ATTRIBUTE_CALLS or ( + module == "os" and value.attr.startswith("exec") + ): + forbidden_callable_aliases.update(target_names) + if module == "httpx" and value.attr in HTTP_NETWORK_METHODS: + forbidden_callable_aliases.update(target_names) + 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)) + root = _import_root(node.module) + for alias in node.names: + local_name = alias.asname or alias.name + if local_name in forbidden_callable_aliases: + forbidden_nodes.append(f"forbidden-import-alias:{root}.{alias.name}") + 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)): + assignment_targets = node.targets if isinstance(node, ast.Assign) else [node.target] + if any( + isinstance(target, ast.Attribute) + and isinstance(target.value, ast.Name) + and target.value.id == "self" + and target.attr == "endpoint" + for target in assignment_targets + ): + self_endpoint_assignments.append(node.value) + 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.Name) and node.func.id == "McpClient": + mcp_client_endpoint_calls.append( + node.args[0] if node.args else ast.Constant(value=None) + ) + 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.Attribute) + and node.func.attr in HTTP_NETWORK_METHODS + and isinstance(node.func.value, ast.Call) + and isinstance(node.func.value.func, ast.Attribute) + and isinstance(node.func.value.func.value, ast.Name) + and import_aliases.get( + node.func.value.func.value.id, + node.func.value.func.value.id, + ) == "httpx" + and node.func.value.func.attr in HTTP_CLIENT_FACTORIES + ): + 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 + or node.func.id in forbidden_callable_aliases + ): + forbidden_nodes.append(f"call:{node.func.id}") + elif isinstance(node.func, ast.Attribute): + pair = _attribute_pair(node.func) + if pair is not None: + module = import_aliases.get(pair[0], pair[0]) + if (module, pair[1]) in FORBIDDEN_ATTRIBUTE_CALLS or ( + module == "os" and pair[1].startswith("exec") + ): + forbidden_nodes.append(f"call:{module}.{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)) + ) + if ( + len(self_endpoint_assignments) != 1 + or not isinstance(self_endpoint_assignments[0], ast.Name) + or self_endpoint_assignments[0].id != "endpoint" + or not mcp_client_endpoint_calls + or any(not _is_localdocs_endpoint(endpoint) for endpoint in mcp_client_endpoint_calls) + ): + raise ProjectionError( + "INLINE_CODE_LOCALDOCS_ENDPOINT_FLOW_INVALID", + f"assignments={len(self_endpoint_assignments)};constructors={len(mcp_client_endpoint_calls)}", + ) + if len(release_constants) != 1 or not re.fullmatch(r"[a-f0-9]{64}", release_constants[0]): + raise ProjectionError( + "EXPECTED_PARENT_RELEASE_CONSTANT_EXACT_ONE_REQUIRED", + repr(release_constants), + ) + + 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, + "expected_parent_stage2_release_sha256": release_constants[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_40_inline_code_receipt.v1", + "workflow_id": "S2_40", + "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, + "exactly_one_stage": True, + "exactly_one_task": True, + "exactly_one_code_executor_run_code": True, + "authoring_rewritten": False, + "projection_byte_identical_to_authoring": True, + "code_mirrors_byte_identical": True, + "canonical_task_semantics_sha256": semantics_sha256, + }, + "expected_parent_stage2_release_sha256": validation[ + "expected_parent_stage2_release_sha256" + ], + "parity_status": "PASS", + } + outputs = { + PROJECTION_PATH: authoring_raw, + MIRROR_PY_PATH: code_bytes, + MIRROR_TXT_PATH: code_bytes, + RECEIPT_PATH: canonical_json_bytes(receipt), + } + return outputs, receipt + + +def _assert_output_target(path: Path) -> None: + root = DEPLOYMENT_ROOT.resolve(strict=True) + resolved = path.resolve(strict=False) + try: + resolved.relative_to(root) + except ValueError as exc: + raise ProjectionError("OUTPUT_OUTSIDE_DEPLOYMENT_ROOT", path.as_posix()) from exc + if path.exists() and path.is_symlink(): + raise ProjectionError("OUTPUT_SYMLINK_FORBIDDEN", path.as_posix()) + + +def _atomic_write(path: Path, payload: bytes) -> None: + _assert_output_target(path) + path.parent.mkdir(parents=True, exist_ok=True) + temporary_name: str | None = None + try: + with tempfile.NamedTemporaryFile( + mode="wb", + dir=path.parent, + prefix=f".{path.name}.", + suffix=".tmp", + delete=False, + ) as handle: + temporary_name = handle.name + handle.write(payload) + handle.flush() + os.fsync(handle.fileno()) + os.replace(temporary_name, path) + temporary_name = None + finally: + if temporary_name is not None: + try: + Path(temporary_name).unlink() + except FileNotFoundError: + pass + + +def compare_outputs(outputs: Mapping[Path, bytes]) -> list[dict[str, Any]]: + mismatches: list[dict[str, Any]] = [] + for path, expected in outputs.items(): + if not path.is_file(): + mismatches.append( + {"path": _logical_path(path), "status": "MISSING", "expected_sha256": sha256_bytes(expected)} + ) + continue + observed = path.read_bytes() + if observed != expected: + mismatches.append( + { + "path": _logical_path(path), + "status": "BYTE_MISMATCH", + "expected_sha256": sha256_bytes(expected), + "observed_sha256": sha256_bytes(observed), + } + ) + return mismatches + + +def run(*, check: bool) -> tuple[int, dict[str, Any]]: + before, document = load_authoring() + outputs, receipt = expected_outputs(before, document) + if check: + mismatches = compare_outputs(outputs) + return ( + 0 if not mismatches else 1, + { + "status": "PARITY_PASS" if not mismatches else "PARITY_DRIFT", + "mode": "CHECK_NO_WRITE", + "authoring_sha256": sha256_bytes(before), + "code_sha256": receipt["canonical_code"]["code_sha256"], + "mismatches": mismatches, + }, + ) + + receipt_payload = outputs[RECEIPT_PATH] + for path, payload in outputs.items(): + if path == RECEIPT_PATH: + 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_40 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()) diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_40_inline_projection.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_40_inline_projection.txt new file mode 100644 index 00000000..6b06b6c9 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/build_s2_40_inline_projection.txt @@ -0,0 +1,894 @@ +#!/usr/bin/env python3 +"""Build the version-free S2_40 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_40.yml" +PROJECTION_PATH = DEPLOYMENT_ROOT / "agent_scripts" / "Stage_2_S2_40.yml" +MIRROR_PY_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_40_commit.py" +MIRROR_TXT_PATH = DEPLOYMENT_ROOT / "runtime" / "s2_40_commit.txt" +RECEIPT_PATH = DEPLOYMENT_ROOT / "manifest" / "s2_40_inline_code_receipt.json" + +EXPECTED_TASK_NAME = "Task_S2_40_deterministic_finalizer" +EXPECTED_AGENT_NAME = "Stage_2_S2_40" +EXPECTED_AGENT_VERSION = "1.0.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", + "stage2_control/s2_40_request.json", + "run_status.json", + "reduce_and_render", + "invariant_results", + "candidate_material", + "publish_candidate", + "validate_review_receipts", + "final_status", +) +REQUIRED_CODE_TOKEN_ALTERNATIVES = ( + ("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", "open"}) +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"}) +HTTP_CLIENT_FACTORIES = frozenset({"Client", "AsyncClient"}) + + +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 = "") -> 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 _find_forbidden_model_fields(value: Any, pointer: str = "") -> list[str]: + forbidden = {"llm_provider", "llm_model", "llm_reasoning", "llm_verbosity", "prompt"} + findings: list[str] = [] + if isinstance(value, dict): + for key, child in value.items(): + child_pointer = f"{pointer}/{key}" + if key in forbidden: + findings.append(child_pointer) + findings.extend(_find_forbidden_model_fields(child, child_pointer)) + elif isinstance(value, list): + for index, child in enumerate(value): + findings.extend(_find_forbidden_model_fields(child, f"{pointer}/{index}")) + return findings + + +def extract_run_code_task(document: Mapping[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]: + agent = _require_mapping(document.get("Agent"), "AGENT_OBJECT_REQUIRED") + if agent.get("name") != EXPECTED_AGENT_NAME or agent.get("version") != EXPECTED_AGENT_VERSION: + raise ProjectionError( + "AGENT_IDENTITY_MISMATCH", + f"expected {EXPECTED_AGENT_NAME}/{EXPECTED_AGENT_VERSION}", + ) + forbidden_model_fields = _find_forbidden_model_fields(agent) + if forbidden_model_fields: + raise ProjectionError("LLM_OR_PROMPT_FIELD_FORBIDDEN", repr(forbidden_model_fields)) + stages = _require_list(agent.get("Stages"), "STAGES_ARRAY_REQUIRED") + if len(stages) != 1: + raise ProjectionError("EXACTLY_ONE_STAGE_REQUIRED", str(len(stages))) + stage = _require_mapping(stages[0], "STAGE_OBJECT_REQUIRED") + if stage.get("name") != "S2_40": + raise ProjectionError("S2_40_STAGE_NAME_REQUIRED", repr(stage.get("name"))) + if stage.get("skip_confirm") is not True: + raise ProjectionError( + "S2_40_SKIP_CONFIRM_TRUE_REQUIRED", + repr(stage.get("skip_confirm")), + ) + 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", + ) + if set(servers) != {"localdocs", "code-executor"}: + raise ProjectionError("MCP_SERVER_SET_MISMATCH", repr(sorted(servers))) + 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 + or isinstance(node, ast.Attribute) + and isinstance(node.value, ast.Name) + and node.value.id == "self" + and node.attr == "endpoint" + ) + + +def validate_inline_code(code: str) -> dict[str, Any]: + code_bytes = code.encode("utf-8") + try: + compile(code, "", "exec", dont_inherit=True) + tree = ast.parse(code, filename="", 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() + import_aliases: dict[str, str] = {} + forbidden_callable_aliases: set[str] = set() + mcp_client_endpoint_calls: list[ast.expr] = [] + self_endpoint_assignments: list[ast.expr] = [] + for candidate in ast.walk(tree): + if isinstance(candidate, ast.Import): + for alias in candidate.names: + import_aliases[alias.asname or _import_root(alias.name)] = _import_root(alias.name) + elif isinstance(candidate, ast.ImportFrom) and not candidate.level: + root = _import_root(candidate.module) + for alias in candidate.names: + local_name = alias.asname or alias.name + if root == "httpx" and ( + alias.name in HTTP_NETWORK_METHODS or alias.name in HTTP_CLIENT_FACTORIES + ): + forbidden_callable_aliases.add(local_name) + if root == "os" and ( + alias.name in {name for module, name in FORBIDDEN_ATTRIBUTE_CALLS if module == "os"} + or alias.name.startswith("exec") + ): + forbidden_callable_aliases.add(local_name) + if root == "builtins" and alias.name in FORBIDDEN_CALL_NAMES: + forbidden_callable_aliases.add(local_name) + + derived_client_names: set[str] = set() + release_constants: list[str] = [] + for candidate in ast.walk(tree): + if not isinstance(candidate, (ast.Assign, ast.AnnAssign)): + continue + value = candidate.value + targets = candidate.targets if isinstance(candidate, ast.Assign) else [candidate.target] + target_names = {target.id for target in targets if isinstance(target, ast.Name)} + if ( + "EXPECTED_STAGE2_RELEASE_SHA256" in target_names + and isinstance(value, ast.Constant) + and isinstance(value.value, str) + ): + release_constants.append(value.value) + if ( + isinstance(value, ast.Call) + and isinstance(value.func, ast.Attribute) + and isinstance(value.func.value, ast.Name) + and import_aliases.get(value.func.value.id, value.func.value.id) == "httpx" + and value.func.attr in HTTP_CLIENT_FACTORIES + ): + derived_client_names.update(target_names) + if isinstance(value, ast.Name) and ( + value.id in FORBIDDEN_CALL_NAMES or value.id in forbidden_callable_aliases + ): + forbidden_callable_aliases.update(target_names) + if isinstance(value, ast.Attribute) and isinstance(value.value, ast.Name): + module = import_aliases.get(value.value.id, value.value.id) + if (module, value.attr) in FORBIDDEN_ATTRIBUTE_CALLS or ( + module == "os" and value.attr.startswith("exec") + ): + forbidden_callable_aliases.update(target_names) + if module == "httpx" and value.attr in HTTP_NETWORK_METHODS: + forbidden_callable_aliases.update(target_names) + 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)) + root = _import_root(node.module) + for alias in node.names: + local_name = alias.asname or alias.name + if local_name in forbidden_callable_aliases: + forbidden_nodes.append(f"forbidden-import-alias:{root}.{alias.name}") + 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)): + assignment_targets = node.targets if isinstance(node, ast.Assign) else [node.target] + if any( + isinstance(target, ast.Attribute) + and isinstance(target.value, ast.Name) + and target.value.id == "self" + and target.attr == "endpoint" + for target in assignment_targets + ): + self_endpoint_assignments.append(node.value) + 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.Name) and node.func.id == "McpClient": + mcp_client_endpoint_calls.append( + node.args[0] if node.args else ast.Constant(value=None) + ) + 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.Attribute) + and node.func.attr in HTTP_NETWORK_METHODS + and isinstance(node.func.value, ast.Call) + and isinstance(node.func.value.func, ast.Attribute) + and isinstance(node.func.value.func.value, ast.Name) + and import_aliases.get( + node.func.value.func.value.id, + node.func.value.func.value.id, + ) == "httpx" + and node.func.value.func.attr in HTTP_CLIENT_FACTORIES + ): + 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 + or node.func.id in forbidden_callable_aliases + ): + forbidden_nodes.append(f"call:{node.func.id}") + elif isinstance(node.func, ast.Attribute): + pair = _attribute_pair(node.func) + if pair is not None: + module = import_aliases.get(pair[0], pair[0]) + if (module, pair[1]) in FORBIDDEN_ATTRIBUTE_CALLS or ( + module == "os" and pair[1].startswith("exec") + ): + forbidden_nodes.append(f"call:{module}.{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)) + ) + if ( + len(self_endpoint_assignments) != 1 + or not isinstance(self_endpoint_assignments[0], ast.Name) + or self_endpoint_assignments[0].id != "endpoint" + or not mcp_client_endpoint_calls + or any(not _is_localdocs_endpoint(endpoint) for endpoint in mcp_client_endpoint_calls) + ): + raise ProjectionError( + "INLINE_CODE_LOCALDOCS_ENDPOINT_FLOW_INVALID", + f"assignments={len(self_endpoint_assignments)};constructors={len(mcp_client_endpoint_calls)}", + ) + if len(release_constants) != 1 or not re.fullmatch(r"[a-f0-9]{64}", release_constants[0]): + raise ProjectionError( + "EXPECTED_PARENT_RELEASE_CONSTANT_EXACT_ONE_REQUIRED", + repr(release_constants), + ) + + 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, + "expected_parent_stage2_release_sha256": release_constants[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_40_inline_code_receipt.v1", + "workflow_id": "S2_40", + "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, + "exactly_one_stage": True, + "exactly_one_task": True, + "exactly_one_code_executor_run_code": True, + "authoring_rewritten": False, + "projection_byte_identical_to_authoring": True, + "code_mirrors_byte_identical": True, + "canonical_task_semantics_sha256": semantics_sha256, + }, + "expected_parent_stage2_release_sha256": validation[ + "expected_parent_stage2_release_sha256" + ], + "parity_status": "PASS", + } + outputs = { + PROJECTION_PATH: authoring_raw, + MIRROR_PY_PATH: code_bytes, + MIRROR_TXT_PATH: code_bytes, + RECEIPT_PATH: canonical_json_bytes(receipt), + } + return outputs, receipt + + +def _assert_output_target(path: Path) -> None: + root = DEPLOYMENT_ROOT.resolve(strict=True) + resolved = path.resolve(strict=False) + try: + resolved.relative_to(root) + except ValueError as exc: + raise ProjectionError("OUTPUT_OUTSIDE_DEPLOYMENT_ROOT", path.as_posix()) from exc + if path.exists() and path.is_symlink(): + raise ProjectionError("OUTPUT_SYMLINK_FORBIDDEN", path.as_posix()) + + +def _atomic_write(path: Path, payload: bytes) -> None: + _assert_output_target(path) + path.parent.mkdir(parents=True, exist_ok=True) + temporary_name: str | None = None + try: + with tempfile.NamedTemporaryFile( + mode="wb", + dir=path.parent, + prefix=f".{path.name}.", + suffix=".tmp", + delete=False, + ) as handle: + temporary_name = handle.name + handle.write(payload) + handle.flush() + os.fsync(handle.fileno()) + os.replace(temporary_name, path) + temporary_name = None + finally: + if temporary_name is not None: + try: + Path(temporary_name).unlink() + except FileNotFoundError: + pass + + +def compare_outputs(outputs: Mapping[Path, bytes]) -> list[dict[str, Any]]: + mismatches: list[dict[str, Any]] = [] + for path, expected in outputs.items(): + if not path.is_file(): + mismatches.append( + {"path": _logical_path(path), "status": "MISSING", "expected_sha256": sha256_bytes(expected)} + ) + continue + observed = path.read_bytes() + if observed != expected: + mismatches.append( + { + "path": _logical_path(path), + "status": "BYTE_MISMATCH", + "expected_sha256": sha256_bytes(expected), + "observed_sha256": sha256_bytes(observed), + } + ) + return mismatches + + +def run(*, check: bool) -> tuple[int, dict[str, Any]]: + before, document = load_authoring() + outputs, receipt = expected_outputs(before, document) + if check: + mismatches = compare_outputs(outputs) + return ( + 0 if not mismatches else 1, + { + "status": "PARITY_PASS" if not mismatches else "PARITY_DRIFT", + "mode": "CHECK_NO_WRITE", + "authoring_sha256": sha256_bytes(before), + "code_sha256": receipt["canonical_code"]["code_sha256"], + "mismatches": mismatches, + }, + ) + + receipt_payload = outputs[RECEIPT_PATH] + for path, payload in outputs.items(): + if path == RECEIPT_PATH: + 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_40 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()) diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/validate_s2_30_contract.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/validate_s2_30_contract.py index 48f863ea..e897871e 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/validate_s2_30_contract.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/validate_s2_30_contract.py @@ -125,29 +125,46 @@ ADVERSE_REQUIRED = frozenset( "presentation_authorization_ref", } ) -SUCCESS_ARTIFACT_FAMILIES = frozenset( - {"DRAFT_PART", "ISSUE_PATCH", "WORKNOTE_PART", "USAGE_PART", "ITEM_RECEIPT"} +PART_FAMILIES = frozenset( + {"DRAFT_PART", "ISSUE_PATCH", "WORKNOTE_PART", "USAGE_PART"} ) -SUCCESS_ARTIFACT_FILENAMES = { +PART_FILENAMES = { "DRAFT_PART": "draft_parts", "ISSUE_PATCH": "issue_patches", "WORKNOTE_PART": "worknote_parts", "USAGE_PART": "usage_parts", - "ITEM_RECEIPT": "item_receipts", } -PUBLISH_ARTIFACT_ROW_FIELDS = frozenset( +PART_SCHEMA_REFS = { + "DRAFT_PART": "schemas/draft_atoms.schema.json#/$defs/draft_part", + "ISSUE_PATCH": "schemas/draft_atoms.schema.json#/$defs/issue_patch_part", + "WORKNOTE_PART": "schemas/draft_atoms.schema.json#/$defs/worknote_part", + "USAGE_PART": "schemas/draft_atoms.schema.json#/$defs/usage_part", +} +PART_DEF_NAMES = { + "DRAFT_PART": "draft_part", + "ISSUE_PATCH": "issue_patch_part", + "WORKNOTE_PART": "worknote_part", + "USAGE_PART": "usage_part", +} +PART_SELF_HASH_FIELDS = {family: "part_sha256" for family in PART_FAMILIES} +COMMON_PROVENANCE_FIELDS = frozenset( { - "claim_group_id", - "artifact_family", - "artifact_path", - "artifact_sha256", - "read_back_sha256", - "immutable_write_status", - "read_back_status", - "item_receipt_path", - "item_receipt_sha256", - "item_receipt_persistence_status", - "artifact_receipt_sha256", + "compile_mode", + "parent_stage2_release_sha256", + "s2_30_release_sha256", + "s2_30_agent_sha256", + "s2_30_binding_sha256", + "p00_prompt_sha256", + "p30_prompt_sha256", + "s2_30_producer_contract_digest", + } +) +GROUP_PROVENANCE_FIELDS = frozenset( + { + *COMMON_PROVENANCE_FIELDS, + "p31_rule_and_pack_sha256", + "p32_common_authority_sha256", + "s30_group_slice_sha256", } ) REQUIRED_PENDING = { @@ -1765,79 +1782,328 @@ def evaluate_retry( raise ContractError("ATTEMPT_NO_INVALID", "$/attempt_no", repr(attempt_no)) +def _validate_handoff_provenance( + provenance: Mapping[str, Any], + *, + common_only: bool, + path: str, +) -> None: + expected = COMMON_PROVENANCE_FIELDS if common_only else GROUP_PROVENANCE_FIELDS + if set(provenance) != expected: + raise ContractError( + "HANDOFF_PROVENANCE_CLOSED_SHAPE", + path, + repr(sorted(set(provenance) ^ expected)), + ) + if provenance.get("compile_mode") not in ALLOWED_MODES: + raise ContractError( + "COMPILE_MODE_INVALID", f"{path}/compile_mode", repr(provenance.get("compile_mode")) + ) + for key in expected - {"compile_mode"}: + value = provenance.get(key) + if not isinstance(value, str) or HEX64.fullmatch(value) is None: + raise ContractError("HANDOFF_PROVENANCE_HASH_INVALID", f"{path}/{key}", repr(value)) + + +def _common_provenance(provenance: Mapping[str, Any]) -> dict[str, Any]: + return {key: provenance[key] for key in sorted(COMMON_PROVENANCE_FIELDS)} + + +def validate_persisted_part( + part: Mapping[str, Any], + family: str, + *, + expected_group_id: str | None = None, + expected_common_provenance: Mapping[str, Any] | None = None, + schema: Mapping[str, Any] | None = None, + path: str = "$/part", +) -> dict[str, Any]: + """Validate one immutable S2_30 physical part without discovering siblings.""" + + if family not in PART_FAMILIES: + raise ContractError("PART_FAMILY_INVALID", path, repr(family)) + if schema is not None: + validate_instance(part, PART_DEF_NAMES[family], schema) + _require_self_hash(part, PART_SELF_HASH_FIELDS[family], path) + group_id = part.get("claim_group_id") + if expected_group_id is not None and group_id != expected_group_id: + raise ContractError( + "PART_GROUP_MISMATCH", f"{path}/claim_group_id", repr((group_id, expected_group_id)) + ) + provenance = part.get("provenance") + if not isinstance(provenance, dict): + raise ContractError("HANDOFF_PROVENANCE_REQUIRED", f"{path}/provenance", repr(provenance)) + _validate_handoff_provenance(provenance, common_only=False, path=f"{path}/provenance") + if expected_common_provenance is not None and _common_provenance(provenance) != dict( + expected_common_provenance + ): + raise ContractError( + "PART_COMMON_PROVENANCE_MISMATCH", + f"{path}/provenance", + repr((_common_provenance(provenance), dict(expected_common_provenance))), + ) + if family == "DRAFT_PART": + atoms = part.get("canonical_atoms") + atom_ids = [row.get("atom_id") for row in atoms] if isinstance(atoms, list) else [] + if len(atom_ids) != len(set(atom_ids)): + raise ContractError("DRAFT_PART_ATOM_ID_DUPLICATE", f"{path}/canonical_atoms", repr(atom_ids)) + if any(isinstance(row, dict) and row.get("claim_group_id") != group_id for row in atoms or []): + raise ContractError("DRAFT_PART_ATOM_GROUP_MISMATCH", f"{path}/canonical_atoms", repr(group_id)) + coverage = part.get("atomic_claim_coverage") + coverage_refs = [ + ref + for row in coverage or [] + if isinstance(row, dict) + for key in ("relief_atom_local_refs", "cause_atom_local_refs") + for ref in row.get(key, []) + ] + if len(coverage_refs) != len(set(coverage_refs)) or set(coverage_refs) != set(atom_ids) - { + row.get("atom_id") + for row in atoms or [] + if isinstance(row, dict) and row.get("output_section") in {"procedural_declaration", "worknote_only"} + }: + raise ContractError("DRAFT_PART_COVERAGE_PARTITION_MISMATCH", f"{path}/atomic_claim_coverage", repr(coverage_refs)) + return {"status": "PASS", "claim_group_id": group_id, "part_family": family} + + +def validate_part_manifest_core( + manifest: Mapping[str, Any], + part_bytes_by_path: Mapping[str, bytes], + schema: Mapping[str, Any] | None = None, +) -> dict[str, Any]: + """Validate the receipt-free exact part index using only enumerated byte inputs.""" + + if schema is not None: + validate_instance(manifest, "part_manifest_core", schema) + _require_self_hash(manifest, "part_manifest_core_sha256", "$/artifact_manifest") + if any("receipt" in key.lower() for key in manifest): + raise ContractError("MANIFEST_RECEIPT_REFERENCE_FORBIDDEN", "$/artifact_manifest", repr(sorted(manifest))) + common = manifest.get("provenance") + if not isinstance(common, dict): + raise ContractError("HANDOFF_PROVENANCE_REQUIRED", "$/artifact_manifest/provenance", repr(common)) + _validate_handoff_provenance(common, common_only=True, path="$/artifact_manifest/provenance") + expected_groups = manifest.get("expected_claim_group_ids") + if not isinstance(expected_groups, list) or expected_groups != sorted(expected_groups): + raise ContractError("MANIFEST_GROUP_ORDER_INVALID", "$/artifact_manifest/expected_claim_group_ids", repr(expected_groups)) + rows = manifest.get("part_rows") + if not isinstance(rows, list): + raise ContractError("MANIFEST_PART_ROWS_REQUIRED", "$/artifact_manifest/part_rows", repr(rows)) + if any(not isinstance(row, dict) for row in rows): + raise ContractError("MANIFEST_PART_ROW_OBJECT_REQUIRED", "$/artifact_manifest/part_rows", repr(rows)) + sort_key = lambda row: (row.get("claim_group_id"), row.get("part_family"), row.get("path")) + if rows != sorted(rows, key=sort_key): + raise ContractError("MANIFEST_PART_ROW_ORDER_INVALID", "$/artifact_manifest/part_rows", "not stable sorted") + expected_pairs = {(group_id, family) for group_id in expected_groups for family in PART_FAMILIES} + observed_pairs: set[tuple[str, str]] = set() + declared_paths: list[str] = [] + group_provenance: dict[str, dict[str, Any]] = {} + for index, row in enumerate(rows): + if not isinstance(row, dict): + raise ContractError("MANIFEST_PART_ROW_OBJECT_REQUIRED", f"$/artifact_manifest/part_rows/{index}", repr(row)) + group_id = row.get("claim_group_id") + family = row.get("part_family") + pair = (str(group_id), str(family)) + if pair not in expected_pairs or pair in observed_pairs: + raise ContractError("MANIFEST_PART_PAIR_INVALID", f"$/artifact_manifest/part_rows/{index}", repr(pair)) + expected_path = f"map_s2_30/{PART_FILENAMES[str(family)]}/{group_id}.json" + if row.get("path") != expected_path or row.get("schema_ref") != PART_SCHEMA_REFS[str(family)]: + raise ContractError("MANIFEST_PART_BINDING_MISMATCH", f"$/artifact_manifest/part_rows/{index}", repr(row)) + declared_paths.append(expected_path) + raw = part_bytes_by_path.get(expected_path) + if not isinstance(raw, bytes): + raise ContractError("MANIFEST_PART_BYTES_MISSING", f"$/parts/{expected_path}", repr(type(raw))) + if sha256_bytes(raw) != row.get("sha256"): + raise ContractError("MANIFEST_PART_RAW_HASH_MISMATCH", f"$/parts/{expected_path}", repr(row.get("sha256"))) + part = parse_canonical_json_object(raw, f"$/parts/{expected_path}") + validate_persisted_part( + part, + str(family), + expected_group_id=str(group_id), + expected_common_provenance=common, + schema=schema, + path=f"$/parts/{expected_path}", + ) + observed_provenance = dict(part["provenance"]) + previous_provenance = group_provenance.get(str(group_id)) + if previous_provenance is not None and observed_provenance != previous_provenance: + raise ContractError( + "PART_GROUP_PROVENANCE_MISMATCH", + f"$/parts/{expected_path}/provenance", + repr((previous_provenance, observed_provenance)), + ) + group_provenance[str(group_id)] = observed_provenance + observed_pairs.add(pair) + if observed_pairs != expected_pairs: + raise ContractError("MANIFEST_PART_SET_MISMATCH", "$/artifact_manifest/part_rows", repr((observed_pairs, expected_pairs))) + if set(part_bytes_by_path) != set(declared_paths): + raise ContractError( + "UNENUMERATED_PART_INPUT_FORBIDDEN", + "$/parts", + repr(sorted(set(part_bytes_by_path) ^ set(declared_paths))), + ) + return { + "status": "PASS", + "claim_group_ids": expected_groups, + "part_count": len(rows), + "part_manifest_core_sha256": manifest["part_manifest_core_sha256"], + "group_provenance": group_provenance, + } + + +def _validate_receipt_object( + receipt: Mapping[str, Any], + def_name: str, + manifest_core_sha256: str, + common_provenance: Mapping[str, Any], + expected_group_provenance: Mapping[str, Any] | None, + schema: Mapping[str, Any] | None, + path: str, +) -> None: + if schema is not None: + validate_instance(receipt, def_name, schema) + _require_self_hash(receipt, "receipt_sha256", path) + if receipt.get("part_manifest_core_sha256") != manifest_core_sha256: + raise ContractError( + "RECEIPT_MANIFEST_CORE_HASH_MISMATCH", + f"{path}/part_manifest_core_sha256", + repr(receipt.get("part_manifest_core_sha256")), + ) + provenance = receipt.get("provenance") + if not isinstance(provenance, dict): + raise ContractError("HANDOFF_PROVENANCE_REQUIRED", f"{path}/provenance", repr(provenance)) + _validate_handoff_provenance( + provenance, + common_only=def_name == "cohort_receipt", + path=f"{path}/provenance", + ) + if _common_provenance(provenance) != dict(common_provenance): + raise ContractError("RECEIPT_COMMON_PROVENANCE_MISMATCH", f"{path}/provenance", repr(provenance)) + if expected_group_provenance is not None and dict(provenance) != dict(expected_group_provenance): + raise ContractError("ITEM_RECEIPT_GROUP_PROVENANCE_MISMATCH", f"{path}/provenance", repr(provenance)) + + +def validate_handoff_chain( + publish_status: Mapping[str, Any], + manifest: Mapping[str, Any], + part_bytes_by_path: Mapping[str, bytes], + item_receipt_bytes_by_path: Mapping[str, bytes], + cohort_receipt_bytes_by_path: Mapping[str, bytes], + schema: Mapping[str, Any] | None = None, +) -> dict[str, Any]: + """Validate barrier -> manifest -> parts and ordered receipts without scan/glob.""" + + if schema is not None: + validate_instance(publish_status, "publish_status", schema) + _require_self_hash(publish_status, "status_sha256", "$/publish_status") + manifest_report = validate_part_manifest_core(manifest, part_bytes_by_path, schema) + manifest_raw = canonical_json_bytes(manifest) + if publish_status.get("artifact_manifest_sha256") != sha256_bytes(manifest_raw): + raise ContractError("PUBLISH_MANIFEST_RAW_HASH_MISMATCH", "$/publish_status/artifact_manifest_sha256", "raw") + if publish_status.get("artifact_manifest_path") != "map_s2_30/artifact_manifest.json": + raise ContractError("PUBLISH_MANIFEST_PATH_MISMATCH", "$/publish_status/artifact_manifest_path", repr(publish_status.get("artifact_manifest_path"))) + common = manifest["provenance"] + if publish_status.get("provenance") != common: + raise ContractError("PUBLISH_COMMON_PROVENANCE_MISMATCH", "$/publish_status/provenance", "manifest") + if publish_status.get("compile_mode") != common.get("compile_mode"): + raise ContractError("PUBLISH_COMPILE_MODE_MISMATCH", "$/publish_status/compile_mode", repr(publish_status.get("compile_mode"))) + if publish_status.get("parent_stage2_release_sha256") != common.get("parent_stage2_release_sha256") or publish_status.get("s2_30_release_sha256") != common.get("s2_30_release_sha256"): + raise ContractError("PUBLISH_RELEASE_PROVENANCE_MISMATCH", "$/publish_status", "release") + expected_groups = list(manifest["expected_claim_group_ids"]) + if publish_status.get("expected_claim_group_ids") != expected_groups or publish_status.get("published_claim_group_ids") != expected_groups: + raise ContractError("PUBLISH_GROUP_SET_MISMATCH", "$/publish_status", repr(expected_groups)) + if publish_status.get("terminal_failure_claim_group_ids") != [] or publish_status.get("status") != "S2_30_COMPLETE" or publish_status.get("route") != "TO_S2_40": + raise ContractError("PUBLISH_SUCCESS_ROUTE_INVALID", "$/publish_status", repr(publish_status.get("route"))) + + item_refs = publish_status.get("ordered_item_receipts") + cohort_refs = publish_status.get("ordered_cohort_receipts") + if not isinstance(item_refs, list) or any(not isinstance(row, dict) for row in item_refs): + raise ContractError("ITEM_RECEIPT_REFS_INVALID", "$/publish_status/ordered_item_receipts", repr(item_refs)) + if not isinstance(cohort_refs, list) or any(not isinstance(row, dict) for row in cohort_refs): + raise ContractError("COHORT_RECEIPT_REFS_INVALID", "$/publish_status/ordered_cohort_receipts", repr(cohort_refs)) + if item_refs != sorted(item_refs, key=lambda row: (row.get("claim_group_id"), row.get("path"))): + raise ContractError("ITEM_RECEIPT_ORDER_INVALID", "$/publish_status/ordered_item_receipts", repr(item_refs)) + if cohort_refs != sorted(cohort_refs, key=lambda row: row.get("path")): + raise ContractError("COHORT_RECEIPT_ORDER_INVALID", "$/publish_status/ordered_cohort_receipts", repr(cohort_refs)) + if [row.get("claim_group_id") for row in item_refs] != expected_groups: + raise ContractError("ITEM_RECEIPT_GROUP_SET_MISMATCH", "$/publish_status/ordered_item_receipts", repr(item_refs)) + if set(item_receipt_bytes_by_path) != {row.get("path") for row in item_refs}: + raise ContractError("ITEM_RECEIPT_INPUT_SET_MISMATCH", "$/item_receipts", repr(sorted(item_receipt_bytes_by_path))) + if set(cohort_receipt_bytes_by_path) != {row.get("path") for row in cohort_refs}: + raise ContractError("COHORT_RECEIPT_INPUT_SET_MISMATCH", "$/cohort_receipts", repr(sorted(cohort_receipt_bytes_by_path))) + for index, ref in enumerate(item_refs): + raw = item_receipt_bytes_by_path[ref["path"]] + if sha256_bytes(raw) != ref.get("sha256"): + raise ContractError("ITEM_RECEIPT_RAW_HASH_MISMATCH", f"$/item_receipts/{index}", ref["path"]) + receipt = parse_canonical_json_object(raw, f"$/item_receipts/{index}") + _validate_receipt_object( + receipt, + "item_receipt", + manifest["part_manifest_core_sha256"], + common, + manifest_report["group_provenance"].get(str(ref.get("claim_group_id"))), + schema, + f"$/item_receipts/{index}", + ) + if receipt.get("claim_group_id") != ref.get("claim_group_id"): + raise ContractError("ITEM_RECEIPT_GROUP_MISMATCH", f"$/item_receipts/{index}", ref["path"]) + for index, ref in enumerate(cohort_refs): + raw = cohort_receipt_bytes_by_path[ref["path"]] + if sha256_bytes(raw) != ref.get("sha256"): + raise ContractError("COHORT_RECEIPT_RAW_HASH_MISMATCH", f"$/cohort_receipts/{index}", ref["path"]) + receipt = parse_canonical_json_object(raw, f"$/cohort_receipts/{index}") + _validate_receipt_object( + receipt, + "cohort_receipt", + manifest["part_manifest_core_sha256"], + common, + None, + schema, + f"$/cohort_receipts/{index}", + ) + return { + "status": "PASS", + "publish_status_allowed": True, + "claim_group_ids": expected_groups, + "part_count": manifest_report["part_count"], + "item_receipt_count": len(item_refs), + "cohort_receipt_count": len(cohort_refs), + "physical_atomicity_attested": False, + } + + def validate_publish_barrier(bundle: Mapping[str, Any]) -> dict[str, Any]: + """Status-last barrier oracle over explicit objects/bytes; discovery is forbidden.""" + expected = set(bundle.get("expected_group_ids", [])) succeeded = set(bundle.get("succeeded_group_ids", [])) failed = set(bundle.get("failed_group_ids", [])) if not expected or succeeded & failed or succeeded | failed != expected: raise ContractError("PUBLISH_PARTITION_MISMATCH", "$", repr((expected, succeeded, failed))) - artifact_rows = bundle.get("artifact_rows") - if not isinstance(artifact_rows, list): - raise ContractError("ARTIFACT_ROWS_REQUIRED", "$/artifact_rows", repr(type(artifact_rows))) - verified_families: dict[str, set[str]] = {group_id: set() for group_id in expected} - for index, row in enumerate(artifact_rows): - if not isinstance(row, dict): - raise ContractError("ARTIFACT_ROW_OBJECT_REQUIRED", f"$/artifact_rows/{index}", repr(row)) - if set(row) != PUBLISH_ARTIFACT_ROW_FIELDS: - raise ContractError( - "ARTIFACT_ROW_CLOSED_SHAPE", - f"$/artifact_rows/{index}", - repr(sorted(set(row) ^ PUBLISH_ARTIFACT_ROW_FIELDS)), - ) - _require_self_hash(row, "artifact_receipt_sha256", f"$/artifact_rows/{index}") - group_id = row.get("claim_group_id") - family = row.get("artifact_family") - if group_id not in expected or family not in SUCCESS_ARTIFACT_FAMILIES: - raise ContractError("ARTIFACT_FAMILY_OR_GROUP_INVALID", f"$/artifact_rows/{index}", repr((group_id, family))) - expected_path = f"map_s2_30/{SUCCESS_ARTIFACT_FILENAMES[str(family)]}/{group_id}.json" - receipt_path = f"map_s2_30/item_receipts/{group_id}.json" - if row.get("artifact_path") != expected_path or row.get("item_receipt_path") != receipt_path: - raise ContractError( - "ARTIFACT_PATH_BINDING_MISMATCH", - f"$/artifact_rows/{index}", - repr((row.get("artifact_path"), row.get("item_receipt_path"))), - ) - artifact_sha = row.get("artifact_sha256") - read_back_sha = row.get("read_back_sha256") - item_receipt_sha = row.get("item_receipt_sha256") - if any( - not isinstance(value, str) or HEX64.fullmatch(value) is None - for value in (artifact_sha, read_back_sha, item_receipt_sha) - ): - raise ContractError("ARTIFACT_HASH_INVALID", f"$/artifact_rows/{index}", repr(row)) - if artifact_sha != read_back_sha: - raise ContractError( - "ARTIFACT_READ_BACK_HASH_MISMATCH", - f"$/artifact_rows/{index}", - repr((artifact_sha, read_back_sha)), - ) - if family == "ITEM_RECEIPT" and artifact_sha != item_receipt_sha: - raise ContractError( - "ITEM_RECEIPT_HASH_BINDING_MISMATCH", - f"$/artifact_rows/{index}", - repr((artifact_sha, item_receipt_sha)), - ) - if ( - row.get("immutable_write_status") in {"CREATED", "IDEMPOTENT_MATCH"} - and row.get("read_back_status") == "PASS" - and row.get("item_receipt_persistence_status") in {"PUBLISHED", "IDEMPOTENT_BYTE_IDENTICAL"} - ): - if family in verified_families[str(group_id)]: - raise ContractError("ARTIFACT_FAMILY_DUPLICATE", f"$/artifact_rows/{index}", str(family)) - verified_families[str(group_id)].add(str(family)) - verified = { - group_id - for group_id, families in verified_families.items() - if families == SUCCESS_ARTIFACT_FAMILIES - } status_written = bool(bundle.get("publish_status_written")) - if status_written and (failed or verified != expected): - raise ContractError("STATUS_LAST_BARRIER_VIOLATION", "$/publish_status_written", repr((verified, expected, failed))) - return { - "status": "PASS", - "publish_status_allowed": not failed and verified == expected, - "physical_atomicity_attested": False, - } + if status_written and failed: + raise ContractError("STATUS_LAST_BARRIER_VIOLATION", "$/publish_status_written", repr(sorted(failed))) + required = ( + "publish_status", + "artifact_manifest", + "part_bytes_by_path", + "item_receipt_bytes_by_path", + "cohort_receipt_bytes_by_path", + ) + missing = [key for key in required if key not in bundle] + if missing: + raise ContractError("STATUS_LAST_BARRIER_VIOLATION", "$", repr(missing)) + report = validate_handoff_chain( + bundle["publish_status"], + bundle["artifact_manifest"], + bundle["part_bytes_by_path"], + bundle["item_receipt_bytes_by_path"], + bundle["cohort_receipt_bytes_by_path"], + bundle.get("schema"), + ) + if set(report["claim_group_ids"]) != expected: + raise ContractError("PUBLISH_GROUP_SET_MISMATCH", "$", repr((report["claim_group_ids"], sorted(expected)))) + report["publish_status_allowed"] = status_written and not failed + return report def validate_pending_external_receipt(kind: str, receipt: Mapping[str, Any]) -> None: @@ -1866,7 +2132,7 @@ def validate_embedded_task_admission( if not isinstance(stage_rows, list) or not isinstance(helper_rows, list): raise ContractError("EXECUTOR_BINDING_ARRAYS_REQUIRED", "$", "stage/helper") stage_ids = [row.get("stage_id") for row in stage_rows if isinstance(row, dict)] - if stage_ids != ["S2_00", "S2_20"] or "S2_30" in stage_ids: + if stage_ids != ["S2_00", "S2_20", "S2_40"] or "S2_30" in stage_ids: raise ContractError("S2_30_STAGE_MISCLASSIFIED", "$/stage_bindings", repr(stage_ids)) if len(helper_rows) != 1 or not isinstance(helper_rows[0], dict): raise ContractError("S2_30_HELPER_EXACT_ONE_REQUIRED", "$/embedded_task_bindings", repr(helper_rows)) @@ -1907,7 +2173,7 @@ def validate_embedded_task_admission( if admission.get("executor_binding_sha256") != binding_sha256: raise ContractError("ADMISSION_EXECUTOR_HASH_MISMATCH", "$/executor_binding_sha256", repr(admission.get("executor_binding_sha256"))) - if admission.get("present_deterministic_stage_ids") != ["S2_00", "S2_20"]: + if admission.get("present_deterministic_stage_ids") != ["S2_00", "S2_20", "S2_40"]: raise ContractError("ADMISSION_STAGE_SET_MISMATCH", "$/present_deterministic_stage_ids", repr(admission.get("present_deterministic_stage_ids"))) embedded = admission.get("embedded_task_admissions") if not isinstance(embedded, list) or len(embedded) != 1 or not isinstance(embedded[0], dict): diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/validate_s2_30_contract.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/validate_s2_30_contract.txt index 48f863ea..e897871e 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/validate_s2_30_contract.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/offline_build/validate_s2_30_contract.txt @@ -125,29 +125,46 @@ ADVERSE_REQUIRED = frozenset( "presentation_authorization_ref", } ) -SUCCESS_ARTIFACT_FAMILIES = frozenset( - {"DRAFT_PART", "ISSUE_PATCH", "WORKNOTE_PART", "USAGE_PART", "ITEM_RECEIPT"} +PART_FAMILIES = frozenset( + {"DRAFT_PART", "ISSUE_PATCH", "WORKNOTE_PART", "USAGE_PART"} ) -SUCCESS_ARTIFACT_FILENAMES = { +PART_FILENAMES = { "DRAFT_PART": "draft_parts", "ISSUE_PATCH": "issue_patches", "WORKNOTE_PART": "worknote_parts", "USAGE_PART": "usage_parts", - "ITEM_RECEIPT": "item_receipts", } -PUBLISH_ARTIFACT_ROW_FIELDS = frozenset( +PART_SCHEMA_REFS = { + "DRAFT_PART": "schemas/draft_atoms.schema.json#/$defs/draft_part", + "ISSUE_PATCH": "schemas/draft_atoms.schema.json#/$defs/issue_patch_part", + "WORKNOTE_PART": "schemas/draft_atoms.schema.json#/$defs/worknote_part", + "USAGE_PART": "schemas/draft_atoms.schema.json#/$defs/usage_part", +} +PART_DEF_NAMES = { + "DRAFT_PART": "draft_part", + "ISSUE_PATCH": "issue_patch_part", + "WORKNOTE_PART": "worknote_part", + "USAGE_PART": "usage_part", +} +PART_SELF_HASH_FIELDS = {family: "part_sha256" for family in PART_FAMILIES} +COMMON_PROVENANCE_FIELDS = frozenset( { - "claim_group_id", - "artifact_family", - "artifact_path", - "artifact_sha256", - "read_back_sha256", - "immutable_write_status", - "read_back_status", - "item_receipt_path", - "item_receipt_sha256", - "item_receipt_persistence_status", - "artifact_receipt_sha256", + "compile_mode", + "parent_stage2_release_sha256", + "s2_30_release_sha256", + "s2_30_agent_sha256", + "s2_30_binding_sha256", + "p00_prompt_sha256", + "p30_prompt_sha256", + "s2_30_producer_contract_digest", + } +) +GROUP_PROVENANCE_FIELDS = frozenset( + { + *COMMON_PROVENANCE_FIELDS, + "p31_rule_and_pack_sha256", + "p32_common_authority_sha256", + "s30_group_slice_sha256", } ) REQUIRED_PENDING = { @@ -1765,79 +1782,328 @@ def evaluate_retry( raise ContractError("ATTEMPT_NO_INVALID", "$/attempt_no", repr(attempt_no)) +def _validate_handoff_provenance( + provenance: Mapping[str, Any], + *, + common_only: bool, + path: str, +) -> None: + expected = COMMON_PROVENANCE_FIELDS if common_only else GROUP_PROVENANCE_FIELDS + if set(provenance) != expected: + raise ContractError( + "HANDOFF_PROVENANCE_CLOSED_SHAPE", + path, + repr(sorted(set(provenance) ^ expected)), + ) + if provenance.get("compile_mode") not in ALLOWED_MODES: + raise ContractError( + "COMPILE_MODE_INVALID", f"{path}/compile_mode", repr(provenance.get("compile_mode")) + ) + for key in expected - {"compile_mode"}: + value = provenance.get(key) + if not isinstance(value, str) or HEX64.fullmatch(value) is None: + raise ContractError("HANDOFF_PROVENANCE_HASH_INVALID", f"{path}/{key}", repr(value)) + + +def _common_provenance(provenance: Mapping[str, Any]) -> dict[str, Any]: + return {key: provenance[key] for key in sorted(COMMON_PROVENANCE_FIELDS)} + + +def validate_persisted_part( + part: Mapping[str, Any], + family: str, + *, + expected_group_id: str | None = None, + expected_common_provenance: Mapping[str, Any] | None = None, + schema: Mapping[str, Any] | None = None, + path: str = "$/part", +) -> dict[str, Any]: + """Validate one immutable S2_30 physical part without discovering siblings.""" + + if family not in PART_FAMILIES: + raise ContractError("PART_FAMILY_INVALID", path, repr(family)) + if schema is not None: + validate_instance(part, PART_DEF_NAMES[family], schema) + _require_self_hash(part, PART_SELF_HASH_FIELDS[family], path) + group_id = part.get("claim_group_id") + if expected_group_id is not None and group_id != expected_group_id: + raise ContractError( + "PART_GROUP_MISMATCH", f"{path}/claim_group_id", repr((group_id, expected_group_id)) + ) + provenance = part.get("provenance") + if not isinstance(provenance, dict): + raise ContractError("HANDOFF_PROVENANCE_REQUIRED", f"{path}/provenance", repr(provenance)) + _validate_handoff_provenance(provenance, common_only=False, path=f"{path}/provenance") + if expected_common_provenance is not None and _common_provenance(provenance) != dict( + expected_common_provenance + ): + raise ContractError( + "PART_COMMON_PROVENANCE_MISMATCH", + f"{path}/provenance", + repr((_common_provenance(provenance), dict(expected_common_provenance))), + ) + if family == "DRAFT_PART": + atoms = part.get("canonical_atoms") + atom_ids = [row.get("atom_id") for row in atoms] if isinstance(atoms, list) else [] + if len(atom_ids) != len(set(atom_ids)): + raise ContractError("DRAFT_PART_ATOM_ID_DUPLICATE", f"{path}/canonical_atoms", repr(atom_ids)) + if any(isinstance(row, dict) and row.get("claim_group_id") != group_id for row in atoms or []): + raise ContractError("DRAFT_PART_ATOM_GROUP_MISMATCH", f"{path}/canonical_atoms", repr(group_id)) + coverage = part.get("atomic_claim_coverage") + coverage_refs = [ + ref + for row in coverage or [] + if isinstance(row, dict) + for key in ("relief_atom_local_refs", "cause_atom_local_refs") + for ref in row.get(key, []) + ] + if len(coverage_refs) != len(set(coverage_refs)) or set(coverage_refs) != set(atom_ids) - { + row.get("atom_id") + for row in atoms or [] + if isinstance(row, dict) and row.get("output_section") in {"procedural_declaration", "worknote_only"} + }: + raise ContractError("DRAFT_PART_COVERAGE_PARTITION_MISMATCH", f"{path}/atomic_claim_coverage", repr(coverage_refs)) + return {"status": "PASS", "claim_group_id": group_id, "part_family": family} + + +def validate_part_manifest_core( + manifest: Mapping[str, Any], + part_bytes_by_path: Mapping[str, bytes], + schema: Mapping[str, Any] | None = None, +) -> dict[str, Any]: + """Validate the receipt-free exact part index using only enumerated byte inputs.""" + + if schema is not None: + validate_instance(manifest, "part_manifest_core", schema) + _require_self_hash(manifest, "part_manifest_core_sha256", "$/artifact_manifest") + if any("receipt" in key.lower() for key in manifest): + raise ContractError("MANIFEST_RECEIPT_REFERENCE_FORBIDDEN", "$/artifact_manifest", repr(sorted(manifest))) + common = manifest.get("provenance") + if not isinstance(common, dict): + raise ContractError("HANDOFF_PROVENANCE_REQUIRED", "$/artifact_manifest/provenance", repr(common)) + _validate_handoff_provenance(common, common_only=True, path="$/artifact_manifest/provenance") + expected_groups = manifest.get("expected_claim_group_ids") + if not isinstance(expected_groups, list) or expected_groups != sorted(expected_groups): + raise ContractError("MANIFEST_GROUP_ORDER_INVALID", "$/artifact_manifest/expected_claim_group_ids", repr(expected_groups)) + rows = manifest.get("part_rows") + if not isinstance(rows, list): + raise ContractError("MANIFEST_PART_ROWS_REQUIRED", "$/artifact_manifest/part_rows", repr(rows)) + if any(not isinstance(row, dict) for row in rows): + raise ContractError("MANIFEST_PART_ROW_OBJECT_REQUIRED", "$/artifact_manifest/part_rows", repr(rows)) + sort_key = lambda row: (row.get("claim_group_id"), row.get("part_family"), row.get("path")) + if rows != sorted(rows, key=sort_key): + raise ContractError("MANIFEST_PART_ROW_ORDER_INVALID", "$/artifact_manifest/part_rows", "not stable sorted") + expected_pairs = {(group_id, family) for group_id in expected_groups for family in PART_FAMILIES} + observed_pairs: set[tuple[str, str]] = set() + declared_paths: list[str] = [] + group_provenance: dict[str, dict[str, Any]] = {} + for index, row in enumerate(rows): + if not isinstance(row, dict): + raise ContractError("MANIFEST_PART_ROW_OBJECT_REQUIRED", f"$/artifact_manifest/part_rows/{index}", repr(row)) + group_id = row.get("claim_group_id") + family = row.get("part_family") + pair = (str(group_id), str(family)) + if pair not in expected_pairs or pair in observed_pairs: + raise ContractError("MANIFEST_PART_PAIR_INVALID", f"$/artifact_manifest/part_rows/{index}", repr(pair)) + expected_path = f"map_s2_30/{PART_FILENAMES[str(family)]}/{group_id}.json" + if row.get("path") != expected_path or row.get("schema_ref") != PART_SCHEMA_REFS[str(family)]: + raise ContractError("MANIFEST_PART_BINDING_MISMATCH", f"$/artifact_manifest/part_rows/{index}", repr(row)) + declared_paths.append(expected_path) + raw = part_bytes_by_path.get(expected_path) + if not isinstance(raw, bytes): + raise ContractError("MANIFEST_PART_BYTES_MISSING", f"$/parts/{expected_path}", repr(type(raw))) + if sha256_bytes(raw) != row.get("sha256"): + raise ContractError("MANIFEST_PART_RAW_HASH_MISMATCH", f"$/parts/{expected_path}", repr(row.get("sha256"))) + part = parse_canonical_json_object(raw, f"$/parts/{expected_path}") + validate_persisted_part( + part, + str(family), + expected_group_id=str(group_id), + expected_common_provenance=common, + schema=schema, + path=f"$/parts/{expected_path}", + ) + observed_provenance = dict(part["provenance"]) + previous_provenance = group_provenance.get(str(group_id)) + if previous_provenance is not None and observed_provenance != previous_provenance: + raise ContractError( + "PART_GROUP_PROVENANCE_MISMATCH", + f"$/parts/{expected_path}/provenance", + repr((previous_provenance, observed_provenance)), + ) + group_provenance[str(group_id)] = observed_provenance + observed_pairs.add(pair) + if observed_pairs != expected_pairs: + raise ContractError("MANIFEST_PART_SET_MISMATCH", "$/artifact_manifest/part_rows", repr((observed_pairs, expected_pairs))) + if set(part_bytes_by_path) != set(declared_paths): + raise ContractError( + "UNENUMERATED_PART_INPUT_FORBIDDEN", + "$/parts", + repr(sorted(set(part_bytes_by_path) ^ set(declared_paths))), + ) + return { + "status": "PASS", + "claim_group_ids": expected_groups, + "part_count": len(rows), + "part_manifest_core_sha256": manifest["part_manifest_core_sha256"], + "group_provenance": group_provenance, + } + + +def _validate_receipt_object( + receipt: Mapping[str, Any], + def_name: str, + manifest_core_sha256: str, + common_provenance: Mapping[str, Any], + expected_group_provenance: Mapping[str, Any] | None, + schema: Mapping[str, Any] | None, + path: str, +) -> None: + if schema is not None: + validate_instance(receipt, def_name, schema) + _require_self_hash(receipt, "receipt_sha256", path) + if receipt.get("part_manifest_core_sha256") != manifest_core_sha256: + raise ContractError( + "RECEIPT_MANIFEST_CORE_HASH_MISMATCH", + f"{path}/part_manifest_core_sha256", + repr(receipt.get("part_manifest_core_sha256")), + ) + provenance = receipt.get("provenance") + if not isinstance(provenance, dict): + raise ContractError("HANDOFF_PROVENANCE_REQUIRED", f"{path}/provenance", repr(provenance)) + _validate_handoff_provenance( + provenance, + common_only=def_name == "cohort_receipt", + path=f"{path}/provenance", + ) + if _common_provenance(provenance) != dict(common_provenance): + raise ContractError("RECEIPT_COMMON_PROVENANCE_MISMATCH", f"{path}/provenance", repr(provenance)) + if expected_group_provenance is not None and dict(provenance) != dict(expected_group_provenance): + raise ContractError("ITEM_RECEIPT_GROUP_PROVENANCE_MISMATCH", f"{path}/provenance", repr(provenance)) + + +def validate_handoff_chain( + publish_status: Mapping[str, Any], + manifest: Mapping[str, Any], + part_bytes_by_path: Mapping[str, bytes], + item_receipt_bytes_by_path: Mapping[str, bytes], + cohort_receipt_bytes_by_path: Mapping[str, bytes], + schema: Mapping[str, Any] | None = None, +) -> dict[str, Any]: + """Validate barrier -> manifest -> parts and ordered receipts without scan/glob.""" + + if schema is not None: + validate_instance(publish_status, "publish_status", schema) + _require_self_hash(publish_status, "status_sha256", "$/publish_status") + manifest_report = validate_part_manifest_core(manifest, part_bytes_by_path, schema) + manifest_raw = canonical_json_bytes(manifest) + if publish_status.get("artifact_manifest_sha256") != sha256_bytes(manifest_raw): + raise ContractError("PUBLISH_MANIFEST_RAW_HASH_MISMATCH", "$/publish_status/artifact_manifest_sha256", "raw") + if publish_status.get("artifact_manifest_path") != "map_s2_30/artifact_manifest.json": + raise ContractError("PUBLISH_MANIFEST_PATH_MISMATCH", "$/publish_status/artifact_manifest_path", repr(publish_status.get("artifact_manifest_path"))) + common = manifest["provenance"] + if publish_status.get("provenance") != common: + raise ContractError("PUBLISH_COMMON_PROVENANCE_MISMATCH", "$/publish_status/provenance", "manifest") + if publish_status.get("compile_mode") != common.get("compile_mode"): + raise ContractError("PUBLISH_COMPILE_MODE_MISMATCH", "$/publish_status/compile_mode", repr(publish_status.get("compile_mode"))) + if publish_status.get("parent_stage2_release_sha256") != common.get("parent_stage2_release_sha256") or publish_status.get("s2_30_release_sha256") != common.get("s2_30_release_sha256"): + raise ContractError("PUBLISH_RELEASE_PROVENANCE_MISMATCH", "$/publish_status", "release") + expected_groups = list(manifest["expected_claim_group_ids"]) + if publish_status.get("expected_claim_group_ids") != expected_groups or publish_status.get("published_claim_group_ids") != expected_groups: + raise ContractError("PUBLISH_GROUP_SET_MISMATCH", "$/publish_status", repr(expected_groups)) + if publish_status.get("terminal_failure_claim_group_ids") != [] or publish_status.get("status") != "S2_30_COMPLETE" or publish_status.get("route") != "TO_S2_40": + raise ContractError("PUBLISH_SUCCESS_ROUTE_INVALID", "$/publish_status", repr(publish_status.get("route"))) + + item_refs = publish_status.get("ordered_item_receipts") + cohort_refs = publish_status.get("ordered_cohort_receipts") + if not isinstance(item_refs, list) or any(not isinstance(row, dict) for row in item_refs): + raise ContractError("ITEM_RECEIPT_REFS_INVALID", "$/publish_status/ordered_item_receipts", repr(item_refs)) + if not isinstance(cohort_refs, list) or any(not isinstance(row, dict) for row in cohort_refs): + raise ContractError("COHORT_RECEIPT_REFS_INVALID", "$/publish_status/ordered_cohort_receipts", repr(cohort_refs)) + if item_refs != sorted(item_refs, key=lambda row: (row.get("claim_group_id"), row.get("path"))): + raise ContractError("ITEM_RECEIPT_ORDER_INVALID", "$/publish_status/ordered_item_receipts", repr(item_refs)) + if cohort_refs != sorted(cohort_refs, key=lambda row: row.get("path")): + raise ContractError("COHORT_RECEIPT_ORDER_INVALID", "$/publish_status/ordered_cohort_receipts", repr(cohort_refs)) + if [row.get("claim_group_id") for row in item_refs] != expected_groups: + raise ContractError("ITEM_RECEIPT_GROUP_SET_MISMATCH", "$/publish_status/ordered_item_receipts", repr(item_refs)) + if set(item_receipt_bytes_by_path) != {row.get("path") for row in item_refs}: + raise ContractError("ITEM_RECEIPT_INPUT_SET_MISMATCH", "$/item_receipts", repr(sorted(item_receipt_bytes_by_path))) + if set(cohort_receipt_bytes_by_path) != {row.get("path") for row in cohort_refs}: + raise ContractError("COHORT_RECEIPT_INPUT_SET_MISMATCH", "$/cohort_receipts", repr(sorted(cohort_receipt_bytes_by_path))) + for index, ref in enumerate(item_refs): + raw = item_receipt_bytes_by_path[ref["path"]] + if sha256_bytes(raw) != ref.get("sha256"): + raise ContractError("ITEM_RECEIPT_RAW_HASH_MISMATCH", f"$/item_receipts/{index}", ref["path"]) + receipt = parse_canonical_json_object(raw, f"$/item_receipts/{index}") + _validate_receipt_object( + receipt, + "item_receipt", + manifest["part_manifest_core_sha256"], + common, + manifest_report["group_provenance"].get(str(ref.get("claim_group_id"))), + schema, + f"$/item_receipts/{index}", + ) + if receipt.get("claim_group_id") != ref.get("claim_group_id"): + raise ContractError("ITEM_RECEIPT_GROUP_MISMATCH", f"$/item_receipts/{index}", ref["path"]) + for index, ref in enumerate(cohort_refs): + raw = cohort_receipt_bytes_by_path[ref["path"]] + if sha256_bytes(raw) != ref.get("sha256"): + raise ContractError("COHORT_RECEIPT_RAW_HASH_MISMATCH", f"$/cohort_receipts/{index}", ref["path"]) + receipt = parse_canonical_json_object(raw, f"$/cohort_receipts/{index}") + _validate_receipt_object( + receipt, + "cohort_receipt", + manifest["part_manifest_core_sha256"], + common, + None, + schema, + f"$/cohort_receipts/{index}", + ) + return { + "status": "PASS", + "publish_status_allowed": True, + "claim_group_ids": expected_groups, + "part_count": manifest_report["part_count"], + "item_receipt_count": len(item_refs), + "cohort_receipt_count": len(cohort_refs), + "physical_atomicity_attested": False, + } + + def validate_publish_barrier(bundle: Mapping[str, Any]) -> dict[str, Any]: + """Status-last barrier oracle over explicit objects/bytes; discovery is forbidden.""" + expected = set(bundle.get("expected_group_ids", [])) succeeded = set(bundle.get("succeeded_group_ids", [])) failed = set(bundle.get("failed_group_ids", [])) if not expected or succeeded & failed or succeeded | failed != expected: raise ContractError("PUBLISH_PARTITION_MISMATCH", "$", repr((expected, succeeded, failed))) - artifact_rows = bundle.get("artifact_rows") - if not isinstance(artifact_rows, list): - raise ContractError("ARTIFACT_ROWS_REQUIRED", "$/artifact_rows", repr(type(artifact_rows))) - verified_families: dict[str, set[str]] = {group_id: set() for group_id in expected} - for index, row in enumerate(artifact_rows): - if not isinstance(row, dict): - raise ContractError("ARTIFACT_ROW_OBJECT_REQUIRED", f"$/artifact_rows/{index}", repr(row)) - if set(row) != PUBLISH_ARTIFACT_ROW_FIELDS: - raise ContractError( - "ARTIFACT_ROW_CLOSED_SHAPE", - f"$/artifact_rows/{index}", - repr(sorted(set(row) ^ PUBLISH_ARTIFACT_ROW_FIELDS)), - ) - _require_self_hash(row, "artifact_receipt_sha256", f"$/artifact_rows/{index}") - group_id = row.get("claim_group_id") - family = row.get("artifact_family") - if group_id not in expected or family not in SUCCESS_ARTIFACT_FAMILIES: - raise ContractError("ARTIFACT_FAMILY_OR_GROUP_INVALID", f"$/artifact_rows/{index}", repr((group_id, family))) - expected_path = f"map_s2_30/{SUCCESS_ARTIFACT_FILENAMES[str(family)]}/{group_id}.json" - receipt_path = f"map_s2_30/item_receipts/{group_id}.json" - if row.get("artifact_path") != expected_path or row.get("item_receipt_path") != receipt_path: - raise ContractError( - "ARTIFACT_PATH_BINDING_MISMATCH", - f"$/artifact_rows/{index}", - repr((row.get("artifact_path"), row.get("item_receipt_path"))), - ) - artifact_sha = row.get("artifact_sha256") - read_back_sha = row.get("read_back_sha256") - item_receipt_sha = row.get("item_receipt_sha256") - if any( - not isinstance(value, str) or HEX64.fullmatch(value) is None - for value in (artifact_sha, read_back_sha, item_receipt_sha) - ): - raise ContractError("ARTIFACT_HASH_INVALID", f"$/artifact_rows/{index}", repr(row)) - if artifact_sha != read_back_sha: - raise ContractError( - "ARTIFACT_READ_BACK_HASH_MISMATCH", - f"$/artifact_rows/{index}", - repr((artifact_sha, read_back_sha)), - ) - if family == "ITEM_RECEIPT" and artifact_sha != item_receipt_sha: - raise ContractError( - "ITEM_RECEIPT_HASH_BINDING_MISMATCH", - f"$/artifact_rows/{index}", - repr((artifact_sha, item_receipt_sha)), - ) - if ( - row.get("immutable_write_status") in {"CREATED", "IDEMPOTENT_MATCH"} - and row.get("read_back_status") == "PASS" - and row.get("item_receipt_persistence_status") in {"PUBLISHED", "IDEMPOTENT_BYTE_IDENTICAL"} - ): - if family in verified_families[str(group_id)]: - raise ContractError("ARTIFACT_FAMILY_DUPLICATE", f"$/artifact_rows/{index}", str(family)) - verified_families[str(group_id)].add(str(family)) - verified = { - group_id - for group_id, families in verified_families.items() - if families == SUCCESS_ARTIFACT_FAMILIES - } status_written = bool(bundle.get("publish_status_written")) - if status_written and (failed or verified != expected): - raise ContractError("STATUS_LAST_BARRIER_VIOLATION", "$/publish_status_written", repr((verified, expected, failed))) - return { - "status": "PASS", - "publish_status_allowed": not failed and verified == expected, - "physical_atomicity_attested": False, - } + if status_written and failed: + raise ContractError("STATUS_LAST_BARRIER_VIOLATION", "$/publish_status_written", repr(sorted(failed))) + required = ( + "publish_status", + "artifact_manifest", + "part_bytes_by_path", + "item_receipt_bytes_by_path", + "cohort_receipt_bytes_by_path", + ) + missing = [key for key in required if key not in bundle] + if missing: + raise ContractError("STATUS_LAST_BARRIER_VIOLATION", "$", repr(missing)) + report = validate_handoff_chain( + bundle["publish_status"], + bundle["artifact_manifest"], + bundle["part_bytes_by_path"], + bundle["item_receipt_bytes_by_path"], + bundle["cohort_receipt_bytes_by_path"], + bundle.get("schema"), + ) + if set(report["claim_group_ids"]) != expected: + raise ContractError("PUBLISH_GROUP_SET_MISMATCH", "$", repr((report["claim_group_ids"], sorted(expected)))) + report["publish_status_allowed"] = status_written and not failed + return report def validate_pending_external_receipt(kind: str, receipt: Mapping[str, Any]) -> None: @@ -1866,7 +2132,7 @@ def validate_embedded_task_admission( if not isinstance(stage_rows, list) or not isinstance(helper_rows, list): raise ContractError("EXECUTOR_BINDING_ARRAYS_REQUIRED", "$", "stage/helper") stage_ids = [row.get("stage_id") for row in stage_rows if isinstance(row, dict)] - if stage_ids != ["S2_00", "S2_20"] or "S2_30" in stage_ids: + if stage_ids != ["S2_00", "S2_20", "S2_40"] or "S2_30" in stage_ids: raise ContractError("S2_30_STAGE_MISCLASSIFIED", "$/stage_bindings", repr(stage_ids)) if len(helper_rows) != 1 or not isinstance(helper_rows[0], dict): raise ContractError("S2_30_HELPER_EXACT_ONE_REQUIRED", "$/embedded_task_bindings", repr(helper_rows)) @@ -1907,7 +2173,7 @@ def validate_embedded_task_admission( if admission.get("executor_binding_sha256") != binding_sha256: raise ContractError("ADMISSION_EXECUTOR_HASH_MISMATCH", "$/executor_binding_sha256", repr(admission.get("executor_binding_sha256"))) - if admission.get("present_deterministic_stage_ids") != ["S2_00", "S2_20"]: + if admission.get("present_deterministic_stage_ids") != ["S2_00", "S2_20", "S2_40"]: raise ContractError("ADMISSION_STAGE_SET_MISMATCH", "$/present_deterministic_stage_ids", repr(admission.get("present_deterministic_stage_ids"))) embedded = admission.get("embedded_task_admissions") if not isinstance(embedded, list) or len(embedded) != 1 or not isinstance(embedded[0], dict): diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/registry/regression/finding_fixture_map.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/registry/regression/finding_fixture_map.yml index 81eaa9c6..5e822f7c 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/registry/regression/finding_fixture_map.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/registry/regression/finding_fixture_map.yml @@ -5,28 +5,77 @@ "execution_eligible": false, "runtime_legal_source": false, "required_fixture_case_ids": [ - "S20-F01-SINGLE-OPTION-GROUP", - "S20-F02-MIXED-PORTFOLIO", - "S20-F03-CLIENT-NO-SUE", - "S20-F04-CASE-RULE-EXACTNESS", - "S20-F05-ROW-KIND-BRANCH", - "S20-F06-PARTY-TITLE", - "S20-F07-CE01-INTEREST", - "S20-F08-CE03-LIMITATION", - "S20-F09-CE08-RESERVED-SHARE", - "S20-F10-ACTIO-ROUTE-CAP", - "S20-F11-CE13-COURT-VALUE", - "S20-F12-RETRIEVAL-BOUNDARY", - "S20-F13-CORPUS-INTEGRITY", - "S20-F14-EXHIBIT-LABEL", - "S20-F15-OPTION-SILENT-LOSS", - "S20-F16-PUBLISH-BARRIER", - "S20-F17-LEGACY-PATH" + "S20-F01-SINGLE-OPTION-GROUP", "S20-F02-MIXED-PORTFOLIO", "S20-F03-CLIENT-NO-SUE", + "S20-F04-CASE-RULE-EXACTNESS", "S20-F05-ROW-KIND-BRANCH", "S20-F06-PARTY-TITLE", + "S20-F07-CE01-INTEREST", "S20-F08-CE03-LIMITATION", "S20-F09-CE08-RESERVED-SHARE", + "S20-F10-ACTIO-ROUTE-CAP", "S20-F11-CE13-COURT-VALUE", "S20-F12-RETRIEVAL-BOUNDARY", + "S20-F13-CORPUS-INTEGRITY", "S20-F14-EXHIBIT-LABEL", "S20-F15-OPTION-SILENT-LOSS", + "S20-F16-PUBLISH-BARRIER", "S20-F17-LEGACY-PATH" ], - "mapping_rows": [], - "mapped_fixture_case_count": 0, + "mapping_rows": [ + {"source_finding_id":"DR1-STAGE1_TO_STAGE2_FACT_LOSS","source_locator":"discrepancy_report_1.md","invariant_id":"V01","fixture_case_id":"S40-F006","mutation_id":"V01-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"IR1-CRITICAL_FACT_CONSERVATION","source_locator":"improvement_report_1.md","invariant_id":"V02","fixture_case_id":"S40-F006","mutation_id":"V02-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"IR2-DOMAIN_CONFIG_COMPLETENESS","source_locator":"improvement_report_2.md","invariant_id":"V03","fixture_case_id":"S40-F006","mutation_id":"V03-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"IR3-DEFENSE_CHAIN_LOSS","source_locator":"improvement_report_3.md","invariant_id":"V04","fixture_case_id":"S40-F006","mutation_id":"V04-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"IM-CLAIM_GROUP_RELATION","source_locator":"improvement_merged.md","invariant_id":"V05","fixture_case_id":"S40-F006","mutation_id":"V05-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"EVAL-M15-CASE-TYPE-PREDICATE","source_locator":"eval_stage_2_optimal_update_strategy_v.3.md","invariant_id":"V06","fixture_case_id":"S40-F006","mutation_id":"V06-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"DR3-ACTIO-CALCULATION-LOSS","source_locator":"discrepancy_report_3.md","invariant_id":"V07","fixture_case_id":"S40-F007","mutation_id":"V07-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"IM-SAME-RECOVERY-DUPLICATE","source_locator":"improvement_merged.md","invariant_id":"V08","fixture_case_id":"S40-F006","mutation_id":"V08-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"DR4-RELIEF-OBJECT-DATE-MISMATCH","source_locator":"discrepancy_report_4.md","invariant_id":"V09","fixture_case_id":"S40-F005","mutation_id":"V09-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"IM-RELIEF-FORM-NUMBERING","source_locator":"improvement_merged.md","invariant_id":"V10","fixture_case_id":"S40-F004","mutation_id":"V10-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"DR1-RELIEF-CAUSE-CROSSMATCH","source_locator":"discrepancy_report_1.md","invariant_id":"V11","fixture_case_id":"S40-F005","mutation_id":"V11-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"EVAL-M16-CORPUS-NAMESPACE","source_locator":"eval_stage_2_optimal_update_strategy_v.3.md","invariant_id":"V12","fixture_case_id":"S40-F006","mutation_id":"V12-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"EVAL-M13-LAW-VALUE-SEAL","source_locator":"eval_stage_2_optimal_update_strategy_v.3.md","invariant_id":"V13","fixture_case_id":"S40-F007","mutation_id":"V13-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"EVAL-M18-NONCYCLIC-SEAL","source_locator":"eval_stage_2_optimal_update_strategy_v.3.md","invariant_id":"V14","fixture_case_id":"S40-F015","mutation_id":"V14-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"EVAL-C1-CAUSE-ATOM-PROVENANCE","source_locator":"eval_stage_2_optimal_update_strategy_v.3.md","invariant_id":"V15","fixture_case_id":"S40-F008","mutation_id":"V15-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"IR4-OPTION-SILENT-LOSS","source_locator":"improvement_report_4.md","invariant_id":"V16","fixture_case_id":"S40-F003","mutation_id":"V16-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"DR2-OBJECT-EXHIBIT-COMPLETENESS","source_locator":"discrepancy_report_2.md","invariant_id":"V17","fixture_case_id":"S40-F008","mutation_id":"V17-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]}, + {"source_finding_id":"IM-CLOSED-RENDERER-INDEPENDENCE","source_locator":"improvement_merged.md","invariant_id":"V18","fixture_case_id":"S40-F004","mutation_id":"V18-CONTRADICTION-OR-ABSENCE","expected_statuses":["FAIL","UNEVALUABLE"]} + ], + "mapped_fixture_case_count": 7, "required_fixture_case_count": 17, - "source_finding_families": ["discrepancy_report_1..4", "improvement_report_1..4", "improvement_merged", "eval_stage_2_optimal_update_strategy_v.3"], - "unresolved_reason_codes": ["SOURCE_FINDINGS_NOT_EXTRACTED","INVARIANT_MAPPING_NOT_REVIEWED","FIXTURE_CROSSWALK_NOT_SIGNED"], - "guards": {"runtime_routing_use_forbidden":true,"legal_proposition_source_use_forbidden":true,"unmapped_finding_silent_drop_forbidden":true,"pending_map_is_not_coverage_proof":true} + "s2_40_required_fixture_case_ids": [ + "S40-F001", "S40-F002", "S40-F003", "S40-F004", "S40-F005", + "S40-F006", "S40-F007", "S40-F008", "S40-F009", "S40-F010", + "S40-F011", "S40-F012", "S40-F013", "S40-F014", "S40-F015" + ], + "s2_40_required_fixture_case_count": 15, + "s2_40_v_code_mapping_count": 18, + "s2_40_binding_status": "OFFLINE_BYTES_BOUND_LEGAL_AND_LIVE_PENDING", + "s2_40_fixture_family_coverage_rows": [ + {"family_id":"S40-FAMILY-01","fixture_case_ids":["S40-F002"],"coverage":"STATUS_ONLY_EXACT_FIVE"}, + {"family_id":"S40-FAMILY-02","fixture_case_ids":["S40-F001"],"coverage":"SINGLE_GROUP_LOGICAL_COMMIT"}, + {"family_id":"S40-FAMILY-03","fixture_case_ids":["S40-F004","S40-F007"],"coverage":"MULTI_GROUP_RELATION_AND_NUMBERING"}, + {"family_id":"S40-FAMILY-04","fixture_case_ids":["S40-F009","S40-F010"],"coverage":"GAP_PRESERVATION_AND_WAIT"}, + {"family_id":"S40-FAMILY-05","fixture_case_ids":["S40-F006"],"coverage":"V01_V18_PASS_FAIL_UNEVALUABLE"}, + {"family_id":"S40-FAMILY-06","fixture_case_ids":["S40-F004"],"coverage":"CASE_RULE_RENDERER_ZERO_MULTI_STALE_FREE_TEXT"}, + {"family_id":"S40-FAMILY-07","fixture_case_ids":["S40-F007","S40-F008"],"coverage":"COST_PROVISIONAL_ANNEX_EXHIBIT_OBJECT_PARTY"}, + {"family_id":"S40-FAMILY-08","fixture_case_ids":["S40-F005"],"coverage":"RELIEF_CAUSE_CROSSMATCH"}, + {"family_id":"S40-FAMILY-09","fixture_case_ids":["S40-F006","S40-F007"],"coverage":"CORPUS_AUTHORITY_LAW_VALUE_CALC_PROVENANCE"}, + {"family_id":"S40-FAMILY-10","fixture_case_ids":["S40-F003","S40-F005"],"coverage":"OPTION_RECOVERY_ISSUE_CONSERVATION"}, + {"family_id":"S40-FAMILY-11","fixture_case_ids":["S40-F015"],"coverage":"CANDIDATE_DIGEST_NONCYCLE_TAMPER"}, + {"family_id":"S40-FAMILY-12","fixture_case_ids":["S40-F010","S40-F011"],"coverage":"RECEIPT_WAIT_RESUME_COMMIT"}, + {"family_id":"S40-FAMILY-13","fixture_case_ids":["S40-F010"],"coverage":"RECEIPT_TRUST_SCOPE_TIME_REVOCATION"}, + {"family_id":"S40-FAMILY-14","fixture_case_ids":["S40-F012"],"coverage":"CONTENT_CHANGE_EARLIEST_OWNER"}, + {"family_id":"S40-FAMILY-15","fixture_case_ids":["S40-F013"],"coverage":"PARTIAL_WRITE_AND_BARRIER_LAST"}, + {"family_id":"S40-FAMILY-16","fixture_case_ids":["S40-F014"],"coverage":"IDEMPOTENCE_CONFLICT_CONCURRENCY"}, + {"family_id":"S40-FAMILY-17","fixture_case_ids":["S40-F004"],"coverage":"LEGACY_EXTERNAL_PY_SCAN_SECRET_REJECTION"}, + {"family_id":"S40-FAMILY-18","fixture_case_ids":["S40-F007"],"coverage":"ACTIO_STRUCTURAL_DEPENDENCIES_LEGAL_PENDING"}, + {"family_id":"S40-FAMILY-19","fixture_case_ids":["S40-F007"],"coverage":"SPECIAL_CASE_TEMPORAL_STRUCTURES_LEGAL_PENDING"}, + {"family_id":"S40-FAMILY-20","fixture_case_ids":["S40-F004"],"coverage":"CASE_TYPE_137_STRUCTURAL_COVERAGE_LEGAL_PENDING"} + ], + "source_finding_families": [ + "discrepancy_report_1..4", "improvement_report_1..4", "improvement_merged", + "eval_stage_2_optimal_update_strategy_v.3" + ], + "unresolved_reason_codes": [ + "SOURCE_FINDING_LOCATORS_NOT_SIGNED", + "KOREAN_LAWYER_FIXTURE_CROSSWALK_NOT_SIGNED" + ], + "guards": { + "runtime_routing_use_forbidden": true, + "legal_proposition_source_use_forbidden": true, + "unmapped_finding_silent_drop_forbidden": true, + "pending_map_is_not_coverage_proof": true + } } diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/registry/review/review_policy_registry.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/registry/review/review_policy_registry.yml index a1476a6c..a7aabef7 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/registry/review/review_policy_registry.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/registry/review/review_policy_registry.yml @@ -19,16 +19,57 @@ ], "exactly_one_policy_result_required": true }, + "final_review_contract": { + "policy_result_enum": [ + "STANDARD_ATTORNEY_REVIEW", + "MANDATORY_SPECIALIST_REVIEW" + ], + "base_required_receipt_types": [ + "STANDARD_ATTORNEY_REVIEW" + ], + "allowed_review_tags": [ + "AUTHORITY_TEMPORAL_REVIEW", + "CALCULATION_SPECIALIST_REVIEW", + "CORPUS_GAP_REVIEW", + "PARTY_TITLE_REVIEW", + "RENDERER_BRANCH_REVIEW", + "SPECIAL_LAW_REVIEW" + ], + "runtime_trigger_sources": [ + "V01_V18_RESULT", + "RENDERER_BINDING", + "AUTHORITY_RELEASE", + "CORPUS_RELEASE", + "CALCULATION_RECEIPT" + ], + "receipt_disposition_enum": [ + "APPROVE_AS_IS", + "CONTENT_CHANGE_REQUIRED" + ], + "external_cryptographic_verification_required": true, + "candidate_digest_and_review_subject_digest_required": true, + "in_place_candidate_edit_forbidden": true, + "missing_or_unapproved_policy_result": "STANDARD_ATTORNEY_REVIEW", + "missing_or_invalid_receipt_route": "WAIT_EXTERNAL_REVIEW" + }, "policy_rows": [], "default_unapproved_result": { "drafting_permission": "WORKNOTE_ONLY", "issue_code": "REVIEW_POLICY_NOT_APPROVED", - "ready_eligible": false + "ready_eligible": false, + "required_receipt_types": [ + "STANDARD_ATTORNEY_REVIEW" + ], + "legal_readiness_ceiling": "LAWYER_REVIEW_REQUIRED" }, "closure": { "ready_requires_all_required_receipts": true, "ready_requires_no_unresolved_blocking_issue": true, - "missing_policy_cannot_upgrade_permission": true + "missing_policy_cannot_upgrade_permission": true, + "ready_requires_production_compile_mode": true, + "ready_requires_v01_v18_all_pass": true, + "ready_requires_execution_eligible_legal_assets": true, + "candidate_receipt_cannot_cure_release_level_legal_gap": true }, "review": { "required_role": "KOREAN_LAWYER", diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/release_ops/release_validator.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/release_ops/release_validator.py index c21272d9..b5ca7a39 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/release_ops/release_validator.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/release_ops/release_validator.py @@ -13,8 +13,14 @@ import copy import hashlib import json from pathlib import Path, PurePosixPath +import re from typing import Any +try: + import yaml +except ImportError: # pragma: no cover - incomplete offline validation host + yaml = None # type: ignore[assignment] + MODULE_MANIFEST_SCHEMA = "stage2_module_manifest.v1" PARENT_RELEASE_SCHEMA = "stage2_release.v2" @@ -73,9 +79,118 @@ FORBIDDEN_PARENT_MEMBERS = frozenset( "manifest/s2_30_model_benchmark_receipt.json", "manifest/s2_30_legal_review_receipt.json", "manifest/s2_30_release.json", + "agent_scripts/Stage_2_S2_40.yml", + "runtime/s2_40_commit.py", + "runtime/s2_40_commit.txt", + "manifest/s2_40_inline_code_receipt.json", } ) +STAGE_GENERIC_METADATA = { + "S2_20": { + "asset_version": "s2_20.1", + "module_id_prefix": "S2_20-ASSET-", + "owner": "Stage_2_S2_20_owner", + "schema_version": "stage2_s2_20_generic_asset.v1", + "scope_predicate": "workflow_id == S2_20", + }, + "S2_30": { + "asset_version": "s2_30.1", + "module_id_prefix": "S2_30-ASSET-", + "owner": "Stage_2_S2_30_owner", + "schema_version": "stage2_s2_30_generic_asset.v1", + "scope_predicate": "workflow_id == S2_30", + }, + "S2_40": { + "asset_version": "s2_40.1", + "module_id_prefix": "S2_40-ASSET-", + "owner": "Stage_2_S2_40_owner", + "schema_version": "stage2_s2_40_generic_asset.v1", + "scope_predicate": "workflow_id == S2_40", + }, +} + +S2_40_WORKFLOW_PATH = "workflows/S2_40_final_review_render_and_commit.yml" +S2_40_TRANSITIONED_STUB_VALUES = frozenset( + { + "WF-S2_40-STATUS-ONLY", + "s2_40.status_only.1", + "DRAFT_HANDOFF_STUB_HASH_BOUND", + "entrypoint_id == S2_40_STATUS_ONLY", + } +) +S2_40_WORKFLOW_REQUIRED_METADATA: dict[str, Any] = { + "asset_version": "s2_40.finalizer.1", + "consumed_schema_ids": [ + "https://schemas.liti-agent.local/stage2/s2_00/context.schema.v2.json", + "https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_10/s2_10.schema.v2.json", + "https://schemas.liti-agent.local/stage2/s2_20/binding_retrieval.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_20/calculation.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_20/relief_plan.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_30/draft_atoms.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_40/package.schema.v1.json", + "https://schemas.liti-agent.local/stage2/shared/deployment.schema.v3.json", + "https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json", + ], + "entry_routes": ["TO_S2_40", "TO_S2_40_STATUS_ONLY"], + "implementation_status": "IMPLEMENTED_OFFLINE_CONTRACT_LIVE_ADMISSION_PENDING", + "inputs": [ + "ingress/ingress_status.json", + "ingress/technical_diagnostic.json", + "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", + "review/issue_ledger.base.json", + "map_s2_10/s2_10_publish_status.json", + "plan/plan_publish_status.json", + "plan/canonical_relief_plan.json", + "plan/claim_groups.json", + "plan/case_type_bindings.json", + "map_s2_30/s2_30_publish_status.json", + "map_s2_30/artifact_manifest.json", + "map_s2_30/{draft_parts,issue_patches,worknote_parts,usage_parts}/.json", + "review/review_receipts/.json", + "review/lawyer_judgment_record.json", + ], + "legal_admission_status": "PENDING", + "live_admission_status": "PENDING", + "module_id": "WF-S2_40", + "module_kind": "WORKFLOW", + "outputs": [ + "review/issue_ledger.final.json", + "review/assumption_ledger.json", + "review/llm_usage.jsonl", + "candidates/by-content-digest//", + "review/review_requests/.json", + "final/claim_relief.md", + "final/claim_cause.md", + "final/pleading_draft.md", + "final/stage2_package.json", + "commit/commit_intent.json", + "commit/stage2_commit_result.json", + "control/run_status.json", + ], + "owner": "Stage_2_S2_40_owner", + "path": S2_40_WORKFLOW_PATH, + "produced_schema_ids": [ + "stage2_s2_40_candidate_manifest.v1", + "stage2_s2_40_commit_intent.v1", + "stage2_s2_40_commit_result.v1", + "stage2_s2_40_package.v1", + "stage2_s2_40_run_status.v1", + ], + "schema_version": "stage2_workflow_contract.v1", + "scope_predicate": "workflow_id == S2_40 and entry_route in {TO_S2_40,TO_S2_40_STATUS_ONLY}", + "semantic_review_status": "PENDING_LEGAL_AND_LIVE_ADMISSION", + "status_only_exact_inputs": [ + "ingress/ingress_status.json", + "ingress/technical_diagnostic.json", + "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", + "review/issue_ledger.base.json", + ], +} + class ValidationInputError(ValueError): """Raised when a validation input cannot be parsed deterministically.""" @@ -103,6 +218,38 @@ def _load_json(path: Path) -> Any: raise ValidationInputError(f"JSON_READ_FAILED:{path.as_posix()}:{exc}") from exc +if yaml is not None: + + class _UniqueKeySafeLoader(yaml.SafeLoader): + def construct_mapping(self, node: Any, deep: bool = False) -> dict[Any, Any]: + self.flatten_mapping(node) + result: dict[Any, Any] = {} + for key_node, value_node in node.value: + key = self.construct_object(key_node, deep=deep) + if key in result: + raise ValidationInputError(f"DUPLICATE_YAML_KEY:{key!r}") + result[key] = self.construct_object(value_node, deep=deep) + return result + +else: # pragma: no cover + + class _UniqueKeySafeLoader: # type: ignore[no-redef] + pass + + +def _load_yaml(path: Path) -> Any: + if yaml is None: + raise ValidationInputError("PYYAML_REQUIRED") + try: + raw = path.read_bytes() + text = raw.decode("utf-8") + if text.startswith("\ufeff"): + raise ValidationInputError(f"YAML_UTF8_BOM_FORBIDDEN:{path.as_posix()}") + return yaml.load(text, Loader=_UniqueKeySafeLoader) + except (OSError, UnicodeDecodeError, yaml.YAMLError) as exc: + raise ValidationInputError(f"YAML_READ_FAILED:{path.as_posix()}:{exc}") from exc + + def _canonical_bytes(document: Any) -> bytes: return ( json.dumps( @@ -169,6 +316,89 @@ def _physical(root: Path, relative: str) -> Path | None: return resolved +def _resolve_root(root: Path) -> Path: + """Resolve a CLI/library root before deriving authoring-relative paths.""" + + try: + resolved = root.resolve(strict=True) + except (FileNotFoundError, OSError) as exc: + raise ValidationInputError(f"ROOT_UNAVAILABLE:{root.as_posix()}") from exc + if not resolved.is_dir(): + raise ValidationInputError(f"ROOT_DIRECTORY_REQUIRED:{resolved.as_posix()}") + return resolved + + +def _validate_s2_40_workflow_module_row( + rows: Any, +) -> list[dict[str, str]]: + if not isinstance(rows, list): + return [_finding("S2_40_WORKFLOW_MODULE_ROW_REQUIRED", "$/modules", "modules array required")] + matches = [ + row + for row in rows + if isinstance(row, dict) and row.get("path") == S2_40_WORKFLOW_PATH + ] + s2_40_family_active = bool(matches) or any( + isinstance(row, dict) + and ( + row.get("owner") == "Stage_2_S2_40_owner" + or row.get("schema_version") == "stage2_s2_40_generic_asset.v1" + or ( + isinstance(row.get("module_id"), str) + and row["module_id"].startswith("S2_40-ASSET-") + ) + ) + for row in rows + ) + if not s2_40_family_active: + # Pre-S2_40 synthetic/unit manifests remain valid inputs. Once any + # S2_40 family member is present, however, the full workflow row is a + # mandatory semantic anchor and a status-only substitute is forbidden. + return [] + if len(matches) != 1: + return [ + _finding( + "S2_40_WORKFLOW_MODULE_ROW_EXACT_ONE_REQUIRED", + "$/modules", + f"observed={len(matches)}", + ) + ] + row = matches[0] + observed_stub = sorted( + str(value) + for value in { + row.get("module_id"), + row.get("asset_version"), + row.get("implementation_status"), + row.get("scope_predicate"), + } + & S2_40_TRANSITIONED_STUB_VALUES + ) + findings: list[dict[str, str]] = [] + if observed_stub: + findings.append( + _finding( + "S2_40_TRANSITIONED_STUB_METADATA_FORBIDDEN", + f"module:{S2_40_WORKFLOW_PATH}", + repr(observed_stub), + ) + ) + drift = { + key: {"expected": expected, "observed": row.get(key)} + for key, expected in S2_40_WORKFLOW_REQUIRED_METADATA.items() + if row.get(key) != expected + } + if drift: + findings.append( + _finding( + "S2_40_WORKFLOW_MODULE_METADATA_MISMATCH", + f"module:{S2_40_WORKFLOW_PATH}", + json.dumps(drift, ensure_ascii=False, sort_keys=True), + ) + ) + return findings + + def _validate_module_manifest( root: Path, manifest: dict[str, Any], @@ -187,6 +417,7 @@ def _validate_module_manifest( rows = manifest.get("modules") if not isinstance(rows, list): return errors + [_finding("MODULES_REQUIRED", "$/modules", "canonical modules array missing")], pending, {"module_count": 0, "mirror_count": 0} + errors.extend(_validate_s2_40_workflow_module_row(rows)) seen_ids: set[str] = set() seen_paths: set[str] = set() row_by_path: dict[str, dict[str, Any]] = {} @@ -518,6 +749,234 @@ def _validate_137_coverage( } +def _walk_strings(value: Any) -> list[str]: + if isinstance(value, str): + return [value] + if isinstance(value, list): + return [item for child in value for item in _walk_strings(child)] + if isinstance(value, dict): + return [item for child in value.values() for item in _walk_strings(child)] + return [] + + +def _validate_s2_40_detached( + root: Path, + parent_release_raw: bytes, +) -> tuple[list[dict[str, str]], list[dict[str, str]], dict[str, int]]: + """Independently validate the detached S2_40 Agent/code/admission lane. + + This check is activated only after the non-empty S2_40 parent allowlist is + installed. It never upgrades pending backend or legal evidence to an + admitted state. + """ + + errors: list[dict[str, str]] = [] + pending: list[dict[str, str]] = [] + counts = {"s2_40_stage_binding_count": 0, "s2_40_run_code_task_count": 0} + required = { + "authoring": root.parent.parent / "Stage_2_S2_40.yml", + "projection": root / "agent_scripts/Stage_2_S2_40.yml", + "mirror_py": root / "runtime/s2_40_commit.py", + "mirror_txt": root / "runtime/s2_40_commit.txt", + "receipt": root / "manifest/s2_40_inline_code_receipt.json", + "binding": root / "deployment/stage2_code_executor_binding.yml", + "admission": root / "manifest/stage2_deterministic_admission_receipt.json", + "package_schema": root / "schemas/package.schema.json", + "review_schema": root / "schemas/review_status.schema.json", + "deployment_schema": root / "schemas/deployment.schema.json", + } + missing = [name for name, path in required.items() if not path.is_file() or path.is_symlink()] + if missing: + errors.append( + _finding( + "S2_40_DETACHED_ASSET_MISSING", + "s2_40_detached:$", + repr(sorted(missing)), + ) + ) + return errors, pending, counts + + authoring_raw = required["authoring"].read_bytes() + projection_raw = required["projection"].read_bytes() + mirror_py_raw = required["mirror_py"].read_bytes() + mirror_txt_raw = required["mirror_txt"].read_bytes() + if authoring_raw != projection_raw: + errors.append( + _finding( + "S2_40_AUTHORING_PROJECTION_BYTES_DIFFER", + "s2_40_detached:/projection", + f"authoring={_sha256(authoring_raw)};projection={_sha256(projection_raw)}", + ) + ) + if mirror_py_raw != mirror_txt_raw: + errors.append( + _finding( + "S2_40_CODE_MIRROR_BYTES_DIFFER", + "s2_40_detached:/mirror", + f"py={_sha256(mirror_py_raw)};txt={_sha256(mirror_txt_raw)}", + ) + ) + + try: + agent_doc = _load_yaml(required["authoring"]) + except ValidationInputError as exc: + errors.append(_finding("S2_40_AUTHORING_YAML_INVALID", "s2_40_detached:/authoring", str(exc))) + agent_doc = None + code_raw = b"" + if not isinstance(agent_doc, dict): + errors.append(_finding("S2_40_AGENT_ROOT_INVALID", "s2_40_detached:/authoring", "object required")) + else: + agent = agent_doc.get("Agent") + if not isinstance(agent, dict): + errors.append(_finding("S2_40_AGENT_OBJECT_REQUIRED", "s2_40_detached:/Agent", repr(agent))) + else: + if agent.get("name") != "Stage_2_S2_40" or agent.get("version") != "1.0.0": + errors.append(_finding("S2_40_AGENT_IDENTITY_MISMATCH", "s2_40_detached:/Agent", repr({"name": agent.get("name"), "version": agent.get("version")}))) + forbidden_model_fields = [ + string + for string in _walk_strings(agent) + if string in {"gpt-5.6-sol", "xhigh"} + ] + if forbidden_model_fields or any( + key in agent + for key in ("llm_provider", "llm_model", "llm_reasoning", "llm_verbosity") + ): + errors.append(_finding("S2_40_LLM_FIELD_FORBIDDEN", "s2_40_detached:/Agent", repr(forbidden_model_fields))) + stages = agent.get("Stages") + if not isinstance(stages, list) or len(stages) != 1 or not isinstance(stages[0], dict): + errors.append(_finding("S2_40_EXACT_ONE_STAGE_REQUIRED", "s2_40_detached:/Agent/Stages", repr(stages))) + else: + stage = stages[0] + tasks = stage.get("tasks") + run_code = [ + row + for row in tasks + if isinstance(row, dict) + and row.get("mcp") == "code-executor" + and row.get("tool_name") == "run_code" + ] if isinstance(tasks, list) else [] + counts["s2_40_run_code_task_count"] = len(run_code) + if stage.get("name") != "S2_40" or not isinstance(tasks, list) or len(tasks) != 1 or len(run_code) != 1: + errors.append(_finding("S2_40_EXACT_ONE_RUN_CODE_TASK_REQUIRED", "s2_40_detached:/Agent/Stages/0", f"stage={stage.get('name')!r};tasks={len(tasks) if isinstance(tasks, list) else 'invalid'};run_code={len(run_code)}")) + else: + task = run_code[0] + parameters = task.get("parameters") + expected = { + "language": "python", + "requirements": "httpx==0.28.1", + "network": "agent-network", + "timeout": 300, + } + if task.get("task_name") != "Task_S2_40_deterministic_finalizer" or not isinstance(parameters, dict) or any(parameters.get(key) != value for key, value in expected.items()): + errors.append(_finding("S2_40_RUN_CODE_SEMANTICS_MISMATCH", "s2_40_detached:/Agent/Stages/0/tasks/0", repr(task))) + elif isinstance(parameters.get("code"), str): + code_raw = parameters["code"].encode("utf-8") + procedure = stage.get("task_procedure") + expected_procedure = { + "IN": {"nexts": ["Task_S2_40_deterministic_finalizer"], "wait_until": []}, + "Task_S2_40_deterministic_finalizer": {"nexts": ["OUT"], "wait_until": ["IN"]}, + "OUT": {"nexts": [], "wait_until": ["Task_S2_40_deterministic_finalizer"]}, + } + if procedure != expected_procedure: + errors.append(_finding("S2_40_TASK_PROCEDURE_MISMATCH", "s2_40_detached:/Agent/Stages/0/task_procedure", repr(procedure))) + legacy_refs = sorted( + value + for value in _walk_strings(agent_doc) + if re.search(r"(?:^|[/\\])v\.[0-3](?:[/\\]|$)", value) + ) + if legacy_refs: + errors.append(_finding("S2_40_LEGACY_STAGE2_DEPENDENCY", "s2_40_detached:/authoring", repr(legacy_refs))) + + if code_raw and code_raw != mirror_py_raw: + errors.append(_finding("S2_40_INLINE_CODE_MIRROR_MISMATCH", "s2_40_detached:/canonical_code", f"code={_sha256(code_raw)};mirror={_sha256(mirror_py_raw)}")) + + receipt = _load_json(required["receipt"]) + if not isinstance(receipt, dict) or receipt.get("schema_version") != "stage2_s2_40_inline_code_receipt.v1" or receipt.get("workflow_id") != "S2_40": + errors.append(_finding("S2_40_INLINE_RECEIPT_INVALID", "s2_40_detached:/receipt", repr(receipt))) + else: + bindings = ( + ("authoring", authoring_raw), + ("deployment_projection", projection_raw), + ) + for key, raw in bindings: + row = receipt.get(key) + if not isinstance(row, dict) or row.get("sha256") != _sha256(raw) or row.get("size_bytes") != len(raw): + errors.append(_finding("S2_40_INLINE_RECEIPT_HASH_MISMATCH", f"s2_40_detached:/receipt/{key}", repr(row))) + canonical_code = receipt.get("canonical_code") + if not isinstance(canonical_code, dict) or canonical_code.get("sha256", canonical_code.get("code_sha256")) != _sha256(code_raw): + errors.append(_finding("S2_40_INLINE_RECEIPT_CODE_HASH_MISMATCH", "s2_40_detached:/receipt/canonical_code", repr(canonical_code))) + expected_parent = _sha256(parent_release_raw) + if receipt.get("expected_parent_stage2_release_sha256") != expected_parent: + errors.append(_finding("S2_40_PARENT_RELEASE_BINDING_MISMATCH", "s2_40_detached:/receipt/expected_parent_stage2_release_sha256", f"expected={expected_parent};observed={receipt.get('expected_parent_stage2_release_sha256')}")) + + binding = _load_yaml(required["binding"]) + rows = binding.get("stage_bindings") if isinstance(binding, dict) else None + matches = [row for row in rows if isinstance(row, dict) and row.get("stage_id") == "S2_40"] if isinstance(rows, list) else [] + counts["s2_40_stage_binding_count"] = len(matches) + if len(matches) != 1: + errors.append(_finding("S2_40_STAGE_BINDING_EXACT_ONE_REQUIRED", "s2_40_detached:/binding/stage_bindings", str(len(matches)))) + else: + row = matches[0] + expected = { + "workflow_id": "S2_40", + "execution_class": "NON-LLM-DETERMINISTIC", + "active_runtime_authority": False, + "mcp_server_id": "code-executor", + "tool_name": "run_code", + "language": "python", + "network": "agent-network", + "timeout_seconds": 300, + "external_mcp_contract": None, + } + drift = {key: {"expected": value, "observed": row.get(key)} for key, value in expected.items() if row.get(key) != value} + localdocs = row.get("localdocs_contract") + if not isinstance(localdocs, dict) or localdocs.get("endpoint") != "http://mcp-localdocs:8012/mcp" or localdocs.get("fixed_request_path") != "stage2_control/s2_40_request.json" or localdocs.get("tool_allowlist") != ["read_binary_doc", "write_binary_file"]: + drift["localdocs_contract"] = {"expected": "S2_40 localdocs binary-only contract", "observed": localdocs} + ref_expectations = { + "agent_script_ref": ("agent_scripts/Stage_2_S2_40.yml", projection_raw), + "inline_code_receipt_ref": ("manifest/s2_40_inline_code_receipt.json", required["receipt"].read_bytes()), + "stage2_release_ref": ("manifest/stage2_release.json", parent_release_raw), + } + for key, (path, raw) in ref_expectations.items(): + ref = row.get(key) + if not isinstance(ref, dict) or ref.get("path") != path or ref.get("sha256") != _sha256(raw): + drift[key] = {"expected": {"path": path, "sha256": _sha256(raw)}, "observed": ref} + if drift: + errors.append(_finding("S2_40_STAGE_BINDING_MISMATCH", "s2_40_detached:/binding/stage_bindings/S2_40", json.dumps(drift, ensure_ascii=False, sort_keys=True))) + if row.get("live_admission_status") not in {"PENDING_SECRET_BINDING", "PENDING_LIVE_VERIFICATION", "PENDING"}: + errors.append(_finding("S2_40_LIVE_ADMISSION_STATUS_DISHONEST", "s2_40_detached:/binding/stage_bindings/S2_40/live_admission_status", repr(row.get("live_admission_status")))) + else: + pending.append(_finding("S2_40_LIVE_CODE_EXECUTOR_ADMISSION_PENDING", "s2_40_detached:/binding/stage_bindings/S2_40", str(row.get("live_admission_status")))) + + admission = _load_json(required["admission"]) + expected_ids = ["S2_00", "S2_20", "S2_40"] + if not isinstance(admission, dict) or admission.get("present_deterministic_stage_ids") != expected_ids: + errors.append(_finding("S2_40_DETERMINISTIC_ADMISSION_SET_MISMATCH", "s2_40_detached:/admission/present_deterministic_stage_ids", repr(admission.get("present_deterministic_stage_ids") if isinstance(admission, dict) else admission))) + elif admission.get("executor_binding_sha256") != _sha256(required["binding"].read_bytes()) or admission.get("parent_release_sha256") != _sha256(parent_release_raw): + errors.append(_finding("S2_40_DETERMINISTIC_ADMISSION_HASH_MISMATCH", "s2_40_detached:/admission", repr(admission))) + elif admission.get("admission_status") != "PENDING": + errors.append(_finding("S2_40_UNSUPPORTED_ADMISSION_CLAIM", "s2_40_detached:/admission/admission_status", repr(admission.get("admission_status")))) + else: + pending.append(_finding("S2_40_DETERMINISTIC_ADMISSION_PENDING", "s2_40_detached:/admission", "external signed backend evidence pending")) + + deployment_schema = _load_json(required["deployment_schema"]) + deployment_defs = deployment_schema.get("$defs") if isinstance(deployment_schema, dict) else None + required_defs = { + "s2_40_request", + "s2_40_execution_receipt", + "s2_40_inline_code_receipt", + "s2_40_commit_intent", + "s2_40_commit_result", + } + if not isinstance(deployment_defs, dict) or not required_defs.issubset(deployment_defs): + errors.append(_finding("S2_40_DEPLOYMENT_SCHEMA_DEFS_MISSING", "s2_40_detached:/schemas/deployment/$defs", repr(sorted(required_defs - set(deployment_defs or {}))))) + for name in ("package_schema", "review_schema"): + schema = _load_json(required[name]) + if not isinstance(schema, dict) or not isinstance(schema.get("$defs"), dict) or not schema.get("$id"): + errors.append(_finding("S2_40_SCHEMA_ROOT_INVALID", f"s2_40_detached:/schemas/{name}", repr(schema))) + return errors, pending, counts + + def validate_package( root: Path, manifest_path: Path, @@ -526,6 +985,15 @@ def validate_package( rule_registry_path: Path, coverage_path: Path, ) -> dict[str, Any]: + root = _resolve_root(root) + try: + manifest_path = manifest_path.resolve(strict=True) + release_path = release_path.resolve(strict=True) + case_registry_path = case_registry_path.resolve(strict=True) + rule_registry_path = rule_registry_path.resolve(strict=True) + coverage_path = coverage_path.resolve(strict=True) + except (FileNotFoundError, OSError) as exc: + raise ValidationInputError(f"VALIDATION_INPUT_UNAVAILABLE:{exc}") from exc manifest = _load_json(manifest_path) release = _load_json(release_path) case_registry = _load_json(case_registry_path) @@ -539,6 +1007,17 @@ def validate_package( errors.extend(parent_errors) errors.extend(coverage_errors) errors.extend(_validate_parent_member_lists(root, manifest)) + s2_40_allowlist_path = root / "manifest/s2_40_parent_member_paths.json" + if s2_40_allowlist_path.is_file(): + s2_40_allowlist = _load_json(s2_40_allowlist_path) + if isinstance(s2_40_allowlist, list) and s2_40_allowlist: + detached_errors, detached_pending, detached_counts = _validate_s2_40_detached( + root, + release_path.read_bytes(), + ) + errors.extend(detached_errors) + pending.extend(detached_pending) + counts.update(detached_counts) pending.extend(parent_pending) pending.extend(coverage_pending) if ( @@ -569,28 +1048,29 @@ def validate(root: Path, manifest: dict[str, object]) -> list[str]: def _validate_parent_member_lists(root: Path, manifest: dict[str, Any]) -> list[dict[str, str]]: - """Verify the cumulative S2_20 + S2_30 allowlist without widening it.""" + """Verify disjoint cumulative S2_20/S2_30/S2_40 owner allowlists.""" paths = ( - root / "manifest" / "s2_20_parent_member_paths.json", - root / "manifest" / "s2_30_parent_member_paths.json", + ("S2_20", root / "manifest" / "s2_20_parent_member_paths.json"), + ("S2_30", root / "manifest" / "s2_30_parent_member_paths.json"), + ("S2_40", root / "manifest" / "s2_40_parent_member_paths.json"), ) - loaded: list[list[str]] = [] - for path in paths: + loaded: list[tuple[str, list[str]]] = [] + for owner_stage, path in paths: if not path.is_file(): return [_finding("PARENT_MEMBER_LIST_MISSING", path.as_posix(), "required cumulative allowlist component")] value = _load_json(path) if not isinstance(value, list) or not all(isinstance(row, str) for row in value): return [_finding("PARENT_MEMBER_LIST_INVALID", path.as_posix(), "string array required")] - loaded.append(value) - overlap = sorted(set(loaded[0]) & set(loaded[1])) + if value != sorted(value) or len(value) != len(set(value)): + return [_finding("PARENT_MEMBER_LIST_NOT_SORTED_UNIQUE", path.as_posix(), "sorted unique string array required")] + loaded.append((owner_stage, value)) findings: list[dict[str, str]] = [] - if overlap: - findings.append(_finding("PARENT_MEMBER_LISTS_NOT_DISJOINT", "manifest", repr(overlap))) rows = manifest.get("modules") - module_paths = { - row.get("path") for row in rows if isinstance(row, dict) - } if isinstance(rows, list) else set() + row_by_path = { + row.get("path"): row for row in rows if isinstance(row, dict) and isinstance(row.get("path"), str) + } if isinstance(rows, list) else {} + module_paths = set(row_by_path) mirrors = manifest.get("documentation_mirrors") if isinstance(mirrors, list): module_paths.update( @@ -598,14 +1078,42 @@ def _validate_parent_member_lists(root: Path, manifest: dict[str, Any]) -> list[ for row in mirrors if isinstance(row, dict) and isinstance(row.get("mirror_path"), str) ) - for relative in sorted(set(loaded[0]) | set(loaded[1])): - normalized = _relative_path(relative) - if normalized is None: - findings.append(_finding("PARENT_MEMBER_PATH_INVALID", "manifest", repr(relative))) - elif normalized in FORBIDDEN_PARENT_MEMBERS: - findings.append(_finding("NON_CYCLIC_PARENT_VIOLATION", "manifest", normalized)) - elif normalized not in module_paths: - findings.append(_finding("PARENT_MEMBER_NOT_IN_MODULE_MANIFEST", "manifest", normalized)) + seen: dict[str, str] = {} + for owner_stage, values in loaded: + metadata = STAGE_GENERIC_METADATA[owner_stage] + for relative in values: + if relative in seen: + findings.append(_finding("PARENT_MEMBER_LISTS_NOT_DISJOINT", "manifest", f"path={relative};owners={seen[relative]},{owner_stage}")) + else: + seen[relative] = owner_stage + normalized = _relative_path(relative) + if normalized is None: + findings.append(_finding("PARENT_MEMBER_PATH_INVALID", "manifest", repr(relative))) + elif normalized in FORBIDDEN_PARENT_MEMBERS: + findings.append(_finding("NON_CYCLIC_PARENT_VIOLATION", "manifest", normalized)) + elif normalized not in module_paths: + findings.append(_finding("PARENT_MEMBER_NOT_IN_MODULE_MANIFEST", "manifest", normalized)) + elif not normalized.endswith(".txt"): + row = row_by_path.get(normalized) + if isinstance(row, dict) and row.get("schema_version") in { + item["schema_version"] for item in STAGE_GENERIC_METADATA.values() + }: + expected = { + "asset_version": metadata["asset_version"], + "owner": metadata["owner"], + "schema_version": metadata["schema_version"], + "scope_predicate": metadata["scope_predicate"], + } + drift = { + key: {"expected": value, "observed": row.get(key)} + for key, value in expected.items() + if row.get(key) != value + } + module_id = row.get("module_id") + if not isinstance(module_id, str) or not module_id.startswith(metadata["module_id_prefix"]): + drift["module_id"] = {"expected_prefix": metadata["module_id_prefix"], "observed": module_id} + if drift: + findings.append(_finding("PARENT_MEMBER_OWNER_METADATA_MISMATCH", f"manifest:{normalized}", json.dumps(drift, ensure_ascii=False, sort_keys=True))) return findings diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/release_ops/release_validator.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/release_ops/release_validator.txt index c21272d9..b5ca7a39 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/release_ops/release_validator.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/release_ops/release_validator.txt @@ -13,8 +13,14 @@ import copy import hashlib import json from pathlib import Path, PurePosixPath +import re from typing import Any +try: + import yaml +except ImportError: # pragma: no cover - incomplete offline validation host + yaml = None # type: ignore[assignment] + MODULE_MANIFEST_SCHEMA = "stage2_module_manifest.v1" PARENT_RELEASE_SCHEMA = "stage2_release.v2" @@ -73,9 +79,118 @@ FORBIDDEN_PARENT_MEMBERS = frozenset( "manifest/s2_30_model_benchmark_receipt.json", "manifest/s2_30_legal_review_receipt.json", "manifest/s2_30_release.json", + "agent_scripts/Stage_2_S2_40.yml", + "runtime/s2_40_commit.py", + "runtime/s2_40_commit.txt", + "manifest/s2_40_inline_code_receipt.json", } ) +STAGE_GENERIC_METADATA = { + "S2_20": { + "asset_version": "s2_20.1", + "module_id_prefix": "S2_20-ASSET-", + "owner": "Stage_2_S2_20_owner", + "schema_version": "stage2_s2_20_generic_asset.v1", + "scope_predicate": "workflow_id == S2_20", + }, + "S2_30": { + "asset_version": "s2_30.1", + "module_id_prefix": "S2_30-ASSET-", + "owner": "Stage_2_S2_30_owner", + "schema_version": "stage2_s2_30_generic_asset.v1", + "scope_predicate": "workflow_id == S2_30", + }, + "S2_40": { + "asset_version": "s2_40.1", + "module_id_prefix": "S2_40-ASSET-", + "owner": "Stage_2_S2_40_owner", + "schema_version": "stage2_s2_40_generic_asset.v1", + "scope_predicate": "workflow_id == S2_40", + }, +} + +S2_40_WORKFLOW_PATH = "workflows/S2_40_final_review_render_and_commit.yml" +S2_40_TRANSITIONED_STUB_VALUES = frozenset( + { + "WF-S2_40-STATUS-ONLY", + "s2_40.status_only.1", + "DRAFT_HANDOFF_STUB_HASH_BOUND", + "entrypoint_id == S2_40_STATUS_ONLY", + } +) +S2_40_WORKFLOW_REQUIRED_METADATA: dict[str, Any] = { + "asset_version": "s2_40.finalizer.1", + "consumed_schema_ids": [ + "https://schemas.liti-agent.local/stage2/s2_00/context.schema.v2.json", + "https://schemas.liti-agent.local/stage2/s2_00/ingress.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_10/s2_10.schema.v2.json", + "https://schemas.liti-agent.local/stage2/s2_20/binding_retrieval.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_20/calculation.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_20/relief_plan.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_30/draft_atoms.schema.v1.json", + "https://schemas.liti-agent.local/stage2/s2_40/package.schema.v1.json", + "https://schemas.liti-agent.local/stage2/shared/deployment.schema.v3.json", + "https://schemas.liti-agent.local/stage2/shared/review_status.schema.v1.json", + ], + "entry_routes": ["TO_S2_40", "TO_S2_40_STATUS_ONLY"], + "implementation_status": "IMPLEMENTED_OFFLINE_CONTRACT_LIVE_ADMISSION_PENDING", + "inputs": [ + "ingress/ingress_status.json", + "ingress/technical_diagnostic.json", + "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", + "review/issue_ledger.base.json", + "map_s2_10/s2_10_publish_status.json", + "plan/plan_publish_status.json", + "plan/canonical_relief_plan.json", + "plan/claim_groups.json", + "plan/case_type_bindings.json", + "map_s2_30/s2_30_publish_status.json", + "map_s2_30/artifact_manifest.json", + "map_s2_30/{draft_parts,issue_patches,worknote_parts,usage_parts}/.json", + "review/review_receipts/.json", + "review/lawyer_judgment_record.json", + ], + "legal_admission_status": "PENDING", + "live_admission_status": "PENDING", + "module_id": "WF-S2_40", + "module_kind": "WORKFLOW", + "outputs": [ + "review/issue_ledger.final.json", + "review/assumption_ledger.json", + "review/llm_usage.jsonl", + "candidates/by-content-digest//", + "review/review_requests/.json", + "final/claim_relief.md", + "final/claim_cause.md", + "final/pleading_draft.md", + "final/stage2_package.json", + "commit/commit_intent.json", + "commit/stage2_commit_result.json", + "control/run_status.json", + ], + "owner": "Stage_2_S2_40_owner", + "path": S2_40_WORKFLOW_PATH, + "produced_schema_ids": [ + "stage2_s2_40_candidate_manifest.v1", + "stage2_s2_40_commit_intent.v1", + "stage2_s2_40_commit_result.v1", + "stage2_s2_40_package.v1", + "stage2_s2_40_run_status.v1", + ], + "schema_version": "stage2_workflow_contract.v1", + "scope_predicate": "workflow_id == S2_40 and entry_route in {TO_S2_40,TO_S2_40_STATUS_ONLY}", + "semantic_review_status": "PENDING_LEGAL_AND_LIVE_ADMISSION", + "status_only_exact_inputs": [ + "ingress/ingress_status.json", + "ingress/technical_diagnostic.json", + "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", + "review/issue_ledger.base.json", + ], +} + class ValidationInputError(ValueError): """Raised when a validation input cannot be parsed deterministically.""" @@ -103,6 +218,38 @@ def _load_json(path: Path) -> Any: raise ValidationInputError(f"JSON_READ_FAILED:{path.as_posix()}:{exc}") from exc +if yaml is not None: + + class _UniqueKeySafeLoader(yaml.SafeLoader): + def construct_mapping(self, node: Any, deep: bool = False) -> dict[Any, Any]: + self.flatten_mapping(node) + result: dict[Any, Any] = {} + for key_node, value_node in node.value: + key = self.construct_object(key_node, deep=deep) + if key in result: + raise ValidationInputError(f"DUPLICATE_YAML_KEY:{key!r}") + result[key] = self.construct_object(value_node, deep=deep) + return result + +else: # pragma: no cover + + class _UniqueKeySafeLoader: # type: ignore[no-redef] + pass + + +def _load_yaml(path: Path) -> Any: + if yaml is None: + raise ValidationInputError("PYYAML_REQUIRED") + try: + raw = path.read_bytes() + text = raw.decode("utf-8") + if text.startswith("\ufeff"): + raise ValidationInputError(f"YAML_UTF8_BOM_FORBIDDEN:{path.as_posix()}") + return yaml.load(text, Loader=_UniqueKeySafeLoader) + except (OSError, UnicodeDecodeError, yaml.YAMLError) as exc: + raise ValidationInputError(f"YAML_READ_FAILED:{path.as_posix()}:{exc}") from exc + + def _canonical_bytes(document: Any) -> bytes: return ( json.dumps( @@ -169,6 +316,89 @@ def _physical(root: Path, relative: str) -> Path | None: return resolved +def _resolve_root(root: Path) -> Path: + """Resolve a CLI/library root before deriving authoring-relative paths.""" + + try: + resolved = root.resolve(strict=True) + except (FileNotFoundError, OSError) as exc: + raise ValidationInputError(f"ROOT_UNAVAILABLE:{root.as_posix()}") from exc + if not resolved.is_dir(): + raise ValidationInputError(f"ROOT_DIRECTORY_REQUIRED:{resolved.as_posix()}") + return resolved + + +def _validate_s2_40_workflow_module_row( + rows: Any, +) -> list[dict[str, str]]: + if not isinstance(rows, list): + return [_finding("S2_40_WORKFLOW_MODULE_ROW_REQUIRED", "$/modules", "modules array required")] + matches = [ + row + for row in rows + if isinstance(row, dict) and row.get("path") == S2_40_WORKFLOW_PATH + ] + s2_40_family_active = bool(matches) or any( + isinstance(row, dict) + and ( + row.get("owner") == "Stage_2_S2_40_owner" + or row.get("schema_version") == "stage2_s2_40_generic_asset.v1" + or ( + isinstance(row.get("module_id"), str) + and row["module_id"].startswith("S2_40-ASSET-") + ) + ) + for row in rows + ) + if not s2_40_family_active: + # Pre-S2_40 synthetic/unit manifests remain valid inputs. Once any + # S2_40 family member is present, however, the full workflow row is a + # mandatory semantic anchor and a status-only substitute is forbidden. + return [] + if len(matches) != 1: + return [ + _finding( + "S2_40_WORKFLOW_MODULE_ROW_EXACT_ONE_REQUIRED", + "$/modules", + f"observed={len(matches)}", + ) + ] + row = matches[0] + observed_stub = sorted( + str(value) + for value in { + row.get("module_id"), + row.get("asset_version"), + row.get("implementation_status"), + row.get("scope_predicate"), + } + & S2_40_TRANSITIONED_STUB_VALUES + ) + findings: list[dict[str, str]] = [] + if observed_stub: + findings.append( + _finding( + "S2_40_TRANSITIONED_STUB_METADATA_FORBIDDEN", + f"module:{S2_40_WORKFLOW_PATH}", + repr(observed_stub), + ) + ) + drift = { + key: {"expected": expected, "observed": row.get(key)} + for key, expected in S2_40_WORKFLOW_REQUIRED_METADATA.items() + if row.get(key) != expected + } + if drift: + findings.append( + _finding( + "S2_40_WORKFLOW_MODULE_METADATA_MISMATCH", + f"module:{S2_40_WORKFLOW_PATH}", + json.dumps(drift, ensure_ascii=False, sort_keys=True), + ) + ) + return findings + + def _validate_module_manifest( root: Path, manifest: dict[str, Any], @@ -187,6 +417,7 @@ def _validate_module_manifest( rows = manifest.get("modules") if not isinstance(rows, list): return errors + [_finding("MODULES_REQUIRED", "$/modules", "canonical modules array missing")], pending, {"module_count": 0, "mirror_count": 0} + errors.extend(_validate_s2_40_workflow_module_row(rows)) seen_ids: set[str] = set() seen_paths: set[str] = set() row_by_path: dict[str, dict[str, Any]] = {} @@ -518,6 +749,234 @@ def _validate_137_coverage( } +def _walk_strings(value: Any) -> list[str]: + if isinstance(value, str): + return [value] + if isinstance(value, list): + return [item for child in value for item in _walk_strings(child)] + if isinstance(value, dict): + return [item for child in value.values() for item in _walk_strings(child)] + return [] + + +def _validate_s2_40_detached( + root: Path, + parent_release_raw: bytes, +) -> tuple[list[dict[str, str]], list[dict[str, str]], dict[str, int]]: + """Independently validate the detached S2_40 Agent/code/admission lane. + + This check is activated only after the non-empty S2_40 parent allowlist is + installed. It never upgrades pending backend or legal evidence to an + admitted state. + """ + + errors: list[dict[str, str]] = [] + pending: list[dict[str, str]] = [] + counts = {"s2_40_stage_binding_count": 0, "s2_40_run_code_task_count": 0} + required = { + "authoring": root.parent.parent / "Stage_2_S2_40.yml", + "projection": root / "agent_scripts/Stage_2_S2_40.yml", + "mirror_py": root / "runtime/s2_40_commit.py", + "mirror_txt": root / "runtime/s2_40_commit.txt", + "receipt": root / "manifest/s2_40_inline_code_receipt.json", + "binding": root / "deployment/stage2_code_executor_binding.yml", + "admission": root / "manifest/stage2_deterministic_admission_receipt.json", + "package_schema": root / "schemas/package.schema.json", + "review_schema": root / "schemas/review_status.schema.json", + "deployment_schema": root / "schemas/deployment.schema.json", + } + missing = [name for name, path in required.items() if not path.is_file() or path.is_symlink()] + if missing: + errors.append( + _finding( + "S2_40_DETACHED_ASSET_MISSING", + "s2_40_detached:$", + repr(sorted(missing)), + ) + ) + return errors, pending, counts + + authoring_raw = required["authoring"].read_bytes() + projection_raw = required["projection"].read_bytes() + mirror_py_raw = required["mirror_py"].read_bytes() + mirror_txt_raw = required["mirror_txt"].read_bytes() + if authoring_raw != projection_raw: + errors.append( + _finding( + "S2_40_AUTHORING_PROJECTION_BYTES_DIFFER", + "s2_40_detached:/projection", + f"authoring={_sha256(authoring_raw)};projection={_sha256(projection_raw)}", + ) + ) + if mirror_py_raw != mirror_txt_raw: + errors.append( + _finding( + "S2_40_CODE_MIRROR_BYTES_DIFFER", + "s2_40_detached:/mirror", + f"py={_sha256(mirror_py_raw)};txt={_sha256(mirror_txt_raw)}", + ) + ) + + try: + agent_doc = _load_yaml(required["authoring"]) + except ValidationInputError as exc: + errors.append(_finding("S2_40_AUTHORING_YAML_INVALID", "s2_40_detached:/authoring", str(exc))) + agent_doc = None + code_raw = b"" + if not isinstance(agent_doc, dict): + errors.append(_finding("S2_40_AGENT_ROOT_INVALID", "s2_40_detached:/authoring", "object required")) + else: + agent = agent_doc.get("Agent") + if not isinstance(agent, dict): + errors.append(_finding("S2_40_AGENT_OBJECT_REQUIRED", "s2_40_detached:/Agent", repr(agent))) + else: + if agent.get("name") != "Stage_2_S2_40" or agent.get("version") != "1.0.0": + errors.append(_finding("S2_40_AGENT_IDENTITY_MISMATCH", "s2_40_detached:/Agent", repr({"name": agent.get("name"), "version": agent.get("version")}))) + forbidden_model_fields = [ + string + for string in _walk_strings(agent) + if string in {"gpt-5.6-sol", "xhigh"} + ] + if forbidden_model_fields or any( + key in agent + for key in ("llm_provider", "llm_model", "llm_reasoning", "llm_verbosity") + ): + errors.append(_finding("S2_40_LLM_FIELD_FORBIDDEN", "s2_40_detached:/Agent", repr(forbidden_model_fields))) + stages = agent.get("Stages") + if not isinstance(stages, list) or len(stages) != 1 or not isinstance(stages[0], dict): + errors.append(_finding("S2_40_EXACT_ONE_STAGE_REQUIRED", "s2_40_detached:/Agent/Stages", repr(stages))) + else: + stage = stages[0] + tasks = stage.get("tasks") + run_code = [ + row + for row in tasks + if isinstance(row, dict) + and row.get("mcp") == "code-executor" + and row.get("tool_name") == "run_code" + ] if isinstance(tasks, list) else [] + counts["s2_40_run_code_task_count"] = len(run_code) + if stage.get("name") != "S2_40" or not isinstance(tasks, list) or len(tasks) != 1 or len(run_code) != 1: + errors.append(_finding("S2_40_EXACT_ONE_RUN_CODE_TASK_REQUIRED", "s2_40_detached:/Agent/Stages/0", f"stage={stage.get('name')!r};tasks={len(tasks) if isinstance(tasks, list) else 'invalid'};run_code={len(run_code)}")) + else: + task = run_code[0] + parameters = task.get("parameters") + expected = { + "language": "python", + "requirements": "httpx==0.28.1", + "network": "agent-network", + "timeout": 300, + } + if task.get("task_name") != "Task_S2_40_deterministic_finalizer" or not isinstance(parameters, dict) or any(parameters.get(key) != value for key, value in expected.items()): + errors.append(_finding("S2_40_RUN_CODE_SEMANTICS_MISMATCH", "s2_40_detached:/Agent/Stages/0/tasks/0", repr(task))) + elif isinstance(parameters.get("code"), str): + code_raw = parameters["code"].encode("utf-8") + procedure = stage.get("task_procedure") + expected_procedure = { + "IN": {"nexts": ["Task_S2_40_deterministic_finalizer"], "wait_until": []}, + "Task_S2_40_deterministic_finalizer": {"nexts": ["OUT"], "wait_until": ["IN"]}, + "OUT": {"nexts": [], "wait_until": ["Task_S2_40_deterministic_finalizer"]}, + } + if procedure != expected_procedure: + errors.append(_finding("S2_40_TASK_PROCEDURE_MISMATCH", "s2_40_detached:/Agent/Stages/0/task_procedure", repr(procedure))) + legacy_refs = sorted( + value + for value in _walk_strings(agent_doc) + if re.search(r"(?:^|[/\\])v\.[0-3](?:[/\\]|$)", value) + ) + if legacy_refs: + errors.append(_finding("S2_40_LEGACY_STAGE2_DEPENDENCY", "s2_40_detached:/authoring", repr(legacy_refs))) + + if code_raw and code_raw != mirror_py_raw: + errors.append(_finding("S2_40_INLINE_CODE_MIRROR_MISMATCH", "s2_40_detached:/canonical_code", f"code={_sha256(code_raw)};mirror={_sha256(mirror_py_raw)}")) + + receipt = _load_json(required["receipt"]) + if not isinstance(receipt, dict) or receipt.get("schema_version") != "stage2_s2_40_inline_code_receipt.v1" or receipt.get("workflow_id") != "S2_40": + errors.append(_finding("S2_40_INLINE_RECEIPT_INVALID", "s2_40_detached:/receipt", repr(receipt))) + else: + bindings = ( + ("authoring", authoring_raw), + ("deployment_projection", projection_raw), + ) + for key, raw in bindings: + row = receipt.get(key) + if not isinstance(row, dict) or row.get("sha256") != _sha256(raw) or row.get("size_bytes") != len(raw): + errors.append(_finding("S2_40_INLINE_RECEIPT_HASH_MISMATCH", f"s2_40_detached:/receipt/{key}", repr(row))) + canonical_code = receipt.get("canonical_code") + if not isinstance(canonical_code, dict) or canonical_code.get("sha256", canonical_code.get("code_sha256")) != _sha256(code_raw): + errors.append(_finding("S2_40_INLINE_RECEIPT_CODE_HASH_MISMATCH", "s2_40_detached:/receipt/canonical_code", repr(canonical_code))) + expected_parent = _sha256(parent_release_raw) + if receipt.get("expected_parent_stage2_release_sha256") != expected_parent: + errors.append(_finding("S2_40_PARENT_RELEASE_BINDING_MISMATCH", "s2_40_detached:/receipt/expected_parent_stage2_release_sha256", f"expected={expected_parent};observed={receipt.get('expected_parent_stage2_release_sha256')}")) + + binding = _load_yaml(required["binding"]) + rows = binding.get("stage_bindings") if isinstance(binding, dict) else None + matches = [row for row in rows if isinstance(row, dict) and row.get("stage_id") == "S2_40"] if isinstance(rows, list) else [] + counts["s2_40_stage_binding_count"] = len(matches) + if len(matches) != 1: + errors.append(_finding("S2_40_STAGE_BINDING_EXACT_ONE_REQUIRED", "s2_40_detached:/binding/stage_bindings", str(len(matches)))) + else: + row = matches[0] + expected = { + "workflow_id": "S2_40", + "execution_class": "NON-LLM-DETERMINISTIC", + "active_runtime_authority": False, + "mcp_server_id": "code-executor", + "tool_name": "run_code", + "language": "python", + "network": "agent-network", + "timeout_seconds": 300, + "external_mcp_contract": None, + } + drift = {key: {"expected": value, "observed": row.get(key)} for key, value in expected.items() if row.get(key) != value} + localdocs = row.get("localdocs_contract") + if not isinstance(localdocs, dict) or localdocs.get("endpoint") != "http://mcp-localdocs:8012/mcp" or localdocs.get("fixed_request_path") != "stage2_control/s2_40_request.json" or localdocs.get("tool_allowlist") != ["read_binary_doc", "write_binary_file"]: + drift["localdocs_contract"] = {"expected": "S2_40 localdocs binary-only contract", "observed": localdocs} + ref_expectations = { + "agent_script_ref": ("agent_scripts/Stage_2_S2_40.yml", projection_raw), + "inline_code_receipt_ref": ("manifest/s2_40_inline_code_receipt.json", required["receipt"].read_bytes()), + "stage2_release_ref": ("manifest/stage2_release.json", parent_release_raw), + } + for key, (path, raw) in ref_expectations.items(): + ref = row.get(key) + if not isinstance(ref, dict) or ref.get("path") != path or ref.get("sha256") != _sha256(raw): + drift[key] = {"expected": {"path": path, "sha256": _sha256(raw)}, "observed": ref} + if drift: + errors.append(_finding("S2_40_STAGE_BINDING_MISMATCH", "s2_40_detached:/binding/stage_bindings/S2_40", json.dumps(drift, ensure_ascii=False, sort_keys=True))) + if row.get("live_admission_status") not in {"PENDING_SECRET_BINDING", "PENDING_LIVE_VERIFICATION", "PENDING"}: + errors.append(_finding("S2_40_LIVE_ADMISSION_STATUS_DISHONEST", "s2_40_detached:/binding/stage_bindings/S2_40/live_admission_status", repr(row.get("live_admission_status")))) + else: + pending.append(_finding("S2_40_LIVE_CODE_EXECUTOR_ADMISSION_PENDING", "s2_40_detached:/binding/stage_bindings/S2_40", str(row.get("live_admission_status")))) + + admission = _load_json(required["admission"]) + expected_ids = ["S2_00", "S2_20", "S2_40"] + if not isinstance(admission, dict) or admission.get("present_deterministic_stage_ids") != expected_ids: + errors.append(_finding("S2_40_DETERMINISTIC_ADMISSION_SET_MISMATCH", "s2_40_detached:/admission/present_deterministic_stage_ids", repr(admission.get("present_deterministic_stage_ids") if isinstance(admission, dict) else admission))) + elif admission.get("executor_binding_sha256") != _sha256(required["binding"].read_bytes()) or admission.get("parent_release_sha256") != _sha256(parent_release_raw): + errors.append(_finding("S2_40_DETERMINISTIC_ADMISSION_HASH_MISMATCH", "s2_40_detached:/admission", repr(admission))) + elif admission.get("admission_status") != "PENDING": + errors.append(_finding("S2_40_UNSUPPORTED_ADMISSION_CLAIM", "s2_40_detached:/admission/admission_status", repr(admission.get("admission_status")))) + else: + pending.append(_finding("S2_40_DETERMINISTIC_ADMISSION_PENDING", "s2_40_detached:/admission", "external signed backend evidence pending")) + + deployment_schema = _load_json(required["deployment_schema"]) + deployment_defs = deployment_schema.get("$defs") if isinstance(deployment_schema, dict) else None + required_defs = { + "s2_40_request", + "s2_40_execution_receipt", + "s2_40_inline_code_receipt", + "s2_40_commit_intent", + "s2_40_commit_result", + } + if not isinstance(deployment_defs, dict) or not required_defs.issubset(deployment_defs): + errors.append(_finding("S2_40_DEPLOYMENT_SCHEMA_DEFS_MISSING", "s2_40_detached:/schemas/deployment/$defs", repr(sorted(required_defs - set(deployment_defs or {}))))) + for name in ("package_schema", "review_schema"): + schema = _load_json(required[name]) + if not isinstance(schema, dict) or not isinstance(schema.get("$defs"), dict) or not schema.get("$id"): + errors.append(_finding("S2_40_SCHEMA_ROOT_INVALID", f"s2_40_detached:/schemas/{name}", repr(schema))) + return errors, pending, counts + + def validate_package( root: Path, manifest_path: Path, @@ -526,6 +985,15 @@ def validate_package( rule_registry_path: Path, coverage_path: Path, ) -> dict[str, Any]: + root = _resolve_root(root) + try: + manifest_path = manifest_path.resolve(strict=True) + release_path = release_path.resolve(strict=True) + case_registry_path = case_registry_path.resolve(strict=True) + rule_registry_path = rule_registry_path.resolve(strict=True) + coverage_path = coverage_path.resolve(strict=True) + except (FileNotFoundError, OSError) as exc: + raise ValidationInputError(f"VALIDATION_INPUT_UNAVAILABLE:{exc}") from exc manifest = _load_json(manifest_path) release = _load_json(release_path) case_registry = _load_json(case_registry_path) @@ -539,6 +1007,17 @@ def validate_package( errors.extend(parent_errors) errors.extend(coverage_errors) errors.extend(_validate_parent_member_lists(root, manifest)) + s2_40_allowlist_path = root / "manifest/s2_40_parent_member_paths.json" + if s2_40_allowlist_path.is_file(): + s2_40_allowlist = _load_json(s2_40_allowlist_path) + if isinstance(s2_40_allowlist, list) and s2_40_allowlist: + detached_errors, detached_pending, detached_counts = _validate_s2_40_detached( + root, + release_path.read_bytes(), + ) + errors.extend(detached_errors) + pending.extend(detached_pending) + counts.update(detached_counts) pending.extend(parent_pending) pending.extend(coverage_pending) if ( @@ -569,28 +1048,29 @@ def validate(root: Path, manifest: dict[str, object]) -> list[str]: def _validate_parent_member_lists(root: Path, manifest: dict[str, Any]) -> list[dict[str, str]]: - """Verify the cumulative S2_20 + S2_30 allowlist without widening it.""" + """Verify disjoint cumulative S2_20/S2_30/S2_40 owner allowlists.""" paths = ( - root / "manifest" / "s2_20_parent_member_paths.json", - root / "manifest" / "s2_30_parent_member_paths.json", + ("S2_20", root / "manifest" / "s2_20_parent_member_paths.json"), + ("S2_30", root / "manifest" / "s2_30_parent_member_paths.json"), + ("S2_40", root / "manifest" / "s2_40_parent_member_paths.json"), ) - loaded: list[list[str]] = [] - for path in paths: + loaded: list[tuple[str, list[str]]] = [] + for owner_stage, path in paths: if not path.is_file(): return [_finding("PARENT_MEMBER_LIST_MISSING", path.as_posix(), "required cumulative allowlist component")] value = _load_json(path) if not isinstance(value, list) or not all(isinstance(row, str) for row in value): return [_finding("PARENT_MEMBER_LIST_INVALID", path.as_posix(), "string array required")] - loaded.append(value) - overlap = sorted(set(loaded[0]) & set(loaded[1])) + if value != sorted(value) or len(value) != len(set(value)): + return [_finding("PARENT_MEMBER_LIST_NOT_SORTED_UNIQUE", path.as_posix(), "sorted unique string array required")] + loaded.append((owner_stage, value)) findings: list[dict[str, str]] = [] - if overlap: - findings.append(_finding("PARENT_MEMBER_LISTS_NOT_DISJOINT", "manifest", repr(overlap))) rows = manifest.get("modules") - module_paths = { - row.get("path") for row in rows if isinstance(row, dict) - } if isinstance(rows, list) else set() + row_by_path = { + row.get("path"): row for row in rows if isinstance(row, dict) and isinstance(row.get("path"), str) + } if isinstance(rows, list) else {} + module_paths = set(row_by_path) mirrors = manifest.get("documentation_mirrors") if isinstance(mirrors, list): module_paths.update( @@ -598,14 +1078,42 @@ def _validate_parent_member_lists(root: Path, manifest: dict[str, Any]) -> list[ for row in mirrors if isinstance(row, dict) and isinstance(row.get("mirror_path"), str) ) - for relative in sorted(set(loaded[0]) | set(loaded[1])): - normalized = _relative_path(relative) - if normalized is None: - findings.append(_finding("PARENT_MEMBER_PATH_INVALID", "manifest", repr(relative))) - elif normalized in FORBIDDEN_PARENT_MEMBERS: - findings.append(_finding("NON_CYCLIC_PARENT_VIOLATION", "manifest", normalized)) - elif normalized not in module_paths: - findings.append(_finding("PARENT_MEMBER_NOT_IN_MODULE_MANIFEST", "manifest", normalized)) + seen: dict[str, str] = {} + for owner_stage, values in loaded: + metadata = STAGE_GENERIC_METADATA[owner_stage] + for relative in values: + if relative in seen: + findings.append(_finding("PARENT_MEMBER_LISTS_NOT_DISJOINT", "manifest", f"path={relative};owners={seen[relative]},{owner_stage}")) + else: + seen[relative] = owner_stage + normalized = _relative_path(relative) + if normalized is None: + findings.append(_finding("PARENT_MEMBER_PATH_INVALID", "manifest", repr(relative))) + elif normalized in FORBIDDEN_PARENT_MEMBERS: + findings.append(_finding("NON_CYCLIC_PARENT_VIOLATION", "manifest", normalized)) + elif normalized not in module_paths: + findings.append(_finding("PARENT_MEMBER_NOT_IN_MODULE_MANIFEST", "manifest", normalized)) + elif not normalized.endswith(".txt"): + row = row_by_path.get(normalized) + if isinstance(row, dict) and row.get("schema_version") in { + item["schema_version"] for item in STAGE_GENERIC_METADATA.values() + }: + expected = { + "asset_version": metadata["asset_version"], + "owner": metadata["owner"], + "schema_version": metadata["schema_version"], + "scope_predicate": metadata["scope_predicate"], + } + drift = { + key: {"expected": value, "observed": row.get(key)} + for key, value in expected.items() + if row.get(key) != value + } + module_id = row.get("module_id") + if not isinstance(module_id, str) or not module_id.startswith(metadata["module_id_prefix"]): + drift["module_id"] = {"expected_prefix": metadata["module_id_prefix"], "observed": module_id} + if drift: + findings.append(_finding("PARENT_MEMBER_OWNER_METADATA_MISMATCH", f"manifest:{normalized}", json.dumps(drift, ensure_ascii=False, sort_keys=True))) return findings diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R01_money_payment.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R01_money_payment.yml index 15bdbdfb..6124f1be 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R01_money_payment.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R01_money_payment.yml @@ -13,9 +13,26 @@ "obligor_ref", "payment_event_ref" ], + "slot_definitions": [ + {"name": "amount", "type": "MONEY", "cardinality": "EXACTLY_ONE"}, + {"name": "currency", "type": "STRING", "cardinality": "EXACTLY_ONE"}, + {"name": "obligor_ref", "type": "PARTY_REF", "cardinality": "EXACTLY_ONE"}, + {"name": "payment_event_ref", "type": "IDENTIFIER", "cardinality": "EXACTLY_ONE"} + ], "legal_branch_may_add_required_slots_only_after_review": true, "missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING" }, + "closed_ast_contract": { + "normalization_version": "NFC_LF_UTF8_V1", + "allowed_atom_types": ["RELIEF_ATOM", "COST_ATOM", "PROVISIONAL_EXECUTION_ATOM"], + "template_representation": "ORDERED_LITERAL_OR_TYPED_SLOT_SEGMENTS", + "immutable_literal_source": "APPROVED_BRANCH_ROWS_ONLY", + "branch_cardinality": "EXACTLY_ONE", + "independent_rerender_required": true, + "unknown_slot_forbidden": true, + "dangling_token_forbidden": true, + "required_exhibit_resolution": "BRANCH_DECLARED_ONLY" + }, "branch_rows": [], "closure": { "exactly_one_approved_branch_required": true, diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R02_delivery_possession.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R02_delivery_possession.yml index 0df92c57..e7fb50b2 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R02_delivery_possession.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R02_delivery_possession.yml @@ -12,9 +12,25 @@ "obligor_ref", "performance_mode" ], + "slot_definitions": [ + {"name": "object_ref", "type": "OBJECT_REF", "cardinality": "EXACTLY_ONE"}, + {"name": "obligor_ref", "type": "PARTY_REF", "cardinality": "EXACTLY_ONE"}, + {"name": "performance_mode", "type": "IDENTIFIER", "cardinality": "EXACTLY_ONE"} + ], "legal_branch_may_add_required_slots_only_after_review": true, "missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING" }, + "closed_ast_contract": { + "normalization_version": "NFC_LF_UTF8_V1", + "allowed_atom_types": ["RELIEF_ATOM", "COST_ATOM", "PROVISIONAL_EXECUTION_ATOM", "ANNEX_ATOM"], + "template_representation": "ORDERED_LITERAL_OR_TYPED_SLOT_SEGMENTS", + "immutable_literal_source": "APPROVED_BRANCH_ROWS_ONLY", + "branch_cardinality": "EXACTLY_ONE", + "independent_rerender_required": true, + "unknown_slot_forbidden": true, + "dangling_token_forbidden": true, + "required_exhibit_resolution": "BRANCH_DECLARED_ONLY" + }, "branch_rows": [], "closure": { "exactly_one_approved_branch_required": true, diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R03_declaration_registry.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R03_declaration_registry.yml index 652633d4..bf4af4ee 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R03_declaration_registry.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R03_declaration_registry.yml @@ -12,9 +12,26 @@ "registry_action", "obligor_ref" ], + "slot_definitions": [ + {"name": "registry_object_ref", "type": "OBJECT_REF", "cardinality": "EXACTLY_ONE"}, + {"name": "registry_action", "type": "IDENTIFIER", "cardinality": "EXACTLY_ONE"}, + {"name": "obligor_ref", "type": "PARTY_REF", "cardinality": "EXACTLY_ONE"} + ], "legal_branch_may_add_required_slots_only_after_review": true, "missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING" }, + "closed_ast_contract": { + "normalization_version": "NFC_LF_UTF8_V1", + "allowed_atom_types": ["RELIEF_ATOM", "COST_ATOM", "ANNEX_ATOM"], + "template_representation": "ORDERED_LITERAL_OR_TYPED_SLOT_SEGMENTS", + "immutable_literal_source": "APPROVED_BRANCH_ROWS_ONLY", + "branch_cardinality": "EXACTLY_ONE", + "independent_rerender_required": true, + "unknown_slot_forbidden": true, + "dangling_token_forbidden": true, + "required_exhibit_resolution": "BRANCH_DECLARED_ONLY", + "provisional_execution_forbidden": true + }, "branch_rows": [], "closure": { "exactly_one_approved_branch_required": true, diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R04_special_nonmoney_performance.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R04_special_nonmoney_performance.yml index 29510d65..dd37fe3b 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R04_special_nonmoney_performance.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R04_special_nonmoney_performance.yml @@ -12,9 +12,26 @@ "performance_mode", "obligor_ref" ], + "slot_definitions": [ + {"name": "performance_object_ref", "type": "OBJECT_REF", "cardinality": "EXACTLY_ONE"}, + {"name": "performance_mode", "type": "IDENTIFIER", "cardinality": "EXACTLY_ONE"}, + {"name": "obligor_ref", "type": "PARTY_REF", "cardinality": "EXACTLY_ONE"} + ], "legal_branch_may_add_required_slots_only_after_review": true, "missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING" }, + "closed_ast_contract": { + "normalization_version": "NFC_LF_UTF8_V1", + "allowed_atom_types": ["RELIEF_ATOM", "COST_ATOM", "PROVISIONAL_EXECUTION_ATOM", "ANNEX_ATOM"], + "template_representation": "ORDERED_LITERAL_OR_TYPED_SLOT_SEGMENTS", + "immutable_literal_source": "APPROVED_BRANCH_ROWS_ONLY", + "branch_cardinality": "EXACTLY_ONE", + "independent_rerender_required": true, + "unknown_slot_forbidden": true, + "dangling_token_forbidden": true, + "required_exhibit_resolution": "BRANCH_DECLARED_ONLY", + "provisional_execution_requires_branch_authority": true + }, "branch_rows": [], "closure": { "exactly_one_approved_branch_required": true, diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R05_declaratory.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R05_declaratory.yml index 3155c5a0..1c59b785 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R05_declaratory.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R05_declaratory.yml @@ -12,9 +12,26 @@ "declaration_scope", "opposing_party_ref" ], + "slot_definitions": [ + {"name": "legal_relation_ref", "type": "IDENTIFIER", "cardinality": "EXACTLY_ONE"}, + {"name": "declaration_scope", "type": "STRING", "cardinality": "EXACTLY_ONE"}, + {"name": "opposing_party_ref", "type": "PARTY_REF", "cardinality": "EXACTLY_ONE"} + ], "legal_branch_may_add_required_slots_only_after_review": true, "missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING" }, + "closed_ast_contract": { + "normalization_version": "NFC_LF_UTF8_V1", + "allowed_atom_types": ["RELIEF_ATOM", "COST_ATOM"], + "template_representation": "ORDERED_LITERAL_OR_TYPED_SLOT_SEGMENTS", + "immutable_literal_source": "APPROVED_BRANCH_ROWS_ONLY", + "branch_cardinality": "EXACTLY_ONE", + "independent_rerender_required": true, + "unknown_slot_forbidden": true, + "dangling_token_forbidden": true, + "required_exhibit_resolution": "BRANCH_DECLARED_ONLY", + "provisional_execution_forbidden": true + }, "branch_rows": [], "closure": { "exactly_one_approved_branch_required": true, diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R06_constitutive_judgment_challenge.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R06_constitutive_judgment_challenge.yml index 8535c997..497ac156 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R06_constitutive_judgment_challenge.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/renderers/R06_constitutive_judgment_challenge.yml @@ -12,9 +12,26 @@ "constitutive_method", "opposing_party_ref" ], + "slot_definitions": [ + {"name": "legal_effect_ref", "type": "IDENTIFIER", "cardinality": "EXACTLY_ONE"}, + {"name": "constitutive_method", "type": "IDENTIFIER", "cardinality": "EXACTLY_ONE"}, + {"name": "opposing_party_ref", "type": "PARTY_REF", "cardinality": "EXACTLY_ONE"} + ], "legal_branch_may_add_required_slots_only_after_review": true, "missing_required_slot_issue_code": "RENDERER_REQUIRED_SLOT_MISSING" }, + "closed_ast_contract": { + "normalization_version": "NFC_LF_UTF8_V1", + "allowed_atom_types": ["RELIEF_ATOM", "COST_ATOM", "ANNEX_ATOM"], + "template_representation": "ORDERED_LITERAL_OR_TYPED_SLOT_SEGMENTS", + "immutable_literal_source": "APPROVED_BRANCH_ROWS_ONLY", + "branch_cardinality": "EXACTLY_ONE", + "independent_rerender_required": true, + "unknown_slot_forbidden": true, + "dangling_token_forbidden": true, + "required_exhibit_resolution": "BRANCH_DECLARED_ONLY", + "provisional_execution_forbidden": true + }, "branch_rows": [], "closure": { "exactly_one_approved_branch_required": true, diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/c45_document_assembler.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/c45_document_assembler.py new file mode 100644 index 00000000..6fe5e871 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/c45_document_assembler.py @@ -0,0 +1,236 @@ +from __future__ import annotations + +"""Pure offline C40/C45 oracle for the S2_40 deterministic finalizer.""" + +import hashlib +import json +import unicodedata +import re +from typing import Any, Iterable, Mapping, Sequence + + +class AssemblyError(ValueError): + pass + + +RELATION_ORDER = {"PRIMARY": 0, "PRELIMINARY": 1, "ALTERNATIVE": 2, "SELECTIVE": 3} +CAUSE_SECTION_ORDER = { + "PARTY_AND_TITLE": 0, "COMMON_FACT": 1, "GROUP_FACT": 2, + "ELEMENT_FACT_EVIDENCE": 3, "DEFENSE_REBUTTAL": 4, + "CONCLUSION": 5, "ANNEX_EXHIBIT_REFERENCE": 6, +} +HEX64 = re.compile(r"^[a-f0-9]{64}$") + + +def normalize_text(value: str) -> str: + if not isinstance(value, str): + raise AssemblyError("TEXT_TYPE_INVALID") + value = unicodedata.normalize("NFC", value.replace("\r\n", "\n").replace("\r", "\n")) + if "\x00" in value: + raise AssemblyError("TEXT_NUL_FORBIDDEN") + return value + + +def canonical_json_bytes(value: Any) -> bytes: + return (json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8") + + +def sha256_bytes(raw: bytes) -> str: + return hashlib.sha256(raw).hexdigest() + + +def reduce_immutable_rows(parts: Sequence[Mapping[str, Any]], *, id_field: str, row_field: str) -> list[dict[str, Any]]: + """Stable union; only byte-equivalent duplicates are tolerated.""" + by_id: dict[str, tuple[bytes, dict[str, Any]]] = {} + seen_parts: set[str] = set() + for part in sorted(parts, key=lambda row: (str(row.get("group_id", "")), str(row.get("part_id", "")))): + part_id = part.get("part_id") + if not isinstance(part_id, str) or not part_id or part_id in seen_parts: + raise AssemblyError("IMMUTABLE_PART_ID_MISSING_OR_DUPLICATE") + seen_parts.add(part_id) + rows = part.get(row_field) + if not isinstance(rows, list): + raise AssemblyError("IMMUTABLE_PART_ROWS_INVALID") + for row in rows: + row_id = row.get(id_field) if isinstance(row, dict) else None + if not isinstance(row_id, str) or not row_id: + raise AssemblyError("IMMUTABLE_ROW_ID_INVALID") + raw = canonical_json_bytes(row) + if row_id in by_id and by_id[row_id][0] != raw: + raise AssemblyError("IMMUTABLE_ROW_CONFLICT") + by_id[row_id] = (raw, dict(row)) + return [by_id[key][1] for key in sorted(by_id)] + + +def validate_exact_group_part_set( + parts: Sequence[Mapping[str, Any]], *, expected_group_ids: Sequence[str], + expected_families: Sequence[str] = ("DRAFT_PART", "ISSUE_PATCH", "WORKNOTE_PART", "USAGE_PART"), +) -> None: + if len(expected_group_ids) != len(set(expected_group_ids)) or len(expected_families) != len(set(expected_families)): + raise AssemblyError("EXPECTED_PART_SET_DUPLICATE") + expected = {(group_id, family) for group_id in expected_group_ids for family in expected_families} + observed: list[tuple[str, str]] = [] + part_ids: set[str] = set() + for part in parts: + part_id, group_id, family = part.get("part_id"), part.get("group_id"), part.get("part_family") + if not all(isinstance(value, str) and value for value in (part_id, group_id, family)): + raise AssemblyError("PART_SET_ROW_INVALID") + if part_id in part_ids: + raise AssemblyError("PART_SET_PART_ID_DUPLICATE") + part_ids.add(part_id) + observed.append((group_id, family)) + if len(observed) != len(set(observed)) or set(observed) != expected: + raise AssemblyError("PART_SET_NOT_EXACT") + + +def validate_option_partition(option_ids: Iterable[str], partitions: Mapping[str, Sequence[str]]) -> None: + required = {"selected", "alternative", "excluded", "deferred"} + if set(partitions) != required: + raise AssemblyError("OPTION_PARTITION_SHAPE_INVALID") + flattened = [item for name in sorted(required) for item in partitions[name]] + if len(flattened) != len(set(flattened)): + raise AssemblyError("OPTION_PARTITION_OVERLAP") + if set(flattened) != set(option_ids): + raise AssemblyError("OPTION_PARTITION_NOT_CONSERVATIVE") + + +def build_usage_projection( + usage_parts: Sequence[Mapping[str, Any]], *, run_binding_digest: str, +) -> dict[str, Any]: + """Reduce immutable S2_30 usage parts into the exact S2_40 projection contract.""" + if HEX64.fullmatch(run_binding_digest) is None: + raise AssemblyError("USAGE_RUN_BINDING_DIGEST_INVALID") + source_hashes: list[str] = [] + by_id: dict[str, tuple[bytes, dict[str, Any]]] = {} + observed_row_count = 0 + for part in sorted(usage_parts, key=lambda value: str(value.get("part_id", ""))): + if set(part) != {"part_id", "raw_sha256", "rows"}: + raise AssemblyError("USAGE_PART_SHAPE_NOT_EXACT") + if not isinstance(part["part_id"], str) or not part["part_id"]: + raise AssemblyError("USAGE_PART_ID_INVALID") + if not isinstance(part["raw_sha256"], str) or HEX64.fullmatch(part["raw_sha256"]) is None: + raise AssemblyError("USAGE_PART_SHA256_INVALID") + rows = part["rows"] + if not isinstance(rows, list): + raise AssemblyError("USAGE_PART_ROWS_INVALID") + source_hashes.append(part["raw_sha256"]) + for row in rows: + if not isinstance(row, dict): + raise AssemblyError("USAGE_ROW_NOT_OBJECT") + usage_id = row.get("usage_id") + if not isinstance(usage_id, str) or not usage_id: + raise AssemblyError("USAGE_ID_INVALID") + observed_row_count += 1 + raw = canonical_json_bytes(row) + if usage_id in by_id and by_id[usage_id][0] != raw: + raise AssemblyError("USAGE_ROW_CONFLICT") + by_id[usage_id] = (raw, dict(row)) + if len(source_hashes) != len(set(source_hashes)): + raise AssemblyError("USAGE_SOURCE_PART_SHA256_DUPLICATE") + rows = [by_id[key][1] for key in sorted(by_id)] + if observed_row_count != len(rows): + raise AssemblyError("USAGE_CONSERVATION_FAILED") + return { + "schema_version": "stage2_s2_40_usage_projection.v1", + "producer_id": "S2_40", + "run_binding_digest": run_binding_digest, + "source_usage_part_sha256s": sorted(source_hashes), + "rows": rows, + "conservation_status": "PASS", + } + + +def _ordered_relief(rows: Sequence[Mapping[str, Any]]) -> list[Mapping[str, Any]]: + claim_ids = [row.get("atomic_claim_id") for row in rows] + if any(not isinstance(value, str) or not value for value in claim_ids) or len(claim_ids) != len(set(claim_ids)): + raise AssemblyError("RELIEF_ATOMIC_CLAIM_ID_MISSING_OR_DUPLICATE") + for row in rows: + if row.get("relation") not in RELATION_ORDER: + raise AssemblyError("RELIEF_RELATION_UNKNOWN") + if not isinstance(row.get("plan_order"), int) or row["plan_order"] < 0: + raise AssemblyError("RELIEF_PLAN_ORDER_INVALID") + if not isinstance(row.get("rendered_text"), str) or not row["rendered_text"]: + raise AssemblyError("RELIEF_RENDERED_TEXT_MISSING") + return sorted(rows, key=lambda row: (RELATION_ORDER[row["relation"]], row["plan_order"], row["atomic_claim_id"])) + + +def _ordered_causes(atoms: Sequence[Mapping[str, Any]]) -> list[Mapping[str, Any]]: + atom_ids = [atom.get("atom_id") for atom in atoms] + if any(not isinstance(value, str) or not value for value in atom_ids) or len(atom_ids) != len(set(atom_ids)): + raise AssemblyError("CAUSE_ATOM_ID_MISSING_OR_DUPLICATE") + for atom in atoms: + if atom.get("section_kind") not in CAUSE_SECTION_ORDER: + raise AssemblyError("CAUSE_SECTION_KIND_UNKNOWN") + if not atom.get("source_refs"): + raise AssemblyError("CAUSE_ATOM_PROVENANCE_MISSING") + if not isinstance(atom.get("text"), str) or not atom["text"]: + raise AssemblyError("CAUSE_ATOM_TEXT_MISSING") + return sorted(atoms, key=lambda atom: ( + CAUSE_SECTION_ORDER[atom["section_kind"]], str(atom.get("group_id", "")), + int(atom.get("atom_order", 0)), atom["atom_id"], + )) + + +def assemble_documents( + relief_rows: Sequence[Mapping[str, Any]], cause_atoms: Sequence[Mapping[str, Any]], + *, cost_text: str, provisional_rows: Sequence[Mapping[str, Any]], +) -> dict[str, Any]: + relief, causes = _ordered_relief(relief_rows), _ordered_causes(cause_atoms) + cost_text = normalize_text(cost_text) + if not cost_text: + raise AssemblyError("COST_TEXT_MISSING") + relief_lines = [f"{index}. {normalize_text(row['rendered_text'])}" for index, row in enumerate(relief, 1)] + relief_lines.append(f"{len(relief_lines) + 1}. {cost_text}") + for row in sorted(provisional_rows, key=lambda item: item["atomic_claim_id"]): + if row.get("eligible") is not True: + raise AssemblyError("PROVISIONAL_EXECUTION_INELIGIBLE_ATOM") + relief_lines.append(f"{len(relief_lines) + 1}. {normalize_text(row['rendered_text'])}") + relief_text = normalize_text("\n".join(relief_lines) + "\n") + cause_sections: list[str] = [] + current: str | None = None + for atom in causes: + if atom["section_kind"] != current: + current = atom["section_kind"] + cause_sections.append(f"## {current}") + cause_sections.append(normalize_text(atom["text"])) + cause_text = normalize_text("\n\n".join(cause_sections) + "\n") + pleading = normalize_text("# CLAIM_RELIEF\n\n" + relief_text + "\n# CLAIM_CAUSE\n\n" + cause_text) + result = { + "schema_version": "stage2_s2_40_assembled_documents.v1", + "claim_relief": {"text": relief_text, "sha256": sha256_bytes(relief_text.encode())}, + "claim_cause": {"text": cause_text, "sha256": sha256_bytes(cause_text.encode())}, + "pleading_draft": {"text": pleading, "sha256": sha256_bytes(pleading.encode())}, + "ordered_atomic_claim_ids": [row["atomic_claim_id"] for row in relief], + "ordered_cause_atom_ids": [atom["atom_id"] for atom in causes], + } + # A second construction from detached copies must be byte-identical. This + # catches accidental mutable state, locale ordering, and hidden renderer IO. + independent_relief = normalize_text("\n".join(relief_lines) + "\n") + independent_cause = normalize_text("\n\n".join(cause_sections) + "\n") + independent_pleading = normalize_text("# CLAIM_RELIEF\n\n" + independent_relief + "\n# CLAIM_CAUSE\n\n" + independent_cause) + if (independent_relief, independent_cause, independent_pleading) != (relief_text, cause_text, pleading): + raise AssemblyError("CLOSED_DOCUMENT_RERENDER_MISMATCH") + return result + + +def relief_cause_crossmatch(relief_rows: Sequence[Mapping[str, Any]], cause_atoms: Sequence[Mapping[str, Any]]) -> list[str]: + cause_claims = {atom.get("atomic_claim_id") for atom in cause_atoms if atom.get("atomic_claim_id")} + findings: list[str] = [] + for row in relief_rows: + claim_id = row.get("atomic_claim_id") + if claim_id not in cause_claims: + findings.append(f"RELIEF_CAUSE_ATOMIC_CLAIM_MISSING::{claim_id}") + for field in ("claimant_ref", "defendant_ref"): + expected = row.get(field) + if expected and not any(atom.get(field) == expected and atom.get("atomic_claim_id") == claim_id for atom in cause_atoms): + findings.append(f"RELIEF_CAUSE_{field.upper()}_MISMATCH::{claim_id}") + for field in ("amount_ref", "object_ref", "legal_effect_ref"): + expected = row.get(field) + if expected is not None and not any( + atom.get(field) == expected and atom.get("atomic_claim_id") == claim_id for atom in cause_atoms + ): + findings.append(f"RELIEF_CAUSE_{field.upper()}_MISMATCH::{claim_id}") + return sorted(findings) + + +__all__ = ["AssemblyError", "assemble_documents", "build_usage_projection", "canonical_json_bytes", "reduce_immutable_rows", "relief_cause_crossmatch", "sha256_bytes", "validate_exact_group_part_set", "validate_option_partition"] diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/c45_document_assembler.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/c45_document_assembler.txt new file mode 100644 index 00000000..6fe5e871 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/c45_document_assembler.txt @@ -0,0 +1,236 @@ +from __future__ import annotations + +"""Pure offline C40/C45 oracle for the S2_40 deterministic finalizer.""" + +import hashlib +import json +import unicodedata +import re +from typing import Any, Iterable, Mapping, Sequence + + +class AssemblyError(ValueError): + pass + + +RELATION_ORDER = {"PRIMARY": 0, "PRELIMINARY": 1, "ALTERNATIVE": 2, "SELECTIVE": 3} +CAUSE_SECTION_ORDER = { + "PARTY_AND_TITLE": 0, "COMMON_FACT": 1, "GROUP_FACT": 2, + "ELEMENT_FACT_EVIDENCE": 3, "DEFENSE_REBUTTAL": 4, + "CONCLUSION": 5, "ANNEX_EXHIBIT_REFERENCE": 6, +} +HEX64 = re.compile(r"^[a-f0-9]{64}$") + + +def normalize_text(value: str) -> str: + if not isinstance(value, str): + raise AssemblyError("TEXT_TYPE_INVALID") + value = unicodedata.normalize("NFC", value.replace("\r\n", "\n").replace("\r", "\n")) + if "\x00" in value: + raise AssemblyError("TEXT_NUL_FORBIDDEN") + return value + + +def canonical_json_bytes(value: Any) -> bytes: + return (json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8") + + +def sha256_bytes(raw: bytes) -> str: + return hashlib.sha256(raw).hexdigest() + + +def reduce_immutable_rows(parts: Sequence[Mapping[str, Any]], *, id_field: str, row_field: str) -> list[dict[str, Any]]: + """Stable union; only byte-equivalent duplicates are tolerated.""" + by_id: dict[str, tuple[bytes, dict[str, Any]]] = {} + seen_parts: set[str] = set() + for part in sorted(parts, key=lambda row: (str(row.get("group_id", "")), str(row.get("part_id", "")))): + part_id = part.get("part_id") + if not isinstance(part_id, str) or not part_id or part_id in seen_parts: + raise AssemblyError("IMMUTABLE_PART_ID_MISSING_OR_DUPLICATE") + seen_parts.add(part_id) + rows = part.get(row_field) + if not isinstance(rows, list): + raise AssemblyError("IMMUTABLE_PART_ROWS_INVALID") + for row in rows: + row_id = row.get(id_field) if isinstance(row, dict) else None + if not isinstance(row_id, str) or not row_id: + raise AssemblyError("IMMUTABLE_ROW_ID_INVALID") + raw = canonical_json_bytes(row) + if row_id in by_id and by_id[row_id][0] != raw: + raise AssemblyError("IMMUTABLE_ROW_CONFLICT") + by_id[row_id] = (raw, dict(row)) + return [by_id[key][1] for key in sorted(by_id)] + + +def validate_exact_group_part_set( + parts: Sequence[Mapping[str, Any]], *, expected_group_ids: Sequence[str], + expected_families: Sequence[str] = ("DRAFT_PART", "ISSUE_PATCH", "WORKNOTE_PART", "USAGE_PART"), +) -> None: + if len(expected_group_ids) != len(set(expected_group_ids)) or len(expected_families) != len(set(expected_families)): + raise AssemblyError("EXPECTED_PART_SET_DUPLICATE") + expected = {(group_id, family) for group_id in expected_group_ids for family in expected_families} + observed: list[tuple[str, str]] = [] + part_ids: set[str] = set() + for part in parts: + part_id, group_id, family = part.get("part_id"), part.get("group_id"), part.get("part_family") + if not all(isinstance(value, str) and value for value in (part_id, group_id, family)): + raise AssemblyError("PART_SET_ROW_INVALID") + if part_id in part_ids: + raise AssemblyError("PART_SET_PART_ID_DUPLICATE") + part_ids.add(part_id) + observed.append((group_id, family)) + if len(observed) != len(set(observed)) or set(observed) != expected: + raise AssemblyError("PART_SET_NOT_EXACT") + + +def validate_option_partition(option_ids: Iterable[str], partitions: Mapping[str, Sequence[str]]) -> None: + required = {"selected", "alternative", "excluded", "deferred"} + if set(partitions) != required: + raise AssemblyError("OPTION_PARTITION_SHAPE_INVALID") + flattened = [item for name in sorted(required) for item in partitions[name]] + if len(flattened) != len(set(flattened)): + raise AssemblyError("OPTION_PARTITION_OVERLAP") + if set(flattened) != set(option_ids): + raise AssemblyError("OPTION_PARTITION_NOT_CONSERVATIVE") + + +def build_usage_projection( + usage_parts: Sequence[Mapping[str, Any]], *, run_binding_digest: str, +) -> dict[str, Any]: + """Reduce immutable S2_30 usage parts into the exact S2_40 projection contract.""" + if HEX64.fullmatch(run_binding_digest) is None: + raise AssemblyError("USAGE_RUN_BINDING_DIGEST_INVALID") + source_hashes: list[str] = [] + by_id: dict[str, tuple[bytes, dict[str, Any]]] = {} + observed_row_count = 0 + for part in sorted(usage_parts, key=lambda value: str(value.get("part_id", ""))): + if set(part) != {"part_id", "raw_sha256", "rows"}: + raise AssemblyError("USAGE_PART_SHAPE_NOT_EXACT") + if not isinstance(part["part_id"], str) or not part["part_id"]: + raise AssemblyError("USAGE_PART_ID_INVALID") + if not isinstance(part["raw_sha256"], str) or HEX64.fullmatch(part["raw_sha256"]) is None: + raise AssemblyError("USAGE_PART_SHA256_INVALID") + rows = part["rows"] + if not isinstance(rows, list): + raise AssemblyError("USAGE_PART_ROWS_INVALID") + source_hashes.append(part["raw_sha256"]) + for row in rows: + if not isinstance(row, dict): + raise AssemblyError("USAGE_ROW_NOT_OBJECT") + usage_id = row.get("usage_id") + if not isinstance(usage_id, str) or not usage_id: + raise AssemblyError("USAGE_ID_INVALID") + observed_row_count += 1 + raw = canonical_json_bytes(row) + if usage_id in by_id and by_id[usage_id][0] != raw: + raise AssemblyError("USAGE_ROW_CONFLICT") + by_id[usage_id] = (raw, dict(row)) + if len(source_hashes) != len(set(source_hashes)): + raise AssemblyError("USAGE_SOURCE_PART_SHA256_DUPLICATE") + rows = [by_id[key][1] for key in sorted(by_id)] + if observed_row_count != len(rows): + raise AssemblyError("USAGE_CONSERVATION_FAILED") + return { + "schema_version": "stage2_s2_40_usage_projection.v1", + "producer_id": "S2_40", + "run_binding_digest": run_binding_digest, + "source_usage_part_sha256s": sorted(source_hashes), + "rows": rows, + "conservation_status": "PASS", + } + + +def _ordered_relief(rows: Sequence[Mapping[str, Any]]) -> list[Mapping[str, Any]]: + claim_ids = [row.get("atomic_claim_id") for row in rows] + if any(not isinstance(value, str) or not value for value in claim_ids) or len(claim_ids) != len(set(claim_ids)): + raise AssemblyError("RELIEF_ATOMIC_CLAIM_ID_MISSING_OR_DUPLICATE") + for row in rows: + if row.get("relation") not in RELATION_ORDER: + raise AssemblyError("RELIEF_RELATION_UNKNOWN") + if not isinstance(row.get("plan_order"), int) or row["plan_order"] < 0: + raise AssemblyError("RELIEF_PLAN_ORDER_INVALID") + if not isinstance(row.get("rendered_text"), str) or not row["rendered_text"]: + raise AssemblyError("RELIEF_RENDERED_TEXT_MISSING") + return sorted(rows, key=lambda row: (RELATION_ORDER[row["relation"]], row["plan_order"], row["atomic_claim_id"])) + + +def _ordered_causes(atoms: Sequence[Mapping[str, Any]]) -> list[Mapping[str, Any]]: + atom_ids = [atom.get("atom_id") for atom in atoms] + if any(not isinstance(value, str) or not value for value in atom_ids) or len(atom_ids) != len(set(atom_ids)): + raise AssemblyError("CAUSE_ATOM_ID_MISSING_OR_DUPLICATE") + for atom in atoms: + if atom.get("section_kind") not in CAUSE_SECTION_ORDER: + raise AssemblyError("CAUSE_SECTION_KIND_UNKNOWN") + if not atom.get("source_refs"): + raise AssemblyError("CAUSE_ATOM_PROVENANCE_MISSING") + if not isinstance(atom.get("text"), str) or not atom["text"]: + raise AssemblyError("CAUSE_ATOM_TEXT_MISSING") + return sorted(atoms, key=lambda atom: ( + CAUSE_SECTION_ORDER[atom["section_kind"]], str(atom.get("group_id", "")), + int(atom.get("atom_order", 0)), atom["atom_id"], + )) + + +def assemble_documents( + relief_rows: Sequence[Mapping[str, Any]], cause_atoms: Sequence[Mapping[str, Any]], + *, cost_text: str, provisional_rows: Sequence[Mapping[str, Any]], +) -> dict[str, Any]: + relief, causes = _ordered_relief(relief_rows), _ordered_causes(cause_atoms) + cost_text = normalize_text(cost_text) + if not cost_text: + raise AssemblyError("COST_TEXT_MISSING") + relief_lines = [f"{index}. {normalize_text(row['rendered_text'])}" for index, row in enumerate(relief, 1)] + relief_lines.append(f"{len(relief_lines) + 1}. {cost_text}") + for row in sorted(provisional_rows, key=lambda item: item["atomic_claim_id"]): + if row.get("eligible") is not True: + raise AssemblyError("PROVISIONAL_EXECUTION_INELIGIBLE_ATOM") + relief_lines.append(f"{len(relief_lines) + 1}. {normalize_text(row['rendered_text'])}") + relief_text = normalize_text("\n".join(relief_lines) + "\n") + cause_sections: list[str] = [] + current: str | None = None + for atom in causes: + if atom["section_kind"] != current: + current = atom["section_kind"] + cause_sections.append(f"## {current}") + cause_sections.append(normalize_text(atom["text"])) + cause_text = normalize_text("\n\n".join(cause_sections) + "\n") + pleading = normalize_text("# CLAIM_RELIEF\n\n" + relief_text + "\n# CLAIM_CAUSE\n\n" + cause_text) + result = { + "schema_version": "stage2_s2_40_assembled_documents.v1", + "claim_relief": {"text": relief_text, "sha256": sha256_bytes(relief_text.encode())}, + "claim_cause": {"text": cause_text, "sha256": sha256_bytes(cause_text.encode())}, + "pleading_draft": {"text": pleading, "sha256": sha256_bytes(pleading.encode())}, + "ordered_atomic_claim_ids": [row["atomic_claim_id"] for row in relief], + "ordered_cause_atom_ids": [atom["atom_id"] for atom in causes], + } + # A second construction from detached copies must be byte-identical. This + # catches accidental mutable state, locale ordering, and hidden renderer IO. + independent_relief = normalize_text("\n".join(relief_lines) + "\n") + independent_cause = normalize_text("\n\n".join(cause_sections) + "\n") + independent_pleading = normalize_text("# CLAIM_RELIEF\n\n" + independent_relief + "\n# CLAIM_CAUSE\n\n" + independent_cause) + if (independent_relief, independent_cause, independent_pleading) != (relief_text, cause_text, pleading): + raise AssemblyError("CLOSED_DOCUMENT_RERENDER_MISMATCH") + return result + + +def relief_cause_crossmatch(relief_rows: Sequence[Mapping[str, Any]], cause_atoms: Sequence[Mapping[str, Any]]) -> list[str]: + cause_claims = {atom.get("atomic_claim_id") for atom in cause_atoms if atom.get("atomic_claim_id")} + findings: list[str] = [] + for row in relief_rows: + claim_id = row.get("atomic_claim_id") + if claim_id not in cause_claims: + findings.append(f"RELIEF_CAUSE_ATOMIC_CLAIM_MISSING::{claim_id}") + for field in ("claimant_ref", "defendant_ref"): + expected = row.get(field) + if expected and not any(atom.get(field) == expected and atom.get("atomic_claim_id") == claim_id for atom in cause_atoms): + findings.append(f"RELIEF_CAUSE_{field.upper()}_MISMATCH::{claim_id}") + for field in ("amount_ref", "object_ref", "legal_effect_ref"): + expected = row.get(field) + if expected is not None and not any( + atom.get(field) == expected and atom.get("atomic_claim_id") == claim_id for atom in cause_atoms + ): + findings.append(f"RELIEF_CAUSE_{field.upper()}_MISMATCH::{claim_id}") + return sorted(findings) + + +__all__ = ["AssemblyError", "assemble_documents", "build_usage_projection", "canonical_json_bytes", "reduce_immutable_rows", "relief_cause_crossmatch", "sha256_bytes", "validate_exact_group_part_set", "validate_option_partition"] diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/rendering/closed_renderer.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/rendering/closed_renderer.py new file mode 100644 index 00000000..7e410db2 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/rendering/closed_renderer.py @@ -0,0 +1,215 @@ +from __future__ import annotations + +"""Offline oracle for S2_40 closed rendering; contains no legal wording.""" + +from copy import deepcopy +import hashlib +import json +import re +import unicodedata +from typing import Any, Mapping, Sequence + + +ALLOWED_SLOT_TYPES = { + "STRING", "IDENTIFIER", "MONEY", "DATE", "OBJECT_REF", "PARTY_REF", "EXHIBIT_REF" +} +ALLOWED_PREDICATE_OPS = {"EQ", "IN", "BOOL"} + + +class ClosedRenderError(ValueError): + """Raised when a closed renderer contract cannot be applied exactly.""" + + +def normalize_text(value: str) -> str: + if not isinstance(value, str): + raise ClosedRenderError("RENDERER_SLOT_TYPE_MISMATCH") + normalized = unicodedata.normalize("NFC", value.replace("\r\n", "\n").replace("\r", "\n")) + if "\x00" in normalized: + raise ClosedRenderError("RENDERER_NUL_FORBIDDEN") + return normalized + + +def canonical_json_bytes(value: Any) -> bytes: + return (json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8") + + +def sha256_bytes(raw: bytes) -> str: + return hashlib.sha256(raw).hexdigest() + + +def _unique_names(rows: Sequence[Mapping[str, Any]], field: str) -> set[str]: + names = [row.get(field) for row in rows] + if any(not isinstance(name, str) or not name for name in names): + raise ClosedRenderError(f"RENDERER_{field.upper()}_INVALID") + if len(names) != len(set(names)): + raise ClosedRenderError(f"RENDERER_{field.upper()}_DUPLICATE") + return set(names) + + +def validate_descriptor(descriptor: Mapping[str, Any], *, allow_fixture: bool = False) -> None: + required = { + "schema_version", "renderer_id", "renderer_kind", "status", "execution_eligible", + "stage2_20_role", "stage2_40_role", "typed_slot_contract", "closed_ast_contract", + "branch_rows", "closure", "review", + } + if set(descriptor) != required: + raise ClosedRenderError("RENDERER_DESCRIPTOR_SHAPE_INVALID") + if not descriptor["execution_eligible"]: + raise ClosedRenderError("RENDERER_NOT_EXECUTION_ELIGIBLE") + if descriptor["status"] != "APPROVED_LEGAL_CONTENT": + if not (allow_fixture and descriptor["status"] == "STRUCTURAL_FIXTURE_ONLY"): + raise ClosedRenderError("RENDERER_LEGAL_CONTENT_NOT_APPROVED") + slots = descriptor["typed_slot_contract"].get("slot_definitions", []) + slot_names = _unique_names(slots, "name") + structural_names = descriptor["typed_slot_contract"].get("structural_slot_names") + if structural_names is not None and (not isinstance(structural_names, list) or set(structural_names) != slot_names or len(structural_names) != len(slot_names)): + raise ClosedRenderError("RENDERER_STRUCTURAL_SLOT_SET_MISMATCH") + for slot in slots: + if slot.get("type") not in ALLOWED_SLOT_TYPES: + raise ClosedRenderError("RENDERER_SLOT_TYPE_UNKNOWN") + if slot.get("cardinality") not in {"EXACTLY_ONE", "ZERO_OR_ONE", "ONE_OR_MORE"}: + raise ClosedRenderError("RENDERER_SLOT_CARDINALITY_UNKNOWN") + branches = descriptor["branch_rows"] + _unique_names(branches, "branch_id") + for branch in branches: + if branch.get("approval_status") != "APPROVED": + raise ClosedRenderError("RENDERER_BRANCH_NOT_APPROVED") + predicates = branch.get("predicates", []) + if not isinstance(predicates, list): + raise ClosedRenderError("RENDERER_PREDICATES_INVALID") + predicate_keys: set[tuple[str, str]] = set() + for predicate in predicates: + if predicate.get("op") not in ALLOWED_PREDICATE_OPS: + raise ClosedRenderError("RENDERER_PREDICATE_OP_UNKNOWN") + field = predicate.get("field") + if not isinstance(field, str) or not field: + raise ClosedRenderError("RENDERER_PREDICATE_FIELD_INVALID") + key = (field, predicate["op"]) + if key in predicate_keys: + raise ClosedRenderError("RENDERER_PREDICATE_DUPLICATE") + predicate_keys.add(key) + segments = branch.get("segments") + if not isinstance(segments, list) or not segments: + raise ClosedRenderError("RENDERER_SEGMENTS_EMPTY") + for segment in segments: + if segment.get("kind") == "LITERAL": + if set(segment) != {"kind", "value"}: + raise ClosedRenderError("RENDERER_LITERAL_SEGMENT_INVALID") + normalize_text(segment["value"]) + elif segment.get("kind") == "SLOT": + if set(segment) != {"kind", "name", "escape"}: + raise ClosedRenderError("RENDERER_SLOT_SEGMENT_INVALID") + if segment["name"] not in slot_names: + raise ClosedRenderError("RENDERER_UNKNOWN_TEMPLATE_SLOT") + if segment["escape"] not in {"PLAIN_TEXT", "MARKDOWN_TEXT"}: + raise ClosedRenderError("RENDERER_ESCAPE_POLICY_UNKNOWN") + else: + raise ClosedRenderError("RENDERER_SEGMENT_KIND_UNKNOWN") + + +def _matches(predicate: Mapping[str, Any], context: Mapping[str, Any]) -> bool: + field = predicate.get("field") + if not isinstance(field, str) or field not in context: + return False + observed, op = context[field], predicate.get("op") + if op == "EQ": + return observed == predicate.get("value") + if op == "IN": + return isinstance(predicate.get("values"), list) and observed in predicate["values"] + if op == "BOOL": + return isinstance(observed, bool) and observed is predicate.get("value") + return False + + +def select_branch(descriptor: Mapping[str, Any], context: Mapping[str, Any], *, allow_fixture: bool = False) -> Mapping[str, Any]: + validate_descriptor(descriptor, allow_fixture=allow_fixture) + matches = [row for row in descriptor["branch_rows"] if all(_matches(p, context) for p in row.get("predicates", []))] + if not matches: + raise ClosedRenderError(descriptor["closure"]["zero_match_issue_code"]) + if len(matches) != 1: + raise ClosedRenderError(descriptor["closure"]["multi_match_issue_code"]) + return matches[0] + + +def _escape(value: str, policy: str) -> str: + value = normalize_text(value) + if "{{" in value or "}}" in value: + raise ClosedRenderError("RENDERER_DANGLING_TEMPLATE_TOKEN") + if policy == "PLAIN_TEXT": + return value + if policy == "MARKDOWN_TEXT": + return re.sub(r"([\\`*_{}\[\]<>#|])", r"\\\1", value) + raise ClosedRenderError("RENDERER_ESCAPE_POLICY_UNKNOWN") + + +def escape_slot_value(value: str, policy: str) -> str: + """Public oracle for the exact inline PLAIN_TEXT/MARKDOWN_TEXT semantics.""" + return _escape(value, policy) + + +def _render_frozen(branch: Mapping[str, Any], definitions: Mapping[str, Any], slots: Mapping[str, Any]) -> str: + pieces: list[str] = [] + for segment in branch["segments"]: + if segment["kind"] == "LITERAL": + pieces.append(normalize_text(segment["value"])) + continue + definition, value = definitions[segment["name"]], slots.get(segment["name"]) + if value is None and definition["cardinality"] == "ZERO_OR_ONE": + continue + if isinstance(value, list): + if not value or any(not isinstance(item, str) for item in value): + raise ClosedRenderError("RENDERER_SLOT_LIST_INVALID") + pieces.append(", ".join(_escape(item, segment["escape"]) for item in value)) + else: + if value is not None and not isinstance(value, str): + raise ClosedRenderError("RENDERER_SLOT_TYPE_MISMATCH") + pieces.append(_escape(value, segment["escape"])) + return normalize_text("".join(pieces)) + + +def render_closed( + descriptor: Mapping[str, Any], branch_context: Mapping[str, Any], slots: Mapping[str, Any], + *, atom_type: str, allow_fixture: bool = False, +) -> dict[str, Any]: + branch = select_branch(descriptor, branch_context, allow_fixture=allow_fixture) + if atom_type not in set(descriptor["closed_ast_contract"]["allowed_atom_types"]): + raise ClosedRenderError("RENDERER_ATOM_TYPE_FORBIDDEN") + definitions = {row["name"]: row for row in descriptor["typed_slot_contract"]["slot_definitions"]} + if set(slots) - set(definitions): + raise ClosedRenderError("RENDERER_UNKNOWN_SLOT") + for name, definition in definitions.items(): + value = slots.get(name) + if value is None and definition["cardinality"] in {"EXACTLY_ONE", "ONE_OR_MORE"}: + raise ClosedRenderError("RENDERER_REQUIRED_SLOT_MISSING") + if isinstance(value, list) != (definition["cardinality"] == "ONE_OR_MORE") and value is not None: + raise ClosedRenderError("RENDERER_SLOT_CARDINALITY_MISMATCH") + output = _render_frozen(branch, definitions, slots) + detached = json.loads(canonical_json_bytes({"branch": branch, "definitions": definitions, "slots": slots})) + independent = _render_frozen(detached["branch"], detached["definitions"], detached["slots"]) + if output.encode("utf-8") != independent.encode("utf-8"): + raise ClosedRenderError("RENDERER_INDEPENDENT_RERENDER_MISMATCH") + if re.search(r"\{\{[^}]*\}\}", output): + raise ClosedRenderError("RENDERER_DANGLING_TEMPLATE_TOKEN") + return { + "schema_version": "stage2_s2_40_closed_render_result.v1", + "renderer_id": descriptor["renderer_id"], "branch_id": branch["branch_id"], + "atom_type": atom_type, "consumed_slot_names": sorted(slots), + "rendered_text": output, "rendered_sha256": sha256_bytes(output.encode("utf-8")), + "renderer_branch_sha256": sha256_bytes(canonical_json_bytes(branch)), + "slot_binding_sha256": sha256_bytes(canonical_json_bytes(dict(slots))), + "independent_rerender_sha256": sha256_bytes(independent.encode("utf-8")), + "normalization_version": descriptor["closed_ast_contract"]["normalization_version"], + } + + +def provisional_execution_eligible(atom: Mapping[str, Any]) -> bool: + return bool( + atom.get("proprietary_claim") is True and atom.get("performance_atom") is True + and atom.get("atomic_branch_provisional_execution_policy") == "ALLOW" + and atom.get("approved_authority_ref_is_valid") is True + and atom.get("dependent_on_constitutive_judgment") is False + and atom.get("renderer_id") not in {"R03", "R05", "R06"} + ) + + +__all__ = ["ClosedRenderError", "canonical_json_bytes", "escape_slot_value", "normalize_text", "provisional_execution_eligible", "render_closed", "select_branch", "sha256_bytes", "validate_descriptor"] diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/rendering/closed_renderer.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/rendering/closed_renderer.txt new file mode 100644 index 00000000..7e410db2 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/rendering/closed_renderer.txt @@ -0,0 +1,215 @@ +from __future__ import annotations + +"""Offline oracle for S2_40 closed rendering; contains no legal wording.""" + +from copy import deepcopy +import hashlib +import json +import re +import unicodedata +from typing import Any, Mapping, Sequence + + +ALLOWED_SLOT_TYPES = { + "STRING", "IDENTIFIER", "MONEY", "DATE", "OBJECT_REF", "PARTY_REF", "EXHIBIT_REF" +} +ALLOWED_PREDICATE_OPS = {"EQ", "IN", "BOOL"} + + +class ClosedRenderError(ValueError): + """Raised when a closed renderer contract cannot be applied exactly.""" + + +def normalize_text(value: str) -> str: + if not isinstance(value, str): + raise ClosedRenderError("RENDERER_SLOT_TYPE_MISMATCH") + normalized = unicodedata.normalize("NFC", value.replace("\r\n", "\n").replace("\r", "\n")) + if "\x00" in normalized: + raise ClosedRenderError("RENDERER_NUL_FORBIDDEN") + return normalized + + +def canonical_json_bytes(value: Any) -> bytes: + return (json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8") + + +def sha256_bytes(raw: bytes) -> str: + return hashlib.sha256(raw).hexdigest() + + +def _unique_names(rows: Sequence[Mapping[str, Any]], field: str) -> set[str]: + names = [row.get(field) for row in rows] + if any(not isinstance(name, str) or not name for name in names): + raise ClosedRenderError(f"RENDERER_{field.upper()}_INVALID") + if len(names) != len(set(names)): + raise ClosedRenderError(f"RENDERER_{field.upper()}_DUPLICATE") + return set(names) + + +def validate_descriptor(descriptor: Mapping[str, Any], *, allow_fixture: bool = False) -> None: + required = { + "schema_version", "renderer_id", "renderer_kind", "status", "execution_eligible", + "stage2_20_role", "stage2_40_role", "typed_slot_contract", "closed_ast_contract", + "branch_rows", "closure", "review", + } + if set(descriptor) != required: + raise ClosedRenderError("RENDERER_DESCRIPTOR_SHAPE_INVALID") + if not descriptor["execution_eligible"]: + raise ClosedRenderError("RENDERER_NOT_EXECUTION_ELIGIBLE") + if descriptor["status"] != "APPROVED_LEGAL_CONTENT": + if not (allow_fixture and descriptor["status"] == "STRUCTURAL_FIXTURE_ONLY"): + raise ClosedRenderError("RENDERER_LEGAL_CONTENT_NOT_APPROVED") + slots = descriptor["typed_slot_contract"].get("slot_definitions", []) + slot_names = _unique_names(slots, "name") + structural_names = descriptor["typed_slot_contract"].get("structural_slot_names") + if structural_names is not None and (not isinstance(structural_names, list) or set(structural_names) != slot_names or len(structural_names) != len(slot_names)): + raise ClosedRenderError("RENDERER_STRUCTURAL_SLOT_SET_MISMATCH") + for slot in slots: + if slot.get("type") not in ALLOWED_SLOT_TYPES: + raise ClosedRenderError("RENDERER_SLOT_TYPE_UNKNOWN") + if slot.get("cardinality") not in {"EXACTLY_ONE", "ZERO_OR_ONE", "ONE_OR_MORE"}: + raise ClosedRenderError("RENDERER_SLOT_CARDINALITY_UNKNOWN") + branches = descriptor["branch_rows"] + _unique_names(branches, "branch_id") + for branch in branches: + if branch.get("approval_status") != "APPROVED": + raise ClosedRenderError("RENDERER_BRANCH_NOT_APPROVED") + predicates = branch.get("predicates", []) + if not isinstance(predicates, list): + raise ClosedRenderError("RENDERER_PREDICATES_INVALID") + predicate_keys: set[tuple[str, str]] = set() + for predicate in predicates: + if predicate.get("op") not in ALLOWED_PREDICATE_OPS: + raise ClosedRenderError("RENDERER_PREDICATE_OP_UNKNOWN") + field = predicate.get("field") + if not isinstance(field, str) or not field: + raise ClosedRenderError("RENDERER_PREDICATE_FIELD_INVALID") + key = (field, predicate["op"]) + if key in predicate_keys: + raise ClosedRenderError("RENDERER_PREDICATE_DUPLICATE") + predicate_keys.add(key) + segments = branch.get("segments") + if not isinstance(segments, list) or not segments: + raise ClosedRenderError("RENDERER_SEGMENTS_EMPTY") + for segment in segments: + if segment.get("kind") == "LITERAL": + if set(segment) != {"kind", "value"}: + raise ClosedRenderError("RENDERER_LITERAL_SEGMENT_INVALID") + normalize_text(segment["value"]) + elif segment.get("kind") == "SLOT": + if set(segment) != {"kind", "name", "escape"}: + raise ClosedRenderError("RENDERER_SLOT_SEGMENT_INVALID") + if segment["name"] not in slot_names: + raise ClosedRenderError("RENDERER_UNKNOWN_TEMPLATE_SLOT") + if segment["escape"] not in {"PLAIN_TEXT", "MARKDOWN_TEXT"}: + raise ClosedRenderError("RENDERER_ESCAPE_POLICY_UNKNOWN") + else: + raise ClosedRenderError("RENDERER_SEGMENT_KIND_UNKNOWN") + + +def _matches(predicate: Mapping[str, Any], context: Mapping[str, Any]) -> bool: + field = predicate.get("field") + if not isinstance(field, str) or field not in context: + return False + observed, op = context[field], predicate.get("op") + if op == "EQ": + return observed == predicate.get("value") + if op == "IN": + return isinstance(predicate.get("values"), list) and observed in predicate["values"] + if op == "BOOL": + return isinstance(observed, bool) and observed is predicate.get("value") + return False + + +def select_branch(descriptor: Mapping[str, Any], context: Mapping[str, Any], *, allow_fixture: bool = False) -> Mapping[str, Any]: + validate_descriptor(descriptor, allow_fixture=allow_fixture) + matches = [row for row in descriptor["branch_rows"] if all(_matches(p, context) for p in row.get("predicates", []))] + if not matches: + raise ClosedRenderError(descriptor["closure"]["zero_match_issue_code"]) + if len(matches) != 1: + raise ClosedRenderError(descriptor["closure"]["multi_match_issue_code"]) + return matches[0] + + +def _escape(value: str, policy: str) -> str: + value = normalize_text(value) + if "{{" in value or "}}" in value: + raise ClosedRenderError("RENDERER_DANGLING_TEMPLATE_TOKEN") + if policy == "PLAIN_TEXT": + return value + if policy == "MARKDOWN_TEXT": + return re.sub(r"([\\`*_{}\[\]<>#|])", r"\\\1", value) + raise ClosedRenderError("RENDERER_ESCAPE_POLICY_UNKNOWN") + + +def escape_slot_value(value: str, policy: str) -> str: + """Public oracle for the exact inline PLAIN_TEXT/MARKDOWN_TEXT semantics.""" + return _escape(value, policy) + + +def _render_frozen(branch: Mapping[str, Any], definitions: Mapping[str, Any], slots: Mapping[str, Any]) -> str: + pieces: list[str] = [] + for segment in branch["segments"]: + if segment["kind"] == "LITERAL": + pieces.append(normalize_text(segment["value"])) + continue + definition, value = definitions[segment["name"]], slots.get(segment["name"]) + if value is None and definition["cardinality"] == "ZERO_OR_ONE": + continue + if isinstance(value, list): + if not value or any(not isinstance(item, str) for item in value): + raise ClosedRenderError("RENDERER_SLOT_LIST_INVALID") + pieces.append(", ".join(_escape(item, segment["escape"]) for item in value)) + else: + if value is not None and not isinstance(value, str): + raise ClosedRenderError("RENDERER_SLOT_TYPE_MISMATCH") + pieces.append(_escape(value, segment["escape"])) + return normalize_text("".join(pieces)) + + +def render_closed( + descriptor: Mapping[str, Any], branch_context: Mapping[str, Any], slots: Mapping[str, Any], + *, atom_type: str, allow_fixture: bool = False, +) -> dict[str, Any]: + branch = select_branch(descriptor, branch_context, allow_fixture=allow_fixture) + if atom_type not in set(descriptor["closed_ast_contract"]["allowed_atom_types"]): + raise ClosedRenderError("RENDERER_ATOM_TYPE_FORBIDDEN") + definitions = {row["name"]: row for row in descriptor["typed_slot_contract"]["slot_definitions"]} + if set(slots) - set(definitions): + raise ClosedRenderError("RENDERER_UNKNOWN_SLOT") + for name, definition in definitions.items(): + value = slots.get(name) + if value is None and definition["cardinality"] in {"EXACTLY_ONE", "ONE_OR_MORE"}: + raise ClosedRenderError("RENDERER_REQUIRED_SLOT_MISSING") + if isinstance(value, list) != (definition["cardinality"] == "ONE_OR_MORE") and value is not None: + raise ClosedRenderError("RENDERER_SLOT_CARDINALITY_MISMATCH") + output = _render_frozen(branch, definitions, slots) + detached = json.loads(canonical_json_bytes({"branch": branch, "definitions": definitions, "slots": slots})) + independent = _render_frozen(detached["branch"], detached["definitions"], detached["slots"]) + if output.encode("utf-8") != independent.encode("utf-8"): + raise ClosedRenderError("RENDERER_INDEPENDENT_RERENDER_MISMATCH") + if re.search(r"\{\{[^}]*\}\}", output): + raise ClosedRenderError("RENDERER_DANGLING_TEMPLATE_TOKEN") + return { + "schema_version": "stage2_s2_40_closed_render_result.v1", + "renderer_id": descriptor["renderer_id"], "branch_id": branch["branch_id"], + "atom_type": atom_type, "consumed_slot_names": sorted(slots), + "rendered_text": output, "rendered_sha256": sha256_bytes(output.encode("utf-8")), + "renderer_branch_sha256": sha256_bytes(canonical_json_bytes(branch)), + "slot_binding_sha256": sha256_bytes(canonical_json_bytes(dict(slots))), + "independent_rerender_sha256": sha256_bytes(independent.encode("utf-8")), + "normalization_version": descriptor["closed_ast_contract"]["normalization_version"], + } + + +def provisional_execution_eligible(atom: Mapping[str, Any]) -> bool: + return bool( + atom.get("proprietary_claim") is True and atom.get("performance_atom") is True + and atom.get("atomic_branch_provisional_execution_policy") == "ALLOW" + and atom.get("approved_authority_ref_is_valid") is True + and atom.get("dependent_on_constitutive_judgment") is False + and atom.get("renderer_id") not in {"R03", "R05", "R06"} + ) + + +__all__ = ["ClosedRenderError", "canonical_json_bytes", "escape_slot_value", "normalize_text", "provisional_execution_eligible", "render_closed", "select_branch", "sha256_bytes", "validate_descriptor"] diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.py index c5b2d013..386f61e6 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.py @@ -149,7 +149,7 @@ _RAW_VALUE_UNSET = object() # literal placeholders in the offline parity mirror and its unit tests. INLINE_USER_HASH = "{{__user_hash__}}" INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}" -EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" +EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" INLINE_REQUEST_PATH = "stage2_control/s2_00_request.json" INLINE_STAGE2_ASSET_ROOT = "Default_Agent/Stage_2_Clean" INLINE_STAGE2_RELEASE_PATH = ( diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.txt index c5b2d013..386f61e6 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_00_ingress.txt @@ -149,7 +149,7 @@ _RAW_VALUE_UNSET = object() # literal placeholders in the offline parity mirror and its unit tests. INLINE_USER_HASH = "{{__user_hash__}}" INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}" -EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" +EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" INLINE_REQUEST_PATH = "stage2_control/s2_00_request.json" INLINE_STAGE2_ASSET_ROOT = "Default_Agent/Stage_2_Clean" INLINE_STAGE2_RELEASE_PATH = ( diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.py index 44c8d80a..f61de598 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.py @@ -27,7 +27,7 @@ from typing import Any, Iterable, Mapping, Sequence WORKFLOW_ID = "S2_20" ALGORITHM_VERSION = "s2_20_relief_plan/1.0.0" -EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" +EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" WEAVIATE_MCP_URL = "https://weaviate.eroomai.com/mcp" MCP_PROTOCOL_VERSION = "2025-03-26" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.txt index 44c8d80a..f61de598 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_20_reduce.txt @@ -27,7 +27,7 @@ from typing import Any, Iterable, Mapping, Sequence WORKFLOW_ID = "S2_20" ALGORITHM_VERSION = "s2_20_relief_plan/1.0.0" -EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" +EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" WEAVIATE_MCP_URL = "https://weaviate.eroomai.com/mcp" MCP_PROTOCOL_VERSION = "2025-03-26" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_30_dispatch_planner.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_30_dispatch_planner.py index 50625f8a..f5d6af77 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_30_dispatch_planner.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_30_dispatch_planner.py @@ -18,7 +18,7 @@ import sys from typing import Any, Mapping -EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" +EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" MCP_PROTOCOL_VERSION = "2025-03-26" INLINE_USER_HASH = "{{__user_hash__}}" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_30_dispatch_planner.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_30_dispatch_planner.txt index 50625f8a..f5d6af77 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_30_dispatch_planner.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_30_dispatch_planner.txt @@ -18,7 +18,7 @@ import sys from typing import Any, Mapping -EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" +EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" MCP_PROTOCOL_VERSION = "2025-03-26" INLINE_USER_HASH = "{{__user_hash__}}" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_40_commit.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_40_commit.py new file mode 100644 index 00000000..c706c1f2 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_40_commit.py @@ -0,0 +1,3518 @@ +#!/usr/bin/env python3 +"""Release-bound deterministic S2_40 finalizer. + +This module is self-contained. It never imports workspace Python, calls +an LLM, scans directories, invokes a shell, or invents legal content. +All runtime reads and writes use the localdocs MCP binary contract. +""" + +from __future__ import annotations + +import base64 +import binascii +import contextlib +from datetime import datetime, timezone +import hashlib +import io +import itertools +import json +import re +import sys +import unicodedata +from pathlib import PurePosixPath +from typing import Any, Iterable, Mapping, Sequence + + +WORKFLOW_ID = "S2_40" +ALGORITHM_VERSION = "s2_40_finalizer/1.0.0" +EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" +LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" +MCP_PROTOCOL_VERSION = "2025-03-26" +INLINE_USER_HASH = "{{__user_hash__}}" +INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}" +REQUEST_PATH = "stage2_control/s2_40_request.json" +ASSET_ROOT = "Default_Agent/Stage_2_Clean" +AGENT_PATH = f"{ASSET_ROOT}/agent_scripts/Stage_2_S2_40.yml" +BINDING_PATH = f"{ASSET_ROOT}/deployment/stage2_code_executor_binding.yml" +INLINE_RECEIPT_PATH = f"{ASSET_ROOT}/manifest/s2_40_inline_code_receipt.json" +PARENT_RELEASE_PATH = f"{ASSET_ROOT}/manifest/stage2_release.json" +MODULE_MANIFEST_PATH = f"{ASSET_ROOT}/manifest/module_manifest.json" +AUTHORITY_RELEASE_REL = "manifest/authority_release.json" +CASE_TYPE_COVERAGE_REL = "manifest/case_type_coverage.json" +CASE_TYPE_REGISTRY_REL = "manifest/case_type_registry.yml" +CASE_TYPE_RULE_REGISTRY_REL = "manifest/case_type_rule_registry.yml" +INPUT_SCHEMA_RELS = ( + "schemas/ingress.schema.json", + "schemas/context.schema.json", + "schemas/domain_verdict.schema.json", + "schemas/s2_10.schema.json", + "schemas/relief_plan.schema.json", + "schemas/binding_retrieval.schema.json", + "schemas/calculation.schema.json", + "schemas/draft_atoms.schema.json", + "schemas/package.schema.json", + "schemas/review_status.schema.json", + "schemas/deployment.schema.json", +) +MAX_FILE_BYTES = 32 * 1024 * 1024 +MAX_TOTAL_BYTES = 256 * 1024 * 1024 +MAX_ARTIFACT_ROWS = 20000 +HEX64 = re.compile(r"^[a-f0-9]{64}$") +IDENT = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$") +PLACEHOLDER = re.compile(r"\{\{([A-Za-z][A-Za-z0-9_]*)\}\}") +ENTRY_ROUTES = {"TO_S2_40", "TO_S2_40_STATUS_ONLY"} +COMPILE_MODES = {"STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"} +TRANSITIONS = {"FREEZE", "RESUME"} +V_IDS = tuple(f"V{i:02d}" for i in range(1, 19)) +PART_FAMILIES = ("DRAFT_PART", "ISSUE_PATCH", "USAGE_PART", "WORKNOTE_PART") +PART_DIRECTORIES = { + "DRAFT_PART": "draft_parts", + "ISSUE_PATCH": "issue_patches", + "USAGE_PART": "usage_parts", + "WORKNOTE_PART": "worknote_parts", +} +PART_SCHEMA_REFS = { + "DRAFT_PART": "schemas/draft_atoms.schema.json#/$defs/draft_part", + "ISSUE_PATCH": "schemas/draft_atoms.schema.json#/$defs/issue_patch_part", + "USAGE_PART": "schemas/draft_atoms.schema.json#/$defs/usage_part", + "WORKNOTE_PART": "schemas/draft_atoms.schema.json#/$defs/worknote_part", +} +COMMON_PROVENANCE_FIELDS = { + "compile_mode", "parent_stage2_release_sha256", "s2_30_release_sha256", + "s2_30_agent_sha256", "s2_30_binding_sha256", "p00_prompt_sha256", + "p30_prompt_sha256", "s2_30_producer_contract_digest", +} +GROUP_PROVENANCE_FIELDS = COMMON_PROVENANCE_FIELDS | { + "p31_rule_and_pack_sha256", "p32_common_authority_sha256", + "s30_group_slice_sha256", +} +TRUSTED_REVIEW_ISSUER = "AGENTBACKEND_STAGE2_REVIEW_AUTHORITY" +TRUSTED_REVIEW_KEY_IDS = {"AGENTBACKEND_STAGE2_REVIEW_KEY_V1"} +TRUSTED_REVIEW_SIGNATURE_ALGORITHM = "AGENTBACKEND_TRUSTED_ATTESTATION_V1" +TRUSTED_REVIEW_ROLE = "KOREAN_LAWYER" +TRUSTED_REVIEW_QUALIFICATION = "QUALIFIED_KOREAN_LAWYER" +REQUIRED_LEGAL_GATES = { + "binding", "authority", "renderer_branch", "rule_sub_rule", + "review_policy", "case_type_coverage_137", "corpus", "law_value", + "calculator", "required_receipts", +} + + +class S240Error(Exception): + def __init__(self, code: str, message: str, *, details: Any | None = None) -> None: + super().__init__(message) + self.code = code + self.message = message + self.details = details + + def as_dict(self) -> dict[str, Any]: + row: dict[str, Any] = {"code": self.code, "message": self.message} + if self.details is not None: + row["details"] = self.details + return row + + +def nfc(value: str) -> str: + return unicodedata.normalize("NFC", value) + + +def no_duplicates(pairs: list[tuple[str, Any]]) -> dict[str, Any]: + result: dict[str, Any] = {} + for key, value in pairs: + if key in result: + raise S240Error("DUPLICATE_JSON_KEY", f"duplicate JSON key: {key}") + result[key] = value + return result + + +def load_json(raw: bytes, *, label: str) -> Any: + if len(raw) > MAX_FILE_BYTES: + raise S240Error("SOURCE_SIZE_LIMIT", f"file exceeds limit: {label}") + try: + text = raw.decode("utf-8", errors="strict") + return json.loads( + text, + object_pairs_hook=no_duplicates, + parse_constant=lambda token: (_ for _ in ()).throw( + S240Error("NON_FINITE_NUMBER", f"non-finite number: {token}") + ), + ) + except (UnicodeDecodeError, json.JSONDecodeError) as exc: + raise S240Error("JSON_PARSE_ERROR", f"strict JSON parse failed: {label}") from exc + + +def canonical_bytes(value: Any) -> bytes: + return ( + json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False) + + "\n" + ).encode("utf-8") + + +def canonical_markdown(value: str) -> bytes: + if not isinstance(value, str): + raise S240Error("MARKDOWN_TYPE", "markdown must be a string") + text = nfc(value.replace("\r\n", "\n").replace("\r", "\n")).lstrip("\ufeff") + if "\x00" in text: + raise S240Error("MARKDOWN_NUL", "markdown contains NUL") + return (text.rstrip("\n") + "\n").encode("utf-8") + + +def digest(value: Any) -> str: + payload = value if isinstance(value, bytes) else canonical_bytes(value) + return hashlib.sha256(payload).hexdigest() + + +def require_hex(value: Any, *, code: str) -> str: + if not isinstance(value, str) or HEX64.fullmatch(value) is None: + raise S240Error(code, "expected lower-case SHA-256") + return value + + +def require_ident(value: Any, *, code: str) -> str: + if not isinstance(value, str) or IDENT.fullmatch(value) is None: + raise S240Error(code, "invalid identifier") + return value + + +def require_text(value: Any, *, code: str) -> str: + if not isinstance(value, str) or not value.strip(): + raise S240Error(code, "non-empty text required") + return nfc(value) + + +def safe_path(value: Any, *, code: str = "PATH_INVALID") -> str: + if not isinstance(value, str) or not value or "\x00" in value: + raise S240Error(code, "path must be a non-empty string") + if value.startswith("/") or "\\" in value: + raise S240Error(code, "absolute or backslash path is forbidden") + normalized = PurePosixPath(value) + if any(part in {"", ".", ".."} for part in normalized.parts): + raise S240Error(code, "path traversal or ambiguous component") + return normalized.as_posix() + + +def join_path(*parts: str) -> str: + return safe_path("/".join(part.strip("/") for part in parts if part)) + + +def stable_id(prefix: str, *parts: Any) -> str: + return f"{prefix}-{digest([nfc(str(part)) for part in parts])[:24]}" + + +def utc_now() -> str: + return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") + + +def require_object(value: Any, *, code: str) -> dict[str, Any]: + if not isinstance(value, dict): + raise S240Error(code, "object required") + return value + + +def require_list(value: Any, *, code: str) -> list[Any]: + if not isinstance(value, list): + raise S240Error(code, "array required") + return value + + +def _parse_mcp_payload(raw: bytes, expected_id: int) -> Mapping[str, Any]: + candidates: list[Any] + if raw.lstrip().startswith(b"{"): + try: + candidates = [load_json(raw, label="mcp-json")] + except S240Error as exc: + if exc.code != "JSON_PARSE_ERROR": + raise + try: + text = raw.decode("utf-8", errors="strict") + decoder = json.JSONDecoder(object_pairs_hook=no_duplicates) + first, offset = decoder.raw_decode(text.lstrip()) + tail = text.lstrip()[offset:].strip() + candidates = [first] + while tail: + extra, offset = decoder.raw_decode(tail) + candidates.append(extra) + tail = tail[offset:].strip() + except (UnicodeDecodeError, json.JSONDecodeError) as parse_exc: + raise S240Error("MCP_JSON_EXTRA_DATA", "invalid concatenated MCP JSON") from parse_exc + else: + try: + text = raw.decode("utf-8", errors="strict") + except UnicodeDecodeError as exc: + raise S240Error("MCP_SSE_UTF8", "invalid MCP SSE UTF-8") from exc + events: list[bytes] = [] + data_lines: list[str] = [] + for line in text.replace("\r\n", "\n").split("\n"): + if not line: + if data_lines: + events.append("\n".join(data_lines).encode("utf-8")) + data_lines = [] + continue + if line.startswith((":", "event:", "id:", "retry:")): + continue + if not line.startswith("data:"): + raise S240Error("MCP_SSE_SHAPE", "unexpected SSE line") + data_lines.append(line[5:].lstrip()) + if data_lines: + events.append("\n".join(data_lines).encode("utf-8")) + candidates = [load_json(event, label="mcp-sse-event") for event in events] + matches = [row for row in candidates if isinstance(row, dict) and row.get("id") == expected_id] + if len(matches) != 1: + raise S240Error("MCP_RESPONSE_ID", "exactly one matching JSON-RPC result required") + row = matches[0] + if row.get("jsonrpc") != "2.0" or row.get("error") is not None: + raise S240Error("MCP_JSONRPC_ERROR", "MCP returned an invalid/error response") + if not isinstance(row.get("result"), dict): + raise S240Error("MCP_RESULT_SHAPE", "MCP result must be an object") + return row + + +def _tool_text(result: Mapping[str, Any], tool: str) -> str: + if result.get("isError") is True: + rendered = str(result.get("content", "")) + code = "LOCALDOCS_NOT_FOUND" if "not found" in rendered.lower() else "MCP_TOOL_ERROR" + raise S240Error(code, f"{tool} returned isError=true") + content = result.get("content") + if not isinstance(content, list) or len(content) != 1: + raise S240Error("MCP_CONTENT_CARDINALITY", "one content block required") + block = content[0] + if not isinstance(block, dict) or block.get("type") != "text" or not isinstance(block.get("text"), str): + raise S240Error("MCP_CONTENT_SHAPE", "one text block required") + return block["text"] + + +def _binary_from_text(text: str, path: str) -> bytes: + value = load_json(text.encode("utf-8"), label=path) + if isinstance(value, dict) and isinstance(value.get("results"), list): + rows = value["results"] + if len(rows) != 1 or not isinstance(rows[0], dict): + raise S240Error("LOCALDOCS_RESULT_CARDINALITY", "one binary result required") + value = rows[0].get("content", rows[0].get("text")) + if isinstance(value, str): + value = load_json(value.encode("utf-8"), label=path) + if not isinstance(value, dict) or not isinstance(value.get("content_base64"), str): + raise S240Error("LOCALDOCS_BINARY_ENVELOPE", "content_base64 is required") + try: + raw = base64.b64decode(value["content_base64"].encode("ascii"), validate=True) + except (UnicodeEncodeError, binascii.Error, ValueError) as exc: + raise S240Error("LOCALDOCS_BASE64", "strict base64 required") from exc + if value.get("byte_length", value.get("size", len(raw))) != len(raw): + raise S240Error("LOCALDOCS_LENGTH", f"byte length mismatch: {path}") + if value.get("sha256", digest(raw)) != digest(raw): + raise S240Error("LOCALDOCS_HASH", f"raw hash mismatch: {path}") + return raw + + +class McpClient: + def __init__(self, endpoint: str, name: str) -> None: + try: + import httpx # type: ignore + except ImportError as exc: + raise S240Error("HTTPX_UNAVAILABLE", "httpx==0.28.1 is required") from exc + self.endpoint = endpoint + self.name = name + self.client = httpx.Client(timeout=60) + self.headers = {"Content-Type": "application/json", "Accept": "application/json, text/event-stream"} + self.ids = itertools.count(10) + self.initialized = False + + def close(self) -> None: + self.client.close() + + def _post(self, body: Mapping[str, Any], expected_id: int | None) -> Mapping[str, Any] | None: + try: + response = self.client.post(self.endpoint, json=dict(body), headers=dict(self.headers)) + response.raise_for_status() + except Exception as exc: + raise S240Error("MCP_TRANSPORT", f"{self.name} transport failed") from exc + session = response.headers.get("mcp-session-id") + if session: + self.headers["mcp-session-id"] = session + if expected_id is None: + return None + return _parse_mcp_payload(bytes(response.content), expected_id) + + def initialize(self) -> None: + row = self._post( + { + "jsonrpc": "2.0", "id": 1, "method": "initialize", + "params": { + "protocolVersion": MCP_PROTOCOL_VERSION, + "capabilities": {}, + "clientInfo": { + "name": "liti-s2-40-inline", "version": "1.0.0", + "user_id": INLINE_USER_HASH, "workspace_id": INLINE_WORKSPACE_HASH, + }, + }, + }, + 1, + ) + if row is None or row["result"].get("protocolVersion") != MCP_PROTOCOL_VERSION: + raise S240Error("MCP_PROTOCOL", "MCP protocol negotiation failed") + self._post({"jsonrpc": "2.0", "method": "notifications/initialized"}, None) + self.initialized = True + + def call(self, tool: str, arguments: Mapping[str, Any]) -> Mapping[str, Any]: + if not self.initialized: + raise S240Error("MCP_NOT_INITIALIZED", "initialize before tools/call") + message_id = next(self.ids) + row = self._post( + {"jsonrpc": "2.0", "id": message_id, "method": "tools/call", "params": {"name": tool, "arguments": dict(arguments)}}, + message_id, + ) + if row is None: + raise S240Error("MCP_EMPTY", f"empty response: {tool}") + return row["result"] + + def read_binary(self, path: str) -> bytes: + safe = safe_path(path) + return _binary_from_text(_tool_text(self.call("read_binary_doc", {"doc_name": safe}), "read_binary_doc"), safe) + + def read_optional(self, path: str) -> bytes | None: + try: + return self.read_binary(path) + except S240Error as exc: + if exc.code == "LOCALDOCS_NOT_FOUND": + return None + raise + + def write_immutable(self, path: str, payload: bytes) -> str: + safe = safe_path(path) + existing = self.read_optional(safe) + if existing is not None: + if existing != payload: + raise S240Error("IMMUTABLE_CONFLICT", f"existing bytes differ: {safe}") + return digest(existing) + encoded = base64.b64encode(payload).decode("ascii") + _tool_text( + self.call("write_binary_file", {"path": safe, "content_base64": encoded, "overwrite": False}), + "write_binary_file", + ) + observed = self.read_binary(safe) + if observed != payload: + raise S240Error("WRITE_READBACK_MISMATCH", f"read-back differs: {safe}") + return digest(observed) + + def write_latest(self, path: str, payload: bytes, expected_previous: str | None) -> str: + safe = safe_path(path) + existing = self.read_optional(safe) + if expected_previous is None: + if existing is not None and existing != payload: + raise S240Error("LATEST_BARRIER_CONFLICT", "unexpected previous latest barrier") + else: + if existing is None or digest(existing) != expected_previous: + raise S240Error("LATEST_BARRIER_CAS", "previous latest barrier hash mismatch") + if existing == payload: + return digest(existing) + encoded = base64.b64encode(payload).decode("ascii") + _tool_text( + self.call("write_binary_file", {"path": safe, "content_base64": encoded, "overwrite": existing is not None}), + "write_binary_file", + ) + observed = self.read_binary(safe) + if observed != payload: + raise S240Error("LATEST_READBACK_MISMATCH", "latest barrier read-back mismatch") + return digest(observed) + + +REQUEST_KEYS = { + "schema_version", "request_id", "candidate_attempt_id", "run_binding_digest", + "user_identity_hash", "workspace_identity_hash", "stage2_run_root_ref", + "entry_route", "compile_mode", "requested_transition", + "expected_previous_run_status_sha256", "expected_candidate_content_digest", + "expected_ingress_status_sha256", "expected_s2_10_publish_status_sha256", + "expected_plan_publish_status_sha256", "expected_s2_30_publish_status_sha256", + "expected_s2_30_artifact_manifest_sha256", "expected_parent_stage2_release_sha256", + "expected_s2_40_agent_sha256", "expected_s2_40_executor_binding_sha256", + "expected_s2_40_inline_code_receipt_sha256", "host_cas_receipt_ref", + "host_cas_receipt_sha256", "detached_admission_receipt_ref", + "detached_admission_receipt_sha256", "outer_execution_receipt_target_ref", + "review_receipt_refs", +} + + +def validate_request(raw: bytes) -> dict[str, Any]: + value = load_json(raw, label=REQUEST_PATH) + if not isinstance(value, dict) or set(value) != REQUEST_KEYS: + keys = set(value) if isinstance(value, dict) else set() + raise S240Error("REQUEST_CLOSED_SHAPE", "request keys differ", details={"missing": sorted(REQUEST_KEYS - keys), "extra": sorted(keys - REQUEST_KEYS)}) + if value["schema_version"] != "stage2_s2_40_request.v1": + raise S240Error("REQUEST_VERSION", "unsupported request schema") + for key in ("request_id", "candidate_attempt_id"): + require_ident(value[key], code="REQUEST_IDENTIFIER") + run_digest = require_hex(value["run_binding_digest"], code="RUN_BINDING_DIGEST") + for key in ( + "user_identity_hash", "workspace_identity_hash", "expected_ingress_status_sha256", + "expected_parent_stage2_release_sha256", "expected_s2_40_agent_sha256", + "expected_s2_40_executor_binding_sha256", "expected_s2_40_inline_code_receipt_sha256", + "host_cas_receipt_sha256", "detached_admission_receipt_sha256", + ): + require_hex(value[key], code=f"REQUEST_{key.upper()}") + for key in ( + "expected_previous_run_status_sha256", "expected_candidate_content_digest", + "expected_s2_10_publish_status_sha256", "expected_plan_publish_status_sha256", + "expected_s2_30_publish_status_sha256", "expected_s2_30_artifact_manifest_sha256", + ): + if value[key] is not None: + require_hex(value[key], code=f"REQUEST_{key.upper()}") + if value["user_identity_hash"] != INLINE_USER_HASH or value["workspace_identity_hash"] != INLINE_WORKSPACE_HASH: + raise S240Error("REQUEST_IDENTITY", "request identity differs from AgentBackend substitution") + expected_root = f"stage2_runs/by-binding/{run_digest}" + if value["stage2_run_root_ref"] != expected_root: + raise S240Error("REQUEST_RUN_ROOT", "run root must derive from binding digest") + if value["entry_route"] not in ENTRY_ROUTES or value["requested_transition"] not in TRANSITIONS: + raise S240Error("REQUEST_ENUM", "unsupported entry route or transition") + receipt_refs = require_list(value["review_receipt_refs"], code="REQUEST_REVIEW_REFS") + if len(receipt_refs) > 64 or len(set(receipt_refs)) != len(receipt_refs): + raise S240Error("REQUEST_REVIEW_REFS", "review receipt refs must be unique and bounded") + for ref in receipt_refs: + safe_path(ref, code="REQUEST_REVIEW_REF_PATH") + expected_cas = f"stage2_control/host_cas/{run_digest}/S2_40/{value['candidate_attempt_id']}/{value['requested_transition']}.json" + if value["host_cas_receipt_ref"] != expected_cas: + raise S240Error("REQUEST_CAS_PATH", "host CAS path mismatch") + if value["outer_execution_receipt_target_ref"] != f"{expected_root}/control/s2_40_outer_execution_receipt.json": + raise S240Error("REQUEST_OUTER_RECEIPT_PATH", "outer receipt target mismatch") + status_only = value["entry_route"] == "TO_S2_40_STATUS_ONLY" + upstream_keys = ( + "expected_s2_10_publish_status_sha256", "expected_plan_publish_status_sha256", + "expected_s2_30_publish_status_sha256", "expected_s2_30_artifact_manifest_sha256", + ) + if status_only: + if value["compile_mode"] is not None or value["requested_transition"] != "FREEZE": + raise S240Error("REQUEST_STATUS_ONLY_MODE", "status-only requires null mode and FREEZE") + if any(value[key] is not None for key in upstream_keys) or value["expected_candidate_content_digest"] is not None or receipt_refs: + raise S240Error("REQUEST_STATUS_ONLY_SCOPE", "status-only forbids normal input and review refs") + else: + if value["compile_mode"] not in COMPILE_MODES or any(value[key] is None for key in upstream_keys): + raise S240Error("REQUEST_NORMAL_SCOPE", "normal route requires mode and all upstream hashes") + if value["requested_transition"] == "FREEZE": + if value["expected_candidate_content_digest"] is not None: + raise S240Error("REQUEST_FREEZE_DIGEST", "FREEZE must not supply candidate digest") + if value["expected_previous_run_status_sha256"] is not None or receipt_refs: + raise S240Error("REQUEST_FREEZE_SCOPE", "FREEZE forbids previous status and review receipts") + if value["requested_transition"] == "RESUME": + if value["expected_candidate_content_digest"] is None or value["expected_previous_run_status_sha256"] is None: + raise S240Error("REQUEST_RESUME_SCOPE", "RESUME requires candidate and previous status digests") + return value + + +def read_bound_json(client: McpClient, path: str, expected_sha256: str | None = None) -> tuple[dict[str, Any], bytes]: + raw_a = client.read_binary(path) + if expected_sha256 is not None and digest(raw_a) != expected_sha256: + raise S240Error("BOUND_HASH_MISMATCH", f"raw hash mismatch: {path}") + value = require_object(load_json(raw_a, label=path), code="BOUND_OBJECT") + raw_b = client.read_binary(path) + if raw_b != raw_a: + raise S240Error("TOCTOU_INPUT_CHANGED", f"input changed between reads: {path}") + return value, raw_a + + +def read_release_bound_jsons( + client: McpClient, relative_paths: Sequence[str], +) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], list[dict[str, Any]]]: + """Read exact module-manifest members; directory discovery is never used.""" + parent_raw = client.read_binary(PARENT_RELEASE_PATH) + if digest(parent_raw) != EXPECTED_STAGE2_RELEASE_SHA256: + raise S240Error("BOUND_PARENT_DRIFT", "parent release differs from inline constant") + parent = require_object(load_json(parent_raw, label=PARENT_RELEASE_PATH), code="BOUND_PARENT_OBJECT") + require_self_hash(parent, "release_digest", code="BOUND_PARENT_SELF_HASH") + module_ref = require_object(parent.get("module_manifest_ref"), code="BOUND_MODULE_REF") + module_raw = client.read_binary(MODULE_MANIFEST_PATH) + if digest(module_raw) != require_hex(module_ref.get("sha256"), code="BOUND_MODULE_HASH"): + raise S240Error("BOUND_MODULE_HASH", "module manifest differs from parent binding") + module = require_object(load_json(module_raw, label=MODULE_MANIFEST_PATH), code="BOUND_MODULE_OBJECT") + require_self_hash(module, "manifest_digest", code="BOUND_MODULE_SELF_HASH") + rows = require_list(module.get("modules"), code="BOUND_MODULE_ROWS") + values: dict[str, dict[str, Any]] = {} + raws: dict[str, bytes] = {} + source_rows: list[dict[str, Any]] = [] + for relative in relative_paths: + relative = safe_path(relative, code="BOUND_MEMBER_PATH") + matches = [row for row in rows if isinstance(row, dict) and row.get("path") == relative] + if len(matches) != 1: + raise S240Error("BOUND_MEMBER_CARDINALITY", f"release member must be exact-one: {relative}") + member = matches[0] + expected = require_hex(member.get("sha256"), code="BOUND_MEMBER_HASH") + raw = client.read_binary(join_path(ASSET_ROOT, relative)) + if digest(raw) != expected or member.get("size_bytes") != len(raw): + raise S240Error("BOUND_MEMBER_DRIFT", f"release member bytes differ: {relative}") + value = require_object(load_json(raw, label=relative), code="BOUND_MEMBER_OBJECT") + values[relative] = value + raws[relative] = raw + source_rows.append({"path": relative, "sha256": expected, "size_bytes": len(raw)}) + return values, raws, sorted(source_rows, key=lambda row: row["path"]) + + +def json_pointer(document: Any, fragment: str) -> Any: + if fragment in {"", "#"}: + return document + pointer = fragment[1:] if fragment.startswith("#") else fragment + if not pointer.startswith("/"): + raise S240Error("SCHEMA_POINTER", f"unsupported JSON pointer: {fragment}") + current = document + for token in pointer[1:].split("/"): + token = token.replace("~1", "/").replace("~0", "~") + if isinstance(current, dict) and token in current: + current = current[token] + elif isinstance(current, list) and token.isdigit() and int(token) < len(current): + current = current[int(token)] + else: + raise S240Error("SCHEMA_POINTER", f"unresolvable JSON pointer: {fragment}") + return current + + +def resolve_schema_ref( + ref: str, current_path: str, store: Mapping[str, Mapping[str, Any]], +) -> tuple[Mapping[str, Any], str]: + if "#" in ref: + file_ref, fragment = ref.split("#", 1) + fragment = "#" + fragment + else: + file_ref, fragment = ref, "#" + if file_ref: + if file_ref.startswith("schemas/"): + target_path = safe_path(file_ref, code="SCHEMA_REF_PATH") + else: + target_path = safe_path( + str(PurePosixPath(current_path).parent / file_ref), code="SCHEMA_REF_PATH", + ) + else: + target_path = current_path + target_document = store.get(target_path) + if not isinstance(target_document, dict): + raise S240Error("SCHEMA_REF_UNBOUND", f"schema is not release-bound: {target_path}") + target = json_pointer(target_document, fragment) + return require_object(target, code="SCHEMA_REF_TARGET"), target_path + + +def schema_errors( + value: Any, + schema: Mapping[str, Any], + current_path: str, + store: Mapping[str, Mapping[str, Any]], + *, + location: str = "$", + depth: int = 0, +) -> list[str]: + """Deterministic JSON-Schema subset covering every keyword used by Stage 2 input roots.""" + if depth > 160: + return [f"{location}:schema recursion limit"] + if "$ref" in schema: + target, target_path = resolve_schema_ref(str(schema["$ref"]), current_path, store) + return schema_errors(value, target, target_path, store, location=location, depth=depth + 1) + errors: list[str] = [] + if "const" in schema and value != schema["const"]: + errors.append(f"{location}:const") + if "enum" in schema and value not in schema["enum"]: + errors.append(f"{location}:enum") + expected_type = schema.get("type") + allowed_types = [expected_type] if isinstance(expected_type, str) else expected_type + if isinstance(allowed_types, list): + def type_ok(name: str) -> bool: + return { + "object": isinstance(value, dict), + "array": isinstance(value, list), + "string": isinstance(value, str), + "integer": isinstance(value, int) and not isinstance(value, bool), + "number": isinstance(value, (int, float)) and not isinstance(value, bool), + "boolean": isinstance(value, bool), + "null": value is None, + }.get(name, True) + if not any(type_ok(str(name)) for name in allowed_types): + return errors + [f"{location}:type"] + if isinstance(value, dict): + required = schema.get("required", []) + if isinstance(required, list): + errors.extend(f"{location}.{key}:required" for key in required if key not in value) + properties = schema.get("properties", {}) + if isinstance(properties, dict): + for key, child in properties.items(): + if key in value and isinstance(child, dict): + errors.extend(schema_errors(value[key], child, current_path, store, location=f"{location}.{key}", depth=depth + 1)) + if schema.get("additionalProperties") is False: + errors.extend(f"{location}.{key}:additional" for key in value if key not in properties) + if isinstance(schema.get("minProperties"), int) and len(value) < schema["minProperties"]: + errors.append(f"{location}:minProperties") + if isinstance(value, list): + if isinstance(schema.get("minItems"), int) and len(value) < schema["minItems"]: + errors.append(f"{location}:minItems") + if isinstance(schema.get("maxItems"), int) and len(value) > schema["maxItems"]: + errors.append(f"{location}:maxItems") + if schema.get("uniqueItems") is True: + serialized = [canonical_bytes(item) for item in value] + if len(serialized) != len(set(serialized)): + errors.append(f"{location}:uniqueItems") + prefix = schema.get("prefixItems") + if isinstance(prefix, list): + for index, child in enumerate(prefix): + if index < len(value) and isinstance(child, dict): + errors.extend(schema_errors(value[index], child, current_path, store, location=f"{location}[{index}]", depth=depth + 1)) + if schema.get("items") is False and len(value) > len(prefix): + errors.append(f"{location}:additionalItems") + elif isinstance(schema.get("items"), dict): + for index, item in enumerate(value): + errors.extend(schema_errors(item, schema["items"], current_path, store, location=f"{location}[{index}]", depth=depth + 1)) + contains = schema.get("contains") + if isinstance(contains, dict) and not any(not schema_errors(item, contains, current_path, store, location=location, depth=depth + 1) for item in value): + errors.append(f"{location}:contains") + if isinstance(value, str): + if isinstance(schema.get("minLength"), int) and len(value) < schema["minLength"]: + errors.append(f"{location}:minLength") + if isinstance(schema.get("maxLength"), int) and len(value) > schema["maxLength"]: + errors.append(f"{location}:maxLength") + if isinstance(schema.get("pattern"), str) and re.search(schema["pattern"], value) is None: + errors.append(f"{location}:pattern") + if isinstance(value, (int, float)) and not isinstance(value, bool): + if isinstance(schema.get("minimum"), (int, float)) and value < schema["minimum"]: + errors.append(f"{location}:minimum") + if isinstance(schema.get("maximum"), (int, float)) and value > schema["maximum"]: + errors.append(f"{location}:maximum") + for child in schema.get("allOf", []) if isinstance(schema.get("allOf"), list) else []: + if isinstance(child, dict): + errors.extend(schema_errors(value, child, current_path, store, location=location, depth=depth + 1)) + any_of = schema.get("anyOf") + if isinstance(any_of, list) and not any(isinstance(child, dict) and not schema_errors(value, child, current_path, store, location=location, depth=depth + 1) for child in any_of): + errors.append(f"{location}:anyOf") + one_of = schema.get("oneOf") + if isinstance(one_of, list) and sum(1 for child in one_of if isinstance(child, dict) and not schema_errors(value, child, current_path, store, location=location, depth=depth + 1)) != 1: + errors.append(f"{location}:oneOf") + forbidden = schema.get("not") + if isinstance(forbidden, dict) and not schema_errors(value, forbidden, current_path, store, location=location, depth=depth + 1): + errors.append(f"{location}:not") + condition = schema.get("if") + if isinstance(condition, dict): + branch_name = "then" if not schema_errors(value, condition, current_path, store, location=location, depth=depth + 1) else "else" + branch = schema.get(branch_name) + if isinstance(branch, dict): + errors.extend(schema_errors(value, branch, current_path, store, location=location, depth=depth + 1)) + return errors[:96] + + +def validate_schema_instance( + value: Any, schema_ref: str, store: Mapping[str, Mapping[str, Any]], *, code: str, +) -> None: + target, path = resolve_schema_ref(schema_ref, "schemas/ingress.schema.json", store) + errors = schema_errors(value, target, path, store) + if errors: + raise S240Error(code, f"schema validation failed: {schema_ref}", details=errors[:16]) + + +def preflight(client: McpClient, request: Mapping[str, Any]) -> str: + if request["expected_parent_stage2_release_sha256"] != EXPECTED_STAGE2_RELEASE_SHA256: + raise S240Error("PARENT_CONSTANT_REQUEST", "request parent hash differs from inline constant") + fixed = ( + (PARENT_RELEASE_PATH, request["expected_parent_stage2_release_sha256"]), + (AGENT_PATH, request["expected_s2_40_agent_sha256"]), + (BINDING_PATH, request["expected_s2_40_executor_binding_sha256"]), + (INLINE_RECEIPT_PATH, request["expected_s2_40_inline_code_receipt_sha256"]), + (request["host_cas_receipt_ref"], request["host_cas_receipt_sha256"]), + (request["detached_admission_receipt_ref"], request["detached_admission_receipt_sha256"]), + ) + snapshot_rows: list[dict[str, Any]] = [] + fixed_raw: dict[str, bytes] = {} + for path, expected in fixed: + raw = client.read_binary(path) + if digest(raw) != expected: + raise S240Error("PREFLIGHT_HASH", f"preflight hash mismatch: {path}") + fixed_raw[path] = raw + snapshot_rows.append({"path": path, "sha256": expected, "size": len(raw)}) + parent = require_object(load_json(fixed_raw[PARENT_RELEASE_PATH], label=PARENT_RELEASE_PATH), code="PARENT_RELEASE_OBJECT") + require_self_hash(parent, "release_digest", code="PARENT_RELEASE_SELF_HASH") + module_ref = require_object(parent.get("module_manifest_ref"), code="PARENT_MODULE_REF") + if module_ref.get("path") != "manifest/module_manifest.json" or module_ref.get("binding_status") != "BOUND": + raise S240Error("PARENT_MODULE_REF", "parent does not bind canonical module manifest") + module_raw = client.read_binary(MODULE_MANIFEST_PATH) + if digest(module_raw) != require_hex(module_ref.get("sha256"), code="PARENT_MODULE_HASH"): + raise S240Error("PARENT_MODULE_HASH", "module manifest raw hash differs from parent") + module = require_object(load_json(module_raw, label=MODULE_MANIFEST_PATH), code="MODULE_MANIFEST_OBJECT") + require_self_hash(module, "manifest_digest", code="MODULE_MANIFEST_SELF_HASH") + modules = require_list(module.get("modules"), code="MODULE_ROWS") + workflow_rows = [row for row in modules if isinstance(row, dict) and row.get("module_id") == "WF-S2_40"] + if len(workflow_rows) != 1 or workflow_rows[0].get("path") != "workflows/S2_40_final_review_render_and_commit.yml": + raise S240Error("S240_MODULE_MEMBERSHIP", "exact S2_40 workflow module membership missing") + + inline_receipt = require_object(load_json(fixed_raw[INLINE_RECEIPT_PATH], label=INLINE_RECEIPT_PATH), code="INLINE_RECEIPT_OBJECT") + if (inline_receipt.get("schema_version") != "stage2_s2_40_inline_code_receipt.v1" + or inline_receipt.get("parity_status") != "PASS" + or inline_receipt.get("expected_parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or inline_receipt.get("deployment_projection", {}).get("sha256") != request["expected_s2_40_agent_sha256"] + or inline_receipt.get("deployment_projection", {}).get("path") != AGENT_PATH): + raise S240Error("INLINE_RECEIPT_MEMBERSHIP", "inline receipt does not bind parent and actual Agent") + binding_text = fixed_raw[BINDING_PATH].decode("utf-8", errors="strict") + required_binding_literals = ( + "stage_id: S2_40", "binding_id: S2-BINDING-S2_40-CODE-EXECUTOR-V1", + "path: agent_scripts/Stage_2_S2_40.yml", request["expected_s2_40_agent_sha256"], + "path: manifest/s2_40_inline_code_receipt.json", request["expected_s2_40_inline_code_receipt_sha256"], + "path: manifest/stage2_release.json", EXPECTED_STAGE2_RELEASE_SHA256, + ) + if any(literal not in binding_text for literal in required_binding_literals): + raise S240Error("BINDING_MEMBERSHIP", "binding does not bind exact S2_40 Agent/parent/receipt") + + admission = require_object(load_json(fixed_raw[request["detached_admission_receipt_ref"]], label="detached-admission"), code="ADMISSION_OBJECT") + admitted_status = "PRODUCTION_ADMITTED" if request.get("compile_mode") == "PRODUCTION" else "CANARY_ADMITTED" + if (admission.get("schema_version") != "stage2_deterministic_admission_receipt.v1" + or admission.get("parent_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or admission.get("executor_binding_sha256") != request["expected_s2_40_executor_binding_sha256"] + or admission.get("admission_status") not in {admitted_status, "PRODUCTION_ADMITTED"} + or admission.get("signature_verification_status") != "BACKEND_VERIFIED" + or admission.get("external_trust_verified") is not True + or not isinstance(admission.get("signature"), str) + or admission.get("signature", "").startswith("PENDING")): + raise S240Error("DETACHED_ADMISSION_NOT_TRUSTED", "release-bound external admission is absent or invalid") + signed_admission = { + key: value for key, value in admission.items() + if key not in {"signature", "signature_verification_status", "signed_payload_sha256"} + } + if (admission.get("signed_payload_sha256") != digest(signed_admission) + or HEX64.fullmatch(str(admission.get("backend_capability_receipt_sha256", ""))) is None): + raise S240Error("DETACHED_ADMISSION_SIGNATURE_SCOPE", "admission signed payload scope/hash differs") + receipt_matches = [row for row in admission.get("stage_receipts", []) if isinstance(row, dict) + and row.get("path") == "manifest/s2_40_inline_code_receipt.json" + and row.get("sha256") == request["expected_s2_40_inline_code_receipt_sha256"]] + if len(receipt_matches) != 1 or "S2_40" not in admission.get("present_deterministic_stage_ids", []): + raise S240Error("DETACHED_ADMISSION_S240", "admission does not bind exact S2_40 receipt") + + cas = require_object(load_json(fixed_raw[request["host_cas_receipt_ref"]], label="host-cas"), code="HOST_CAS_OBJECT") + if (cas.get("schema_version") != "stage2_s2_40_host_cas_receipt.v1" + or cas.get("run_binding_digest") != request["run_binding_digest"] + or cas.get("stage_id") != "S2_40" + or cas.get("candidate_attempt_id") != request["candidate_attempt_id"] + or cas.get("requested_transition") != request["requested_transition"] + or cas.get("expected_previous_run_status_sha256") != request["expected_previous_run_status_sha256"] + or cas.get("lease_status") != "ACQUIRED" + or HEX64.fullmatch(str(cas.get("signature_attestation", ""))) is None): + raise S240Error("HOST_CAS_NOT_BOUND", "host CAS receipt does not bind request transition") + try: + issued = datetime.fromisoformat(str(cas.get("issued_at")).replace("Z", "+00:00")) + expires = datetime.fromisoformat(str(cas.get("expires_at")).replace("Z", "+00:00")) + now = datetime.now(timezone.utc) + if issued.tzinfo is None or expires.tzinfo is None or issued > now or expires <= now or expires <= issued: + raise S240Error("HOST_CAS_TIME", "host CAS lease is not currently valid") + except (TypeError, ValueError) as exc: + raise S240Error("HOST_CAS_TIME", "host CAS timestamps are invalid") from exc + snapshot_rows.append({"path": MODULE_MANIFEST_PATH, "sha256": digest(module_raw), "size": len(module_raw)}) + return digest(snapshot_rows) + + +def load_output_schema_store(client: McpClient) -> dict[str, Mapping[str, Any]]: + values, _, _ = read_release_bound_jsons(client, INPUT_SCHEMA_RELS) + return {path: value for path, value in values.items() if path.startswith("schemas/")} + + +def write_terminal_status( + client: McpClient, + request: Mapping[str, Any], + *, + workflow_phase: str, + route: str, + candidate_content_digest: str | None, + run_technical_status: str, + artifact_technical_status: str, + legal_readiness: str, + validation_report_sha256: str | None = None, + review_subject_digest: str | None = None, + review_receipt_sha256s: Sequence[str] = (), + stage2_package_sha256: str | None = None, + artifact_set_digest: str | None = None, + commit_intent_sha256: str | None = None, + commit_result_sha256: str | None = None, + emit_status_event: bool = True, + schema_store: Mapping[str, Mapping[str, Any]] | None = None, +) -> dict[str, Any]: + """Write one immutable transition event and the latest barrier last.""" + output_schemas = dict(schema_store) if schema_store is not None else load_output_schema_store(client) + root = request["stage2_run_root_ref"] + event_core = { + "schema_version": "stage2_s2_40_status_event.v1", + "writer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "workflow_phase": workflow_phase, "route": route, + "candidate_content_digest": candidate_content_digest, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "request_sha256": require_hex(request.get("_request_sha256"), code="REQUEST_RAW_HASH"), + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + } + event_raw_hash: str | None = None + if emit_status_event: + event = {**event_core, "event_digest": digest(event_core)} + validate_schema_instance( + event, "schemas/review_status.schema.json#/$defs/status_event", + output_schemas, code="GENERATED_STATUS_EVENT_SCHEMA", + ) + event_payload = canonical_bytes(event) + event_path = join_path(root, "control/status_events", f"{event['event_digest']}.json") + event_raw_hash = client.write_immutable(event_path, event_payload) + status = { + "schema_version": "stage2_s2_40_run_status.v1", "writer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "entry_route": request["entry_route"], "compile_mode": request["compile_mode"], + "workflow_phase": workflow_phase, "route": route, + "candidate_content_digest": candidate_content_digest, + "run_technical_status": run_technical_status, + "artifact_technical_status": artifact_technical_status, + "legal_readiness": legal_readiness, + "validation_report_sha256": validation_report_sha256, + "review_subject_digest": review_subject_digest, + "review_receipt_sha256s": sorted(set(review_receipt_sha256s)), + "stage2_package_sha256": stage2_package_sha256, + "artifact_set_digest": artifact_set_digest, + "commit_intent_sha256": commit_intent_sha256, + "commit_result_sha256": commit_result_sha256, + "request_sha256": request["_request_sha256"], + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + "outer_execution_receipt_sha256": None, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "status_event_sha256": event_raw_hash, + "barrier_written_last": True, "readback_verified": True, + } + validate_schema_instance( + status, "schemas/review_status.schema.json#/$defs/run_status", + output_schemas, code="GENERATED_RUN_STATUS_SCHEMA", + ) + status_payload = canonical_bytes(status) + status_path = join_path(root, "control/run_status.json") + status_hash = client.write_latest( + status_path, status_payload, request["expected_previous_run_status_sha256"], + ) + return {"status": status, "status_sha256": status_hash, "status_path": status_path} + + +def ingress_schema_ref(path: str) -> str: + exact = { + "ingress/stage1_input_manifest.json": "schemas/ingress.schema.json#/$defs/stage1_input_manifest", + "ingress/intake_report.json": "schemas/ingress.schema.json#/$defs/intake_report", + "ingress/technical_diagnostic.json": "schemas/ingress.schema.json#/$defs/technical_diagnostic", + "context/case_context.json": "schemas/context.schema.json#/$defs/case_context", + "context/evidence_inventory.json": "schemas/context.schema.json#/$defs/evidence_inventory", + "context/object_registry.json": "schemas/context.schema.json#/$defs/object_registry", + "context/party_and_title_context.json": "schemas/context.schema.json#/$defs/party_and_title_context", + "context/slot_crosswalk.json": "schemas/context.schema.json#/$defs/slot_crosswalk", + "context/cluster_plan.json": "schemas/context.schema.json#/$defs/cluster_plan", + "context/bundle_plan.json": "schemas/context.schema.json#/$defs/bundle_plan", + "review/issue_ledger.base.json": "schemas/review_status.schema.json#/$defs/issue_ledger_base", + } + if path in exact: + return exact[path] + if re.fullmatch(r"context/cluster_slices/[A-Za-z0-9][A-Za-z0-9._:-]{0,255}\.json", path): + return "schemas/context.schema.json#/$defs/cluster_slice" + raise S240Error("INGRESS_ARTIFACT_PATH", f"unrecognized ingress artifact path: {path}") + + +def hydrate_ingress_barrier_artifacts( + client: McpClient, + root: str, + ingress: Mapping[str, Any], + schema_store: Mapping[str, Mapping[str, Any]], + *, + exact_paths: set[str] | None = None, +) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], list[dict[str, Any]]]: + barrier = require_object(ingress.get("output_barrier"), code="INGRESS_OUTPUT_BARRIER") + rows = require_list(barrier.get("artifacts"), code="INGRESS_OUTPUT_ROWS") + if barrier.get("artifact_set_digest") != digest(rows): + raise S240Error("INGRESS_OUTPUT_SET_DIGEST", "ingress artifact-set digest differs") + paths = [safe_path(row.get("path"), code="INGRESS_OUTPUT_PATH") for row in rows if isinstance(row, dict)] + if len(paths) != len(rows) or len(paths) != len(set(paths)) or paths != sorted(paths): + raise S240Error("INGRESS_OUTPUT_SET", "ingress artifact rows must be unique and sorted") + if exact_paths is not None and set(paths) != exact_paths: + raise S240Error("INGRESS_OUTPUT_EXACT_SET", "ingress barrier does not bind the exact expected paths") + values: dict[str, dict[str, Any]] = {} + raws: dict[str, bytes] = {} + normalized_rows: list[dict[str, Any]] = [] + for row in rows: + row = require_object(row, code="INGRESS_OUTPUT_ROW") + path = safe_path(row.get("path"), code="INGRESS_OUTPUT_PATH") + if row.get("logical_artifact_id") != path: + raise S240Error("INGRESS_OUTPUT_LOGICAL_ID", "logical artifact id must equal canonical path") + schema_ref = ingress_schema_ref(path) + schema_path = schema_ref.split("#", 1)[0] + if row.get("schema_id") != schema_store[schema_path].get("$id"): + raise S240Error("INGRESS_OUTPUT_SCHEMA_ID", f"schema id differs: {path}") + raw_a = client.read_binary(join_path(root, path)) + raw_b = client.read_binary(join_path(root, path)) + if raw_a != raw_b: + raise S240Error("INGRESS_OUTPUT_TOCTOU", f"ingress artifact changed between reads: {path}") + if digest(raw_a) != require_hex(row.get("raw_sha256"), code="INGRESS_OUTPUT_HASH"): + raise S240Error("INGRESS_OUTPUT_HASH", f"ingress artifact hash differs: {path}") + if row.get("byte_length", len(raw_a)) != len(raw_a): + raise S240Error("INGRESS_OUTPUT_SIZE", f"ingress artifact size differs: {path}") + value = require_object(load_json(raw_a, label=path), code="INGRESS_OUTPUT_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="INGRESS_OUTPUT_SCHEMA") + values[path] = value + raws[path] = raw_a + normalized_rows.append({ + "path": path, "raw_sha256": digest(raw_a), "byte_length": len(raw_a), + "schema_id": row.get("schema_id"), "schema_ref": schema_ref, + }) + return values, raws, normalized_rows + + +def status_only(client: McpClient, request: Mapping[str, Any], preflight_digest: str) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + schema_values, _, schema_rows = read_release_bound_jsons(client, INPUT_SCHEMA_RELS) + schema_store: dict[str, Mapping[str, Any]] = dict(schema_values) + rels_and_refs = ( + ("ingress/ingress_status.json", "schemas/ingress.schema.json#/$defs/ingress_status"), + ("ingress/technical_diagnostic.json", "schemas/ingress.schema.json#/$defs/technical_diagnostic"), + ("ingress/stage1_input_manifest.json", "schemas/ingress.schema.json#/$defs/stage1_input_manifest"), + ("ingress/intake_report.json", "schemas/ingress.schema.json#/$defs/intake_report"), + ("review/issue_ledger.base.json", "schemas/review_status.schema.json#/$defs/issue_ledger_base"), + ) + rows: list[dict[str, Any]] = [] + values: dict[str, dict[str, Any]] = {} + for rel, schema_ref in rels_and_refs: + path = join_path(root, rel) + raw = client.read_binary(path) + if rel == "ingress/ingress_status.json" and digest(raw) != request["expected_ingress_status_sha256"]: + raise S240Error("STATUS_ONLY_INGRESS_HASH", "ingress status hash mismatch") + value = require_object(load_json(raw, label=path), code="STATUS_ONLY_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="STATUS_ONLY_SCHEMA") + values[rel] = value + rows.append({ + "path": rel, "sha256": digest(raw), "size": len(raw), + "schema_ref": schema_ref, "schema_version": value.get("schema_version"), + }) + ingress = values["ingress/ingress_status.json"] + diagnostic = values["ingress/technical_diagnostic.json"] + manifest = values["ingress/stage1_input_manifest.json"] + intake = values["ingress/intake_report.json"] + ledger = values["review/issue_ledger.base.json"] + run_receipt = require_object(ingress.get("run_binding_receipt"), code="STATUS_ONLY_RUN_RECEIPT") + run_id = ingress.get("run_id") + input_set_digest = manifest.get("input_set_digest") + if ( + ingress.get("route") != "TO_S2_40_STATUS_ONLY" + or require_object(ingress.get("output_barrier"), code="STATUS_ONLY_BARRIER").get("branch") != "DIAGNOSTIC" + or ingress["output_barrier"].get("written_last") is not True + or diagnostic.get("route") != "TO_S2_40_STATUS_ONLY" + or diagnostic.get("context_published") is not False + or diagnostic.get("minimum_coherent_package_possible") is not False + or intake.get("minimum_coherent_package_possible") is not False + ): + raise S240Error("STATUS_ONLY_ROUTE_CONTRACT", "diagnostic route semantics differ") + if ( + run_receipt.get("run_binding_digest") != request["run_binding_digest"] + or run_receipt.get("stage2_release_digest") != EXPECTED_STAGE2_RELEASE_SHA256 + or run_receipt.get("run_id") != run_id + or run_receipt.get("input_set_digest") != input_set_digest + or manifest.get("run_id") != run_id + or intake.get("run_id") != run_id + or diagnostic.get("run_id") != run_id + or ledger.get("run_id") != run_id + or ledger.get("producer_id") != "S2_00" + or ledger.get("input_set_digest") != input_set_digest + ): + raise S240Error("STATUS_ONLY_CROSS_BINDING", "exact-five inputs do not bind one run/input/release") + if set(diagnostic.get("reason_codes", [])) - set(ingress.get("issue_codes", [])): + raise S240Error("STATUS_ONLY_REASON_CONSERVATION", "diagnostic reasons are absent from ingress issue codes") + _, barrier_raws, barrier_rows = hydrate_ingress_barrier_artifacts( + client, root, ingress, schema_store, + exact_paths={ + "ingress/technical_diagnostic.json", "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", "review/issue_ledger.base.json", + }, + ) + for row in rows[1:]: + if barrier_raws.get(row["path"]) is None or digest(barrier_raws[row["path"]]) != row["sha256"]: + raise S240Error("STATUS_ONLY_BARRIER_BINDING", f"barrier/raw mismatch: {row['path']}") + status_only_digest = digest({ + "domain_separator": "STAGE2_S2_40_STATUS_ONLY_EXACT_FIVE_V1", + "preflight_snapshot_digest": preflight_digest, + "run_id": run_id, "input_set_digest": input_set_digest, + "input_rows": rows, "barrier_rows": barrier_rows, + "release_schema_rows": schema_rows, + }) + return write_terminal_status( + client, request, + workflow_phase="DIAGNOSTIC_ONLY", route="STOP_TECHNICAL_INCOMPLETE", + candidate_content_digest=None, run_technical_status="TECHNICAL_INCOMPLETE", + artifact_technical_status="NOT_PRODUCED", legal_readiness="NOT_ASSESSED", + validation_report_sha256=status_only_digest, + emit_status_event=False, + schema_store=schema_store, + ) + + +def require_self_hash(value: Mapping[str, Any], field: str, *, code: str) -> None: + observed = require_hex(value.get(field), code=code) + material = {key: item for key, item in value.items() if key != field} + if observed != digest(material): + raise S240Error(code, f"self hash mismatch: {field}") + + +def hydrate_s210_artifacts( + client: McpClient, + root: str, + ingress: Mapping[str, Any], + ingress_documents: Mapping[str, Mapping[str, Any]], + ingress_raws: Mapping[str, bytes], + s210: Mapping[str, Any], + request: Mapping[str, Any], + schema_store: Mapping[str, Mapping[str, Any]], +) -> dict[str, Any]: + """Hydrate the exact S2_10 universe named by the S2_00 plans.""" + cluster_plan = require_object( + ingress_documents.get("context/cluster_plan.json"), code="S210_CLUSTER_PLAN", + ) + bundle_plan = require_object( + ingress_documents.get("context/bundle_plan.json"), code="S210_BUNDLE_PLAN", + ) + cluster_ids = [ + require_ident(value, code="S210_CLUSTER_ID") + for value in require_list(cluster_plan.get("executable_cluster_ids"), code="S210_CLUSTER_IDS") + ] + if ( + cluster_ids != sorted(cluster_ids) + or len(cluster_ids) != len(set(cluster_ids)) + or cluster_ids != ingress.get("executable_cluster_ids") + or sorted(s210.get("expected_executable_cluster_ids", [])) != cluster_ids + or sorted(s210.get("valid_domain_verdict_cluster_ids", [])) != cluster_ids + or s210.get("terminal_technical_failure_cluster_ids") != [] + ): + raise S240Error("S210_CLUSTER_CLOSURE", "S2_00/S2_10 executable cluster sets differ") + + wave_by_cluster: dict[str, int] = {} + for cohort in require_list(bundle_plan.get("cohorts"), code="S210_BUNDLE_COHORTS"): + cohort = require_object(cohort, code="S210_BUNDLE_COHORT") + if cohort.get("cohort_status") != "EXECUTABLE": + continue + members = require_list(cohort.get("member_slices"), code="S210_BUNDLE_MEMBERS") + for member in members: + member = require_object(member, code="S210_BUNDLE_MEMBER") + cluster_id = require_ident(member.get("cluster_id"), code="S210_BUNDLE_CLUSTER") + ordinal = member.get("dependency_wave_ordinal") + if cluster_id in wave_by_cluster or cluster_id not in cluster_ids or not isinstance(ordinal, int) or ordinal < 0: + raise S240Error("S210_BUNDLE_WAVE", "bundle member/wave mapping is not exact") + expected_slice = f"context/cluster_slices/{cluster_id}.json" + if ( + member.get("path") != expected_slice + or member.get("sha256") != digest(ingress_raws[expected_slice]) + ): + raise S240Error("S210_BUNDLE_SLICE", f"bundle slice hash differs: {cluster_id}") + wave_by_cluster[cluster_id] = ordinal + if set(wave_by_cluster) != set(cluster_ids): + raise S240Error("S210_BUNDLE_COVERAGE", "bundle does not cover the exact executable cluster set") + wave_ordinals = sorted(set(wave_by_cluster.values())) + if wave_ordinals != list(range(len(wave_ordinals))): + raise S240Error("S210_WAVE_ORDINALS", "dependency-wave ordinals are not contiguous from zero") + + def stable_json(path: str, schema_ref: str) -> tuple[dict[str, Any], bytes]: + raw_a = client.read_binary(join_path(root, path)) + raw_b = client.read_binary(join_path(root, path)) + if raw_a != raw_b: + raise S240Error("S210_TOCTOU", f"S2_10 artifact changed between reads: {path}") + value = require_object(load_json(raw_a, label=path), code="S210_ARTIFACT_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="S210_ARTIFACT_SCHEMA") + closure_rows.append({ + "path": path, "sha256": digest(raw_a), "expected_sha256": digest(raw_a), + "schema_ref": schema_ref, "schema_version": value.get("schema_version"), + "producer_id": value.get("producer_id", "S2_10"), + "schema_valid": True, "hash_match": True, + }) + return value, raw_a + + verdicts: dict[str, dict[str, Any]] = {} + item_receipts: dict[str, dict[str, Any]] = {} + issue_parts: dict[str, dict[str, Any]] = {} + assumption_parts: dict[str, dict[str, Any]] = {} + usage_parts: dict[str, dict[str, Any]] = {} + raw_by_path: dict[str, bytes] = {} + closure_rows: list[dict[str, Any]] = [] + request_ids: set[str] = set() + producer_contract_digests: set[str] = set() + for cluster_id in cluster_ids: + paths = { + "verdict": f"map_s2_10/domain_verdicts/{cluster_id}.json", + "item": f"map_s2_10/item_receipts/{cluster_id}.json", + "issue": f"map_s2_10/issue_patches/{cluster_id}.json", + "assumption": f"map_s2_10/assumption_parts/{cluster_id}.json", + "usage": f"map_s2_10/usage_parts/{cluster_id}.json", + } + verdict, verdict_raw = stable_json(paths["verdict"], "schemas/s2_10.schema.json#/$defs/canonical_domain_verdict") + item, item_raw = stable_json(paths["item"], "schemas/s2_10.schema.json#/$defs/item_receipt") + issue, issue_raw = stable_json(paths["issue"], "schemas/s2_10.schema.json#/$defs/issue_part") + assumption, assumption_raw = stable_json(paths["assumption"], "schemas/s2_10.schema.json#/$defs/assumption_part") + usage, usage_raw = stable_json(paths["usage"], "schemas/s2_10.schema.json#/$defs/usage_part") + require_self_hash(verdict, "domain_verdict_sha256", code="S210_VERDICT_SELF_HASH") + require_self_hash(item, "receipt_sha256", code="S210_ITEM_SELF_HASH") + for part, label in ((issue, "ISSUE"), (assumption, "ASSUMPTION"), (usage, "USAGE")): + require_self_hash(part, "part_sha256", code=f"S210_{label}_SELF_HASH") + producer_contract_digest = require_hex( + verdict.get("producer_contract_digest"), code="S210_PRODUCER_CONTRACT", + ) + producer_contract_digests.add(producer_contract_digest) + verdict_hash = verdict["domain_verdict_sha256"] + if ( + verdict.get("cluster_id") != cluster_id + or verdict.get("run_binding_digest") != request["run_binding_digest"] + or verdict.get("cluster_slice_sha256") != digest(ingress_raws[f"context/cluster_slices/{cluster_id}.json"]) + or verdict.get("wave_ordinal") != wave_by_cluster[cluster_id] + or item.get("cluster_id") != cluster_id + or item.get("run_binding_digest") != request["run_binding_digest"] + or item.get("domain_verdict_path") != paths["verdict"] + or item.get("domain_verdict_sha256") != verdict_hash + or item.get("read_back_sha256") != verdict_hash + or item.get("request_id") != verdict.get("request_id") + or item.get("wave_ordinal") != verdict.get("wave_ordinal") + or item.get("attempt_no") != verdict.get("attempt_no") + or item.get("raw_model_output_sha256") != verdict.get("raw_model_output_sha256") + or item.get("validation_status") != "PASS" + or item.get("persistence_status") not in {"PUBLISHED", "IDEMPOTENT_BYTE_IDENTICAL"} + ): + raise S240Error("S210_ITEM_LINK", f"S2_10 verdict/item link differs: {cluster_id}") + for part, expected_hash, label in ( + (issue, item.get("issue_part_sha256"), "ISSUE"), + (assumption, item.get("assumption_part_sha256"), "ASSUMPTION"), + (usage, item.get("usage_part_sha256"), "USAGE"), + ): + header = require_object(part.get("header"), code=f"S210_{label}_HEADER") + if ( + part.get("part_sha256") != expected_hash + or header.get("producer_contract_digest") != producer_contract_digest + or header.get("request_id") != item.get("request_id") + or header.get("run_binding_digest") != request["run_binding_digest"] + or header.get("wave_ordinal") != item.get("wave_ordinal") + or header.get("attempt_no") != item.get("attempt_no") + or header.get("cluster_id") != cluster_id + or header.get("domain_verdict_sha256") != verdict_hash + ): + raise S240Error(f"S210_{label}_LINK", f"S2_10 {label.lower()} part link differs: {cluster_id}") + if assumption.get("assumptions") != verdict.get("assumptions"): + raise S240Error("S210_ASSUMPTION_CONTENT", f"assumption part differs from verdict: {cluster_id}") + request_ids.add(str(item.get("request_id"))) + verdicts[cluster_id] = verdict + item_receipts[cluster_id] = item + issue_parts[cluster_id] = issue + assumption_parts[cluster_id] = assumption + usage_parts[cluster_id] = usage + raw_by_path.update({ + paths["verdict"]: verdict_raw, paths["item"]: item_raw, + paths["issue"]: issue_raw, paths["assumption"]: assumption_raw, + paths["usage"]: usage_raw, + }) + if len(request_ids) != 1 or len(producer_contract_digests) != 1: + raise S240Error("S210_REQUEST_PRODUCER_SET", "S2_10 items do not share one request/producer contract") + + wave_receipts: list[dict[str, Any]] = [] + covered: set[str] = set() + for ordinal in wave_ordinals: + path = f"map_s2_10/wave_receipts/wave-{ordinal:04d}.json" + wave, raw = stable_json(path, "schemas/s2_10.schema.json#/$defs/wave_receipt") + require_self_hash(wave, "receipt_sha256", code="S210_WAVE_SELF_HASH") + expected_clusters = sorted(key for key, value in wave_by_cluster.items() if value == ordinal) + if ( + wave.get("request_id") not in request_ids + or wave.get("run_binding_digest") != request["run_binding_digest"] + or wave.get("wave_ordinal") != ordinal + or wave.get("is_final_wave") != (ordinal == wave_ordinals[-1]) + or sorted(wave.get("expected_wave_cluster_ids", [])) != expected_clusters + or sorted(wave.get("valid_domain_verdict_cluster_ids", [])) != expected_clusters + or wave.get("terminal_technical_failure_cluster_ids") != [] + or wave.get("wave_status") != "WAVE_COMPLETE" + or wave.get("route") != ("TO_S2_20" if ordinal == wave_ordinals[-1] else "NEXT_WAVE") + or wave.get("written_once") is not True + ): + raise S240Error("S210_WAVE_LINK", f"S2_10 wave receipt differs: {ordinal}") + covered.update(expected_clusters) + wave_receipts.append(wave) + raw_by_path[path] = raw + if covered != set(cluster_ids) or s210.get("terminal_wave_receipt_sha256s") != [ + row["receipt_sha256"] for row in wave_receipts + ]: + raise S240Error("S210_WAVE_CLOSURE", "S2_10 terminal wave receipt closure differs") + return { + "cluster_ids": cluster_ids, "verdicts": verdicts, + "item_receipts": item_receipts, "issue_parts": issue_parts, + "assumption_parts": assumption_parts, "usage_parts": usage_parts, + "wave_receipts": wave_receipts, "raw_by_path": raw_by_path, + "source_rows": [ + {"path": path, "sha256": digest(raw), "ref_family": "s2_10_runtime"} + for path, raw in sorted(raw_by_path.items()) + ], + "closure_rows": sorted(closure_rows, key=lambda row: row["path"]), + } + + +def validate_handoff_provenance( + value: Any, *, common_only: bool, expected_mode: str, code: str, +) -> dict[str, Any]: + row = require_object(value, code=code) + expected = COMMON_PROVENANCE_FIELDS if common_only else GROUP_PROVENANCE_FIELDS + if set(row) != expected: + raise S240Error(code, "handoff provenance is not closed", details=sorted(set(row) ^ expected)) + if row.get("compile_mode") != expected_mode: + raise S240Error("COMPILE_MODE_DRIFT", "handoff compile mode differs") + for key in expected - {"compile_mode"}: + require_hex(row.get(key), code=code) + return row + + +def common_provenance(value: Mapping[str, Any]) -> dict[str, Any]: + return {key: value[key] for key in sorted(COMMON_PROVENANCE_FIELDS)} + + +def artifact_rows(manifest: Mapping[str, Any]) -> list[dict[str, Any]]: + rows = require_list(manifest.get("part_rows"), code="S230_MANIFEST_ROWS") + if len(rows) > MAX_ARTIFACT_ROWS: + raise S240Error("S230_MANIFEST_LIMIT", "too many artifact rows") + result: list[dict[str, Any]] = [] + seen_pairs: set[tuple[str, str]] = set() + seen_paths: set[str] = set() + for value in rows: + row = require_object(value, code="S230_MANIFEST_ROW") + if set(row) != {"claim_group_id", "part_family", "path", "sha256", "schema_ref"}: + raise S240Error("S230_MANIFEST_ROW_SHAPE", "manifest row is not closed") + group_id = require_ident(row.get("claim_group_id"), code="S230_MANIFEST_GROUP") + family = row.get("part_family") + if family not in PART_FAMILIES: + raise S240Error("S230_MANIFEST_KIND", f"unsupported part family: {family}") + path = safe_path(row.get("path"), code="S230_MANIFEST_PATH") + expected_path = f"map_s2_30/{PART_DIRECTORIES[family]}/{group_id}.json" + if path != expected_path or row.get("schema_ref") != PART_SCHEMA_REFS[family]: + raise S240Error("S230_MANIFEST_BINDING", "part path/schema differs from canonical binding") + pair = (group_id, family) + if pair in seen_pairs or path in seen_paths: + raise S240Error("S230_MANIFEST_DUPLICATE", "duplicate part pair/path") + seen_pairs.add(pair) + seen_paths.add(path) + result.append({ + "path": path, + "sha256": require_hex(row.get("sha256"), code="S230_MANIFEST_HASH"), + "schema_ref": row["schema_ref"], + "part_family": family, + "claim_group_id": group_id, + }) + if result != sorted(result, key=lambda row: (row["claim_group_id"], row["part_family"], row["path"])): + raise S240Error("S230_MANIFEST_ORDER", "part rows must be canonically sorted") + return result + + +def plan_artifact_rows(plan: Mapping[str, Any]) -> list[dict[str, Any]]: + rows = require_list(plan.get("artifact_rows"), code="S220_ARTIFACT_ROWS") + result: list[dict[str, Any]] = [] + seen: set[str] = set() + for value in rows: + row = require_object(value, code="S220_ARTIFACT_ROW") + path = safe_path(row.get("path"), code="S220_ARTIFACT_PATH") + if path in seen: + raise S240Error("S220_ARTIFACT_DUPLICATE", f"duplicate plan artifact: {path}") + seen.add(path) + result.append({ + "path": path, + "schema_ref": row.get("schema_ref"), + "raw_sha256": require_hex(row.get("raw_sha256"), code="S220_ARTIFACT_HASH"), + "byte_size": row.get("byte_size"), + "producer_component": row.get("producer_component"), + }) + if result != sorted(result, key=lambda row: row["path"]): + raise S240Error("S220_ARTIFACT_ORDER", "plan artifact rows must be sorted") + if plan.get("artifact_set_digest") != digest(result): + raise S240Error("S220_ARTIFACT_SET_DIGEST", "plan artifact set digest mismatch") + return result + + +def read_plan_artifacts( + client: McpClient, root: str, plan: Mapping[str, Any], total: int, + schema_store: Mapping[str, Mapping[str, Any]], +) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], int]: + rows = plan_artifact_rows(plan) + documents: dict[str, dict[str, Any]] = {} + raw_by_path: dict[str, bytes] = {} + for row in rows: + value, raw = read_bound_json(client, join_path(root, row["path"]), row["raw_sha256"]) + if isinstance(row.get("schema_ref"), str) and row["schema_ref"].startswith("schemas/"): + validate_schema_instance(value, row["schema_ref"], schema_store, code="S220_ARTIFACT_SCHEMA") + if row["byte_size"] != len(raw): + raise S240Error("S220_ARTIFACT_SIZE", f"plan artifact size mismatch: {row['path']}") + total += len(raw) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + documents[row["path"]] = value + raw_by_path[row["path"]] = raw + return documents, raw_by_path, total + + +def resolve_frozen_ref( + client: McpClient, + root: str, + plan_rows: Mapping[str, bytes], + ref: Mapping[str, Any], + *, + code: str, +) -> tuple[dict[str, Any], bytes, str]: + relative = safe_path(ref.get("path"), code=code) + expected = require_hex(ref.get("sha256"), code=code) + plan_path = relative if relative.startswith("plan/") else f"plan/{relative}" + if plan_path in plan_rows: + raw = plan_rows[plan_path] + if digest(raw) != expected: + raise S240Error(code, f"frozen plan ref hash mismatch: {relative}") + return require_object(load_json(raw, label=plan_path), code=code), raw, plan_path + asset_path = relative if relative.startswith(f"{ASSET_ROOT}/") else join_path(ASSET_ROOT, relative) + value, raw = read_bound_json(client, asset_path, expected) + return value, raw, asset_path + + +def hydrate_normal(client: McpClient, request: Mapping[str, Any]) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + ingress, ingress_raw = read_bound_json(client, join_path(root, "ingress/ingress_status.json"), request["expected_ingress_status_sha256"]) + s210, s210_raw = read_bound_json(client, join_path(root, "map_s2_10/s2_10_publish_status.json"), request["expected_s2_10_publish_status_sha256"]) + plan, plan_raw = read_bound_json(client, join_path(root, "plan/plan_publish_status.json"), request["expected_plan_publish_status_sha256"]) + s230, s230_raw = read_bound_json(client, join_path(root, "map_s2_30/s2_30_publish_status.json"), request["expected_s2_30_publish_status_sha256"]) + manifest_path = join_path(root, "map_s2_30/artifact_manifest.json") + manifest, manifest_raw = read_bound_json(client, manifest_path, request["expected_s2_30_artifact_manifest_sha256"]) + release_values, release_raws, release_rows = read_release_bound_jsons( + client, ( + *INPUT_SCHEMA_RELS, AUTHORITY_RELEASE_REL, CASE_TYPE_COVERAGE_REL, + CASE_TYPE_REGISTRY_REL, CASE_TYPE_RULE_REGISTRY_REL, + ), + ) + schema_store: dict[str, Mapping[str, Any]] = { + path: value for path, value in release_values.items() if path.startswith("schemas/") + } + validate_schema_instance(ingress, "schemas/ingress.schema.json#/$defs/ingress_status", schema_store, code="V01_INGRESS_SCHEMA") + validate_schema_instance(s210, "schemas/s2_10.schema.json#/$defs/global_publish_status", schema_store, code="V01_S210_SCHEMA") + validate_schema_instance(plan, "schemas/relief_plan.schema.json#/$defs/plan_publish_status", schema_store, code="V01_S220_SCHEMA") + validate_schema_instance(s230, "schemas/draft_atoms.schema.json#/$defs/publish_status", schema_store, code="V01_S230_SCHEMA") + validate_schema_instance(manifest, "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", schema_store, code="V01_S230_MANIFEST_SCHEMA") + executable_cluster_ids = [ + require_ident(value, code="INGRESS_EXECUTABLE_CLUSTER") + for value in require_list(ingress.get("executable_cluster_ids"), code="INGRESS_EXECUTABLE_CLUSTERS") + ] + normal_ingress_paths = { + "ingress/stage1_input_manifest.json", "ingress/intake_report.json", + "context/case_context.json", "context/evidence_inventory.json", + "context/object_registry.json", "context/party_and_title_context.json", + "context/slot_crosswalk.json", "context/cluster_plan.json", + "context/bundle_plan.json", "review/issue_ledger.base.json", + *{f"context/cluster_slices/{cluster_id}.json" for cluster_id in executable_cluster_ids}, + } + ingress_documents, ingress_raws, ingress_artifact_rows = hydrate_ingress_barrier_artifacts( + client, root, ingress, schema_store, exact_paths=normal_ingress_paths, + ) + ingress_barrier = require_object(ingress.get("output_barrier"), code="INGRESS_NORMAL_BARRIER") + if ( + ingress_barrier.get("branch") != "NORMAL" + or ingress_barrier.get("written_last") is not True + or ingress_barrier.get("non_status_artifacts_read_back_verified", True) is not True + or ingress_documents["context/cluster_plan.json"].get("executable_cluster_ids") != executable_cluster_ids + ): + raise S240Error("INGRESS_NORMAL_CLOSURE", "normal ingress barrier/context closure differs") + ingress_receipt = require_object(ingress.get("run_binding_receipt"), code="V01_INGRESS_RUN_BINDING") + if ( + ingress.get("route") not in {"TO_S2_10", "TO_S2_10_WITH_ISSUES"} + or ingress_receipt.get("run_binding_digest") != request["run_binding_digest"] + or ingress_receipt.get("stage2_release_digest") != EXPECTED_STAGE2_RELEASE_SHA256 + or s210.get("producer_id") != "S2_10_NATIVE_RESULT_ADAPTER" + or s210.get("run_binding_digest") != request["run_binding_digest"] + or s210.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or s210.get("status") != "COMPLETE" or s210.get("route") != "TO_S2_20" + or s210.get("status_written_last") is not True + or plan.get("workflow_id") != "S2_20" + or plan.get("run_binding_digest") != request["run_binding_digest"] + or plan.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or plan.get("s2_10_publish_status_sha256") != request["expected_s2_10_publish_status_sha256"] + or s230.get("run_binding_digest") != request["run_binding_digest"] + or s230.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or manifest.get("run_binding_digest") != request["run_binding_digest"] + ): + raise S240Error("V01_INPUT_LINEAGE", "normal barriers do not share exact producer/run/release lineage") + require_self_hash(s210, "status_sha256", code="S210_STATUS_SELF_HASH") + s210_handoff = hydrate_s210_artifacts( + client, root, ingress, ingress_documents, ingress_raws, + s210, request, schema_store, + ) + require_self_hash(plan, "barrier_sha256", code="S220_STATUS_SELF_HASH") + if plan.get("plan_status") == "TECHNICAL_INCOMPLETE" or plan.get("route") != "TO_S2_30" or plan.get("consumer_authorized") is not True: + raise S240Error("S220_BARRIER_NOT_CONSUMABLE", "S2_20 barrier is not consumer-authorized") + if s230.get("status") != "S2_30_COMPLETE" or s230.get("route") != "TO_S2_40" or s230.get("status_written_last") is not True: + raise S240Error("S230_BARRIER_NOT_CONSUMABLE", "S2_30 barrier is not complete") + require_self_hash(s230, "status_sha256", code="S230_STATUS_SELF_HASH") + require_self_hash(manifest, "part_manifest_core_sha256", code="S230_MANIFEST_SELF_HASH") + common = validate_handoff_provenance( + manifest.get("provenance"), common_only=True, + expected_mode=request["compile_mode"], code="S230_COMMON_PROVENANCE", + ) + if s230.get("compile_mode") != request["compile_mode"] or s230.get("provenance") != common: + raise S240Error("COMPILE_MODE_DRIFT", "S2_30 barrier/manifest mode or provenance differs") + if ( + s230.get("artifact_manifest_path") != "map_s2_30/artifact_manifest.json" + or s230.get("artifact_manifest_schema_ref") != "schemas/draft_atoms.schema.json#/$defs/part_manifest_core" + or s230.get("artifact_manifest_sha256") != digest(manifest_raw) + ): + raise S240Error("S230_BARRIER_MANIFEST", "S2_30 barrier does not bind exact manifest bytes") + expected_groups = require_list(manifest.get("expected_claim_group_ids"), code="S230_EXPECTED_GROUPS") + if expected_groups != sorted(expected_groups) or len(expected_groups) != len(set(expected_groups)): + raise S240Error("S230_EXPECTED_GROUP_ORDER", "manifest group ids must be unique and sorted") + if ( + s230.get("expected_claim_group_ids") != expected_groups + or s230.get("published_claim_group_ids") != expected_groups + or s230.get("terminal_failure_claim_group_ids") != [] + ): + raise S240Error("S230_GROUP_SET", "publish expected/published group set differs") + if sorted(plan.get("group_ids", [])) != expected_groups: + raise S240Error("S220_S230_GROUP_SET", "S2_20 and S2_30 group sets differ") + rows = artifact_rows(manifest) + expected_pairs = {(group_id, family) for group_id in expected_groups for family in PART_FAMILIES} + if {(row["claim_group_id"], row["part_family"]) for row in rows} != expected_pairs: + raise S240Error("S230_PART_COVERAGE", "manifest must contain exactly four part families per group") + parts: dict[str, list[dict[str, Any]]] = {family: [] for family in PART_FAMILIES} + group_provenance: dict[str, dict[str, Any]] = {} + total = ( + sum(len(raw) for raw in (ingress_raw, s210_raw, plan_raw, s230_raw, manifest_raw)) + + sum(len(raw) for raw in release_raws.values()) + + sum(len(raw) for raw in ingress_raws.values()) + + sum(len(raw) for raw in s210_handoff["raw_by_path"].values()) + ) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + for row in rows: + value, raw = read_bound_json(client, join_path(root, row["path"]), row["sha256"]) + validate_schema_instance(value, row["schema_ref"], schema_store, code="S230_PART_SCHEMA") + total += len(raw) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + require_self_hash(value, "part_sha256", code="S230_PART_SELF_HASH") + provenance = validate_handoff_provenance( + value.get("provenance"), common_only=False, + expected_mode=request["compile_mode"], code="S230_GROUP_PROVENANCE", + ) + if common_provenance(provenance) != common: + raise S240Error("S230_PART_COMMON_PROVENANCE", "part common provenance differs") + if value.get("claim_group_id") != row["claim_group_id"]: + raise S240Error("S230_PART_GROUP", "part group mismatch") + prior = group_provenance.setdefault(row["claim_group_id"], provenance) + if prior != provenance: + raise S240Error("S230_PART_GROUP_PROVENANCE", "part family provenance differs within group") + parts[row["part_family"]].append(value) + item_refs = require_list(s230.get("ordered_item_receipts"), code="S230_ITEM_RECEIPT_REFS") + cohort_refs = require_list(s230.get("ordered_cohort_receipts"), code="S230_COHORT_RECEIPT_REFS") + if item_refs != sorted(item_refs, key=lambda row: (row.get("claim_group_id"), row.get("path"))): + raise S240Error("S230_ITEM_RECEIPT_ORDER", "item receipt refs are not sorted") + if cohort_refs != sorted(cohort_refs, key=lambda row: row.get("path")): + raise S240Error("S230_COHORT_RECEIPT_ORDER", "cohort receipt refs are not sorted") + if [row.get("claim_group_id") for row in item_refs] != expected_groups: + raise S240Error("S230_ITEM_RECEIPT_GROUP_SET", "item receipt group set differs") + receipt_rows: list[dict[str, Any]] = [] + for kind, refs in (("ITEM", item_refs), ("COHORT", cohort_refs)): + for ref in refs: + receipt_path = safe_path(ref.get("path"), code="S230_RECEIPT_PATH") + receipt, receipt_raw = read_bound_json(client, join_path(root, receipt_path), require_hex(ref.get("sha256"), code="S230_RECEIPT_HASH")) + require_self_hash(receipt, "receipt_sha256", code="S230_RECEIPT_SELF_HASH") + if receipt.get("part_manifest_core_sha256") != manifest["part_manifest_core_sha256"]: + raise S240Error("S230_RECEIPT_CORE_HASH", "receipt references a different manifest core") + receipt_provenance = validate_handoff_provenance( + receipt.get("provenance"), common_only=kind == "COHORT", + expected_mode=request["compile_mode"], code="S230_RECEIPT_PROVENANCE", + ) + if common_provenance(receipt_provenance) != common: + raise S240Error("S230_RECEIPT_COMMON_PROVENANCE", "receipt provenance differs") + if kind == "ITEM": + group_id = ref.get("claim_group_id") + if receipt.get("claim_group_id") != group_id or receipt_provenance != group_provenance.get(group_id): + raise S240Error("S230_ITEM_RECEIPT_GROUP", "item receipt group/provenance differs") + total += len(receipt_raw) + receipt_rows.append({"kind": kind, "path": receipt_path, "sha256": digest(receipt_raw)}) + plan_documents, plan_raw_by_path, total = read_plan_artifacts(client, root, plan, total, schema_store) + rule_packs: dict[str, dict[str, Any]] = {} + group_slices: dict[str, dict[str, Any]] = {} + renderer_descriptors: dict[str, dict[str, Any]] = {} + frozen_assets: dict[str, dict[str, Any]] = {} + frozen_source_rows: list[dict[str, Any]] = [dict(row) for row in release_rows] + frozen_source_rows.extend({ + "path": row["path"], "sha256": row["raw_sha256"], "ref_family": "s2_00_runtime", + } for row in ingress_artifact_rows) + frozen_source_rows.extend(s210_handoff["source_rows"]) + frozen_source_rows.append({ + "path": "map_s2_30/artifact_manifest.json", + "sha256": digest(manifest_raw), "ref_family": "upstream_manifest", + }) + calculation_receipts: dict[str, dict[str, Any]] = {} + for group_id in expected_groups: + group_path = f"plan/group_slices/{group_id}.json" + group_slice = require_object(plan_documents.get(group_path), code="S220_GROUP_SLICE") + if group_slice.get("claim_group_id") != group_id: + raise S240Error("S220_GROUP_SLICE_ID", "group slice id differs") + group_echo = require_object(group_provenance.get(group_id), code="S230_GROUP_ECHO") + if (request["compile_mode"] != "STRUCTURAL_FIXTURE" + and digest(plan_raw_by_path[group_path]) != group_echo.get("s30_group_slice_sha256")): + raise S240Error("S220_S230_GROUP_SLICE_HASH", "S2_30 group-slice echo differs from frozen S2_20 bytes") + group_slices[group_id] = group_slice + rule_pack, rule_raw, resolved = resolve_frozen_ref( + client, root, plan_raw_by_path, + require_object(group_slice.get("rule_context_pack_ref"), code="S220_RULE_PACK_REF"), + code="S220_RULE_PACK_REF", + ) + if (request["compile_mode"] != "STRUCTURAL_FIXTURE" + and digest(rule_raw) != group_echo.get("p31_rule_and_pack_sha256")): + raise S240Error("S220_S230_RULE_PACK_HASH", "S2_30 rule-pack echo differs from frozen S2_20 bytes") + rule_packs[group_id] = rule_pack + frozen_source_rows.append({"path": resolved, "sha256": digest(rule_raw)}) + for ref in require_list(rule_pack.get("renderer_refs"), code="S220_RENDERER_REFS"): + descriptor, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_RENDERER_REF"), code="S220_RENDERER_REF") + renderer_id = require_ident(descriptor.get("renderer_id"), code="S220_RENDERER_ID") + if renderer_id in renderer_descriptors and canonical_bytes(renderer_descriptors[renderer_id]) != canonical_bytes(descriptor): + raise S240Error("S220_RENDERER_CONFLICT", "renderer id binds conflicting bytes") + renderer_descriptors[renderer_id] = descriptor + frozen_assets[resolved] = descriptor + frozen_source_rows.append({"path": resolved, "sha256": digest(raw)}) + for ref_name in ("structured_relief_rule_refs", "review_policy_refs", "ce13_branch_refs"): + for ref in require_list(rule_pack.get(ref_name), code="S220_RULE_ASSET_REFS"): + asset, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_RULE_ASSET_REF"), code="S220_RULE_ASSET_REF") + frozen_assets[resolved] = asset + frozen_source_rows.append({"path": resolved, "sha256": digest(raw), "ref_family": ref_name}) + for ref in require_list(group_slice.get("calculation_receipt_refs"), code="S220_CALC_REFS"): + receipt, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_CALC_REF"), code="S220_CALC_REF") + receipt_id = require_ident(receipt.get("calculation_receipt_id"), code="S220_CALC_ID") + calculation_receipts[receipt_id] = receipt + frozen_source_rows.append({"path": resolved, "sha256": digest(raw), "ref_family": "calculation"}) + exhibit_register = require_object(plan_documents.get("plan/exhibit_register.json"), code="S220_EXHIBIT_REGISTER") + authority_release = release_values[AUTHORITY_RELEASE_REL] + case_type_coverage = release_values[CASE_TYPE_COVERAGE_REL] + case_type_registry = release_values[CASE_TYPE_REGISTRY_REL] + case_type_rule_registry = release_values[CASE_TYPE_RULE_REGISTRY_REL] + input_closure_rows = [ + { + "path": "ingress/ingress_status.json", "sha256": digest(ingress_raw), + "expected_sha256": request["expected_ingress_status_sha256"], + "schema_ref": "schemas/ingress.schema.json#/$defs/ingress_status", + "schema_version": ingress.get("schema_version"), "producer_id": "S2_00", + "schema_valid": True, "hash_match": digest(ingress_raw) == request["expected_ingress_status_sha256"], + }, + { + "path": "map_s2_10/s2_10_publish_status.json", "sha256": digest(s210_raw), + "expected_sha256": request["expected_s2_10_publish_status_sha256"], + "schema_ref": "schemas/s2_10.schema.json#/$defs/global_publish_status", + "schema_version": s210.get("schema_version"), "producer_id": s210.get("producer_id"), + "schema_valid": True, "hash_match": digest(s210_raw) == request["expected_s2_10_publish_status_sha256"], + }, + { + "path": "plan/plan_publish_status.json", "sha256": digest(plan_raw), + "expected_sha256": request["expected_plan_publish_status_sha256"], + "schema_ref": "schemas/relief_plan.schema.json#/$defs/plan_publish_status", + "schema_version": plan.get("schema_version"), "producer_id": plan.get("workflow_id"), + "schema_valid": True, "hash_match": digest(plan_raw) == request["expected_plan_publish_status_sha256"], + }, + { + "path": "map_s2_30/s2_30_publish_status.json", "sha256": digest(s230_raw), + "expected_sha256": request["expected_s2_30_publish_status_sha256"], + "schema_ref": "schemas/draft_atoms.schema.json#/$defs/publish_status", + "schema_version": s230.get("schema_version"), "producer_id": "S2_30", + "schema_valid": True, "hash_match": digest(s230_raw) == request["expected_s2_30_publish_status_sha256"], + }, + { + "path": "map_s2_30/artifact_manifest.json", "sha256": digest(manifest_raw), + "expected_sha256": request["expected_s2_30_artifact_manifest_sha256"], + "schema_ref": "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", + "schema_version": manifest.get("schema_version"), "producer_id": "S2_30", + "schema_valid": True, "hash_match": digest(manifest_raw) == request["expected_s2_30_artifact_manifest_sha256"], + }, + ] + input_closure_rows.extend({ + "path": row["path"], "sha256": row["raw_sha256"], + "expected_sha256": row["raw_sha256"], "schema_ref": row["schema_ref"], + "schema_version": ingress_documents[row["path"]].get("schema_version"), + "producer_id": ingress_documents[row["path"]].get("producer_id", "S2_00"), + "schema_valid": True, "hash_match": True, + } for row in ingress_artifact_rows) + input_closure_rows.extend(s210_handoff["closure_rows"]) + input_snapshot_preimage = [ + digest(ingress_raw), digest(s210_raw), digest(plan_raw), digest(s230_raw), + digest(manifest_raw), *[row["sha256"] for row in rows], + *[row["sha256"] for row in receipt_rows], + *[digest(ingress_raws[path]) for path in sorted(ingress_raws)], + *[digest(s210_handoff["raw_by_path"][path]) for path in sorted(s210_handoff["raw_by_path"])], + *[digest(plan_raw_by_path[path]) for path in sorted(plan_raw_by_path)], + *[row["sha256"] for row in sorted(frozen_source_rows, key=lambda item: (item["path"], item["sha256"]))], + ] + return { + "ingress": ingress, "s210": s210, "plan": plan, "s230": s230, + "manifest": manifest, "manifest_sha256": digest(manifest_raw), "rows": rows, + "parts": parts, "group_ids": expected_groups, "group_provenance": group_provenance, + "receipt_rows": receipt_rows, "plan_documents": plan_documents, + "plan_raw_by_path": plan_raw_by_path, + "group_slices": group_slices, "rule_packs": rule_packs, + "renderer_descriptors": renderer_descriptors, + "frozen_assets": frozen_assets, + "calculation_receipts": calculation_receipts, + "exhibit_register": exhibit_register, + "ingress_documents": ingress_documents, "ingress_raws": ingress_raws, + "ingress_artifact_rows": ingress_artifact_rows, + "s210_handoff": s210_handoff, + "authority_release": authority_release, + "authority_release_sha256": digest(release_raws[AUTHORITY_RELEASE_REL]), + "case_type_coverage": case_type_coverage, + "case_type_coverage_sha256": digest(release_raws[CASE_TYPE_COVERAGE_REL]), + "case_type_registry": case_type_registry, + "case_type_registry_sha256": digest(release_raws[CASE_TYPE_REGISTRY_REL]), + "case_type_rule_registry": case_type_rule_registry, + "case_type_rule_registry_sha256": digest(release_raws[CASE_TYPE_RULE_REGISTRY_REL]), + "schema_store": schema_store, + "frozen_source_rows": sorted(frozen_source_rows, key=lambda row: (row["path"], row["sha256"])), + "input_closure_rows": input_closure_rows, + "input_snapshot_preimage": input_snapshot_preimage, + "input_snapshot_digest": digest(input_snapshot_preimage), + } + + +def flatten(parts: Iterable[Mapping[str, Any]], keys: Sequence[str]) -> list[Any]: + result: list[Any] = [] + for part in parts: + value: Any = None + for key in keys: + if key in part: + value = part[key] + break + if value is None: + continue + if not isinstance(value, list): + raise S240Error("PART_PAYLOAD_TYPE", f"part payload must be an array: {keys[0]}") + result.extend(value) + return result + + +def unique_sorted(rows: Iterable[Any], id_keys: Sequence[str], *, code: str) -> list[dict[str, Any]]: + by_id: dict[str, dict[str, Any]] = {} + for value in rows: + row = require_object(value, code=code) + row_id: Any = None + for key in id_keys: + if key in row: + row_id = row[key] + break + row_id = require_ident(row_id, code=code) + if row_id in by_id and canonical_bytes(by_id[row_id]) != canonical_bytes(row): + raise S240Error("IMMUTABLE_ID_CONFLICT", f"conflicting immutable row: {row_id}") + by_id[row_id] = row + return [by_id[key] for key in sorted(by_id)] + + +def provenance_source_refs(rows: Any) -> list[str]: + refs: set[str] = set() + for row in rows if isinstance(rows, list) else []: + if not isinstance(row, dict): + continue + for key, value in row.items(): + if key.endswith("_ref") and isinstance(value, str) and value: + refs.add(value) + elif key.endswith("_refs") and isinstance(value, list): + refs.update(item for item in value if isinstance(item, str) and item) + elif key == "locator" and isinstance(value, dict): + refs.add("locator:" + digest(value)) + return sorted(refs) + + +def slot_values(text_or_slots: Mapping[str, Any]) -> dict[str, str | list[str]]: + rows = require_list(text_or_slots.get("slots"), code="ATOM_TYPED_SLOTS") + values: dict[str, str | list[str]] = {} + for value in rows: + row = require_object(value, code="ATOM_TYPED_SLOT") + slot_id = require_ident(row.get("slot_id"), code="ATOM_SLOT_ID") + if slot_id in values: + raise S240Error("ATOM_SLOT_DUPLICATE", f"duplicate typed slot: {slot_id}") + raw = row.get("value") + if raw is None: + continue + if not isinstance(raw, str): + raise S240Error("ATOM_SLOT_VALUE", "typed slot value must be string or null") + rendered = nfc(raw) + if any(token in rendered for token in ("{{", "}}", "\x00")): + raise S240Error("ATOM_SLOT_INJECTION", "typed slot contains forbidden token") + values[slot_id] = rendered + return values + + +def select_renderer_branch( + descriptor: Mapping[str, Any], branch_id: str, *, allow_fixture: bool, +) -> Mapping[str, Any]: + status = descriptor.get("status") + eligible = descriptor.get("execution_eligible") is True + if not eligible or status not in ({"APPROVED_LEGAL_CONTENT", "STRUCTURAL_FIXTURE_ONLY"} if allow_fixture else {"APPROVED_LEGAL_CONTENT"}): + raise S240Error("RENDERER_NOT_ELIGIBLE", "frozen renderer is not approved/execution-eligible") + branches = require_list(descriptor.get("branch_rows"), code="RENDER_BRANCH_ROWS") + matches = [row for row in branches if isinstance(row, dict) and row.get("branch_id") == branch_id] + if len(matches) != 1: + raise S240Error("RENDER_BRANCH_CARDINALITY", "template_branch_id must match exactly one frozen branch") + branch = matches[0] + if branch.get("approval_status") != "APPROVED": + raise S240Error("RENDER_BRANCH_NOT_APPROVED", "selected branch is not approved") + return branch + + +def render_segments( + descriptor: Mapping[str, Any], branch: Mapping[str, Any], slots: Mapping[str, Any], +) -> tuple[str, str]: + definitions = { + row.get("name"): row + for row in descriptor.get("typed_slot_contract", {}).get("slot_definitions", []) + if isinstance(row, dict) and isinstance(row.get("name"), str) + } + if set(slots) - set(definitions): + raise S240Error("RENDERER_UNKNOWN_SLOT", "atom supplies a slot outside frozen descriptor") + for name, definition in definitions.items(): + if definition.get("cardinality") in {"EXACTLY_ONE", "ONE_OR_MORE"} and name not in slots: + raise S240Error("RENDERER_REQUIRED_SLOT_MISSING", f"missing frozen slot: {name}") + segments = require_list(branch.get("segments"), code="RENDER_SEGMENTS") + + def render_a() -> str: + pieces: list[str] = [] + for segment in segments: + row = require_object(segment, code="RENDER_SEGMENT") + if row.get("kind") == "LITERAL" and set(row) == {"kind", "value"} and isinstance(row.get("value"), str): + pieces.append(nfc(row["value"])) + elif row.get("kind") == "SLOT" and set(row) == {"kind", "name", "escape"}: + name = row.get("name") + if name not in slots: + if definitions.get(name, {}).get("cardinality") == "ZERO_OR_ONE": + continue + raise S240Error("RENDERER_REQUIRED_SLOT_MISSING", f"missing segment slot: {name}") + value = slots[name] + pieces.append(", ".join(value) if isinstance(value, list) else str(value)) + else: + raise S240Error("RENDER_SEGMENT_SHAPE", "closed renderer segment is invalid") + return nfc("".join(pieces)) + + primary = render_a() + independent_segments = [dict(row) for row in segments] + independent_slots = {key: (list(value) if isinstance(value, list) else value) for key, value in slots.items()} + independent = "".join( + nfc(str(row["value"])) if row.get("kind") == "LITERAL" + else ( + ", ".join(independent_slots[row["name"]]) + if isinstance(independent_slots.get(row["name"]), list) + else str(independent_slots.get(row["name"], "")) + ) + for row in independent_segments + ) + independent = nfc(independent) + if primary.encode("utf-8") != independent.encode("utf-8"): + raise S240Error("RENDERER_INDEPENDENT_RERENDER_MISMATCH", "independent renderer bytes differ") + if PLACEHOLDER.search(primary): + raise S240Error("RENDER_DANGLING_SLOT", "closed renderer left a template token") + return primary, independent + + +def reduce_and_render(inputs: Mapping[str, Any], request: Mapping[str, Any]) -> dict[str, Any]: + parts = inputs["parts"] + atoms = unique_sorted( + flatten(parts["DRAFT_PART"], ("canonical_atoms",)), + ("atom_id",), code="DRAFT_ATOM_ID", + ) + atom_by_id: dict[str, dict[str, Any]] = {} + source_plan_hashes: set[str] = set() + for part in parts["DRAFT_PART"]: + source_plan_hashes.add(require_hex(part.get("source_plan_sha256"), code="DRAFT_SOURCE_PLAN_HASH")) + for atom in part["canonical_atoms"]: + require_self_hash(atom, "canonical_atom_sha256", code="CANONICAL_ATOM_SELF_HASH") + if "legal_admission" in atom or "closed_renderer" in atom: + raise S240Error("ATOM_SELF_ASSERTED_LEGAL_ADMISSION", "atom may not carry legal admission or renderer bytes") + atom_by_id[atom["atom_id"]] = atom + base_ledger = require_object( + inputs["ingress_documents"].get("review/issue_ledger.base.json"), + code="BASE_ISSUE_LEDGER", + ) + plan_ledger = require_object( + inputs["plan_documents"].get("plan/issue_ledger.plan.json"), + code="PLAN_ISSUE_LEDGER", + ) + base_issues = [dict(row) for row in require_list(base_ledger.get("issues"), code="BASE_ISSUES")] + base_issue_ids = sorted(str(row.get("issue_id")) for row in base_issues) + if ( + len(base_issue_ids) != len(set(base_issue_ids)) + or plan_ledger.get("preserved_base_issue_ids") != base_issue_ids + or plan_ledger.get("base_ledger_sha256") != digest(inputs["ingress_raws"]["review/issue_ledger.base.json"]) + ): + raise S240Error("ISSUE_LEDGER_BASE_CONSERVATION", "S2_20 did not preserve the exact S2_00 issue universe") + issues: list[dict[str, Any]] = list(base_issues) + issue_source_keys: list[str] = [f"S2_00:{value}" for value in base_issue_ids] + for row in require_list(plan_ledger.get("plan_issues"), code="PLAN_ISSUES"): + row = require_object(row, code="PLAN_ISSUE") + source_id = require_ident(row.get("issue_id"), code="PLAN_ISSUE_ID") + issue_id = source_id if re.fullmatch(r"ISS-[A-Fa-f0-9]{16,64}", source_id) else stable_id("ISS", "S2_20", source_id) + code = require_ident(row.get("code"), code="PLAN_ISSUE_CODE") + scope_ref = require_ident(row.get("scope_ref"), code="PLAN_ISSUE_SCOPE") + issues.append({ + "issue_id": issue_id, "issue_code": code, + "technical_severity": "REVIEW", "review_partition": "UNRESOLVED", + "impact_scope": "REVIEW_ITEM", "scope_refs": [scope_ref], + "source_contract_row_refs": [f"S2_20:{source_id}"], + "reason_codes": [code], "downstream_allowed_actions": ["REVIEW"], + "source_refs": [f"S2_20:{source_id}"], "status": "CARRIED_FORWARD", + }) + issue_source_keys.append(f"S2_20:{source_id}") + s210_impact = {"RUN_WIDE": "GLOBAL", "CLUSTER_LOCAL": "CLUSTER", "OPTION_ONLY": "REVIEW_ITEM"} + s210_severity = {"INFO": "INFO", "WARNING": "REVIEW", "BLOCKING": "BLOCK"} + for cluster_id, part in sorted(inputs["s210_handoff"]["issue_parts"].items()): + for row in require_list(part.get("issues"), code="S210_ISSUES"): + row = require_object(row, code="S210_ISSUE") + source_id = require_ident(row.get("issue_id"), code="S210_ISSUE_ID") + issue_id = stable_id("ISS", "S2_10", cluster_id, source_id) + issue_code = require_ident(row.get("issue_code"), code="S210_ISSUE_CODE") + source_refs = sorted(set(str(value) for value in row.get("source_refs", []) if isinstance(value, str) and value)) + issues.append({ + "issue_id": issue_id, "issue_code": issue_code, + "technical_severity": s210_severity.get(str(row.get("severity")), "REVIEW"), + "review_partition": "SUPPORTED" if row.get("status") == "RESOLVED" else "UNRESOLVED", + "impact_scope": s210_impact.get(str(row.get("impact_scope")), "REVIEW_ITEM"), + "scope_refs": [cluster_id], "source_contract_row_refs": [f"S2_10:{source_id}"], + "reason_codes": sorted(set([issue_code, *[str(value) for value in row.get("resolution_condition_codes", [])]])), + "downstream_allowed_actions": ["REVIEW"], + "source_refs": source_refs or [f"S2_10:{cluster_id}"], + "status": "CARRIED_FORWARD", + "upstream_review_key": source_id, "raw_item_sha256": digest(row), + }) + issue_source_keys.append(f"S2_10:{cluster_id}:{source_id}") + for part in parts["ISSUE_PATCH"]: + for code in sorted(set(part.get("review_flags", [])) | set(part.get("missing_inputs", []))): + issues.append({ + "issue_id": stable_id("ISS", part["claim_group_id"], code), + "issue_code": str(code), "technical_severity": "REVIEW", + "review_partition": "UNRESOLVED", "impact_scope": "REVIEW_ITEM", + "scope_refs": [part["claim_group_id"]], + "source_contract_row_refs": [f"S2_30:{part['claim_group_id']}"], + "reason_codes": [str(code)], + "downstream_allowed_actions": ["REVIEW"], + "source_refs": [f"S2_30:{part['claim_group_id']}"], "status": "OPEN", + }) + issue_source_keys.append(f"S2_30:{part['claim_group_id']}:CODE:{code}") + for row in part.get("adverse_fact_rows", []): + adverse_digest = digest(row) + issues.append({ + "issue_id": stable_id("ISS", part["claim_group_id"], adverse_digest), + "issue_code": "ADVERSE_FACT_PRESERVED", "technical_severity": "REVIEW", + "review_partition": "CONDITIONAL", "impact_scope": "FACT", + "scope_refs": [part["claim_group_id"]], + "source_contract_row_refs": [f"S2_30:{part['claim_group_id']}"], + "reason_codes": ["ADVERSE_FACT_PRESERVED"], + "downstream_allowed_actions": ["REVIEW"], + "source_refs": provenance_source_refs([row]) or [f"S2_30:{part['claim_group_id']}"], + "status": "OPEN", + }) + issue_source_keys.append(f"S2_30:{part['claim_group_id']}:ADVERSE:{adverse_digest}") + issues = unique_sorted(issues, ("issue_id",), code="ISSUE_ID") if issues else [] + worknotes: list[dict[str, Any]] = [] + for part in parts["WORKNOTE_PART"]: + for atom_id in part.get("worknote_atom_ids", []): + atom = atom_by_id.get(atom_id) + if atom is None or atom.get("output_section") != "worknote_only": + raise S240Error("WORKNOTE_ATOM_REF", "worknote part references a missing/non-worknote atom") + text = atom.get("text_or_slots", {}).get("draft_text") + if not isinstance(text, str) or not text: + text = canonical_bytes(atom.get("text_or_slots", {}).get("slots", [])).decode("utf-8").strip() + worknotes.append({ + "worknote_id": atom_id, "text": nfc(text), + "source_refs": provenance_source_refs(atom.get("provenance")) or [f"ATOM:{atom_id}"], + }) + assumptions: list[dict[str, Any]] = [] + assumption_source_keys: list[str] = [] + assumption_impact = {"RUN_WIDE": "GLOBAL", "CLUSTER_LOCAL": "CLAIM_GROUP", "OPTION_ONLY": "ATOMIC_CLAIM"} + for cluster_id, part in sorted(inputs["s210_handoff"]["assumption_parts"].items()): + for row in require_list(part.get("assumptions"), code="S210_ASSUMPTIONS"): + row = require_object(row, code="S210_ASSUMPTION") + local_ref = require_ident(row.get("assumption_local_ref"), code="S210_ASSUMPTION_REF") + basis = sorted(set(str(value) for value in row.get("basis_refs", []) if isinstance(value, str) and value)) + assumptions.append({ + "assumption_id": stable_id("ASM", cluster_id, local_ref), + "text": require_text(row.get("statement"), code="S210_ASSUMPTION_TEXT"), + "status": "OPEN", "source_refs": basis or [f"S2_10:{cluster_id}"], + "impact_scope": assumption_impact.get(str(row.get("impact_scope")), "CLAIM_GROUP"), + }) + assumption_source_keys.append(f"S2_10:{cluster_id}:{local_ref}") + assumptions = unique_sorted(assumptions, ("assumption_id",), code="ASSUMPTION_ID") if assumptions else [] + usage: list[dict[str, Any]] = [] + usage_source_keys: list[str] = [] + for cluster_id, part in sorted(inputs["s210_handoff"]["usage_parts"].items()): + usage.append({ + "source_stage": "S2_10", "source_scope_id": cluster_id, + "source_part_sha256": part["part_sha256"], "payload": dict(part), + }) + usage_source_keys.append(f"S2_10:{cluster_id}:{part['part_sha256']}") + for part in sorted(parts["USAGE_PART"], key=lambda row: row["claim_group_id"]): + usage.append({ + "source_stage": "S2_30", "source_scope_id": part["claim_group_id"], + "source_part_sha256": part["part_sha256"], "payload": dict(part), + }) + usage_source_keys.append(f"S2_30:{part['claim_group_id']}:{part['part_sha256']}") + relief_rows: list[dict[str, Any]] = [] + cause_rows: list[dict[str, Any]] = [] + render_errors: list[str] = [] + render_absences: list[str] = [] + rerender_equal = True + group_contracts = { + group_id: require_object(group_slice.get("claim_group"), code="GROUP_CONTRACT") + for group_id, group_slice in inputs["group_slices"].items() + } + for atom in atoms: + if atom.get("drafting_disposition") == "WORKNOTE_ONLY" or atom.get("output_section") == "worknote_only": + continue + text_slots = require_object(atom.get("text_or_slots"), code="ATOM_TEXT_OR_SLOTS") + renderer_id = require_ident(text_slots.get("renderer_id"), code="ATOM_RENDERER_ID") + branch_id = require_ident(text_slots.get("template_branch_id"), code="ATOM_BRANCH_ID") + descriptor = inputs["renderer_descriptors"].get(renderer_id) + rendered: str | None = None + try: + if descriptor is None: + raise S240Error("RENDERER_DESCRIPTOR_MISSING", "S2_20 did not freeze selected renderer") + branch = select_renderer_branch(descriptor, branch_id, allow_fixture=request["compile_mode"] == "STRUCTURAL_FIXTURE") + rendered, independent = render_segments(descriptor, branch, slot_values(text_slots)) + rerender_equal = rerender_equal and rendered.encode("utf-8") == independent.encode("utf-8") + except S240Error as exc: + if exc.code in {"RENDERER_NOT_ELIGIBLE", "RENDERER_DESCRIPTOR_MISSING", "RENDER_BRANCH_NOT_APPROVED"}: + render_absences.append(f"{atom['atom_id']}:{exc.code}") + else: + render_errors.append(f"{atom['atom_id']}:{exc.code}") + section = atom.get("output_section") + group_contract = require_object(group_contracts.get(atom["claim_group_id"]), code="ATOM_GROUP_CONTRACT") + typed_group_projection = { + "party_refs": group_contract.get("party_refs", []), + "object_refs": group_contract.get("object_refs", []), + "amount_slots": group_contract.get("amount_slots", []), + "period_slots": group_contract.get("period_slots", []), + "calculation_receipt_ids": group_contract.get("calculation_receipt_ids", []), + "counter_performance_refs": group_contract.get("counter_performance_refs", []), + } + if section in {"relief_main", "relief_cost", "relief_provisional_execution"}: + if rendered is not None: + relief_rows.append({ + "atom_id": atom["atom_id"], "atomic_claim_id": atom["atomic_claim_id"], + "claim_group_id": atom["claim_group_id"], "output_section": section, + "renderer_id": renderer_id, "branch_id": branch_id, "text": rendered, + **typed_group_projection, + }) + elif section.startswith("cause_") or section == "procedural_declaration": + text = text_slots.get("draft_text") if text_slots.get("rendering_mode") == "REVIEW_TEXT_WITH_SLOTS" else rendered + if isinstance(text, str) and text and not PLACEHOLDER.search(text): + cause_rows.append({ + "atom_id": atom["atom_id"], "atomic_claim_id": atom["atomic_claim_id"], + "claim_group_id": atom["claim_group_id"], "output_section": section, + "text": nfc(text), "source_refs": provenance_source_refs(atom.get("provenance")), + **typed_group_projection, + }) + elif rendered is None: + render_absences.append(f"{atom['atom_id']}:CAUSE_TEXT_UNAVAILABLE") + relief_rows.sort(key=lambda row: (row["claim_group_id"], row["atomic_claim_id"], row["output_section"], row["atom_id"])) + cause_rows.sort(key=lambda row: (row["claim_group_id"], row["atomic_claim_id"], row["output_section"], row["atom_id"])) + legal_assets_admitted = bool(atoms) and not render_errors and not render_absences and all( + descriptor.get("status") == "APPROVED_LEGAL_CONTENT" and descriptor.get("execution_eligible") is True + for descriptor in inputs["renderer_descriptors"].values() + ) + clean_render_allowed = request["compile_mode"] in {"SUBSET_CANARY", "PRODUCTION"} and legal_assets_admitted + relief = "\n".join(f"{index}. {row['text']}" for index, row in enumerate(relief_rows, 1)) if clean_render_allowed else "" + cause = "\n\n".join(row["text"] for row in cause_rows) if clean_render_allowed else "" + pleading = f"# 청구취지\n\n{relief}\n\n# 청구원인\n\n{cause}" if clean_render_allowed else "" + return { + "atoms": atoms, "issues": issues, "worknotes": worknotes, "usage": usage, + "assumptions": assumptions, + "conservation": { + "issue_source_keys": sorted(issue_source_keys), + "issue_ids": sorted(str(row["issue_id"]) for row in issues), + "assumption_source_keys": sorted(assumption_source_keys), + "assumption_ids": sorted(str(row["assumption_id"]) for row in assumptions), + "usage_source_keys": sorted(usage_source_keys), + }, + "relief_rows": relief_rows, "cause_rows": cause_rows, + "relief": relief, "cause": cause, "pleading": pleading, + "render_errors": sorted(set(render_errors)), "render_absences": sorted(set(render_absences)), + "rerender_equal": rerender_equal, "clean_render_allowed": clean_render_allowed, + "legal_assets_admitted": legal_assets_admitted, + "source_plan_hashes": sorted(source_plan_hashes), + } + + +def invariant_result( + invariant_id: str, observed: bool | None, reason: str, + *, source_refs: Sequence[str] = (), incomplete: bool = False, +) -> dict[str, Any]: + status = "UNEVALUABLE" if observed is None else ("PASS" if observed else "FAIL") + scope = "OK" if status == "PASS" else ("INCOMPLETE" if incomplete else "REVIEW_REQUIRED") + return { + "invariant_id": invariant_id, "evaluation_status": status, + "finding_ids": [] if status == "PASS" else [stable_id("F40", invariant_id, reason)], + "impact_scope": scope, "source_refs": sorted(set(source_refs)), + "expected": True, "observed": observed, "reason_codes": [reason], + "validator_algorithm_id": f"{ALGORITHM_VERSION}::{invariant_id}", + } + + +def invariant_results(inputs: Mapping[str, Any], reduced: Mapping[str, Any], request: Mapping[str, Any]) -> list[dict[str, Any]]: + atoms = reduced["atoms"] + relief_claims = {row["atomic_claim_id"] for row in reduced["relief_rows"]} + cause_claims = {row["atomic_claim_id"] for row in reduced["cause_rows"]} + slot_rows = [row for atom in atoms for row in atom.get("text_or_slots", {}).get("slots", []) if isinstance(row, dict)] + slot_ids = [(atom["atom_id"], row.get("slot_id")) for atom in atoms for row in atom.get("text_or_slots", {}).get("slots", []) if isinstance(row, dict)] + legal_provenance = [row for atom in atoms for row in atom.get("provenance", []) if isinstance(row, dict) and row.get("proposition_kind") == "LEGAL_PROPOSITION"] + defense_rows = [row for atom in atoms for row in atom.get("provenance", []) if isinstance(row, dict) and "REBUTTAL" in str(row.get("proposition_kind", ""))] + binding_rows = [row for pack in inputs["rule_packs"].values() for row in pack.get("binding_rows", []) if isinstance(row, dict)] + binding_by_claim: dict[str, list[dict[str, Any]]] = {} + for row in binding_rows: + binding_by_claim.setdefault(str(row.get("atomic_claim_id")), []).append(row) + selected_claims = {str(row.get("atomic_claim_id")) for row in binding_rows if row.get("case_type_binding_status") == "BOUND" and row.get("sub_rule_binding_status") == "BOUND"} + all_claims = {str(atom.get("atomic_claim_id")) for atom in atoms} + calculation_tokens = [row for row in slot_rows if row.get("value_kind") == "CALCULATION_TOKEN"] + calc_observed: bool | None = None if not calculation_tokens else bool(inputs["calculation_receipts"]) + provenance_complete = all(bool(provenance_source_refs(atom.get("provenance"))) for atom in atoms) + option_ids: list[str] = [] + partition_ids: list[str] = [] + option_evaluable = False + for group_slice in inputs["group_slices"].values(): + claim_group = group_slice.get("claim_group", {}) + if isinstance(claim_group, dict): + ids = claim_group.get("claim_option_ids", claim_group.get("option_ids", [])) + if isinstance(ids, list): + option_ids.extend(str(item) for item in ids) + partition = claim_group.get("option_partition", {}) + if isinstance(partition, dict): + option_evaluable = True + for name in ("selected", "alternative", "excluded", "deferred"): + values = partition.get(name, []) + if isinstance(values, list): + partition_ids.extend(str(item) for item in values) + option_ok = None if not option_evaluable else len(partition_ids) == len(set(partition_ids)) and set(partition_ids) == set(option_ids) + exhibit_rows = inputs["exhibit_register"].get("rows") + exhibit_ok = None if not isinstance(exhibit_rows, list) else all(isinstance(row, dict) for row in exhibit_rows) + authority_ok = None if not legal_provenance else all(row.get("authority_id") and row.get("locator") for row in legal_provenance) + closure_rows = inputs.get("input_closure_rows", []) + expected_closure = { + "ingress/ingress_status.json": ("stage2_s2_00_ingress_status.v1", "stage2_s2_00_ingress_status.v1.1", "S2_00"), + "map_s2_10/s2_10_publish_status.json": ("stage2_s2_10_publish_status.v2", "S2_10_NATIVE_RESULT_ADAPTER"), + "plan/plan_publish_status.json": ("stage2_plan_publish_status.v1", "S2_20"), + "map_s2_30/s2_30_publish_status.json": ("stage2_s2_30_publish_status.v1", "S2_30"), + "map_s2_30/artifact_manifest.json": ("stage2_s2_30_part_manifest_core.v1", "S2_30"), + } + closure_by_path = {str(row.get("path")): row for row in closure_rows if isinstance(row, dict)} + v01 = ( + len(closure_rows) == len(closure_by_path) + and set(expected_closure).issubset(closure_by_path) + and all( + row.get("schema_valid") is True + and row.get("hash_match") is True + and row.get("sha256") == row.get("expected_sha256") + and HEX64.fullmatch(str(row.get("sha256", ""))) + and isinstance(row.get("schema_ref"), str) + for row in closure_rows if isinstance(row, dict) + ) + ) + if v01: + for path, allowed in expected_closure.items(): + row = closure_by_path[path] + version_allowed = allowed[:-1] + producer = allowed[-1] + if not ( + row.get("schema_version") in version_allowed + and row.get("producer_id") == producer + and row.get("schema_valid") is True + and row.get("hash_match") is True + and row.get("sha256") == row.get("expected_sha256") + and HEX64.fullmatch(str(row.get("sha256", ""))) + and isinstance(row.get("schema_ref"), str) + ): + v01 = False + break + atom_groups = {str(atom.get("claim_group_id")) for atom in atoms} + source_atoms = [row for part in inputs["parts"]["DRAFT_PART"] for row in part.get("canonical_atoms", [])] + source_atom_ids = [str(row.get("atom_id")) for row in source_atoms if isinstance(row, dict)] + reduced_atom_ids = [str(row.get("atom_id")) for row in atoms] + source_worknote_ids = sorted( + str(atom_id) for part in inputs["parts"]["WORKNOTE_PART"] + for atom_id in part.get("worknote_atom_ids", []) + ) + conservation = require_object(reduced.get("conservation"), code="V02_CONSERVATION") + issue_source_keys = require_list(conservation.get("issue_source_keys"), code="V02_ISSUE_KEYS") + assumption_source_keys = require_list(conservation.get("assumption_source_keys"), code="V02_ASSUMPTION_KEYS") + usage_source_keys = require_list(conservation.get("usage_source_keys"), code="V02_USAGE_KEYS") + v02 = ( + bool(atoms) + and atom_groups == set(inputs["group_ids"]) + and len(source_atom_ids) == len(set(source_atom_ids)) + and sorted(source_atom_ids) == sorted(reduced_atom_ids) + and len(issue_source_keys) == len(set(issue_source_keys)) == len(reduced["issues"]) + and len(assumption_source_keys) == len(set(assumption_source_keys)) == len(reduced["assumptions"]) + and len(usage_source_keys) == len(set(usage_source_keys)) == len(reduced["usage"]) + and source_worknote_ids == sorted(str(row.get("worknote_id")) for row in reduced["worknotes"]) + and inputs["s210_handoff"]["cluster_ids"] == inputs["ingress"]["executable_cluster_ids"] + ) + v03 = all(row.get("slot_id") and row.get("namespace_owner") and row.get("domain_id") for row in slot_rows) if slot_rows else None + v04 = all( + row.get("opposing_fact_id") and row.get("rebuttal_id") and row.get("evidence_refs") + and row.get("polarity") and row.get("presentation_status") + for row in defense_rows + ) if defense_rows else None + v05 = all( + isinstance(group_slice.get("claim_group"), dict) + and group_slice.get("claim_group", {}).get("dependency_wave_id") + and group_slice.get("claim_group", {}).get("relation_consistency_status") == "PASS" + for group_slice in inputs["group_slices"].values() + ) if inputs["group_slices"] else None + v07 = all( + token.get("calculation_receipt_id") in inputs["calculation_receipts"] + and token.get("operand_digest") == inputs["calculation_receipts"][token["calculation_receipt_id"]].get("operand_digest") + and inputs["calculation_receipts"][token["calculation_receipt_id"]].get("missing_law_values") in ([], None) + for token in calculation_tokens + ) if calculation_tokens else None + recovery_keys = [(atom.get("recovery_object_id"), atom.get("recovery_scope")) for atom in atoms if atom.get("recovery_object_id")] + v08 = len(recovery_keys) == len(set(recovery_keys)) if recovery_keys else None + canonical_plan = inputs["plan_documents"].get("plan/canonical_relief_plan.json") + canonical_plan_raw = inputs["plan_raw_by_path"].get("plan/canonical_relief_plan.json") + plan_claims = { + str(row.get("atomic_claim_id")): row + for row in (canonical_plan.get("atomic_claims", []) if isinstance(canonical_plan, dict) else []) + if isinstance(row, dict) + } + plan_hash = digest(canonical_plan_raw) if isinstance(canonical_plan_raw, bytes) else None + v09 = all( + atom.get("source_plan_sha256") == plan_hash + and atom.get("atomic_claim_id") in plan_claims + and plan_claims[atom["atomic_claim_id"]].get("claim_group_id") == atom.get("claim_group_id") + and atom.get("claim_option_id") in plan_claims[atom["atomic_claim_id"]].get("source_claim_option_ids", []) + and len(binding_by_claim.get(str(atom.get("atomic_claim_id")), [])) == 1 + for atom in atoms + ) if atoms else None + v10 = (not reduced["render_errors"] and not reduced["render_absences"] and + all(row.get("output_section") and row.get("text") for row in reduced["relief_rows"] + reduced["cause_rows"])) if atoms else None + def relation_signature(row: Mapping[str, Any]) -> tuple[str, str, str, str, str, str, str]: + return ( + str(row.get("atomic_claim_id")), digest(row.get("party_refs", [])), + digest(row.get("object_refs", [])), digest(row.get("amount_slots", [])), + digest(row.get("period_slots", [])), digest(row.get("calculation_receipt_ids", [])), + digest(row.get("counter_performance_refs", [])), + ) + relief_relation = {relation_signature(row) for row in reduced["relief_rows"]} + cause_relation = {relation_signature(row) for row in reduced["cause_rows"]} + v11 = relief_relation == cause_relation if relief_relation or cause_relation else None + v12 = all(pack.get("corpus_release_sha256") and pack.get("slot_crosswalk_status") == "PASS" and pack.get("injection_isolation_status") == "PASS" for pack in inputs["plan_documents"].values() if isinstance(pack, dict) and pack.get("schema_version") == "stage2_requirement_fact_pack.v1") or None + v13 = all(row.get("authority_id") and row.get("locator") and row.get("temporal_scope_status") == "PASS" and row.get("negative_treatment_status") == "CLEAR" for row in legal_provenance) if legal_provenance else None + def contains_downstream_key(value: Any) -> bool: + forbidden_keys = { + "candidate_content_digest", "review_subject_digest", "review_receipt_sha256s", + "stage2_package_sha256", "commit_intent_sha256", + "commit_result_sha256", "status_event_sha256", + } + if isinstance(value, dict): + return any(key in forbidden_keys or contains_downstream_key(item) for key, item in value.items()) + if isinstance(value, list): + return any(contains_downstream_key(item) for item in value) + return False + v14 = not contains_downstream_key({ + "parts": inputs.get("parts"), "group_slices": inputs.get("group_slices"), + "rule_packs": inputs.get("rule_packs"), "plan_documents": inputs.get("plan_documents"), + "ingress_documents": inputs.get("ingress_documents"), + "s210_handoff": inputs.get("s210_handoff"), + }) and inputs.get("frozen_source_rows") == sorted( + inputs.get("frozen_source_rows", []), key=lambda row: (row["path"], row["sha256"]) + ) if atoms else None + v15 = all(atom.get("provenance") and all(row.get("source_ref") or row.get("source_refs") for row in atom.get("provenance", []) if isinstance(row, dict)) for atom in atoms) if atoms else None + v17 = all(row.get("party_id") and row.get("object_id") and row.get("exhibit_id") and row.get("party_title") for row in exhibit_rows) if isinstance(exhibit_rows, list) and exhibit_rows else None + renderer_observed: bool | None = ( + False if reduced["render_errors"] else + (None if reduced["render_absences"] else bool(reduced["relief_rows"] or reduced["cause_rows"]) and reduced["rerender_equal"]) + ) + checks = { + "V01": invariant_result("V01", v01, "BOUND_INPUT_HASH_SCHEMA_PRODUCER", incomplete=True), + "V02": invariant_result("V02", v02, "REVIEW_UNIVERSE_CONSERVED", incomplete=True), + "V03": invariant_result("V03", v03, "DOMAIN_SLOT_NAMESPACE_BOUND"), + "V04": invariant_result("V04", v04, "DEFENSE_REBUTTAL_PROVENANCE_BOUND"), + "V05": invariant_result("V05", v05, "DEPENDENCY_WAVE_BOUND"), + "V06": invariant_result("V06", all(len(binding_by_claim.get(claim, [])) == 1 and claim in selected_claims for claim in all_claims) if all_claims else None, "CASE_TYPE_SUB_RULE_EXACT"), + "V07": invariant_result("V07", v07, "CALCULATION_RECEIPT_BOUND"), + "V08": invariant_result("V08", v08, "DUPLICATE_RECOVERY_ABSENT"), + "V09": invariant_result("V09", v09, "RELIEF_PLAN_MATCH"), + "V10": invariant_result("V10", v10, "DOCUMENT_ORDER_TEMPLATE_MATCH"), + "V11": invariant_result("V11", v11, "RELIEF_CAUSE_CROSSMATCH"), + "V12": invariant_result("V12", v12, "CORPUS_BOUND"), + "V13": invariant_result("V13", v13, "AUTHORITY_TEMPORAL_BOUND"), + "V14": invariant_result("V14", v14, "NON_CYCLIC_DIGEST_GRAPH"), + "V15": invariant_result("V15", v15, "PROVENANCE_COMPLETE"), + "V16": invariant_result("V16", option_ok, "OPTION_PARTITION_EXACT"), + "V17": invariant_result("V17", v17, "PARTY_OBJECT_EXHIBIT_COMPLETE"), + "V18": invariant_result("V18", renderer_observed, "CLOSED_RENDER_AND_RERENDER_EQUAL"), + } + return [checks[invariant_id] for invariant_id in V_IDS] + + +def review_request_basis( + inputs: Mapping[str, Any], + validation: Sequence[Mapping[str, Any]], + review_policy_contract: Mapping[str, Any], + parent_release_sha256: str, +) -> dict[str, Any]: + review_policies = [ + value for value in inputs.get("frozen_assets", {}).values() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + if len(review_policies) > 1: + raise S240Error("REVIEW_POLICY_CARDINALITY", "multiple frozen review policies") + policy = review_policies[0] if review_policies else None + policy_sha256 = digest(policy) if policy is not None else digest({"status": "MISSING_REVIEW_POLICY"}) + corpus_hashes = sorted({ + str(value.get("corpus_release_sha256")) for value in inputs.get("plan_documents", {}).values() + if isinstance(value, dict) and value.get("schema_version") == "stage2_requirement_fact_pack.v1" + }) + release_sha256s = { + "parent": parent_release_sha256, + "authority": require_hex(inputs.get("authority_release_sha256"), code="REVIEW_AUTHORITY_RELEASE_HASH"), + "corpus": corpus_hashes[0] if len(corpus_hashes) == 1 and HEX64.fullmatch(corpus_hashes[0]) else digest(corpus_hashes), + "case_type_coverage": require_hex(inputs.get("case_type_coverage_sha256"), code="REVIEW_CASE_TYPE_COVERAGE_HASH"), + } + return { + "schema_version": "stage2_s2_40_review_request_basis.v1", + "required_receipt_types": review_policy_contract["required_receipt_types"], + "scope_ids": inputs["group_ids"], + "finding_ids": sorted(row["finding_ids"][0] for row in validation if row["finding_ids"]), + "policy_version": str(policy.get("schema_version")) if policy is not None else "MISSING_REVIEW_POLICY", + "policy_sha256": policy_sha256, + "reviewer_role": TRUSTED_REVIEW_ROLE, + "reviewer_qualification": TRUSTED_REVIEW_QUALIFICATION, + "release_snapshot_sha256s": release_sha256s, + } + + +def review_subject( + candidate_digest: str, + lawyer_review_packet_core_sha256: str, + validation_envelope_core_sha256: str, + basis: Mapping[str, Any], +) -> dict[str, Any]: + cores: list[dict[str, Any]] = [] + bindings: list[dict[str, str]] = [] + for receipt_type in require_list(basis.get("required_receipt_types"), code="REVIEW_REQUIRED_TYPES"): + core = { + "candidate_content_digest": candidate_digest, "receipt_type": receipt_type, + "scope_ids": basis["scope_ids"], "finding_ids": basis["finding_ids"], + "policy_version": basis["policy_version"], "policy_sha256": basis["policy_sha256"], + "reviewer_role": basis["reviewer_role"], + "reviewer_qualification": basis["reviewer_qualification"], + "release_snapshot_sha256s": basis["release_snapshot_sha256s"], + } + cores.append(core) + bindings.append({ + "receipt_type": str(receipt_type), + "review_request_core_sha256": digest(core), + }) + bindings.sort(key=lambda row: row["receipt_type"]) + if len(bindings) != len({row["receipt_type"] for row in bindings}): + raise S240Error("REVIEW_REQUEST_TYPE_DUPLICATE", "review request receipt types must be unique") + subject_core = { + "schema_version": "stage2_s2_40_review_subject.v1", + "domain_separator": "STAGE2_S2_40_REVIEW_SUBJECT_V1", + "candidate_content_digest": candidate_digest, + "review_request_core_bindings": bindings, + "lawyer_review_packet_core_sha256": lawyer_review_packet_core_sha256, + "validation_envelope_core_sha256": validation_envelope_core_sha256, + "finding_ids": basis["finding_ids"], "scope_ids": basis["scope_ids"], + "review_policy_sha256": basis["policy_sha256"], + "release_sha256s": basis["release_snapshot_sha256s"], + } + subject = digest(subject_core) + core_by_type = {str(core["receipt_type"]): core for core in cores} + requests = [ + { + "request_id": stable_id( + "RR40", "STAGE2_S2_40_REVIEW_REQUEST_V1", subject, + binding["receipt_type"], *sorted(basis["scope_ids"]), + ), + "receipt_type": binding["receipt_type"], + "core": core_by_type[binding["receipt_type"]], + "core_sha256": binding["review_request_core_sha256"], + "review_subject_digest": subject, + } + for binding in bindings + ] + return { + "review_subject_digest": subject, + "subject": {**subject_core, "review_subject_digest": subject}, + "bindings": bindings, "requests": requests, + } + + +def aggregate_validation(validation: Sequence[Mapping[str, Any]]) -> dict[str, str]: + scopes = {row.get("impact_scope") for row in validation} + if "INCOMPLETE" in scopes: + run_status = "TECHNICAL_INCOMPLETE" + elif any(row.get("evaluation_status") != "PASS" for row in validation): + run_status = "TECHNICAL_REVIEW_REQUIRED" + else: + run_status = "CONSISTENT" + artifact_status = ( + "NOT_PRODUCED" if run_status == "TECHNICAL_INCOMPLETE" + else ("TECHNICAL_REVIEW_REQUIRED" if run_status == "TECHNICAL_REVIEW_REQUIRED" else "CONSISTENT") + ) + return {"run_technical_status": run_status, "artifact_technical_status": artifact_status} + + +def legal_gate_snapshot(inputs: Mapping[str, Any], reduced: Mapping[str, Any]) -> dict[str, bool]: + binding_rows = [ + row for pack in inputs["rule_packs"].values() + for row in pack.get("binding_rows", []) if isinstance(row, dict) + ] + review_policies = [ + value for value in inputs.get("frozen_assets", {}).values() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + structured_rules = [ + value for path, value in inputs.get("frozen_assets", {}).items() + if "case_type_relief_rules" in path + ] + calculations = list(inputs.get("calculation_receipts", {}).values()) + requirement_packs = [ + value for value in inputs.get("plan_documents", {}).values() + if isinstance(value, dict) and value.get("schema_version") == "stage2_requirement_fact_pack.v1" + ] + authority_release = require_object(inputs.get("authority_release"), code="AUTHORITY_RELEASE_OBJECT") + authority_signature = authority_release.get("signature") + authority_ok = ( + authority_release.get("status") == "PRODUCTION_ADMITTED" + and authority_release.get("release_class") == "PRODUCTION_RELEASE" + and authority_release.get("sealed") is True + and authority_release.get("signed") is True + and authority_release.get("executable") is True + and authority_release.get("unresolved") == [] + and isinstance(authority_signature, str) and bool(authority_signature) + and not authority_signature.startswith("PENDING") + and require_object(authority_release.get("registry"), code="AUTHORITY_REGISTRY_REF").get("required_status") == "VERIFIED" + and authority_release.get("hash_binding_status") == "PRODUCTION_ADMITTED" + ) + coverage = require_object(inputs.get("case_type_coverage"), code="CASE_TYPE_COVERAGE_OBJECT") + coverage_rows = require_list(coverage.get("coverage_rows"), code="CASE_TYPE_COVERAGE_ROWS") + case_registry = require_object(inputs.get("case_type_registry"), code="CASE_TYPE_REGISTRY_OBJECT") + rule_registry = require_object(inputs.get("case_type_rule_registry"), code="CASE_TYPE_RULE_REGISTRY_OBJECT") + case_rows = require_list(case_registry.get("rows"), code="CASE_TYPE_REGISTRY_ROWS") + rule_rows = require_list(rule_registry.get("rows"), code="CASE_TYPE_RULE_REGISTRY_ROWS") + approved_values = {"APPROVED", "VERIFIED", "IMPLEMENTED", "RELEASED", "PRODUCTION_ADMITTED", "PASS"} + downstream_keys = { + "relief_rule", "renderer", "corpus", "substantive_profile", + "special_law_or_overlay", "calculation", "review_policy", + } + expected_case_ids = [f"CT-{index:03d}" for index in range(1, 138)] + expected_catalog_ids = [f"CAT-{index:03d}" for index in range(1, 138)] + coverage_ids = [row.get("case_type_id") for row in coverage_rows if isinstance(row, dict)] + case_ids = [row.get("case_type_id") for row in case_rows if isinstance(row, dict)] + rule_ids = [row.get("case_type_id") for row in rule_rows if isinstance(row, dict)] + claim_capable_ids = [ + str(row.get("case_type_id")) for row in case_rows if isinstance(row, dict) + and row.get("claim_capable_disposition") == "CLAIM_CAPABLE" + ] + coverage_rows_ok = ( + coverage_ids == expected_case_ids + and case_ids == expected_case_ids + and rule_ids == expected_case_ids + and case_registry.get("catalog_row_ids") == expected_catalog_ids + and [row.get("catalog_row_id") for row in case_rows] == expected_catalog_ids + and [row.get("source_ordinal") for row in case_rows] == list(range(1, 138)) + and [row.get("canonical_name_ko") for row in coverage_rows] + == [row.get("source_label") for row in case_rows] + ) + for row, registry_row, rule_row in zip(coverage_rows, case_rows, rule_rows): + if not isinstance(row, dict): + coverage_rows_ok = False + continue + downstream = row.get("downstream_coverage") + rule_branches = rule_row.get("rule_branches") if isinstance(rule_row, dict) else None + branch_or_nonclaim_ok = ( + isinstance(rule_branches, list) + and bool(rule_branches) + and all(isinstance(branch, dict) and branch.get("legal_content_status") == "APPROVED" for branch in rule_branches) + ) or ( + isinstance(rule_row, dict) + and rule_row.get("non_claim_disposition") in {"COMPANION_ONLY", "CLASSIFICATION_ONLY"} + and isinstance(rule_row.get("companion_case_type_ids"), list) + ) + if ( + row.get("catalog_mapping_status") not in approved_values + or row.get("legal_signoff") not in approved_values + or row.get("technical_verification") not in approved_values + or row.get("release_status") not in approved_values + or not isinstance(downstream, dict) + or set(downstream) != downstream_keys + or any(value not in approved_values for value in downstream.values()) + or row.get("issue_codes") != [] + or not isinstance(registry_row, dict) + or registry_row.get("legal_classification_status") != "APPROVED" + or registry_row.get("legal_content_status") != "APPROVED" + or not isinstance(rule_row, dict) + or rule_row.get("legal_classification_status") != "APPROVED" + or rule_row.get("legal_content_status") != "APPROVED" + or not branch_or_nonclaim_ok + ): + coverage_rows_ok = False + coverage_catalog = require_object(coverage.get("catalog"), code="CASE_TYPE_COVERAGE_CATALOG") + coverage_dependency = require_object(coverage.get("registry_dependency"), code="CASE_TYPE_COVERAGE_REGISTRY_DEPENDENCY") + coverage_summary = require_object(coverage.get("summary"), code="CASE_TYPE_COVERAGE_SUMMARY") + coverage_ok = ( + coverage.get("release_eligible") is True + and coverage.get("status") == "FULL_137_PRODUCTION_READY" + and coverage_catalog.get("sha256") == case_registry.get("catalog_source_sha256") + and coverage_dependency.get("path") == CASE_TYPE_REGISTRY_REL + and coverage_dependency.get("sha256") == inputs.get("case_type_registry_sha256") + and rule_registry.get("case_type_registry_ref") == CASE_TYPE_REGISTRY_REL + and rule_registry.get("case_type_registry_sha256") == inputs.get("case_type_registry_sha256") + and coverage_summary.get("total_case_type_rows") == 137 + and coverage_summary.get("markdown_doc_count") == 137 + and coverage.get("release_scope_catalog_row_ids") == expected_catalog_ids + and coverage.get("excluded_catalog_row_ids") == [] + and coverage.get("release_scope_claim_capable_ids") == claim_capable_ids + and coverage_rows_ok + ) + gates = { + "binding": bool(binding_rows) and all(row.get("case_type_binding_status") == "BOUND" and row.get("sub_rule_binding_status") == "BOUND" for row in binding_rows), + "authority": authority_ok, + "renderer_branch": reduced["legal_assets_admitted"], + "rule_sub_rule": bool(structured_rules) and all(value.get("execution_eligible") is True and value.get("status") in {"APPROVED", "LEGAL_CONTENT_ADMITTED"} for value in structured_rules), + "review_policy": len(review_policies) == 1 and review_policies[0].get("execution_eligible") is True and review_policies[0].get("status") == "APPROVED_LEGAL_CONTENT", + "case_type_coverage_137": coverage_ok, + "corpus": bool(requirement_packs) and all(require_hex(value.get("corpus_release_sha256"), code="CORPUS_RELEASE_HASH") for value in requirement_packs), + "law_value": all(row.get("calculation_status") == "CALCULATED" and not row.get("missing_law_values") for row in calculations) if calculations else True, + "calculator": all(row.get("calculation_status") == "CALCULATED" for row in calculations) if calculations else True, + "required_receipts": False, + } + if set(gates) != REQUIRED_LEGAL_GATES: + raise S240Error("LEGAL_GATE_SET", "legal gate set is not closed") + return gates + + +def resolve_review_policy_contract( + inputs: Mapping[str, Any], validation: Sequence[Mapping[str, Any]], legal_gates: Mapping[str, bool], +) -> dict[str, Any]: + policy_values = [ + (path, value) for path, value in inputs.get("frozen_assets", {}).items() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + if len(policy_values) > 1: + raise S240Error("REVIEW_POLICY_CARDINALITY", "multiple frozen review policies") + policy_path, policy = policy_values[0] if len(policy_values) == 1 else ( + "MISSING_REVIEW_POLICY", {"status": "MISSING_REVIEW_POLICY"}, + ) + active_tags = sorted({ + str(reason) for row in validation if row.get("evaluation_status") != "PASS" + for reason in row.get("reason_codes", []) + }) + runtime_triggers = sorted( + str(row.get("invariant_id")) for row in validation if row.get("evaluation_status") != "PASS" + ) + approved = policy.get("execution_eligible") is True and policy.get("status") == "APPROVED_LEGAL_CONTENT" + final_contract = policy.get("final_review_contract") if isinstance(policy.get("final_review_contract"), dict) else {} + allowed_types = set(final_contract.get("policy_result_enum", [ + "STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW", + ])) + if approved: + required_types = list(final_contract.get("base_required_receipt_types", [])) + for row in policy.get("policy_rows", []) if isinstance(policy.get("policy_rows"), list) else []: + if not isinstance(row, dict): + raise S240Error("REVIEW_POLICY_ROW", "review policy row must be an object") + row_tags = set(row.get("trigger_tags", row.get("active_tags", []))) + row_triggers = set(row.get("runtime_triggers", row.get("invariant_ids", []))) + if row.get("always_required") is True or row_tags.intersection(active_tags) or row_triggers.intersection(runtime_triggers): + required_types.extend(row.get("required_receipt_types", [])) + else: + default = policy.get("default_unapproved_result") if isinstance(policy.get("default_unapproved_result"), dict) else {} + required_types = list(default.get("required_receipt_types", ["STANDARD_ATTORNEY_REVIEW"])) + if any(not isinstance(value, str) or value not in allowed_types for value in required_types): + raise S240Error("REVIEW_POLICY_RECEIPT_TYPE", "policy emitted a receipt type outside its closed enum") + required_types = sorted(set(required_types)) + if "MANDATORY_SPECIALIST_REVIEW" in required_types: + base_policy = "MANDATORY_SPECIALIST_REVIEW" + elif "STANDARD_ATTORNEY_REVIEW" in required_types: + base_policy = "STANDARD_ATTORNEY_REVIEW" + else: + fallback = final_contract.get("missing_or_unapproved_policy_result", "STANDARD_ATTORNEY_REVIEW") + base_policy = fallback if fallback in allowed_types else "STANDARD_ATTORNEY_REVIEW" + pre_receipt_ready = ( + approved + and not active_tags + and all(value for key, value in legal_gates.items() if key != "required_receipts") + ) + return { + "policy_path": policy_path, "policy": policy, + "policy_registry_sha256": digest(policy), "base_policy": base_policy, + "active_tags": active_tags, "runtime_triggers": runtime_triggers, + "required_receipt_types": required_types, + "pre_receipt_ready_eligible": pre_receipt_ready, + } + + +def candidate_material(inputs: Mapping[str, Any], reduced: Mapping[str, Any], validation: Sequence[Mapping[str, Any]], request: Mapping[str, Any]) -> dict[str, Any]: + schema_store = require_object(inputs.get("schema_store"), code="OUTPUT_SCHEMA_STORE") + documents: dict[str, bytes] = {} + if reduced["clean_render_allowed"]: + documents = { + "claim_relief.md": canonical_markdown(reduced["relief"]), + "claim_cause.md": canonical_markdown(reduced["cause"]), + "pleading_draft.md": canonical_markdown(reduced["pleading"]), + } + legal_gates = legal_gate_snapshot(inputs, reduced) + review_contract = resolve_review_policy_contract(inputs, validation, legal_gates) + conservation = require_object(reduced.get("conservation"), code="CONSERVATION_OBJECT") + issue_source_keys = require_list(conservation.get("issue_source_keys"), code="ISSUE_SOURCE_KEYS") + assumption_source_keys = require_list(conservation.get("assumption_source_keys"), code="ASSUMPTION_SOURCE_KEYS") + usage_source_keys = require_list(conservation.get("usage_source_keys"), code="USAGE_SOURCE_KEYS") + if ( + len(issue_source_keys) != len(set(issue_source_keys)) + or len(issue_source_keys) != len(reduced["issues"]) + or len(assumption_source_keys) != len(set(assumption_source_keys)) + or len(assumption_source_keys) != len(reduced["assumptions"]) + or len(usage_source_keys) != len(set(usage_source_keys)) + or len(usage_source_keys) != len(reduced["usage"]) + ): + raise S240Error("REVIEW_UNIVERSE_CONSERVATION", "issue/assumption/usage occurrence universe was not conserved") + source_ledger_hashes = sorted({ + digest(inputs["ingress_raws"]["review/issue_ledger.base.json"]), + digest(inputs["plan_raw_by_path"]["plan/issue_ledger.plan.json"]), + }) + s210_issue_hashes = { + digest(raw) for path, raw in inputs["s210_handoff"]["raw_by_path"].items() + if path.startswith("map_s2_10/issue_patches/") + } + s230_issue_hashes = { + row["sha256"] for row in inputs["rows"] if row["part_family"] == "ISSUE_PATCH" + } + ledger = { + "schema_version": "stage2_s2_40_final_issue_ledger.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "source_ledger_sha256s": source_ledger_hashes, + "source_issue_part_sha256s": sorted(s210_issue_hashes | s230_issue_hashes), + "issues": reduced["issues"], "conservation_status": "PASS", + } + s210_assumption_hashes = sorted({ + digest(raw) for path, raw in inputs["s210_handoff"]["raw_by_path"].items() + if path.startswith("map_s2_10/assumption_parts/") + }) + assumptions = { + "schema_version": "stage2_s2_40_assumption_ledger.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "source_assumption_part_sha256s": s210_assumption_hashes, + "rows": reduced["assumptions"], "conservation_status": "PASS", + } + source_usage_hashes = sorted({ + row["source_part_sha256"] for row in reduced["usage"] + }) + usage_projection = { + "schema_version": "stage2_s2_40_usage_projection.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "source_usage_part_sha256s": source_usage_hashes, + "rows": reduced["usage"], "conservation_status": "PASS", + } + worknotes_core = { + "schema_version": "stage2_s2_40_attorney_worknotes_core.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "rows": reduced["worknotes"], + } + render_diagnostic = { + "schema_version": "stage2_s2_40_render_diagnostic.v1", + "render_errors": reduced["render_errors"], "render_absences": reduced["render_absences"], + "independent_rerender_equal": reduced["rerender_equal"], + } + review_policy_core = { + "schema_version": "stage2_s2_40_review_policy_core.v1", + "policy_registry_sha256": review_contract["policy_registry_sha256"], + "base_policy": review_contract["base_policy"], + "active_tags": review_contract["active_tags"], + "runtime_triggers": review_contract["runtime_triggers"], + "required_receipt_types": review_contract["required_receipt_types"], + "pre_receipt_ready_eligible": review_contract["pre_receipt_ready_eligible"], + } + review_basis = review_request_basis( + inputs, validation, review_contract, request["expected_parent_stage2_release_sha256"], + ) + dependency_snapshot = { + "parent_release_sha256": request["expected_parent_stage2_release_sha256"], + "upstream_barrier_sha256s": [ + request["expected_ingress_status_sha256"], request["expected_s2_10_publish_status_sha256"], + request["expected_plan_publish_status_sha256"], request["expected_s2_30_publish_status_sha256"], + ], + "ordered_source_digest": inputs["input_snapshot_digest"], + } + ordered_source_preimage = { + "schema_version": "stage2_s2_40_ordered_source_snapshot_preimage.v1", + "ordered_sha256s": inputs["input_snapshot_preimage"], + "snapshot_digest": inputs["input_snapshot_digest"], + } + generated_pre_manifest = ( + (ledger, "schemas/review_status.schema.json#/$defs/final_issue_ledger", "GENERATED_FINAL_ISSUE_SCHEMA"), + (assumptions, "schemas/review_status.schema.json#/$defs/assumption_ledger", "GENERATED_ASSUMPTION_SCHEMA"), + (usage_projection, "schemas/package.schema.json#/$defs/usage_projection", "GENERATED_USAGE_SCHEMA"), + (worknotes_core, "schemas/package.schema.json#/$defs/attorney_worknotes_core", "GENERATED_WORKNOTES_CORE_SCHEMA"), + (render_diagnostic, "schemas/package.schema.json#/$defs/render_diagnostic", "GENERATED_RENDER_DIAGNOSTIC_SCHEMA"), + (review_policy_core, "schemas/package.schema.json#/$defs/review_policy_core", "GENERATED_REVIEW_POLICY_CORE_SCHEMA"), + (dependency_snapshot, "schemas/package.schema.json#/$defs/dependency_snapshot", "GENERATED_DEPENDENCY_SCHEMA"), + (ordered_source_preimage, "schemas/package.schema.json#/$defs/ordered_source_snapshot_preimage", "GENERATED_ORDERED_SOURCE_SCHEMA"), + (review_basis, "schemas/package.schema.json#/$defs/review_request_basis", "GENERATED_REVIEW_BASIS_SCHEMA"), + (inputs["frozen_source_rows"], "schemas/package.schema.json#/$defs/frozen_source_rows", "GENERATED_FROZEN_SOURCE_SCHEMA"), + (legal_gates, "schemas/package.schema.json#/$defs/legal_gate_snapshot", "GENERATED_LEGAL_GATE_SCHEMA"), + ) + for value, schema_ref, code in generated_pre_manifest: + validate_schema_instance(value, schema_ref, schema_store, code=code) + pre_payloads: dict[str, tuple[bytes, str | None, str]] = { + "issue_ledger.final.json": (canonical_bytes(ledger), "schemas/review_status.schema.json#/$defs/final_issue_ledger", "application/json"), + "assumption_ledger.json": (canonical_bytes(assumptions), "schemas/review_status.schema.json#/$defs/assumption_ledger", "application/json"), + "llm_usage_projection.json": (canonical_bytes(usage_projection), "schemas/package.schema.json#/$defs/usage_projection", "application/json"), + "attorney_worknotes.core.json": (canonical_bytes(worknotes_core), "schemas/package.schema.json#/$defs/attorney_worknotes_core", "application/json"), + "render_diagnostic.json": (canonical_bytes(render_diagnostic), "schemas/package.schema.json#/$defs/render_diagnostic", "application/json"), + "review_policy_core.json": (canonical_bytes(review_policy_core), "schemas/package.schema.json#/$defs/review_policy_core", "application/json"), + "upstream_dependency_snapshot.json": (canonical_bytes(dependency_snapshot), "schemas/package.schema.json#/$defs/dependency_snapshot", "application/json"), + "ordered_source_snapshot_preimage.json": ( + canonical_bytes(ordered_source_preimage), + "schemas/package.schema.json#/$defs/ordered_source_snapshot_preimage", + "application/json", + ), + "review_request_basis.json": (canonical_bytes(review_basis), "schemas/package.schema.json#/$defs/review_request_basis", "application/json"), + "frozen_source_rows.json": (canonical_bytes(inputs["frozen_source_rows"]), "schemas/package.schema.json#/$defs/frozen_source_rows", "application/json"), + "legal_gate_snapshot.json": (canonical_bytes(legal_gates), "schemas/package.schema.json#/$defs/legal_gate_snapshot", "application/json"), + } + for name, payload in documents.items(): + pre_payloads[name] = (payload, None, "text/markdown; charset=utf-8") + artifact_rows = [ + { + "path": name, "raw_sha256": digest(payload), "content_type": content_type, + "size_bytes": len(payload), "schema_ref": schema_ref, "producer_id": "S2_40", + } + for name, (payload, schema_ref, content_type) in sorted(pre_payloads.items()) + ] + manifest_core = { + "schema_version": "stage2_s2_40_candidate_manifest_core.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], "candidate_attempt_id": request["candidate_attempt_id"], + "dependency_snapshot": dependency_snapshot, "artifacts": artifact_rows, + } + validate_schema_instance( + manifest_core, "schemas/package.schema.json#/$defs/candidate_manifest_core", + schema_store, code="GENERATED_CANDIDATE_MANIFEST_SCHEMA", + ) + manifest_hash = digest(manifest_core) + statuses = aggregate_validation(validation) + validation_core = { + "schema_version": "stage2_s2_40_validation_core.v1", + "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "candidate_manifest_core_sha256": manifest_hash, + "invariant_results": list(validation), + "run_technical_status": statuses["run_technical_status"], + "artifact_technical_status": statuses["artifact_technical_status"], + } + validate_schema_instance( + validation_core, "schemas/package.schema.json#/$defs/validation_core", + schema_store, code="GENERATED_VALIDATION_CORE_SCHEMA", + ) + validation_hash = digest(validation_core) + document_sha256s = { + "claim_relief": digest(documents.get("claim_relief.md", b"")), + "claim_cause": digest(documents.get("claim_cause.md", b"")), + "pleading_draft": digest(documents.get("pleading_draft.md", b"")), + } + digest_core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + "run_binding_digest": request["run_binding_digest"], + "dependency_snapshot_sha256": digest(dependency_snapshot), + "candidate_manifest_core_sha256": manifest_hash, + "document_sha256s": document_sha256s, + "attorney_worknotes_core_sha256": digest(worknotes_core), + "final_issue_ledger_sha256": digest(ledger), + "assumption_ledger_sha256": digest(assumptions), + "validation_core_sha256": validation_hash, + "ordered_source_dependency_snapshot_digest": inputs["input_snapshot_digest"], + } + candidate_digest = digest(digest_core) + digest_envelope = { + **digest_core, + "candidate_content_digest": candidate_digest, + } + validate_schema_instance( + digest_envelope, "schemas/package.schema.json#/$defs/candidate_digest_envelope", + schema_store, code="GENERATED_CANDIDATE_DIGEST_SCHEMA", + ) + worknotes = { + "schema_version": "stage2_s2_40_attorney_worknotes.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], "candidate_content_digest": candidate_digest, + "rows": reduced["worknotes"], + } + validate_schema_instance( + worknotes, "schemas/package.schema.json#/$defs/attorney_worknotes", + schema_store, code="GENERATED_ATTORNEY_WORKNOTES_SCHEMA", + ) + packet_core = { + "schema_version": "stage2_s2_40_lawyer_review_packet_core.v1", + "candidate_content_digest": candidate_digest, + "finding_ids": sorted(row["finding_ids"][0] for row in validation if row["finding_ids"]), + "scope_ids": inputs["group_ids"], + "document_refs": sorted(documents) or ["issue_ledger.final.json"], + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + validation_envelope_core = { + "schema_version": "stage2_s2_40_validation_envelope_core.v1", + "candidate_content_digest": candidate_digest, + "validation_core_sha256": validation_hash, + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + subject = review_subject( + candidate_digest, digest(packet_core), digest(validation_envelope_core), review_basis, + ) + validate_schema_instance( + packet_core, "schemas/package.schema.json#/$defs/lawyer_review_packet_core", + schema_store, code="GENERATED_REVIEW_PACKET_CORE_SCHEMA", + ) + validate_schema_instance( + validation_envelope_core, "schemas/package.schema.json#/$defs/validation_envelope_core", + schema_store, code="GENERATED_VALIDATION_ENVELOPE_CORE_SCHEMA", + ) + validate_schema_instance( + subject["subject"], "schemas/package.schema.json#/$defs/review_subject", + schema_store, code="GENERATED_REVIEW_SUBJECT_SCHEMA", + ) + packet = { + "schema_version": "stage2_s2_40_lawyer_review_packet.v1", + "lawyer_review_packet_core": packet_core, + "lawyer_review_packet_core_sha256": digest(packet_core), + "review_subject_digest": subject["review_subject_digest"], + } + validation_envelope = { + "schema_version": "stage2_s2_40_validation_envelope.v1", + "validation_envelope_core": validation_envelope_core, + "validation_envelope_core_sha256": digest(validation_envelope_core), + "review_subject_digest": subject["review_subject_digest"], + } + review_policy_result = { + "schema_version": "stage2_s2_40_review_policy_result.v1", + "candidate_content_digest": candidate_digest, + "policy_registry_sha256": review_contract["policy_registry_sha256"], + "base_policy": review_contract["base_policy"], + "active_tags": review_contract["active_tags"], + "runtime_triggers": review_contract["runtime_triggers"], + "required_receipt_types": review_contract["required_receipt_types"], + "ready_eligible": review_contract["pre_receipt_ready_eligible"], + } + for value, schema_ref, code in ( + (packet, "schemas/package.schema.json#/$defs/lawyer_review_packet", "GENERATED_REVIEW_PACKET_SCHEMA"), + (validation_envelope, "schemas/package.schema.json#/$defs/validation_envelope", "GENERATED_VALIDATION_ENVELOPE_SCHEMA"), + (review_policy_result, "schemas/review_status.schema.json#/$defs/review_policy_result", "GENERATED_REVIEW_POLICY_RESULT_SCHEMA"), + ): + validate_schema_instance(value, schema_ref, schema_store, code=code) + return { + "documents": documents, "pre_payloads": pre_payloads, "ledger": ledger, + "assumptions": assumptions, "usage_projection": usage_projection, "worknotes": worknotes, + "validation_core": validation_core, "manifest_core": manifest_core, + "validation_envelope": validation_envelope, + "candidate_digest_envelope": digest_envelope, "candidate_digest": candidate_digest, + "review": subject, "packet": packet, "legal_gates": legal_gates, + "review_policy_result": review_policy_result, "review_policy_path": review_contract["policy_path"], + "schema_store": schema_store, + } + + +def publish_candidate(client: McpClient, request: Mapping[str, Any], material: Mapping[str, Any]) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + candidate_digest = material["candidate_digest"] + candidate_root = join_path(root, "candidates/by-content-digest", candidate_digest) + outputs: list[tuple[str, bytes]] = [ + ("candidate_package_manifest.json", canonical_bytes(material["manifest_core"])), + ("candidate_content_digest.json", canonical_bytes(material["candidate_digest_envelope"])), + ("attorney_worknotes.json", canonical_bytes(material["worknotes"])), + ("validation_core.json", canonical_bytes(material["validation_core"])), + ("validation_envelope.json", canonical_bytes(material["validation_envelope"])), + ("review_subject.json", canonical_bytes(material["review"]["subject"])), + ("lawyer_review_packet.json", canonical_bytes(material["packet"])), + ] + outputs.extend((name, payload[0]) for name, payload in sorted(material["pre_payloads"].items())) + outputs.extend(sorted(material["documents"].items())) + deduplicated: dict[str, bytes] = {} + for name, payload in outputs: + if name in deduplicated and deduplicated[name] != payload: + raise S240Error("CANDIDATE_ARTIFACT_CONFLICT", f"candidate path conflicts: {name}") + deduplicated[name] = payload + rows: list[dict[str, Any]] = [] + for rel, payload in sorted(deduplicated.items()): + path = join_path(candidate_root, rel) + observed = client.write_immutable(path, payload) + rows.append({"path": path, "raw_sha256": observed, "size_bytes": len(payload), "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8"}) + review = material["review"] + review_publications: list[dict[str, Any]] = [] + for request_row in review["requests"]: + request_envelope = { + "schema_version": "stage2_s2_40_review_request.v1", + "request_id": request_row["request_id"], + "review_request_core": request_row["core"], + "review_request_core_sha256": request_row["core_sha256"], + "review_subject_digest": request_row["review_subject_digest"], + } + validate_schema_instance( + request_envelope, "schemas/review_status.schema.json#/$defs/review_request", + material["schema_store"], code="GENERATED_REVIEW_REQUEST_SCHEMA", + ) + review_path = join_path(root, "review/review_requests", f"{request_row['request_id']}.json") + review_hash = client.write_immutable(review_path, canonical_bytes(request_envelope)) + review_publications.append({ + "receipt_type": request_row["receipt_type"], "path": review_path, + "sha256": review_hash, "request": request_envelope, + }) + return { + "candidate_root": candidate_root, "artifact_rows": rows, + "review_requests": review_publications, + } + + +def validate_review_receipts(client: McpClient, request: Mapping[str, Any], material: Mapping[str, Any]) -> tuple[bool, bool, list[dict[str, Any]]]: + refs = request["review_receipt_refs"] + required_types = set(material["review_policy_result"].get("required_receipt_types", [])) + expected_requests = { + str(row["receipt_type"]): row + for row in require_list(material["review"].get("requests"), code="REVIEW_EXPECTED_REQUESTS") + } + if set(expected_requests) != required_types or len(expected_requests) != len(material["review"]["requests"]): + raise S240Error("REVIEW_REQUEST_SET", "review request map differs from required receipt types") + if not refs: + return not required_types, False, [] + rows: list[dict[str, Any]] = [] + content_change = False + approved_types: set[str] = set() + seen_types: set[str] = set() + schema_store = require_object(material.get("schema_store"), code="REVIEW_SCHEMA_STORE") + for ref in refs: + raw: bytes | None = None + value: dict[str, Any] = {} + reasons: list[str] = [] + try: + raw = client.read_binary(ref) + value = require_object(load_json(raw, label=ref), code="REVIEW_RECEIPT_OBJECT") + if client.read_binary(ref) != raw: + reasons.append("REVIEW_RECEIPT_TOCTOU") + if canonical_bytes(value) != raw: + reasons.append("REVIEW_RECEIPT_NON_CANONICAL") + try: + validate_schema_instance( + value, "schemas/review_status.schema.json#/$defs/review_receipt", + schema_store, code="REVIEW_RECEIPT_SCHEMA", + ) + except S240Error as exc: + reasons.append(exc.code) + receipt_type = value.get("receipt_type") + expected_request = expected_requests.get(str(receipt_type)) + if expected_request is None: + reasons.append("REVIEW_RECEIPT_TYPE_NOT_REQUIRED") + if receipt_type in seen_types: + reasons.append("REVIEW_RECEIPT_TYPE_DUPLICATE") + seen_types.add(str(receipt_type)) + expected_core = expected_request.get("core", {}) if expected_request is not None else {} + if expected_request is None or ( + value.get("request_id") != expected_request.get("request_id") + or value.get("candidate_content_digest") != material["candidate_digest"] + or value.get("review_subject_digest") != material["review"]["review_subject_digest"] + or value.get("finding_ids") != expected_core.get("finding_ids") + or value.get("scope_ids") != expected_core.get("scope_ids") + or value.get("reviewer_role") != expected_core.get("reviewer_role") + or value.get("reviewer_qualification") != expected_core.get("reviewer_qualification") + ): + reasons.append("REVIEW_RECEIPT_SUBJECT") + if ( + value.get("reviewer_role") != TRUSTED_REVIEW_ROLE + or value.get("reviewer_qualification") != TRUSTED_REVIEW_QUALIFICATION + or value.get("issuer_id") != TRUSTED_REVIEW_ISSUER + or value.get("key_id") not in TRUSTED_REVIEW_KEY_IDS + or value.get("signature_algorithm") != TRUSTED_REVIEW_SIGNATURE_ALGORITHM + ): + reasons.append("REVIEW_RECEIPT_ISSUER") + if value.get("cryptographic_verification_status") != "VERIFIED_BY_EXTERNAL_ADAPTER" or value.get("revocation_status") != "NOT_REVOKED": + reasons.append("REVIEW_RECEIPT_TRUST") + if HEX64.fullmatch(str(value.get("external_verification_attestation_sha256", ""))) is None: + reasons.append("REVIEW_RECEIPT_EXTERNAL_ATTESTATION") + try: + issued = datetime.fromisoformat(str(value.get("issued_at")).replace("Z", "+00:00")) + expires = datetime.fromisoformat(str(value.get("expires_at")).replace("Z", "+00:00")) + now = datetime.now(timezone.utc) + if issued.tzinfo is None or expires.tzinfo is None or issued > now or expires <= now or expires <= issued: + reasons.append("REVIEW_RECEIPT_TIME") + except (TypeError, ValueError): + reasons.append("REVIEW_RECEIPT_TIME") + disposition = value.get("review_disposition") + change_scope = value.get("change_scope") + expected_signed_material = digest([ + "STAGE2_S2_40_REVIEW_RECEIPT_V1", value.get("request_id"), + value.get("candidate_content_digest"), value.get("review_subject_digest"), + value.get("receipt_type"), value.get("finding_ids"), value.get("scope_ids"), + value.get("reviewer_role"), value.get("reviewer_qualification"), + value.get("issuer_id"), value.get("key_id"), value.get("signature_algorithm"), + value.get("external_verification_attestation_sha256"), + value.get("issued_at"), value.get("expires_at"), + value.get("revocation_status"), value.get("cryptographic_verification_status"), + disposition, change_scope, value.get("reason_codes"), + ]) + if value.get("signed_material_digest") != expected_signed_material: + reasons.append("REVIEW_RECEIPT_SIGNED_SCOPE") + if disposition == "CONTENT_CHANGE_REQUIRED": + if change_scope not in {"STAGE1_CONTEXT", "LEGAL_JUDGMENT", "PLAN_RULE_CALCULATION_BINDING", "DRAFTING_TEXT_ATOM"}: + reasons.append("REVIEW_CHANGE_SCOPE") + elif disposition != "APPROVE_AS_IS" or change_scope != "NONE": + reasons.append("REVIEW_RECEIPT_DISPOSITION") + except (S240Error, TypeError, ValueError) as exc: + reasons.append(exc.code if isinstance(exc, S240Error) else "REVIEW_RECEIPT_PARSE") + if not reasons and value.get("review_disposition") == "CONTENT_CHANGE_REQUIRED": + content_change = True + if not reasons and value.get("review_disposition") == "APPROVE_AS_IS": + approved_types.add(str(value.get("receipt_type"))) + row = { + "path": ref, "receipt_id": value.get("receipt_id"), + "receipt_type": value.get("receipt_type"), + "disposition": value.get("review_disposition"), + "change_scope": value.get("change_scope"), + "validation_status": "VALID" if not reasons else "INVALID", + "reason_codes": sorted(set(reasons)), + } + if raw is not None: + row["sha256"] = digest(raw) + rows.append(row) + approved = not content_change and approved_types == required_types and len(rows) == len(required_types) and all( + row.get("validation_status") == "VALID" for row in rows + ) + return approved, content_change, rows + + +def final_status( + client: McpClient, + request: Mapping[str, Any], + preflight_digest: str, + inputs: Mapping[str, Any], + material: Mapping[str, Any], + publication: Mapping[str, Any], + approved: bool, + content_change: bool, + review_rows: Sequence[Mapping[str, Any]], +) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + candidate_digest = material["candidate_digest"] + validation_rows = material["validation_core"]["invariant_results"] + all_pass = len(validation_rows) == 18 and all( + row["evaluation_status"] == "PASS" for row in validation_rows + ) + effective_gates = dict(material["legal_gates"]) + effective_gates["required_receipts"] = approved + full_production_gates = ( + request["compile_mode"] == "PRODUCTION" + and all_pass + and bool(material["documents"]) + and effective_gates == {key: True for key in REQUIRED_LEGAL_GATES} + and material["review_policy_result"]["ready_eligible"] + ) + receipt_hashes = sorted({ + str(row["sha256"]) for row in review_rows + if row.get("validation_status") == "VALID" + and HEX64.fullmatch(str(row.get("sha256", ""))) + }) + validation_hash = digest(material["validation_core"]) + review_subject_digest = material["review"]["review_subject_digest"] + if content_change: + scope_order = { + "STAGE1_CONTEXT": (0, "RESTART_FROM_S2_00"), + "LEGAL_JUDGMENT": (1, "RESTART_FROM_S2_10"), + "PLAN_RULE_CALCULATION_BINDING": (2, "RESTART_FROM_S2_20"), + "DRAFTING_TEXT_ATOM": (3, "RESTART_FROM_S2_30"), + } + scopes = [ + row["change_scope"] for row in review_rows + if row.get("validation_status") == "VALID" + and row.get("disposition") == "CONTENT_CHANGE_REQUIRED" + and row.get("change_scope") in scope_order + ] + if not scopes: + raise S240Error("REVIEW_CHANGE_SCOPE_MISSING", "content-change receipt lacks earliest-owner scope") + phase, route = "SUPERSEDED", scope_order[min(scopes, key=lambda value: scope_order[value][0])][1] + elif not full_production_gates: + phase, route = "AWAITING_EXTERNAL_REVIEW", "WAIT_EXTERNAL_REVIEW" + else: + phase, route = "READY_TO_COMMIT", "CONTINUE_TO_COMMIT" + artifact_set_digest: str | None = None + stage2_package_sha256: str | None = None + commit_intent_sha256: str | None = None + commit_result_sha256: str | None = None + if phase == "READY_TO_COMMIT": + final_payloads: dict[str, bytes] = { + "candidate_package_manifest.json": canonical_bytes(material["manifest_core"]), + "candidate_content_digest.json": canonical_bytes(material["candidate_digest_envelope"]), + "attorney_worknotes.json": canonical_bytes(material["worknotes"]), + "lawyer_review_packet.json": canonical_bytes(material["packet"]), + "stage2_final_validation_report.json": canonical_bytes(material["validation_core"]), + "review_policy_result.json": canonical_bytes(material["review_policy_result"]), + } + for rel, value in sorted(material["pre_payloads"].items()): + if rel in final_payloads and final_payloads[rel] != value[0]: + raise S240Error("FINAL_ARTIFACT_CONFLICT", f"final artifact path conflicts: {rel}") + final_payloads[rel] = value[0] + final_payloads.update(material["documents"]) + package_artifacts = [ + { + "path": join_path(root, "final", rel), "raw_sha256": digest(payload), + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, "producer_id": "S2_40", + } + for rel, payload in sorted(final_payloads.items()) + ] + package = { + "schema_version": "stage2_s2_40_package.v1", + "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "compile_mode": request["compile_mode"], + "candidate_manifest_core_sha256": digest(material["manifest_core"]), + "artifacts": package_artifacts, + "validation_report_sha256": validation_hash, + "review_policy_result_sha256": digest(material["review_policy_result"]), + "review_receipt_sha256s": receipt_hashes, + "filing_decision_receipt_sha256": None, + "run_technical_status": "CONSISTENT", + "artifact_technical_status": "CONSISTENT", + "legal_readiness": "READY_FOR_LAWYER_FILING_DECISION", + "filing_permission": "NOT_GRANTED", + } + validate_schema_instance( + package, "schemas/package.schema.json#/$defs/stage2_package", + material["schema_store"], code="GENERATED_STAGE2_PACKAGE_SCHEMA", + ) + package_payload = canonical_bytes(package) + stage2_package_sha256 = digest(package_payload) + final_payloads["stage2_package.json"] = package_payload + expected_rows = [ + { + "path": join_path(root, "final", rel), "raw_sha256": digest(payload), + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, + } + for rel, payload in sorted(final_payloads.items()) + ] + intent_core = { + "schema_version": "stage2_s2_40_commit_intent.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "candidate_attempt_id": request["candidate_attempt_id"], + "candidate_manifest_core_sha256": digest(material["manifest_core"]), + "validation_report_sha256": validation_hash, + "review_subject_digest": review_subject_digest, + "review_receipt_sha256s": receipt_hashes, + "stage2_package_sha256": stage2_package_sha256, + "expected_artifacts": expected_rows, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "request_sha256": request["_request_sha256"], + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + } + intent = {**intent_core, "intent_digest": digest(intent_core)} + validate_schema_instance( + intent, "schemas/deployment.schema.json#/$defs/s2_40_commit_intent", + material["schema_store"], code="GENERATED_COMMIT_INTENT_SCHEMA", + ) + intent_path = join_path(root, "commit/commit_intent.json") + commit_intent_sha256 = client.write_immutable(intent_path, canonical_bytes(intent)) + final_rows: list[dict[str, Any]] = [] + for rel, payload in sorted(final_payloads.items()): + path = join_path(root, "final", rel) + observed = client.write_immutable(path, payload) + final_rows.append({ + "path": path, "raw_sha256": observed, + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, + }) + if final_rows != expected_rows: + raise S240Error("COMMIT_EXPECTED_ROWS", "written final rows differ from commit intent") + artifact_set_digest = digest(final_rows) + result_core = { + "schema_version": "stage2_s2_40_commit_result.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "commit_intent_sha256": commit_intent_sha256, + "artifact_set_digest": artifact_set_digest, + "artifact_rows": final_rows, + "readback_status": "PASS", "conflicting_target_count": 0, + "missing_target_count_after_write": 0, + } + result = {**result_core, "commit_result_digest": digest(result_core)} + validate_schema_instance( + result, "schemas/deployment.schema.json#/$defs/s2_40_commit_result", + material["schema_store"], code="GENERATED_COMMIT_RESULT_SCHEMA", + ) + commit_result_sha256 = client.write_immutable( + join_path(root, "commit/stage2_commit_result.json"), canonical_bytes(result), + ) + phase, route = "COMMITTED", "PACKAGE_COMMITTED" + aggregate = aggregate_validation(validation_rows) + if aggregate["run_technical_status"] == "TECHNICAL_INCOMPLETE": + artifact_status, legal_readiness = "NOT_PRODUCED", "NOT_ASSESSED" + else: + artifact_status = aggregate["artifact_technical_status"] + legal_readiness = "READY_FOR_LAWYER_FILING_DECISION" if full_production_gates else "LAWYER_REVIEW_REQUIRED" + return write_terminal_status( + client, request, workflow_phase=phase, route=route, + candidate_content_digest=candidate_digest, + run_technical_status=aggregate["run_technical_status"], + artifact_technical_status=artifact_status, legal_readiness=legal_readiness, + validation_report_sha256=validation_hash, + review_subject_digest=review_subject_digest, + review_receipt_sha256s=receipt_hashes, + stage2_package_sha256=stage2_package_sha256, + artifact_set_digest=artifact_set_digest, + commit_intent_sha256=commit_intent_sha256, + commit_result_sha256=commit_result_sha256, + schema_store=material["schema_store"], + ) + + +def verify_frozen_candidate_digest_chain( + expected: str, + manifest: Mapping[str, Any], + envelope: Mapping[str, Any], + pre_payloads: Mapping[str, tuple[bytes, str | None, str]], + documents: Mapping[str, bytes], + validation_core: Mapping[str, Any], +) -> dict[str, Any]: + """Recompute every pre-review candidate digest edge from frozen bytes.""" + def payload_json(name: str) -> Any: + if name not in pre_payloads: + raise S240Error("RESUME_REQUIRED_ARTIFACT", f"required frozen artifact missing: {name}") + raw = pre_payloads[name][0] + value = load_json(raw, label=name) + if canonical_bytes(value) != raw: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {name}") + return value + + dependency = require_object(manifest.get("dependency_snapshot"), code="RESUME_DEPENDENCY_SNAPSHOT") + persisted_dependency = require_object( + payload_json("upstream_dependency_snapshot.json"), code="RESUME_PERSISTED_DEPENDENCY", + ) + if persisted_dependency != dependency: + raise S240Error("RESUME_DEPENDENCY_SNAPSHOT_DRIFT", "embedded and persisted dependency snapshots differ") + ordered_preimage = require_object( + payload_json("ordered_source_snapshot_preimage.json"), code="RESUME_ORDERED_SOURCE_PREIMAGE", + ) + ordered_hashes = require_list(ordered_preimage.get("ordered_sha256s"), code="RESUME_ORDERED_SOURCE_HASHES") + for value in ordered_hashes: + require_hex(value, code="RESUME_ORDERED_SOURCE_HASH") + ordered_digest = digest(ordered_hashes) + if ( + ordered_preimage.get("snapshot_digest") != ordered_digest + or dependency.get("ordered_source_digest") != ordered_digest + ): + raise S240Error("RESUME_ORDERED_SOURCE_DIGEST", "ordered source preimage digest differs") + worknotes_core = require_object( + payload_json("attorney_worknotes.core.json"), code="RESUME_WORKNOTES_CORE", + ) + ledger = require_object(payload_json("issue_ledger.final.json"), code="RESUME_FINAL_ISSUE_LEDGER") + assumptions = require_object(payload_json("assumption_ledger.json"), code="RESUME_ASSUMPTION_LEDGER") + document_sha256s = { + "claim_relief": digest(documents.get("claim_relief.md", b"")), + "claim_cause": digest(documents.get("claim_cause.md", b"")), + "pleading_draft": digest(documents.get("pleading_draft.md", b"")), + } + digest_core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + "run_binding_digest": manifest.get("run_binding_digest"), + "dependency_snapshot_sha256": digest(dependency), + "candidate_manifest_core_sha256": digest(manifest), + "document_sha256s": document_sha256s, + "attorney_worknotes_core_sha256": digest(worknotes_core), + "final_issue_ledger_sha256": digest(ledger), + "assumption_ledger_sha256": digest(assumptions), + "validation_core_sha256": digest(validation_core), + "ordered_source_dependency_snapshot_digest": ordered_digest, + } + recomputed = digest(digest_core) + if recomputed != expected or envelope != {**digest_core, "candidate_content_digest": recomputed}: + raise S240Error("RESUME_CANDIDATE_DIGEST_CHAIN", "frozen candidate digest chain does not recompute exactly") + return { + "dependency": dependency, "ordered_source_preimage": ordered_preimage, + "worknotes_core": worknotes_core, "ledger": ledger, "assumptions": assumptions, + } + + +def hydrate_frozen_candidate(client: McpClient, request: Mapping[str, Any]) -> dict[str, Any]: + """RESUME validates and re-derives the frozen candidate without upstream rerendering.""" + root = request["stage2_run_root_ref"] + expected = require_hex(request["expected_candidate_content_digest"], code="RESUME_CANDIDATE_HASH") + schema_store = load_output_schema_store(client) + + def canonical_bound_json(path: str, expected_sha256: str | None = None) -> tuple[dict[str, Any], bytes]: + value, raw = read_bound_json(client, path, expected_sha256) + if canonical_bytes(value) != raw: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {path}") + return value, raw + + previous, _ = canonical_bound_json( + join_path(root, "control/run_status.json"), request["expected_previous_run_status_sha256"], + ) + validate_schema_instance( + previous, "schemas/review_status.schema.json#/$defs/run_status", + schema_store, code="RESUME_PREVIOUS_STATUS_SCHEMA", + ) + if ( + previous.get("candidate_content_digest") != expected + or previous.get("workflow_phase") != "AWAITING_EXTERNAL_REVIEW" + or previous.get("compile_mode") != request["compile_mode"] + or previous.get("run_binding_digest") != request["run_binding_digest"] + or previous.get("candidate_attempt_id") != request["candidate_attempt_id"] + ): + raise S240Error("RESUME_CHECKPOINT", "previous status does not bind the frozen candidate") + candidate_root = join_path(root, "candidates/by-content-digest", expected) + if PurePosixPath(candidate_root).name != expected: + raise S240Error("RESUME_CANDIDATE_DIRECTORY", "candidate directory basename differs from expected digest") + manifest, _ = canonical_bound_json(join_path(candidate_root, "candidate_package_manifest.json")) + envelope, _ = canonical_bound_json(join_path(candidate_root, "candidate_content_digest.json")) + validate_schema_instance( + manifest, "schemas/package.schema.json#/$defs/candidate_manifest_core", + schema_store, code="RESUME_CANDIDATE_MANIFEST_SCHEMA", + ) + validate_schema_instance( + envelope, "schemas/package.schema.json#/$defs/candidate_digest_envelope", + schema_store, code="RESUME_CANDIDATE_ENVELOPE_SCHEMA", + ) + expected_upstream = [ + request["expected_ingress_status_sha256"], request["expected_s2_10_publish_status_sha256"], + request["expected_plan_publish_status_sha256"], request["expected_s2_30_publish_status_sha256"], + ] + dependency = require_object(manifest.get("dependency_snapshot"), code="RESUME_DEPENDENCY_SNAPSHOT") + if ( + manifest.get("producer_id") != "S2_40" + or manifest.get("run_binding_digest") != request["run_binding_digest"] + or manifest.get("compile_mode") != request["compile_mode"] + or manifest.get("candidate_attempt_id") != request["candidate_attempt_id"] + or dependency.get("parent_release_sha256") != request["expected_parent_stage2_release_sha256"] + or dependency.get("upstream_barrier_sha256s") != expected_upstream + ): + raise S240Error("RESUME_DEPENDENCY_DRIFT", "RESUME request differs from the frozen dependency snapshot") + pre_payloads: dict[str, tuple[bytes, str | None, str]] = {} + documents: dict[str, bytes] = {} + artifact_rows = require_list(manifest.get("artifacts"), code="RESUME_ARTIFACT_ROWS") + artifact_paths = [safe_path(row.get("path"), code="RESUME_ARTIFACT_PATH") for row in artifact_rows if isinstance(row, dict)] + if len(artifact_paths) != len(artifact_rows) or artifact_paths != sorted(artifact_paths) or len(set(artifact_paths)) != len(artifact_paths): + raise S240Error("RESUME_ARTIFACT_SET", "candidate artifact paths must be unique and sorted") + for row in artifact_rows: + row = require_object(row, code="RESUME_ARTIFACT_ROW") + rel = safe_path(row.get("path"), code="RESUME_ARTIFACT_PATH") + raw_a = client.read_binary(join_path(candidate_root, rel)) + raw_b = client.read_binary(join_path(candidate_root, rel)) + if raw_a != raw_b: + raise S240Error("RESUME_ARTIFACT_TOCTOU", f"frozen candidate artifact changed: {rel}") + if digest(raw_a) != require_hex(row.get("raw_sha256"), code="RESUME_ARTIFACT_HASH") or len(raw_a) != row.get("size_bytes"): + raise S240Error("RESUME_ARTIFACT_DRIFT", f"frozen candidate artifact differs: {rel}") + content_type = str(row.get("content_type")) + schema_ref = row.get("schema_ref") + if content_type.startswith("text/markdown"): + if schema_ref is not None: + raise S240Error("RESUME_MARKDOWN_SCHEMA_REF", f"markdown must not declare JSON schema: {rel}") + documents[rel] = raw_a + else: + if not isinstance(schema_ref, str): + raise S240Error("RESUME_JSON_SCHEMA_REF", f"JSON artifact lacks schema binding: {rel}") + value = load_json(raw_a, label=rel) + if canonical_bytes(value) != raw_a: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {rel}") + validate_schema_instance(value, schema_ref, schema_store, code="RESUME_ARTIFACT_SCHEMA") + pre_payloads[rel] = (raw_a, schema_ref, content_type) + + def auxiliary_json(name: str, schema_ref: str) -> dict[str, Any]: + value, _ = canonical_bound_json(join_path(candidate_root, name)) + validate_schema_instance(value, schema_ref, schema_store, code="RESUME_AUXILIARY_SCHEMA") + return value + + validation_core = auxiliary_json("validation_core.json", "schemas/package.schema.json#/$defs/validation_core") + packet = auxiliary_json("lawyer_review_packet.json", "schemas/package.schema.json#/$defs/lawyer_review_packet") + worknotes = auxiliary_json("attorney_worknotes.json", "schemas/package.schema.json#/$defs/attorney_worknotes") + validation_envelope = auxiliary_json("validation_envelope.json", "schemas/package.schema.json#/$defs/validation_envelope") + stored_subject = auxiliary_json("review_subject.json", "schemas/package.schema.json#/$defs/review_subject") + chain = verify_frozen_candidate_digest_chain( + expected, manifest, envelope, pre_payloads, documents, validation_core, + ) + if ( + worknotes.get("candidate_content_digest") != expected + or worknotes.get("rows") != chain["worknotes_core"].get("rows") + or packet.get("lawyer_review_packet_core_sha256") != digest(packet.get("lawyer_review_packet_core")) + or validation_envelope.get("validation_envelope_core_sha256") != digest(validation_envelope.get("validation_envelope_core")) + or validation_envelope.get("validation_envelope_core", {}).get("validation_core_sha256") != digest(validation_core) + ): + raise S240Error("RESUME_AUXILIARY_DIGEST_CHAIN", "frozen auxiliary candidate objects do not recompute") + review_basis = require_object( + load_json(pre_payloads["review_request_basis.json"][0], label="review_request_basis"), + code="RESUME_REVIEW_BASIS", + ) + rebuilt_review = review_subject( + expected, packet["lawyer_review_packet_core_sha256"], + validation_envelope["validation_envelope_core_sha256"], review_basis, + ) + if ( + rebuilt_review["subject"] != stored_subject + or packet.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + or validation_envelope.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + or previous.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + ): + raise S240Error("RESUME_REVIEW_SUBJECT", "frozen review subject does not re-derive exactly") + for request_row in rebuilt_review["requests"]: + request_path = join_path(root, "review/review_requests", f"{request_row['request_id']}.json") + review_request, _ = canonical_bound_json(request_path) + validate_schema_instance( + review_request, "schemas/review_status.schema.json#/$defs/review_request", + schema_store, code="RESUME_REVIEW_REQUEST_SCHEMA", + ) + expected_request = { + "schema_version": "stage2_s2_40_review_request.v1", + "request_id": request_row["request_id"], + "review_request_core": request_row["core"], + "review_request_core_sha256": request_row["core_sha256"], + "review_subject_digest": request_row["review_subject_digest"], + } + if review_request != expected_request: + raise S240Error("RESUME_REVIEW_REQUEST_DRIFT", f"frozen review request differs: {request_row['receipt_type']}") + review_policy_core = require_object( + load_json(pre_payloads["review_policy_core.json"][0], label="review_policy_core"), + code="RESUME_REVIEW_POLICY_CORE", + ) + policy_result = { + "schema_version": "stage2_s2_40_review_policy_result.v1", + "candidate_content_digest": expected, + "policy_registry_sha256": review_policy_core.get("policy_registry_sha256"), + "base_policy": review_policy_core.get("base_policy"), + "active_tags": review_policy_core.get("active_tags"), + "runtime_triggers": review_policy_core.get("runtime_triggers"), + "required_receipt_types": review_policy_core.get("required_receipt_types"), + "ready_eligible": review_policy_core.get("pre_receipt_ready_eligible") is True, + } + validate_schema_instance( + policy_result, "schemas/review_status.schema.json#/$defs/review_policy_result", + schema_store, code="RESUME_REVIEW_POLICY_RESULT_SCHEMA", + ) + frozen_sources = require_list( + load_json(pre_payloads["frozen_source_rows.json"][0], label="frozen_source_rows"), + code="RESUME_FROZEN_SOURCE_ROWS", + ) + manifest_rows = [ + row for row in frozen_sources if isinstance(row, dict) + and row.get("path") == "map_s2_30/artifact_manifest.json" + and row.get("ref_family") == "upstream_manifest" + ] + if len(manifest_rows) != 1 or manifest_rows[0].get("sha256") != request["expected_s2_30_artifact_manifest_sha256"]: + raise S240Error("RESUME_MANIFEST_DRIFT", "RESUME request differs from frozen S2_30 artifact manifest") + legal_gates = require_object( + load_json(pre_payloads["legal_gate_snapshot.json"][0], label="legal_gate_snapshot"), + code="RESUME_LEGAL_GATES", + ) + return { + "documents": documents, "pre_payloads": pre_payloads, + "manifest_core": manifest, "candidate_digest_envelope": envelope, + "candidate_digest": expected, "validation_core": validation_core, + "packet": packet, "worknotes": worknotes, "legal_gates": legal_gates, + "review_policy_result": policy_result, "review": rebuilt_review, + "schema_store": schema_store, + } + + +def normal_route(client: McpClient, request: Mapping[str, Any], preflight_digest: str) -> dict[str, Any]: + if request["requested_transition"] == "RESUME": + inputs: dict[str, Any] = {} + material = hydrate_frozen_candidate(client, request) + publication: dict[str, Any] = {"resume_reused_frozen_candidate": True} + else: + inputs = hydrate_normal(client, request) + reduced = reduce_and_render(inputs, request) + validation = invariant_results(inputs, reduced, request) + material = candidate_material(inputs, reduced, validation, request) + publication = publish_candidate(client, request, material) + approved, content_change, review_rows = validate_review_receipts(client, request, material) + return final_status(client, request, preflight_digest, inputs, material, publication, approved, content_change, review_rows) + + +def publish_post_preflight_failure( + client: McpClient, request: Mapping[str, Any], preflight_digest: str, error: Mapping[str, Any], +) -> dict[str, Any]: + """Preserve a closed diagnostic, then publish the failure barrier last.""" + root = request["stage2_run_root_ref"] + diagnostic = { + "schema_version": "stage2_s2_40_technical_diagnostic.v1", + "writer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "reason_codes": [str(error.get("code", "INLINE_RUNTIME_ERROR"))], + "error": dict(error), "preflight_snapshot_digest": preflight_digest, + } + diagnostic_id = digest(diagnostic) + client.write_immutable( + join_path(root, "diagnostic", f"failure-{diagnostic_id}.json"), + canonical_bytes(diagnostic), + ) + return write_terminal_status( + client, request, workflow_phase="DIAGNOSTIC_ONLY", + route="STOP_TECHNICAL_INCOMPLETE", candidate_content_digest=None, + run_technical_status="TECHNICAL_INCOMPLETE", + artifact_technical_status="NOT_PRODUCED", legal_readiness="NOT_ASSESSED", + ) + + +def run() -> int: + localdocs: McpClient | None = None + request: dict[str, Any] | None = None + receipt: dict[str, Any] + exit_code = 0 + preflight_digest: str | None = None + output_schema_store: dict[str, Mapping[str, Any]] | None = None + try: + with contextlib.redirect_stdout(io.StringIO()): + if HEX64.fullmatch(INLINE_USER_HASH) is None or HEX64.fullmatch(INLINE_WORKSPACE_HASH) is None: + raise S240Error("INLINE_CONTEXT_UNBOUND", "AgentBackend user/workspace substitutions are required") + localdocs = McpClient(LOCALDOCS_URL, "localdocs") + localdocs.initialize() + request_raw = localdocs.read_binary(REQUEST_PATH) + request = validate_request(request_raw) + request["_request_sha256"] = digest(request_raw) + preflight_digest = preflight(localdocs, request) + output_schema_store = load_output_schema_store(localdocs) + publication = status_only(localdocs, request, preflight_digest) if request["entry_route"] == "TO_S2_40_STATUS_ONLY" else normal_route(localdocs, request, preflight_digest) + status = publication["status"] + receipt = { + "schema_version": "stage2_s2_40_execution_receipt.v1", + "ok": True, + "workflow_id": WORKFLOW_ID, + "request_id": request["request_id"], + "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "requested_transition": request["requested_transition"], + "workflow_phase": status["workflow_phase"], + "candidate_content_digest": status["candidate_content_digest"], + "route": status["route"], + "run_status_path": publication["status_path"], + "run_status_sha256": publication["status_sha256"], + "error": None, + } + except Exception as exc: + error = exc.as_dict() if isinstance(exc, S240Error) else {"code": "INLINE_RUNTIME_ERROR", "message": str(exc)} + failure_publication: dict[str, Any] | None = None + if localdocs is not None and request is not None and preflight_digest is not None: + try: + failure_publication = publish_post_preflight_failure(localdocs, request, preflight_digest, error) + except Exception as close_exc: + error = { + "code": "POST_PREFLIGHT_FAILURE_AND_SAFE_CLOSE_FAILED", + "message": str(exc), + "safe_close_error": close_exc.as_dict() if isinstance(close_exc, S240Error) else {"message": str(close_exc)}, + } + fallback_binding = request["run_binding_digest"] if request is not None else "0" * 64 + receipt = { + "schema_version": "stage2_s2_40_execution_receipt.v1", + "ok": False, + "workflow_id": WORKFLOW_ID, + "request_id": request["request_id"] if request is not None else "UNBOUND", + "run_binding_digest": fallback_binding, + "candidate_attempt_id": request["candidate_attempt_id"] if request is not None else "UNBOUND", + "requested_transition": request["requested_transition"] if request is not None else "FREEZE", + "workflow_phase": "DIAGNOSTIC_ONLY", + "candidate_content_digest": None, + "route": "STOP_TECHNICAL_INCOMPLETE", + "run_status_path": failure_publication["status_path"] if failure_publication is not None else None, + "run_status_sha256": failure_publication["status_sha256"] if failure_publication is not None else None, + "error": error, + } + exit_code = 2 + finally: + if localdocs is not None: + localdocs.close() + if output_schema_store is not None: + validate_schema_instance( + receipt, "schemas/deployment.schema.json#/$defs/s2_40_execution_receipt", + output_schema_store, code="GENERATED_EXECUTION_RECEIPT_SCHEMA", + ) + sys.stdout.buffer.write(canonical_bytes(receipt)) + return exit_code + + +if __name__ == "__main__": + raise SystemExit(run()) \ No newline at end of file diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_40_commit.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_40_commit.txt new file mode 100644 index 00000000..c706c1f2 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/s2_40_commit.txt @@ -0,0 +1,3518 @@ +#!/usr/bin/env python3 +"""Release-bound deterministic S2_40 finalizer. + +This module is self-contained. It never imports workspace Python, calls +an LLM, scans directories, invokes a shell, or invents legal content. +All runtime reads and writes use the localdocs MCP binary contract. +""" + +from __future__ import annotations + +import base64 +import binascii +import contextlib +from datetime import datetime, timezone +import hashlib +import io +import itertools +import json +import re +import sys +import unicodedata +from pathlib import PurePosixPath +from typing import Any, Iterable, Mapping, Sequence + + +WORKFLOW_ID = "S2_40" +ALGORITHM_VERSION = "s2_40_finalizer/1.0.0" +EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" +LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" +MCP_PROTOCOL_VERSION = "2025-03-26" +INLINE_USER_HASH = "{{__user_hash__}}" +INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}" +REQUEST_PATH = "stage2_control/s2_40_request.json" +ASSET_ROOT = "Default_Agent/Stage_2_Clean" +AGENT_PATH = f"{ASSET_ROOT}/agent_scripts/Stage_2_S2_40.yml" +BINDING_PATH = f"{ASSET_ROOT}/deployment/stage2_code_executor_binding.yml" +INLINE_RECEIPT_PATH = f"{ASSET_ROOT}/manifest/s2_40_inline_code_receipt.json" +PARENT_RELEASE_PATH = f"{ASSET_ROOT}/manifest/stage2_release.json" +MODULE_MANIFEST_PATH = f"{ASSET_ROOT}/manifest/module_manifest.json" +AUTHORITY_RELEASE_REL = "manifest/authority_release.json" +CASE_TYPE_COVERAGE_REL = "manifest/case_type_coverage.json" +CASE_TYPE_REGISTRY_REL = "manifest/case_type_registry.yml" +CASE_TYPE_RULE_REGISTRY_REL = "manifest/case_type_rule_registry.yml" +INPUT_SCHEMA_RELS = ( + "schemas/ingress.schema.json", + "schemas/context.schema.json", + "schemas/domain_verdict.schema.json", + "schemas/s2_10.schema.json", + "schemas/relief_plan.schema.json", + "schemas/binding_retrieval.schema.json", + "schemas/calculation.schema.json", + "schemas/draft_atoms.schema.json", + "schemas/package.schema.json", + "schemas/review_status.schema.json", + "schemas/deployment.schema.json", +) +MAX_FILE_BYTES = 32 * 1024 * 1024 +MAX_TOTAL_BYTES = 256 * 1024 * 1024 +MAX_ARTIFACT_ROWS = 20000 +HEX64 = re.compile(r"^[a-f0-9]{64}$") +IDENT = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$") +PLACEHOLDER = re.compile(r"\{\{([A-Za-z][A-Za-z0-9_]*)\}\}") +ENTRY_ROUTES = {"TO_S2_40", "TO_S2_40_STATUS_ONLY"} +COMPILE_MODES = {"STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"} +TRANSITIONS = {"FREEZE", "RESUME"} +V_IDS = tuple(f"V{i:02d}" for i in range(1, 19)) +PART_FAMILIES = ("DRAFT_PART", "ISSUE_PATCH", "USAGE_PART", "WORKNOTE_PART") +PART_DIRECTORIES = { + "DRAFT_PART": "draft_parts", + "ISSUE_PATCH": "issue_patches", + "USAGE_PART": "usage_parts", + "WORKNOTE_PART": "worknote_parts", +} +PART_SCHEMA_REFS = { + "DRAFT_PART": "schemas/draft_atoms.schema.json#/$defs/draft_part", + "ISSUE_PATCH": "schemas/draft_atoms.schema.json#/$defs/issue_patch_part", + "USAGE_PART": "schemas/draft_atoms.schema.json#/$defs/usage_part", + "WORKNOTE_PART": "schemas/draft_atoms.schema.json#/$defs/worknote_part", +} +COMMON_PROVENANCE_FIELDS = { + "compile_mode", "parent_stage2_release_sha256", "s2_30_release_sha256", + "s2_30_agent_sha256", "s2_30_binding_sha256", "p00_prompt_sha256", + "p30_prompt_sha256", "s2_30_producer_contract_digest", +} +GROUP_PROVENANCE_FIELDS = COMMON_PROVENANCE_FIELDS | { + "p31_rule_and_pack_sha256", "p32_common_authority_sha256", + "s30_group_slice_sha256", +} +TRUSTED_REVIEW_ISSUER = "AGENTBACKEND_STAGE2_REVIEW_AUTHORITY" +TRUSTED_REVIEW_KEY_IDS = {"AGENTBACKEND_STAGE2_REVIEW_KEY_V1"} +TRUSTED_REVIEW_SIGNATURE_ALGORITHM = "AGENTBACKEND_TRUSTED_ATTESTATION_V1" +TRUSTED_REVIEW_ROLE = "KOREAN_LAWYER" +TRUSTED_REVIEW_QUALIFICATION = "QUALIFIED_KOREAN_LAWYER" +REQUIRED_LEGAL_GATES = { + "binding", "authority", "renderer_branch", "rule_sub_rule", + "review_policy", "case_type_coverage_137", "corpus", "law_value", + "calculator", "required_receipts", +} + + +class S240Error(Exception): + def __init__(self, code: str, message: str, *, details: Any | None = None) -> None: + super().__init__(message) + self.code = code + self.message = message + self.details = details + + def as_dict(self) -> dict[str, Any]: + row: dict[str, Any] = {"code": self.code, "message": self.message} + if self.details is not None: + row["details"] = self.details + return row + + +def nfc(value: str) -> str: + return unicodedata.normalize("NFC", value) + + +def no_duplicates(pairs: list[tuple[str, Any]]) -> dict[str, Any]: + result: dict[str, Any] = {} + for key, value in pairs: + if key in result: + raise S240Error("DUPLICATE_JSON_KEY", f"duplicate JSON key: {key}") + result[key] = value + return result + + +def load_json(raw: bytes, *, label: str) -> Any: + if len(raw) > MAX_FILE_BYTES: + raise S240Error("SOURCE_SIZE_LIMIT", f"file exceeds limit: {label}") + try: + text = raw.decode("utf-8", errors="strict") + return json.loads( + text, + object_pairs_hook=no_duplicates, + parse_constant=lambda token: (_ for _ in ()).throw( + S240Error("NON_FINITE_NUMBER", f"non-finite number: {token}") + ), + ) + except (UnicodeDecodeError, json.JSONDecodeError) as exc: + raise S240Error("JSON_PARSE_ERROR", f"strict JSON parse failed: {label}") from exc + + +def canonical_bytes(value: Any) -> bytes: + return ( + json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False) + + "\n" + ).encode("utf-8") + + +def canonical_markdown(value: str) -> bytes: + if not isinstance(value, str): + raise S240Error("MARKDOWN_TYPE", "markdown must be a string") + text = nfc(value.replace("\r\n", "\n").replace("\r", "\n")).lstrip("\ufeff") + if "\x00" in text: + raise S240Error("MARKDOWN_NUL", "markdown contains NUL") + return (text.rstrip("\n") + "\n").encode("utf-8") + + +def digest(value: Any) -> str: + payload = value if isinstance(value, bytes) else canonical_bytes(value) + return hashlib.sha256(payload).hexdigest() + + +def require_hex(value: Any, *, code: str) -> str: + if not isinstance(value, str) or HEX64.fullmatch(value) is None: + raise S240Error(code, "expected lower-case SHA-256") + return value + + +def require_ident(value: Any, *, code: str) -> str: + if not isinstance(value, str) or IDENT.fullmatch(value) is None: + raise S240Error(code, "invalid identifier") + return value + + +def require_text(value: Any, *, code: str) -> str: + if not isinstance(value, str) or not value.strip(): + raise S240Error(code, "non-empty text required") + return nfc(value) + + +def safe_path(value: Any, *, code: str = "PATH_INVALID") -> str: + if not isinstance(value, str) or not value or "\x00" in value: + raise S240Error(code, "path must be a non-empty string") + if value.startswith("/") or "\\" in value: + raise S240Error(code, "absolute or backslash path is forbidden") + normalized = PurePosixPath(value) + if any(part in {"", ".", ".."} for part in normalized.parts): + raise S240Error(code, "path traversal or ambiguous component") + return normalized.as_posix() + + +def join_path(*parts: str) -> str: + return safe_path("/".join(part.strip("/") for part in parts if part)) + + +def stable_id(prefix: str, *parts: Any) -> str: + return f"{prefix}-{digest([nfc(str(part)) for part in parts])[:24]}" + + +def utc_now() -> str: + return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") + + +def require_object(value: Any, *, code: str) -> dict[str, Any]: + if not isinstance(value, dict): + raise S240Error(code, "object required") + return value + + +def require_list(value: Any, *, code: str) -> list[Any]: + if not isinstance(value, list): + raise S240Error(code, "array required") + return value + + +def _parse_mcp_payload(raw: bytes, expected_id: int) -> Mapping[str, Any]: + candidates: list[Any] + if raw.lstrip().startswith(b"{"): + try: + candidates = [load_json(raw, label="mcp-json")] + except S240Error as exc: + if exc.code != "JSON_PARSE_ERROR": + raise + try: + text = raw.decode("utf-8", errors="strict") + decoder = json.JSONDecoder(object_pairs_hook=no_duplicates) + first, offset = decoder.raw_decode(text.lstrip()) + tail = text.lstrip()[offset:].strip() + candidates = [first] + while tail: + extra, offset = decoder.raw_decode(tail) + candidates.append(extra) + tail = tail[offset:].strip() + except (UnicodeDecodeError, json.JSONDecodeError) as parse_exc: + raise S240Error("MCP_JSON_EXTRA_DATA", "invalid concatenated MCP JSON") from parse_exc + else: + try: + text = raw.decode("utf-8", errors="strict") + except UnicodeDecodeError as exc: + raise S240Error("MCP_SSE_UTF8", "invalid MCP SSE UTF-8") from exc + events: list[bytes] = [] + data_lines: list[str] = [] + for line in text.replace("\r\n", "\n").split("\n"): + if not line: + if data_lines: + events.append("\n".join(data_lines).encode("utf-8")) + data_lines = [] + continue + if line.startswith((":", "event:", "id:", "retry:")): + continue + if not line.startswith("data:"): + raise S240Error("MCP_SSE_SHAPE", "unexpected SSE line") + data_lines.append(line[5:].lstrip()) + if data_lines: + events.append("\n".join(data_lines).encode("utf-8")) + candidates = [load_json(event, label="mcp-sse-event") for event in events] + matches = [row for row in candidates if isinstance(row, dict) and row.get("id") == expected_id] + if len(matches) != 1: + raise S240Error("MCP_RESPONSE_ID", "exactly one matching JSON-RPC result required") + row = matches[0] + if row.get("jsonrpc") != "2.0" or row.get("error") is not None: + raise S240Error("MCP_JSONRPC_ERROR", "MCP returned an invalid/error response") + if not isinstance(row.get("result"), dict): + raise S240Error("MCP_RESULT_SHAPE", "MCP result must be an object") + return row + + +def _tool_text(result: Mapping[str, Any], tool: str) -> str: + if result.get("isError") is True: + rendered = str(result.get("content", "")) + code = "LOCALDOCS_NOT_FOUND" if "not found" in rendered.lower() else "MCP_TOOL_ERROR" + raise S240Error(code, f"{tool} returned isError=true") + content = result.get("content") + if not isinstance(content, list) or len(content) != 1: + raise S240Error("MCP_CONTENT_CARDINALITY", "one content block required") + block = content[0] + if not isinstance(block, dict) or block.get("type") != "text" or not isinstance(block.get("text"), str): + raise S240Error("MCP_CONTENT_SHAPE", "one text block required") + return block["text"] + + +def _binary_from_text(text: str, path: str) -> bytes: + value = load_json(text.encode("utf-8"), label=path) + if isinstance(value, dict) and isinstance(value.get("results"), list): + rows = value["results"] + if len(rows) != 1 or not isinstance(rows[0], dict): + raise S240Error("LOCALDOCS_RESULT_CARDINALITY", "one binary result required") + value = rows[0].get("content", rows[0].get("text")) + if isinstance(value, str): + value = load_json(value.encode("utf-8"), label=path) + if not isinstance(value, dict) or not isinstance(value.get("content_base64"), str): + raise S240Error("LOCALDOCS_BINARY_ENVELOPE", "content_base64 is required") + try: + raw = base64.b64decode(value["content_base64"].encode("ascii"), validate=True) + except (UnicodeEncodeError, binascii.Error, ValueError) as exc: + raise S240Error("LOCALDOCS_BASE64", "strict base64 required") from exc + if value.get("byte_length", value.get("size", len(raw))) != len(raw): + raise S240Error("LOCALDOCS_LENGTH", f"byte length mismatch: {path}") + if value.get("sha256", digest(raw)) != digest(raw): + raise S240Error("LOCALDOCS_HASH", f"raw hash mismatch: {path}") + return raw + + +class McpClient: + def __init__(self, endpoint: str, name: str) -> None: + try: + import httpx # type: ignore + except ImportError as exc: + raise S240Error("HTTPX_UNAVAILABLE", "httpx==0.28.1 is required") from exc + self.endpoint = endpoint + self.name = name + self.client = httpx.Client(timeout=60) + self.headers = {"Content-Type": "application/json", "Accept": "application/json, text/event-stream"} + self.ids = itertools.count(10) + self.initialized = False + + def close(self) -> None: + self.client.close() + + def _post(self, body: Mapping[str, Any], expected_id: int | None) -> Mapping[str, Any] | None: + try: + response = self.client.post(self.endpoint, json=dict(body), headers=dict(self.headers)) + response.raise_for_status() + except Exception as exc: + raise S240Error("MCP_TRANSPORT", f"{self.name} transport failed") from exc + session = response.headers.get("mcp-session-id") + if session: + self.headers["mcp-session-id"] = session + if expected_id is None: + return None + return _parse_mcp_payload(bytes(response.content), expected_id) + + def initialize(self) -> None: + row = self._post( + { + "jsonrpc": "2.0", "id": 1, "method": "initialize", + "params": { + "protocolVersion": MCP_PROTOCOL_VERSION, + "capabilities": {}, + "clientInfo": { + "name": "liti-s2-40-inline", "version": "1.0.0", + "user_id": INLINE_USER_HASH, "workspace_id": INLINE_WORKSPACE_HASH, + }, + }, + }, + 1, + ) + if row is None or row["result"].get("protocolVersion") != MCP_PROTOCOL_VERSION: + raise S240Error("MCP_PROTOCOL", "MCP protocol negotiation failed") + self._post({"jsonrpc": "2.0", "method": "notifications/initialized"}, None) + self.initialized = True + + def call(self, tool: str, arguments: Mapping[str, Any]) -> Mapping[str, Any]: + if not self.initialized: + raise S240Error("MCP_NOT_INITIALIZED", "initialize before tools/call") + message_id = next(self.ids) + row = self._post( + {"jsonrpc": "2.0", "id": message_id, "method": "tools/call", "params": {"name": tool, "arguments": dict(arguments)}}, + message_id, + ) + if row is None: + raise S240Error("MCP_EMPTY", f"empty response: {tool}") + return row["result"] + + def read_binary(self, path: str) -> bytes: + safe = safe_path(path) + return _binary_from_text(_tool_text(self.call("read_binary_doc", {"doc_name": safe}), "read_binary_doc"), safe) + + def read_optional(self, path: str) -> bytes | None: + try: + return self.read_binary(path) + except S240Error as exc: + if exc.code == "LOCALDOCS_NOT_FOUND": + return None + raise + + def write_immutable(self, path: str, payload: bytes) -> str: + safe = safe_path(path) + existing = self.read_optional(safe) + if existing is not None: + if existing != payload: + raise S240Error("IMMUTABLE_CONFLICT", f"existing bytes differ: {safe}") + return digest(existing) + encoded = base64.b64encode(payload).decode("ascii") + _tool_text( + self.call("write_binary_file", {"path": safe, "content_base64": encoded, "overwrite": False}), + "write_binary_file", + ) + observed = self.read_binary(safe) + if observed != payload: + raise S240Error("WRITE_READBACK_MISMATCH", f"read-back differs: {safe}") + return digest(observed) + + def write_latest(self, path: str, payload: bytes, expected_previous: str | None) -> str: + safe = safe_path(path) + existing = self.read_optional(safe) + if expected_previous is None: + if existing is not None and existing != payload: + raise S240Error("LATEST_BARRIER_CONFLICT", "unexpected previous latest barrier") + else: + if existing is None or digest(existing) != expected_previous: + raise S240Error("LATEST_BARRIER_CAS", "previous latest barrier hash mismatch") + if existing == payload: + return digest(existing) + encoded = base64.b64encode(payload).decode("ascii") + _tool_text( + self.call("write_binary_file", {"path": safe, "content_base64": encoded, "overwrite": existing is not None}), + "write_binary_file", + ) + observed = self.read_binary(safe) + if observed != payload: + raise S240Error("LATEST_READBACK_MISMATCH", "latest barrier read-back mismatch") + return digest(observed) + + +REQUEST_KEYS = { + "schema_version", "request_id", "candidate_attempt_id", "run_binding_digest", + "user_identity_hash", "workspace_identity_hash", "stage2_run_root_ref", + "entry_route", "compile_mode", "requested_transition", + "expected_previous_run_status_sha256", "expected_candidate_content_digest", + "expected_ingress_status_sha256", "expected_s2_10_publish_status_sha256", + "expected_plan_publish_status_sha256", "expected_s2_30_publish_status_sha256", + "expected_s2_30_artifact_manifest_sha256", "expected_parent_stage2_release_sha256", + "expected_s2_40_agent_sha256", "expected_s2_40_executor_binding_sha256", + "expected_s2_40_inline_code_receipt_sha256", "host_cas_receipt_ref", + "host_cas_receipt_sha256", "detached_admission_receipt_ref", + "detached_admission_receipt_sha256", "outer_execution_receipt_target_ref", + "review_receipt_refs", +} + + +def validate_request(raw: bytes) -> dict[str, Any]: + value = load_json(raw, label=REQUEST_PATH) + if not isinstance(value, dict) or set(value) != REQUEST_KEYS: + keys = set(value) if isinstance(value, dict) else set() + raise S240Error("REQUEST_CLOSED_SHAPE", "request keys differ", details={"missing": sorted(REQUEST_KEYS - keys), "extra": sorted(keys - REQUEST_KEYS)}) + if value["schema_version"] != "stage2_s2_40_request.v1": + raise S240Error("REQUEST_VERSION", "unsupported request schema") + for key in ("request_id", "candidate_attempt_id"): + require_ident(value[key], code="REQUEST_IDENTIFIER") + run_digest = require_hex(value["run_binding_digest"], code="RUN_BINDING_DIGEST") + for key in ( + "user_identity_hash", "workspace_identity_hash", "expected_ingress_status_sha256", + "expected_parent_stage2_release_sha256", "expected_s2_40_agent_sha256", + "expected_s2_40_executor_binding_sha256", "expected_s2_40_inline_code_receipt_sha256", + "host_cas_receipt_sha256", "detached_admission_receipt_sha256", + ): + require_hex(value[key], code=f"REQUEST_{key.upper()}") + for key in ( + "expected_previous_run_status_sha256", "expected_candidate_content_digest", + "expected_s2_10_publish_status_sha256", "expected_plan_publish_status_sha256", + "expected_s2_30_publish_status_sha256", "expected_s2_30_artifact_manifest_sha256", + ): + if value[key] is not None: + require_hex(value[key], code=f"REQUEST_{key.upper()}") + if value["user_identity_hash"] != INLINE_USER_HASH or value["workspace_identity_hash"] != INLINE_WORKSPACE_HASH: + raise S240Error("REQUEST_IDENTITY", "request identity differs from AgentBackend substitution") + expected_root = f"stage2_runs/by-binding/{run_digest}" + if value["stage2_run_root_ref"] != expected_root: + raise S240Error("REQUEST_RUN_ROOT", "run root must derive from binding digest") + if value["entry_route"] not in ENTRY_ROUTES or value["requested_transition"] not in TRANSITIONS: + raise S240Error("REQUEST_ENUM", "unsupported entry route or transition") + receipt_refs = require_list(value["review_receipt_refs"], code="REQUEST_REVIEW_REFS") + if len(receipt_refs) > 64 or len(set(receipt_refs)) != len(receipt_refs): + raise S240Error("REQUEST_REVIEW_REFS", "review receipt refs must be unique and bounded") + for ref in receipt_refs: + safe_path(ref, code="REQUEST_REVIEW_REF_PATH") + expected_cas = f"stage2_control/host_cas/{run_digest}/S2_40/{value['candidate_attempt_id']}/{value['requested_transition']}.json" + if value["host_cas_receipt_ref"] != expected_cas: + raise S240Error("REQUEST_CAS_PATH", "host CAS path mismatch") + if value["outer_execution_receipt_target_ref"] != f"{expected_root}/control/s2_40_outer_execution_receipt.json": + raise S240Error("REQUEST_OUTER_RECEIPT_PATH", "outer receipt target mismatch") + status_only = value["entry_route"] == "TO_S2_40_STATUS_ONLY" + upstream_keys = ( + "expected_s2_10_publish_status_sha256", "expected_plan_publish_status_sha256", + "expected_s2_30_publish_status_sha256", "expected_s2_30_artifact_manifest_sha256", + ) + if status_only: + if value["compile_mode"] is not None or value["requested_transition"] != "FREEZE": + raise S240Error("REQUEST_STATUS_ONLY_MODE", "status-only requires null mode and FREEZE") + if any(value[key] is not None for key in upstream_keys) or value["expected_candidate_content_digest"] is not None or receipt_refs: + raise S240Error("REQUEST_STATUS_ONLY_SCOPE", "status-only forbids normal input and review refs") + else: + if value["compile_mode"] not in COMPILE_MODES or any(value[key] is None for key in upstream_keys): + raise S240Error("REQUEST_NORMAL_SCOPE", "normal route requires mode and all upstream hashes") + if value["requested_transition"] == "FREEZE": + if value["expected_candidate_content_digest"] is not None: + raise S240Error("REQUEST_FREEZE_DIGEST", "FREEZE must not supply candidate digest") + if value["expected_previous_run_status_sha256"] is not None or receipt_refs: + raise S240Error("REQUEST_FREEZE_SCOPE", "FREEZE forbids previous status and review receipts") + if value["requested_transition"] == "RESUME": + if value["expected_candidate_content_digest"] is None or value["expected_previous_run_status_sha256"] is None: + raise S240Error("REQUEST_RESUME_SCOPE", "RESUME requires candidate and previous status digests") + return value + + +def read_bound_json(client: McpClient, path: str, expected_sha256: str | None = None) -> tuple[dict[str, Any], bytes]: + raw_a = client.read_binary(path) + if expected_sha256 is not None and digest(raw_a) != expected_sha256: + raise S240Error("BOUND_HASH_MISMATCH", f"raw hash mismatch: {path}") + value = require_object(load_json(raw_a, label=path), code="BOUND_OBJECT") + raw_b = client.read_binary(path) + if raw_b != raw_a: + raise S240Error("TOCTOU_INPUT_CHANGED", f"input changed between reads: {path}") + return value, raw_a + + +def read_release_bound_jsons( + client: McpClient, relative_paths: Sequence[str], +) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], list[dict[str, Any]]]: + """Read exact module-manifest members; directory discovery is never used.""" + parent_raw = client.read_binary(PARENT_RELEASE_PATH) + if digest(parent_raw) != EXPECTED_STAGE2_RELEASE_SHA256: + raise S240Error("BOUND_PARENT_DRIFT", "parent release differs from inline constant") + parent = require_object(load_json(parent_raw, label=PARENT_RELEASE_PATH), code="BOUND_PARENT_OBJECT") + require_self_hash(parent, "release_digest", code="BOUND_PARENT_SELF_HASH") + module_ref = require_object(parent.get("module_manifest_ref"), code="BOUND_MODULE_REF") + module_raw = client.read_binary(MODULE_MANIFEST_PATH) + if digest(module_raw) != require_hex(module_ref.get("sha256"), code="BOUND_MODULE_HASH"): + raise S240Error("BOUND_MODULE_HASH", "module manifest differs from parent binding") + module = require_object(load_json(module_raw, label=MODULE_MANIFEST_PATH), code="BOUND_MODULE_OBJECT") + require_self_hash(module, "manifest_digest", code="BOUND_MODULE_SELF_HASH") + rows = require_list(module.get("modules"), code="BOUND_MODULE_ROWS") + values: dict[str, dict[str, Any]] = {} + raws: dict[str, bytes] = {} + source_rows: list[dict[str, Any]] = [] + for relative in relative_paths: + relative = safe_path(relative, code="BOUND_MEMBER_PATH") + matches = [row for row in rows if isinstance(row, dict) and row.get("path") == relative] + if len(matches) != 1: + raise S240Error("BOUND_MEMBER_CARDINALITY", f"release member must be exact-one: {relative}") + member = matches[0] + expected = require_hex(member.get("sha256"), code="BOUND_MEMBER_HASH") + raw = client.read_binary(join_path(ASSET_ROOT, relative)) + if digest(raw) != expected or member.get("size_bytes") != len(raw): + raise S240Error("BOUND_MEMBER_DRIFT", f"release member bytes differ: {relative}") + value = require_object(load_json(raw, label=relative), code="BOUND_MEMBER_OBJECT") + values[relative] = value + raws[relative] = raw + source_rows.append({"path": relative, "sha256": expected, "size_bytes": len(raw)}) + return values, raws, sorted(source_rows, key=lambda row: row["path"]) + + +def json_pointer(document: Any, fragment: str) -> Any: + if fragment in {"", "#"}: + return document + pointer = fragment[1:] if fragment.startswith("#") else fragment + if not pointer.startswith("/"): + raise S240Error("SCHEMA_POINTER", f"unsupported JSON pointer: {fragment}") + current = document + for token in pointer[1:].split("/"): + token = token.replace("~1", "/").replace("~0", "~") + if isinstance(current, dict) and token in current: + current = current[token] + elif isinstance(current, list) and token.isdigit() and int(token) < len(current): + current = current[int(token)] + else: + raise S240Error("SCHEMA_POINTER", f"unresolvable JSON pointer: {fragment}") + return current + + +def resolve_schema_ref( + ref: str, current_path: str, store: Mapping[str, Mapping[str, Any]], +) -> tuple[Mapping[str, Any], str]: + if "#" in ref: + file_ref, fragment = ref.split("#", 1) + fragment = "#" + fragment + else: + file_ref, fragment = ref, "#" + if file_ref: + if file_ref.startswith("schemas/"): + target_path = safe_path(file_ref, code="SCHEMA_REF_PATH") + else: + target_path = safe_path( + str(PurePosixPath(current_path).parent / file_ref), code="SCHEMA_REF_PATH", + ) + else: + target_path = current_path + target_document = store.get(target_path) + if not isinstance(target_document, dict): + raise S240Error("SCHEMA_REF_UNBOUND", f"schema is not release-bound: {target_path}") + target = json_pointer(target_document, fragment) + return require_object(target, code="SCHEMA_REF_TARGET"), target_path + + +def schema_errors( + value: Any, + schema: Mapping[str, Any], + current_path: str, + store: Mapping[str, Mapping[str, Any]], + *, + location: str = "$", + depth: int = 0, +) -> list[str]: + """Deterministic JSON-Schema subset covering every keyword used by Stage 2 input roots.""" + if depth > 160: + return [f"{location}:schema recursion limit"] + if "$ref" in schema: + target, target_path = resolve_schema_ref(str(schema["$ref"]), current_path, store) + return schema_errors(value, target, target_path, store, location=location, depth=depth + 1) + errors: list[str] = [] + if "const" in schema and value != schema["const"]: + errors.append(f"{location}:const") + if "enum" in schema and value not in schema["enum"]: + errors.append(f"{location}:enum") + expected_type = schema.get("type") + allowed_types = [expected_type] if isinstance(expected_type, str) else expected_type + if isinstance(allowed_types, list): + def type_ok(name: str) -> bool: + return { + "object": isinstance(value, dict), + "array": isinstance(value, list), + "string": isinstance(value, str), + "integer": isinstance(value, int) and not isinstance(value, bool), + "number": isinstance(value, (int, float)) and not isinstance(value, bool), + "boolean": isinstance(value, bool), + "null": value is None, + }.get(name, True) + if not any(type_ok(str(name)) for name in allowed_types): + return errors + [f"{location}:type"] + if isinstance(value, dict): + required = schema.get("required", []) + if isinstance(required, list): + errors.extend(f"{location}.{key}:required" for key in required if key not in value) + properties = schema.get("properties", {}) + if isinstance(properties, dict): + for key, child in properties.items(): + if key in value and isinstance(child, dict): + errors.extend(schema_errors(value[key], child, current_path, store, location=f"{location}.{key}", depth=depth + 1)) + if schema.get("additionalProperties") is False: + errors.extend(f"{location}.{key}:additional" for key in value if key not in properties) + if isinstance(schema.get("minProperties"), int) and len(value) < schema["minProperties"]: + errors.append(f"{location}:minProperties") + if isinstance(value, list): + if isinstance(schema.get("minItems"), int) and len(value) < schema["minItems"]: + errors.append(f"{location}:minItems") + if isinstance(schema.get("maxItems"), int) and len(value) > schema["maxItems"]: + errors.append(f"{location}:maxItems") + if schema.get("uniqueItems") is True: + serialized = [canonical_bytes(item) for item in value] + if len(serialized) != len(set(serialized)): + errors.append(f"{location}:uniqueItems") + prefix = schema.get("prefixItems") + if isinstance(prefix, list): + for index, child in enumerate(prefix): + if index < len(value) and isinstance(child, dict): + errors.extend(schema_errors(value[index], child, current_path, store, location=f"{location}[{index}]", depth=depth + 1)) + if schema.get("items") is False and len(value) > len(prefix): + errors.append(f"{location}:additionalItems") + elif isinstance(schema.get("items"), dict): + for index, item in enumerate(value): + errors.extend(schema_errors(item, schema["items"], current_path, store, location=f"{location}[{index}]", depth=depth + 1)) + contains = schema.get("contains") + if isinstance(contains, dict) and not any(not schema_errors(item, contains, current_path, store, location=location, depth=depth + 1) for item in value): + errors.append(f"{location}:contains") + if isinstance(value, str): + if isinstance(schema.get("minLength"), int) and len(value) < schema["minLength"]: + errors.append(f"{location}:minLength") + if isinstance(schema.get("maxLength"), int) and len(value) > schema["maxLength"]: + errors.append(f"{location}:maxLength") + if isinstance(schema.get("pattern"), str) and re.search(schema["pattern"], value) is None: + errors.append(f"{location}:pattern") + if isinstance(value, (int, float)) and not isinstance(value, bool): + if isinstance(schema.get("minimum"), (int, float)) and value < schema["minimum"]: + errors.append(f"{location}:minimum") + if isinstance(schema.get("maximum"), (int, float)) and value > schema["maximum"]: + errors.append(f"{location}:maximum") + for child in schema.get("allOf", []) if isinstance(schema.get("allOf"), list) else []: + if isinstance(child, dict): + errors.extend(schema_errors(value, child, current_path, store, location=location, depth=depth + 1)) + any_of = schema.get("anyOf") + if isinstance(any_of, list) and not any(isinstance(child, dict) and not schema_errors(value, child, current_path, store, location=location, depth=depth + 1) for child in any_of): + errors.append(f"{location}:anyOf") + one_of = schema.get("oneOf") + if isinstance(one_of, list) and sum(1 for child in one_of if isinstance(child, dict) and not schema_errors(value, child, current_path, store, location=location, depth=depth + 1)) != 1: + errors.append(f"{location}:oneOf") + forbidden = schema.get("not") + if isinstance(forbidden, dict) and not schema_errors(value, forbidden, current_path, store, location=location, depth=depth + 1): + errors.append(f"{location}:not") + condition = schema.get("if") + if isinstance(condition, dict): + branch_name = "then" if not schema_errors(value, condition, current_path, store, location=location, depth=depth + 1) else "else" + branch = schema.get(branch_name) + if isinstance(branch, dict): + errors.extend(schema_errors(value, branch, current_path, store, location=location, depth=depth + 1)) + return errors[:96] + + +def validate_schema_instance( + value: Any, schema_ref: str, store: Mapping[str, Mapping[str, Any]], *, code: str, +) -> None: + target, path = resolve_schema_ref(schema_ref, "schemas/ingress.schema.json", store) + errors = schema_errors(value, target, path, store) + if errors: + raise S240Error(code, f"schema validation failed: {schema_ref}", details=errors[:16]) + + +def preflight(client: McpClient, request: Mapping[str, Any]) -> str: + if request["expected_parent_stage2_release_sha256"] != EXPECTED_STAGE2_RELEASE_SHA256: + raise S240Error("PARENT_CONSTANT_REQUEST", "request parent hash differs from inline constant") + fixed = ( + (PARENT_RELEASE_PATH, request["expected_parent_stage2_release_sha256"]), + (AGENT_PATH, request["expected_s2_40_agent_sha256"]), + (BINDING_PATH, request["expected_s2_40_executor_binding_sha256"]), + (INLINE_RECEIPT_PATH, request["expected_s2_40_inline_code_receipt_sha256"]), + (request["host_cas_receipt_ref"], request["host_cas_receipt_sha256"]), + (request["detached_admission_receipt_ref"], request["detached_admission_receipt_sha256"]), + ) + snapshot_rows: list[dict[str, Any]] = [] + fixed_raw: dict[str, bytes] = {} + for path, expected in fixed: + raw = client.read_binary(path) + if digest(raw) != expected: + raise S240Error("PREFLIGHT_HASH", f"preflight hash mismatch: {path}") + fixed_raw[path] = raw + snapshot_rows.append({"path": path, "sha256": expected, "size": len(raw)}) + parent = require_object(load_json(fixed_raw[PARENT_RELEASE_PATH], label=PARENT_RELEASE_PATH), code="PARENT_RELEASE_OBJECT") + require_self_hash(parent, "release_digest", code="PARENT_RELEASE_SELF_HASH") + module_ref = require_object(parent.get("module_manifest_ref"), code="PARENT_MODULE_REF") + if module_ref.get("path") != "manifest/module_manifest.json" or module_ref.get("binding_status") != "BOUND": + raise S240Error("PARENT_MODULE_REF", "parent does not bind canonical module manifest") + module_raw = client.read_binary(MODULE_MANIFEST_PATH) + if digest(module_raw) != require_hex(module_ref.get("sha256"), code="PARENT_MODULE_HASH"): + raise S240Error("PARENT_MODULE_HASH", "module manifest raw hash differs from parent") + module = require_object(load_json(module_raw, label=MODULE_MANIFEST_PATH), code="MODULE_MANIFEST_OBJECT") + require_self_hash(module, "manifest_digest", code="MODULE_MANIFEST_SELF_HASH") + modules = require_list(module.get("modules"), code="MODULE_ROWS") + workflow_rows = [row for row in modules if isinstance(row, dict) and row.get("module_id") == "WF-S2_40"] + if len(workflow_rows) != 1 or workflow_rows[0].get("path") != "workflows/S2_40_final_review_render_and_commit.yml": + raise S240Error("S240_MODULE_MEMBERSHIP", "exact S2_40 workflow module membership missing") + + inline_receipt = require_object(load_json(fixed_raw[INLINE_RECEIPT_PATH], label=INLINE_RECEIPT_PATH), code="INLINE_RECEIPT_OBJECT") + if (inline_receipt.get("schema_version") != "stage2_s2_40_inline_code_receipt.v1" + or inline_receipt.get("parity_status") != "PASS" + or inline_receipt.get("expected_parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or inline_receipt.get("deployment_projection", {}).get("sha256") != request["expected_s2_40_agent_sha256"] + or inline_receipt.get("deployment_projection", {}).get("path") != AGENT_PATH): + raise S240Error("INLINE_RECEIPT_MEMBERSHIP", "inline receipt does not bind parent and actual Agent") + binding_text = fixed_raw[BINDING_PATH].decode("utf-8", errors="strict") + required_binding_literals = ( + "stage_id: S2_40", "binding_id: S2-BINDING-S2_40-CODE-EXECUTOR-V1", + "path: agent_scripts/Stage_2_S2_40.yml", request["expected_s2_40_agent_sha256"], + "path: manifest/s2_40_inline_code_receipt.json", request["expected_s2_40_inline_code_receipt_sha256"], + "path: manifest/stage2_release.json", EXPECTED_STAGE2_RELEASE_SHA256, + ) + if any(literal not in binding_text for literal in required_binding_literals): + raise S240Error("BINDING_MEMBERSHIP", "binding does not bind exact S2_40 Agent/parent/receipt") + + admission = require_object(load_json(fixed_raw[request["detached_admission_receipt_ref"]], label="detached-admission"), code="ADMISSION_OBJECT") + admitted_status = "PRODUCTION_ADMITTED" if request.get("compile_mode") == "PRODUCTION" else "CANARY_ADMITTED" + if (admission.get("schema_version") != "stage2_deterministic_admission_receipt.v1" + or admission.get("parent_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or admission.get("executor_binding_sha256") != request["expected_s2_40_executor_binding_sha256"] + or admission.get("admission_status") not in {admitted_status, "PRODUCTION_ADMITTED"} + or admission.get("signature_verification_status") != "BACKEND_VERIFIED" + or admission.get("external_trust_verified") is not True + or not isinstance(admission.get("signature"), str) + or admission.get("signature", "").startswith("PENDING")): + raise S240Error("DETACHED_ADMISSION_NOT_TRUSTED", "release-bound external admission is absent or invalid") + signed_admission = { + key: value for key, value in admission.items() + if key not in {"signature", "signature_verification_status", "signed_payload_sha256"} + } + if (admission.get("signed_payload_sha256") != digest(signed_admission) + or HEX64.fullmatch(str(admission.get("backend_capability_receipt_sha256", ""))) is None): + raise S240Error("DETACHED_ADMISSION_SIGNATURE_SCOPE", "admission signed payload scope/hash differs") + receipt_matches = [row for row in admission.get("stage_receipts", []) if isinstance(row, dict) + and row.get("path") == "manifest/s2_40_inline_code_receipt.json" + and row.get("sha256") == request["expected_s2_40_inline_code_receipt_sha256"]] + if len(receipt_matches) != 1 or "S2_40" not in admission.get("present_deterministic_stage_ids", []): + raise S240Error("DETACHED_ADMISSION_S240", "admission does not bind exact S2_40 receipt") + + cas = require_object(load_json(fixed_raw[request["host_cas_receipt_ref"]], label="host-cas"), code="HOST_CAS_OBJECT") + if (cas.get("schema_version") != "stage2_s2_40_host_cas_receipt.v1" + or cas.get("run_binding_digest") != request["run_binding_digest"] + or cas.get("stage_id") != "S2_40" + or cas.get("candidate_attempt_id") != request["candidate_attempt_id"] + or cas.get("requested_transition") != request["requested_transition"] + or cas.get("expected_previous_run_status_sha256") != request["expected_previous_run_status_sha256"] + or cas.get("lease_status") != "ACQUIRED" + or HEX64.fullmatch(str(cas.get("signature_attestation", ""))) is None): + raise S240Error("HOST_CAS_NOT_BOUND", "host CAS receipt does not bind request transition") + try: + issued = datetime.fromisoformat(str(cas.get("issued_at")).replace("Z", "+00:00")) + expires = datetime.fromisoformat(str(cas.get("expires_at")).replace("Z", "+00:00")) + now = datetime.now(timezone.utc) + if issued.tzinfo is None or expires.tzinfo is None or issued > now or expires <= now or expires <= issued: + raise S240Error("HOST_CAS_TIME", "host CAS lease is not currently valid") + except (TypeError, ValueError) as exc: + raise S240Error("HOST_CAS_TIME", "host CAS timestamps are invalid") from exc + snapshot_rows.append({"path": MODULE_MANIFEST_PATH, "sha256": digest(module_raw), "size": len(module_raw)}) + return digest(snapshot_rows) + + +def load_output_schema_store(client: McpClient) -> dict[str, Mapping[str, Any]]: + values, _, _ = read_release_bound_jsons(client, INPUT_SCHEMA_RELS) + return {path: value for path, value in values.items() if path.startswith("schemas/")} + + +def write_terminal_status( + client: McpClient, + request: Mapping[str, Any], + *, + workflow_phase: str, + route: str, + candidate_content_digest: str | None, + run_technical_status: str, + artifact_technical_status: str, + legal_readiness: str, + validation_report_sha256: str | None = None, + review_subject_digest: str | None = None, + review_receipt_sha256s: Sequence[str] = (), + stage2_package_sha256: str | None = None, + artifact_set_digest: str | None = None, + commit_intent_sha256: str | None = None, + commit_result_sha256: str | None = None, + emit_status_event: bool = True, + schema_store: Mapping[str, Mapping[str, Any]] | None = None, +) -> dict[str, Any]: + """Write one immutable transition event and the latest barrier last.""" + output_schemas = dict(schema_store) if schema_store is not None else load_output_schema_store(client) + root = request["stage2_run_root_ref"] + event_core = { + "schema_version": "stage2_s2_40_status_event.v1", + "writer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "workflow_phase": workflow_phase, "route": route, + "candidate_content_digest": candidate_content_digest, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "request_sha256": require_hex(request.get("_request_sha256"), code="REQUEST_RAW_HASH"), + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + } + event_raw_hash: str | None = None + if emit_status_event: + event = {**event_core, "event_digest": digest(event_core)} + validate_schema_instance( + event, "schemas/review_status.schema.json#/$defs/status_event", + output_schemas, code="GENERATED_STATUS_EVENT_SCHEMA", + ) + event_payload = canonical_bytes(event) + event_path = join_path(root, "control/status_events", f"{event['event_digest']}.json") + event_raw_hash = client.write_immutable(event_path, event_payload) + status = { + "schema_version": "stage2_s2_40_run_status.v1", "writer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "entry_route": request["entry_route"], "compile_mode": request["compile_mode"], + "workflow_phase": workflow_phase, "route": route, + "candidate_content_digest": candidate_content_digest, + "run_technical_status": run_technical_status, + "artifact_technical_status": artifact_technical_status, + "legal_readiness": legal_readiness, + "validation_report_sha256": validation_report_sha256, + "review_subject_digest": review_subject_digest, + "review_receipt_sha256s": sorted(set(review_receipt_sha256s)), + "stage2_package_sha256": stage2_package_sha256, + "artifact_set_digest": artifact_set_digest, + "commit_intent_sha256": commit_intent_sha256, + "commit_result_sha256": commit_result_sha256, + "request_sha256": request["_request_sha256"], + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + "outer_execution_receipt_sha256": None, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "status_event_sha256": event_raw_hash, + "barrier_written_last": True, "readback_verified": True, + } + validate_schema_instance( + status, "schemas/review_status.schema.json#/$defs/run_status", + output_schemas, code="GENERATED_RUN_STATUS_SCHEMA", + ) + status_payload = canonical_bytes(status) + status_path = join_path(root, "control/run_status.json") + status_hash = client.write_latest( + status_path, status_payload, request["expected_previous_run_status_sha256"], + ) + return {"status": status, "status_sha256": status_hash, "status_path": status_path} + + +def ingress_schema_ref(path: str) -> str: + exact = { + "ingress/stage1_input_manifest.json": "schemas/ingress.schema.json#/$defs/stage1_input_manifest", + "ingress/intake_report.json": "schemas/ingress.schema.json#/$defs/intake_report", + "ingress/technical_diagnostic.json": "schemas/ingress.schema.json#/$defs/technical_diagnostic", + "context/case_context.json": "schemas/context.schema.json#/$defs/case_context", + "context/evidence_inventory.json": "schemas/context.schema.json#/$defs/evidence_inventory", + "context/object_registry.json": "schemas/context.schema.json#/$defs/object_registry", + "context/party_and_title_context.json": "schemas/context.schema.json#/$defs/party_and_title_context", + "context/slot_crosswalk.json": "schemas/context.schema.json#/$defs/slot_crosswalk", + "context/cluster_plan.json": "schemas/context.schema.json#/$defs/cluster_plan", + "context/bundle_plan.json": "schemas/context.schema.json#/$defs/bundle_plan", + "review/issue_ledger.base.json": "schemas/review_status.schema.json#/$defs/issue_ledger_base", + } + if path in exact: + return exact[path] + if re.fullmatch(r"context/cluster_slices/[A-Za-z0-9][A-Za-z0-9._:-]{0,255}\.json", path): + return "schemas/context.schema.json#/$defs/cluster_slice" + raise S240Error("INGRESS_ARTIFACT_PATH", f"unrecognized ingress artifact path: {path}") + + +def hydrate_ingress_barrier_artifacts( + client: McpClient, + root: str, + ingress: Mapping[str, Any], + schema_store: Mapping[str, Mapping[str, Any]], + *, + exact_paths: set[str] | None = None, +) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], list[dict[str, Any]]]: + barrier = require_object(ingress.get("output_barrier"), code="INGRESS_OUTPUT_BARRIER") + rows = require_list(barrier.get("artifacts"), code="INGRESS_OUTPUT_ROWS") + if barrier.get("artifact_set_digest") != digest(rows): + raise S240Error("INGRESS_OUTPUT_SET_DIGEST", "ingress artifact-set digest differs") + paths = [safe_path(row.get("path"), code="INGRESS_OUTPUT_PATH") for row in rows if isinstance(row, dict)] + if len(paths) != len(rows) or len(paths) != len(set(paths)) or paths != sorted(paths): + raise S240Error("INGRESS_OUTPUT_SET", "ingress artifact rows must be unique and sorted") + if exact_paths is not None and set(paths) != exact_paths: + raise S240Error("INGRESS_OUTPUT_EXACT_SET", "ingress barrier does not bind the exact expected paths") + values: dict[str, dict[str, Any]] = {} + raws: dict[str, bytes] = {} + normalized_rows: list[dict[str, Any]] = [] + for row in rows: + row = require_object(row, code="INGRESS_OUTPUT_ROW") + path = safe_path(row.get("path"), code="INGRESS_OUTPUT_PATH") + if row.get("logical_artifact_id") != path: + raise S240Error("INGRESS_OUTPUT_LOGICAL_ID", "logical artifact id must equal canonical path") + schema_ref = ingress_schema_ref(path) + schema_path = schema_ref.split("#", 1)[0] + if row.get("schema_id") != schema_store[schema_path].get("$id"): + raise S240Error("INGRESS_OUTPUT_SCHEMA_ID", f"schema id differs: {path}") + raw_a = client.read_binary(join_path(root, path)) + raw_b = client.read_binary(join_path(root, path)) + if raw_a != raw_b: + raise S240Error("INGRESS_OUTPUT_TOCTOU", f"ingress artifact changed between reads: {path}") + if digest(raw_a) != require_hex(row.get("raw_sha256"), code="INGRESS_OUTPUT_HASH"): + raise S240Error("INGRESS_OUTPUT_HASH", f"ingress artifact hash differs: {path}") + if row.get("byte_length", len(raw_a)) != len(raw_a): + raise S240Error("INGRESS_OUTPUT_SIZE", f"ingress artifact size differs: {path}") + value = require_object(load_json(raw_a, label=path), code="INGRESS_OUTPUT_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="INGRESS_OUTPUT_SCHEMA") + values[path] = value + raws[path] = raw_a + normalized_rows.append({ + "path": path, "raw_sha256": digest(raw_a), "byte_length": len(raw_a), + "schema_id": row.get("schema_id"), "schema_ref": schema_ref, + }) + return values, raws, normalized_rows + + +def status_only(client: McpClient, request: Mapping[str, Any], preflight_digest: str) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + schema_values, _, schema_rows = read_release_bound_jsons(client, INPUT_SCHEMA_RELS) + schema_store: dict[str, Mapping[str, Any]] = dict(schema_values) + rels_and_refs = ( + ("ingress/ingress_status.json", "schemas/ingress.schema.json#/$defs/ingress_status"), + ("ingress/technical_diagnostic.json", "schemas/ingress.schema.json#/$defs/technical_diagnostic"), + ("ingress/stage1_input_manifest.json", "schemas/ingress.schema.json#/$defs/stage1_input_manifest"), + ("ingress/intake_report.json", "schemas/ingress.schema.json#/$defs/intake_report"), + ("review/issue_ledger.base.json", "schemas/review_status.schema.json#/$defs/issue_ledger_base"), + ) + rows: list[dict[str, Any]] = [] + values: dict[str, dict[str, Any]] = {} + for rel, schema_ref in rels_and_refs: + path = join_path(root, rel) + raw = client.read_binary(path) + if rel == "ingress/ingress_status.json" and digest(raw) != request["expected_ingress_status_sha256"]: + raise S240Error("STATUS_ONLY_INGRESS_HASH", "ingress status hash mismatch") + value = require_object(load_json(raw, label=path), code="STATUS_ONLY_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="STATUS_ONLY_SCHEMA") + values[rel] = value + rows.append({ + "path": rel, "sha256": digest(raw), "size": len(raw), + "schema_ref": schema_ref, "schema_version": value.get("schema_version"), + }) + ingress = values["ingress/ingress_status.json"] + diagnostic = values["ingress/technical_diagnostic.json"] + manifest = values["ingress/stage1_input_manifest.json"] + intake = values["ingress/intake_report.json"] + ledger = values["review/issue_ledger.base.json"] + run_receipt = require_object(ingress.get("run_binding_receipt"), code="STATUS_ONLY_RUN_RECEIPT") + run_id = ingress.get("run_id") + input_set_digest = manifest.get("input_set_digest") + if ( + ingress.get("route") != "TO_S2_40_STATUS_ONLY" + or require_object(ingress.get("output_barrier"), code="STATUS_ONLY_BARRIER").get("branch") != "DIAGNOSTIC" + or ingress["output_barrier"].get("written_last") is not True + or diagnostic.get("route") != "TO_S2_40_STATUS_ONLY" + or diagnostic.get("context_published") is not False + or diagnostic.get("minimum_coherent_package_possible") is not False + or intake.get("minimum_coherent_package_possible") is not False + ): + raise S240Error("STATUS_ONLY_ROUTE_CONTRACT", "diagnostic route semantics differ") + if ( + run_receipt.get("run_binding_digest") != request["run_binding_digest"] + or run_receipt.get("stage2_release_digest") != EXPECTED_STAGE2_RELEASE_SHA256 + or run_receipt.get("run_id") != run_id + or run_receipt.get("input_set_digest") != input_set_digest + or manifest.get("run_id") != run_id + or intake.get("run_id") != run_id + or diagnostic.get("run_id") != run_id + or ledger.get("run_id") != run_id + or ledger.get("producer_id") != "S2_00" + or ledger.get("input_set_digest") != input_set_digest + ): + raise S240Error("STATUS_ONLY_CROSS_BINDING", "exact-five inputs do not bind one run/input/release") + if set(diagnostic.get("reason_codes", [])) - set(ingress.get("issue_codes", [])): + raise S240Error("STATUS_ONLY_REASON_CONSERVATION", "diagnostic reasons are absent from ingress issue codes") + _, barrier_raws, barrier_rows = hydrate_ingress_barrier_artifacts( + client, root, ingress, schema_store, + exact_paths={ + "ingress/technical_diagnostic.json", "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", "review/issue_ledger.base.json", + }, + ) + for row in rows[1:]: + if barrier_raws.get(row["path"]) is None or digest(barrier_raws[row["path"]]) != row["sha256"]: + raise S240Error("STATUS_ONLY_BARRIER_BINDING", f"barrier/raw mismatch: {row['path']}") + status_only_digest = digest({ + "domain_separator": "STAGE2_S2_40_STATUS_ONLY_EXACT_FIVE_V1", + "preflight_snapshot_digest": preflight_digest, + "run_id": run_id, "input_set_digest": input_set_digest, + "input_rows": rows, "barrier_rows": barrier_rows, + "release_schema_rows": schema_rows, + }) + return write_terminal_status( + client, request, + workflow_phase="DIAGNOSTIC_ONLY", route="STOP_TECHNICAL_INCOMPLETE", + candidate_content_digest=None, run_technical_status="TECHNICAL_INCOMPLETE", + artifact_technical_status="NOT_PRODUCED", legal_readiness="NOT_ASSESSED", + validation_report_sha256=status_only_digest, + emit_status_event=False, + schema_store=schema_store, + ) + + +def require_self_hash(value: Mapping[str, Any], field: str, *, code: str) -> None: + observed = require_hex(value.get(field), code=code) + material = {key: item for key, item in value.items() if key != field} + if observed != digest(material): + raise S240Error(code, f"self hash mismatch: {field}") + + +def hydrate_s210_artifacts( + client: McpClient, + root: str, + ingress: Mapping[str, Any], + ingress_documents: Mapping[str, Mapping[str, Any]], + ingress_raws: Mapping[str, bytes], + s210: Mapping[str, Any], + request: Mapping[str, Any], + schema_store: Mapping[str, Mapping[str, Any]], +) -> dict[str, Any]: + """Hydrate the exact S2_10 universe named by the S2_00 plans.""" + cluster_plan = require_object( + ingress_documents.get("context/cluster_plan.json"), code="S210_CLUSTER_PLAN", + ) + bundle_plan = require_object( + ingress_documents.get("context/bundle_plan.json"), code="S210_BUNDLE_PLAN", + ) + cluster_ids = [ + require_ident(value, code="S210_CLUSTER_ID") + for value in require_list(cluster_plan.get("executable_cluster_ids"), code="S210_CLUSTER_IDS") + ] + if ( + cluster_ids != sorted(cluster_ids) + or len(cluster_ids) != len(set(cluster_ids)) + or cluster_ids != ingress.get("executable_cluster_ids") + or sorted(s210.get("expected_executable_cluster_ids", [])) != cluster_ids + or sorted(s210.get("valid_domain_verdict_cluster_ids", [])) != cluster_ids + or s210.get("terminal_technical_failure_cluster_ids") != [] + ): + raise S240Error("S210_CLUSTER_CLOSURE", "S2_00/S2_10 executable cluster sets differ") + + wave_by_cluster: dict[str, int] = {} + for cohort in require_list(bundle_plan.get("cohorts"), code="S210_BUNDLE_COHORTS"): + cohort = require_object(cohort, code="S210_BUNDLE_COHORT") + if cohort.get("cohort_status") != "EXECUTABLE": + continue + members = require_list(cohort.get("member_slices"), code="S210_BUNDLE_MEMBERS") + for member in members: + member = require_object(member, code="S210_BUNDLE_MEMBER") + cluster_id = require_ident(member.get("cluster_id"), code="S210_BUNDLE_CLUSTER") + ordinal = member.get("dependency_wave_ordinal") + if cluster_id in wave_by_cluster or cluster_id not in cluster_ids or not isinstance(ordinal, int) or ordinal < 0: + raise S240Error("S210_BUNDLE_WAVE", "bundle member/wave mapping is not exact") + expected_slice = f"context/cluster_slices/{cluster_id}.json" + if ( + member.get("path") != expected_slice + or member.get("sha256") != digest(ingress_raws[expected_slice]) + ): + raise S240Error("S210_BUNDLE_SLICE", f"bundle slice hash differs: {cluster_id}") + wave_by_cluster[cluster_id] = ordinal + if set(wave_by_cluster) != set(cluster_ids): + raise S240Error("S210_BUNDLE_COVERAGE", "bundle does not cover the exact executable cluster set") + wave_ordinals = sorted(set(wave_by_cluster.values())) + if wave_ordinals != list(range(len(wave_ordinals))): + raise S240Error("S210_WAVE_ORDINALS", "dependency-wave ordinals are not contiguous from zero") + + def stable_json(path: str, schema_ref: str) -> tuple[dict[str, Any], bytes]: + raw_a = client.read_binary(join_path(root, path)) + raw_b = client.read_binary(join_path(root, path)) + if raw_a != raw_b: + raise S240Error("S210_TOCTOU", f"S2_10 artifact changed between reads: {path}") + value = require_object(load_json(raw_a, label=path), code="S210_ARTIFACT_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="S210_ARTIFACT_SCHEMA") + closure_rows.append({ + "path": path, "sha256": digest(raw_a), "expected_sha256": digest(raw_a), + "schema_ref": schema_ref, "schema_version": value.get("schema_version"), + "producer_id": value.get("producer_id", "S2_10"), + "schema_valid": True, "hash_match": True, + }) + return value, raw_a + + verdicts: dict[str, dict[str, Any]] = {} + item_receipts: dict[str, dict[str, Any]] = {} + issue_parts: dict[str, dict[str, Any]] = {} + assumption_parts: dict[str, dict[str, Any]] = {} + usage_parts: dict[str, dict[str, Any]] = {} + raw_by_path: dict[str, bytes] = {} + closure_rows: list[dict[str, Any]] = [] + request_ids: set[str] = set() + producer_contract_digests: set[str] = set() + for cluster_id in cluster_ids: + paths = { + "verdict": f"map_s2_10/domain_verdicts/{cluster_id}.json", + "item": f"map_s2_10/item_receipts/{cluster_id}.json", + "issue": f"map_s2_10/issue_patches/{cluster_id}.json", + "assumption": f"map_s2_10/assumption_parts/{cluster_id}.json", + "usage": f"map_s2_10/usage_parts/{cluster_id}.json", + } + verdict, verdict_raw = stable_json(paths["verdict"], "schemas/s2_10.schema.json#/$defs/canonical_domain_verdict") + item, item_raw = stable_json(paths["item"], "schemas/s2_10.schema.json#/$defs/item_receipt") + issue, issue_raw = stable_json(paths["issue"], "schemas/s2_10.schema.json#/$defs/issue_part") + assumption, assumption_raw = stable_json(paths["assumption"], "schemas/s2_10.schema.json#/$defs/assumption_part") + usage, usage_raw = stable_json(paths["usage"], "schemas/s2_10.schema.json#/$defs/usage_part") + require_self_hash(verdict, "domain_verdict_sha256", code="S210_VERDICT_SELF_HASH") + require_self_hash(item, "receipt_sha256", code="S210_ITEM_SELF_HASH") + for part, label in ((issue, "ISSUE"), (assumption, "ASSUMPTION"), (usage, "USAGE")): + require_self_hash(part, "part_sha256", code=f"S210_{label}_SELF_HASH") + producer_contract_digest = require_hex( + verdict.get("producer_contract_digest"), code="S210_PRODUCER_CONTRACT", + ) + producer_contract_digests.add(producer_contract_digest) + verdict_hash = verdict["domain_verdict_sha256"] + if ( + verdict.get("cluster_id") != cluster_id + or verdict.get("run_binding_digest") != request["run_binding_digest"] + or verdict.get("cluster_slice_sha256") != digest(ingress_raws[f"context/cluster_slices/{cluster_id}.json"]) + or verdict.get("wave_ordinal") != wave_by_cluster[cluster_id] + or item.get("cluster_id") != cluster_id + or item.get("run_binding_digest") != request["run_binding_digest"] + or item.get("domain_verdict_path") != paths["verdict"] + or item.get("domain_verdict_sha256") != verdict_hash + or item.get("read_back_sha256") != verdict_hash + or item.get("request_id") != verdict.get("request_id") + or item.get("wave_ordinal") != verdict.get("wave_ordinal") + or item.get("attempt_no") != verdict.get("attempt_no") + or item.get("raw_model_output_sha256") != verdict.get("raw_model_output_sha256") + or item.get("validation_status") != "PASS" + or item.get("persistence_status") not in {"PUBLISHED", "IDEMPOTENT_BYTE_IDENTICAL"} + ): + raise S240Error("S210_ITEM_LINK", f"S2_10 verdict/item link differs: {cluster_id}") + for part, expected_hash, label in ( + (issue, item.get("issue_part_sha256"), "ISSUE"), + (assumption, item.get("assumption_part_sha256"), "ASSUMPTION"), + (usage, item.get("usage_part_sha256"), "USAGE"), + ): + header = require_object(part.get("header"), code=f"S210_{label}_HEADER") + if ( + part.get("part_sha256") != expected_hash + or header.get("producer_contract_digest") != producer_contract_digest + or header.get("request_id") != item.get("request_id") + or header.get("run_binding_digest") != request["run_binding_digest"] + or header.get("wave_ordinal") != item.get("wave_ordinal") + or header.get("attempt_no") != item.get("attempt_no") + or header.get("cluster_id") != cluster_id + or header.get("domain_verdict_sha256") != verdict_hash + ): + raise S240Error(f"S210_{label}_LINK", f"S2_10 {label.lower()} part link differs: {cluster_id}") + if assumption.get("assumptions") != verdict.get("assumptions"): + raise S240Error("S210_ASSUMPTION_CONTENT", f"assumption part differs from verdict: {cluster_id}") + request_ids.add(str(item.get("request_id"))) + verdicts[cluster_id] = verdict + item_receipts[cluster_id] = item + issue_parts[cluster_id] = issue + assumption_parts[cluster_id] = assumption + usage_parts[cluster_id] = usage + raw_by_path.update({ + paths["verdict"]: verdict_raw, paths["item"]: item_raw, + paths["issue"]: issue_raw, paths["assumption"]: assumption_raw, + paths["usage"]: usage_raw, + }) + if len(request_ids) != 1 or len(producer_contract_digests) != 1: + raise S240Error("S210_REQUEST_PRODUCER_SET", "S2_10 items do not share one request/producer contract") + + wave_receipts: list[dict[str, Any]] = [] + covered: set[str] = set() + for ordinal in wave_ordinals: + path = f"map_s2_10/wave_receipts/wave-{ordinal:04d}.json" + wave, raw = stable_json(path, "schemas/s2_10.schema.json#/$defs/wave_receipt") + require_self_hash(wave, "receipt_sha256", code="S210_WAVE_SELF_HASH") + expected_clusters = sorted(key for key, value in wave_by_cluster.items() if value == ordinal) + if ( + wave.get("request_id") not in request_ids + or wave.get("run_binding_digest") != request["run_binding_digest"] + or wave.get("wave_ordinal") != ordinal + or wave.get("is_final_wave") != (ordinal == wave_ordinals[-1]) + or sorted(wave.get("expected_wave_cluster_ids", [])) != expected_clusters + or sorted(wave.get("valid_domain_verdict_cluster_ids", [])) != expected_clusters + or wave.get("terminal_technical_failure_cluster_ids") != [] + or wave.get("wave_status") != "WAVE_COMPLETE" + or wave.get("route") != ("TO_S2_20" if ordinal == wave_ordinals[-1] else "NEXT_WAVE") + or wave.get("written_once") is not True + ): + raise S240Error("S210_WAVE_LINK", f"S2_10 wave receipt differs: {ordinal}") + covered.update(expected_clusters) + wave_receipts.append(wave) + raw_by_path[path] = raw + if covered != set(cluster_ids) or s210.get("terminal_wave_receipt_sha256s") != [ + row["receipt_sha256"] for row in wave_receipts + ]: + raise S240Error("S210_WAVE_CLOSURE", "S2_10 terminal wave receipt closure differs") + return { + "cluster_ids": cluster_ids, "verdicts": verdicts, + "item_receipts": item_receipts, "issue_parts": issue_parts, + "assumption_parts": assumption_parts, "usage_parts": usage_parts, + "wave_receipts": wave_receipts, "raw_by_path": raw_by_path, + "source_rows": [ + {"path": path, "sha256": digest(raw), "ref_family": "s2_10_runtime"} + for path, raw in sorted(raw_by_path.items()) + ], + "closure_rows": sorted(closure_rows, key=lambda row: row["path"]), + } + + +def validate_handoff_provenance( + value: Any, *, common_only: bool, expected_mode: str, code: str, +) -> dict[str, Any]: + row = require_object(value, code=code) + expected = COMMON_PROVENANCE_FIELDS if common_only else GROUP_PROVENANCE_FIELDS + if set(row) != expected: + raise S240Error(code, "handoff provenance is not closed", details=sorted(set(row) ^ expected)) + if row.get("compile_mode") != expected_mode: + raise S240Error("COMPILE_MODE_DRIFT", "handoff compile mode differs") + for key in expected - {"compile_mode"}: + require_hex(row.get(key), code=code) + return row + + +def common_provenance(value: Mapping[str, Any]) -> dict[str, Any]: + return {key: value[key] for key in sorted(COMMON_PROVENANCE_FIELDS)} + + +def artifact_rows(manifest: Mapping[str, Any]) -> list[dict[str, Any]]: + rows = require_list(manifest.get("part_rows"), code="S230_MANIFEST_ROWS") + if len(rows) > MAX_ARTIFACT_ROWS: + raise S240Error("S230_MANIFEST_LIMIT", "too many artifact rows") + result: list[dict[str, Any]] = [] + seen_pairs: set[tuple[str, str]] = set() + seen_paths: set[str] = set() + for value in rows: + row = require_object(value, code="S230_MANIFEST_ROW") + if set(row) != {"claim_group_id", "part_family", "path", "sha256", "schema_ref"}: + raise S240Error("S230_MANIFEST_ROW_SHAPE", "manifest row is not closed") + group_id = require_ident(row.get("claim_group_id"), code="S230_MANIFEST_GROUP") + family = row.get("part_family") + if family not in PART_FAMILIES: + raise S240Error("S230_MANIFEST_KIND", f"unsupported part family: {family}") + path = safe_path(row.get("path"), code="S230_MANIFEST_PATH") + expected_path = f"map_s2_30/{PART_DIRECTORIES[family]}/{group_id}.json" + if path != expected_path or row.get("schema_ref") != PART_SCHEMA_REFS[family]: + raise S240Error("S230_MANIFEST_BINDING", "part path/schema differs from canonical binding") + pair = (group_id, family) + if pair in seen_pairs or path in seen_paths: + raise S240Error("S230_MANIFEST_DUPLICATE", "duplicate part pair/path") + seen_pairs.add(pair) + seen_paths.add(path) + result.append({ + "path": path, + "sha256": require_hex(row.get("sha256"), code="S230_MANIFEST_HASH"), + "schema_ref": row["schema_ref"], + "part_family": family, + "claim_group_id": group_id, + }) + if result != sorted(result, key=lambda row: (row["claim_group_id"], row["part_family"], row["path"])): + raise S240Error("S230_MANIFEST_ORDER", "part rows must be canonically sorted") + return result + + +def plan_artifact_rows(plan: Mapping[str, Any]) -> list[dict[str, Any]]: + rows = require_list(plan.get("artifact_rows"), code="S220_ARTIFACT_ROWS") + result: list[dict[str, Any]] = [] + seen: set[str] = set() + for value in rows: + row = require_object(value, code="S220_ARTIFACT_ROW") + path = safe_path(row.get("path"), code="S220_ARTIFACT_PATH") + if path in seen: + raise S240Error("S220_ARTIFACT_DUPLICATE", f"duplicate plan artifact: {path}") + seen.add(path) + result.append({ + "path": path, + "schema_ref": row.get("schema_ref"), + "raw_sha256": require_hex(row.get("raw_sha256"), code="S220_ARTIFACT_HASH"), + "byte_size": row.get("byte_size"), + "producer_component": row.get("producer_component"), + }) + if result != sorted(result, key=lambda row: row["path"]): + raise S240Error("S220_ARTIFACT_ORDER", "plan artifact rows must be sorted") + if plan.get("artifact_set_digest") != digest(result): + raise S240Error("S220_ARTIFACT_SET_DIGEST", "plan artifact set digest mismatch") + return result + + +def read_plan_artifacts( + client: McpClient, root: str, plan: Mapping[str, Any], total: int, + schema_store: Mapping[str, Mapping[str, Any]], +) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], int]: + rows = plan_artifact_rows(plan) + documents: dict[str, dict[str, Any]] = {} + raw_by_path: dict[str, bytes] = {} + for row in rows: + value, raw = read_bound_json(client, join_path(root, row["path"]), row["raw_sha256"]) + if isinstance(row.get("schema_ref"), str) and row["schema_ref"].startswith("schemas/"): + validate_schema_instance(value, row["schema_ref"], schema_store, code="S220_ARTIFACT_SCHEMA") + if row["byte_size"] != len(raw): + raise S240Error("S220_ARTIFACT_SIZE", f"plan artifact size mismatch: {row['path']}") + total += len(raw) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + documents[row["path"]] = value + raw_by_path[row["path"]] = raw + return documents, raw_by_path, total + + +def resolve_frozen_ref( + client: McpClient, + root: str, + plan_rows: Mapping[str, bytes], + ref: Mapping[str, Any], + *, + code: str, +) -> tuple[dict[str, Any], bytes, str]: + relative = safe_path(ref.get("path"), code=code) + expected = require_hex(ref.get("sha256"), code=code) + plan_path = relative if relative.startswith("plan/") else f"plan/{relative}" + if plan_path in plan_rows: + raw = plan_rows[plan_path] + if digest(raw) != expected: + raise S240Error(code, f"frozen plan ref hash mismatch: {relative}") + return require_object(load_json(raw, label=plan_path), code=code), raw, plan_path + asset_path = relative if relative.startswith(f"{ASSET_ROOT}/") else join_path(ASSET_ROOT, relative) + value, raw = read_bound_json(client, asset_path, expected) + return value, raw, asset_path + + +def hydrate_normal(client: McpClient, request: Mapping[str, Any]) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + ingress, ingress_raw = read_bound_json(client, join_path(root, "ingress/ingress_status.json"), request["expected_ingress_status_sha256"]) + s210, s210_raw = read_bound_json(client, join_path(root, "map_s2_10/s2_10_publish_status.json"), request["expected_s2_10_publish_status_sha256"]) + plan, plan_raw = read_bound_json(client, join_path(root, "plan/plan_publish_status.json"), request["expected_plan_publish_status_sha256"]) + s230, s230_raw = read_bound_json(client, join_path(root, "map_s2_30/s2_30_publish_status.json"), request["expected_s2_30_publish_status_sha256"]) + manifest_path = join_path(root, "map_s2_30/artifact_manifest.json") + manifest, manifest_raw = read_bound_json(client, manifest_path, request["expected_s2_30_artifact_manifest_sha256"]) + release_values, release_raws, release_rows = read_release_bound_jsons( + client, ( + *INPUT_SCHEMA_RELS, AUTHORITY_RELEASE_REL, CASE_TYPE_COVERAGE_REL, + CASE_TYPE_REGISTRY_REL, CASE_TYPE_RULE_REGISTRY_REL, + ), + ) + schema_store: dict[str, Mapping[str, Any]] = { + path: value for path, value in release_values.items() if path.startswith("schemas/") + } + validate_schema_instance(ingress, "schemas/ingress.schema.json#/$defs/ingress_status", schema_store, code="V01_INGRESS_SCHEMA") + validate_schema_instance(s210, "schemas/s2_10.schema.json#/$defs/global_publish_status", schema_store, code="V01_S210_SCHEMA") + validate_schema_instance(plan, "schemas/relief_plan.schema.json#/$defs/plan_publish_status", schema_store, code="V01_S220_SCHEMA") + validate_schema_instance(s230, "schemas/draft_atoms.schema.json#/$defs/publish_status", schema_store, code="V01_S230_SCHEMA") + validate_schema_instance(manifest, "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", schema_store, code="V01_S230_MANIFEST_SCHEMA") + executable_cluster_ids = [ + require_ident(value, code="INGRESS_EXECUTABLE_CLUSTER") + for value in require_list(ingress.get("executable_cluster_ids"), code="INGRESS_EXECUTABLE_CLUSTERS") + ] + normal_ingress_paths = { + "ingress/stage1_input_manifest.json", "ingress/intake_report.json", + "context/case_context.json", "context/evidence_inventory.json", + "context/object_registry.json", "context/party_and_title_context.json", + "context/slot_crosswalk.json", "context/cluster_plan.json", + "context/bundle_plan.json", "review/issue_ledger.base.json", + *{f"context/cluster_slices/{cluster_id}.json" for cluster_id in executable_cluster_ids}, + } + ingress_documents, ingress_raws, ingress_artifact_rows = hydrate_ingress_barrier_artifacts( + client, root, ingress, schema_store, exact_paths=normal_ingress_paths, + ) + ingress_barrier = require_object(ingress.get("output_barrier"), code="INGRESS_NORMAL_BARRIER") + if ( + ingress_barrier.get("branch") != "NORMAL" + or ingress_barrier.get("written_last") is not True + or ingress_barrier.get("non_status_artifacts_read_back_verified", True) is not True + or ingress_documents["context/cluster_plan.json"].get("executable_cluster_ids") != executable_cluster_ids + ): + raise S240Error("INGRESS_NORMAL_CLOSURE", "normal ingress barrier/context closure differs") + ingress_receipt = require_object(ingress.get("run_binding_receipt"), code="V01_INGRESS_RUN_BINDING") + if ( + ingress.get("route") not in {"TO_S2_10", "TO_S2_10_WITH_ISSUES"} + or ingress_receipt.get("run_binding_digest") != request["run_binding_digest"] + or ingress_receipt.get("stage2_release_digest") != EXPECTED_STAGE2_RELEASE_SHA256 + or s210.get("producer_id") != "S2_10_NATIVE_RESULT_ADAPTER" + or s210.get("run_binding_digest") != request["run_binding_digest"] + or s210.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or s210.get("status") != "COMPLETE" or s210.get("route") != "TO_S2_20" + or s210.get("status_written_last") is not True + or plan.get("workflow_id") != "S2_20" + or plan.get("run_binding_digest") != request["run_binding_digest"] + or plan.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or plan.get("s2_10_publish_status_sha256") != request["expected_s2_10_publish_status_sha256"] + or s230.get("run_binding_digest") != request["run_binding_digest"] + or s230.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or manifest.get("run_binding_digest") != request["run_binding_digest"] + ): + raise S240Error("V01_INPUT_LINEAGE", "normal barriers do not share exact producer/run/release lineage") + require_self_hash(s210, "status_sha256", code="S210_STATUS_SELF_HASH") + s210_handoff = hydrate_s210_artifacts( + client, root, ingress, ingress_documents, ingress_raws, + s210, request, schema_store, + ) + require_self_hash(plan, "barrier_sha256", code="S220_STATUS_SELF_HASH") + if plan.get("plan_status") == "TECHNICAL_INCOMPLETE" or plan.get("route") != "TO_S2_30" or plan.get("consumer_authorized") is not True: + raise S240Error("S220_BARRIER_NOT_CONSUMABLE", "S2_20 barrier is not consumer-authorized") + if s230.get("status") != "S2_30_COMPLETE" or s230.get("route") != "TO_S2_40" or s230.get("status_written_last") is not True: + raise S240Error("S230_BARRIER_NOT_CONSUMABLE", "S2_30 barrier is not complete") + require_self_hash(s230, "status_sha256", code="S230_STATUS_SELF_HASH") + require_self_hash(manifest, "part_manifest_core_sha256", code="S230_MANIFEST_SELF_HASH") + common = validate_handoff_provenance( + manifest.get("provenance"), common_only=True, + expected_mode=request["compile_mode"], code="S230_COMMON_PROVENANCE", + ) + if s230.get("compile_mode") != request["compile_mode"] or s230.get("provenance") != common: + raise S240Error("COMPILE_MODE_DRIFT", "S2_30 barrier/manifest mode or provenance differs") + if ( + s230.get("artifact_manifest_path") != "map_s2_30/artifact_manifest.json" + or s230.get("artifact_manifest_schema_ref") != "schemas/draft_atoms.schema.json#/$defs/part_manifest_core" + or s230.get("artifact_manifest_sha256") != digest(manifest_raw) + ): + raise S240Error("S230_BARRIER_MANIFEST", "S2_30 barrier does not bind exact manifest bytes") + expected_groups = require_list(manifest.get("expected_claim_group_ids"), code="S230_EXPECTED_GROUPS") + if expected_groups != sorted(expected_groups) or len(expected_groups) != len(set(expected_groups)): + raise S240Error("S230_EXPECTED_GROUP_ORDER", "manifest group ids must be unique and sorted") + if ( + s230.get("expected_claim_group_ids") != expected_groups + or s230.get("published_claim_group_ids") != expected_groups + or s230.get("terminal_failure_claim_group_ids") != [] + ): + raise S240Error("S230_GROUP_SET", "publish expected/published group set differs") + if sorted(plan.get("group_ids", [])) != expected_groups: + raise S240Error("S220_S230_GROUP_SET", "S2_20 and S2_30 group sets differ") + rows = artifact_rows(manifest) + expected_pairs = {(group_id, family) for group_id in expected_groups for family in PART_FAMILIES} + if {(row["claim_group_id"], row["part_family"]) for row in rows} != expected_pairs: + raise S240Error("S230_PART_COVERAGE", "manifest must contain exactly four part families per group") + parts: dict[str, list[dict[str, Any]]] = {family: [] for family in PART_FAMILIES} + group_provenance: dict[str, dict[str, Any]] = {} + total = ( + sum(len(raw) for raw in (ingress_raw, s210_raw, plan_raw, s230_raw, manifest_raw)) + + sum(len(raw) for raw in release_raws.values()) + + sum(len(raw) for raw in ingress_raws.values()) + + sum(len(raw) for raw in s210_handoff["raw_by_path"].values()) + ) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + for row in rows: + value, raw = read_bound_json(client, join_path(root, row["path"]), row["sha256"]) + validate_schema_instance(value, row["schema_ref"], schema_store, code="S230_PART_SCHEMA") + total += len(raw) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + require_self_hash(value, "part_sha256", code="S230_PART_SELF_HASH") + provenance = validate_handoff_provenance( + value.get("provenance"), common_only=False, + expected_mode=request["compile_mode"], code="S230_GROUP_PROVENANCE", + ) + if common_provenance(provenance) != common: + raise S240Error("S230_PART_COMMON_PROVENANCE", "part common provenance differs") + if value.get("claim_group_id") != row["claim_group_id"]: + raise S240Error("S230_PART_GROUP", "part group mismatch") + prior = group_provenance.setdefault(row["claim_group_id"], provenance) + if prior != provenance: + raise S240Error("S230_PART_GROUP_PROVENANCE", "part family provenance differs within group") + parts[row["part_family"]].append(value) + item_refs = require_list(s230.get("ordered_item_receipts"), code="S230_ITEM_RECEIPT_REFS") + cohort_refs = require_list(s230.get("ordered_cohort_receipts"), code="S230_COHORT_RECEIPT_REFS") + if item_refs != sorted(item_refs, key=lambda row: (row.get("claim_group_id"), row.get("path"))): + raise S240Error("S230_ITEM_RECEIPT_ORDER", "item receipt refs are not sorted") + if cohort_refs != sorted(cohort_refs, key=lambda row: row.get("path")): + raise S240Error("S230_COHORT_RECEIPT_ORDER", "cohort receipt refs are not sorted") + if [row.get("claim_group_id") for row in item_refs] != expected_groups: + raise S240Error("S230_ITEM_RECEIPT_GROUP_SET", "item receipt group set differs") + receipt_rows: list[dict[str, Any]] = [] + for kind, refs in (("ITEM", item_refs), ("COHORT", cohort_refs)): + for ref in refs: + receipt_path = safe_path(ref.get("path"), code="S230_RECEIPT_PATH") + receipt, receipt_raw = read_bound_json(client, join_path(root, receipt_path), require_hex(ref.get("sha256"), code="S230_RECEIPT_HASH")) + require_self_hash(receipt, "receipt_sha256", code="S230_RECEIPT_SELF_HASH") + if receipt.get("part_manifest_core_sha256") != manifest["part_manifest_core_sha256"]: + raise S240Error("S230_RECEIPT_CORE_HASH", "receipt references a different manifest core") + receipt_provenance = validate_handoff_provenance( + receipt.get("provenance"), common_only=kind == "COHORT", + expected_mode=request["compile_mode"], code="S230_RECEIPT_PROVENANCE", + ) + if common_provenance(receipt_provenance) != common: + raise S240Error("S230_RECEIPT_COMMON_PROVENANCE", "receipt provenance differs") + if kind == "ITEM": + group_id = ref.get("claim_group_id") + if receipt.get("claim_group_id") != group_id or receipt_provenance != group_provenance.get(group_id): + raise S240Error("S230_ITEM_RECEIPT_GROUP", "item receipt group/provenance differs") + total += len(receipt_raw) + receipt_rows.append({"kind": kind, "path": receipt_path, "sha256": digest(receipt_raw)}) + plan_documents, plan_raw_by_path, total = read_plan_artifacts(client, root, plan, total, schema_store) + rule_packs: dict[str, dict[str, Any]] = {} + group_slices: dict[str, dict[str, Any]] = {} + renderer_descriptors: dict[str, dict[str, Any]] = {} + frozen_assets: dict[str, dict[str, Any]] = {} + frozen_source_rows: list[dict[str, Any]] = [dict(row) for row in release_rows] + frozen_source_rows.extend({ + "path": row["path"], "sha256": row["raw_sha256"], "ref_family": "s2_00_runtime", + } for row in ingress_artifact_rows) + frozen_source_rows.extend(s210_handoff["source_rows"]) + frozen_source_rows.append({ + "path": "map_s2_30/artifact_manifest.json", + "sha256": digest(manifest_raw), "ref_family": "upstream_manifest", + }) + calculation_receipts: dict[str, dict[str, Any]] = {} + for group_id in expected_groups: + group_path = f"plan/group_slices/{group_id}.json" + group_slice = require_object(plan_documents.get(group_path), code="S220_GROUP_SLICE") + if group_slice.get("claim_group_id") != group_id: + raise S240Error("S220_GROUP_SLICE_ID", "group slice id differs") + group_echo = require_object(group_provenance.get(group_id), code="S230_GROUP_ECHO") + if (request["compile_mode"] != "STRUCTURAL_FIXTURE" + and digest(plan_raw_by_path[group_path]) != group_echo.get("s30_group_slice_sha256")): + raise S240Error("S220_S230_GROUP_SLICE_HASH", "S2_30 group-slice echo differs from frozen S2_20 bytes") + group_slices[group_id] = group_slice + rule_pack, rule_raw, resolved = resolve_frozen_ref( + client, root, plan_raw_by_path, + require_object(group_slice.get("rule_context_pack_ref"), code="S220_RULE_PACK_REF"), + code="S220_RULE_PACK_REF", + ) + if (request["compile_mode"] != "STRUCTURAL_FIXTURE" + and digest(rule_raw) != group_echo.get("p31_rule_and_pack_sha256")): + raise S240Error("S220_S230_RULE_PACK_HASH", "S2_30 rule-pack echo differs from frozen S2_20 bytes") + rule_packs[group_id] = rule_pack + frozen_source_rows.append({"path": resolved, "sha256": digest(rule_raw)}) + for ref in require_list(rule_pack.get("renderer_refs"), code="S220_RENDERER_REFS"): + descriptor, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_RENDERER_REF"), code="S220_RENDERER_REF") + renderer_id = require_ident(descriptor.get("renderer_id"), code="S220_RENDERER_ID") + if renderer_id in renderer_descriptors and canonical_bytes(renderer_descriptors[renderer_id]) != canonical_bytes(descriptor): + raise S240Error("S220_RENDERER_CONFLICT", "renderer id binds conflicting bytes") + renderer_descriptors[renderer_id] = descriptor + frozen_assets[resolved] = descriptor + frozen_source_rows.append({"path": resolved, "sha256": digest(raw)}) + for ref_name in ("structured_relief_rule_refs", "review_policy_refs", "ce13_branch_refs"): + for ref in require_list(rule_pack.get(ref_name), code="S220_RULE_ASSET_REFS"): + asset, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_RULE_ASSET_REF"), code="S220_RULE_ASSET_REF") + frozen_assets[resolved] = asset + frozen_source_rows.append({"path": resolved, "sha256": digest(raw), "ref_family": ref_name}) + for ref in require_list(group_slice.get("calculation_receipt_refs"), code="S220_CALC_REFS"): + receipt, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_CALC_REF"), code="S220_CALC_REF") + receipt_id = require_ident(receipt.get("calculation_receipt_id"), code="S220_CALC_ID") + calculation_receipts[receipt_id] = receipt + frozen_source_rows.append({"path": resolved, "sha256": digest(raw), "ref_family": "calculation"}) + exhibit_register = require_object(plan_documents.get("plan/exhibit_register.json"), code="S220_EXHIBIT_REGISTER") + authority_release = release_values[AUTHORITY_RELEASE_REL] + case_type_coverage = release_values[CASE_TYPE_COVERAGE_REL] + case_type_registry = release_values[CASE_TYPE_REGISTRY_REL] + case_type_rule_registry = release_values[CASE_TYPE_RULE_REGISTRY_REL] + input_closure_rows = [ + { + "path": "ingress/ingress_status.json", "sha256": digest(ingress_raw), + "expected_sha256": request["expected_ingress_status_sha256"], + "schema_ref": "schemas/ingress.schema.json#/$defs/ingress_status", + "schema_version": ingress.get("schema_version"), "producer_id": "S2_00", + "schema_valid": True, "hash_match": digest(ingress_raw) == request["expected_ingress_status_sha256"], + }, + { + "path": "map_s2_10/s2_10_publish_status.json", "sha256": digest(s210_raw), + "expected_sha256": request["expected_s2_10_publish_status_sha256"], + "schema_ref": "schemas/s2_10.schema.json#/$defs/global_publish_status", + "schema_version": s210.get("schema_version"), "producer_id": s210.get("producer_id"), + "schema_valid": True, "hash_match": digest(s210_raw) == request["expected_s2_10_publish_status_sha256"], + }, + { + "path": "plan/plan_publish_status.json", "sha256": digest(plan_raw), + "expected_sha256": request["expected_plan_publish_status_sha256"], + "schema_ref": "schemas/relief_plan.schema.json#/$defs/plan_publish_status", + "schema_version": plan.get("schema_version"), "producer_id": plan.get("workflow_id"), + "schema_valid": True, "hash_match": digest(plan_raw) == request["expected_plan_publish_status_sha256"], + }, + { + "path": "map_s2_30/s2_30_publish_status.json", "sha256": digest(s230_raw), + "expected_sha256": request["expected_s2_30_publish_status_sha256"], + "schema_ref": "schemas/draft_atoms.schema.json#/$defs/publish_status", + "schema_version": s230.get("schema_version"), "producer_id": "S2_30", + "schema_valid": True, "hash_match": digest(s230_raw) == request["expected_s2_30_publish_status_sha256"], + }, + { + "path": "map_s2_30/artifact_manifest.json", "sha256": digest(manifest_raw), + "expected_sha256": request["expected_s2_30_artifact_manifest_sha256"], + "schema_ref": "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", + "schema_version": manifest.get("schema_version"), "producer_id": "S2_30", + "schema_valid": True, "hash_match": digest(manifest_raw) == request["expected_s2_30_artifact_manifest_sha256"], + }, + ] + input_closure_rows.extend({ + "path": row["path"], "sha256": row["raw_sha256"], + "expected_sha256": row["raw_sha256"], "schema_ref": row["schema_ref"], + "schema_version": ingress_documents[row["path"]].get("schema_version"), + "producer_id": ingress_documents[row["path"]].get("producer_id", "S2_00"), + "schema_valid": True, "hash_match": True, + } for row in ingress_artifact_rows) + input_closure_rows.extend(s210_handoff["closure_rows"]) + input_snapshot_preimage = [ + digest(ingress_raw), digest(s210_raw), digest(plan_raw), digest(s230_raw), + digest(manifest_raw), *[row["sha256"] for row in rows], + *[row["sha256"] for row in receipt_rows], + *[digest(ingress_raws[path]) for path in sorted(ingress_raws)], + *[digest(s210_handoff["raw_by_path"][path]) for path in sorted(s210_handoff["raw_by_path"])], + *[digest(plan_raw_by_path[path]) for path in sorted(plan_raw_by_path)], + *[row["sha256"] for row in sorted(frozen_source_rows, key=lambda item: (item["path"], item["sha256"]))], + ] + return { + "ingress": ingress, "s210": s210, "plan": plan, "s230": s230, + "manifest": manifest, "manifest_sha256": digest(manifest_raw), "rows": rows, + "parts": parts, "group_ids": expected_groups, "group_provenance": group_provenance, + "receipt_rows": receipt_rows, "plan_documents": plan_documents, + "plan_raw_by_path": plan_raw_by_path, + "group_slices": group_slices, "rule_packs": rule_packs, + "renderer_descriptors": renderer_descriptors, + "frozen_assets": frozen_assets, + "calculation_receipts": calculation_receipts, + "exhibit_register": exhibit_register, + "ingress_documents": ingress_documents, "ingress_raws": ingress_raws, + "ingress_artifact_rows": ingress_artifact_rows, + "s210_handoff": s210_handoff, + "authority_release": authority_release, + "authority_release_sha256": digest(release_raws[AUTHORITY_RELEASE_REL]), + "case_type_coverage": case_type_coverage, + "case_type_coverage_sha256": digest(release_raws[CASE_TYPE_COVERAGE_REL]), + "case_type_registry": case_type_registry, + "case_type_registry_sha256": digest(release_raws[CASE_TYPE_REGISTRY_REL]), + "case_type_rule_registry": case_type_rule_registry, + "case_type_rule_registry_sha256": digest(release_raws[CASE_TYPE_RULE_REGISTRY_REL]), + "schema_store": schema_store, + "frozen_source_rows": sorted(frozen_source_rows, key=lambda row: (row["path"], row["sha256"])), + "input_closure_rows": input_closure_rows, + "input_snapshot_preimage": input_snapshot_preimage, + "input_snapshot_digest": digest(input_snapshot_preimage), + } + + +def flatten(parts: Iterable[Mapping[str, Any]], keys: Sequence[str]) -> list[Any]: + result: list[Any] = [] + for part in parts: + value: Any = None + for key in keys: + if key in part: + value = part[key] + break + if value is None: + continue + if not isinstance(value, list): + raise S240Error("PART_PAYLOAD_TYPE", f"part payload must be an array: {keys[0]}") + result.extend(value) + return result + + +def unique_sorted(rows: Iterable[Any], id_keys: Sequence[str], *, code: str) -> list[dict[str, Any]]: + by_id: dict[str, dict[str, Any]] = {} + for value in rows: + row = require_object(value, code=code) + row_id: Any = None + for key in id_keys: + if key in row: + row_id = row[key] + break + row_id = require_ident(row_id, code=code) + if row_id in by_id and canonical_bytes(by_id[row_id]) != canonical_bytes(row): + raise S240Error("IMMUTABLE_ID_CONFLICT", f"conflicting immutable row: {row_id}") + by_id[row_id] = row + return [by_id[key] for key in sorted(by_id)] + + +def provenance_source_refs(rows: Any) -> list[str]: + refs: set[str] = set() + for row in rows if isinstance(rows, list) else []: + if not isinstance(row, dict): + continue + for key, value in row.items(): + if key.endswith("_ref") and isinstance(value, str) and value: + refs.add(value) + elif key.endswith("_refs") and isinstance(value, list): + refs.update(item for item in value if isinstance(item, str) and item) + elif key == "locator" and isinstance(value, dict): + refs.add("locator:" + digest(value)) + return sorted(refs) + + +def slot_values(text_or_slots: Mapping[str, Any]) -> dict[str, str | list[str]]: + rows = require_list(text_or_slots.get("slots"), code="ATOM_TYPED_SLOTS") + values: dict[str, str | list[str]] = {} + for value in rows: + row = require_object(value, code="ATOM_TYPED_SLOT") + slot_id = require_ident(row.get("slot_id"), code="ATOM_SLOT_ID") + if slot_id in values: + raise S240Error("ATOM_SLOT_DUPLICATE", f"duplicate typed slot: {slot_id}") + raw = row.get("value") + if raw is None: + continue + if not isinstance(raw, str): + raise S240Error("ATOM_SLOT_VALUE", "typed slot value must be string or null") + rendered = nfc(raw) + if any(token in rendered for token in ("{{", "}}", "\x00")): + raise S240Error("ATOM_SLOT_INJECTION", "typed slot contains forbidden token") + values[slot_id] = rendered + return values + + +def select_renderer_branch( + descriptor: Mapping[str, Any], branch_id: str, *, allow_fixture: bool, +) -> Mapping[str, Any]: + status = descriptor.get("status") + eligible = descriptor.get("execution_eligible") is True + if not eligible or status not in ({"APPROVED_LEGAL_CONTENT", "STRUCTURAL_FIXTURE_ONLY"} if allow_fixture else {"APPROVED_LEGAL_CONTENT"}): + raise S240Error("RENDERER_NOT_ELIGIBLE", "frozen renderer is not approved/execution-eligible") + branches = require_list(descriptor.get("branch_rows"), code="RENDER_BRANCH_ROWS") + matches = [row for row in branches if isinstance(row, dict) and row.get("branch_id") == branch_id] + if len(matches) != 1: + raise S240Error("RENDER_BRANCH_CARDINALITY", "template_branch_id must match exactly one frozen branch") + branch = matches[0] + if branch.get("approval_status") != "APPROVED": + raise S240Error("RENDER_BRANCH_NOT_APPROVED", "selected branch is not approved") + return branch + + +def render_segments( + descriptor: Mapping[str, Any], branch: Mapping[str, Any], slots: Mapping[str, Any], +) -> tuple[str, str]: + definitions = { + row.get("name"): row + for row in descriptor.get("typed_slot_contract", {}).get("slot_definitions", []) + if isinstance(row, dict) and isinstance(row.get("name"), str) + } + if set(slots) - set(definitions): + raise S240Error("RENDERER_UNKNOWN_SLOT", "atom supplies a slot outside frozen descriptor") + for name, definition in definitions.items(): + if definition.get("cardinality") in {"EXACTLY_ONE", "ONE_OR_MORE"} and name not in slots: + raise S240Error("RENDERER_REQUIRED_SLOT_MISSING", f"missing frozen slot: {name}") + segments = require_list(branch.get("segments"), code="RENDER_SEGMENTS") + + def render_a() -> str: + pieces: list[str] = [] + for segment in segments: + row = require_object(segment, code="RENDER_SEGMENT") + if row.get("kind") == "LITERAL" and set(row) == {"kind", "value"} and isinstance(row.get("value"), str): + pieces.append(nfc(row["value"])) + elif row.get("kind") == "SLOT" and set(row) == {"kind", "name", "escape"}: + name = row.get("name") + if name not in slots: + if definitions.get(name, {}).get("cardinality") == "ZERO_OR_ONE": + continue + raise S240Error("RENDERER_REQUIRED_SLOT_MISSING", f"missing segment slot: {name}") + value = slots[name] + pieces.append(", ".join(value) if isinstance(value, list) else str(value)) + else: + raise S240Error("RENDER_SEGMENT_SHAPE", "closed renderer segment is invalid") + return nfc("".join(pieces)) + + primary = render_a() + independent_segments = [dict(row) for row in segments] + independent_slots = {key: (list(value) if isinstance(value, list) else value) for key, value in slots.items()} + independent = "".join( + nfc(str(row["value"])) if row.get("kind") == "LITERAL" + else ( + ", ".join(independent_slots[row["name"]]) + if isinstance(independent_slots.get(row["name"]), list) + else str(independent_slots.get(row["name"], "")) + ) + for row in independent_segments + ) + independent = nfc(independent) + if primary.encode("utf-8") != independent.encode("utf-8"): + raise S240Error("RENDERER_INDEPENDENT_RERENDER_MISMATCH", "independent renderer bytes differ") + if PLACEHOLDER.search(primary): + raise S240Error("RENDER_DANGLING_SLOT", "closed renderer left a template token") + return primary, independent + + +def reduce_and_render(inputs: Mapping[str, Any], request: Mapping[str, Any]) -> dict[str, Any]: + parts = inputs["parts"] + atoms = unique_sorted( + flatten(parts["DRAFT_PART"], ("canonical_atoms",)), + ("atom_id",), code="DRAFT_ATOM_ID", + ) + atom_by_id: dict[str, dict[str, Any]] = {} + source_plan_hashes: set[str] = set() + for part in parts["DRAFT_PART"]: + source_plan_hashes.add(require_hex(part.get("source_plan_sha256"), code="DRAFT_SOURCE_PLAN_HASH")) + for atom in part["canonical_atoms"]: + require_self_hash(atom, "canonical_atom_sha256", code="CANONICAL_ATOM_SELF_HASH") + if "legal_admission" in atom or "closed_renderer" in atom: + raise S240Error("ATOM_SELF_ASSERTED_LEGAL_ADMISSION", "atom may not carry legal admission or renderer bytes") + atom_by_id[atom["atom_id"]] = atom + base_ledger = require_object( + inputs["ingress_documents"].get("review/issue_ledger.base.json"), + code="BASE_ISSUE_LEDGER", + ) + plan_ledger = require_object( + inputs["plan_documents"].get("plan/issue_ledger.plan.json"), + code="PLAN_ISSUE_LEDGER", + ) + base_issues = [dict(row) for row in require_list(base_ledger.get("issues"), code="BASE_ISSUES")] + base_issue_ids = sorted(str(row.get("issue_id")) for row in base_issues) + if ( + len(base_issue_ids) != len(set(base_issue_ids)) + or plan_ledger.get("preserved_base_issue_ids") != base_issue_ids + or plan_ledger.get("base_ledger_sha256") != digest(inputs["ingress_raws"]["review/issue_ledger.base.json"]) + ): + raise S240Error("ISSUE_LEDGER_BASE_CONSERVATION", "S2_20 did not preserve the exact S2_00 issue universe") + issues: list[dict[str, Any]] = list(base_issues) + issue_source_keys: list[str] = [f"S2_00:{value}" for value in base_issue_ids] + for row in require_list(plan_ledger.get("plan_issues"), code="PLAN_ISSUES"): + row = require_object(row, code="PLAN_ISSUE") + source_id = require_ident(row.get("issue_id"), code="PLAN_ISSUE_ID") + issue_id = source_id if re.fullmatch(r"ISS-[A-Fa-f0-9]{16,64}", source_id) else stable_id("ISS", "S2_20", source_id) + code = require_ident(row.get("code"), code="PLAN_ISSUE_CODE") + scope_ref = require_ident(row.get("scope_ref"), code="PLAN_ISSUE_SCOPE") + issues.append({ + "issue_id": issue_id, "issue_code": code, + "technical_severity": "REVIEW", "review_partition": "UNRESOLVED", + "impact_scope": "REVIEW_ITEM", "scope_refs": [scope_ref], + "source_contract_row_refs": [f"S2_20:{source_id}"], + "reason_codes": [code], "downstream_allowed_actions": ["REVIEW"], + "source_refs": [f"S2_20:{source_id}"], "status": "CARRIED_FORWARD", + }) + issue_source_keys.append(f"S2_20:{source_id}") + s210_impact = {"RUN_WIDE": "GLOBAL", "CLUSTER_LOCAL": "CLUSTER", "OPTION_ONLY": "REVIEW_ITEM"} + s210_severity = {"INFO": "INFO", "WARNING": "REVIEW", "BLOCKING": "BLOCK"} + for cluster_id, part in sorted(inputs["s210_handoff"]["issue_parts"].items()): + for row in require_list(part.get("issues"), code="S210_ISSUES"): + row = require_object(row, code="S210_ISSUE") + source_id = require_ident(row.get("issue_id"), code="S210_ISSUE_ID") + issue_id = stable_id("ISS", "S2_10", cluster_id, source_id) + issue_code = require_ident(row.get("issue_code"), code="S210_ISSUE_CODE") + source_refs = sorted(set(str(value) for value in row.get("source_refs", []) if isinstance(value, str) and value)) + issues.append({ + "issue_id": issue_id, "issue_code": issue_code, + "technical_severity": s210_severity.get(str(row.get("severity")), "REVIEW"), + "review_partition": "SUPPORTED" if row.get("status") == "RESOLVED" else "UNRESOLVED", + "impact_scope": s210_impact.get(str(row.get("impact_scope")), "REVIEW_ITEM"), + "scope_refs": [cluster_id], "source_contract_row_refs": [f"S2_10:{source_id}"], + "reason_codes": sorted(set([issue_code, *[str(value) for value in row.get("resolution_condition_codes", [])]])), + "downstream_allowed_actions": ["REVIEW"], + "source_refs": source_refs or [f"S2_10:{cluster_id}"], + "status": "CARRIED_FORWARD", + "upstream_review_key": source_id, "raw_item_sha256": digest(row), + }) + issue_source_keys.append(f"S2_10:{cluster_id}:{source_id}") + for part in parts["ISSUE_PATCH"]: + for code in sorted(set(part.get("review_flags", [])) | set(part.get("missing_inputs", []))): + issues.append({ + "issue_id": stable_id("ISS", part["claim_group_id"], code), + "issue_code": str(code), "technical_severity": "REVIEW", + "review_partition": "UNRESOLVED", "impact_scope": "REVIEW_ITEM", + "scope_refs": [part["claim_group_id"]], + "source_contract_row_refs": [f"S2_30:{part['claim_group_id']}"], + "reason_codes": [str(code)], + "downstream_allowed_actions": ["REVIEW"], + "source_refs": [f"S2_30:{part['claim_group_id']}"], "status": "OPEN", + }) + issue_source_keys.append(f"S2_30:{part['claim_group_id']}:CODE:{code}") + for row in part.get("adverse_fact_rows", []): + adverse_digest = digest(row) + issues.append({ + "issue_id": stable_id("ISS", part["claim_group_id"], adverse_digest), + "issue_code": "ADVERSE_FACT_PRESERVED", "technical_severity": "REVIEW", + "review_partition": "CONDITIONAL", "impact_scope": "FACT", + "scope_refs": [part["claim_group_id"]], + "source_contract_row_refs": [f"S2_30:{part['claim_group_id']}"], + "reason_codes": ["ADVERSE_FACT_PRESERVED"], + "downstream_allowed_actions": ["REVIEW"], + "source_refs": provenance_source_refs([row]) or [f"S2_30:{part['claim_group_id']}"], + "status": "OPEN", + }) + issue_source_keys.append(f"S2_30:{part['claim_group_id']}:ADVERSE:{adverse_digest}") + issues = unique_sorted(issues, ("issue_id",), code="ISSUE_ID") if issues else [] + worknotes: list[dict[str, Any]] = [] + for part in parts["WORKNOTE_PART"]: + for atom_id in part.get("worknote_atom_ids", []): + atom = atom_by_id.get(atom_id) + if atom is None or atom.get("output_section") != "worknote_only": + raise S240Error("WORKNOTE_ATOM_REF", "worknote part references a missing/non-worknote atom") + text = atom.get("text_or_slots", {}).get("draft_text") + if not isinstance(text, str) or not text: + text = canonical_bytes(atom.get("text_or_slots", {}).get("slots", [])).decode("utf-8").strip() + worknotes.append({ + "worknote_id": atom_id, "text": nfc(text), + "source_refs": provenance_source_refs(atom.get("provenance")) or [f"ATOM:{atom_id}"], + }) + assumptions: list[dict[str, Any]] = [] + assumption_source_keys: list[str] = [] + assumption_impact = {"RUN_WIDE": "GLOBAL", "CLUSTER_LOCAL": "CLAIM_GROUP", "OPTION_ONLY": "ATOMIC_CLAIM"} + for cluster_id, part in sorted(inputs["s210_handoff"]["assumption_parts"].items()): + for row in require_list(part.get("assumptions"), code="S210_ASSUMPTIONS"): + row = require_object(row, code="S210_ASSUMPTION") + local_ref = require_ident(row.get("assumption_local_ref"), code="S210_ASSUMPTION_REF") + basis = sorted(set(str(value) for value in row.get("basis_refs", []) if isinstance(value, str) and value)) + assumptions.append({ + "assumption_id": stable_id("ASM", cluster_id, local_ref), + "text": require_text(row.get("statement"), code="S210_ASSUMPTION_TEXT"), + "status": "OPEN", "source_refs": basis or [f"S2_10:{cluster_id}"], + "impact_scope": assumption_impact.get(str(row.get("impact_scope")), "CLAIM_GROUP"), + }) + assumption_source_keys.append(f"S2_10:{cluster_id}:{local_ref}") + assumptions = unique_sorted(assumptions, ("assumption_id",), code="ASSUMPTION_ID") if assumptions else [] + usage: list[dict[str, Any]] = [] + usage_source_keys: list[str] = [] + for cluster_id, part in sorted(inputs["s210_handoff"]["usage_parts"].items()): + usage.append({ + "source_stage": "S2_10", "source_scope_id": cluster_id, + "source_part_sha256": part["part_sha256"], "payload": dict(part), + }) + usage_source_keys.append(f"S2_10:{cluster_id}:{part['part_sha256']}") + for part in sorted(parts["USAGE_PART"], key=lambda row: row["claim_group_id"]): + usage.append({ + "source_stage": "S2_30", "source_scope_id": part["claim_group_id"], + "source_part_sha256": part["part_sha256"], "payload": dict(part), + }) + usage_source_keys.append(f"S2_30:{part['claim_group_id']}:{part['part_sha256']}") + relief_rows: list[dict[str, Any]] = [] + cause_rows: list[dict[str, Any]] = [] + render_errors: list[str] = [] + render_absences: list[str] = [] + rerender_equal = True + group_contracts = { + group_id: require_object(group_slice.get("claim_group"), code="GROUP_CONTRACT") + for group_id, group_slice in inputs["group_slices"].items() + } + for atom in atoms: + if atom.get("drafting_disposition") == "WORKNOTE_ONLY" or atom.get("output_section") == "worknote_only": + continue + text_slots = require_object(atom.get("text_or_slots"), code="ATOM_TEXT_OR_SLOTS") + renderer_id = require_ident(text_slots.get("renderer_id"), code="ATOM_RENDERER_ID") + branch_id = require_ident(text_slots.get("template_branch_id"), code="ATOM_BRANCH_ID") + descriptor = inputs["renderer_descriptors"].get(renderer_id) + rendered: str | None = None + try: + if descriptor is None: + raise S240Error("RENDERER_DESCRIPTOR_MISSING", "S2_20 did not freeze selected renderer") + branch = select_renderer_branch(descriptor, branch_id, allow_fixture=request["compile_mode"] == "STRUCTURAL_FIXTURE") + rendered, independent = render_segments(descriptor, branch, slot_values(text_slots)) + rerender_equal = rerender_equal and rendered.encode("utf-8") == independent.encode("utf-8") + except S240Error as exc: + if exc.code in {"RENDERER_NOT_ELIGIBLE", "RENDERER_DESCRIPTOR_MISSING", "RENDER_BRANCH_NOT_APPROVED"}: + render_absences.append(f"{atom['atom_id']}:{exc.code}") + else: + render_errors.append(f"{atom['atom_id']}:{exc.code}") + section = atom.get("output_section") + group_contract = require_object(group_contracts.get(atom["claim_group_id"]), code="ATOM_GROUP_CONTRACT") + typed_group_projection = { + "party_refs": group_contract.get("party_refs", []), + "object_refs": group_contract.get("object_refs", []), + "amount_slots": group_contract.get("amount_slots", []), + "period_slots": group_contract.get("period_slots", []), + "calculation_receipt_ids": group_contract.get("calculation_receipt_ids", []), + "counter_performance_refs": group_contract.get("counter_performance_refs", []), + } + if section in {"relief_main", "relief_cost", "relief_provisional_execution"}: + if rendered is not None: + relief_rows.append({ + "atom_id": atom["atom_id"], "atomic_claim_id": atom["atomic_claim_id"], + "claim_group_id": atom["claim_group_id"], "output_section": section, + "renderer_id": renderer_id, "branch_id": branch_id, "text": rendered, + **typed_group_projection, + }) + elif section.startswith("cause_") or section == "procedural_declaration": + text = text_slots.get("draft_text") if text_slots.get("rendering_mode") == "REVIEW_TEXT_WITH_SLOTS" else rendered + if isinstance(text, str) and text and not PLACEHOLDER.search(text): + cause_rows.append({ + "atom_id": atom["atom_id"], "atomic_claim_id": atom["atomic_claim_id"], + "claim_group_id": atom["claim_group_id"], "output_section": section, + "text": nfc(text), "source_refs": provenance_source_refs(atom.get("provenance")), + **typed_group_projection, + }) + elif rendered is None: + render_absences.append(f"{atom['atom_id']}:CAUSE_TEXT_UNAVAILABLE") + relief_rows.sort(key=lambda row: (row["claim_group_id"], row["atomic_claim_id"], row["output_section"], row["atom_id"])) + cause_rows.sort(key=lambda row: (row["claim_group_id"], row["atomic_claim_id"], row["output_section"], row["atom_id"])) + legal_assets_admitted = bool(atoms) and not render_errors and not render_absences and all( + descriptor.get("status") == "APPROVED_LEGAL_CONTENT" and descriptor.get("execution_eligible") is True + for descriptor in inputs["renderer_descriptors"].values() + ) + clean_render_allowed = request["compile_mode"] in {"SUBSET_CANARY", "PRODUCTION"} and legal_assets_admitted + relief = "\n".join(f"{index}. {row['text']}" for index, row in enumerate(relief_rows, 1)) if clean_render_allowed else "" + cause = "\n\n".join(row["text"] for row in cause_rows) if clean_render_allowed else "" + pleading = f"# 청구취지\n\n{relief}\n\n# 청구원인\n\n{cause}" if clean_render_allowed else "" + return { + "atoms": atoms, "issues": issues, "worknotes": worknotes, "usage": usage, + "assumptions": assumptions, + "conservation": { + "issue_source_keys": sorted(issue_source_keys), + "issue_ids": sorted(str(row["issue_id"]) for row in issues), + "assumption_source_keys": sorted(assumption_source_keys), + "assumption_ids": sorted(str(row["assumption_id"]) for row in assumptions), + "usage_source_keys": sorted(usage_source_keys), + }, + "relief_rows": relief_rows, "cause_rows": cause_rows, + "relief": relief, "cause": cause, "pleading": pleading, + "render_errors": sorted(set(render_errors)), "render_absences": sorted(set(render_absences)), + "rerender_equal": rerender_equal, "clean_render_allowed": clean_render_allowed, + "legal_assets_admitted": legal_assets_admitted, + "source_plan_hashes": sorted(source_plan_hashes), + } + + +def invariant_result( + invariant_id: str, observed: bool | None, reason: str, + *, source_refs: Sequence[str] = (), incomplete: bool = False, +) -> dict[str, Any]: + status = "UNEVALUABLE" if observed is None else ("PASS" if observed else "FAIL") + scope = "OK" if status == "PASS" else ("INCOMPLETE" if incomplete else "REVIEW_REQUIRED") + return { + "invariant_id": invariant_id, "evaluation_status": status, + "finding_ids": [] if status == "PASS" else [stable_id("F40", invariant_id, reason)], + "impact_scope": scope, "source_refs": sorted(set(source_refs)), + "expected": True, "observed": observed, "reason_codes": [reason], + "validator_algorithm_id": f"{ALGORITHM_VERSION}::{invariant_id}", + } + + +def invariant_results(inputs: Mapping[str, Any], reduced: Mapping[str, Any], request: Mapping[str, Any]) -> list[dict[str, Any]]: + atoms = reduced["atoms"] + relief_claims = {row["atomic_claim_id"] for row in reduced["relief_rows"]} + cause_claims = {row["atomic_claim_id"] for row in reduced["cause_rows"]} + slot_rows = [row for atom in atoms for row in atom.get("text_or_slots", {}).get("slots", []) if isinstance(row, dict)] + slot_ids = [(atom["atom_id"], row.get("slot_id")) for atom in atoms for row in atom.get("text_or_slots", {}).get("slots", []) if isinstance(row, dict)] + legal_provenance = [row for atom in atoms for row in atom.get("provenance", []) if isinstance(row, dict) and row.get("proposition_kind") == "LEGAL_PROPOSITION"] + defense_rows = [row for atom in atoms for row in atom.get("provenance", []) if isinstance(row, dict) and "REBUTTAL" in str(row.get("proposition_kind", ""))] + binding_rows = [row for pack in inputs["rule_packs"].values() for row in pack.get("binding_rows", []) if isinstance(row, dict)] + binding_by_claim: dict[str, list[dict[str, Any]]] = {} + for row in binding_rows: + binding_by_claim.setdefault(str(row.get("atomic_claim_id")), []).append(row) + selected_claims = {str(row.get("atomic_claim_id")) for row in binding_rows if row.get("case_type_binding_status") == "BOUND" and row.get("sub_rule_binding_status") == "BOUND"} + all_claims = {str(atom.get("atomic_claim_id")) for atom in atoms} + calculation_tokens = [row for row in slot_rows if row.get("value_kind") == "CALCULATION_TOKEN"] + calc_observed: bool | None = None if not calculation_tokens else bool(inputs["calculation_receipts"]) + provenance_complete = all(bool(provenance_source_refs(atom.get("provenance"))) for atom in atoms) + option_ids: list[str] = [] + partition_ids: list[str] = [] + option_evaluable = False + for group_slice in inputs["group_slices"].values(): + claim_group = group_slice.get("claim_group", {}) + if isinstance(claim_group, dict): + ids = claim_group.get("claim_option_ids", claim_group.get("option_ids", [])) + if isinstance(ids, list): + option_ids.extend(str(item) for item in ids) + partition = claim_group.get("option_partition", {}) + if isinstance(partition, dict): + option_evaluable = True + for name in ("selected", "alternative", "excluded", "deferred"): + values = partition.get(name, []) + if isinstance(values, list): + partition_ids.extend(str(item) for item in values) + option_ok = None if not option_evaluable else len(partition_ids) == len(set(partition_ids)) and set(partition_ids) == set(option_ids) + exhibit_rows = inputs["exhibit_register"].get("rows") + exhibit_ok = None if not isinstance(exhibit_rows, list) else all(isinstance(row, dict) for row in exhibit_rows) + authority_ok = None if not legal_provenance else all(row.get("authority_id") and row.get("locator") for row in legal_provenance) + closure_rows = inputs.get("input_closure_rows", []) + expected_closure = { + "ingress/ingress_status.json": ("stage2_s2_00_ingress_status.v1", "stage2_s2_00_ingress_status.v1.1", "S2_00"), + "map_s2_10/s2_10_publish_status.json": ("stage2_s2_10_publish_status.v2", "S2_10_NATIVE_RESULT_ADAPTER"), + "plan/plan_publish_status.json": ("stage2_plan_publish_status.v1", "S2_20"), + "map_s2_30/s2_30_publish_status.json": ("stage2_s2_30_publish_status.v1", "S2_30"), + "map_s2_30/artifact_manifest.json": ("stage2_s2_30_part_manifest_core.v1", "S2_30"), + } + closure_by_path = {str(row.get("path")): row for row in closure_rows if isinstance(row, dict)} + v01 = ( + len(closure_rows) == len(closure_by_path) + and set(expected_closure).issubset(closure_by_path) + and all( + row.get("schema_valid") is True + and row.get("hash_match") is True + and row.get("sha256") == row.get("expected_sha256") + and HEX64.fullmatch(str(row.get("sha256", ""))) + and isinstance(row.get("schema_ref"), str) + for row in closure_rows if isinstance(row, dict) + ) + ) + if v01: + for path, allowed in expected_closure.items(): + row = closure_by_path[path] + version_allowed = allowed[:-1] + producer = allowed[-1] + if not ( + row.get("schema_version") in version_allowed + and row.get("producer_id") == producer + and row.get("schema_valid") is True + and row.get("hash_match") is True + and row.get("sha256") == row.get("expected_sha256") + and HEX64.fullmatch(str(row.get("sha256", ""))) + and isinstance(row.get("schema_ref"), str) + ): + v01 = False + break + atom_groups = {str(atom.get("claim_group_id")) for atom in atoms} + source_atoms = [row for part in inputs["parts"]["DRAFT_PART"] for row in part.get("canonical_atoms", [])] + source_atom_ids = [str(row.get("atom_id")) for row in source_atoms if isinstance(row, dict)] + reduced_atom_ids = [str(row.get("atom_id")) for row in atoms] + source_worknote_ids = sorted( + str(atom_id) for part in inputs["parts"]["WORKNOTE_PART"] + for atom_id in part.get("worknote_atom_ids", []) + ) + conservation = require_object(reduced.get("conservation"), code="V02_CONSERVATION") + issue_source_keys = require_list(conservation.get("issue_source_keys"), code="V02_ISSUE_KEYS") + assumption_source_keys = require_list(conservation.get("assumption_source_keys"), code="V02_ASSUMPTION_KEYS") + usage_source_keys = require_list(conservation.get("usage_source_keys"), code="V02_USAGE_KEYS") + v02 = ( + bool(atoms) + and atom_groups == set(inputs["group_ids"]) + and len(source_atom_ids) == len(set(source_atom_ids)) + and sorted(source_atom_ids) == sorted(reduced_atom_ids) + and len(issue_source_keys) == len(set(issue_source_keys)) == len(reduced["issues"]) + and len(assumption_source_keys) == len(set(assumption_source_keys)) == len(reduced["assumptions"]) + and len(usage_source_keys) == len(set(usage_source_keys)) == len(reduced["usage"]) + and source_worknote_ids == sorted(str(row.get("worknote_id")) for row in reduced["worknotes"]) + and inputs["s210_handoff"]["cluster_ids"] == inputs["ingress"]["executable_cluster_ids"] + ) + v03 = all(row.get("slot_id") and row.get("namespace_owner") and row.get("domain_id") for row in slot_rows) if slot_rows else None + v04 = all( + row.get("opposing_fact_id") and row.get("rebuttal_id") and row.get("evidence_refs") + and row.get("polarity") and row.get("presentation_status") + for row in defense_rows + ) if defense_rows else None + v05 = all( + isinstance(group_slice.get("claim_group"), dict) + and group_slice.get("claim_group", {}).get("dependency_wave_id") + and group_slice.get("claim_group", {}).get("relation_consistency_status") == "PASS" + for group_slice in inputs["group_slices"].values() + ) if inputs["group_slices"] else None + v07 = all( + token.get("calculation_receipt_id") in inputs["calculation_receipts"] + and token.get("operand_digest") == inputs["calculation_receipts"][token["calculation_receipt_id"]].get("operand_digest") + and inputs["calculation_receipts"][token["calculation_receipt_id"]].get("missing_law_values") in ([], None) + for token in calculation_tokens + ) if calculation_tokens else None + recovery_keys = [(atom.get("recovery_object_id"), atom.get("recovery_scope")) for atom in atoms if atom.get("recovery_object_id")] + v08 = len(recovery_keys) == len(set(recovery_keys)) if recovery_keys else None + canonical_plan = inputs["plan_documents"].get("plan/canonical_relief_plan.json") + canonical_plan_raw = inputs["plan_raw_by_path"].get("plan/canonical_relief_plan.json") + plan_claims = { + str(row.get("atomic_claim_id")): row + for row in (canonical_plan.get("atomic_claims", []) if isinstance(canonical_plan, dict) else []) + if isinstance(row, dict) + } + plan_hash = digest(canonical_plan_raw) if isinstance(canonical_plan_raw, bytes) else None + v09 = all( + atom.get("source_plan_sha256") == plan_hash + and atom.get("atomic_claim_id") in plan_claims + and plan_claims[atom["atomic_claim_id"]].get("claim_group_id") == atom.get("claim_group_id") + and atom.get("claim_option_id") in plan_claims[atom["atomic_claim_id"]].get("source_claim_option_ids", []) + and len(binding_by_claim.get(str(atom.get("atomic_claim_id")), [])) == 1 + for atom in atoms + ) if atoms else None + v10 = (not reduced["render_errors"] and not reduced["render_absences"] and + all(row.get("output_section") and row.get("text") for row in reduced["relief_rows"] + reduced["cause_rows"])) if atoms else None + def relation_signature(row: Mapping[str, Any]) -> tuple[str, str, str, str, str, str, str]: + return ( + str(row.get("atomic_claim_id")), digest(row.get("party_refs", [])), + digest(row.get("object_refs", [])), digest(row.get("amount_slots", [])), + digest(row.get("period_slots", [])), digest(row.get("calculation_receipt_ids", [])), + digest(row.get("counter_performance_refs", [])), + ) + relief_relation = {relation_signature(row) for row in reduced["relief_rows"]} + cause_relation = {relation_signature(row) for row in reduced["cause_rows"]} + v11 = relief_relation == cause_relation if relief_relation or cause_relation else None + v12 = all(pack.get("corpus_release_sha256") and pack.get("slot_crosswalk_status") == "PASS" and pack.get("injection_isolation_status") == "PASS" for pack in inputs["plan_documents"].values() if isinstance(pack, dict) and pack.get("schema_version") == "stage2_requirement_fact_pack.v1") or None + v13 = all(row.get("authority_id") and row.get("locator") and row.get("temporal_scope_status") == "PASS" and row.get("negative_treatment_status") == "CLEAR" for row in legal_provenance) if legal_provenance else None + def contains_downstream_key(value: Any) -> bool: + forbidden_keys = { + "candidate_content_digest", "review_subject_digest", "review_receipt_sha256s", + "stage2_package_sha256", "commit_intent_sha256", + "commit_result_sha256", "status_event_sha256", + } + if isinstance(value, dict): + return any(key in forbidden_keys or contains_downstream_key(item) for key, item in value.items()) + if isinstance(value, list): + return any(contains_downstream_key(item) for item in value) + return False + v14 = not contains_downstream_key({ + "parts": inputs.get("parts"), "group_slices": inputs.get("group_slices"), + "rule_packs": inputs.get("rule_packs"), "plan_documents": inputs.get("plan_documents"), + "ingress_documents": inputs.get("ingress_documents"), + "s210_handoff": inputs.get("s210_handoff"), + }) and inputs.get("frozen_source_rows") == sorted( + inputs.get("frozen_source_rows", []), key=lambda row: (row["path"], row["sha256"]) + ) if atoms else None + v15 = all(atom.get("provenance") and all(row.get("source_ref") or row.get("source_refs") for row in atom.get("provenance", []) if isinstance(row, dict)) for atom in atoms) if atoms else None + v17 = all(row.get("party_id") and row.get("object_id") and row.get("exhibit_id") and row.get("party_title") for row in exhibit_rows) if isinstance(exhibit_rows, list) and exhibit_rows else None + renderer_observed: bool | None = ( + False if reduced["render_errors"] else + (None if reduced["render_absences"] else bool(reduced["relief_rows"] or reduced["cause_rows"]) and reduced["rerender_equal"]) + ) + checks = { + "V01": invariant_result("V01", v01, "BOUND_INPUT_HASH_SCHEMA_PRODUCER", incomplete=True), + "V02": invariant_result("V02", v02, "REVIEW_UNIVERSE_CONSERVED", incomplete=True), + "V03": invariant_result("V03", v03, "DOMAIN_SLOT_NAMESPACE_BOUND"), + "V04": invariant_result("V04", v04, "DEFENSE_REBUTTAL_PROVENANCE_BOUND"), + "V05": invariant_result("V05", v05, "DEPENDENCY_WAVE_BOUND"), + "V06": invariant_result("V06", all(len(binding_by_claim.get(claim, [])) == 1 and claim in selected_claims for claim in all_claims) if all_claims else None, "CASE_TYPE_SUB_RULE_EXACT"), + "V07": invariant_result("V07", v07, "CALCULATION_RECEIPT_BOUND"), + "V08": invariant_result("V08", v08, "DUPLICATE_RECOVERY_ABSENT"), + "V09": invariant_result("V09", v09, "RELIEF_PLAN_MATCH"), + "V10": invariant_result("V10", v10, "DOCUMENT_ORDER_TEMPLATE_MATCH"), + "V11": invariant_result("V11", v11, "RELIEF_CAUSE_CROSSMATCH"), + "V12": invariant_result("V12", v12, "CORPUS_BOUND"), + "V13": invariant_result("V13", v13, "AUTHORITY_TEMPORAL_BOUND"), + "V14": invariant_result("V14", v14, "NON_CYCLIC_DIGEST_GRAPH"), + "V15": invariant_result("V15", v15, "PROVENANCE_COMPLETE"), + "V16": invariant_result("V16", option_ok, "OPTION_PARTITION_EXACT"), + "V17": invariant_result("V17", v17, "PARTY_OBJECT_EXHIBIT_COMPLETE"), + "V18": invariant_result("V18", renderer_observed, "CLOSED_RENDER_AND_RERENDER_EQUAL"), + } + return [checks[invariant_id] for invariant_id in V_IDS] + + +def review_request_basis( + inputs: Mapping[str, Any], + validation: Sequence[Mapping[str, Any]], + review_policy_contract: Mapping[str, Any], + parent_release_sha256: str, +) -> dict[str, Any]: + review_policies = [ + value for value in inputs.get("frozen_assets", {}).values() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + if len(review_policies) > 1: + raise S240Error("REVIEW_POLICY_CARDINALITY", "multiple frozen review policies") + policy = review_policies[0] if review_policies else None + policy_sha256 = digest(policy) if policy is not None else digest({"status": "MISSING_REVIEW_POLICY"}) + corpus_hashes = sorted({ + str(value.get("corpus_release_sha256")) for value in inputs.get("plan_documents", {}).values() + if isinstance(value, dict) and value.get("schema_version") == "stage2_requirement_fact_pack.v1" + }) + release_sha256s = { + "parent": parent_release_sha256, + "authority": require_hex(inputs.get("authority_release_sha256"), code="REVIEW_AUTHORITY_RELEASE_HASH"), + "corpus": corpus_hashes[0] if len(corpus_hashes) == 1 and HEX64.fullmatch(corpus_hashes[0]) else digest(corpus_hashes), + "case_type_coverage": require_hex(inputs.get("case_type_coverage_sha256"), code="REVIEW_CASE_TYPE_COVERAGE_HASH"), + } + return { + "schema_version": "stage2_s2_40_review_request_basis.v1", + "required_receipt_types": review_policy_contract["required_receipt_types"], + "scope_ids": inputs["group_ids"], + "finding_ids": sorted(row["finding_ids"][0] for row in validation if row["finding_ids"]), + "policy_version": str(policy.get("schema_version")) if policy is not None else "MISSING_REVIEW_POLICY", + "policy_sha256": policy_sha256, + "reviewer_role": TRUSTED_REVIEW_ROLE, + "reviewer_qualification": TRUSTED_REVIEW_QUALIFICATION, + "release_snapshot_sha256s": release_sha256s, + } + + +def review_subject( + candidate_digest: str, + lawyer_review_packet_core_sha256: str, + validation_envelope_core_sha256: str, + basis: Mapping[str, Any], +) -> dict[str, Any]: + cores: list[dict[str, Any]] = [] + bindings: list[dict[str, str]] = [] + for receipt_type in require_list(basis.get("required_receipt_types"), code="REVIEW_REQUIRED_TYPES"): + core = { + "candidate_content_digest": candidate_digest, "receipt_type": receipt_type, + "scope_ids": basis["scope_ids"], "finding_ids": basis["finding_ids"], + "policy_version": basis["policy_version"], "policy_sha256": basis["policy_sha256"], + "reviewer_role": basis["reviewer_role"], + "reviewer_qualification": basis["reviewer_qualification"], + "release_snapshot_sha256s": basis["release_snapshot_sha256s"], + } + cores.append(core) + bindings.append({ + "receipt_type": str(receipt_type), + "review_request_core_sha256": digest(core), + }) + bindings.sort(key=lambda row: row["receipt_type"]) + if len(bindings) != len({row["receipt_type"] for row in bindings}): + raise S240Error("REVIEW_REQUEST_TYPE_DUPLICATE", "review request receipt types must be unique") + subject_core = { + "schema_version": "stage2_s2_40_review_subject.v1", + "domain_separator": "STAGE2_S2_40_REVIEW_SUBJECT_V1", + "candidate_content_digest": candidate_digest, + "review_request_core_bindings": bindings, + "lawyer_review_packet_core_sha256": lawyer_review_packet_core_sha256, + "validation_envelope_core_sha256": validation_envelope_core_sha256, + "finding_ids": basis["finding_ids"], "scope_ids": basis["scope_ids"], + "review_policy_sha256": basis["policy_sha256"], + "release_sha256s": basis["release_snapshot_sha256s"], + } + subject = digest(subject_core) + core_by_type = {str(core["receipt_type"]): core for core in cores} + requests = [ + { + "request_id": stable_id( + "RR40", "STAGE2_S2_40_REVIEW_REQUEST_V1", subject, + binding["receipt_type"], *sorted(basis["scope_ids"]), + ), + "receipt_type": binding["receipt_type"], + "core": core_by_type[binding["receipt_type"]], + "core_sha256": binding["review_request_core_sha256"], + "review_subject_digest": subject, + } + for binding in bindings + ] + return { + "review_subject_digest": subject, + "subject": {**subject_core, "review_subject_digest": subject}, + "bindings": bindings, "requests": requests, + } + + +def aggregate_validation(validation: Sequence[Mapping[str, Any]]) -> dict[str, str]: + scopes = {row.get("impact_scope") for row in validation} + if "INCOMPLETE" in scopes: + run_status = "TECHNICAL_INCOMPLETE" + elif any(row.get("evaluation_status") != "PASS" for row in validation): + run_status = "TECHNICAL_REVIEW_REQUIRED" + else: + run_status = "CONSISTENT" + artifact_status = ( + "NOT_PRODUCED" if run_status == "TECHNICAL_INCOMPLETE" + else ("TECHNICAL_REVIEW_REQUIRED" if run_status == "TECHNICAL_REVIEW_REQUIRED" else "CONSISTENT") + ) + return {"run_technical_status": run_status, "artifact_technical_status": artifact_status} + + +def legal_gate_snapshot(inputs: Mapping[str, Any], reduced: Mapping[str, Any]) -> dict[str, bool]: + binding_rows = [ + row for pack in inputs["rule_packs"].values() + for row in pack.get("binding_rows", []) if isinstance(row, dict) + ] + review_policies = [ + value for value in inputs.get("frozen_assets", {}).values() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + structured_rules = [ + value for path, value in inputs.get("frozen_assets", {}).items() + if "case_type_relief_rules" in path + ] + calculations = list(inputs.get("calculation_receipts", {}).values()) + requirement_packs = [ + value for value in inputs.get("plan_documents", {}).values() + if isinstance(value, dict) and value.get("schema_version") == "stage2_requirement_fact_pack.v1" + ] + authority_release = require_object(inputs.get("authority_release"), code="AUTHORITY_RELEASE_OBJECT") + authority_signature = authority_release.get("signature") + authority_ok = ( + authority_release.get("status") == "PRODUCTION_ADMITTED" + and authority_release.get("release_class") == "PRODUCTION_RELEASE" + and authority_release.get("sealed") is True + and authority_release.get("signed") is True + and authority_release.get("executable") is True + and authority_release.get("unresolved") == [] + and isinstance(authority_signature, str) and bool(authority_signature) + and not authority_signature.startswith("PENDING") + and require_object(authority_release.get("registry"), code="AUTHORITY_REGISTRY_REF").get("required_status") == "VERIFIED" + and authority_release.get("hash_binding_status") == "PRODUCTION_ADMITTED" + ) + coverage = require_object(inputs.get("case_type_coverage"), code="CASE_TYPE_COVERAGE_OBJECT") + coverage_rows = require_list(coverage.get("coverage_rows"), code="CASE_TYPE_COVERAGE_ROWS") + case_registry = require_object(inputs.get("case_type_registry"), code="CASE_TYPE_REGISTRY_OBJECT") + rule_registry = require_object(inputs.get("case_type_rule_registry"), code="CASE_TYPE_RULE_REGISTRY_OBJECT") + case_rows = require_list(case_registry.get("rows"), code="CASE_TYPE_REGISTRY_ROWS") + rule_rows = require_list(rule_registry.get("rows"), code="CASE_TYPE_RULE_REGISTRY_ROWS") + approved_values = {"APPROVED", "VERIFIED", "IMPLEMENTED", "RELEASED", "PRODUCTION_ADMITTED", "PASS"} + downstream_keys = { + "relief_rule", "renderer", "corpus", "substantive_profile", + "special_law_or_overlay", "calculation", "review_policy", + } + expected_case_ids = [f"CT-{index:03d}" for index in range(1, 138)] + expected_catalog_ids = [f"CAT-{index:03d}" for index in range(1, 138)] + coverage_ids = [row.get("case_type_id") for row in coverage_rows if isinstance(row, dict)] + case_ids = [row.get("case_type_id") for row in case_rows if isinstance(row, dict)] + rule_ids = [row.get("case_type_id") for row in rule_rows if isinstance(row, dict)] + claim_capable_ids = [ + str(row.get("case_type_id")) for row in case_rows if isinstance(row, dict) + and row.get("claim_capable_disposition") == "CLAIM_CAPABLE" + ] + coverage_rows_ok = ( + coverage_ids == expected_case_ids + and case_ids == expected_case_ids + and rule_ids == expected_case_ids + and case_registry.get("catalog_row_ids") == expected_catalog_ids + and [row.get("catalog_row_id") for row in case_rows] == expected_catalog_ids + and [row.get("source_ordinal") for row in case_rows] == list(range(1, 138)) + and [row.get("canonical_name_ko") for row in coverage_rows] + == [row.get("source_label") for row in case_rows] + ) + for row, registry_row, rule_row in zip(coverage_rows, case_rows, rule_rows): + if not isinstance(row, dict): + coverage_rows_ok = False + continue + downstream = row.get("downstream_coverage") + rule_branches = rule_row.get("rule_branches") if isinstance(rule_row, dict) else None + branch_or_nonclaim_ok = ( + isinstance(rule_branches, list) + and bool(rule_branches) + and all(isinstance(branch, dict) and branch.get("legal_content_status") == "APPROVED" for branch in rule_branches) + ) or ( + isinstance(rule_row, dict) + and rule_row.get("non_claim_disposition") in {"COMPANION_ONLY", "CLASSIFICATION_ONLY"} + and isinstance(rule_row.get("companion_case_type_ids"), list) + ) + if ( + row.get("catalog_mapping_status") not in approved_values + or row.get("legal_signoff") not in approved_values + or row.get("technical_verification") not in approved_values + or row.get("release_status") not in approved_values + or not isinstance(downstream, dict) + or set(downstream) != downstream_keys + or any(value not in approved_values for value in downstream.values()) + or row.get("issue_codes") != [] + or not isinstance(registry_row, dict) + or registry_row.get("legal_classification_status") != "APPROVED" + or registry_row.get("legal_content_status") != "APPROVED" + or not isinstance(rule_row, dict) + or rule_row.get("legal_classification_status") != "APPROVED" + or rule_row.get("legal_content_status") != "APPROVED" + or not branch_or_nonclaim_ok + ): + coverage_rows_ok = False + coverage_catalog = require_object(coverage.get("catalog"), code="CASE_TYPE_COVERAGE_CATALOG") + coverage_dependency = require_object(coverage.get("registry_dependency"), code="CASE_TYPE_COVERAGE_REGISTRY_DEPENDENCY") + coverage_summary = require_object(coverage.get("summary"), code="CASE_TYPE_COVERAGE_SUMMARY") + coverage_ok = ( + coverage.get("release_eligible") is True + and coverage.get("status") == "FULL_137_PRODUCTION_READY" + and coverage_catalog.get("sha256") == case_registry.get("catalog_source_sha256") + and coverage_dependency.get("path") == CASE_TYPE_REGISTRY_REL + and coverage_dependency.get("sha256") == inputs.get("case_type_registry_sha256") + and rule_registry.get("case_type_registry_ref") == CASE_TYPE_REGISTRY_REL + and rule_registry.get("case_type_registry_sha256") == inputs.get("case_type_registry_sha256") + and coverage_summary.get("total_case_type_rows") == 137 + and coverage_summary.get("markdown_doc_count") == 137 + and coverage.get("release_scope_catalog_row_ids") == expected_catalog_ids + and coverage.get("excluded_catalog_row_ids") == [] + and coverage.get("release_scope_claim_capable_ids") == claim_capable_ids + and coverage_rows_ok + ) + gates = { + "binding": bool(binding_rows) and all(row.get("case_type_binding_status") == "BOUND" and row.get("sub_rule_binding_status") == "BOUND" for row in binding_rows), + "authority": authority_ok, + "renderer_branch": reduced["legal_assets_admitted"], + "rule_sub_rule": bool(structured_rules) and all(value.get("execution_eligible") is True and value.get("status") in {"APPROVED", "LEGAL_CONTENT_ADMITTED"} for value in structured_rules), + "review_policy": len(review_policies) == 1 and review_policies[0].get("execution_eligible") is True and review_policies[0].get("status") == "APPROVED_LEGAL_CONTENT", + "case_type_coverage_137": coverage_ok, + "corpus": bool(requirement_packs) and all(require_hex(value.get("corpus_release_sha256"), code="CORPUS_RELEASE_HASH") for value in requirement_packs), + "law_value": all(row.get("calculation_status") == "CALCULATED" and not row.get("missing_law_values") for row in calculations) if calculations else True, + "calculator": all(row.get("calculation_status") == "CALCULATED" for row in calculations) if calculations else True, + "required_receipts": False, + } + if set(gates) != REQUIRED_LEGAL_GATES: + raise S240Error("LEGAL_GATE_SET", "legal gate set is not closed") + return gates + + +def resolve_review_policy_contract( + inputs: Mapping[str, Any], validation: Sequence[Mapping[str, Any]], legal_gates: Mapping[str, bool], +) -> dict[str, Any]: + policy_values = [ + (path, value) for path, value in inputs.get("frozen_assets", {}).items() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + if len(policy_values) > 1: + raise S240Error("REVIEW_POLICY_CARDINALITY", "multiple frozen review policies") + policy_path, policy = policy_values[0] if len(policy_values) == 1 else ( + "MISSING_REVIEW_POLICY", {"status": "MISSING_REVIEW_POLICY"}, + ) + active_tags = sorted({ + str(reason) for row in validation if row.get("evaluation_status") != "PASS" + for reason in row.get("reason_codes", []) + }) + runtime_triggers = sorted( + str(row.get("invariant_id")) for row in validation if row.get("evaluation_status") != "PASS" + ) + approved = policy.get("execution_eligible") is True and policy.get("status") == "APPROVED_LEGAL_CONTENT" + final_contract = policy.get("final_review_contract") if isinstance(policy.get("final_review_contract"), dict) else {} + allowed_types = set(final_contract.get("policy_result_enum", [ + "STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW", + ])) + if approved: + required_types = list(final_contract.get("base_required_receipt_types", [])) + for row in policy.get("policy_rows", []) if isinstance(policy.get("policy_rows"), list) else []: + if not isinstance(row, dict): + raise S240Error("REVIEW_POLICY_ROW", "review policy row must be an object") + row_tags = set(row.get("trigger_tags", row.get("active_tags", []))) + row_triggers = set(row.get("runtime_triggers", row.get("invariant_ids", []))) + if row.get("always_required") is True or row_tags.intersection(active_tags) or row_triggers.intersection(runtime_triggers): + required_types.extend(row.get("required_receipt_types", [])) + else: + default = policy.get("default_unapproved_result") if isinstance(policy.get("default_unapproved_result"), dict) else {} + required_types = list(default.get("required_receipt_types", ["STANDARD_ATTORNEY_REVIEW"])) + if any(not isinstance(value, str) or value not in allowed_types for value in required_types): + raise S240Error("REVIEW_POLICY_RECEIPT_TYPE", "policy emitted a receipt type outside its closed enum") + required_types = sorted(set(required_types)) + if "MANDATORY_SPECIALIST_REVIEW" in required_types: + base_policy = "MANDATORY_SPECIALIST_REVIEW" + elif "STANDARD_ATTORNEY_REVIEW" in required_types: + base_policy = "STANDARD_ATTORNEY_REVIEW" + else: + fallback = final_contract.get("missing_or_unapproved_policy_result", "STANDARD_ATTORNEY_REVIEW") + base_policy = fallback if fallback in allowed_types else "STANDARD_ATTORNEY_REVIEW" + pre_receipt_ready = ( + approved + and not active_tags + and all(value for key, value in legal_gates.items() if key != "required_receipts") + ) + return { + "policy_path": policy_path, "policy": policy, + "policy_registry_sha256": digest(policy), "base_policy": base_policy, + "active_tags": active_tags, "runtime_triggers": runtime_triggers, + "required_receipt_types": required_types, + "pre_receipt_ready_eligible": pre_receipt_ready, + } + + +def candidate_material(inputs: Mapping[str, Any], reduced: Mapping[str, Any], validation: Sequence[Mapping[str, Any]], request: Mapping[str, Any]) -> dict[str, Any]: + schema_store = require_object(inputs.get("schema_store"), code="OUTPUT_SCHEMA_STORE") + documents: dict[str, bytes] = {} + if reduced["clean_render_allowed"]: + documents = { + "claim_relief.md": canonical_markdown(reduced["relief"]), + "claim_cause.md": canonical_markdown(reduced["cause"]), + "pleading_draft.md": canonical_markdown(reduced["pleading"]), + } + legal_gates = legal_gate_snapshot(inputs, reduced) + review_contract = resolve_review_policy_contract(inputs, validation, legal_gates) + conservation = require_object(reduced.get("conservation"), code="CONSERVATION_OBJECT") + issue_source_keys = require_list(conservation.get("issue_source_keys"), code="ISSUE_SOURCE_KEYS") + assumption_source_keys = require_list(conservation.get("assumption_source_keys"), code="ASSUMPTION_SOURCE_KEYS") + usage_source_keys = require_list(conservation.get("usage_source_keys"), code="USAGE_SOURCE_KEYS") + if ( + len(issue_source_keys) != len(set(issue_source_keys)) + or len(issue_source_keys) != len(reduced["issues"]) + or len(assumption_source_keys) != len(set(assumption_source_keys)) + or len(assumption_source_keys) != len(reduced["assumptions"]) + or len(usage_source_keys) != len(set(usage_source_keys)) + or len(usage_source_keys) != len(reduced["usage"]) + ): + raise S240Error("REVIEW_UNIVERSE_CONSERVATION", "issue/assumption/usage occurrence universe was not conserved") + source_ledger_hashes = sorted({ + digest(inputs["ingress_raws"]["review/issue_ledger.base.json"]), + digest(inputs["plan_raw_by_path"]["plan/issue_ledger.plan.json"]), + }) + s210_issue_hashes = { + digest(raw) for path, raw in inputs["s210_handoff"]["raw_by_path"].items() + if path.startswith("map_s2_10/issue_patches/") + } + s230_issue_hashes = { + row["sha256"] for row in inputs["rows"] if row["part_family"] == "ISSUE_PATCH" + } + ledger = { + "schema_version": "stage2_s2_40_final_issue_ledger.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "source_ledger_sha256s": source_ledger_hashes, + "source_issue_part_sha256s": sorted(s210_issue_hashes | s230_issue_hashes), + "issues": reduced["issues"], "conservation_status": "PASS", + } + s210_assumption_hashes = sorted({ + digest(raw) for path, raw in inputs["s210_handoff"]["raw_by_path"].items() + if path.startswith("map_s2_10/assumption_parts/") + }) + assumptions = { + "schema_version": "stage2_s2_40_assumption_ledger.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "source_assumption_part_sha256s": s210_assumption_hashes, + "rows": reduced["assumptions"], "conservation_status": "PASS", + } + source_usage_hashes = sorted({ + row["source_part_sha256"] for row in reduced["usage"] + }) + usage_projection = { + "schema_version": "stage2_s2_40_usage_projection.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "source_usage_part_sha256s": source_usage_hashes, + "rows": reduced["usage"], "conservation_status": "PASS", + } + worknotes_core = { + "schema_version": "stage2_s2_40_attorney_worknotes_core.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "rows": reduced["worknotes"], + } + render_diagnostic = { + "schema_version": "stage2_s2_40_render_diagnostic.v1", + "render_errors": reduced["render_errors"], "render_absences": reduced["render_absences"], + "independent_rerender_equal": reduced["rerender_equal"], + } + review_policy_core = { + "schema_version": "stage2_s2_40_review_policy_core.v1", + "policy_registry_sha256": review_contract["policy_registry_sha256"], + "base_policy": review_contract["base_policy"], + "active_tags": review_contract["active_tags"], + "runtime_triggers": review_contract["runtime_triggers"], + "required_receipt_types": review_contract["required_receipt_types"], + "pre_receipt_ready_eligible": review_contract["pre_receipt_ready_eligible"], + } + review_basis = review_request_basis( + inputs, validation, review_contract, request["expected_parent_stage2_release_sha256"], + ) + dependency_snapshot = { + "parent_release_sha256": request["expected_parent_stage2_release_sha256"], + "upstream_barrier_sha256s": [ + request["expected_ingress_status_sha256"], request["expected_s2_10_publish_status_sha256"], + request["expected_plan_publish_status_sha256"], request["expected_s2_30_publish_status_sha256"], + ], + "ordered_source_digest": inputs["input_snapshot_digest"], + } + ordered_source_preimage = { + "schema_version": "stage2_s2_40_ordered_source_snapshot_preimage.v1", + "ordered_sha256s": inputs["input_snapshot_preimage"], + "snapshot_digest": inputs["input_snapshot_digest"], + } + generated_pre_manifest = ( + (ledger, "schemas/review_status.schema.json#/$defs/final_issue_ledger", "GENERATED_FINAL_ISSUE_SCHEMA"), + (assumptions, "schemas/review_status.schema.json#/$defs/assumption_ledger", "GENERATED_ASSUMPTION_SCHEMA"), + (usage_projection, "schemas/package.schema.json#/$defs/usage_projection", "GENERATED_USAGE_SCHEMA"), + (worknotes_core, "schemas/package.schema.json#/$defs/attorney_worknotes_core", "GENERATED_WORKNOTES_CORE_SCHEMA"), + (render_diagnostic, "schemas/package.schema.json#/$defs/render_diagnostic", "GENERATED_RENDER_DIAGNOSTIC_SCHEMA"), + (review_policy_core, "schemas/package.schema.json#/$defs/review_policy_core", "GENERATED_REVIEW_POLICY_CORE_SCHEMA"), + (dependency_snapshot, "schemas/package.schema.json#/$defs/dependency_snapshot", "GENERATED_DEPENDENCY_SCHEMA"), + (ordered_source_preimage, "schemas/package.schema.json#/$defs/ordered_source_snapshot_preimage", "GENERATED_ORDERED_SOURCE_SCHEMA"), + (review_basis, "schemas/package.schema.json#/$defs/review_request_basis", "GENERATED_REVIEW_BASIS_SCHEMA"), + (inputs["frozen_source_rows"], "schemas/package.schema.json#/$defs/frozen_source_rows", "GENERATED_FROZEN_SOURCE_SCHEMA"), + (legal_gates, "schemas/package.schema.json#/$defs/legal_gate_snapshot", "GENERATED_LEGAL_GATE_SCHEMA"), + ) + for value, schema_ref, code in generated_pre_manifest: + validate_schema_instance(value, schema_ref, schema_store, code=code) + pre_payloads: dict[str, tuple[bytes, str | None, str]] = { + "issue_ledger.final.json": (canonical_bytes(ledger), "schemas/review_status.schema.json#/$defs/final_issue_ledger", "application/json"), + "assumption_ledger.json": (canonical_bytes(assumptions), "schemas/review_status.schema.json#/$defs/assumption_ledger", "application/json"), + "llm_usage_projection.json": (canonical_bytes(usage_projection), "schemas/package.schema.json#/$defs/usage_projection", "application/json"), + "attorney_worknotes.core.json": (canonical_bytes(worknotes_core), "schemas/package.schema.json#/$defs/attorney_worknotes_core", "application/json"), + "render_diagnostic.json": (canonical_bytes(render_diagnostic), "schemas/package.schema.json#/$defs/render_diagnostic", "application/json"), + "review_policy_core.json": (canonical_bytes(review_policy_core), "schemas/package.schema.json#/$defs/review_policy_core", "application/json"), + "upstream_dependency_snapshot.json": (canonical_bytes(dependency_snapshot), "schemas/package.schema.json#/$defs/dependency_snapshot", "application/json"), + "ordered_source_snapshot_preimage.json": ( + canonical_bytes(ordered_source_preimage), + "schemas/package.schema.json#/$defs/ordered_source_snapshot_preimage", + "application/json", + ), + "review_request_basis.json": (canonical_bytes(review_basis), "schemas/package.schema.json#/$defs/review_request_basis", "application/json"), + "frozen_source_rows.json": (canonical_bytes(inputs["frozen_source_rows"]), "schemas/package.schema.json#/$defs/frozen_source_rows", "application/json"), + "legal_gate_snapshot.json": (canonical_bytes(legal_gates), "schemas/package.schema.json#/$defs/legal_gate_snapshot", "application/json"), + } + for name, payload in documents.items(): + pre_payloads[name] = (payload, None, "text/markdown; charset=utf-8") + artifact_rows = [ + { + "path": name, "raw_sha256": digest(payload), "content_type": content_type, + "size_bytes": len(payload), "schema_ref": schema_ref, "producer_id": "S2_40", + } + for name, (payload, schema_ref, content_type) in sorted(pre_payloads.items()) + ] + manifest_core = { + "schema_version": "stage2_s2_40_candidate_manifest_core.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], "candidate_attempt_id": request["candidate_attempt_id"], + "dependency_snapshot": dependency_snapshot, "artifacts": artifact_rows, + } + validate_schema_instance( + manifest_core, "schemas/package.schema.json#/$defs/candidate_manifest_core", + schema_store, code="GENERATED_CANDIDATE_MANIFEST_SCHEMA", + ) + manifest_hash = digest(manifest_core) + statuses = aggregate_validation(validation) + validation_core = { + "schema_version": "stage2_s2_40_validation_core.v1", + "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "candidate_manifest_core_sha256": manifest_hash, + "invariant_results": list(validation), + "run_technical_status": statuses["run_technical_status"], + "artifact_technical_status": statuses["artifact_technical_status"], + } + validate_schema_instance( + validation_core, "schemas/package.schema.json#/$defs/validation_core", + schema_store, code="GENERATED_VALIDATION_CORE_SCHEMA", + ) + validation_hash = digest(validation_core) + document_sha256s = { + "claim_relief": digest(documents.get("claim_relief.md", b"")), + "claim_cause": digest(documents.get("claim_cause.md", b"")), + "pleading_draft": digest(documents.get("pleading_draft.md", b"")), + } + digest_core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + "run_binding_digest": request["run_binding_digest"], + "dependency_snapshot_sha256": digest(dependency_snapshot), + "candidate_manifest_core_sha256": manifest_hash, + "document_sha256s": document_sha256s, + "attorney_worknotes_core_sha256": digest(worknotes_core), + "final_issue_ledger_sha256": digest(ledger), + "assumption_ledger_sha256": digest(assumptions), + "validation_core_sha256": validation_hash, + "ordered_source_dependency_snapshot_digest": inputs["input_snapshot_digest"], + } + candidate_digest = digest(digest_core) + digest_envelope = { + **digest_core, + "candidate_content_digest": candidate_digest, + } + validate_schema_instance( + digest_envelope, "schemas/package.schema.json#/$defs/candidate_digest_envelope", + schema_store, code="GENERATED_CANDIDATE_DIGEST_SCHEMA", + ) + worknotes = { + "schema_version": "stage2_s2_40_attorney_worknotes.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], "candidate_content_digest": candidate_digest, + "rows": reduced["worknotes"], + } + validate_schema_instance( + worknotes, "schemas/package.schema.json#/$defs/attorney_worknotes", + schema_store, code="GENERATED_ATTORNEY_WORKNOTES_SCHEMA", + ) + packet_core = { + "schema_version": "stage2_s2_40_lawyer_review_packet_core.v1", + "candidate_content_digest": candidate_digest, + "finding_ids": sorted(row["finding_ids"][0] for row in validation if row["finding_ids"]), + "scope_ids": inputs["group_ids"], + "document_refs": sorted(documents) or ["issue_ledger.final.json"], + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + validation_envelope_core = { + "schema_version": "stage2_s2_40_validation_envelope_core.v1", + "candidate_content_digest": candidate_digest, + "validation_core_sha256": validation_hash, + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + subject = review_subject( + candidate_digest, digest(packet_core), digest(validation_envelope_core), review_basis, + ) + validate_schema_instance( + packet_core, "schemas/package.schema.json#/$defs/lawyer_review_packet_core", + schema_store, code="GENERATED_REVIEW_PACKET_CORE_SCHEMA", + ) + validate_schema_instance( + validation_envelope_core, "schemas/package.schema.json#/$defs/validation_envelope_core", + schema_store, code="GENERATED_VALIDATION_ENVELOPE_CORE_SCHEMA", + ) + validate_schema_instance( + subject["subject"], "schemas/package.schema.json#/$defs/review_subject", + schema_store, code="GENERATED_REVIEW_SUBJECT_SCHEMA", + ) + packet = { + "schema_version": "stage2_s2_40_lawyer_review_packet.v1", + "lawyer_review_packet_core": packet_core, + "lawyer_review_packet_core_sha256": digest(packet_core), + "review_subject_digest": subject["review_subject_digest"], + } + validation_envelope = { + "schema_version": "stage2_s2_40_validation_envelope.v1", + "validation_envelope_core": validation_envelope_core, + "validation_envelope_core_sha256": digest(validation_envelope_core), + "review_subject_digest": subject["review_subject_digest"], + } + review_policy_result = { + "schema_version": "stage2_s2_40_review_policy_result.v1", + "candidate_content_digest": candidate_digest, + "policy_registry_sha256": review_contract["policy_registry_sha256"], + "base_policy": review_contract["base_policy"], + "active_tags": review_contract["active_tags"], + "runtime_triggers": review_contract["runtime_triggers"], + "required_receipt_types": review_contract["required_receipt_types"], + "ready_eligible": review_contract["pre_receipt_ready_eligible"], + } + for value, schema_ref, code in ( + (packet, "schemas/package.schema.json#/$defs/lawyer_review_packet", "GENERATED_REVIEW_PACKET_SCHEMA"), + (validation_envelope, "schemas/package.schema.json#/$defs/validation_envelope", "GENERATED_VALIDATION_ENVELOPE_SCHEMA"), + (review_policy_result, "schemas/review_status.schema.json#/$defs/review_policy_result", "GENERATED_REVIEW_POLICY_RESULT_SCHEMA"), + ): + validate_schema_instance(value, schema_ref, schema_store, code=code) + return { + "documents": documents, "pre_payloads": pre_payloads, "ledger": ledger, + "assumptions": assumptions, "usage_projection": usage_projection, "worknotes": worknotes, + "validation_core": validation_core, "manifest_core": manifest_core, + "validation_envelope": validation_envelope, + "candidate_digest_envelope": digest_envelope, "candidate_digest": candidate_digest, + "review": subject, "packet": packet, "legal_gates": legal_gates, + "review_policy_result": review_policy_result, "review_policy_path": review_contract["policy_path"], + "schema_store": schema_store, + } + + +def publish_candidate(client: McpClient, request: Mapping[str, Any], material: Mapping[str, Any]) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + candidate_digest = material["candidate_digest"] + candidate_root = join_path(root, "candidates/by-content-digest", candidate_digest) + outputs: list[tuple[str, bytes]] = [ + ("candidate_package_manifest.json", canonical_bytes(material["manifest_core"])), + ("candidate_content_digest.json", canonical_bytes(material["candidate_digest_envelope"])), + ("attorney_worknotes.json", canonical_bytes(material["worknotes"])), + ("validation_core.json", canonical_bytes(material["validation_core"])), + ("validation_envelope.json", canonical_bytes(material["validation_envelope"])), + ("review_subject.json", canonical_bytes(material["review"]["subject"])), + ("lawyer_review_packet.json", canonical_bytes(material["packet"])), + ] + outputs.extend((name, payload[0]) for name, payload in sorted(material["pre_payloads"].items())) + outputs.extend(sorted(material["documents"].items())) + deduplicated: dict[str, bytes] = {} + for name, payload in outputs: + if name in deduplicated and deduplicated[name] != payload: + raise S240Error("CANDIDATE_ARTIFACT_CONFLICT", f"candidate path conflicts: {name}") + deduplicated[name] = payload + rows: list[dict[str, Any]] = [] + for rel, payload in sorted(deduplicated.items()): + path = join_path(candidate_root, rel) + observed = client.write_immutable(path, payload) + rows.append({"path": path, "raw_sha256": observed, "size_bytes": len(payload), "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8"}) + review = material["review"] + review_publications: list[dict[str, Any]] = [] + for request_row in review["requests"]: + request_envelope = { + "schema_version": "stage2_s2_40_review_request.v1", + "request_id": request_row["request_id"], + "review_request_core": request_row["core"], + "review_request_core_sha256": request_row["core_sha256"], + "review_subject_digest": request_row["review_subject_digest"], + } + validate_schema_instance( + request_envelope, "schemas/review_status.schema.json#/$defs/review_request", + material["schema_store"], code="GENERATED_REVIEW_REQUEST_SCHEMA", + ) + review_path = join_path(root, "review/review_requests", f"{request_row['request_id']}.json") + review_hash = client.write_immutable(review_path, canonical_bytes(request_envelope)) + review_publications.append({ + "receipt_type": request_row["receipt_type"], "path": review_path, + "sha256": review_hash, "request": request_envelope, + }) + return { + "candidate_root": candidate_root, "artifact_rows": rows, + "review_requests": review_publications, + } + + +def validate_review_receipts(client: McpClient, request: Mapping[str, Any], material: Mapping[str, Any]) -> tuple[bool, bool, list[dict[str, Any]]]: + refs = request["review_receipt_refs"] + required_types = set(material["review_policy_result"].get("required_receipt_types", [])) + expected_requests = { + str(row["receipt_type"]): row + for row in require_list(material["review"].get("requests"), code="REVIEW_EXPECTED_REQUESTS") + } + if set(expected_requests) != required_types or len(expected_requests) != len(material["review"]["requests"]): + raise S240Error("REVIEW_REQUEST_SET", "review request map differs from required receipt types") + if not refs: + return not required_types, False, [] + rows: list[dict[str, Any]] = [] + content_change = False + approved_types: set[str] = set() + seen_types: set[str] = set() + schema_store = require_object(material.get("schema_store"), code="REVIEW_SCHEMA_STORE") + for ref in refs: + raw: bytes | None = None + value: dict[str, Any] = {} + reasons: list[str] = [] + try: + raw = client.read_binary(ref) + value = require_object(load_json(raw, label=ref), code="REVIEW_RECEIPT_OBJECT") + if client.read_binary(ref) != raw: + reasons.append("REVIEW_RECEIPT_TOCTOU") + if canonical_bytes(value) != raw: + reasons.append("REVIEW_RECEIPT_NON_CANONICAL") + try: + validate_schema_instance( + value, "schemas/review_status.schema.json#/$defs/review_receipt", + schema_store, code="REVIEW_RECEIPT_SCHEMA", + ) + except S240Error as exc: + reasons.append(exc.code) + receipt_type = value.get("receipt_type") + expected_request = expected_requests.get(str(receipt_type)) + if expected_request is None: + reasons.append("REVIEW_RECEIPT_TYPE_NOT_REQUIRED") + if receipt_type in seen_types: + reasons.append("REVIEW_RECEIPT_TYPE_DUPLICATE") + seen_types.add(str(receipt_type)) + expected_core = expected_request.get("core", {}) if expected_request is not None else {} + if expected_request is None or ( + value.get("request_id") != expected_request.get("request_id") + or value.get("candidate_content_digest") != material["candidate_digest"] + or value.get("review_subject_digest") != material["review"]["review_subject_digest"] + or value.get("finding_ids") != expected_core.get("finding_ids") + or value.get("scope_ids") != expected_core.get("scope_ids") + or value.get("reviewer_role") != expected_core.get("reviewer_role") + or value.get("reviewer_qualification") != expected_core.get("reviewer_qualification") + ): + reasons.append("REVIEW_RECEIPT_SUBJECT") + if ( + value.get("reviewer_role") != TRUSTED_REVIEW_ROLE + or value.get("reviewer_qualification") != TRUSTED_REVIEW_QUALIFICATION + or value.get("issuer_id") != TRUSTED_REVIEW_ISSUER + or value.get("key_id") not in TRUSTED_REVIEW_KEY_IDS + or value.get("signature_algorithm") != TRUSTED_REVIEW_SIGNATURE_ALGORITHM + ): + reasons.append("REVIEW_RECEIPT_ISSUER") + if value.get("cryptographic_verification_status") != "VERIFIED_BY_EXTERNAL_ADAPTER" or value.get("revocation_status") != "NOT_REVOKED": + reasons.append("REVIEW_RECEIPT_TRUST") + if HEX64.fullmatch(str(value.get("external_verification_attestation_sha256", ""))) is None: + reasons.append("REVIEW_RECEIPT_EXTERNAL_ATTESTATION") + try: + issued = datetime.fromisoformat(str(value.get("issued_at")).replace("Z", "+00:00")) + expires = datetime.fromisoformat(str(value.get("expires_at")).replace("Z", "+00:00")) + now = datetime.now(timezone.utc) + if issued.tzinfo is None or expires.tzinfo is None or issued > now or expires <= now or expires <= issued: + reasons.append("REVIEW_RECEIPT_TIME") + except (TypeError, ValueError): + reasons.append("REVIEW_RECEIPT_TIME") + disposition = value.get("review_disposition") + change_scope = value.get("change_scope") + expected_signed_material = digest([ + "STAGE2_S2_40_REVIEW_RECEIPT_V1", value.get("request_id"), + value.get("candidate_content_digest"), value.get("review_subject_digest"), + value.get("receipt_type"), value.get("finding_ids"), value.get("scope_ids"), + value.get("reviewer_role"), value.get("reviewer_qualification"), + value.get("issuer_id"), value.get("key_id"), value.get("signature_algorithm"), + value.get("external_verification_attestation_sha256"), + value.get("issued_at"), value.get("expires_at"), + value.get("revocation_status"), value.get("cryptographic_verification_status"), + disposition, change_scope, value.get("reason_codes"), + ]) + if value.get("signed_material_digest") != expected_signed_material: + reasons.append("REVIEW_RECEIPT_SIGNED_SCOPE") + if disposition == "CONTENT_CHANGE_REQUIRED": + if change_scope not in {"STAGE1_CONTEXT", "LEGAL_JUDGMENT", "PLAN_RULE_CALCULATION_BINDING", "DRAFTING_TEXT_ATOM"}: + reasons.append("REVIEW_CHANGE_SCOPE") + elif disposition != "APPROVE_AS_IS" or change_scope != "NONE": + reasons.append("REVIEW_RECEIPT_DISPOSITION") + except (S240Error, TypeError, ValueError) as exc: + reasons.append(exc.code if isinstance(exc, S240Error) else "REVIEW_RECEIPT_PARSE") + if not reasons and value.get("review_disposition") == "CONTENT_CHANGE_REQUIRED": + content_change = True + if not reasons and value.get("review_disposition") == "APPROVE_AS_IS": + approved_types.add(str(value.get("receipt_type"))) + row = { + "path": ref, "receipt_id": value.get("receipt_id"), + "receipt_type": value.get("receipt_type"), + "disposition": value.get("review_disposition"), + "change_scope": value.get("change_scope"), + "validation_status": "VALID" if not reasons else "INVALID", + "reason_codes": sorted(set(reasons)), + } + if raw is not None: + row["sha256"] = digest(raw) + rows.append(row) + approved = not content_change and approved_types == required_types and len(rows) == len(required_types) and all( + row.get("validation_status") == "VALID" for row in rows + ) + return approved, content_change, rows + + +def final_status( + client: McpClient, + request: Mapping[str, Any], + preflight_digest: str, + inputs: Mapping[str, Any], + material: Mapping[str, Any], + publication: Mapping[str, Any], + approved: bool, + content_change: bool, + review_rows: Sequence[Mapping[str, Any]], +) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + candidate_digest = material["candidate_digest"] + validation_rows = material["validation_core"]["invariant_results"] + all_pass = len(validation_rows) == 18 and all( + row["evaluation_status"] == "PASS" for row in validation_rows + ) + effective_gates = dict(material["legal_gates"]) + effective_gates["required_receipts"] = approved + full_production_gates = ( + request["compile_mode"] == "PRODUCTION" + and all_pass + and bool(material["documents"]) + and effective_gates == {key: True for key in REQUIRED_LEGAL_GATES} + and material["review_policy_result"]["ready_eligible"] + ) + receipt_hashes = sorted({ + str(row["sha256"]) for row in review_rows + if row.get("validation_status") == "VALID" + and HEX64.fullmatch(str(row.get("sha256", ""))) + }) + validation_hash = digest(material["validation_core"]) + review_subject_digest = material["review"]["review_subject_digest"] + if content_change: + scope_order = { + "STAGE1_CONTEXT": (0, "RESTART_FROM_S2_00"), + "LEGAL_JUDGMENT": (1, "RESTART_FROM_S2_10"), + "PLAN_RULE_CALCULATION_BINDING": (2, "RESTART_FROM_S2_20"), + "DRAFTING_TEXT_ATOM": (3, "RESTART_FROM_S2_30"), + } + scopes = [ + row["change_scope"] for row in review_rows + if row.get("validation_status") == "VALID" + and row.get("disposition") == "CONTENT_CHANGE_REQUIRED" + and row.get("change_scope") in scope_order + ] + if not scopes: + raise S240Error("REVIEW_CHANGE_SCOPE_MISSING", "content-change receipt lacks earliest-owner scope") + phase, route = "SUPERSEDED", scope_order[min(scopes, key=lambda value: scope_order[value][0])][1] + elif not full_production_gates: + phase, route = "AWAITING_EXTERNAL_REVIEW", "WAIT_EXTERNAL_REVIEW" + else: + phase, route = "READY_TO_COMMIT", "CONTINUE_TO_COMMIT" + artifact_set_digest: str | None = None + stage2_package_sha256: str | None = None + commit_intent_sha256: str | None = None + commit_result_sha256: str | None = None + if phase == "READY_TO_COMMIT": + final_payloads: dict[str, bytes] = { + "candidate_package_manifest.json": canonical_bytes(material["manifest_core"]), + "candidate_content_digest.json": canonical_bytes(material["candidate_digest_envelope"]), + "attorney_worknotes.json": canonical_bytes(material["worknotes"]), + "lawyer_review_packet.json": canonical_bytes(material["packet"]), + "stage2_final_validation_report.json": canonical_bytes(material["validation_core"]), + "review_policy_result.json": canonical_bytes(material["review_policy_result"]), + } + for rel, value in sorted(material["pre_payloads"].items()): + if rel in final_payloads and final_payloads[rel] != value[0]: + raise S240Error("FINAL_ARTIFACT_CONFLICT", f"final artifact path conflicts: {rel}") + final_payloads[rel] = value[0] + final_payloads.update(material["documents"]) + package_artifacts = [ + { + "path": join_path(root, "final", rel), "raw_sha256": digest(payload), + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, "producer_id": "S2_40", + } + for rel, payload in sorted(final_payloads.items()) + ] + package = { + "schema_version": "stage2_s2_40_package.v1", + "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "compile_mode": request["compile_mode"], + "candidate_manifest_core_sha256": digest(material["manifest_core"]), + "artifacts": package_artifacts, + "validation_report_sha256": validation_hash, + "review_policy_result_sha256": digest(material["review_policy_result"]), + "review_receipt_sha256s": receipt_hashes, + "filing_decision_receipt_sha256": None, + "run_technical_status": "CONSISTENT", + "artifact_technical_status": "CONSISTENT", + "legal_readiness": "READY_FOR_LAWYER_FILING_DECISION", + "filing_permission": "NOT_GRANTED", + } + validate_schema_instance( + package, "schemas/package.schema.json#/$defs/stage2_package", + material["schema_store"], code="GENERATED_STAGE2_PACKAGE_SCHEMA", + ) + package_payload = canonical_bytes(package) + stage2_package_sha256 = digest(package_payload) + final_payloads["stage2_package.json"] = package_payload + expected_rows = [ + { + "path": join_path(root, "final", rel), "raw_sha256": digest(payload), + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, + } + for rel, payload in sorted(final_payloads.items()) + ] + intent_core = { + "schema_version": "stage2_s2_40_commit_intent.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "candidate_attempt_id": request["candidate_attempt_id"], + "candidate_manifest_core_sha256": digest(material["manifest_core"]), + "validation_report_sha256": validation_hash, + "review_subject_digest": review_subject_digest, + "review_receipt_sha256s": receipt_hashes, + "stage2_package_sha256": stage2_package_sha256, + "expected_artifacts": expected_rows, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "request_sha256": request["_request_sha256"], + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + } + intent = {**intent_core, "intent_digest": digest(intent_core)} + validate_schema_instance( + intent, "schemas/deployment.schema.json#/$defs/s2_40_commit_intent", + material["schema_store"], code="GENERATED_COMMIT_INTENT_SCHEMA", + ) + intent_path = join_path(root, "commit/commit_intent.json") + commit_intent_sha256 = client.write_immutable(intent_path, canonical_bytes(intent)) + final_rows: list[dict[str, Any]] = [] + for rel, payload in sorted(final_payloads.items()): + path = join_path(root, "final", rel) + observed = client.write_immutable(path, payload) + final_rows.append({ + "path": path, "raw_sha256": observed, + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, + }) + if final_rows != expected_rows: + raise S240Error("COMMIT_EXPECTED_ROWS", "written final rows differ from commit intent") + artifact_set_digest = digest(final_rows) + result_core = { + "schema_version": "stage2_s2_40_commit_result.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "commit_intent_sha256": commit_intent_sha256, + "artifact_set_digest": artifact_set_digest, + "artifact_rows": final_rows, + "readback_status": "PASS", "conflicting_target_count": 0, + "missing_target_count_after_write": 0, + } + result = {**result_core, "commit_result_digest": digest(result_core)} + validate_schema_instance( + result, "schemas/deployment.schema.json#/$defs/s2_40_commit_result", + material["schema_store"], code="GENERATED_COMMIT_RESULT_SCHEMA", + ) + commit_result_sha256 = client.write_immutable( + join_path(root, "commit/stage2_commit_result.json"), canonical_bytes(result), + ) + phase, route = "COMMITTED", "PACKAGE_COMMITTED" + aggregate = aggregate_validation(validation_rows) + if aggregate["run_technical_status"] == "TECHNICAL_INCOMPLETE": + artifact_status, legal_readiness = "NOT_PRODUCED", "NOT_ASSESSED" + else: + artifact_status = aggregate["artifact_technical_status"] + legal_readiness = "READY_FOR_LAWYER_FILING_DECISION" if full_production_gates else "LAWYER_REVIEW_REQUIRED" + return write_terminal_status( + client, request, workflow_phase=phase, route=route, + candidate_content_digest=candidate_digest, + run_technical_status=aggregate["run_technical_status"], + artifact_technical_status=artifact_status, legal_readiness=legal_readiness, + validation_report_sha256=validation_hash, + review_subject_digest=review_subject_digest, + review_receipt_sha256s=receipt_hashes, + stage2_package_sha256=stage2_package_sha256, + artifact_set_digest=artifact_set_digest, + commit_intent_sha256=commit_intent_sha256, + commit_result_sha256=commit_result_sha256, + schema_store=material["schema_store"], + ) + + +def verify_frozen_candidate_digest_chain( + expected: str, + manifest: Mapping[str, Any], + envelope: Mapping[str, Any], + pre_payloads: Mapping[str, tuple[bytes, str | None, str]], + documents: Mapping[str, bytes], + validation_core: Mapping[str, Any], +) -> dict[str, Any]: + """Recompute every pre-review candidate digest edge from frozen bytes.""" + def payload_json(name: str) -> Any: + if name not in pre_payloads: + raise S240Error("RESUME_REQUIRED_ARTIFACT", f"required frozen artifact missing: {name}") + raw = pre_payloads[name][0] + value = load_json(raw, label=name) + if canonical_bytes(value) != raw: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {name}") + return value + + dependency = require_object(manifest.get("dependency_snapshot"), code="RESUME_DEPENDENCY_SNAPSHOT") + persisted_dependency = require_object( + payload_json("upstream_dependency_snapshot.json"), code="RESUME_PERSISTED_DEPENDENCY", + ) + if persisted_dependency != dependency: + raise S240Error("RESUME_DEPENDENCY_SNAPSHOT_DRIFT", "embedded and persisted dependency snapshots differ") + ordered_preimage = require_object( + payload_json("ordered_source_snapshot_preimage.json"), code="RESUME_ORDERED_SOURCE_PREIMAGE", + ) + ordered_hashes = require_list(ordered_preimage.get("ordered_sha256s"), code="RESUME_ORDERED_SOURCE_HASHES") + for value in ordered_hashes: + require_hex(value, code="RESUME_ORDERED_SOURCE_HASH") + ordered_digest = digest(ordered_hashes) + if ( + ordered_preimage.get("snapshot_digest") != ordered_digest + or dependency.get("ordered_source_digest") != ordered_digest + ): + raise S240Error("RESUME_ORDERED_SOURCE_DIGEST", "ordered source preimage digest differs") + worknotes_core = require_object( + payload_json("attorney_worknotes.core.json"), code="RESUME_WORKNOTES_CORE", + ) + ledger = require_object(payload_json("issue_ledger.final.json"), code="RESUME_FINAL_ISSUE_LEDGER") + assumptions = require_object(payload_json("assumption_ledger.json"), code="RESUME_ASSUMPTION_LEDGER") + document_sha256s = { + "claim_relief": digest(documents.get("claim_relief.md", b"")), + "claim_cause": digest(documents.get("claim_cause.md", b"")), + "pleading_draft": digest(documents.get("pleading_draft.md", b"")), + } + digest_core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + "run_binding_digest": manifest.get("run_binding_digest"), + "dependency_snapshot_sha256": digest(dependency), + "candidate_manifest_core_sha256": digest(manifest), + "document_sha256s": document_sha256s, + "attorney_worknotes_core_sha256": digest(worknotes_core), + "final_issue_ledger_sha256": digest(ledger), + "assumption_ledger_sha256": digest(assumptions), + "validation_core_sha256": digest(validation_core), + "ordered_source_dependency_snapshot_digest": ordered_digest, + } + recomputed = digest(digest_core) + if recomputed != expected or envelope != {**digest_core, "candidate_content_digest": recomputed}: + raise S240Error("RESUME_CANDIDATE_DIGEST_CHAIN", "frozen candidate digest chain does not recompute exactly") + return { + "dependency": dependency, "ordered_source_preimage": ordered_preimage, + "worknotes_core": worknotes_core, "ledger": ledger, "assumptions": assumptions, + } + + +def hydrate_frozen_candidate(client: McpClient, request: Mapping[str, Any]) -> dict[str, Any]: + """RESUME validates and re-derives the frozen candidate without upstream rerendering.""" + root = request["stage2_run_root_ref"] + expected = require_hex(request["expected_candidate_content_digest"], code="RESUME_CANDIDATE_HASH") + schema_store = load_output_schema_store(client) + + def canonical_bound_json(path: str, expected_sha256: str | None = None) -> tuple[dict[str, Any], bytes]: + value, raw = read_bound_json(client, path, expected_sha256) + if canonical_bytes(value) != raw: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {path}") + return value, raw + + previous, _ = canonical_bound_json( + join_path(root, "control/run_status.json"), request["expected_previous_run_status_sha256"], + ) + validate_schema_instance( + previous, "schemas/review_status.schema.json#/$defs/run_status", + schema_store, code="RESUME_PREVIOUS_STATUS_SCHEMA", + ) + if ( + previous.get("candidate_content_digest") != expected + or previous.get("workflow_phase") != "AWAITING_EXTERNAL_REVIEW" + or previous.get("compile_mode") != request["compile_mode"] + or previous.get("run_binding_digest") != request["run_binding_digest"] + or previous.get("candidate_attempt_id") != request["candidate_attempt_id"] + ): + raise S240Error("RESUME_CHECKPOINT", "previous status does not bind the frozen candidate") + candidate_root = join_path(root, "candidates/by-content-digest", expected) + if PurePosixPath(candidate_root).name != expected: + raise S240Error("RESUME_CANDIDATE_DIRECTORY", "candidate directory basename differs from expected digest") + manifest, _ = canonical_bound_json(join_path(candidate_root, "candidate_package_manifest.json")) + envelope, _ = canonical_bound_json(join_path(candidate_root, "candidate_content_digest.json")) + validate_schema_instance( + manifest, "schemas/package.schema.json#/$defs/candidate_manifest_core", + schema_store, code="RESUME_CANDIDATE_MANIFEST_SCHEMA", + ) + validate_schema_instance( + envelope, "schemas/package.schema.json#/$defs/candidate_digest_envelope", + schema_store, code="RESUME_CANDIDATE_ENVELOPE_SCHEMA", + ) + expected_upstream = [ + request["expected_ingress_status_sha256"], request["expected_s2_10_publish_status_sha256"], + request["expected_plan_publish_status_sha256"], request["expected_s2_30_publish_status_sha256"], + ] + dependency = require_object(manifest.get("dependency_snapshot"), code="RESUME_DEPENDENCY_SNAPSHOT") + if ( + manifest.get("producer_id") != "S2_40" + or manifest.get("run_binding_digest") != request["run_binding_digest"] + or manifest.get("compile_mode") != request["compile_mode"] + or manifest.get("candidate_attempt_id") != request["candidate_attempt_id"] + or dependency.get("parent_release_sha256") != request["expected_parent_stage2_release_sha256"] + or dependency.get("upstream_barrier_sha256s") != expected_upstream + ): + raise S240Error("RESUME_DEPENDENCY_DRIFT", "RESUME request differs from the frozen dependency snapshot") + pre_payloads: dict[str, tuple[bytes, str | None, str]] = {} + documents: dict[str, bytes] = {} + artifact_rows = require_list(manifest.get("artifacts"), code="RESUME_ARTIFACT_ROWS") + artifact_paths = [safe_path(row.get("path"), code="RESUME_ARTIFACT_PATH") for row in artifact_rows if isinstance(row, dict)] + if len(artifact_paths) != len(artifact_rows) or artifact_paths != sorted(artifact_paths) or len(set(artifact_paths)) != len(artifact_paths): + raise S240Error("RESUME_ARTIFACT_SET", "candidate artifact paths must be unique and sorted") + for row in artifact_rows: + row = require_object(row, code="RESUME_ARTIFACT_ROW") + rel = safe_path(row.get("path"), code="RESUME_ARTIFACT_PATH") + raw_a = client.read_binary(join_path(candidate_root, rel)) + raw_b = client.read_binary(join_path(candidate_root, rel)) + if raw_a != raw_b: + raise S240Error("RESUME_ARTIFACT_TOCTOU", f"frozen candidate artifact changed: {rel}") + if digest(raw_a) != require_hex(row.get("raw_sha256"), code="RESUME_ARTIFACT_HASH") or len(raw_a) != row.get("size_bytes"): + raise S240Error("RESUME_ARTIFACT_DRIFT", f"frozen candidate artifact differs: {rel}") + content_type = str(row.get("content_type")) + schema_ref = row.get("schema_ref") + if content_type.startswith("text/markdown"): + if schema_ref is not None: + raise S240Error("RESUME_MARKDOWN_SCHEMA_REF", f"markdown must not declare JSON schema: {rel}") + documents[rel] = raw_a + else: + if not isinstance(schema_ref, str): + raise S240Error("RESUME_JSON_SCHEMA_REF", f"JSON artifact lacks schema binding: {rel}") + value = load_json(raw_a, label=rel) + if canonical_bytes(value) != raw_a: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {rel}") + validate_schema_instance(value, schema_ref, schema_store, code="RESUME_ARTIFACT_SCHEMA") + pre_payloads[rel] = (raw_a, schema_ref, content_type) + + def auxiliary_json(name: str, schema_ref: str) -> dict[str, Any]: + value, _ = canonical_bound_json(join_path(candidate_root, name)) + validate_schema_instance(value, schema_ref, schema_store, code="RESUME_AUXILIARY_SCHEMA") + return value + + validation_core = auxiliary_json("validation_core.json", "schemas/package.schema.json#/$defs/validation_core") + packet = auxiliary_json("lawyer_review_packet.json", "schemas/package.schema.json#/$defs/lawyer_review_packet") + worknotes = auxiliary_json("attorney_worknotes.json", "schemas/package.schema.json#/$defs/attorney_worknotes") + validation_envelope = auxiliary_json("validation_envelope.json", "schemas/package.schema.json#/$defs/validation_envelope") + stored_subject = auxiliary_json("review_subject.json", "schemas/package.schema.json#/$defs/review_subject") + chain = verify_frozen_candidate_digest_chain( + expected, manifest, envelope, pre_payloads, documents, validation_core, + ) + if ( + worknotes.get("candidate_content_digest") != expected + or worknotes.get("rows") != chain["worknotes_core"].get("rows") + or packet.get("lawyer_review_packet_core_sha256") != digest(packet.get("lawyer_review_packet_core")) + or validation_envelope.get("validation_envelope_core_sha256") != digest(validation_envelope.get("validation_envelope_core")) + or validation_envelope.get("validation_envelope_core", {}).get("validation_core_sha256") != digest(validation_core) + ): + raise S240Error("RESUME_AUXILIARY_DIGEST_CHAIN", "frozen auxiliary candidate objects do not recompute") + review_basis = require_object( + load_json(pre_payloads["review_request_basis.json"][0], label="review_request_basis"), + code="RESUME_REVIEW_BASIS", + ) + rebuilt_review = review_subject( + expected, packet["lawyer_review_packet_core_sha256"], + validation_envelope["validation_envelope_core_sha256"], review_basis, + ) + if ( + rebuilt_review["subject"] != stored_subject + or packet.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + or validation_envelope.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + or previous.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + ): + raise S240Error("RESUME_REVIEW_SUBJECT", "frozen review subject does not re-derive exactly") + for request_row in rebuilt_review["requests"]: + request_path = join_path(root, "review/review_requests", f"{request_row['request_id']}.json") + review_request, _ = canonical_bound_json(request_path) + validate_schema_instance( + review_request, "schemas/review_status.schema.json#/$defs/review_request", + schema_store, code="RESUME_REVIEW_REQUEST_SCHEMA", + ) + expected_request = { + "schema_version": "stage2_s2_40_review_request.v1", + "request_id": request_row["request_id"], + "review_request_core": request_row["core"], + "review_request_core_sha256": request_row["core_sha256"], + "review_subject_digest": request_row["review_subject_digest"], + } + if review_request != expected_request: + raise S240Error("RESUME_REVIEW_REQUEST_DRIFT", f"frozen review request differs: {request_row['receipt_type']}") + review_policy_core = require_object( + load_json(pre_payloads["review_policy_core.json"][0], label="review_policy_core"), + code="RESUME_REVIEW_POLICY_CORE", + ) + policy_result = { + "schema_version": "stage2_s2_40_review_policy_result.v1", + "candidate_content_digest": expected, + "policy_registry_sha256": review_policy_core.get("policy_registry_sha256"), + "base_policy": review_policy_core.get("base_policy"), + "active_tags": review_policy_core.get("active_tags"), + "runtime_triggers": review_policy_core.get("runtime_triggers"), + "required_receipt_types": review_policy_core.get("required_receipt_types"), + "ready_eligible": review_policy_core.get("pre_receipt_ready_eligible") is True, + } + validate_schema_instance( + policy_result, "schemas/review_status.schema.json#/$defs/review_policy_result", + schema_store, code="RESUME_REVIEW_POLICY_RESULT_SCHEMA", + ) + frozen_sources = require_list( + load_json(pre_payloads["frozen_source_rows.json"][0], label="frozen_source_rows"), + code="RESUME_FROZEN_SOURCE_ROWS", + ) + manifest_rows = [ + row for row in frozen_sources if isinstance(row, dict) + and row.get("path") == "map_s2_30/artifact_manifest.json" + and row.get("ref_family") == "upstream_manifest" + ] + if len(manifest_rows) != 1 or manifest_rows[0].get("sha256") != request["expected_s2_30_artifact_manifest_sha256"]: + raise S240Error("RESUME_MANIFEST_DRIFT", "RESUME request differs from frozen S2_30 artifact manifest") + legal_gates = require_object( + load_json(pre_payloads["legal_gate_snapshot.json"][0], label="legal_gate_snapshot"), + code="RESUME_LEGAL_GATES", + ) + return { + "documents": documents, "pre_payloads": pre_payloads, + "manifest_core": manifest, "candidate_digest_envelope": envelope, + "candidate_digest": expected, "validation_core": validation_core, + "packet": packet, "worknotes": worknotes, "legal_gates": legal_gates, + "review_policy_result": policy_result, "review": rebuilt_review, + "schema_store": schema_store, + } + + +def normal_route(client: McpClient, request: Mapping[str, Any], preflight_digest: str) -> dict[str, Any]: + if request["requested_transition"] == "RESUME": + inputs: dict[str, Any] = {} + material = hydrate_frozen_candidate(client, request) + publication: dict[str, Any] = {"resume_reused_frozen_candidate": True} + else: + inputs = hydrate_normal(client, request) + reduced = reduce_and_render(inputs, request) + validation = invariant_results(inputs, reduced, request) + material = candidate_material(inputs, reduced, validation, request) + publication = publish_candidate(client, request, material) + approved, content_change, review_rows = validate_review_receipts(client, request, material) + return final_status(client, request, preflight_digest, inputs, material, publication, approved, content_change, review_rows) + + +def publish_post_preflight_failure( + client: McpClient, request: Mapping[str, Any], preflight_digest: str, error: Mapping[str, Any], +) -> dict[str, Any]: + """Preserve a closed diagnostic, then publish the failure barrier last.""" + root = request["stage2_run_root_ref"] + diagnostic = { + "schema_version": "stage2_s2_40_technical_diagnostic.v1", + "writer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "reason_codes": [str(error.get("code", "INLINE_RUNTIME_ERROR"))], + "error": dict(error), "preflight_snapshot_digest": preflight_digest, + } + diagnostic_id = digest(diagnostic) + client.write_immutable( + join_path(root, "diagnostic", f"failure-{diagnostic_id}.json"), + canonical_bytes(diagnostic), + ) + return write_terminal_status( + client, request, workflow_phase="DIAGNOSTIC_ONLY", + route="STOP_TECHNICAL_INCOMPLETE", candidate_content_digest=None, + run_technical_status="TECHNICAL_INCOMPLETE", + artifact_technical_status="NOT_PRODUCED", legal_readiness="NOT_ASSESSED", + ) + + +def run() -> int: + localdocs: McpClient | None = None + request: dict[str, Any] | None = None + receipt: dict[str, Any] + exit_code = 0 + preflight_digest: str | None = None + output_schema_store: dict[str, Mapping[str, Any]] | None = None + try: + with contextlib.redirect_stdout(io.StringIO()): + if HEX64.fullmatch(INLINE_USER_HASH) is None or HEX64.fullmatch(INLINE_WORKSPACE_HASH) is None: + raise S240Error("INLINE_CONTEXT_UNBOUND", "AgentBackend user/workspace substitutions are required") + localdocs = McpClient(LOCALDOCS_URL, "localdocs") + localdocs.initialize() + request_raw = localdocs.read_binary(REQUEST_PATH) + request = validate_request(request_raw) + request["_request_sha256"] = digest(request_raw) + preflight_digest = preflight(localdocs, request) + output_schema_store = load_output_schema_store(localdocs) + publication = status_only(localdocs, request, preflight_digest) if request["entry_route"] == "TO_S2_40_STATUS_ONLY" else normal_route(localdocs, request, preflight_digest) + status = publication["status"] + receipt = { + "schema_version": "stage2_s2_40_execution_receipt.v1", + "ok": True, + "workflow_id": WORKFLOW_ID, + "request_id": request["request_id"], + "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "requested_transition": request["requested_transition"], + "workflow_phase": status["workflow_phase"], + "candidate_content_digest": status["candidate_content_digest"], + "route": status["route"], + "run_status_path": publication["status_path"], + "run_status_sha256": publication["status_sha256"], + "error": None, + } + except Exception as exc: + error = exc.as_dict() if isinstance(exc, S240Error) else {"code": "INLINE_RUNTIME_ERROR", "message": str(exc)} + failure_publication: dict[str, Any] | None = None + if localdocs is not None and request is not None and preflight_digest is not None: + try: + failure_publication = publish_post_preflight_failure(localdocs, request, preflight_digest, error) + except Exception as close_exc: + error = { + "code": "POST_PREFLIGHT_FAILURE_AND_SAFE_CLOSE_FAILED", + "message": str(exc), + "safe_close_error": close_exc.as_dict() if isinstance(close_exc, S240Error) else {"message": str(close_exc)}, + } + fallback_binding = request["run_binding_digest"] if request is not None else "0" * 64 + receipt = { + "schema_version": "stage2_s2_40_execution_receipt.v1", + "ok": False, + "workflow_id": WORKFLOW_ID, + "request_id": request["request_id"] if request is not None else "UNBOUND", + "run_binding_digest": fallback_binding, + "candidate_attempt_id": request["candidate_attempt_id"] if request is not None else "UNBOUND", + "requested_transition": request["requested_transition"] if request is not None else "FREEZE", + "workflow_phase": "DIAGNOSTIC_ONLY", + "candidate_content_digest": None, + "route": "STOP_TECHNICAL_INCOMPLETE", + "run_status_path": failure_publication["status_path"] if failure_publication is not None else None, + "run_status_sha256": failure_publication["status_sha256"] if failure_publication is not None else None, + "error": error, + } + exit_code = 2 + finally: + if localdocs is not None: + localdocs.close() + if output_schema_store is not None: + validate_schema_instance( + receipt, "schemas/deployment.schema.json#/$defs/s2_40_execution_receipt", + output_schema_store, code="GENERATED_EXECUTION_RECEIPT_SCHEMA", + ) + sys.stdout.buffer.write(canonical_bytes(receipt)) + return exit_code + + +if __name__ == "__main__": + raise SystemExit(run()) \ No newline at end of file diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/validation/invariant_runner.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/validation/invariant_runner.py new file mode 100644 index 00000000..52844864 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/validation/invariant_runner.py @@ -0,0 +1,575 @@ +from __future__ import annotations + +"""Closed S2_40 V01-V18 and review/commit state oracle.""" + +import hashlib +import json +import re +from datetime import datetime, timezone +from typing import Any, Mapping, Sequence + + +INVARIANT_IDS = tuple(f"V{index:02d}" for index in range(1, 19)) +IMPACT_SCOPES = {"OK", "REVIEW_REQUIRED", "INCOMPLETE"} +REQUIRED_LEGAL_GATES = { + "binding", "authority", "renderer_branch", "rule_sub_rule", "review_policy", + "case_type_coverage_137", "corpus", "law_value", "calculator", "required_receipts", +} +HEX64 = re.compile(r"^[a-f0-9]{64}$") +CANDIDATE_MATERIAL_KEYS = { + "run_binding_digest", "dependency_snapshot_sha256", "candidate_manifest_core_sha256", + "document_sha256s", "attorney_worknotes_core_sha256", "final_issue_ledger_sha256", + "assumption_ledger_sha256", "validation_core_sha256", + "ordered_source_dependency_snapshot_digest", +} +DOCUMENT_DIGEST_KEYS = {"claim_relief", "claim_cause", "pleading_draft"} +STATUS_ONLY_PATHS = ( + "ingress/ingress_status.json", + "ingress/technical_diagnostic.json", + "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", + "review/issue_ledger.base.json", +) +REVIEW_RECEIPT_KEYS = { + "schema_version", "receipt_id", "request_id", "receipt_type", + "candidate_content_digest", "review_subject_digest", "finding_ids", "scope_ids", + "reviewer_role", "reviewer_qualification", "issuer_id", "key_id", + "signature_algorithm", "signed_material_digest", + "external_verification_attestation_sha256", "issued_at", "expires_at", + "revocation_status", "cryptographic_verification_status", "review_disposition", + "change_scope", "reason_codes", +} +TRUSTED_REVIEW_ISSUER = "AGENTBACKEND_STAGE2_REVIEW_AUTHORITY" +TRUSTED_REVIEW_KEY_IDS = frozenset({"AGENTBACKEND_STAGE2_REVIEW_KEY_V1"}) +TRUSTED_REVIEW_SIGNATURE_ALGORITHM = "AGENTBACKEND_TRUSTED_ATTESTATION_V1" +TRUSTED_REVIEW_ROLE = "KOREAN_LAWYER" +TRUSTED_REVIEW_QUALIFICATION = "QUALIFIED_KOREAN_LAWYER" + + +class InvariantError(ValueError): + pass + + +class JsonSchemaValidationError(InvariantError): + pass + + +def canonical_json_bytes(value: Any) -> bytes: + return (json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8") + + +def _require_sha256(value: Any, code: str) -> str: + if not isinstance(value, str) or HEX64.fullmatch(value) is None: + raise InvariantError(code) + return value + + +def validate_jsonschema_instance( + instance: Any, schema: Mapping[str, Any], *, + schema_store: Mapping[str, Mapping[str, Any]] | None = None, +) -> None: + """Validate the closed JSON-Schema subset used by the S2_40 contracts.""" + store = dict(schema_store or {}) + root = schema + + def resolve(reference: str, current_root: Mapping[str, Any]) -> tuple[Mapping[str, Any], Mapping[str, Any]]: + if "#" in reference: + file_name, fragment = reference.split("#", 1) + else: + file_name, fragment = reference, "" + target_root = current_root if not file_name else store.get(file_name) + if target_root is None: + raise JsonSchemaValidationError(f"SCHEMA_REF_UNRESOLVED::{reference}") + target: Any = target_root + if fragment: + if not fragment.startswith("/"): + raise JsonSchemaValidationError(f"SCHEMA_REF_FRAGMENT_INVALID::{reference}") + for token in fragment[1:].split("/"): + token = token.replace("~1", "/").replace("~0", "~") + if not isinstance(target, Mapping) or token not in target: + raise JsonSchemaValidationError(f"SCHEMA_REF_UNRESOLVED::{reference}") + target = target[token] + if not isinstance(target, Mapping): + raise JsonSchemaValidationError(f"SCHEMA_REF_TARGET_INVALID::{reference}") + return target, target_root + + def type_matches(value: Any, type_name: str) -> bool: + return { + "object": isinstance(value, Mapping), + "array": isinstance(value, list), + "string": isinstance(value, str), + "integer": isinstance(value, int) and not isinstance(value, bool), + "number": isinstance(value, (int, float)) and not isinstance(value, bool), + "boolean": isinstance(value, bool), + "null": value is None, + }.get(type_name, False) + + def check(value: Any, rule: Mapping[str, Any], current_root: Mapping[str, Any], path: str) -> None: + if "$ref" in rule: + target, target_root = resolve(str(rule["$ref"]), current_root) + check(value, target, target_root, path) + return + if "allOf" in rule: + for index, branch in enumerate(rule["allOf"]): + check(value, branch, current_root, f"{path}/allOf/{index}") + if "oneOf" in rule: + successes = 0 + for branch in rule["oneOf"]: + try: + check(value, branch, current_root, path) + successes += 1 + except JsonSchemaValidationError: + pass + if successes != 1: + raise JsonSchemaValidationError(f"{path}:ONE_OF_COUNT::{successes}") + if "anyOf" in rule: + for branch in rule["anyOf"]: + try: + check(value, branch, current_root, path) + break + except JsonSchemaValidationError: + continue + else: + raise JsonSchemaValidationError(f"{path}:ANY_OF_NO_MATCH") + if "not" in rule: + try: + check(value, rule["not"], current_root, path) + except JsonSchemaValidationError: + pass + else: + raise JsonSchemaValidationError(f"{path}:NOT_SCHEMA_MATCHED") + if "if" in rule: + try: + check(value, rule["if"], current_root, path) + matched = True + except JsonSchemaValidationError: + matched = False + if matched and "then" in rule: + check(value, rule["then"], current_root, path) + if not matched and "else" in rule: + check(value, rule["else"], current_root, path) + if "const" in rule and value != rule["const"]: + raise JsonSchemaValidationError(f"{path}:CONST_MISMATCH") + if "enum" in rule and value not in rule["enum"]: + raise JsonSchemaValidationError(f"{path}:ENUM_MISMATCH") + declared_type = rule.get("type") + if declared_type is not None: + allowed = [declared_type] if isinstance(declared_type, str) else list(declared_type) + if not any(type_matches(value, item) for item in allowed): + raise JsonSchemaValidationError(f"{path}:TYPE_MISMATCH") + if isinstance(value, str): + if len(value) < int(rule.get("minLength", 0)): + raise JsonSchemaValidationError(f"{path}:MIN_LENGTH") + if "pattern" in rule and re.search(str(rule["pattern"]), value) is None: + raise JsonSchemaValidationError(f"{path}:PATTERN_MISMATCH") + if rule.get("format") == "date-time": + try: + _parse_review_time(value, f"{path}:DATETIME_INVALID") + except InvariantError as exc: + raise JsonSchemaValidationError(str(exc)) from exc + if isinstance(value, Mapping): + required = rule.get("required", []) + missing = [key for key in required if key not in value] + if missing: + raise JsonSchemaValidationError(f"{path}:REQUIRED_MISSING::{','.join(missing)}") + properties = rule.get("properties", {}) + if rule.get("additionalProperties") is False: + extras = sorted(set(value) - set(properties)) + if extras: + raise JsonSchemaValidationError(f"{path}:ADDITIONAL_PROPERTIES::{','.join(extras)}") + for key, child in properties.items(): + if key in value: + check(value[key], child, current_root, f"{path}/{key}") + if isinstance(value, list): + if len(value) < int(rule.get("minItems", 0)): + raise JsonSchemaValidationError(f"{path}:MIN_ITEMS") + if "maxItems" in rule and len(value) > int(rule["maxItems"]): + raise JsonSchemaValidationError(f"{path}:MAX_ITEMS") + if rule.get("uniqueItems") and len({canonical_json_bytes(item) for item in value}) != len(value): + raise JsonSchemaValidationError(f"{path}:UNIQUE_ITEMS") + if "items" in rule: + for index, item in enumerate(value): + check(item, rule["items"], current_root, f"{path}/{index}") + if isinstance(value, (int, float)) and not isinstance(value, bool) and "minimum" in rule and value < rule["minimum"]: + raise JsonSchemaValidationError(f"{path}:MINIMUM") + + check(instance, root, root, "$") + + +def validate_candidate_material(material: Mapping[str, Any]) -> None: + if set(material) != CANDIDATE_MATERIAL_KEYS: + raise InvariantError("CANDIDATE_DIGEST_MATERIAL_SHAPE") + for key in CANDIDATE_MATERIAL_KEYS - {"document_sha256s"}: + _require_sha256(material[key], f"CANDIDATE_{key.upper()}_INVALID") + documents = material["document_sha256s"] + if not isinstance(documents, Mapping) or set(documents) != DOCUMENT_DIGEST_KEYS: + raise InvariantError("CANDIDATE_DOCUMENT_DIGEST_SET_NOT_EXACT") + for key, value in documents.items(): + _require_sha256(value, f"CANDIDATE_DOCUMENT_{key.upper()}_INVALID") + + +def review_subject_digest( + *, candidate_digest: str, review_request_core_sha256: str, + lawyer_review_packet_core_sha256: str, validation_envelope_core_sha256: str, + finding_ids: Sequence[str], scope_ids: Sequence[str], policy_sha256: str, + release_sha256s: Mapping[str, str], +) -> str: + for value, code in ( + (candidate_digest, "REVIEW_CANDIDATE_DIGEST_INVALID"), + (review_request_core_sha256, "REVIEW_REQUEST_CORE_HASH_INVALID"), + (lawyer_review_packet_core_sha256, "REVIEW_PACKET_CORE_HASH_INVALID"), + (validation_envelope_core_sha256, "REVIEW_VALIDATION_HASH_INVALID"), + (policy_sha256, "REVIEW_POLICY_HASH_INVALID"), + ): + _require_sha256(value, code) + expected_release_keys = {"parent", "authority", "corpus", "case_type_coverage"} + if set(release_sha256s) != expected_release_keys: + raise InvariantError("REVIEW_RELEASE_SNAPSHOT_NOT_EXACT") + for value in release_sha256s.values(): + _require_sha256(value, "REVIEW_RELEASE_HASH_INVALID") + if len(finding_ids) != len(set(finding_ids)) or len(scope_ids) != len(set(scope_ids)): + raise InvariantError("REVIEW_SUBJECT_SET_DUPLICATE") + subject_core = { + "schema_version": "stage2_s2_40_review_subject.v1", + "domain_separator": "STAGE2_S2_40_REVIEW_SUBJECT_V1", + "candidate_content_digest": candidate_digest, + "review_request_core_sha256": review_request_core_sha256, + "lawyer_review_packet_core_sha256": lawyer_review_packet_core_sha256, + "validation_envelope_core_sha256": validation_envelope_core_sha256, + "finding_ids": sorted(finding_ids), "scope_ids": sorted(scope_ids), + "policy_sha256": policy_sha256, + "release_sha256s": {key: release_sha256s[key] for key in sorted(release_sha256s)}, + } + return hashlib.sha256(canonical_json_bytes(subject_core)).hexdigest() + + +def validate_status_only_paths(paths: Sequence[str]) -> None: + if tuple(paths) != STATUS_ONLY_PATHS: + raise InvariantError("STATUS_ONLY_INPUT_SET_NOT_EXACT_FIVE") + + +def validate_reference_closure(required_refs: Sequence[str], available_refs: Sequence[str]) -> None: + if len(required_refs) != len(set(required_refs)) or len(available_refs) != len(set(available_refs)): + raise InvariantError("REFERENCE_SET_DUPLICATE") + missing = sorted(set(required_refs) - set(available_refs)) + if missing: + raise InvariantError("REFERENCE_DANGLING::" + ",".join(missing)) + + +def validate_readback_rows(expected_rows: Sequence[Mapping[str, Any]], observed_rows: Sequence[Mapping[str, Any]]) -> None: + def normalize(rows: Sequence[Mapping[str, Any]]) -> list[tuple[str, str, str, int, str | None]]: + normalized: list[tuple[str, str, str, int, str | None]] = [] + for row in rows: + if set(row) != {"path", "raw_sha256", "content_type", "size_bytes", "schema_ref"}: + raise InvariantError("READBACK_ROW_SHAPE_INVALID") + path = row["path"] + if not isinstance(path, str) or not path.startswith("final/") or ".." in path.split("/"): + raise InvariantError("READBACK_PATH_INVALID") + content_type, schema_ref, size = row["content_type"], row["schema_ref"], row["size_bytes"] + if not isinstance(content_type, str) or not content_type or not isinstance(size, int) or size < 1: + raise InvariantError("READBACK_METADATA_INVALID") + if schema_ref is not None and (not isinstance(schema_ref, str) or not schema_ref): + raise InvariantError("READBACK_SCHEMA_REF_INVALID") + normalized.append((path, _require_sha256(row["raw_sha256"], "READBACK_HASH_INVALID"), content_type, size, schema_ref)) + if len({row[0] for row in normalized}) != len(normalized): + raise InvariantError("READBACK_PATH_DUPLICATE") + return sorted(normalized) + if normalize(expected_rows) != normalize(observed_rows): + raise InvariantError("READBACK_MISMATCH_NO_FINAL_BARRIER") + + +def run_invariants(checks: Mapping[str, Mapping[str, Any]]) -> list[dict[str, Any]]: + if set(checks) != set(INVARIANT_IDS): + raise InvariantError("INVARIANT_SET_NOT_EXACT_V01_V18") + results: list[dict[str, Any]] = [] + for invariant_id in INVARIANT_IDS: + check = checks[invariant_id] + if not isinstance(check, Mapping): + raise InvariantError("INVARIANT_CHECK_NOT_OBJECT") + required_check_keys = { + "evaluable", "passed", "impact_scope", "source_refs", "finding_ids", + "expected", "observed", "reason_codes", + } + if set(check) != required_check_keys: + raise InvariantError(f"{invariant_id}_CHECK_SHAPE_NOT_EXACT") + evaluable = check["evaluable"] + if not isinstance(evaluable, bool): + raise InvariantError(f"{invariant_id}_EVALUABLE_NOT_BOOLEAN") + if evaluable: + if not isinstance(check["passed"], bool): + raise InvariantError(f"{invariant_id}_PASSED_NOT_BOOLEAN") + if check["observed"] is None or check["passed"] != (check["observed"] == check["expected"]): + raise InvariantError(f"{invariant_id}_OBSERVATION_ORACLE_MISMATCH") + evaluation = "PASS" if check["passed"] else "FAIL" + else: + if check["passed"] not in {False, None} or check["observed"] is not None: + raise InvariantError(f"{invariant_id}_UNEVALUABLE_OBSERVATION_INVALID") + evaluation = "UNEVALUABLE" + scope = check.get("impact_scope", "OK" if evaluation == "PASS" else "REVIEW_REQUIRED") + if scope not in IMPACT_SCOPES or (evaluation == "PASS" and scope != "OK"): + raise InvariantError("INVARIANT_IMPACT_SCOPE_INVALID") + reason_values = check["reason_codes"] + source_values = check["source_refs"] + finding_values = check["finding_ids"] + for values in (reason_values, source_values, finding_values): + if (not isinstance(values, list) or len(values) != len(set(values)) + or not all(isinstance(value, str) and value for value in values)): + raise InvariantError("INVARIANT_STRING_SET_INVALID") + if not source_values: + raise InvariantError(f"{invariant_id}_SOURCE_EVIDENCE_REQUIRED") + reason_codes = sorted(set(reason_values)) + if evaluation == "PASS" and (reason_codes or finding_values): + raise InvariantError(f"{invariant_id}_PASS_FINDING_FORBIDDEN") + if evaluation != "PASS" and (not reason_codes or not finding_values): + raise InvariantError(f"{invariant_id}_{evaluation}_FINDING_REQUIRED") + results.append({ + "invariant_id": invariant_id, "evaluation_status": evaluation, + "finding_ids": sorted(set(finding_values)), "impact_scope": scope, + "source_refs": sorted(set(source_values)), + "expected": check["expected"], "observed": check["observed"], + "reason_codes": reason_codes, "validator_algorithm_id": f"S2_40::{invariant_id}::V1", + }) + return results + + +def aggregate_status(results: Sequence[Mapping[str, Any]], *, compile_mode: str | None, legal_gates: Mapping[str, bool]) -> dict[str, str]: + if [row.get("invariant_id") for row in results] != list(INVARIANT_IDS): + raise InvariantError("INVARIANT_RESULT_ORDER_OR_SET_INVALID") + for row in results: + evaluation, scope = row.get("evaluation_status"), row.get("impact_scope") + if evaluation not in {"PASS", "FAIL", "UNEVALUABLE"} or scope not in IMPACT_SCOPES: + raise InvariantError("INVARIANT_RESULT_ENUM_INVALID") + if evaluation == "PASS" and scope != "OK": + raise InvariantError("INVARIANT_PASS_SCOPE_INVALID") + scopes = {row.get("impact_scope") for row in results} + if "INCOMPLETE" in scopes: + run = "TECHNICAL_INCOMPLETE" + elif "REVIEW_REQUIRED" in scopes or any(row.get("evaluation_status") == "UNEVALUABLE" for row in results): + run = "TECHNICAL_REVIEW_REQUIRED" + else: + run = "CONSISTENT" + if run == "TECHNICAL_INCOMPLETE": + artifact, legal = "NOT_PRODUCED", "NOT_ASSESSED" + elif run == "TECHNICAL_REVIEW_REQUIRED": + artifact, legal = "TECHNICAL_REVIEW_REQUIRED", "LAWYER_REVIEW_REQUIRED" + else: + artifact = "CONSISTENT" + gates = set(legal_gates) == REQUIRED_LEGAL_GATES and all(legal_gates.values()) + all_pass = all(row.get("evaluation_status") == "PASS" for row in results) + legal = "READY_FOR_LAWYER_FILING_DECISION" if compile_mode == "PRODUCTION" and all_pass and gates else "LAWYER_REVIEW_REQUIRED" + return {"run_technical_status": run, "artifact_technical_status": artifact, "legal_readiness": legal} + + +def candidate_content_digest(material: Mapping[str, Any]) -> str: + forbidden = {"candidate_content_digest", "review_request", "review_receipt", "commit_intent", "commit_result", "run_status", "artifact_set_digest"} + if forbidden & set(material): + raise InvariantError("CANDIDATE_DIGEST_MATERIAL_CYCLE") + validate_candidate_material(material) + digest_core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + **material, + } + return hashlib.sha256(canonical_json_bytes(digest_core)).hexdigest() + + +def artifact_set_digest(rows: Sequence[Mapping[str, Any]]) -> str: + ordered = sorted(rows, key=lambda row: row["path"]) + paths = [row["path"] for row in ordered] + if len(paths) != len(set(paths)): + raise InvariantError("ARTIFACT_PATH_DUPLICATE") + for row in ordered: + if set(row) != {"path", "raw_sha256", "content_type", "size_bytes", "schema_ref"}: + raise InvariantError("ARTIFACT_ROW_SHAPE_INVALID") + _require_sha256(row["raw_sha256"], "ARTIFACT_ROW_HASH_INVALID") + if not isinstance(row["content_type"], str) or not row["content_type"]: + raise InvariantError("ARTIFACT_ROW_CONTENT_TYPE_INVALID") + if not isinstance(row["size_bytes"], int) or row["size_bytes"] < 1: + raise InvariantError("ARTIFACT_ROW_SIZE_INVALID") + if row["schema_ref"] is not None and (not isinstance(row["schema_ref"], str) or not row["schema_ref"]): + raise InvariantError("ARTIFACT_ROW_SCHEMA_REF_INVALID") + return hashlib.sha256(canonical_json_bytes(ordered)).hexdigest() + + +def derive_review_requirements(policy: Mapping[str, Any], active_tags: Sequence[str], runtime_triggers: Sequence[str]) -> list[str]: + if policy.get("status") != "APPROVED_LEGAL_CONTENT" or policy.get("execution_eligible") is not True: + return ["STANDARD_ATTORNEY_REVIEW"] + allowed_tags = set(policy["final_review_contract"]["allowed_review_tags"]) + if not set(active_tags) <= allowed_tags: + raise InvariantError("REVIEW_TAG_UNKNOWN") + required = set(policy["final_review_contract"]["base_required_receipt_types"]) + for row in policy.get("policy_rows", []): + if set(row.get("match_tags", [])) <= set(active_tags) and set(row.get("runtime_triggers", [])) <= set(runtime_triggers): + required.update(row.get("required_receipt_types", [])) + return sorted(required) + + +def review_receipt_signed_material_digest(receipt: Mapping[str, Any]) -> str: + """Hash the exact inline receipt preimage, including detached-adapter evidence.""" + keys = ( + "request_id", "candidate_content_digest", "review_subject_digest", "receipt_type", + "finding_ids", "scope_ids", "reviewer_role", "reviewer_qualification", + "issuer_id", "key_id", "signature_algorithm", + "external_verification_attestation_sha256", "issued_at", "expires_at", + "revocation_status", "cryptographic_verification_status", + "review_disposition", "change_scope", "reason_codes", + ) + if any(key not in receipt for key in keys): + raise InvariantError("REVIEW_SIGNED_MATERIAL_FIELD_MISSING") + material = ["STAGE2_S2_40_REVIEW_RECEIPT_V1", *[receipt[key] for key in keys]] + return hashlib.sha256(canonical_json_bytes(material)).hexdigest() + + +def _parse_review_time(value: Any, code: str) -> datetime: + if not isinstance(value, str): + raise InvariantError(code) + try: + parsed = datetime.fromisoformat(value.replace("Z", "+00:00")) + except ValueError as exc: + raise InvariantError(code) from exc + if parsed.tzinfo is None: + raise InvariantError(code) + return parsed.astimezone(timezone.utc) + + +def validate_review_receipt( + receipt: Mapping[str, Any], *, candidate_digest: str, + expected_review_subject_digest: str, expected_request_id: str, + expected_receipt_type: str, expected_finding_ids: Sequence[str], + expected_scope_ids: Sequence[str], now: datetime, +) -> list[str]: + """Return closed invalidity codes; an empty list means externally admissible.""" + reasons: list[str] = [] + if set(receipt) != REVIEW_RECEIPT_KEYS or receipt.get("schema_version") != "stage2_s2_40_review_receipt.v1": + return ["REVIEW_RECEIPT_CLOSED_SHAPE_INVALID"] + for key in ("receipt_id", "request_id", "receipt_type", "reviewer_role", "reviewer_qualification", "issuer_id", "key_id", "signature_algorithm"): + if not isinstance(receipt.get(key), str) or not receipt[key]: + reasons.append(f"REVIEW_RECEIPT_{key.upper()}_INVALID") + for key in ("candidate_content_digest", "review_subject_digest", "signed_material_digest", "external_verification_attestation_sha256"): + try: + _require_sha256(receipt.get(key), f"REVIEW_RECEIPT_{key.upper()}_INVALID") + except InvariantError as exc: + reasons.append(str(exc)) + for key, expected in ( + ("candidate_content_digest", candidate_digest), + ("review_subject_digest", expected_review_subject_digest), + ("request_id", expected_request_id), + ("receipt_type", expected_receipt_type), + ("finding_ids", sorted(expected_finding_ids)), + ("scope_ids", sorted(expected_scope_ids)), + ): + observed = sorted(receipt[key]) if key in {"finding_ids", "scope_ids"} and isinstance(receipt[key], list) else receipt[key] + if observed != expected: + reasons.append(f"REVIEW_RECEIPT_{key.upper()}_MISMATCH") + for key in ("finding_ids", "scope_ids", "reason_codes"): + values = receipt.get(key) + if not isinstance(values, list) or values != sorted(set(values)) or not all(isinstance(value, str) and value for value in values): + reasons.append(f"REVIEW_RECEIPT_{key.upper()}_NOT_SORTED_SET") + if receipt.get("reviewer_role") != TRUSTED_REVIEW_ROLE: + reasons.append("REVIEW_RECEIPT_ROLE_UNTRUSTED") + if receipt.get("reviewer_qualification") != TRUSTED_REVIEW_QUALIFICATION: + reasons.append("REVIEW_RECEIPT_QUALIFICATION_UNTRUSTED") + if receipt.get("issuer_id") != TRUSTED_REVIEW_ISSUER: + reasons.append("REVIEW_RECEIPT_ISSUER_UNTRUSTED") + if receipt.get("key_id") not in TRUSTED_REVIEW_KEY_IDS: + reasons.append("REVIEW_RECEIPT_KEY_UNTRUSTED") + if receipt.get("signature_algorithm") != TRUSTED_REVIEW_SIGNATURE_ALGORITHM: + reasons.append("REVIEW_RECEIPT_SIGNATURE_ALGORITHM_UNTRUSTED") + if receipt.get("cryptographic_verification_status") != "VERIFIED_BY_EXTERNAL_ADAPTER": + reasons.append("REVIEW_RECEIPT_EXTERNAL_VERIFICATION_NOT_VERIFIED") + if receipt.get("revocation_status") != "NOT_REVOKED": + reasons.append("REVIEW_RECEIPT_REVOKED_OR_UNKNOWN") + try: + issued = _parse_review_time(receipt.get("issued_at"), "REVIEW_RECEIPT_ISSUED_AT_INVALID") + expires = _parse_review_time(receipt.get("expires_at"), "REVIEW_RECEIPT_EXPIRES_AT_INVALID") + current = now.astimezone(timezone.utc) + if issued > current or expires <= current or expires <= issued: + reasons.append("REVIEW_RECEIPT_TIME_WINDOW_INVALID") + except InvariantError as exc: + reasons.append(str(exc)) + disposition, change_scope = receipt.get("review_disposition"), receipt.get("change_scope") + if disposition == "APPROVE_AS_IS" and change_scope != "NONE": + reasons.append("REVIEW_RECEIPT_APPROVAL_CHANGE_SCOPE_FORBIDDEN") + elif disposition == "CONTENT_CHANGE_REQUIRED" and change_scope not in { + "STAGE1_CONTEXT", "LEGAL_JUDGMENT", "PLAN_RULE_CALCULATION_BINDING", "DRAFTING_TEXT_ATOM", + }: + reasons.append("REVIEW_RECEIPT_CHANGE_SCOPE_INVALID") + elif disposition not in {"APPROVE_AS_IS", "CONTENT_CHANGE_REQUIRED"}: + reasons.append("REVIEW_RECEIPT_DISPOSITION_INVALID") + try: + expected_signed = review_receipt_signed_material_digest(receipt) + if receipt.get("signed_material_digest") != expected_signed: + reasons.append("REVIEW_RECEIPT_SIGNED_MATERIAL_MISMATCH") + except InvariantError as exc: + reasons.append(str(exc)) + return sorted(set(reasons)) + + +def transition_review_state( + *, candidate_digest: str, required_receipt_types: Sequence[str], + receipts: Sequence[Mapping[str, Any]], expected_review_subject_digest: str, + expected_request_ids: Mapping[str, str], expected_finding_ids: Sequence[str], + expected_scope_ids: Sequence[str], now: datetime, +) -> dict[str, Any]: + _require_sha256(candidate_digest, "REVIEW_CANDIDATE_DIGEST_INVALID") + if len(required_receipt_types) != len(set(required_receipt_types)): + raise InvariantError("REVIEW_REQUIRED_TYPE_DUPLICATE") + _require_sha256(expected_review_subject_digest, "REVIEW_SUBJECT_DIGEST_INVALID") + if set(expected_request_ids) != set(required_receipt_types) or any( + not isinstance(value, str) or not value for value in expected_request_ids.values() + ): + raise InvariantError("REVIEW_REQUEST_ID_MAP_INVALID") + valid: dict[str, Mapping[str, Any]] = {} + invalid: list[str] = [] + invalid_reasons: dict[str, list[str]] = {} + seen_receipt_ids: set[str] = set() + for receipt in receipts: + receipt_id = receipt.get("receipt_id") + receipt_type = receipt.get("receipt_type") + if not isinstance(receipt_id, str) or not receipt_id or receipt_id in seen_receipt_ids: + raise InvariantError("REVIEW_RECEIPT_ID_MISSING_OR_DUPLICATE") + seen_receipt_ids.add(receipt_id) + reasons = validate_review_receipt( + receipt, candidate_digest=candidate_digest, + expected_review_subject_digest=expected_review_subject_digest, + expected_request_id=expected_request_ids.get(str(receipt_type), ""), + expected_receipt_type=str(receipt_type), + expected_finding_ids=expected_finding_ids, expected_scope_ids=expected_scope_ids, + now=now, + ) + if receipt_type not in required_receipt_types: + reasons.append("REVIEW_RECEIPT_TYPE_NOT_REQUIRED") + if reasons: + invalid.append(receipt_id) + invalid_reasons[receipt_id] = sorted(set(reasons)) + else: + if receipt_type in valid: + raise InvariantError("REVIEW_RECEIPT_TYPE_DUPLICATE") + valid[receipt_type] = receipt + routes = { + "STAGE1_CONTEXT": (0, "RESTART_FROM_S2_00"), + "LEGAL_JUDGMENT": (1, "RESTART_FROM_S2_10"), + "PLAN_RULE_CALCULATION_BINDING": (2, "RESTART_FROM_S2_20"), + "DRAFTING_TEXT_ATOM": (3, "RESTART_FROM_S2_30"), + } + changed_scopes = [receipt["change_scope"] for receipt in valid.values() if receipt["review_disposition"] == "CONTENT_CHANGE_REQUIRED"] + if changed_scopes: + earliest = min(changed_scopes, key=lambda scope: routes[scope][0]) + return {"workflow_phase": "SUPERSEDED", "route": routes[earliest][1], "invalid_receipt_ids": sorted(invalid), "invalid_receipt_reasons": invalid_reasons} + missing = sorted(set(required_receipt_types) - set(valid)) + if missing or invalid: + return {"workflow_phase": "AWAITING_EXTERNAL_REVIEW", "route": "WAIT_EXTERNAL_REVIEW", "missing_receipt_types": missing, "invalid_receipt_ids": sorted(invalid), "invalid_receipt_reasons": invalid_reasons} + if any(receipt.get("review_disposition") != "APPROVE_AS_IS" for receipt in valid.values()): + raise InvariantError("REVIEW_DISPOSITION_INVALID") + return {"workflow_phase": "READY_TO_COMMIT", "route": "CONTINUE_TO_COMMIT", "invalid_receipt_ids": [], "invalid_receipt_reasons": {}} + + +def commit_write_order(final_paths: Sequence[str]) -> list[str]: + if len(final_paths) != len(set(final_paths)): + raise InvariantError("COMMIT_TARGET_DUPLICATE") + if any(not path.startswith("final/") or ".." in path.split("/") for path in final_paths): + raise InvariantError("COMMIT_TARGET_OUTSIDE_FINAL_ROOT") + return ["commit/commit_intent.json", *sorted(final_paths), "commit/stage2_commit_result.json", "control/run_status.json"] + + +__all__ = ["INVARIANT_IDS", "InvariantError", "JsonSchemaValidationError", "aggregate_status", "artifact_set_digest", "candidate_content_digest", "commit_write_order", "derive_review_requirements", "review_receipt_signed_material_digest", "review_subject_digest", "run_invariants", "transition_review_state", "validate_candidate_material", "validate_jsonschema_instance", "validate_readback_rows", "validate_reference_closure", "validate_review_receipt", "validate_status_only_paths"] diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/validation/invariant_runner.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/validation/invariant_runner.txt new file mode 100644 index 00000000..52844864 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/runtime/validation/invariant_runner.txt @@ -0,0 +1,575 @@ +from __future__ import annotations + +"""Closed S2_40 V01-V18 and review/commit state oracle.""" + +import hashlib +import json +import re +from datetime import datetime, timezone +from typing import Any, Mapping, Sequence + + +INVARIANT_IDS = tuple(f"V{index:02d}" for index in range(1, 19)) +IMPACT_SCOPES = {"OK", "REVIEW_REQUIRED", "INCOMPLETE"} +REQUIRED_LEGAL_GATES = { + "binding", "authority", "renderer_branch", "rule_sub_rule", "review_policy", + "case_type_coverage_137", "corpus", "law_value", "calculator", "required_receipts", +} +HEX64 = re.compile(r"^[a-f0-9]{64}$") +CANDIDATE_MATERIAL_KEYS = { + "run_binding_digest", "dependency_snapshot_sha256", "candidate_manifest_core_sha256", + "document_sha256s", "attorney_worknotes_core_sha256", "final_issue_ledger_sha256", + "assumption_ledger_sha256", "validation_core_sha256", + "ordered_source_dependency_snapshot_digest", +} +DOCUMENT_DIGEST_KEYS = {"claim_relief", "claim_cause", "pleading_draft"} +STATUS_ONLY_PATHS = ( + "ingress/ingress_status.json", + "ingress/technical_diagnostic.json", + "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", + "review/issue_ledger.base.json", +) +REVIEW_RECEIPT_KEYS = { + "schema_version", "receipt_id", "request_id", "receipt_type", + "candidate_content_digest", "review_subject_digest", "finding_ids", "scope_ids", + "reviewer_role", "reviewer_qualification", "issuer_id", "key_id", + "signature_algorithm", "signed_material_digest", + "external_verification_attestation_sha256", "issued_at", "expires_at", + "revocation_status", "cryptographic_verification_status", "review_disposition", + "change_scope", "reason_codes", +} +TRUSTED_REVIEW_ISSUER = "AGENTBACKEND_STAGE2_REVIEW_AUTHORITY" +TRUSTED_REVIEW_KEY_IDS = frozenset({"AGENTBACKEND_STAGE2_REVIEW_KEY_V1"}) +TRUSTED_REVIEW_SIGNATURE_ALGORITHM = "AGENTBACKEND_TRUSTED_ATTESTATION_V1" +TRUSTED_REVIEW_ROLE = "KOREAN_LAWYER" +TRUSTED_REVIEW_QUALIFICATION = "QUALIFIED_KOREAN_LAWYER" + + +class InvariantError(ValueError): + pass + + +class JsonSchemaValidationError(InvariantError): + pass + + +def canonical_json_bytes(value: Any) -> bytes: + return (json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8") + + +def _require_sha256(value: Any, code: str) -> str: + if not isinstance(value, str) or HEX64.fullmatch(value) is None: + raise InvariantError(code) + return value + + +def validate_jsonschema_instance( + instance: Any, schema: Mapping[str, Any], *, + schema_store: Mapping[str, Mapping[str, Any]] | None = None, +) -> None: + """Validate the closed JSON-Schema subset used by the S2_40 contracts.""" + store = dict(schema_store or {}) + root = schema + + def resolve(reference: str, current_root: Mapping[str, Any]) -> tuple[Mapping[str, Any], Mapping[str, Any]]: + if "#" in reference: + file_name, fragment = reference.split("#", 1) + else: + file_name, fragment = reference, "" + target_root = current_root if not file_name else store.get(file_name) + if target_root is None: + raise JsonSchemaValidationError(f"SCHEMA_REF_UNRESOLVED::{reference}") + target: Any = target_root + if fragment: + if not fragment.startswith("/"): + raise JsonSchemaValidationError(f"SCHEMA_REF_FRAGMENT_INVALID::{reference}") + for token in fragment[1:].split("/"): + token = token.replace("~1", "/").replace("~0", "~") + if not isinstance(target, Mapping) or token not in target: + raise JsonSchemaValidationError(f"SCHEMA_REF_UNRESOLVED::{reference}") + target = target[token] + if not isinstance(target, Mapping): + raise JsonSchemaValidationError(f"SCHEMA_REF_TARGET_INVALID::{reference}") + return target, target_root + + def type_matches(value: Any, type_name: str) -> bool: + return { + "object": isinstance(value, Mapping), + "array": isinstance(value, list), + "string": isinstance(value, str), + "integer": isinstance(value, int) and not isinstance(value, bool), + "number": isinstance(value, (int, float)) and not isinstance(value, bool), + "boolean": isinstance(value, bool), + "null": value is None, + }.get(type_name, False) + + def check(value: Any, rule: Mapping[str, Any], current_root: Mapping[str, Any], path: str) -> None: + if "$ref" in rule: + target, target_root = resolve(str(rule["$ref"]), current_root) + check(value, target, target_root, path) + return + if "allOf" in rule: + for index, branch in enumerate(rule["allOf"]): + check(value, branch, current_root, f"{path}/allOf/{index}") + if "oneOf" in rule: + successes = 0 + for branch in rule["oneOf"]: + try: + check(value, branch, current_root, path) + successes += 1 + except JsonSchemaValidationError: + pass + if successes != 1: + raise JsonSchemaValidationError(f"{path}:ONE_OF_COUNT::{successes}") + if "anyOf" in rule: + for branch in rule["anyOf"]: + try: + check(value, branch, current_root, path) + break + except JsonSchemaValidationError: + continue + else: + raise JsonSchemaValidationError(f"{path}:ANY_OF_NO_MATCH") + if "not" in rule: + try: + check(value, rule["not"], current_root, path) + except JsonSchemaValidationError: + pass + else: + raise JsonSchemaValidationError(f"{path}:NOT_SCHEMA_MATCHED") + if "if" in rule: + try: + check(value, rule["if"], current_root, path) + matched = True + except JsonSchemaValidationError: + matched = False + if matched and "then" in rule: + check(value, rule["then"], current_root, path) + if not matched and "else" in rule: + check(value, rule["else"], current_root, path) + if "const" in rule and value != rule["const"]: + raise JsonSchemaValidationError(f"{path}:CONST_MISMATCH") + if "enum" in rule and value not in rule["enum"]: + raise JsonSchemaValidationError(f"{path}:ENUM_MISMATCH") + declared_type = rule.get("type") + if declared_type is not None: + allowed = [declared_type] if isinstance(declared_type, str) else list(declared_type) + if not any(type_matches(value, item) for item in allowed): + raise JsonSchemaValidationError(f"{path}:TYPE_MISMATCH") + if isinstance(value, str): + if len(value) < int(rule.get("minLength", 0)): + raise JsonSchemaValidationError(f"{path}:MIN_LENGTH") + if "pattern" in rule and re.search(str(rule["pattern"]), value) is None: + raise JsonSchemaValidationError(f"{path}:PATTERN_MISMATCH") + if rule.get("format") == "date-time": + try: + _parse_review_time(value, f"{path}:DATETIME_INVALID") + except InvariantError as exc: + raise JsonSchemaValidationError(str(exc)) from exc + if isinstance(value, Mapping): + required = rule.get("required", []) + missing = [key for key in required if key not in value] + if missing: + raise JsonSchemaValidationError(f"{path}:REQUIRED_MISSING::{','.join(missing)}") + properties = rule.get("properties", {}) + if rule.get("additionalProperties") is False: + extras = sorted(set(value) - set(properties)) + if extras: + raise JsonSchemaValidationError(f"{path}:ADDITIONAL_PROPERTIES::{','.join(extras)}") + for key, child in properties.items(): + if key in value: + check(value[key], child, current_root, f"{path}/{key}") + if isinstance(value, list): + if len(value) < int(rule.get("minItems", 0)): + raise JsonSchemaValidationError(f"{path}:MIN_ITEMS") + if "maxItems" in rule and len(value) > int(rule["maxItems"]): + raise JsonSchemaValidationError(f"{path}:MAX_ITEMS") + if rule.get("uniqueItems") and len({canonical_json_bytes(item) for item in value}) != len(value): + raise JsonSchemaValidationError(f"{path}:UNIQUE_ITEMS") + if "items" in rule: + for index, item in enumerate(value): + check(item, rule["items"], current_root, f"{path}/{index}") + if isinstance(value, (int, float)) and not isinstance(value, bool) and "minimum" in rule and value < rule["minimum"]: + raise JsonSchemaValidationError(f"{path}:MINIMUM") + + check(instance, root, root, "$") + + +def validate_candidate_material(material: Mapping[str, Any]) -> None: + if set(material) != CANDIDATE_MATERIAL_KEYS: + raise InvariantError("CANDIDATE_DIGEST_MATERIAL_SHAPE") + for key in CANDIDATE_MATERIAL_KEYS - {"document_sha256s"}: + _require_sha256(material[key], f"CANDIDATE_{key.upper()}_INVALID") + documents = material["document_sha256s"] + if not isinstance(documents, Mapping) or set(documents) != DOCUMENT_DIGEST_KEYS: + raise InvariantError("CANDIDATE_DOCUMENT_DIGEST_SET_NOT_EXACT") + for key, value in documents.items(): + _require_sha256(value, f"CANDIDATE_DOCUMENT_{key.upper()}_INVALID") + + +def review_subject_digest( + *, candidate_digest: str, review_request_core_sha256: str, + lawyer_review_packet_core_sha256: str, validation_envelope_core_sha256: str, + finding_ids: Sequence[str], scope_ids: Sequence[str], policy_sha256: str, + release_sha256s: Mapping[str, str], +) -> str: + for value, code in ( + (candidate_digest, "REVIEW_CANDIDATE_DIGEST_INVALID"), + (review_request_core_sha256, "REVIEW_REQUEST_CORE_HASH_INVALID"), + (lawyer_review_packet_core_sha256, "REVIEW_PACKET_CORE_HASH_INVALID"), + (validation_envelope_core_sha256, "REVIEW_VALIDATION_HASH_INVALID"), + (policy_sha256, "REVIEW_POLICY_HASH_INVALID"), + ): + _require_sha256(value, code) + expected_release_keys = {"parent", "authority", "corpus", "case_type_coverage"} + if set(release_sha256s) != expected_release_keys: + raise InvariantError("REVIEW_RELEASE_SNAPSHOT_NOT_EXACT") + for value in release_sha256s.values(): + _require_sha256(value, "REVIEW_RELEASE_HASH_INVALID") + if len(finding_ids) != len(set(finding_ids)) or len(scope_ids) != len(set(scope_ids)): + raise InvariantError("REVIEW_SUBJECT_SET_DUPLICATE") + subject_core = { + "schema_version": "stage2_s2_40_review_subject.v1", + "domain_separator": "STAGE2_S2_40_REVIEW_SUBJECT_V1", + "candidate_content_digest": candidate_digest, + "review_request_core_sha256": review_request_core_sha256, + "lawyer_review_packet_core_sha256": lawyer_review_packet_core_sha256, + "validation_envelope_core_sha256": validation_envelope_core_sha256, + "finding_ids": sorted(finding_ids), "scope_ids": sorted(scope_ids), + "policy_sha256": policy_sha256, + "release_sha256s": {key: release_sha256s[key] for key in sorted(release_sha256s)}, + } + return hashlib.sha256(canonical_json_bytes(subject_core)).hexdigest() + + +def validate_status_only_paths(paths: Sequence[str]) -> None: + if tuple(paths) != STATUS_ONLY_PATHS: + raise InvariantError("STATUS_ONLY_INPUT_SET_NOT_EXACT_FIVE") + + +def validate_reference_closure(required_refs: Sequence[str], available_refs: Sequence[str]) -> None: + if len(required_refs) != len(set(required_refs)) or len(available_refs) != len(set(available_refs)): + raise InvariantError("REFERENCE_SET_DUPLICATE") + missing = sorted(set(required_refs) - set(available_refs)) + if missing: + raise InvariantError("REFERENCE_DANGLING::" + ",".join(missing)) + + +def validate_readback_rows(expected_rows: Sequence[Mapping[str, Any]], observed_rows: Sequence[Mapping[str, Any]]) -> None: + def normalize(rows: Sequence[Mapping[str, Any]]) -> list[tuple[str, str, str, int, str | None]]: + normalized: list[tuple[str, str, str, int, str | None]] = [] + for row in rows: + if set(row) != {"path", "raw_sha256", "content_type", "size_bytes", "schema_ref"}: + raise InvariantError("READBACK_ROW_SHAPE_INVALID") + path = row["path"] + if not isinstance(path, str) or not path.startswith("final/") or ".." in path.split("/"): + raise InvariantError("READBACK_PATH_INVALID") + content_type, schema_ref, size = row["content_type"], row["schema_ref"], row["size_bytes"] + if not isinstance(content_type, str) or not content_type or not isinstance(size, int) or size < 1: + raise InvariantError("READBACK_METADATA_INVALID") + if schema_ref is not None and (not isinstance(schema_ref, str) or not schema_ref): + raise InvariantError("READBACK_SCHEMA_REF_INVALID") + normalized.append((path, _require_sha256(row["raw_sha256"], "READBACK_HASH_INVALID"), content_type, size, schema_ref)) + if len({row[0] for row in normalized}) != len(normalized): + raise InvariantError("READBACK_PATH_DUPLICATE") + return sorted(normalized) + if normalize(expected_rows) != normalize(observed_rows): + raise InvariantError("READBACK_MISMATCH_NO_FINAL_BARRIER") + + +def run_invariants(checks: Mapping[str, Mapping[str, Any]]) -> list[dict[str, Any]]: + if set(checks) != set(INVARIANT_IDS): + raise InvariantError("INVARIANT_SET_NOT_EXACT_V01_V18") + results: list[dict[str, Any]] = [] + for invariant_id in INVARIANT_IDS: + check = checks[invariant_id] + if not isinstance(check, Mapping): + raise InvariantError("INVARIANT_CHECK_NOT_OBJECT") + required_check_keys = { + "evaluable", "passed", "impact_scope", "source_refs", "finding_ids", + "expected", "observed", "reason_codes", + } + if set(check) != required_check_keys: + raise InvariantError(f"{invariant_id}_CHECK_SHAPE_NOT_EXACT") + evaluable = check["evaluable"] + if not isinstance(evaluable, bool): + raise InvariantError(f"{invariant_id}_EVALUABLE_NOT_BOOLEAN") + if evaluable: + if not isinstance(check["passed"], bool): + raise InvariantError(f"{invariant_id}_PASSED_NOT_BOOLEAN") + if check["observed"] is None or check["passed"] != (check["observed"] == check["expected"]): + raise InvariantError(f"{invariant_id}_OBSERVATION_ORACLE_MISMATCH") + evaluation = "PASS" if check["passed"] else "FAIL" + else: + if check["passed"] not in {False, None} or check["observed"] is not None: + raise InvariantError(f"{invariant_id}_UNEVALUABLE_OBSERVATION_INVALID") + evaluation = "UNEVALUABLE" + scope = check.get("impact_scope", "OK" if evaluation == "PASS" else "REVIEW_REQUIRED") + if scope not in IMPACT_SCOPES or (evaluation == "PASS" and scope != "OK"): + raise InvariantError("INVARIANT_IMPACT_SCOPE_INVALID") + reason_values = check["reason_codes"] + source_values = check["source_refs"] + finding_values = check["finding_ids"] + for values in (reason_values, source_values, finding_values): + if (not isinstance(values, list) or len(values) != len(set(values)) + or not all(isinstance(value, str) and value for value in values)): + raise InvariantError("INVARIANT_STRING_SET_INVALID") + if not source_values: + raise InvariantError(f"{invariant_id}_SOURCE_EVIDENCE_REQUIRED") + reason_codes = sorted(set(reason_values)) + if evaluation == "PASS" and (reason_codes or finding_values): + raise InvariantError(f"{invariant_id}_PASS_FINDING_FORBIDDEN") + if evaluation != "PASS" and (not reason_codes or not finding_values): + raise InvariantError(f"{invariant_id}_{evaluation}_FINDING_REQUIRED") + results.append({ + "invariant_id": invariant_id, "evaluation_status": evaluation, + "finding_ids": sorted(set(finding_values)), "impact_scope": scope, + "source_refs": sorted(set(source_values)), + "expected": check["expected"], "observed": check["observed"], + "reason_codes": reason_codes, "validator_algorithm_id": f"S2_40::{invariant_id}::V1", + }) + return results + + +def aggregate_status(results: Sequence[Mapping[str, Any]], *, compile_mode: str | None, legal_gates: Mapping[str, bool]) -> dict[str, str]: + if [row.get("invariant_id") for row in results] != list(INVARIANT_IDS): + raise InvariantError("INVARIANT_RESULT_ORDER_OR_SET_INVALID") + for row in results: + evaluation, scope = row.get("evaluation_status"), row.get("impact_scope") + if evaluation not in {"PASS", "FAIL", "UNEVALUABLE"} or scope not in IMPACT_SCOPES: + raise InvariantError("INVARIANT_RESULT_ENUM_INVALID") + if evaluation == "PASS" and scope != "OK": + raise InvariantError("INVARIANT_PASS_SCOPE_INVALID") + scopes = {row.get("impact_scope") for row in results} + if "INCOMPLETE" in scopes: + run = "TECHNICAL_INCOMPLETE" + elif "REVIEW_REQUIRED" in scopes or any(row.get("evaluation_status") == "UNEVALUABLE" for row in results): + run = "TECHNICAL_REVIEW_REQUIRED" + else: + run = "CONSISTENT" + if run == "TECHNICAL_INCOMPLETE": + artifact, legal = "NOT_PRODUCED", "NOT_ASSESSED" + elif run == "TECHNICAL_REVIEW_REQUIRED": + artifact, legal = "TECHNICAL_REVIEW_REQUIRED", "LAWYER_REVIEW_REQUIRED" + else: + artifact = "CONSISTENT" + gates = set(legal_gates) == REQUIRED_LEGAL_GATES and all(legal_gates.values()) + all_pass = all(row.get("evaluation_status") == "PASS" for row in results) + legal = "READY_FOR_LAWYER_FILING_DECISION" if compile_mode == "PRODUCTION" and all_pass and gates else "LAWYER_REVIEW_REQUIRED" + return {"run_technical_status": run, "artifact_technical_status": artifact, "legal_readiness": legal} + + +def candidate_content_digest(material: Mapping[str, Any]) -> str: + forbidden = {"candidate_content_digest", "review_request", "review_receipt", "commit_intent", "commit_result", "run_status", "artifact_set_digest"} + if forbidden & set(material): + raise InvariantError("CANDIDATE_DIGEST_MATERIAL_CYCLE") + validate_candidate_material(material) + digest_core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + **material, + } + return hashlib.sha256(canonical_json_bytes(digest_core)).hexdigest() + + +def artifact_set_digest(rows: Sequence[Mapping[str, Any]]) -> str: + ordered = sorted(rows, key=lambda row: row["path"]) + paths = [row["path"] for row in ordered] + if len(paths) != len(set(paths)): + raise InvariantError("ARTIFACT_PATH_DUPLICATE") + for row in ordered: + if set(row) != {"path", "raw_sha256", "content_type", "size_bytes", "schema_ref"}: + raise InvariantError("ARTIFACT_ROW_SHAPE_INVALID") + _require_sha256(row["raw_sha256"], "ARTIFACT_ROW_HASH_INVALID") + if not isinstance(row["content_type"], str) or not row["content_type"]: + raise InvariantError("ARTIFACT_ROW_CONTENT_TYPE_INVALID") + if not isinstance(row["size_bytes"], int) or row["size_bytes"] < 1: + raise InvariantError("ARTIFACT_ROW_SIZE_INVALID") + if row["schema_ref"] is not None and (not isinstance(row["schema_ref"], str) or not row["schema_ref"]): + raise InvariantError("ARTIFACT_ROW_SCHEMA_REF_INVALID") + return hashlib.sha256(canonical_json_bytes(ordered)).hexdigest() + + +def derive_review_requirements(policy: Mapping[str, Any], active_tags: Sequence[str], runtime_triggers: Sequence[str]) -> list[str]: + if policy.get("status") != "APPROVED_LEGAL_CONTENT" or policy.get("execution_eligible") is not True: + return ["STANDARD_ATTORNEY_REVIEW"] + allowed_tags = set(policy["final_review_contract"]["allowed_review_tags"]) + if not set(active_tags) <= allowed_tags: + raise InvariantError("REVIEW_TAG_UNKNOWN") + required = set(policy["final_review_contract"]["base_required_receipt_types"]) + for row in policy.get("policy_rows", []): + if set(row.get("match_tags", [])) <= set(active_tags) and set(row.get("runtime_triggers", [])) <= set(runtime_triggers): + required.update(row.get("required_receipt_types", [])) + return sorted(required) + + +def review_receipt_signed_material_digest(receipt: Mapping[str, Any]) -> str: + """Hash the exact inline receipt preimage, including detached-adapter evidence.""" + keys = ( + "request_id", "candidate_content_digest", "review_subject_digest", "receipt_type", + "finding_ids", "scope_ids", "reviewer_role", "reviewer_qualification", + "issuer_id", "key_id", "signature_algorithm", + "external_verification_attestation_sha256", "issued_at", "expires_at", + "revocation_status", "cryptographic_verification_status", + "review_disposition", "change_scope", "reason_codes", + ) + if any(key not in receipt for key in keys): + raise InvariantError("REVIEW_SIGNED_MATERIAL_FIELD_MISSING") + material = ["STAGE2_S2_40_REVIEW_RECEIPT_V1", *[receipt[key] for key in keys]] + return hashlib.sha256(canonical_json_bytes(material)).hexdigest() + + +def _parse_review_time(value: Any, code: str) -> datetime: + if not isinstance(value, str): + raise InvariantError(code) + try: + parsed = datetime.fromisoformat(value.replace("Z", "+00:00")) + except ValueError as exc: + raise InvariantError(code) from exc + if parsed.tzinfo is None: + raise InvariantError(code) + return parsed.astimezone(timezone.utc) + + +def validate_review_receipt( + receipt: Mapping[str, Any], *, candidate_digest: str, + expected_review_subject_digest: str, expected_request_id: str, + expected_receipt_type: str, expected_finding_ids: Sequence[str], + expected_scope_ids: Sequence[str], now: datetime, +) -> list[str]: + """Return closed invalidity codes; an empty list means externally admissible.""" + reasons: list[str] = [] + if set(receipt) != REVIEW_RECEIPT_KEYS or receipt.get("schema_version") != "stage2_s2_40_review_receipt.v1": + return ["REVIEW_RECEIPT_CLOSED_SHAPE_INVALID"] + for key in ("receipt_id", "request_id", "receipt_type", "reviewer_role", "reviewer_qualification", "issuer_id", "key_id", "signature_algorithm"): + if not isinstance(receipt.get(key), str) or not receipt[key]: + reasons.append(f"REVIEW_RECEIPT_{key.upper()}_INVALID") + for key in ("candidate_content_digest", "review_subject_digest", "signed_material_digest", "external_verification_attestation_sha256"): + try: + _require_sha256(receipt.get(key), f"REVIEW_RECEIPT_{key.upper()}_INVALID") + except InvariantError as exc: + reasons.append(str(exc)) + for key, expected in ( + ("candidate_content_digest", candidate_digest), + ("review_subject_digest", expected_review_subject_digest), + ("request_id", expected_request_id), + ("receipt_type", expected_receipt_type), + ("finding_ids", sorted(expected_finding_ids)), + ("scope_ids", sorted(expected_scope_ids)), + ): + observed = sorted(receipt[key]) if key in {"finding_ids", "scope_ids"} and isinstance(receipt[key], list) else receipt[key] + if observed != expected: + reasons.append(f"REVIEW_RECEIPT_{key.upper()}_MISMATCH") + for key in ("finding_ids", "scope_ids", "reason_codes"): + values = receipt.get(key) + if not isinstance(values, list) or values != sorted(set(values)) or not all(isinstance(value, str) and value for value in values): + reasons.append(f"REVIEW_RECEIPT_{key.upper()}_NOT_SORTED_SET") + if receipt.get("reviewer_role") != TRUSTED_REVIEW_ROLE: + reasons.append("REVIEW_RECEIPT_ROLE_UNTRUSTED") + if receipt.get("reviewer_qualification") != TRUSTED_REVIEW_QUALIFICATION: + reasons.append("REVIEW_RECEIPT_QUALIFICATION_UNTRUSTED") + if receipt.get("issuer_id") != TRUSTED_REVIEW_ISSUER: + reasons.append("REVIEW_RECEIPT_ISSUER_UNTRUSTED") + if receipt.get("key_id") not in TRUSTED_REVIEW_KEY_IDS: + reasons.append("REVIEW_RECEIPT_KEY_UNTRUSTED") + if receipt.get("signature_algorithm") != TRUSTED_REVIEW_SIGNATURE_ALGORITHM: + reasons.append("REVIEW_RECEIPT_SIGNATURE_ALGORITHM_UNTRUSTED") + if receipt.get("cryptographic_verification_status") != "VERIFIED_BY_EXTERNAL_ADAPTER": + reasons.append("REVIEW_RECEIPT_EXTERNAL_VERIFICATION_NOT_VERIFIED") + if receipt.get("revocation_status") != "NOT_REVOKED": + reasons.append("REVIEW_RECEIPT_REVOKED_OR_UNKNOWN") + try: + issued = _parse_review_time(receipt.get("issued_at"), "REVIEW_RECEIPT_ISSUED_AT_INVALID") + expires = _parse_review_time(receipt.get("expires_at"), "REVIEW_RECEIPT_EXPIRES_AT_INVALID") + current = now.astimezone(timezone.utc) + if issued > current or expires <= current or expires <= issued: + reasons.append("REVIEW_RECEIPT_TIME_WINDOW_INVALID") + except InvariantError as exc: + reasons.append(str(exc)) + disposition, change_scope = receipt.get("review_disposition"), receipt.get("change_scope") + if disposition == "APPROVE_AS_IS" and change_scope != "NONE": + reasons.append("REVIEW_RECEIPT_APPROVAL_CHANGE_SCOPE_FORBIDDEN") + elif disposition == "CONTENT_CHANGE_REQUIRED" and change_scope not in { + "STAGE1_CONTEXT", "LEGAL_JUDGMENT", "PLAN_RULE_CALCULATION_BINDING", "DRAFTING_TEXT_ATOM", + }: + reasons.append("REVIEW_RECEIPT_CHANGE_SCOPE_INVALID") + elif disposition not in {"APPROVE_AS_IS", "CONTENT_CHANGE_REQUIRED"}: + reasons.append("REVIEW_RECEIPT_DISPOSITION_INVALID") + try: + expected_signed = review_receipt_signed_material_digest(receipt) + if receipt.get("signed_material_digest") != expected_signed: + reasons.append("REVIEW_RECEIPT_SIGNED_MATERIAL_MISMATCH") + except InvariantError as exc: + reasons.append(str(exc)) + return sorted(set(reasons)) + + +def transition_review_state( + *, candidate_digest: str, required_receipt_types: Sequence[str], + receipts: Sequence[Mapping[str, Any]], expected_review_subject_digest: str, + expected_request_ids: Mapping[str, str], expected_finding_ids: Sequence[str], + expected_scope_ids: Sequence[str], now: datetime, +) -> dict[str, Any]: + _require_sha256(candidate_digest, "REVIEW_CANDIDATE_DIGEST_INVALID") + if len(required_receipt_types) != len(set(required_receipt_types)): + raise InvariantError("REVIEW_REQUIRED_TYPE_DUPLICATE") + _require_sha256(expected_review_subject_digest, "REVIEW_SUBJECT_DIGEST_INVALID") + if set(expected_request_ids) != set(required_receipt_types) or any( + not isinstance(value, str) or not value for value in expected_request_ids.values() + ): + raise InvariantError("REVIEW_REQUEST_ID_MAP_INVALID") + valid: dict[str, Mapping[str, Any]] = {} + invalid: list[str] = [] + invalid_reasons: dict[str, list[str]] = {} + seen_receipt_ids: set[str] = set() + for receipt in receipts: + receipt_id = receipt.get("receipt_id") + receipt_type = receipt.get("receipt_type") + if not isinstance(receipt_id, str) or not receipt_id or receipt_id in seen_receipt_ids: + raise InvariantError("REVIEW_RECEIPT_ID_MISSING_OR_DUPLICATE") + seen_receipt_ids.add(receipt_id) + reasons = validate_review_receipt( + receipt, candidate_digest=candidate_digest, + expected_review_subject_digest=expected_review_subject_digest, + expected_request_id=expected_request_ids.get(str(receipt_type), ""), + expected_receipt_type=str(receipt_type), + expected_finding_ids=expected_finding_ids, expected_scope_ids=expected_scope_ids, + now=now, + ) + if receipt_type not in required_receipt_types: + reasons.append("REVIEW_RECEIPT_TYPE_NOT_REQUIRED") + if reasons: + invalid.append(receipt_id) + invalid_reasons[receipt_id] = sorted(set(reasons)) + else: + if receipt_type in valid: + raise InvariantError("REVIEW_RECEIPT_TYPE_DUPLICATE") + valid[receipt_type] = receipt + routes = { + "STAGE1_CONTEXT": (0, "RESTART_FROM_S2_00"), + "LEGAL_JUDGMENT": (1, "RESTART_FROM_S2_10"), + "PLAN_RULE_CALCULATION_BINDING": (2, "RESTART_FROM_S2_20"), + "DRAFTING_TEXT_ATOM": (3, "RESTART_FROM_S2_30"), + } + changed_scopes = [receipt["change_scope"] for receipt in valid.values() if receipt["review_disposition"] == "CONTENT_CHANGE_REQUIRED"] + if changed_scopes: + earliest = min(changed_scopes, key=lambda scope: routes[scope][0]) + return {"workflow_phase": "SUPERSEDED", "route": routes[earliest][1], "invalid_receipt_ids": sorted(invalid), "invalid_receipt_reasons": invalid_reasons} + missing = sorted(set(required_receipt_types) - set(valid)) + if missing or invalid: + return {"workflow_phase": "AWAITING_EXTERNAL_REVIEW", "route": "WAIT_EXTERNAL_REVIEW", "missing_receipt_types": missing, "invalid_receipt_ids": sorted(invalid), "invalid_receipt_reasons": invalid_reasons} + if any(receipt.get("review_disposition") != "APPROVE_AS_IS" for receipt in valid.values()): + raise InvariantError("REVIEW_DISPOSITION_INVALID") + return {"workflow_phase": "READY_TO_COMMIT", "route": "CONTINUE_TO_COMMIT", "invalid_receipt_ids": [], "invalid_receipt_reasons": {}} + + +def commit_write_order(final_paths: Sequence[str]) -> list[str]: + if len(final_paths) != len(set(final_paths)): + raise InvariantError("COMMIT_TARGET_DUPLICATE") + if any(not path.startswith("final/") or ".." in path.split("/") for path in final_paths): + raise InvariantError("COMMIT_TARGET_OUTSIDE_FINAL_ROOT") + return ["commit/commit_intent.json", *sorted(final_paths), "commit/stage2_commit_result.json", "control/run_status.json"] + + +__all__ = ["INVARIANT_IDS", "InvariantError", "JsonSchemaValidationError", "aggregate_status", "artifact_set_digest", "candidate_content_digest", "commit_write_order", "derive_review_requirements", "review_receipt_signed_material_digest", "review_subject_digest", "run_invariants", "transition_review_state", "validate_candidate_material", "validate_jsonschema_instance", "validate_readback_rows", "validate_reference_closure", "validate_review_receipt", "validate_status_only_paths"] diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/deployment.schema.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/deployment.schema.json index e99528d9..c993cd22 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/deployment.schema.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/deployment.schema.json @@ -29,6 +29,14 @@ {"$ref": "#/$defs/s2_20_request"}, {"$ref": "#/$defs/s2_20_execution_receipt"}, {"$ref": "#/$defs/s2_20_outer_execution_receipt"}, + {"$ref": "#/$defs/s2_40_request"}, + {"$ref": "#/$defs/s2_40_host_cas_receipt"}, + {"$ref": "#/$defs/s2_40_code_executor_binding"}, + {"$ref": "#/$defs/s2_40_inline_code_receipt"}, + {"$ref": "#/$defs/s2_40_execution_receipt"}, + {"$ref": "#/$defs/s2_40_outer_execution_receipt"}, + {"$ref": "#/$defs/s2_40_commit_intent"}, + {"$ref": "#/$defs/s2_40_commit_result"}, {"$ref": "#/$defs/stage2_deterministic_admission_receipt"}, {"$ref": "#/$defs/code_executor_binding"}, {"$ref": "#/$defs/inline_code_receipt"}, @@ -469,10 +477,25 @@ "host_cas_receipt_sha256": {"$ref": "#/$defs/sha256"} } }, + "s2_40_artifact_digest_row": { + "type": "object", + "additionalProperties": false, + "required": ["path", "raw_sha256", "content_type", "size_bytes", "schema_ref"], + "properties": { + "path": { + "type": "string", + "pattern": "^stage2_runs/by-binding/[a-f0-9]{64}/final/(?!.*(?:^|/)\\.\\.(?:/|$))[^\\u0000]+$" + }, + "raw_sha256": {"$ref": "#/$defs/sha256"}, + "content_type": {"$ref": "#/$defs/nonempty_string"}, + "size_bytes": {"type": "integer", "minimum": 1}, + "schema_ref": {"type": ["string", "null"]} + } + }, "stage2_deterministic_admission_receipt": { "type": "object", "additionalProperties": false, - "required": ["schema_version", "parent_release_sha256", "executor_binding_sha256", "present_deterministic_stage_ids", "stage_receipts", "embedded_task_admissions", "admission_status", "signature", "signature_verification_status", "signed_payload_sha256", "backend_capability_receipt_sha256"], + "required": ["schema_version", "parent_release_sha256", "executor_binding_sha256", "present_deterministic_stage_ids", "stage_receipts", "embedded_task_admissions", "admission_status", "external_trust_verified", "signature", "signature_verification_status", "signed_payload_sha256", "backend_capability_receipt_sha256"], "properties": { "schema_version": {"const": "stage2_deterministic_admission_receipt.v1"}, "parent_release_sha256": {"$ref": "#/$defs/sha256"}, @@ -498,6 +521,7 @@ } }, "admission_status": {"enum": ["PENDING", "CANARY_ADMITTED", "PRODUCTION_ADMITTED"]}, + "external_trust_verified": {"type": "boolean"}, "signature": {"type": "string", "minLength": 1}, "signature_verification_status": {"enum": ["PENDING_EXTERNAL_SIGNATURE", "BACKEND_VERIFIED"]}, "signed_payload_sha256": {"$ref": "#/$defs/bindable_sha256"}, @@ -508,6 +532,7 @@ "if": {"properties": {"admission_status": {"const": "PENDING"}}, "required": ["admission_status"]}, "then": { "properties": { + "external_trust_verified": {"const": false}, "signature": {"const": "PENDING_EXTERNAL_SIGNATURE"}, "signature_verification_status": {"const": "PENDING_EXTERNAL_SIGNATURE"}, "signed_payload_sha256": {"const": "PENDING_SEQUENTIAL_BIND"}, @@ -519,6 +544,7 @@ "if": {"properties": {"admission_status": {"enum": ["CANARY_ADMITTED", "PRODUCTION_ADMITTED"]}}, "required": ["admission_status"]}, "then": { "properties": { + "external_trust_verified": {"const": true}, "signature": {"type": "string", "minLength": 16, "not": {"pattern": "^PENDING"}}, "signature_verification_status": {"const": "BACKEND_VERIFIED"}, "signed_payload_sha256": {"$ref": "#/$defs/sha256"}, @@ -1769,6 +1795,210 @@ } ] }, + "s2_40_request": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", "request_id", "candidate_attempt_id", "run_binding_digest", + "user_identity_hash", "workspace_identity_hash", "stage2_run_root_ref", "entry_route", + "compile_mode", "requested_transition", "expected_previous_run_status_sha256", + "expected_candidate_content_digest", "expected_ingress_status_sha256", + "expected_s2_10_publish_status_sha256", "expected_plan_publish_status_sha256", + "expected_s2_30_publish_status_sha256", "expected_s2_30_artifact_manifest_sha256", + "expected_parent_stage2_release_sha256", "expected_s2_40_agent_sha256", + "expected_s2_40_executor_binding_sha256", "expected_s2_40_inline_code_receipt_sha256", + "host_cas_receipt_ref", "host_cas_receipt_sha256", "detached_admission_receipt_ref", + "detached_admission_receipt_sha256", "outer_execution_receipt_target_ref", + "review_receipt_refs" + ], + "properties": { + "schema_version": {"const": "stage2_s2_40_request.v1"}, + "request_id": {"$ref": "#/$defs/nonempty_string"}, + "candidate_attempt_id": {"$ref": "#/$defs/nonempty_string"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "user_identity_hash": {"$ref": "#/$defs/sha256"}, + "workspace_identity_hash": {"$ref": "#/$defs/sha256"}, + "stage2_run_root_ref": {"type": "string", "pattern": "^stage2_runs/by-binding/[a-f0-9]{64}$"}, + "entry_route": {"enum": ["TO_S2_40", "TO_S2_40_STATUS_ONLY"]}, + "compile_mode": {"type": ["string", "null"], "enum": [null, "STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"]}, + "requested_transition": {"enum": ["FREEZE", "RESUME"]}, + "expected_previous_run_status_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "expected_candidate_content_digest": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "expected_ingress_status_sha256": {"$ref": "#/$defs/sha256"}, + "expected_s2_10_publish_status_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "expected_plan_publish_status_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "expected_s2_30_publish_status_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "expected_s2_30_artifact_manifest_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "expected_parent_stage2_release_sha256": {"$ref": "#/$defs/sha256"}, + "expected_s2_40_agent_sha256": {"$ref": "#/$defs/sha256"}, + "expected_s2_40_executor_binding_sha256": {"$ref": "#/$defs/sha256"}, + "expected_s2_40_inline_code_receipt_sha256": {"$ref": "#/$defs/sha256"}, + "host_cas_receipt_ref": {"type": "string", "pattern": "^stage2_control/host_cas/[a-f0-9]{64}/S2_40/[^/]+/(?:FREEZE|RESUME)\\.json$"}, + "host_cas_receipt_sha256": {"$ref": "#/$defs/sha256"}, + "detached_admission_receipt_ref": {"const": "Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json"}, + "detached_admission_receipt_sha256": {"$ref": "#/$defs/bindable_sha256"}, + "outer_execution_receipt_target_ref": {"type": "string", "pattern": "^stage2_runs/by-binding/[a-f0-9]{64}/control/s2_40_outer_execution_receipt\\.json$"}, + "review_receipt_refs": { + "type": "array", + "items": {"type": "string", "pattern": "^stage2_runs/by-binding/[a-f0-9]{64}/review/review_receipts/[^/]+\\.json$"}, + "maxItems": 64, + "uniqueItems": true + } + }, + "allOf": [ + { + "if": {"properties": {"entry_route": {"const": "TO_S2_40_STATUS_ONLY"}}, "required": ["entry_route"]}, + "then": {"properties": {"compile_mode": {"const": null}, "requested_transition": {"const": "FREEZE"}, "expected_previous_run_status_sha256": {"const": null}, "expected_candidate_content_digest": {"const": null}, "expected_s2_10_publish_status_sha256": {"const": null}, "expected_plan_publish_status_sha256": {"const": null}, "expected_s2_30_publish_status_sha256": {"const": null}, "expected_s2_30_artifact_manifest_sha256": {"const": null}, "review_receipt_refs": {"maxItems": 0}}} + }, + { + "if": {"properties": {"entry_route": {"const": "TO_S2_40"}, "requested_transition": {"const": "FREEZE"}}, "required": ["entry_route", "requested_transition"]}, + "then": {"properties": {"compile_mode": {"enum": ["STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"]}, "expected_candidate_content_digest": {"const": null}, "expected_previous_run_status_sha256": {"const": null}, "expected_s2_10_publish_status_sha256": {"$ref": "#/$defs/sha256"}, "expected_plan_publish_status_sha256": {"$ref": "#/$defs/sha256"}, "expected_s2_30_publish_status_sha256": {"$ref": "#/$defs/sha256"}, "expected_s2_30_artifact_manifest_sha256": {"$ref": "#/$defs/sha256"}, "review_receipt_refs": {"maxItems": 0}}} + }, + { + "if": {"properties": {"requested_transition": {"const": "RESUME"}}, "required": ["requested_transition"]}, + "then": {"properties": {"entry_route": {"const": "TO_S2_40"}, "compile_mode": {"enum": ["STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"]}, "expected_candidate_content_digest": {"$ref": "#/$defs/sha256"}, "expected_previous_run_status_sha256": {"$ref": "#/$defs/sha256"}, "expected_s2_10_publish_status_sha256": {"$ref": "#/$defs/sha256"}, "expected_plan_publish_status_sha256": {"$ref": "#/$defs/sha256"}, "expected_s2_30_publish_status_sha256": {"$ref": "#/$defs/sha256"}, "expected_s2_30_artifact_manifest_sha256": {"$ref": "#/$defs/sha256"}, "review_receipt_refs": {"minItems": 1}}} + } + ] + }, + "s2_40_host_cas_receipt": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "run_binding_digest", "stage_id", "candidate_attempt_id", "requested_transition", "expected_previous_run_status_sha256", "lease_id", "lease_status", "issued_at", "expires_at", "signature_attestation"], + "properties": { + "schema_version": {"const": "stage2_s2_40_host_cas_receipt.v1"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, "stage_id": {"const": "S2_40"}, + "candidate_attempt_id": {"$ref": "#/$defs/nonempty_string"}, "requested_transition": {"enum": ["FREEZE", "RESUME"]}, + "expected_previous_run_status_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "lease_id": {"$ref": "#/$defs/nonempty_string"}, "lease_status": {"const": "ACQUIRED"}, + "issued_at": {"type": "string", "format": "date-time"}, "expires_at": {"type": "string", "format": "date-time"}, + "signature_attestation": {"$ref": "#/$defs/sha256"} + } + }, + "s2_40_code_executor_binding": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "stage_id", "execution_unit", "agent_path", "agent_sha256", "inline_code_sha256", "workflow_path", "workflow_sha256", "request_path", "timeout_seconds", "requirements", "network", "egress_profile_id", "fallback_allowed", "binding_digest"], + "properties": { + "schema_version": {"const": "stage2_s2_40_code_executor_binding.v1"}, "stage_id": {"const": "S2_40"}, + "execution_unit": {"const": "Task_S2_40_deterministic_finalizer"}, "agent_path": {"const": "agent_scripts/Stage_2_S2_40.yml"}, + "agent_sha256": {"$ref": "#/$defs/bindable_sha256"}, "inline_code_sha256": {"$ref": "#/$defs/bindable_sha256"}, + "workflow_path": {"const": "workflows/S2_40_final_review_render_and_commit.yml"}, "workflow_sha256": {"$ref": "#/$defs/bindable_sha256"}, + "request_path": {"const": "stage2_control/s2_40_request.json"}, "timeout_seconds": {"const": 300}, + "requirements": {"const": "httpx==0.28.1"}, "network": {"const": "agent-network"}, + "egress_profile_id": {"const": "LOCALDOCS_EXACT_BINARY_ONLY_V1"}, "fallback_allowed": {"const": false}, + "binding_digest": {"$ref": "#/$defs/bindable_sha256"} + } + }, + "s2_40_inline_code_receipt": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "workflow_id", "build_kind", "source_of_truth", "authoring_rewritten", "authoring", "deployment_projection", "canonical_code", "expected_parent_stage2_release_sha256", "full_code_mirrors", "task_contract", "parity_status"], + "properties": { + "schema_version": {"const": "stage2_s2_40_inline_code_receipt.v1"}, + "workflow_id": {"const": "S2_40"}, + "build_kind": {"const": "OFFLINE_AUTHORING_PROJECTION"}, + "source_of_truth": {"const": "Stage_2_S2_40.yml"}, + "authoring_rewritten": {"const": false}, + "authoring": { + "type": "object", "additionalProperties": false, + "required": ["path", "sha256", "size_bytes", "unique_key_parse"], + "properties": {"path": {"const": "Stage_2_S2_40.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_40.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", "expected_parent_stage2_release_sha256", "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"}, + "expected_parent_stage2_release_sha256": {"$ref": "#/$defs/sha256"}, "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"} + } + }, + "expected_parent_stage2_release_sha256": {"$ref": "#/$defs/sha256"}, + "full_code_mirrors": { + "type": "array", "minItems": 2, "maxItems": 2, + "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_40_commit.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_40_commit.txt"}, "sha256": {"$ref": "#/$defs/sha256"}, "size_bytes": {"type": "integer", "minimum": 1}, "byte_identical_to_canonical_code": {"const": true}}} + ], "items": false + }, + "task_contract": { + "type": "object", "additionalProperties": false, + "required": ["agent", "authoring_rewritten", "canonical_task_semantics_sha256", "code_mirrors_byte_identical", "exactly_one_code_executor_run_code", "exactly_one_stage", "exactly_one_task", "mcp_servers", "projection_byte_identical_to_authoring", "stage", "task", "task_procedure"], + "properties": { + "agent": {"type": "object"}, "authoring_rewritten": {"const": false}, "canonical_task_semantics_sha256": {"$ref": "#/$defs/sha256"}, "code_mirrors_byte_identical": {"const": true}, "exactly_one_code_executor_run_code": {"const": true}, "exactly_one_stage": {"const": true}, "exactly_one_task": {"const": true}, "mcp_servers": {"type": "object"}, "projection_byte_identical_to_authoring": {"const": true}, "stage": {"type": "object"}, "task": {"type": "object"}, "task_procedure": {"type": "object"} + } + }, + "parity_status": {"const": "PASS"} + } + }, + "s2_40_execution_receipt": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "ok", "workflow_id", "request_id", "run_binding_digest", "candidate_attempt_id", "requested_transition", "workflow_phase", "route", "candidate_content_digest", "run_status_path", "run_status_sha256", "error"], + "properties": { + "schema_version": {"const": "stage2_s2_40_execution_receipt.v1"}, "ok": {"type": "boolean"}, "workflow_id": {"const": "S2_40"}, "request_id": {"$ref": "#/$defs/nonempty_string"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, "candidate_attempt_id": {"$ref": "#/$defs/nonempty_string"}, "requested_transition": {"enum": ["FREEZE", "RESUME"]}, + "workflow_phase": {"enum": ["CANDIDATE_FROZEN", "AWAITING_EXTERNAL_REVIEW", "READY_TO_COMMIT", "COMMITTED", "SUPERSEDED", "DIAGNOSTIC_ONLY"]}, + "route": {"enum": ["STOP_TECHNICAL_INCOMPLETE", "CHECKPOINT_FROZEN", "WAIT_EXTERNAL_REVIEW", "CONTINUE_TO_COMMIT", "RESTART_FROM_S2_00", "RESTART_FROM_S2_10", "RESTART_FROM_S2_20", "RESTART_FROM_S2_30", "PACKAGE_COMMITTED"]}, + "candidate_content_digest": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "run_status_path": {"oneOf": [{"type": "string", "pattern": "^stage2_runs/by-binding/[a-f0-9]{64}/control/run_status\\.json$"}, {"type": "null"}]}, + "run_status_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, "error": {"type": ["object", "null"]} + }, + "allOf": [ + { + "if": {"properties": {"ok": {"const": true}}, "required": ["ok"]}, + "then": {"properties": {"run_status_path": {"type": "string", "pattern": "^stage2_runs/by-binding/[a-f0-9]{64}/control/run_status\\.json$"}, "run_status_sha256": {"$ref": "#/$defs/sha256"}, "error": {"type": "null"}}}, + "else": {"properties": {"error": {"type": "object"}}} + }, + { + "oneOf": [ + {"properties": {"run_status_path": {"type": "null"}, "run_status_sha256": {"type": "null"}}}, + {"properties": {"run_status_path": {"type": "string", "pattern": "^stage2_runs/by-binding/[a-f0-9]{64}/control/run_status\\.json$"}, "run_status_sha256": {"$ref": "#/$defs/sha256"}}} + ] + } + ] + }, + "s2_40_outer_execution_receipt": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "workflow_id", "request_id", "run_binding_digest", "candidate_attempt_id", "requested_transition", "agent_sha256", "inline_code_sha256", "binding_sha256", "host_cas_receipt_sha256", "detached_admission_receipt_sha256", "workspace_isolation_status", "outer_result_status", "inner_result_sha256", "issued_at", "signature_attestation"], + "properties": { + "schema_version": {"const": "stage2_s2_40_outer_execution_receipt.v1"}, "workflow_id": {"const": "S2_40"}, "request_id": {"$ref": "#/$defs/nonempty_string"}, "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "candidate_attempt_id": {"$ref": "#/$defs/nonempty_string"}, "requested_transition": {"enum": ["FREEZE", "RESUME"]}, + "agent_sha256": {"$ref": "#/$defs/sha256"}, "inline_code_sha256": {"$ref": "#/$defs/sha256"}, + "binding_sha256": {"$ref": "#/$defs/sha256"}, "host_cas_receipt_sha256": {"$ref": "#/$defs/sha256"}, "detached_admission_receipt_sha256": {"$ref": "#/$defs/sha256"}, + "workspace_isolation_status": {"enum": ["VERIFIED", "FAILED"]}, "outer_result_status": {"enum": ["SUCCESS", "FAILED"]}, + "inner_result_sha256": {"$ref": "#/$defs/sha256"}, "issued_at": {"type": "string", "format": "date-time"}, + "signature_attestation": {"$ref": "#/$defs/sha256"} + } + }, + "s2_40_commit_intent": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "producer_id", "run_binding_digest", "candidate_content_digest", "candidate_attempt_id", "candidate_manifest_core_sha256", "validation_report_sha256", "review_subject_digest", "review_receipt_sha256s", "stage2_package_sha256", "expected_artifacts", "previous_run_status_sha256", "request_sha256", "host_cas_receipt_sha256", "intent_digest"], + "properties": { + "schema_version": {"const": "stage2_s2_40_commit_intent.v1"}, "producer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "candidate_attempt_id": {"$ref": "#/$defs/nonempty_string"}, + "candidate_manifest_core_sha256": {"$ref": "#/$defs/sha256"}, "validation_report_sha256": {"$ref": "#/$defs/sha256"}, "review_subject_digest": {"$ref": "#/$defs/sha256"}, + "review_receipt_sha256s": {"type": "array", "items": {"$ref": "#/$defs/sha256"}, "uniqueItems": true}, "stage2_package_sha256": {"$ref": "#/$defs/sha256"}, + "expected_artifacts": {"type": "array", "items": {"$ref": "#/$defs/s2_40_artifact_digest_row"}, "minItems": 8}, + "previous_run_status_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "request_sha256": {"$ref": "#/$defs/sha256"}, "host_cas_receipt_sha256": {"$ref": "#/$defs/sha256"}, + "intent_digest": {"$ref": "#/$defs/sha256"} + } + }, + "s2_40_commit_result": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "producer_id", "run_binding_digest", "candidate_content_digest", "commit_intent_sha256", "artifact_rows", "artifact_set_digest", "readback_status", "conflicting_target_count", "missing_target_count_after_write", "commit_result_digest"], + "properties": { + "schema_version": {"const": "stage2_s2_40_commit_result.v1"}, "producer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "commit_intent_sha256": {"$ref": "#/$defs/sha256"}, + "artifact_rows": {"type": "array", "items": {"$ref": "#/$defs/s2_40_artifact_digest_row"}, "minItems": 8}, + "artifact_set_digest": {"$ref": "#/$defs/sha256"}, "readback_status": {"const": "PASS"}, "conflicting_target_count": {"const": 0}, "missing_target_count_after_write": {"const": 0}, + "commit_result_digest": {"$ref": "#/$defs/sha256"} + } + }, "loader_receipt": { "type": "object", "additionalProperties": false, diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/draft_atoms.schema.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/draft_atoms.schema.json index 0b95a2aa..b49decbb 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/draft_atoms.schema.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/draft_atoms.schema.json @@ -10,6 +10,11 @@ {"$ref": "#/$defs/materialized_group_item"}, {"$ref": "#/$defs/raw_joint_draft_output"}, {"$ref": "#/$defs/canonical_draft_atom"}, + {"$ref": "#/$defs/draft_part"}, + {"$ref": "#/$defs/issue_patch_part"}, + {"$ref": "#/$defs/worknote_part"}, + {"$ref": "#/$defs/usage_part"}, + {"$ref": "#/$defs/part_manifest_core"}, {"$ref": "#/$defs/item_receipt"}, {"$ref": "#/$defs/canary_authorization"}, {"$ref": "#/$defs/cache_owner_completion_receipt"}, @@ -1398,6 +1403,285 @@ "canonical_atom_sha256": {"$ref": "#/$defs/sha256"} } }, + "execution_provenance": { + "type": "object", + "additionalProperties": false, + "required": [ + "compile_mode", + "parent_stage2_release_sha256", + "s2_30_release_sha256", + "s2_30_agent_sha256", + "s2_30_binding_sha256", + "p00_prompt_sha256", + "p30_prompt_sha256", + "p31_rule_and_pack_sha256", + "p32_common_authority_sha256", + "s30_group_slice_sha256", + "s2_30_producer_contract_digest" + ], + "properties": { + "compile_mode": {"$ref": "#/$defs/compile_mode"}, + "parent_stage2_release_sha256": {"$ref": "#/$defs/sha256"}, + "s2_30_release_sha256": {"$ref": "#/$defs/sha256"}, + "s2_30_agent_sha256": {"$ref": "#/$defs/sha256"}, + "s2_30_binding_sha256": {"$ref": "#/$defs/sha256"}, + "p00_prompt_sha256": {"$ref": "#/$defs/sha256"}, + "p30_prompt_sha256": {"$ref": "#/$defs/sha256"}, + "p31_rule_and_pack_sha256": {"$ref": "#/$defs/sha256"}, + "p32_common_authority_sha256": {"$ref": "#/$defs/sha256"}, + "s30_group_slice_sha256": {"$ref": "#/$defs/sha256"}, + "s2_30_producer_contract_digest": {"$ref": "#/$defs/sha256"} + } + }, + "common_publish_provenance": { + "type": "object", + "additionalProperties": false, + "required": [ + "compile_mode", + "parent_stage2_release_sha256", + "s2_30_release_sha256", + "s2_30_agent_sha256", + "s2_30_binding_sha256", + "p00_prompt_sha256", + "p30_prompt_sha256", + "s2_30_producer_contract_digest" + ], + "properties": { + "compile_mode": {"$ref": "#/$defs/compile_mode"}, + "parent_stage2_release_sha256": {"$ref": "#/$defs/sha256"}, + "s2_30_release_sha256": {"$ref": "#/$defs/sha256"}, + "s2_30_agent_sha256": {"$ref": "#/$defs/sha256"}, + "s2_30_binding_sha256": {"$ref": "#/$defs/sha256"}, + "p00_prompt_sha256": {"$ref": "#/$defs/sha256"}, + "p30_prompt_sha256": {"$ref": "#/$defs/sha256"}, + "s2_30_producer_contract_digest": {"$ref": "#/$defs/sha256"} + } + }, + "draft_part": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "claim_group_id", + "provenance", + "source_plan_sha256", + "drafting_permission", + "canonical_atoms", + "atomic_claim_coverage", + "part_sha256" + ], + "properties": { + "schema_version": {"const": "stage2_s2_30_draft_part.v1"}, + "claim_group_id": {"$ref": "#/$defs/claim_group_id"}, + "provenance": {"$ref": "#/$defs/execution_provenance"}, + "source_plan_sha256": {"$ref": "#/$defs/sha256"}, + "drafting_permission": {"$ref": "#/$defs/drafting_permission"}, + "canonical_atoms": { + "type": "array", + "items": {"$ref": "#/$defs/canonical_draft_atom"}, + "minItems": 1 + }, + "atomic_claim_coverage": { + "type": "array", + "items": {"$ref": "#/$defs/persisted_atomic_claim_coverage"}, + "minItems": 1 + }, + "part_sha256": {"$ref": "#/$defs/sha256"} + } + }, + "persisted_atomic_claim_coverage": { + "type": "object", + "additionalProperties": false, + "required": [ + "atomic_claim_id", + "relief_atom_local_refs", + "cause_atom_local_refs", + "alignment_signature", + "coverage_status", + "missing_reason_codes" + ], + "properties": { + "atomic_claim_id": {"$ref": "#/$defs/atomic_claim_id"}, + "relief_atom_local_refs": { + "type": "array", + "items": {"$ref": "#/$defs/atom_id"}, + "uniqueItems": true + }, + "cause_atom_local_refs": { + "type": "array", + "items": {"$ref": "#/$defs/atom_id"}, + "uniqueItems": true + }, + "alignment_signature": {"$ref": "#/$defs/sha256"}, + "coverage_status": {"enum": ["COMPLETE", "INCOMPLETE"]}, + "missing_reason_codes": {"$ref": "#/$defs/string_set"} + } + }, + "issue_patch_part": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "claim_group_id", + "provenance", + "source_plan_sha256", + "review_flags", + "missing_inputs", + "adverse_fact_rows", + "part_sha256" + ], + "properties": { + "schema_version": {"const": "stage2_s2_30_issue_patch_part.v1"}, + "claim_group_id": {"$ref": "#/$defs/claim_group_id"}, + "provenance": {"$ref": "#/$defs/execution_provenance"}, + "source_plan_sha256": {"$ref": "#/$defs/sha256"}, + "review_flags": {"$ref": "#/$defs/string_set"}, + "missing_inputs": {"$ref": "#/$defs/string_set"}, + "adverse_fact_rows": { + "type": "array", + "items": {"$ref": "#/$defs/adverse_fact_row"} + }, + "part_sha256": {"$ref": "#/$defs/sha256"} + } + }, + "worknote_part": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "claim_group_id", + "provenance", + "source_plan_sha256", + "worknote_atom_ids", + "review_flags", + "missing_inputs", + "part_sha256" + ], + "properties": { + "schema_version": {"const": "stage2_s2_30_worknote_part.v1"}, + "claim_group_id": {"$ref": "#/$defs/claim_group_id"}, + "provenance": {"$ref": "#/$defs/execution_provenance"}, + "source_plan_sha256": {"$ref": "#/$defs/sha256"}, + "worknote_atom_ids": { + "type": "array", + "items": {"$ref": "#/$defs/atom_id"}, + "uniqueItems": true + }, + "review_flags": {"$ref": "#/$defs/string_set"}, + "missing_inputs": {"$ref": "#/$defs/string_set"}, + "part_sha256": {"$ref": "#/$defs/sha256"} + } + }, + "usage_part": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "claim_group_id", + "provenance", + "request_id", + "model", + "reasoning_effort", + "verbosity", + "endpoint", + "input_tokens", + "cached_input_tokens", + "output_tokens", + "usage_observed", + "part_sha256" + ], + "properties": { + "schema_version": {"const": "stage2_s2_30_usage_part.v1"}, + "claim_group_id": {"$ref": "#/$defs/claim_group_id"}, + "provenance": {"$ref": "#/$defs/execution_provenance"}, + "request_id": {"$ref": "#/$defs/nonempty_string"}, + "model": {"const": "gpt-5.6-sol"}, + "reasoning_effort": {"const": "xhigh"}, + "verbosity": {"const": "medium"}, + "endpoint": {"const": "responses"}, + "input_tokens": {"type": "integer", "minimum": 0}, + "cached_input_tokens": {"type": "integer", "minimum": 0}, + "output_tokens": {"type": "integer", "minimum": 0}, + "usage_observed": {"type": "boolean"}, + "part_sha256": {"$ref": "#/$defs/sha256"} + } + }, + "part_manifest_row": { + "type": "object", + "additionalProperties": false, + "required": [ + "claim_group_id", + "part_family", + "path", + "sha256", + "schema_ref" + ], + "properties": { + "claim_group_id": {"$ref": "#/$defs/claim_group_id"}, + "part_family": {"enum": ["DRAFT_PART", "ISSUE_PATCH", "WORKNOTE_PART", "USAGE_PART"]}, + "path": {"$ref": "#/$defs/artifact_path"}, + "sha256": {"$ref": "#/$defs/sha256"}, + "schema_ref": { + "enum": [ + "schemas/draft_atoms.schema.json#/$defs/draft_part", + "schemas/draft_atoms.schema.json#/$defs/issue_patch_part", + "schemas/draft_atoms.schema.json#/$defs/worknote_part", + "schemas/draft_atoms.schema.json#/$defs/usage_part" + ] + } + } + }, + "part_manifest_core": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "request_id", + "run_binding_digest", + "provenance", + "expected_claim_group_ids", + "part_rows", + "part_manifest_core_sha256" + ], + "properties": { + "schema_version": {"const": "stage2_s2_30_part_manifest_core.v1"}, + "request_id": {"$ref": "#/$defs/nonempty_string"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "provenance": {"$ref": "#/$defs/common_publish_provenance"}, + "expected_claim_group_ids": { + "type": "array", + "items": {"$ref": "#/$defs/claim_group_id"}, + "minItems": 1, + "uniqueItems": true + }, + "part_rows": { + "type": "array", + "items": {"$ref": "#/$defs/part_manifest_row"}, + "minItems": 4 + }, + "part_manifest_core_sha256": {"$ref": "#/$defs/sha256"} + }, + "$comment": "Receipt-free by construction: item/cohort receipt paths or hashes must not appear in this core." + }, + "receipt_ref": { + "type": "object", + "additionalProperties": false, + "required": ["path", "sha256"], + "properties": { + "path": {"$ref": "#/$defs/artifact_path"}, + "sha256": {"$ref": "#/$defs/sha256"} + } + }, + "item_receipt_ref": { + "type": "object", + "additionalProperties": false, + "required": ["claim_group_id", "path", "sha256"], + "properties": { + "claim_group_id": {"$ref": "#/$defs/claim_group_id"}, + "path": {"$ref": "#/$defs/artifact_path"}, + "sha256": {"$ref": "#/$defs/sha256"} + } + }, "item_receipt": { "type": "object", "additionalProperties": false, @@ -1408,11 +1692,12 @@ "cohort_id", "attempt_no", "claim_group_id", + "provenance", "dispatch_sha256", "raw_model_output_sha256", "source_plan_sha256", "canonical_atom_ids", - "artifact_manifest_sha256", + "part_manifest_core_sha256", "validation_status", "persistence_status", "read_back_verified", @@ -1425,6 +1710,7 @@ "cohort_id": {"$ref": "#/$defs/nonempty_string"}, "attempt_no": {"type": "integer", "minimum": 1, "maximum": 2}, "claim_group_id": {"$ref": "#/$defs/claim_group_id"}, + "provenance": {"$ref": "#/$defs/execution_provenance"}, "dispatch_sha256": {"$ref": "#/$defs/sha256"}, "raw_model_output_sha256": {"$ref": "#/$defs/sha256"}, "source_plan_sha256": {"$ref": "#/$defs/sha256"}, @@ -1433,7 +1719,7 @@ "items": {"$ref": "#/$defs/atom_id"}, "uniqueItems": true }, - "artifact_manifest_sha256": {"$ref": "#/$defs/sha256"}, + "part_manifest_core_sha256": {"$ref": "#/$defs/sha256"}, "validation_status": {"enum": ["PASS", "FAIL"]}, "persistence_status": {"enum": ["PUBLISHED", "IDEMPOTENT_BYTE_IDENTICAL", "NOT_WRITTEN", "CONFLICT"]}, "read_back_verified": {"type": "boolean"}, @@ -1450,6 +1736,8 @@ "cohort_id", "dispatch_phase", "attempt_no", + "provenance", + "part_manifest_core_sha256", "input_claim_group_ids", "valid_claim_group_ids", "repair_required_claim_group_ids", @@ -1466,6 +1754,8 @@ "cohort_id": {"$ref": "#/$defs/nonempty_string"}, "dispatch_phase": {"enum": ["CACHE_OWNER_SINGLETON", "FOLLOWER_BATCH"]}, "attempt_no": {"type": "integer", "minimum": 1, "maximum": 2}, + "provenance": {"$ref": "#/$defs/common_publish_provenance"}, + "part_manifest_core_sha256": {"$ref": "#/$defs/sha256"}, "input_claim_group_ids": { "type": "array", "items": {"$ref": "#/$defs/claim_group_id"}, @@ -1553,11 +1843,16 @@ "run_binding_digest", "parent_stage2_release_sha256", "s2_30_release_sha256", + "compile_mode", + "provenance", "expected_claim_group_ids", "published_claim_group_ids", "terminal_failure_claim_group_ids", - "terminal_cohort_receipt_sha256s", + "artifact_manifest_path", + "artifact_manifest_schema_ref", "artifact_manifest_sha256", + "ordered_item_receipts", + "ordered_cohort_receipts", "status", "route", "status_written_last", @@ -1569,6 +1864,8 @@ "run_binding_digest": {"$ref": "#/$defs/sha256"}, "parent_stage2_release_sha256": {"$ref": "#/$defs/sha256"}, "s2_30_release_sha256": {"$ref": "#/$defs/sha256"}, + "compile_mode": {"$ref": "#/$defs/compile_mode"}, + "provenance": {"$ref": "#/$defs/common_publish_provenance"}, "expected_claim_group_ids": { "type": "array", "items": {"$ref": "#/$defs/claim_group_id"}, @@ -1585,13 +1882,20 @@ "items": {"$ref": "#/$defs/claim_group_id"}, "uniqueItems": true }, - "terminal_cohort_receipt_sha256s": { + "artifact_manifest_path": {"const": "map_s2_30/artifact_manifest.json"}, + "artifact_manifest_schema_ref": {"const": "schemas/draft_atoms.schema.json#/$defs/part_manifest_core"}, + "artifact_manifest_sha256": {"$ref": "#/$defs/sha256"}, + "ordered_item_receipts": { "type": "array", - "items": {"$ref": "#/$defs/sha256"}, + "items": {"$ref": "#/$defs/item_receipt_ref"}, + "uniqueItems": true + }, + "ordered_cohort_receipts": { + "type": "array", + "items": {"$ref": "#/$defs/receipt_ref"}, "minItems": 1, "uniqueItems": true }, - "artifact_manifest_sha256": {"$ref": "#/$defs/sha256"}, "status": {"enum": ["S2_30_COMPLETE", "TECHNICAL_INCOMPLETE"]}, "route": {"enum": ["TO_S2_40", "STOP_TECHNICAL_INCOMPLETE"]}, "status_written_last": {"const": true}, diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/migration_regression.schema.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/migration_regression.schema.json new file mode 100644 index 00000000..2e7c3b20 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/migration_regression.schema.json @@ -0,0 +1,80 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.liti-agent.local/stage2/s2_40/migration_regression.schema.v1.json", + "title": "S2_40 structural fixture and regression manifest", + "schema_version": "stage2_s2_40_migration_regression.v1", + "oneOf": [ + {"$ref": "#/$defs/fixture_payload"}, + {"$ref": "#/$defs/regression_manifest"} + ], + "$defs": { + "sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"}, + "nonempty": {"type": "string", "minLength": 1}, + "path": {"type": "string", "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$)).+$"}, + "fixture_header": { + "type": "object", + "additionalProperties": false, + "required": ["fixture_case_id", "fixture_only", "production_admissible", "compile_mode", "oracle_kind", "source_locators"], + "properties": { + "fixture_case_id": {"$ref": "#/$defs/nonempty"}, + "fixture_only": {"const": true}, + "production_admissible": {"const": false}, + "compile_mode": {"const": "STRUCTURAL_FIXTURE"}, + "oracle_kind": {"enum": ["NORMAL", "MUTATION", "STATE", "BARRIER", "DIGEST", "REGRESSION_INDEX"]}, + "source_locators": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true} + } + }, + "expected_result": { + "type": "object", + "additionalProperties": false, + "required": ["route", "run_technical_status", "artifact_technical_status", "legal_readiness", "expected_invariant_results", "expected_reason_codes"], + "properties": { + "route": {"enum": ["PACKAGE_COMMITTED", "WAIT_EXTERNAL_REVIEW", "STOP_TECHNICAL_INCOMPLETE", "RESTART_FROM_S2_00", "RESTART_FROM_S2_10", "RESTART_FROM_S2_20", "RESTART_FROM_S2_30", "CONTRACT_TEST_ONLY"]}, + "run_technical_status": {"enum": ["CONSISTENT", "TECHNICAL_REVIEW_REQUIRED", "TECHNICAL_INCOMPLETE"]}, + "artifact_technical_status": {"enum": ["CONSISTENT", "TECHNICAL_REVIEW_REQUIRED", "NOT_PRODUCED"]}, + "legal_readiness": {"enum": ["READY_FOR_LAWYER_FILING_DECISION", "LAWYER_REVIEW_REQUIRED", "NOT_ASSESSED"]}, + "expected_invariant_results": {"type": "object", "propertyNames": {"pattern": "^V(?:0[1-9]|1[0-8])$"}, "additionalProperties": {"enum": ["PASS", "FAIL", "UNEVALUABLE"]}}, + "expected_reason_codes": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true} + } + }, + "fixture_payload": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "header", "input", "mutations", "expected"], + "properties": { + "schema_version": {"const": "stage2_s2_40_fixture_payload.v1"}, + "header": {"$ref": "#/$defs/fixture_header"}, + "input": {"type": "object"}, + "mutations": {"type": "array", "items": {"type": "object", "required": ["mutation_id", "target", "operation"], "properties": {"mutation_id": {"$ref": "#/$defs/nonempty"}, "target": {"$ref": "#/$defs/nonempty"}, "operation": {"$ref": "#/$defs/nonempty"}}, "additionalProperties": true}}, + "expected": {"$ref": "#/$defs/expected_result"} + } + }, + "regression_row": { + "type": "object", + "additionalProperties": false, + "required": ["fixture_case_id", "path", "raw_sha256", "oracle_kind", "expected_route", "expected_invariant_ids"], + "properties": { + "fixture_case_id": {"$ref": "#/$defs/nonempty"}, + "path": {"$ref": "#/$defs/path"}, + "raw_sha256": {"$ref": "#/$defs/sha256"}, + "oracle_kind": {"$ref": "#/$defs/nonempty"}, + "expected_route": {"$ref": "#/$defs/nonempty"}, + "expected_invariant_ids": {"type": "array", "items": {"pattern": "^V(?:0[1-9]|1[0-8])$"}, "uniqueItems": true} + } + }, + "regression_manifest": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "fixture_only", "production_admissible", "compile_mode", "rows", "test_sources", "manifest_digest"], + "properties": { + "schema_version": {"const": "stage2_s2_40_regression_manifest.v1"}, + "fixture_only": {"const": true}, + "production_admissible": {"const": false}, + "compile_mode": {"const": "STRUCTURAL_FIXTURE"}, + "rows": {"type": "array", "items": {"$ref": "#/$defs/regression_row"}, "minItems": 15}, + "test_sources": {"type": "array", "items": {"type": "object", "required": ["path", "raw_sha256"], "properties": {"path": {"$ref": "#/$defs/path"}, "raw_sha256": {"$ref": "#/$defs/sha256"}}, "additionalProperties": false}, "minItems": 6}, + "manifest_digest": {"$ref": "#/$defs/sha256"} + } + } + } +} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/package.schema.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/package.schema.json new file mode 100644 index 00000000..784e8dfb --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/package.schema.json @@ -0,0 +1,324 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.liti-agent.local/stage2/s2_40/package.schema.v1.json", + "title": "S2_40 candidate and sealed package contracts", + "schema_version": "stage2_s2_40_package.v1", + "oneOf": [ + {"$ref": "#/$defs/candidate_manifest_core"}, + {"$ref": "#/$defs/candidate_digest_envelope"}, + {"$ref": "#/$defs/rendered_document_metadata"}, + {"$ref": "#/$defs/attorney_worknotes_core"}, + {"$ref": "#/$defs/attorney_worknotes"}, + {"$ref": "#/$defs/usage_projection"}, + {"$ref": "#/$defs/render_diagnostic"}, + {"$ref": "#/$defs/review_policy_core"}, + {"$ref": "#/$defs/review_request_basis"}, + {"$ref": "#/$defs/frozen_source_rows"}, + {"$ref": "#/$defs/legal_gate_snapshot"}, + {"$ref": "#/$defs/lawyer_review_packet_core"}, + {"$ref": "#/$defs/lawyer_review_packet"}, + {"$ref": "#/$defs/validation_core"}, + {"$ref": "#/$defs/validation_envelope_core"}, + {"$ref": "#/$defs/validation_envelope"}, + {"$ref": "#/$defs/review_subject"}, + {"$ref": "#/$defs/stage2_package"} + ], + "$defs": { + "sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"}, + "nonempty": {"type": "string", "minLength": 1}, + "path": {"type": "string", "pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\x00).+$"}, + "compile_mode": {"enum": ["STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"]}, + "artifact_row": { + "type": "object", + "additionalProperties": false, + "required": ["path", "raw_sha256", "content_type", "size_bytes", "schema_ref", "producer_id"], + "properties": { + "path": {"$ref": "#/$defs/path"}, + "raw_sha256": {"$ref": "#/$defs/sha256"}, + "content_type": {"$ref": "#/$defs/nonempty"}, + "size_bytes": {"type": "integer", "minimum": 0}, + "schema_ref": {"type": ["string", "null"]}, + "producer_id": {"const": "S2_40"} + } + }, + "dependency_snapshot": { + "type": "object", + "additionalProperties": false, + "required": ["parent_release_sha256", "upstream_barrier_sha256s", "ordered_source_digest"], + "properties": { + "parent_release_sha256": {"$ref": "#/$defs/sha256"}, + "upstream_barrier_sha256s": {"type": "array", "items": {"$ref": "#/$defs/sha256"}, "minItems": 4, "uniqueItems": true}, + "ordered_source_digest": {"$ref": "#/$defs/sha256"} + } + }, + "ordered_source_snapshot_preimage": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "ordered_sha256s", "snapshot_digest"], + "properties": { + "schema_version": {"const": "stage2_s2_40_ordered_source_snapshot_preimage.v1"}, + "ordered_sha256s": {"type": "array", "items": {"$ref": "#/$defs/sha256"}}, + "snapshot_digest": {"$ref": "#/$defs/sha256"} + } + }, + "source_hash_row": { + "type": "object", + "additionalProperties": false, + "required": ["path", "sha256"], + "properties": { + "path": {"$ref": "#/$defs/path"}, + "sha256": {"$ref": "#/$defs/sha256"}, + "size_bytes": {"type": "integer", "minimum": 0}, + "ref_family": {"$ref": "#/$defs/nonempty"} + } + }, + "frozen_source_rows": { + "type": "array", + "items": {"$ref": "#/$defs/source_hash_row"} + }, + "attorney_worknotes_core": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "producer_id", "run_binding_digest", "rows"], + "properties": { + "schema_version": {"const": "stage2_s2_40_attorney_worknotes_core.v1"}, + "producer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "rows": {"type": "array", "items": {"type": "object", "required": ["worknote_id", "text", "source_refs"], "properties": {"worknote_id": {"$ref": "#/$defs/nonempty"}, "text": {"$ref": "#/$defs/nonempty"}, "source_refs": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "minItems": 1}}, "additionalProperties": false}} + } + }, + "render_diagnostic": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "render_errors", "render_absences", "independent_rerender_equal"], + "properties": { + "schema_version": {"const": "stage2_s2_40_render_diagnostic.v1"}, + "render_errors": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, + "render_absences": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, + "independent_rerender_equal": {"type": "boolean"} + } + }, + "review_policy_core": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "policy_registry_sha256", "base_policy", "active_tags", "runtime_triggers", "required_receipt_types", "pre_receipt_ready_eligible"], + "properties": { + "schema_version": {"const": "stage2_s2_40_review_policy_core.v1"}, + "policy_registry_sha256": {"$ref": "#/$defs/sha256"}, + "base_policy": {"enum": ["STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW"]}, + "active_tags": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, + "runtime_triggers": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, + "required_receipt_types": {"type": "array", "items": {"enum": ["STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW"]}, "uniqueItems": true}, + "pre_receipt_ready_eligible": {"type": "boolean"} + } + }, + "review_request_basis": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "required_receipt_types", "scope_ids", "finding_ids", "policy_version", "policy_sha256", "reviewer_role", "reviewer_qualification", "release_snapshot_sha256s"], + "properties": { + "schema_version": {"const": "stage2_s2_40_review_request_basis.v1"}, + "required_receipt_types": {"type": "array", "items": {"enum": ["STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW"]}, "uniqueItems": true}, + "scope_ids": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, + "finding_ids": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, + "policy_version": {"$ref": "#/$defs/nonempty"}, + "policy_sha256": {"$ref": "#/$defs/sha256"}, + "reviewer_role": {"$ref": "#/$defs/nonempty"}, + "reviewer_qualification": {"$ref": "#/$defs/nonempty"}, + "release_snapshot_sha256s": {"type": "object", "additionalProperties": false, "required": ["parent", "authority", "corpus", "case_type_coverage"], "properties": {"parent": {"$ref": "#/$defs/sha256"}, "authority": {"$ref": "#/$defs/sha256"}, "corpus": {"$ref": "#/$defs/sha256"}, "case_type_coverage": {"$ref": "#/$defs/sha256"}}} + } + }, + "legal_gate_snapshot": { + "type": "object", + "additionalProperties": false, + "required": ["binding", "authority", "renderer_branch", "rule_sub_rule", "review_policy", "case_type_coverage_137", "corpus", "law_value", "calculator", "required_receipts"], + "properties": { + "binding": {"type": "boolean"}, "authority": {"type": "boolean"}, + "renderer_branch": {"type": "boolean"}, "rule_sub_rule": {"type": "boolean"}, + "review_policy": {"type": "boolean"}, "case_type_coverage_137": {"type": "boolean"}, + "corpus": {"type": "boolean"}, "law_value": {"type": "boolean"}, + "calculator": {"type": "boolean"}, "required_receipts": {"type": "boolean"} + } + }, + "candidate_manifest_core": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "producer_id", "run_binding_digest", "compile_mode", "candidate_attempt_id", "dependency_snapshot", "artifacts"], + "properties": { + "schema_version": {"const": "stage2_s2_40_candidate_manifest_core.v1"}, + "producer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "compile_mode": {"$ref": "#/$defs/compile_mode"}, + "candidate_attempt_id": {"$ref": "#/$defs/nonempty"}, + "dependency_snapshot": {"$ref": "#/$defs/dependency_snapshot"}, + "artifacts": {"type": "array", "items": {"$ref": "#/$defs/artifact_row"}, "minItems": 6} + }, + "not": {"anyOf": [{"required": ["candidate_content_digest"]}, {"required": ["self_sha256"]}]} + }, + "candidate_digest_envelope": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "domain_separator", "run_binding_digest", "dependency_snapshot_sha256", "candidate_manifest_core_sha256", "document_sha256s", "attorney_worknotes_core_sha256", "final_issue_ledger_sha256", "assumption_ledger_sha256", "validation_core_sha256", "ordered_source_dependency_snapshot_digest", "candidate_content_digest"], + "properties": { + "schema_version": {"const": "stage2_s2_40_candidate_content_digest.v1"}, + "domain_separator": {"const": "STAGE2_S2_40_CANDIDATE_CONTENT_V1"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "dependency_snapshot_sha256": {"$ref": "#/$defs/sha256"}, + "candidate_manifest_core_sha256": {"$ref": "#/$defs/sha256"}, + "document_sha256s": { + "type": "object", "additionalProperties": false, + "required": ["claim_relief", "claim_cause", "pleading_draft"], + "properties": {"claim_relief": {"$ref": "#/$defs/sha256"}, "claim_cause": {"$ref": "#/$defs/sha256"}, "pleading_draft": {"$ref": "#/$defs/sha256"}} + }, + "attorney_worknotes_core_sha256": {"$ref": "#/$defs/sha256"}, + "final_issue_ledger_sha256": {"$ref": "#/$defs/sha256"}, + "assumption_ledger_sha256": {"$ref": "#/$defs/sha256"}, + "validation_core_sha256": {"$ref": "#/$defs/sha256"}, + "ordered_source_dependency_snapshot_digest": {"$ref": "#/$defs/sha256"}, + "candidate_content_digest": {"$ref": "#/$defs/sha256"} + }, + "not": {"anyOf": [{"required": ["review_subject_digest"]}, {"required": ["review_receipt_sha256s"]}, {"required": ["commit_result_sha256"]}, {"required": ["run_status_sha256"]}]} + }, + "rendered_document_metadata": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "document_kind", "path", "raw_sha256", "normalization_version", "source_atom_ids", "renderer_branch_refs"], + "properties": { + "schema_version": {"const": "stage2_s2_40_rendered_document_metadata.v1"}, + "document_kind": {"enum": ["CLAIM_RELIEF", "CLAIM_CAUSE", "PLEADING_DRAFT"]}, + "path": {"$ref": "#/$defs/path"}, + "raw_sha256": {"$ref": "#/$defs/sha256"}, + "normalization_version": {"const": "NFC_LF_UTF8_V1"}, + "source_atom_ids": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, + "renderer_branch_refs": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true} + } + }, + "attorney_worknotes": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "producer_id", "run_binding_digest", "candidate_content_digest", "rows"], + "properties": { + "schema_version": {"const": "stage2_s2_40_attorney_worknotes.v1"}, + "producer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "rows": {"type": "array", "items": {"type": "object", "required": ["worknote_id", "text", "source_refs"], "properties": {"worknote_id": {"$ref": "#/$defs/nonempty"}, "text": {"$ref": "#/$defs/nonempty"}, "source_refs": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "minItems": 1}}, "additionalProperties": false}} + } + }, + "usage_projection": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "producer_id", "run_binding_digest", "source_usage_part_sha256s", "rows", "conservation_status"], + "properties": { + "schema_version": {"const": "stage2_s2_40_usage_projection.v1"}, "producer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "source_usage_part_sha256s": {"type": "array", "items": {"$ref": "#/$defs/sha256"}, "uniqueItems": true}, + "rows": {"type": "array", "items": {"type": "object"}}, + "conservation_status": {"const": "PASS"} + } + }, + "lawyer_review_packet_core": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "candidate_content_digest", "finding_ids", "scope_ids", "document_refs", "legal_readiness"], + "properties": { + "schema_version": {"const": "stage2_s2_40_lawyer_review_packet_core.v1"}, + "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "finding_ids": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, + "scope_ids": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, + "document_refs": {"type": "array", "items": {"$ref": "#/$defs/path"}, "minItems": 1, "uniqueItems": true}, + "legal_readiness": {"enum": ["LAWYER_REVIEW_REQUIRED", "READY_FOR_LAWYER_FILING_DECISION"]} + }, + "not": {"anyOf": [{"required": ["review_subject_digest"]}, {"required": ["request_id"]}]} + }, + "lawyer_review_packet": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "lawyer_review_packet_core", "lawyer_review_packet_core_sha256", "review_subject_digest"], + "properties": { + "schema_version": {"const": "stage2_s2_40_lawyer_review_packet.v1"}, + "lawyer_review_packet_core": {"$ref": "#/$defs/lawyer_review_packet_core"}, + "lawyer_review_packet_core_sha256": {"$ref": "#/$defs/sha256"}, + "review_subject_digest": {"$ref": "#/$defs/sha256"} + } + }, + "validation_core": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "run_binding_digest", "compile_mode", "candidate_manifest_core_sha256", "invariant_results", "run_technical_status", "artifact_technical_status"], + "properties": { + "schema_version": {"const": "stage2_s2_40_validation_core.v1"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "compile_mode": {"$ref": "#/$defs/compile_mode"}, + "candidate_manifest_core_sha256": {"$ref": "#/$defs/sha256"}, + "invariant_results": {"type": "array", "items": {"$ref": "review_status.schema.json#/$defs/evaluation_result"}, "minItems": 18, "maxItems": 18}, + "run_technical_status": {"$ref": "review_status.schema.json#/$defs/run_technical_status"}, + "artifact_technical_status": {"$ref": "review_status.schema.json#/$defs/artifact_technical_status"} + } + }, + "validation_envelope_core": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "candidate_content_digest", "validation_core_sha256", "legal_readiness"], + "properties": { + "schema_version": {"const": "stage2_s2_40_validation_envelope_core.v1"}, + "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "validation_core_sha256": {"$ref": "#/$defs/sha256"}, + "legal_readiness": {"$ref": "review_status.schema.json#/$defs/legal_readiness"} + }, + "not": {"anyOf": [{"required": ["review_subject_digest"]}, {"required": ["request_id"]}]} + }, + "validation_envelope": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "validation_envelope_core", "validation_envelope_core_sha256", "review_subject_digest"], + "properties": { + "schema_version": {"const": "stage2_s2_40_validation_envelope.v1"}, + "validation_envelope_core": {"$ref": "#/$defs/validation_envelope_core"}, + "validation_envelope_core_sha256": {"$ref": "#/$defs/sha256"}, + "review_subject_digest": {"$ref": "#/$defs/sha256"} + } + }, + "review_request_core_binding": { + "type": "object", + "additionalProperties": false, + "required": ["receipt_type", "review_request_core_sha256"], + "properties": { + "receipt_type": {"enum": ["STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW"]}, + "review_request_core_sha256": {"$ref": "#/$defs/sha256"} + } + }, + "review_subject": { + "type": "object", "additionalProperties": false, + "required": ["schema_version", "domain_separator", "candidate_content_digest", "review_request_core_bindings", "lawyer_review_packet_core_sha256", "validation_envelope_core_sha256", "finding_ids", "scope_ids", "review_policy_sha256", "release_sha256s", "review_subject_digest"], + "properties": { + "schema_version": {"const": "stage2_s2_40_review_subject.v1"}, "domain_separator": {"const": "STAGE2_S2_40_REVIEW_SUBJECT_V1"}, + "candidate_content_digest": {"$ref": "#/$defs/sha256"}, "review_request_core_bindings": {"type": "array", "items": {"$ref": "#/$defs/review_request_core_binding"}, "uniqueItems": true}, "lawyer_review_packet_core_sha256": {"$ref": "#/$defs/sha256"}, "validation_envelope_core_sha256": {"$ref": "#/$defs/sha256"}, + "finding_ids": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, "scope_ids": {"type": "array", "items": {"$ref": "#/$defs/nonempty"}, "uniqueItems": true}, "review_policy_sha256": {"$ref": "#/$defs/sha256"}, + "release_sha256s": {"type": "object", "additionalProperties": false, "required": ["parent", "authority", "corpus", "case_type_coverage"], "properties": {"parent": {"$ref": "#/$defs/sha256"}, "authority": {"$ref": "#/$defs/sha256"}, "corpus": {"$ref": "#/$defs/sha256"}, "case_type_coverage": {"$ref": "#/$defs/sha256"}}}, + "review_subject_digest": {"$ref": "#/$defs/sha256"} + } + }, + "stage2_package": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "producer_id", "run_binding_digest", "candidate_content_digest", "compile_mode", "candidate_manifest_core_sha256", "artifacts", "validation_report_sha256", "review_policy_result_sha256", "review_receipt_sha256s", "filing_decision_receipt_sha256", "run_technical_status", "artifact_technical_status", "legal_readiness", "filing_permission"], + "properties": { + "schema_version": {"const": "stage2_s2_40_package.v1"}, + "producer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "compile_mode": {"$ref": "#/$defs/compile_mode"}, + "candidate_manifest_core_sha256": {"$ref": "#/$defs/sha256"}, + "artifacts": {"type": "array", "items": {"$ref": "#/$defs/artifact_row"}, "minItems": 8}, + "validation_report_sha256": {"$ref": "#/$defs/sha256"}, + "review_policy_result_sha256": {"$ref": "#/$defs/sha256"}, + "review_receipt_sha256s": {"type": "array", "items": {"$ref": "#/$defs/sha256"}, "uniqueItems": true}, + "filing_decision_receipt_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "run_technical_status": {"$ref": "review_status.schema.json#/$defs/run_technical_status"}, + "artifact_technical_status": {"$ref": "review_status.schema.json#/$defs/artifact_technical_status"}, + "legal_readiness": {"$ref": "review_status.schema.json#/$defs/legal_readiness"}, + "filing_permission": {"const": "NOT_GRANTED"} + }, + "not": {"anyOf": [{"required": ["artifact_set_digest"]}, {"required": ["commit_result_sha256"]}, {"required": ["run_status_sha256"]}]} + } + } +} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/review_status.schema.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/review_status.schema.json index 02c7eac1..5a1d39fc 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/review_status.schema.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/schemas/review_status.schema.json @@ -7,7 +7,16 @@ {"$ref": "#/$defs/issue_ledger_base"}, {"$ref": "relief_plan.schema.json#/$defs/issue_ledger_plan"}, {"$ref": "#/$defs/review_normalization_receipt"}, - {"$ref": "#/$defs/status_only_commit"} + {"$ref": "#/$defs/status_only_commit"}, + {"$ref": "#/$defs/final_issue_ledger"}, + {"$ref": "#/$defs/assumption_ledger"}, + {"$ref": "#/$defs/review_policy_result"}, + {"$ref": "#/$defs/review_request"}, + {"$ref": "#/$defs/review_receipt"}, + {"$ref": "#/$defs/lawyer_judgment_record"}, + {"$ref": "#/$defs/filing_decision_receipt"}, + {"$ref": "#/$defs/status_event"}, + {"$ref": "#/$defs/run_status"} ], "$defs": { "sha256": { @@ -349,6 +358,249 @@ "issue_refs": {"$ref": "#/$defs/string_set"}, "commit_status": {"enum": ["STATUS_ONLY_COMMITTED", "STATUS_ONLY_FAILED"]} } + }, + "evaluation_result": { + "type": "object", + "additionalProperties": false, + "required": ["invariant_id", "evaluation_status", "finding_ids", "impact_scope", "source_refs", "expected", "observed", "reason_codes", "validator_algorithm_id"], + "properties": { + "invariant_id": {"pattern": "^V(?:0[1-9]|1[0-8])$"}, + "evaluation_status": {"enum": ["PASS", "FAIL", "UNEVALUABLE"]}, + "finding_ids": {"$ref": "#/$defs/string_set"}, + "impact_scope": {"enum": ["OK", "REVIEW_REQUIRED", "INCOMPLETE"]}, + "source_refs": {"$ref": "#/$defs/string_set"}, + "expected": {}, + "observed": {}, + "reason_codes": {"$ref": "#/$defs/string_set"}, + "validator_algorithm_id": {"$ref": "#/$defs/nonempty_string"} + }, + "allOf": [{"if": {"properties": {"evaluation_status": {"const": "PASS"}}, "required": ["evaluation_status"]}, "then": {"properties": {"impact_scope": {"const": "OK"}}}}] + }, + "final_issue_ledger": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "producer_id", "run_binding_digest", "compile_mode", "source_ledger_sha256s", "source_issue_part_sha256s", "issues", "conservation_status"], + "properties": { + "schema_version": {"const": "stage2_s2_40_final_issue_ledger.v1"}, + "producer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "compile_mode": {"enum": ["STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"]}, + "source_ledger_sha256s": {"type": "array", "items": {"$ref": "#/$defs/sha256"}, "minItems": 2, "uniqueItems": true}, + "source_issue_part_sha256s": {"type": "array", "items": {"$ref": "#/$defs/sha256"}, "uniqueItems": true}, + "issues": {"type": "array", "items": {"$ref": "#/$defs/issue_row"}}, + "conservation_status": {"enum": ["PASS", "FAIL"]} + } + }, + "assumption_row": { + "type": "object", + "additionalProperties": false, + "required": ["assumption_id", "text", "status", "source_refs", "impact_scope"], + "properties": { + "assumption_id": {"$ref": "#/$defs/nonempty_string"}, + "text": {"$ref": "#/$defs/nonempty_string"}, + "status": {"enum": ["OPEN", "SUPPORTED", "REJECTED", "SUPERSEDED"]}, + "source_refs": {"$ref": "#/$defs/string_set"}, + "impact_scope": {"enum": ["GLOBAL", "CLAIM_GROUP", "ATOMIC_CLAIM", "DOCUMENT"]} + } + }, + "assumption_ledger": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "producer_id", "run_binding_digest", "compile_mode", "source_assumption_part_sha256s", "rows", "conservation_status"], + "properties": { + "schema_version": {"const": "stage2_s2_40_assumption_ledger.v1"}, + "producer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "compile_mode": {"enum": ["STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"]}, + "source_assumption_part_sha256s": {"type": "array", "items": {"$ref": "#/$defs/sha256"}, "uniqueItems": true}, + "rows": {"type": "array", "items": {"$ref": "#/$defs/assumption_row"}}, + "conservation_status": {"const": "PASS"} + } + }, + "review_policy_result": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "candidate_content_digest", "policy_registry_sha256", "base_policy", "active_tags", "runtime_triggers", "required_receipt_types", "ready_eligible"], + "properties": { + "schema_version": {"const": "stage2_s2_40_review_policy_result.v1"}, + "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "policy_registry_sha256": {"$ref": "#/$defs/sha256"}, + "base_policy": {"enum": ["STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW"]}, + "active_tags": {"$ref": "#/$defs/string_set"}, + "runtime_triggers": {"$ref": "#/$defs/string_set"}, + "required_receipt_types": {"$ref": "#/$defs/string_set"}, + "ready_eligible": {"type": "boolean"} + } + }, + "review_request_core": { + "type": "object", + "additionalProperties": false, + "required": ["candidate_content_digest", "receipt_type", "scope_ids", "finding_ids", "policy_version", "policy_sha256", "reviewer_role", "reviewer_qualification", "release_snapshot_sha256s"], + "properties": { + "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "receipt_type": {"enum": ["STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW"]}, + "scope_ids": {"$ref": "#/$defs/string_set"}, + "finding_ids": {"$ref": "#/$defs/string_set"}, + "policy_version": {"$ref": "#/$defs/nonempty_string"}, + "policy_sha256": {"$ref": "#/$defs/sha256"}, + "reviewer_role": {"$ref": "#/$defs/nonempty_string"}, + "reviewer_qualification": {"$ref": "#/$defs/nonempty_string"}, + "release_snapshot_sha256s": { + "type": "object", "additionalProperties": false, + "required": ["parent", "authority", "corpus", "case_type_coverage"], + "properties": {"parent": {"$ref": "#/$defs/sha256"}, "authority": {"$ref": "#/$defs/sha256"}, "corpus": {"$ref": "#/$defs/sha256"}, "case_type_coverage": {"$ref": "#/$defs/sha256"}} + } + }, + "not": {"anyOf": [{"required": ["request_id"]}, {"required": ["review_subject_digest"]}]} + }, + "review_request": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "request_id", "review_subject_digest", "review_request_core", "review_request_core_sha256"], + "properties": { + "schema_version": {"const": "stage2_s2_40_review_request.v1"}, + "request_id": {"$ref": "#/$defs/nonempty_string"}, + "review_subject_digest": {"$ref": "#/$defs/sha256"}, + "review_request_core": {"$ref": "#/$defs/review_request_core"}, + "review_request_core_sha256": {"$ref": "#/$defs/sha256"} + } + }, + "review_receipt": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "receipt_id", "request_id", "receipt_type", "candidate_content_digest", "review_subject_digest", "finding_ids", "scope_ids", "reviewer_role", "reviewer_qualification", "issuer_id", "key_id", "signature_algorithm", "signed_material_digest", "external_verification_attestation_sha256", "issued_at", "expires_at", "revocation_status", "cryptographic_verification_status", "review_disposition", "change_scope", "reason_codes"], + "properties": { + "schema_version": {"const": "stage2_s2_40_review_receipt.v1"}, + "receipt_id": {"$ref": "#/$defs/nonempty_string"}, + "request_id": {"$ref": "#/$defs/nonempty_string"}, + "receipt_type": {"enum": ["STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW"]}, + "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "review_subject_digest": {"$ref": "#/$defs/sha256"}, + "finding_ids": {"$ref": "#/$defs/string_set"}, + "scope_ids": {"$ref": "#/$defs/string_set"}, + "reviewer_role": {"$ref": "#/$defs/nonempty_string"}, + "reviewer_qualification": {"$ref": "#/$defs/nonempty_string"}, + "issuer_id": {"$ref": "#/$defs/nonempty_string"}, + "key_id": {"$ref": "#/$defs/nonempty_string"}, + "signature_algorithm": {"$ref": "#/$defs/nonempty_string"}, + "signed_material_digest": {"$ref": "#/$defs/sha256"}, + "external_verification_attestation_sha256": {"$ref": "#/$defs/sha256"}, + "issued_at": {"type": "string", "format": "date-time"}, + "expires_at": {"type": "string", "format": "date-time"}, + "revocation_status": {"enum": ["NOT_REVOKED", "REVOKED", "UNKNOWN"]}, + "cryptographic_verification_status": {"enum": ["VERIFIED_BY_EXTERNAL_ADAPTER", "PENDING_PLATFORM_ADMISSION", "INVALID"]}, + "review_disposition": {"enum": ["APPROVE_AS_IS", "CONTENT_CHANGE_REQUIRED"]}, + "change_scope": {"enum": ["NONE", "STAGE1_CONTEXT", "LEGAL_JUDGMENT", "PLAN_RULE_CALCULATION_BINDING", "DRAFTING_TEXT_ATOM"]}, + "reason_codes": {"$ref": "#/$defs/string_set"} + }, + "allOf": [ + { + "if": {"properties": {"review_disposition": {"const": "APPROVE_AS_IS"}}, "required": ["review_disposition"]}, + "then": {"properties": {"change_scope": {"const": "NONE"}}} + }, + { + "if": {"properties": {"review_disposition": {"const": "CONTENT_CHANGE_REQUIRED"}}, "required": ["review_disposition"]}, + "then": {"not": {"properties": {"change_scope": {"const": "NONE"}}, "required": ["change_scope"]}} + } + ] + }, + "lawyer_judgment_record": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "candidate_content_digest", "review_subject_digest", "review_receipt_ids", "judgment", "writer_role"], + "properties": { + "schema_version": {"const": "stage2_s2_40_lawyer_judgment_record.v1"}, + "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "review_subject_digest": {"$ref": "#/$defs/sha256"}, + "review_receipt_ids": {"$ref": "#/$defs/string_set"}, + "judgment": {"enum": ["APPROVE_AS_IS", "CONTENT_CHANGE_REQUIRED"]}, + "writer_role": {"const": "KOREAN_LAWYER_EXTERNAL_WRITER"} + } + }, + "filing_decision_receipt": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "decision_id", "candidate_content_digest", "stage2_package_sha256", "artifact_set_digest", "committed_run_status_sha256", "filing_scope", "reviewer_identity", "reviewer_qualification", "issuer_id", "key_id", "signature_algorithm", "signed_material_digest", "external_verification_attestation_sha256", "decision", "issued_at", "expires_at", "revocation_status", "signature_attestation"], + "properties": { + "schema_version": {"const": "stage2_s2_40_filing_decision_receipt.v1"}, + "decision_id": {"$ref": "#/$defs/nonempty_string"}, + "candidate_content_digest": {"$ref": "#/$defs/sha256"}, + "stage2_package_sha256": {"$ref": "#/$defs/sha256"}, + "artifact_set_digest": {"$ref": "#/$defs/sha256"}, + "committed_run_status_sha256": {"$ref": "#/$defs/sha256"}, + "filing_scope": {"$ref": "#/$defs/string_set"}, + "reviewer_identity": {"$ref": "#/$defs/nonempty_string"}, + "reviewer_qualification": {"const": "QUALIFIED_KOREAN_LAWYER"}, + "issuer_id": {"$ref": "#/$defs/nonempty_string"}, "key_id": {"$ref": "#/$defs/nonempty_string"}, "signature_algorithm": {"$ref": "#/$defs/nonempty_string"}, + "signed_material_digest": {"$ref": "#/$defs/sha256"}, "external_verification_attestation_sha256": {"$ref": "#/$defs/sha256"}, + "decision": {"enum": ["APPROVE_FOR_FILING", "DO_NOT_FILE"]}, + "issued_at": {"type": "string", "format": "date-time"}, + "expires_at": {"type": "string", "format": "date-time"}, + "revocation_status": {"enum": ["NOT_REVOKED", "REVOKED", "UNKNOWN"]}, + "signature_attestation": {"$ref": "#/$defs/sha256"} + } + }, + "workflow_phase": {"enum": ["CANDIDATE_FROZEN", "AWAITING_EXTERNAL_REVIEW", "READY_TO_COMMIT", "COMMITTED", "SUPERSEDED", "DIAGNOSTIC_ONLY"]}, + "status_event": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "writer_id", "run_binding_digest", "candidate_attempt_id", "workflow_phase", "route", "candidate_content_digest", "previous_run_status_sha256", "request_sha256", "host_cas_receipt_sha256", "event_digest"], + "properties": { + "schema_version": {"const": "stage2_s2_40_status_event.v1"}, + "writer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "candidate_attempt_id": {"$ref": "#/$defs/nonempty_string"}, + "workflow_phase": {"$ref": "#/$defs/workflow_phase"}, + "route": {"$ref": "#/$defs/nonempty_string"}, + "candidate_content_digest": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "previous_run_status_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "request_sha256": {"$ref": "#/$defs/sha256"}, + "host_cas_receipt_sha256": {"$ref": "#/$defs/sha256"}, + "event_digest": {"$ref": "#/$defs/sha256"} + } + }, + "run_status": { + "type": "object", + "additionalProperties": false, + "required": ["schema_version", "writer_id", "run_binding_digest", "candidate_attempt_id", "entry_route", "compile_mode", "workflow_phase", "route", "candidate_content_digest", "run_technical_status", "artifact_technical_status", "legal_readiness", "validation_report_sha256", "review_subject_digest", "review_receipt_sha256s", "stage2_package_sha256", "artifact_set_digest", "commit_intent_sha256", "commit_result_sha256", "request_sha256", "host_cas_receipt_sha256", "outer_execution_receipt_sha256", "previous_run_status_sha256", "status_event_sha256", "barrier_written_last", "readback_verified"], + "properties": { + "schema_version": {"const": "stage2_s2_40_run_status.v1"}, + "writer_id": {"const": "S2_40"}, + "run_binding_digest": {"$ref": "#/$defs/sha256"}, + "candidate_attempt_id": {"$ref": "#/$defs/nonempty_string"}, + "entry_route": {"enum": ["TO_S2_40", "TO_S2_40_STATUS_ONLY"]}, + "compile_mode": {"type": ["string", "null"], "enum": [null, "STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"]}, + "workflow_phase": {"$ref": "#/$defs/workflow_phase"}, + "route": {"enum": ["STOP_TECHNICAL_INCOMPLETE", "CHECKPOINT_FROZEN", "WAIT_EXTERNAL_REVIEW", "CONTINUE_TO_COMMIT", "RESTART_FROM_S2_00", "RESTART_FROM_S2_10", "RESTART_FROM_S2_20", "RESTART_FROM_S2_30", "PACKAGE_COMMITTED"]}, + "candidate_content_digest": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "run_technical_status": {"$ref": "#/$defs/run_technical_status"}, + "artifact_technical_status": {"$ref": "#/$defs/artifact_technical_status"}, + "legal_readiness": {"$ref": "#/$defs/legal_readiness"}, + "validation_report_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "review_subject_digest": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "review_receipt_sha256s": {"type": "array", "items": {"$ref": "#/$defs/sha256"}, "uniqueItems": true}, + "stage2_package_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "artifact_set_digest": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "commit_intent_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "commit_result_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "request_sha256": {"$ref": "#/$defs/sha256"}, + "host_cas_receipt_sha256": {"$ref": "#/$defs/sha256"}, + "outer_execution_receipt_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "previous_run_status_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "status_event_sha256": {"oneOf": [{"$ref": "#/$defs/sha256"}, {"type": "null"}]}, + "barrier_written_last": {"const": true}, + "readback_verified": {"const": true} + }, + "allOf": [ + { + "if": {"properties": {"entry_route": {"const": "TO_S2_40_STATUS_ONLY"}}, "required": ["entry_route"]}, + "then": {"properties": {"status_event_sha256": {"type": "null"}}} + }, + { + "if": {"properties": {"entry_route": {"const": "TO_S2_40"}}, "required": ["entry_route"]}, + "then": {"properties": {"status_event_sha256": {"$ref": "#/$defs/sha256"}}} + } + ] } } } diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/regression_manifest.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/regression_manifest.json index 836d5716..203e92b3 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/regression_manifest.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/regression_manifest.json @@ -1236,6 +1236,75 @@ } ] }, + "s2_40_fixture_binding": { + "binding_status": "OFFLINE_BYTES_BOUND_LEGAL_AND_LIVE_PENDING", + "fixture_manifest_path": "tests/fixtures/s2_40/regression_manifest.json", + "fixture_manifest_sha256": "ac5d68c8d4061d789aa5c773cd1ffb37728c33c7725785a9dd1f4bea63ec88ce", + "logical_fixture_count": 15, + "payload_file_count": 15, + "payloads": [ + { + "path": "tests/fixtures/s2_40/candidate_digest_noncycle.json", + "sha256": "74885602909bd19ca1678de781cac26afd34c2f386e98fc0370fd6ff6fb7b8bf" + }, + { + "path": "tests/fixtures/s2_40/cost_provisional_execution_numbering.json", + "sha256": "17c380492f5bc56ecf675cf9683784b2e463241c7d0589b7b496e7a381145c9b" + }, + { + "path": "tests/fixtures/s2_40/exhibit_object_party_title_completeness.json", + "sha256": "40045822f45b2a57805504744e751ee420a6187d0790d5a0f442f529ffedcf7e" + }, + { + "path": "tests/fixtures/s2_40/part_set_missing_duplicate_or_cross_group.json", + "sha256": "379273497ee23d4a515135771ba4d3bb5ff0e38325ad40eb4e0a0008cd6b88f4" + }, + { + "path": "tests/fixtures/s2_40/partial_write_readback_barrier.json", + "sha256": "467387c12a4cc6469d243de9f0a7948276adb558a99b3b661ccd74a5d17629cf" + }, + { + "path": "tests/fixtures/s2_40/relief_cause_crossmatch_mutations.json", + "sha256": "e8d148fef61920039e36abd0cfb771cc6e2fe3aa1a9cc0b0b0502c38ddf70567" + }, + { + "path": "tests/fixtures/s2_40/renderer_ast_slot_branch_mutations.json", + "sha256": "e70ecac4e71de962dfe8bb025a42c73c7c03cfba32c29319523d19f49e8260d0" + }, + { + "path": "tests/fixtures/s2_40/review_policy_state_aggregation.json", + "sha256": "953fc301703ff353de4df3cf46ed4e90b6bf4ce8268b08705e16151ffc8c3a21" + }, + { + "path": "tests/fixtures/s2_40/review_receipt_approve_resume.json", + "sha256": "c5b84e34358761750e8e9e7666de6532e0f22a31f32bf027f24efb256a1af5d5" + }, + { + "path": "tests/fixtures/s2_40/review_receipt_content_change_supersede.json", + "sha256": "400d4aeb455e5c3ec26c75a552ea91e9af79cb2329998caa1ad72d1be18da8e7" + }, + { + "path": "tests/fixtures/s2_40/review_receipt_missing_or_invalid.json", + "sha256": "a88645be90a9e0943358d83f7ea105193dd4b4dfebea4519702a17f69615dc65" + }, + { + "path": "tests/fixtures/s2_40/same_binding_idempotence_and_commit_conflict.json", + "sha256": "5536793236fa44da601dc8cf65d94dac32b18ebc2e8dc525a6df92106add57ad" + }, + { + "path": "tests/fixtures/s2_40/v01_v18_invariant_matrix.json", + "sha256": "e4c0a5476647fa1860cd685a15aad6d465a36b4f6b648c8e2a066c8747780eb8" + }, + { + "path": "tests/fixtures/s2_40/valid_full_candidate_and_commit.json", + "sha256": "e98e8dc55ab60f8f875ad2f58c1aec35eb1da3882371c22c3e232e0e9ae46c2f" + }, + { + "path": "tests/fixtures/s2_40/valid_status_only_diagnostic.json", + "sha256": "5676088f5d79168cbae5e1481da4b7cfd9241d06c935378e06dd2af56aae6285" + } + ] + }, "test_sources": [ { "path": "tests/s2_00/test_canonical_ids.py", @@ -1244,7 +1313,7 @@ }, { "path": "tests/s2_00/test_cluster_bundle_compile.py", - "sha256": "aa31cc87246a5c8f6b82e98b9f86dd654bc9306dfc7849af19ec16cfd5137a2a", + "sha256": "b643d2d4018ebe3349c64304063edf7ba0194fc92fb1fe9337eca3f384ae794a", "status": "DEV_HASH_BOUND" }, { @@ -1254,7 +1323,7 @@ }, { "path": "tests/s2_00/test_failure_and_atomic_publish.py", - "sha256": "128a82b4e413132c0ff4a61ae2dc7f85b6c1c050ea33ccf4e53f23ccc993aba6", + "sha256": "613f0c1b32dc26c302365fc62f36c8ede7204e1ced4920e797a1651af8354527", "status": "DEV_HASH_BOUND" }, { @@ -1299,18 +1368,53 @@ }, { "path": "tests/s2_20/test_plan_publish_and_release.py", - "sha256": "eb5a96109d95d4b78473f79129c441f9be9b015bba1157dfa4d4d3616d03525e", + "sha256": "ce0dc52cca2c6744be1051346ebecabac8c4ccbd97d697f7645eadd35aebd1e8", "status": "OFFLINE_VERIFIED_LEGAL_AND_LIVE_PENDING" }, { "path": "tests/s2_20/test_regression_manifest_closure.py", - "sha256": "886ae584a7846acdb5499d52e1ae8ec177e8d1dc34aa1d43e99dbebafa255516", + "sha256": "01ac49ab1ba79f158da9da78313407e3a67a95cf539113c617701a74c29b463f", "status": "OFFLINE_VERIFIED_LEGAL_AND_LIVE_PENDING" }, { "path": "tests/s2_20/test_retrieval_and_pack.py", "sha256": "c314cf27511b0fe065b8961196084a28b1c7c5cb2fed3dd5c8765172ba40462f", "status": "OFFLINE_VERIFIED_LEGAL_AND_LIVE_PENDING" + }, + { + "path": "tests/s2_40/test_agent_and_inline_parity.py", + "sha256": "04cc4a14790eceea6ec8a9331212ca6e767ef96994b5b26483392d23145417ae", + "status": "OFFLINE_VERIFIED_LEGAL_AND_LIVE_PENDING" + }, + { + "path": "tests/s2_40/test_c40_reduce_and_conservation.py", + "sha256": "f610eced056420277c67294cdfe76d559073d88a6f42d3e8c5dae8f219fa82d9", + "status": "OFFLINE_VERIFIED_LEGAL_AND_LIVE_PENDING" + }, + { + "path": "tests/s2_40/test_c45_closed_render.py", + "sha256": "b7cad96735b1a0158644f41703b4f279fdd8b6bc68438f0d7d773b8415ebb460", + "status": "OFFLINE_VERIFIED_LEGAL_AND_LIVE_PENDING" + }, + { + "path": "tests/s2_40/test_commit_barrier_and_idempotence.py", + "sha256": "714e2f05397d5dcc31159739363f11c9bbaf5a091de55b465e0b474c21f90ea0", + "status": "OFFLINE_VERIFIED_LEGAL_AND_LIVE_PENDING" + }, + { + "path": "tests/s2_40/test_release_closure.py", + "sha256": "89139e0286facd52c3ce91a1c7b382a584dfc3e6bc337fcb55fbc8eed59f5933", + "status": "OFFLINE_VERIFIED_LEGAL_AND_LIVE_PENDING" + }, + { + "path": "tests/s2_40/test_review_state_machine.py", + "sha256": "f4dab9bb651b4a3c818c73162b972c8ac3df0f50fbe056e392a12673139b9b4a", + "status": "OFFLINE_VERIFIED_LEGAL_AND_LIVE_PENDING" + }, + { + "path": "tests/s2_40/test_v01_v18.py", + "sha256": "72be88be1aa9d495b5c9387e45b75e86f44ac76ffe15c04b5ba33ba21fa8943f", + "status": "OFFLINE_VERIFIED_LEGAL_AND_LIVE_PENDING" } ] } diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/partial_write_publish_barrier.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/partial_write_publish_barrier.json index a336e625..30950124 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/partial_write_publish_barrier.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/partial_write_publish_barrier.json @@ -1,5 +1,5 @@ { - "schema_version": "stage2_s2_30_partial_write_barrier_fixture.v1", + "schema_version": "stage2_s2_30_partial_write_barrier_fixture.v2", "cases": [ { "case_id": "partial_write_preserve_existing_rows", @@ -23,35 +23,28 @@ "expected": {"failure_code": "READ_BACK_HASH_MISMATCH", "publish_status_written": false, "downstream_allowed": false} }, { - "case_id": "status_last_success", - "expected_claim_group_ids": ["CG-1111111111111111", "CG-2222222222222222"], - "read_back_verified_claim_group_ids": ["CG-1111111111111111", "CG-2222222222222222"], - "terminal_cohort_receipt_sha256s": ["5555555555555555555555555555555555555555555555555555555555555555"], - "artifact_manifest_sha256": "6666666666666666666666666666666666666666666666666666666666666666", - "publish_status": { - "schema_version": "stage2_s2_30_publish_status.v1", - "request_id": "REQ-S2-30-PUBLISH-001", - "run_binding_digest": "7777777777777777777777777777777777777777777777777777777777777777", - "parent_stage2_release_sha256": "8888888888888888888888888888888888888888888888888888888888888888", - "s2_30_release_sha256": "9999999999999999999999999999999999999999999999999999999999999999", - "expected_claim_group_ids": ["CG-1111111111111111", "CG-2222222222222222"], - "published_claim_group_ids": ["CG-1111111111111111", "CG-2222222222222222"], - "terminal_failure_claim_group_ids": [], - "terminal_cohort_receipt_sha256s": ["5555555555555555555555555555555555555555555555555555555555555555"], - "artifact_manifest_sha256": "6666666666666666666666666666666666666666666666666666666666666666", - "status": "S2_30_COMPLETE", - "route": "TO_S2_40", - "status_written_last": true, - "status_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "case_id": "status_last_success_shape", + "manifest": { + "path": "map_s2_30/artifact_manifest.json", + "schema_ref": "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", + "receipt_free": true, + "part_manifest_core_sha256": "5555555555555555555555555555555555555555555555555555555555555555", + "raw_sha256": "6666666666666666666666666666666666666666666666666666666666666666" }, - "expected": {"schema_valid": true, "write_order_last": "map_s2_30/s2_30_publish_status.json", "route": "TO_S2_40"} + "ordered_item_receipts": [ + {"claim_group_id": "CG-1111111111111111", "path": "map_s2_30/item_receipts/CG-1111111111111111.json", "sha256": "7777777777777777777777777777777777777777777777777777777777777777"} + ], + "ordered_cohort_receipts": [ + {"path": "map_s2_30/cohort_receipts/COHORT-001/attempt-1.json", "sha256": "8888888888888888888888888888888888888888888888888888888888888888"} + ], + "expected": {"write_order_last": "map_s2_30/s2_30_publish_status.json", "route": "TO_S2_40", "directory_scan_used": false} } ], "mutations": [ {"mutation_id": "S30-BARRIER-EARLY", "single_defect": "STATUS_WRITTEN_BEFORE_ALL_READ_BACK", "expected_code": "STATUS_LAST_BARRIER_VIOLATION"}, - {"mutation_id": "S30-BARRIER-MISSING-GROUP", "single_defect": "EXPECTED_GROUP_NOT_TERMINAL", "expected_code": "GROUP_TERMINAL_SET_MISMATCH"}, - {"mutation_id": "S30-BARRIER-OVERWRITE", "single_defect": "EXISTING_NONIDENTICAL_ARTIFACT_OVERWRITTEN", "expected_code": "IMMUTABLE_OUTPUT_CONFLICT"}, - {"mutation_id": "S30-BARRIER-DELETE-PARTIAL", "single_defect": "SUCCESSFUL_EXISTING_ARTIFACT_DELETED_AFTER_PEER_FAILURE", "expected_code": "PARTIAL_WRITE_PRESERVATION_FAILED"}, - {"mutation_id": "S30-BARRIER-TO-S2-40-ON-FAILURE", "single_defect": "DOWNSTREAM_ROUTE_OPEN_WITH_TERMINAL_FAILURE", "expected_code": "DOWNSTREAM_ROUTE_MUST_STOP"} + {"mutation_id": "S30-BARRIER-MISSING-GROUP", "single_defect": "EXPECTED_GROUP_NOT_TERMINAL", "expected_code": "PUBLISH_GROUP_SET_MISMATCH"}, + {"mutation_id": "S30-BARRIER-UNENUMERATED-PART", "single_defect": "PART_NOT_IN_MANIFEST", "expected_code": "UNENUMERATED_PART_INPUT_FORBIDDEN"}, + {"mutation_id": "S30-BARRIER-MANIFEST-RECEIPT-CYCLE", "single_defect": "RECEIPT_HASH_INSERTED_IN_MANIFEST_CORE", "expected_code": "MANIFEST_RECEIPT_REFERENCE_FORBIDDEN"}, + {"mutation_id": "S30-BARRIER-TO-S2-40-ON-FAILURE", "single_defect": "DOWNSTREAM_ROUTE_OPEN_WITH_TERMINAL_FAILURE", "expected_code": "PUBLISH_SUCCESS_ROUTE_INVALID"} ] } diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/persisted_handoff_chain.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/persisted_handoff_chain.json new file mode 100644 index 00000000..b8635cd6 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/persisted_handoff_chain.json @@ -0,0 +1,55 @@ +{ + "schema_version": "stage2_s2_30_persisted_handoff_chain_fixture.v1", + "contract": { + "manifest_path": "map_s2_30/artifact_manifest.json", + "manifest_schema_ref": "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", + "part_families": ["DRAFT_PART", "ISSUE_PATCH", "USAGE_PART", "WORKNOTE_PART"], + "rows_per_claim_group": 4, + "manifest_receipt_free": true, + "item_and_cohort_receipts_reference": "part_manifest_core_sha256", + "publish_status_written_last": true, + "runtime_directory_scan_allowed": false, + "runtime_glob_allowed": false, + "group_provenance_fields": [ + "compile_mode", + "p00_prompt_sha256", + "p30_prompt_sha256", + "p31_rule_and_pack_sha256", + "p32_common_authority_sha256", + "parent_stage2_release_sha256", + "s2_30_agent_sha256", + "s2_30_binding_sha256", + "s2_30_producer_contract_digest", + "s2_30_release_sha256", + "s30_group_slice_sha256" + ], + "ordered_receipt_indexes": ["ordered_item_receipts", "ordered_cohort_receipts"] + }, + "mutations": [ + { + "mutation_id": "S30-HANDOFF-MISSING-PART", + "single_defect": "MANIFEST_ROW_HAS_NO_EXPLICIT_PART_BYTES", + "expected_code": "MANIFEST_PART_BYTES_MISSING" + }, + { + "mutation_id": "S30-HANDOFF-UNENUMERATED-PART", + "single_defect": "PART_BYTES_NOT_LISTED_BY_MANIFEST", + "expected_code": "UNENUMERATED_PART_INPUT_FORBIDDEN" + }, + { + "mutation_id": "S30-HANDOFF-RECEIPT-CYCLE", + "single_defect": "MANIFEST_CORE_CONTAINS_RECEIPT_REFERENCE", + "expected_code": "MANIFEST_RECEIPT_REFERENCE_FORBIDDEN" + }, + { + "mutation_id": "S30-HANDOFF-MODE-DRIFT", + "single_defect": "PUBLISH_COMPILE_MODE_DIFFERS_FROM_MANIFEST", + "expected_code": "PUBLISH_COMPILE_MODE_MISMATCH" + }, + { + "mutation_id": "S30-HANDOFF-RECEIPT-CORE-DRIFT", + "single_defect": "RECEIPT_REFERENCES_DIFFERENT_MANIFEST_CORE_HASH", + "expected_code": "RECEIPT_MANIFEST_CORE_HASH_MISMATCH" + } + ] +} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/regression_manifest.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/regression_manifest.json index fd58a991..2ae28e93 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/regression_manifest.json +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_30/regression_manifest.json @@ -2,7 +2,7 @@ "schema_version": "stage2_s2_30_regression_manifest.v1", "status": "OFFLINE_STRUCTURAL_ORACLES_BOUND_LIVE_AND_LEGAL_ORACLES_PENDING", "hash_algorithm": "SHA-256", - "fixture_count_excluding_manifest": 13, + "fixture_count_excluding_manifest": 14, "test_source_count": 5, "fixtures": [ {"filename": "adverse_fact_worknote_policy.json", "sha256": "5b8e9101385f8d65b0332c3be63cb9a22063920675cc86aee51e04da7820aef7", "expected_oracles": ["ADVERSE_FACT_SCHEMA_AND_POLICY_ORACLE"]}, @@ -14,16 +14,17 @@ {"filename": "invalid_preassembled_prompt_item.json", "sha256": "6655402c669e5b40f2e7028a5c0c89571d8e1597dbdef567b4c9d8e2eed15a79", "expected_oracles": ["PARSE_AND_CONTRACT_ORACLE"]}, {"filename": "invalid_reference_output.json", "sha256": "eb2982a09f4948baadc27ae49c4f125426074333ea4a626e9c56ddc5c24ce273", "expected_oracles": ["PARSE_AND_CONTRACT_ORACLE"]}, {"filename": "owner_singleton_dispatch.json", "sha256": "38f9c364591fcdfe60d0dea9f69eb86b2f3b883929f6d60d06a7c35ff376fca6", "expected_oracles": ["OWNER_DISPATCH_AND_MATERIALIZATION_ORACLE"]}, - {"filename": "partial_write_publish_barrier.json", "sha256": "89f8318c7dbec7bf0095e34194f0a585ea5f4cbce9826af64c30d370612fa1f5", "expected_oracles": ["PARSE_AND_CONTRACT_ORACLE"]}, + {"filename": "partial_write_publish_barrier.json", "sha256": "0d878b946ebf810e8d0d8da74af33e56f35e164b04076a3867344b95d5f953eb", "expected_oracles": ["STATUS_LAST_AND_PARTIAL_WRITE_ORACLE"]}, + {"filename": "persisted_handoff_chain.json", "sha256": "54d6d781a60640744cba4b9c2f88a0013a6e58656c9c80a809e39fd4ba7c1097", "expected_oracles": ["RECEIPT_FREE_EXACT_HANDOFF_CHAIN_ORACLE"]}, {"filename": "rule_requirement_admission_gap.json", "sha256": "27dfad63f3508c5d40521270707d84b2bc0c58f035f47d0cde1ae2abc54f9a15", "expected_oracles": ["PARSE_AND_CONTRACT_ORACLE"]}, {"filename": "technical_failure.json", "sha256": "bdcc6410e7515edc73d6b154d5b618b3ec34273ddc7269dc3e3ce55a6eb35fa6", "expected_oracles": ["PARSE_AND_CONTRACT_ORACLE"]}, {"filename": "valid_joint_draft_output.json", "sha256": "0135616c9375602693af8e12c3c16cf2031eaf3d9b74783bec9b5065846327e8", "expected_oracles": ["PARSE_AND_CONTRACT_ORACLE"]} ], "test_sources": [ - {"path": "tests/s2_30/test_agent_contract.py", "sha256": "e7d0f069f8c60ff5c5194a9ea9289376e2fd81a50d1b4b18b1b6abf5f2827529"}, + {"path": "tests/s2_30/test_agent_contract.py", "sha256": "26a37b0b5fa6c4273ed7deff6b0429e3223869533fc2384f4c364fe88d554da5"}, {"path": "tests/s2_30/test_dispatch_materialization.py", "sha256": "9d6ca17f012566b3d7423195ef19908694604a81059bfc10bd0c34dab1c24665"}, {"path": "tests/s2_30/test_draft_atom_contract.py", "sha256": "cb1ecf7131921c37aa4a6dc31f9053f21526f153407b90d1efffd472b0d68923"}, - {"path": "tests/s2_30/test_prompt_cache_and_boundaries.py", "sha256": "9063ca0a247cf06f55e94e586a7ab8ac21facd9f6c607ce4799047aea365e287"}, - {"path": "tests/s2_30/test_release_adapter_retry.py", "sha256": "b15505567db55689527056d608a1cb12d3c605e9df860afba607a6e3e276a0ef"} + {"path": "tests/s2_30/test_prompt_cache_and_boundaries.py", "sha256": "1b9b562418bc24be6db09dc1d35f71845033adbc693aeb41fbba07be16fa7c9d"}, + {"path": "tests/s2_30/test_release_adapter_retry.py", "sha256": "e5af75d54f236eb8ba99b194a06aa31f02fddd5c6aa9ff7385401905359b292c"} ] } diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/candidate_digest_noncycle.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/candidate_digest_noncycle.json new file mode 100644 index 00000000..cfebe0a5 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/candidate_digest_noncycle.json @@ -0,0 +1 @@ +{"schema_version":"stage2_s2_40_fixture_payload.v1","header":{"fixture_case_id":"S40-F015","fixture_only":true,"production_admissible":false,"compile_mode":"STRUCTURAL_FIXTURE","oracle_kind":"DIGEST","source_locators":["fixture://s2_40/noncycle"]},"input":{"ordered_graph":["candidate_manifest_core","candidate_content_digest","review_subject","commit_intent","artifact_set_digest","commit_result","run_status"]},"mutations":[{"mutation_id":"CYCLE","target":"candidate_manifest_core/candidate_content_digest","operation":"ADD"}],"expected":{"route":"CONTRACT_TEST_ONLY","run_technical_status":"TECHNICAL_INCOMPLETE","artifact_technical_status":"NOT_PRODUCED","legal_readiness":"NOT_ASSESSED","expected_invariant_results":{"V14":"FAIL"},"expected_reason_codes":["CANDIDATE_DIGEST_MATERIAL_CYCLE"]}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/cost_provisional_execution_numbering.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/cost_provisional_execution_numbering.json new file mode 100644 index 00000000..d06aab49 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/cost_provisional_execution_numbering.json @@ -0,0 +1,43 @@ +{ + "schema_version": "stage2_s2_40_fixture_payload.v1", + "header": { + "fixture_case_id": "S40-F007", + "fixture_only": true, + "production_admissible": false, + "compile_mode": "STRUCTURAL_FIXTURE", + "oracle_kind": "MUTATION", + "source_locators": ["fixture://s2_40/numbering"] + }, + "input": { + "renderer_ids": ["R01", "R03", "R05", "R06"], + "actio_structural_dependencies": [ + "route", "recipient", "period_one", "period_two", "three_cap", "provisional_execution" + ], + "special_case_structural_dependencies": [ + "reserved_share_temporal", "forced_apology_prohibition", "simultaneous_performance", + "CE-01", "CE-13", "loan_contract_temporal" + ], + "actio_legal_approval_status": "PENDING_LEGAL_ADMISSION", + "special_case_legal_approval_status": "PENDING_LEGAL_ADMISSION" + }, + "mutations": [ + {"mutation_id":"INELIGIBLE","target":"provisional/R03","operation":"ENABLE"}, + {"mutation_id":"NUMBER","target":"relief/order","operation":"PERMUTE"}, + {"mutation_id":"ACTIO_ROUTE","target":"actio.route","operation":"DROP"}, + {"mutation_id":"ACTIO_RECIPIENT","target":"actio.recipient","operation":"SUBSTITUTE"}, + {"mutation_id":"ACTIO_PERIODS","target":"actio.periods","operation":"COLLAPSE_TWO_TO_ONE"}, + {"mutation_id":"ACTIO_THREE_CAP","target":"actio.three_cap","operation":"REMOVE_RECEIPT"}, + {"mutation_id":"RESERVED_SHARE_TEMPORAL","target":"reserved_share.temporal_branch","operation":"STALE"}, + {"mutation_id":"FORCED_APOLOGY","target":"relief.forced_apology","operation":"ENABLE"}, + {"mutation_id":"SIMULTANEOUS_PERFORMANCE","target":"relief.counter_performance","operation":"DROP"}, + {"mutation_id":"CE01_CE13_LOAN_TEMPORAL","target":"law_value_receipts","operation":"REMOVE_TEMPORAL_SCOPE"} + ], + "expected": { + "route": "WAIT_EXTERNAL_REVIEW", + "run_technical_status": "TECHNICAL_REVIEW_REQUIRED", + "artifact_technical_status": "TECHNICAL_REVIEW_REQUIRED", + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + "expected_invariant_results": {"V10":"FAIL", "V18":"FAIL"}, + "expected_reason_codes": ["PROVISIONAL_OR_NUMBERING_INVALID"] + } +} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/exhibit_object_party_title_completeness.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/exhibit_object_party_title_completeness.json new file mode 100644 index 00000000..62b6a178 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/exhibit_object_party_title_completeness.json @@ -0,0 +1 @@ +{"schema_version":"stage2_s2_40_fixture_payload.v1","header":{"fixture_case_id":"S40-F008","fixture_only":true,"production_admissible":false,"compile_mode":"STRUCTURAL_FIXTURE","oracle_kind":"MUTATION","source_locators":["fixture://s2_40/completeness"]},"input":{"refs":["party:P1","object:O1","exhibit:E1"]},"mutations":[{"mutation_id":"DANGLING","target":"exhibit:E1","operation":"DELETE"}],"expected":{"route":"WAIT_EXTERNAL_REVIEW","run_technical_status":"TECHNICAL_REVIEW_REQUIRED","artifact_technical_status":"TECHNICAL_REVIEW_REQUIRED","legal_readiness":"LAWYER_REVIEW_REQUIRED","expected_invariant_results":{"V15":"FAIL","V17":"FAIL"},"expected_reason_codes":["REFERENCE_DANGLING"]}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/part_set_missing_duplicate_or_cross_group.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/part_set_missing_duplicate_or_cross_group.json new file mode 100644 index 00000000..be9afa48 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/part_set_missing_duplicate_or_cross_group.json @@ -0,0 +1 @@ +{"schema_version":"stage2_s2_40_fixture_payload.v1","header":{"fixture_case_id":"S40-F003","fixture_only":true,"production_admissible":false,"compile_mode":"STRUCTURAL_FIXTURE","oracle_kind":"MUTATION","source_locators":["fixture://s2_40/parts"]},"input":{"expected_groups":["G1","G2"]},"mutations":[{"mutation_id":"MISSING","target":"parts/G2","operation":"DELETE"},{"mutation_id":"DUP","target":"parts/G1","operation":"DUPLICATE"},{"mutation_id":"CROSS","target":"parts/G1/group_id","operation":"REPLACE"}],"expected":{"route":"STOP_TECHNICAL_INCOMPLETE","run_technical_status":"TECHNICAL_INCOMPLETE","artifact_technical_status":"NOT_PRODUCED","legal_readiness":"NOT_ASSESSED","expected_invariant_results":{"V01":"FAIL","V02":"FAIL"},"expected_reason_codes":["PART_SET_NOT_EXACT"]}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/partial_write_readback_barrier.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/partial_write_readback_barrier.json new file mode 100644 index 00000000..314598b0 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/partial_write_readback_barrier.json @@ -0,0 +1 @@ +{"schema_version":"stage2_s2_40_fixture_payload.v1","header":{"fixture_case_id":"S40-F013","fixture_only":true,"production_admissible":false,"compile_mode":"STRUCTURAL_FIXTURE","oracle_kind":"BARRIER","source_locators":["fixture://s2_40/partial-write"]},"input":{"barrier_last":true},"mutations":[{"mutation_id":"PARTIAL","target":"final/artifact","operation":"TRUNCATE"}],"expected":{"route":"STOP_TECHNICAL_INCOMPLETE","run_technical_status":"TECHNICAL_INCOMPLETE","artifact_technical_status":"NOT_PRODUCED","legal_readiness":"NOT_ASSESSED","expected_invariant_results":{"V14":"FAIL"},"expected_reason_codes":["READBACK_MISMATCH_NO_FINAL_BARRIER"]}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/regression_manifest.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/regression_manifest.json new file mode 100644 index 00000000..dd94ff11 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/regression_manifest.json @@ -0,0 +1,213 @@ +{ + "schema_version": "stage2_s2_40_regression_manifest.v1", + "fixture_only": true, + "production_admissible": false, + "compile_mode": "STRUCTURAL_FIXTURE", + "rows": [ + { + "fixture_case_id": "S40-F001", + "path": "tests/fixtures/s2_40/valid_full_candidate_and_commit.json", + "raw_sha256": "e98e8dc55ab60f8f875ad2f58c1aec35eb1da3882371c22c3e232e0e9ae46c2f", + "oracle_kind": "NORMAL", + "expected_route": "PACKAGE_COMMITTED", + "expected_invariant_ids": [ + "V01", + "V18" + ] + }, + { + "fixture_case_id": "S40-F002", + "path": "tests/fixtures/s2_40/valid_status_only_diagnostic.json", + "raw_sha256": "5676088f5d79168cbae5e1481da4b7cfd9241d06c935378e06dd2af56aae6285", + "oracle_kind": "BARRIER", + "expected_route": "STOP_TECHNICAL_INCOMPLETE", + "expected_invariant_ids": [ + "V01" + ] + }, + { + "fixture_case_id": "S40-F003", + "path": "tests/fixtures/s2_40/part_set_missing_duplicate_or_cross_group.json", + "raw_sha256": "379273497ee23d4a515135771ba4d3bb5ff0e38325ad40eb4e0a0008cd6b88f4", + "oracle_kind": "MUTATION", + "expected_route": "STOP_TECHNICAL_INCOMPLETE", + "expected_invariant_ids": [ + "V01", + "V02" + ] + }, + { + "fixture_case_id": "S40-F004", + "path": "tests/fixtures/s2_40/renderer_ast_slot_branch_mutations.json", + "raw_sha256": "e70ecac4e71de962dfe8bb025a42c73c7c03cfba32c29319523d19f49e8260d0", + "oracle_kind": "MUTATION", + "expected_route": "STOP_TECHNICAL_INCOMPLETE", + "expected_invariant_ids": [ + "V10", + "V18" + ] + }, + { + "fixture_case_id": "S40-F005", + "path": "tests/fixtures/s2_40/relief_cause_crossmatch_mutations.json", + "raw_sha256": "e8d148fef61920039e36abd0cfb771cc6e2fe3aa1a9cc0b0b0502c38ddf70567", + "oracle_kind": "MUTATION", + "expected_route": "WAIT_EXTERNAL_REVIEW", + "expected_invariant_ids": [ + "V09", + "V11", + "V18" + ] + }, + { + "fixture_case_id": "S40-F006", + "path": "tests/fixtures/s2_40/v01_v18_invariant_matrix.json", + "raw_sha256": "e4c0a5476647fa1860cd685a15aad6d465a36b4f6b648c8e2a066c8747780eb8", + "oracle_kind": "MUTATION", + "expected_route": "CONTRACT_TEST_ONLY", + "expected_invariant_ids": [ + "V01", + "V02", + "V03", + "V04", + "V05", + "V06", + "V07", + "V08", + "V09", + "V10", + "V11", + "V12", + "V13", + "V14", + "V15", + "V16", + "V17", + "V18" + ] + }, + { + "fixture_case_id": "S40-F007", + "path": "tests/fixtures/s2_40/cost_provisional_execution_numbering.json", + "raw_sha256": "17c380492f5bc56ecf675cf9683784b2e463241c7d0589b7b496e7a381145c9b", + "oracle_kind": "MUTATION", + "expected_route": "WAIT_EXTERNAL_REVIEW", + "expected_invariant_ids": [ + "V10", + "V18" + ] + }, + { + "fixture_case_id": "S40-F008", + "path": "tests/fixtures/s2_40/exhibit_object_party_title_completeness.json", + "raw_sha256": "40045822f45b2a57805504744e751ee420a6187d0790d5a0f442f529ffedcf7e", + "oracle_kind": "MUTATION", + "expected_route": "WAIT_EXTERNAL_REVIEW", + "expected_invariant_ids": [ + "V15", + "V17" + ] + }, + { + "fixture_case_id": "S40-F009", + "path": "tests/fixtures/s2_40/review_policy_state_aggregation.json", + "raw_sha256": "953fc301703ff353de4df3cf46ed4e90b6bf4ce8268b08705e16151ffc8c3a21", + "oracle_kind": "STATE", + "expected_route": "WAIT_EXTERNAL_REVIEW", + "expected_invariant_ids": [ + "V18" + ] + }, + { + "fixture_case_id": "S40-F010", + "path": "tests/fixtures/s2_40/review_receipt_missing_or_invalid.json", + "raw_sha256": "a88645be90a9e0943358d83f7ea105193dd4b4dfebea4519702a17f69615dc65", + "oracle_kind": "STATE", + "expected_route": "WAIT_EXTERNAL_REVIEW", + "expected_invariant_ids": [ + "V14" + ] + }, + { + "fixture_case_id": "S40-F011", + "path": "tests/fixtures/s2_40/review_receipt_approve_resume.json", + "raw_sha256": "c5b84e34358761750e8e9e7666de6532e0f22a31f32bf027f24efb256a1af5d5", + "oracle_kind": "STATE", + "expected_route": "PACKAGE_COMMITTED", + "expected_invariant_ids": [ + "V14" + ] + }, + { + "fixture_case_id": "S40-F012", + "path": "tests/fixtures/s2_40/review_receipt_content_change_supersede.json", + "raw_sha256": "400d4aeb455e5c3ec26c75a552ea91e9af79cb2329998caa1ad72d1be18da8e7", + "oracle_kind": "STATE", + "expected_route": "RESTART_FROM_S2_30", + "expected_invariant_ids": [ + "V14" + ] + }, + { + "fixture_case_id": "S40-F013", + "path": "tests/fixtures/s2_40/partial_write_readback_barrier.json", + "raw_sha256": "467387c12a4cc6469d243de9f0a7948276adb558a99b3b661ccd74a5d17629cf", + "oracle_kind": "BARRIER", + "expected_route": "STOP_TECHNICAL_INCOMPLETE", + "expected_invariant_ids": [ + "V14" + ] + }, + { + "fixture_case_id": "S40-F014", + "path": "tests/fixtures/s2_40/same_binding_idempotence_and_commit_conflict.json", + "raw_sha256": "5536793236fa44da601dc8cf65d94dac32b18ebc2e8dc525a6df92106add57ad", + "oracle_kind": "BARRIER", + "expected_route": "STOP_TECHNICAL_INCOMPLETE", + "expected_invariant_ids": [ + "V14" + ] + }, + { + "fixture_case_id": "S40-F015", + "path": "tests/fixtures/s2_40/candidate_digest_noncycle.json", + "raw_sha256": "74885602909bd19ca1678de781cac26afd34c2f386e98fc0370fd6ff6fb7b8bf", + "oracle_kind": "DIGEST", + "expected_route": "CONTRACT_TEST_ONLY", + "expected_invariant_ids": [ + "V14" + ] + } + ], + "test_sources": [ + { + "path": "tests/s2_40/test_agent_and_inline_parity.py", + "raw_sha256": "04cc4a14790eceea6ec8a9331212ca6e767ef96994b5b26483392d23145417ae" + }, + { + "path": "tests/s2_40/test_c40_reduce_and_conservation.py", + "raw_sha256": "f610eced056420277c67294cdfe76d559073d88a6f42d3e8c5dae8f219fa82d9" + }, + { + "path": "tests/s2_40/test_c45_closed_render.py", + "raw_sha256": "b7cad96735b1a0158644f41703b4f279fdd8b6bc68438f0d7d773b8415ebb460" + }, + { + "path": "tests/s2_40/test_commit_barrier_and_idempotence.py", + "raw_sha256": "714e2f05397d5dcc31159739363f11c9bbaf5a091de55b465e0b474c21f90ea0" + }, + { + "path": "tests/s2_40/test_release_closure.py", + "raw_sha256": "89139e0286facd52c3ce91a1c7b382a584dfc3e6bc337fcb55fbc8eed59f5933" + }, + { + "path": "tests/s2_40/test_review_state_machine.py", + "raw_sha256": "f4dab9bb651b4a3c818c73162b972c8ac3df0f50fbe056e392a12673139b9b4a" + }, + { + "path": "tests/s2_40/test_v01_v18.py", + "raw_sha256": "72be88be1aa9d495b5c9387e45b75e86f44ac76ffe15c04b5ba33ba21fa8943f" + } + ], + "manifest_digest": "186e1f1ef33aa20f84004206adcfe0fb3dbfe0c06383411547548d51e20770ab" +} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/relief_cause_crossmatch_mutations.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/relief_cause_crossmatch_mutations.json new file mode 100644 index 00000000..50baea6e --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/relief_cause_crossmatch_mutations.json @@ -0,0 +1 @@ +{"schema_version":"stage2_s2_40_fixture_payload.v1","header":{"fixture_case_id":"S40-F005","fixture_only":true,"production_admissible":false,"compile_mode":"STRUCTURAL_FIXTURE","oracle_kind":"MUTATION","source_locators":["fixture://s2_40/crossmatch"]},"input":{"atomic_claim_ids":["A1"]},"mutations":[{"mutation_id":"PARTY","target":"cause/party_ref","operation":"REPLACE"},{"mutation_id":"AMOUNT","target":"cause/amount","operation":"REPLACE"}],"expected":{"route":"WAIT_EXTERNAL_REVIEW","run_technical_status":"TECHNICAL_REVIEW_REQUIRED","artifact_technical_status":"TECHNICAL_REVIEW_REQUIRED","legal_readiness":"LAWYER_REVIEW_REQUIRED","expected_invariant_results":{"V09":"FAIL","V11":"FAIL","V18":"FAIL"},"expected_reason_codes":["RELIEF_CAUSE_MISMATCH"]}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/renderer_ast_slot_branch_mutations.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/renderer_ast_slot_branch_mutations.json new file mode 100644 index 00000000..1cc96b9b --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/renderer_ast_slot_branch_mutations.json @@ -0,0 +1,38 @@ +{ + "schema_version": "stage2_s2_40_fixture_payload.v1", + "header": { + "fixture_case_id": "S40-F004", + "fixture_only": true, + "production_admissible": false, + "compile_mode": "STRUCTURAL_FIXTURE", + "oracle_kind": "MUTATION", + "source_locators": ["fixture://s2_40/renderer"] + }, + "input": { + "branch_count": 1, + "unknown_slots": [], + "expected_case_type_catalog_row_count": 137, + "case_type_coverage_legal_approval_status": "PENDING_LEGAL_ADMISSION", + "renderer_legal_approval_status": "PENDING_LEGAL_CONTENT" + }, + "mutations": [ + {"mutation_id":"ZERO","target":"branch_rows","operation":"CLEAR"}, + {"mutation_id":"MULTI","target":"branch_rows","operation":"DUPLICATE"}, + {"mutation_id":"UNKNOWN","target":"slots","operation":"ADD_UNKNOWN"}, + {"mutation_id":"STALE_HASH","target":"renderer_branch.raw_sha256","operation":"SUBSTITUTE_HASH"}, + {"mutation_id":"FREE_TEXT_FALLBACK","target":"render_mode","operation":"SET_FREE_TEXT"}, + {"mutation_id":"LEGACY_STAGE2_PATH","target":"source_path","operation":"SET_V0_TO_V3_PATH"}, + {"mutation_id":"EXTERNAL_PY","target":"execution_path","operation":"SET_EXTERNAL_PY"}, + {"mutation_id":"DIRECTORY_SCAN","target":"input_resolution","operation":"SET_GLOB_SCAN"}, + {"mutation_id":"SECRET_INJECTION","target":"slot_value","operation":"ADD_SECRET_TOKEN"}, + {"mutation_id":"COVERAGE_137_ROW_MISSING","target":"case_type_coverage.rows","operation":"DELETE_ONE_ROW"} + ], + "expected": { + "route": "STOP_TECHNICAL_INCOMPLETE", + "run_technical_status": "TECHNICAL_INCOMPLETE", + "artifact_technical_status": "NOT_PRODUCED", + "legal_readiness": "NOT_ASSESSED", + "expected_invariant_results": {"V10":"FAIL", "V18":"FAIL"}, + "expected_reason_codes": ["CLOSED_RENDERER_REJECTED"] + } +} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_policy_state_aggregation.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_policy_state_aggregation.json new file mode 100644 index 00000000..1201f56d --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_policy_state_aggregation.json @@ -0,0 +1 @@ +{"schema_version":"stage2_s2_40_fixture_payload.v1","header":{"fixture_case_id":"S40-F009","fixture_only":true,"production_admissible":false,"compile_mode":"STRUCTURAL_FIXTURE","oracle_kind":"STATE","source_locators":["fixture://s2_40/review-policy"]},"input":{"policy_status":"PENDING_LEGAL_CONTENT"},"mutations":[],"expected":{"route":"WAIT_EXTERNAL_REVIEW","run_technical_status":"CONSISTENT","artifact_technical_status":"CONSISTENT","legal_readiness":"LAWYER_REVIEW_REQUIRED","expected_invariant_results":{"V18":"PASS"},"expected_reason_codes":["REVIEW_POLICY_NOT_APPROVED"]}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_receipt_approve_resume.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_receipt_approve_resume.json new file mode 100644 index 00000000..27538269 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_receipt_approve_resume.json @@ -0,0 +1,33 @@ +{ + "schema_version": "stage2_s2_40_fixture_payload.v1", + "header": { + "fixture_case_id": "S40-F011", + "fixture_only": true, + "production_admissible": false, + "compile_mode": "STRUCTURAL_FIXTURE", + "oracle_kind": "STATE", + "source_locators": ["fixture://s2_40/receipt-approve"] + }, + "input": { + "disposition": "APPROVE_AS_IS", + "candidate_bytes_unchanged": true, + "rerender_call_count_on_resume": 0, + "external_verification_status": "VERIFIED_BY_EXTERNAL_ADAPTER", + "phase_sequence": [ + "FREEZE", + "AWAITING_EXTERNAL_REVIEW", + "RESUME_VALIDATE", + "READY_TO_COMMIT", + "COMMITTED" + ] + }, + "mutations": [], + "expected": { + "route": "PACKAGE_COMMITTED", + "run_technical_status": "CONSISTENT", + "artifact_technical_status": "CONSISTENT", + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + "expected_invariant_results": {"V14": "PASS"}, + "expected_reason_codes": ["FIXTURE_COMMIT_NOT_FILING_APPROVAL"] + } +} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_receipt_content_change_supersede.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_receipt_content_change_supersede.json new file mode 100644 index 00000000..2dcbe176 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_receipt_content_change_supersede.json @@ -0,0 +1 @@ +{"schema_version":"stage2_s2_40_fixture_payload.v1","header":{"fixture_case_id":"S40-F012","fixture_only":true,"production_admissible":false,"compile_mode":"STRUCTURAL_FIXTURE","oracle_kind":"STATE","source_locators":["fixture://s2_40/receipt-change"]},"input":{"disposition":"CONTENT_CHANGE_REQUIRED","change_scope":"DRAFTING_TEXT_ATOM"},"mutations":[],"expected":{"route":"RESTART_FROM_S2_30","run_technical_status":"CONSISTENT","artifact_technical_status":"CONSISTENT","legal_readiness":"LAWYER_REVIEW_REQUIRED","expected_invariant_results":{"V14":"PASS"},"expected_reason_codes":["CANDIDATE_SUPERSEDED_NO_IN_PLACE_EDIT"]}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_receipt_missing_or_invalid.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_receipt_missing_or_invalid.json new file mode 100644 index 00000000..8e94677d --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/review_receipt_missing_or_invalid.json @@ -0,0 +1 @@ +{"schema_version":"stage2_s2_40_fixture_payload.v1","header":{"fixture_case_id":"S40-F010","fixture_only":true,"production_admissible":false,"compile_mode":"STRUCTURAL_FIXTURE","oracle_kind":"STATE","source_locators":["fixture://s2_40/receipt-invalid"]},"input":{"required_receipts":["STANDARD_ATTORNEY_REVIEW"]},"mutations":[{"mutation_id":"WRONG_DIGEST","target":"receipt/candidate_content_digest","operation":"REPLACE"}],"expected":{"route":"WAIT_EXTERNAL_REVIEW","run_technical_status":"CONSISTENT","artifact_technical_status":"CONSISTENT","legal_readiness":"LAWYER_REVIEW_REQUIRED","expected_invariant_results":{"V14":"PASS"},"expected_reason_codes":["RECEIPT_MISSING_OR_INVALID"]}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/same_binding_idempotence_and_commit_conflict.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/same_binding_idempotence_and_commit_conflict.json new file mode 100644 index 00000000..23ef42df --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/same_binding_idempotence_and_commit_conflict.json @@ -0,0 +1 @@ +{"schema_version":"stage2_s2_40_fixture_payload.v1","header":{"fixture_case_id":"S40-F014","fixture_only":true,"production_admissible":false,"compile_mode":"STRUCTURAL_FIXTURE","oracle_kind":"BARRIER","source_locators":["fixture://s2_40/idempotence"]},"input":{"same_binding_same_bytes":"IDEMPOTENT_SUCCESS"},"mutations":[{"mutation_id":"CONFLICT","target":"final/path","operation":"WRITE_DIFFERENT_BYTES"}],"expected":{"route":"STOP_TECHNICAL_INCOMPLETE","run_technical_status":"TECHNICAL_INCOMPLETE","artifact_technical_status":"NOT_PRODUCED","legal_readiness":"NOT_ASSESSED","expected_invariant_results":{"V14":"FAIL"},"expected_reason_codes":["NO_OVERWRITE_CONFLICT"]}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/v01_v18_invariant_matrix.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/v01_v18_invariant_matrix.json new file mode 100644 index 00000000..5a48395f --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/v01_v18_invariant_matrix.json @@ -0,0 +1,62 @@ +{ + "schema_version": "stage2_s2_40_fixture_payload.v1", + "header": { + "fixture_case_id": "S40-F006", + "fixture_only": true, + "production_admissible": false, + "compile_mode": "STRUCTURAL_FIXTURE", + "oracle_kind": "MUTATION", + "source_locators": [ + "fixture://s2_40/v01-v18", + "discrepancy_report_1.md", + "discrepancy_report_2.md", + "discrepancy_report_3.md", + "discrepancy_report_4.md", + "improvement_merged.md" + ] + }, + "input": { + "invariant_ids": [ + "V01", "V02", "V03", "V04", "V05", "V06", "V07", "V08", "V09", + "V10", "V11", "V12", "V13", "V14", "V15", "V16", "V17", "V18" + ], + "normal_oracle": { + "evaluable": true, + "expected": {"contract_state": "BOUND"}, + "observed": {"contract_state": "BOUND"}, + "evaluation_status": "PASS" + } + }, + "mutations": [ + {"mutation_id":"V01-CONTRADICTION-OR-ABSENCE","target":"upstream_allowlist.path_hash_schema_producer","operation":"SUBSTITUTE_HASH_OR_DELETE_ROW","source_finding_ids":["DR1-STAGE1_TO_STAGE2_FACT_LOSS"],"contradiction":{"observed":"HASH_DRIFT","evaluation_status":"FAIL","reason_code":"V01_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V01_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V02-CONTRADICTION-OR-ABSENCE","target":"bo_les_ledger_signal_evidence_review_universe","operation":"DROP_OR_CONTRADICT_REVIEW_KEY","source_finding_ids":["IR1-CRITICAL_FACT_CONSERVATION"],"contradiction":{"observed":"MULTISET_MISMATCH","evaluation_status":"FAIL","reason_code":"V02_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V02_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V03-CONTRADICTION-OR-ABSENCE","target":"active_domain_slot_crosswalk_namespace_owner","operation":"CHANGE_OR_REMOVE_NAMESPACE_OWNER","source_finding_ids":["IR2-DOMAIN_CONFIG_COMPLETENESS"],"contradiction":{"observed":"OWNER_MISMATCH","evaluation_status":"FAIL","reason_code":"V03_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V03_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V04-CONTRADICTION-OR-ABSENCE","target":"defense_opposing_fact_rebuttal_evidence_chain","operation":"REVERSE_POLARITY_OR_REMOVE_REBUTTAL","source_finding_ids":["IR3-DEFENSE_CHAIN_LOSS"],"contradiction":{"observed":"POLARITY_CONFLICT","evaluation_status":"FAIL","reason_code":"V04_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V04_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V05-CONTRADICTION-OR-ABSENCE","target":"cluster_dependency_precondition_incompatibility","operation":"VIOLATE_OR_REMOVE_PRECONDITION","source_finding_ids":["IM-CLAIM_GROUP_RELATION"],"contradiction":{"observed":"DEPENDENCY_VIOLATED","evaluation_status":"FAIL","reason_code":"V05_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V05_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V06-CONTRADICTION-OR-ABSENCE","target":"atomic_claim.case_type_id.sub_rule_id","operation":"DUPLICATE_MATCH_OR_REMOVE_BINDING","source_finding_ids":["EVAL-M15-CASE-TYPE-PREDICATE"],"contradiction":{"observed":"MULTI_MATCH","evaluation_status":"FAIL","reason_code":"V06_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V06_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V07-CONTRADICTION-OR-ABSENCE","target":"calculator_receipt.operand.law_value","operation":"SUBSTITUTE_UNRECEIPTED_VALUE_OR_REMOVE_RECEIPT","source_finding_ids":["DR3-ACTIO-CALCULATION-LOSS"],"contradiction":{"observed":"UNRECEIPTED_VALUE","evaluation_status":"FAIL","reason_code":"V07_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V07_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V08-CONTRADICTION-OR-ABSENCE","target":"same_recovery_relation_partial_claim_disposition","operation":"DUPLICATE_RECOVERY_OR_REMOVE_RELATION","source_finding_ids":["IM-SAME-RECOVERY-DUPLICATE"],"contradiction":{"observed":"DUPLICATE_RECOVERY","evaluation_status":"FAIL","reason_code":"V08_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V08_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V09-CONTRADICTION-OR-ABSENCE","target":"relief_party_object_amount_period","operation":"ALTER_AMOUNT_OR_REMOVE_FROZEN_PLAN","source_finding_ids":["DR4-RELIEF-OBJECT-DATE-MISMATCH"],"contradiction":{"observed":"PLAN_RELIEF_MISMATCH","evaluation_status":"FAIL","reason_code":"V09_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V09_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V10-CONTRADICTION-OR-ABSENCE","target":"cost_provisional_numbering_annex_order_template_scope","operation":"PERMUTE_ORDER_OR_REMOVE_RENDERER_BRANCH","source_finding_ids":["IM-RELIEF-FORM-NUMBERING"],"contradiction":{"observed":"CLOSED_TEMPLATE_DRIFT","evaluation_status":"FAIL","reason_code":"V10_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V10_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V11-CONTRADICTION-OR-ABSENCE","target":"relief_cause_claim_party_amount_interest_counterperformance","operation":"ALTER_PARTY_OR_REMOVE_CAUSE_LINK","source_finding_ids":["DR1-RELIEF-CAUSE-CROSSMATCH"],"contradiction":{"observed":"RELIEF_CAUSE_MISMATCH","evaluation_status":"FAIL","reason_code":"V11_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V11_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V12-CONTRADICTION-OR-ABSENCE","target":"corpus_snapshot_locator_approval_isolation_crosswalk","operation":"SUBSTITUTE_CORPUS_HASH_OR_REMOVE_LOCATOR","source_finding_ids":["EVAL-M16-CORPUS-NAMESPACE"],"contradiction":{"observed":"CORPUS_HASH_DRIFT","evaluation_status":"FAIL","reason_code":"V12_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V12_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V13-CONTRADICTION-OR-ABSENCE","target":"authority_temporal_addenda_negative_treatment_law_value","operation":"EXPIRE_AUTHORITY_OR_REMOVE_TEMPORAL_SCOPE","source_finding_ids":["EVAL-M13-LAW-VALUE-SEAL"],"contradiction":{"observed":"AUTHORITY_TEMPORAL_DRIFT","evaluation_status":"FAIL","reason_code":"V13_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V13_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V14-CONTRADICTION-OR-ABSENCE","target":"candidate_validation_review_status_intent_readback_commit_barrier_graph","operation":"INTRODUCE_BACKLINK_OR_REMOVE_GRAPH_EDGE","source_finding_ids":["EVAL-M18-NONCYCLIC-SEAL"],"contradiction":{"observed":"DIGEST_CYCLE","evaluation_status":"FAIL","reason_code":"V14_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V14_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V15-CONTRADICTION-OR-ABSENCE","target":"atom_provenance_fact_evidence","operation":"INJECT_UNSOURCED_FACT_OR_REMOVE_EVIDENCE_REF","source_finding_ids":["EVAL-C1-CAUSE-ATOM-PROVENANCE"],"contradiction":{"observed":"UNSOURCED_FACT","evaluation_status":"FAIL","reason_code":"V15_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V15_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V16-CONTRADICTION-OR-ABSENCE","target":"claim_option_partition","operation":"OVERLAP_BUCKETS_OR_REMOVE_OPTION","source_finding_ids":["IR4-OPTION-SILENT-LOSS"],"contradiction":{"observed":"PARTITION_OVERLAP","evaluation_status":"FAIL","reason_code":"V16_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V16_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V17-CONTRADICTION-OR-ABSENCE","target":"party_title_liability_object_exhibit_tokens","operation":"CHANGE_PARTY_TITLE_OR_REMOVE_OBJECT_TOKEN","source_finding_ids":["DR2-OBJECT-EXHIBIT-COMPLETENESS"],"contradiction":{"observed":"OBJECT_TOKEN_MISMATCH","evaluation_status":"FAIL","reason_code":"V17_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V17_ABSENT_UNEVALUABLE"}}, + {"mutation_id":"V18-CONTRADICTION-OR-ABSENCE","target":"closed_ast_independent_rerender_frozen_dependencies","operation":"ALTER_RENDERER_BRANCH_OR_REMOVE_RERENDER_EVIDENCE","source_finding_ids":["IM-CLOSED-RENDERER-INDEPENDENCE"],"contradiction":{"observed":"RERENDER_BYTES_MISMATCH","evaluation_status":"FAIL","reason_code":"V18_CONTRADICTION"},"absence":{"observed":null,"evaluation_status":"UNEVALUABLE","reason_code":"V18_ABSENT_UNEVALUABLE"}} + ], + "expected": { + "route": "CONTRACT_TEST_ONLY", + "run_technical_status": "TECHNICAL_REVIEW_REQUIRED", + "artifact_technical_status": "TECHNICAL_REVIEW_REQUIRED", + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + "expected_invariant_results": { + "V01":"PASS", "V02":"PASS", "V03":"PASS", "V04":"PASS", "V05":"PASS", "V06":"PASS", + "V07":"PASS", "V08":"PASS", "V09":"PASS", "V10":"PASS", "V11":"PASS", "V12":"PASS", + "V13":"PASS", "V14":"PASS", "V15":"PASS", "V16":"PASS", "V17":"PASS", "V18":"PASS" + }, + "expected_reason_codes": ["MATRIX_ORACLE"] + } +} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/valid_full_candidate_and_commit.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/valid_full_candidate_and_commit.json new file mode 100644 index 00000000..5476236b --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/valid_full_candidate_and_commit.json @@ -0,0 +1,40 @@ +{ + "schema_version": "stage2_s2_40_fixture_payload.v1", + "header": { + "fixture_case_id": "S40-F001", + "fixture_only": true, + "production_admissible": false, + "compile_mode": "STRUCTURAL_FIXTURE", + "oracle_kind": "NORMAL", + "source_locators": ["fixture://s2_40/valid"] + }, + "input": { + "all_v_pass": true, + "legal_assets_approved": false, + "review_receipt_external_verification_status": "VERIFIED_BY_EXTERNAL_ADAPTER", + "phase_sequence": [ + "FREEZE", + "AWAITING_EXTERNAL_REVIEW", + "RESUME_VALIDATE", + "READY_TO_COMMIT", + "COMMITTED" + ], + "candidate_bytes_reused_on_resume": true, + "rerender_call_count_on_resume": 0, + "logical_commit_order": [ + "commit/commit_intent.json", + "final/*-EXPLICIT-ALLOWLIST-ONLY", + "commit/stage2_commit_result.json", + "control/run_status.json" + ] + }, + "mutations": [], + "expected": { + "route": "PACKAGE_COMMITTED", + "run_technical_status": "CONSISTENT", + "artifact_technical_status": "CONSISTENT", + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + "expected_invariant_results": {"V01": "PASS", "V18": "PASS"}, + "expected_reason_codes": ["STRUCTURAL_FIXTURE_NOT_PRODUCTION"] + } +} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/valid_status_only_diagnostic.json b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/valid_status_only_diagnostic.json new file mode 100644 index 00000000..9685951f --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/fixtures/s2_40/valid_status_only_diagnostic.json @@ -0,0 +1 @@ +{"schema_version":"stage2_s2_40_fixture_payload.v1","header":{"fixture_case_id":"S40-F002","fixture_only":true,"production_admissible":false,"compile_mode":"STRUCTURAL_FIXTURE","oracle_kind":"BARRIER","source_locators":["fixture://s2_40/status-only"]},"input":{"exact_paths":["ingress/ingress_status.json","ingress/technical_diagnostic.json","ingress/stage1_input_manifest.json","ingress/intake_report.json","review/issue_ledger.base.json"]},"mutations":[],"expected":{"route":"STOP_TECHNICAL_INCOMPLETE","run_technical_status":"TECHNICAL_INCOMPLETE","artifact_technical_status":"NOT_PRODUCED","legal_readiness":"NOT_ASSESSED","expected_invariant_results":{"V01":"PASS"},"expected_reason_codes":["STATUS_ONLY_EXACT_FIVE"]}} diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_cluster_bundle_compile.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_cluster_bundle_compile.py index 2c16e42d..a817f95e 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_cluster_bundle_compile.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_cluster_bundle_compile.py @@ -561,7 +561,7 @@ class ClusterAndBundleTests(unittest.TestCase): self.assertIn("producer_emits_field: false", cache_text) self.assertIn("S2_10", cache_text) - def test_s2_40_status_only_is_deterministic_non_llm_stub(self) -> None: + def test_s2_40_is_implemented_deterministic_non_llm_finalizer(self) -> None: workflow = yaml.safe_load( (ROOT / "workflows/S2_40_final_review_render_and_commit.yml").read_text( encoding="utf-8" @@ -569,16 +569,18 @@ class ClusterAndBundleTests(unittest.TestCase): ) stage = workflow["Agent"]["Stages"][0] task = stage["tasks"][0] + self.assertEqual( + workflow["Agent"]["metadata"]["implementation_status"], + "IMPLEMENTED_OFFLINE_CONTRACT_LIVE_ADMISSION_PENDING", + ) self.assertEqual(task["execution_class"], "NON-LLM-DETERMINISTIC") - self.assertEqual(task["implementation_status"], "STUB_NOT_IMPLEMENTED") - self.assertFalse(task["invocation_allowed"]) + self.assertEqual(task["task_name"], "Task_S2_40_deterministic_finalizer") + self.assertEqual(task["mcp"], "code-executor") + self.assertEqual(task["tool_name"], "run_code") self.assertNotIn("prompts", task) self.assertNotIn("tools", stage) - self.assertFalse(stage["prohibitions"]["llm_call_allowed"]) - self.assertEqual( - stage["handoff_contract"]["final_status_fields"]["legal_readiness"], - ["NOT_ASSESSED"], - ) + self.assertFalse(task["llm_call_allowed"]) + self.assertFalse(task["shell_or_subprocess_allowed"]) expected_inputs = [ "ingress/ingress_status.json", "ingress/technical_diagnostic.json", @@ -586,18 +588,17 @@ class ClusterAndBundleTests(unittest.TestCase): "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"]) + entry = stage["entry_contract"] + self.assertEqual(entry["accepted_routes"], ["TO_S2_40", "TO_S2_40_STATUS_ONLY"]) + self.assertEqual(entry["status_only_exact_input_count"], 5) + self.assertEqual(entry["status_only_exact_inputs"], expected_inputs) + self.assertFalse(entry["status_only_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"]) + self.assertEqual(stage["output_contract"]["final_barrier_path"], "control/run_status.json") + self.assertTrue(stage["output_contract"]["barrier_written_last"]) def test_release_oracle_verifies_active_executor_cross_hashes(self) -> None: release_path = ROOT / "manifest/stage2_release.json" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_cluster_bundle_compile.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_cluster_bundle_compile.txt index 2c16e42d..a817f95e 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_cluster_bundle_compile.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_cluster_bundle_compile.txt @@ -561,7 +561,7 @@ class ClusterAndBundleTests(unittest.TestCase): self.assertIn("producer_emits_field: false", cache_text) self.assertIn("S2_10", cache_text) - def test_s2_40_status_only_is_deterministic_non_llm_stub(self) -> None: + def test_s2_40_is_implemented_deterministic_non_llm_finalizer(self) -> None: workflow = yaml.safe_load( (ROOT / "workflows/S2_40_final_review_render_and_commit.yml").read_text( encoding="utf-8" @@ -569,16 +569,18 @@ class ClusterAndBundleTests(unittest.TestCase): ) stage = workflow["Agent"]["Stages"][0] task = stage["tasks"][0] + self.assertEqual( + workflow["Agent"]["metadata"]["implementation_status"], + "IMPLEMENTED_OFFLINE_CONTRACT_LIVE_ADMISSION_PENDING", + ) self.assertEqual(task["execution_class"], "NON-LLM-DETERMINISTIC") - self.assertEqual(task["implementation_status"], "STUB_NOT_IMPLEMENTED") - self.assertFalse(task["invocation_allowed"]) + self.assertEqual(task["task_name"], "Task_S2_40_deterministic_finalizer") + self.assertEqual(task["mcp"], "code-executor") + self.assertEqual(task["tool_name"], "run_code") self.assertNotIn("prompts", task) self.assertNotIn("tools", stage) - self.assertFalse(stage["prohibitions"]["llm_call_allowed"]) - self.assertEqual( - stage["handoff_contract"]["final_status_fields"]["legal_readiness"], - ["NOT_ASSESSED"], - ) + self.assertFalse(task["llm_call_allowed"]) + self.assertFalse(task["shell_or_subprocess_allowed"]) expected_inputs = [ "ingress/ingress_status.json", "ingress/technical_diagnostic.json", @@ -586,18 +588,17 @@ class ClusterAndBundleTests(unittest.TestCase): "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"]) + entry = stage["entry_contract"] + self.assertEqual(entry["accepted_routes"], ["TO_S2_40", "TO_S2_40_STATUS_ONLY"]) + self.assertEqual(entry["status_only_exact_input_count"], 5) + self.assertEqual(entry["status_only_exact_inputs"], expected_inputs) + self.assertFalse(entry["status_only_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"]) + self.assertEqual(stage["output_contract"]["final_barrier_path"], "control/run_status.json") + self.assertTrue(stage["output_contract"]["barrier_written_last"]) def test_release_oracle_verifies_active_executor_cross_hashes(self) -> None: release_path = ROOT / "manifest/stage2_release.json" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_failure_and_atomic_publish.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_failure_and_atomic_publish.py index 11c5f52b..5b88e32d 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_failure_and_atomic_publish.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_failure_and_atomic_publish.py @@ -572,7 +572,7 @@ class FailureAndAtomicPublishTests(unittest.TestCase): relative = s2._safe_relative_path(row["path"]).as_posix() self.assertIn( PurePosixPath(relative).parent.as_posix(), - {"tests/s2_00", "tests/s2_20"}, + {"tests/s2_00", "tests/s2_20", "tests/s2_40"}, ) self.assertTrue((ROOT / relative).is_file(), relative) observed_sha256 = hashlib.sha256((ROOT / relative).read_bytes()).hexdigest() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_failure_and_atomic_publish.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_failure_and_atomic_publish.txt index 11c5f52b..5b88e32d 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_failure_and_atomic_publish.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_00/test_failure_and_atomic_publish.txt @@ -572,7 +572,7 @@ class FailureAndAtomicPublishTests(unittest.TestCase): relative = s2._safe_relative_path(row["path"]).as_posix() self.assertIn( PurePosixPath(relative).parent.as_posix(), - {"tests/s2_00", "tests/s2_20"}, + {"tests/s2_00", "tests/s2_20", "tests/s2_40"}, ) self.assertTrue((ROOT / relative).is_file(), relative) observed_sha256 = hashlib.sha256((ROOT / relative).read_bytes()).hexdigest() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_10/test_release_adapter_retry.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_10/test_release_adapter_retry.py index b73a2e92..e3a56690 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_10/test_release_adapter_retry.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_10/test_release_adapter_retry.py @@ -2,10 +2,13 @@ from __future__ import annotations import copy import hashlib +import importlib.util import json from pathlib import Path import sys +import tempfile import unittest +from unittest import mock import yaml @@ -16,6 +19,21 @@ sys.path.insert(0, str(ROOT)) from offline_build import validate_s2_10_contract as contract # noqa: E402 +PROJECTION_BUILDER_PATH = ROOT / "offline_build" / "build_s2_10_agent_projection.py" + + +def load_module(name: str, path: Path): + spec = importlib.util.spec_from_file_location(name, path) + if spec is None or spec.loader is None: + raise RuntimeError(path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +projection_builder = load_module("s2_10_projection_builder", PROJECTION_BUILDER_PATH) + + CAPABILITIES = { "HOST_ATOMIC_SINGLE_FLIGHT_CAS_V1", "AGENTBACKEND_MAP_SOURCE_ITEMS_V1", @@ -34,6 +52,59 @@ def load_json(path: Path) -> dict: class ReleaseAdapterRetryTests(unittest.TestCase): + def test_default_check_uses_cumulative_parent_and_downstream_oracles(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + prerequisite_path = root / "projection.yml" + parent_path = root / "stage2_release.json" + child_path = root / "s2_10_release.json" + prerequisite_path.write_bytes(b"projection\n") + parent_path.write_bytes(b"parent\n") + child_path.write_bytes(b"child\n") + prerequisite = {prerequisite_path: b"projection\n"} + parent = {parent_path: b"parent\n"} + child = {child_path: b"child\n"} + with ( + mock.patch.object( + projection_builder, + "prerequisite_outputs", + return_value=(prerequisite, {"phase": "prerequisite"}), + ), + mock.patch.object( + projection_builder, + "cumulative_parent_outputs", + return_value=(parent, {"phase": "cumulative_parent"}), + ), + mock.patch.object( + projection_builder, + "cumulative_child_outputs", + return_value=(child, {"phase": "downstream_child"}), + ), + mock.patch.object( + projection_builder, + "child_only_outputs", + side_effect=AssertionError("observed stale child oracle invoked"), + ) as observed_child, + mock.patch.object( + projection_builder, + "expected_outputs", + side_effect=AssertionError("obsolete S2_10-only parent oracle invoked"), + ) as obsolete, + ): + result = projection_builder.check() + self.assertEqual(result["status"], "S2_10_CUMULATIVE_PACKAGE_CHECK_PASS") + self.assertEqual(len(result["checked_paths"]), 3) + obsolete.assert_not_called() + observed_child.assert_not_called() + + parent_path.write_bytes(b"stale-parent\n") + with self.assertRaises(projection_builder.BuildError) as caught: + projection_builder.check() + self.assertEqual(caught.exception.code, "OFFLINE_PACKAGE_DRIFT") + self.assertIn(parent_path.as_posix(), caught.exception.detail) + obsolete.assert_not_called() + observed_child.assert_not_called() + def test_binding_and_all_external_receipts_are_honestly_pending(self) -> None: binding = yaml.safe_load((ROOT / "deployment" / "stage2_s2_10_llm_binding.yml").read_text()) self.assertEqual(binding["binding_status"], "PENDING_EXTERNAL_PLATFORM_BINDING") diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_10/test_release_adapter_retry.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_10/test_release_adapter_retry.txt index b73a2e92..e3a56690 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_10/test_release_adapter_retry.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_10/test_release_adapter_retry.txt @@ -2,10 +2,13 @@ from __future__ import annotations import copy import hashlib +import importlib.util import json from pathlib import Path import sys +import tempfile import unittest +from unittest import mock import yaml @@ -16,6 +19,21 @@ sys.path.insert(0, str(ROOT)) from offline_build import validate_s2_10_contract as contract # noqa: E402 +PROJECTION_BUILDER_PATH = ROOT / "offline_build" / "build_s2_10_agent_projection.py" + + +def load_module(name: str, path: Path): + spec = importlib.util.spec_from_file_location(name, path) + if spec is None or spec.loader is None: + raise RuntimeError(path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +projection_builder = load_module("s2_10_projection_builder", PROJECTION_BUILDER_PATH) + + CAPABILITIES = { "HOST_ATOMIC_SINGLE_FLIGHT_CAS_V1", "AGENTBACKEND_MAP_SOURCE_ITEMS_V1", @@ -34,6 +52,59 @@ def load_json(path: Path) -> dict: class ReleaseAdapterRetryTests(unittest.TestCase): + def test_default_check_uses_cumulative_parent_and_downstream_oracles(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + prerequisite_path = root / "projection.yml" + parent_path = root / "stage2_release.json" + child_path = root / "s2_10_release.json" + prerequisite_path.write_bytes(b"projection\n") + parent_path.write_bytes(b"parent\n") + child_path.write_bytes(b"child\n") + prerequisite = {prerequisite_path: b"projection\n"} + parent = {parent_path: b"parent\n"} + child = {child_path: b"child\n"} + with ( + mock.patch.object( + projection_builder, + "prerequisite_outputs", + return_value=(prerequisite, {"phase": "prerequisite"}), + ), + mock.patch.object( + projection_builder, + "cumulative_parent_outputs", + return_value=(parent, {"phase": "cumulative_parent"}), + ), + mock.patch.object( + projection_builder, + "cumulative_child_outputs", + return_value=(child, {"phase": "downstream_child"}), + ), + mock.patch.object( + projection_builder, + "child_only_outputs", + side_effect=AssertionError("observed stale child oracle invoked"), + ) as observed_child, + mock.patch.object( + projection_builder, + "expected_outputs", + side_effect=AssertionError("obsolete S2_10-only parent oracle invoked"), + ) as obsolete, + ): + result = projection_builder.check() + self.assertEqual(result["status"], "S2_10_CUMULATIVE_PACKAGE_CHECK_PASS") + self.assertEqual(len(result["checked_paths"]), 3) + obsolete.assert_not_called() + observed_child.assert_not_called() + + parent_path.write_bytes(b"stale-parent\n") + with self.assertRaises(projection_builder.BuildError) as caught: + projection_builder.check() + self.assertEqual(caught.exception.code, "OFFLINE_PACKAGE_DRIFT") + self.assertIn(parent_path.as_posix(), caught.exception.detail) + obsolete.assert_not_called() + observed_child.assert_not_called() + def test_binding_and_all_external_receipts_are_honestly_pending(self) -> None: binding = yaml.safe_load((ROOT / "deployment" / "stage2_s2_10_llm_binding.yml").read_text()) self.assertEqual(binding["binding_status"], "PENDING_EXTERNAL_PLATFORM_BINDING") diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_plan_publish_and_release.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_plan_publish_and_release.py index 4c5f6c98..006125ae 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_plan_publish_and_release.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_plan_publish_and_release.py @@ -175,6 +175,7 @@ class PublishAndReleaseTest(unittest.TestCase): self.assertIn("stage_bindings:", text) self.assertEqual(text.count("stage_id: S2_00"), 1) self.assertEqual(text.count("stage_id: S2_20"), 1) + has_s2_40 = text.count("stage_id: S2_40") == 1 self.assertIn("embedded_task_bindings:", text) self.assertEqual(text.count("host_stage_id: S2_30"), 1) self.assertEqual(text.count("task_name: Task_S2_30_dispatch_planner"), 1) @@ -183,7 +184,8 @@ class PublishAndReleaseTest(unittest.TestCase): encoding="utf-8" ) ) - self.assertEqual(admission["present_deterministic_stage_ids"], ["S2_00", "S2_20"]) + expected_stage_ids = ["S2_00", "S2_20"] + (["S2_40"] if has_s2_40 else []) + self.assertEqual(admission["present_deterministic_stage_ids"], expected_stage_ids) self.assertEqual( admission["embedded_task_admissions"][0]["execution_unit_id"], "S2_30::Task_S2_30_dispatch_planner", @@ -260,6 +262,7 @@ class PublishAndReleaseTest(unittest.TestCase): _write_json(root / "manifest/case_type_coverage.json", _coverage()) _write_json(root / "manifest/s2_20_parent_member_paths.json", []) _write_json(root / "manifest/s2_30_parent_member_paths.json", []) + _write_json(root / "manifest/s2_40_parent_member_paths.json", []) report = VALIDATOR.validate_package( root, root / "manifest/module_manifest.json", diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_plan_publish_and_release.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_plan_publish_and_release.txt index 4c5f6c98..006125ae 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_plan_publish_and_release.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_plan_publish_and_release.txt @@ -175,6 +175,7 @@ class PublishAndReleaseTest(unittest.TestCase): self.assertIn("stage_bindings:", text) self.assertEqual(text.count("stage_id: S2_00"), 1) self.assertEqual(text.count("stage_id: S2_20"), 1) + has_s2_40 = text.count("stage_id: S2_40") == 1 self.assertIn("embedded_task_bindings:", text) self.assertEqual(text.count("host_stage_id: S2_30"), 1) self.assertEqual(text.count("task_name: Task_S2_30_dispatch_planner"), 1) @@ -183,7 +184,8 @@ class PublishAndReleaseTest(unittest.TestCase): encoding="utf-8" ) ) - self.assertEqual(admission["present_deterministic_stage_ids"], ["S2_00", "S2_20"]) + expected_stage_ids = ["S2_00", "S2_20"] + (["S2_40"] if has_s2_40 else []) + self.assertEqual(admission["present_deterministic_stage_ids"], expected_stage_ids) self.assertEqual( admission["embedded_task_admissions"][0]["execution_unit_id"], "S2_30::Task_S2_30_dispatch_planner", @@ -260,6 +262,7 @@ class PublishAndReleaseTest(unittest.TestCase): _write_json(root / "manifest/case_type_coverage.json", _coverage()) _write_json(root / "manifest/s2_20_parent_member_paths.json", []) _write_json(root / "manifest/s2_30_parent_member_paths.json", []) + _write_json(root / "manifest/s2_40_parent_member_paths.json", []) report = VALIDATOR.validate_package( root, root / "manifest/module_manifest.json", diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_regression_manifest_closure.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_regression_manifest_closure.py index 540a1190..ea58c845 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_regression_manifest_closure.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_regression_manifest_closure.py @@ -14,6 +14,7 @@ ROOT = Path(__file__).resolve().parents[2] FIXTURE_ROOT = ROOT / "tests/fixtures/s2_20" MANIFEST_PATH = FIXTURE_ROOT / "regression_manifest.json" GLOBAL_MANIFEST_PATH = ROOT / "tests/fixtures/regression_manifest.json" +S2_40_MANIFEST_PATH = ROOT / "tests/fixtures/s2_40/regression_manifest.json" SHA256 = re.compile(r"^[a-f0-9]{64}$") EXPECTED_FIXTURE_IDS = { "S20-F01-SINGLE-OPTION-GROUP", @@ -206,6 +207,26 @@ class RegressionManifestClosureTest(unittest.TestCase): self.assertTrue(physical.is_file()) self.assertEqual(row["sha256"], sha256(physical)) + def test_global_manifest_binds_s2_40_manifest_payloads_and_seven_tests(self) -> None: + global_manifest = json.loads(GLOBAL_MANIFEST_PATH.read_text(encoding="utf-8")) + binding = global_manifest.get("s2_40_fixture_binding") + self.assertIsInstance(binding, dict) + self.assertEqual(binding["binding_status"], "OFFLINE_BYTES_BOUND_LEGAL_AND_LIVE_PENDING") + self.assertEqual(binding["logical_fixture_count"], 15) + self.assertEqual(binding["payload_file_count"], 15) + self.assertEqual(ROOT / binding["fixture_manifest_path"], S2_40_MANIFEST_PATH) + self.assertEqual(binding["fixture_manifest_sha256"], sha256(S2_40_MANIFEST_PATH)) + local = json.loads(S2_40_MANIFEST_PATH.read_text(encoding="utf-8")) + expected_payloads = {row["path"]: row["raw_sha256"] for row in local["rows"]} + self.assertEqual({row["path"]: row["sha256"] for row in binding["payloads"]}, expected_payloads) + for path, expected in expected_payloads.items(): + self.assertEqual(sha256(ROOT / path), expected) + s2_40_test_rows = [row for row in global_manifest["test_sources"] if row["path"].startswith("tests/s2_40/")] + self.assertEqual(len(s2_40_test_rows), 7) + self.assertEqual({row["path"] for row in s2_40_test_rows}, {row["path"] for row in local["test_sources"]}) + for row in s2_40_test_rows: + self.assertEqual(row["sha256"], sha256(ROOT / row["path"])) + if __name__ == "__main__": unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_regression_manifest_closure.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_regression_manifest_closure.txt index 540a1190..ea58c845 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_regression_manifest_closure.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_20/test_regression_manifest_closure.txt @@ -14,6 +14,7 @@ ROOT = Path(__file__).resolve().parents[2] FIXTURE_ROOT = ROOT / "tests/fixtures/s2_20" MANIFEST_PATH = FIXTURE_ROOT / "regression_manifest.json" GLOBAL_MANIFEST_PATH = ROOT / "tests/fixtures/regression_manifest.json" +S2_40_MANIFEST_PATH = ROOT / "tests/fixtures/s2_40/regression_manifest.json" SHA256 = re.compile(r"^[a-f0-9]{64}$") EXPECTED_FIXTURE_IDS = { "S20-F01-SINGLE-OPTION-GROUP", @@ -206,6 +207,26 @@ class RegressionManifestClosureTest(unittest.TestCase): self.assertTrue(physical.is_file()) self.assertEqual(row["sha256"], sha256(physical)) + def test_global_manifest_binds_s2_40_manifest_payloads_and_seven_tests(self) -> None: + global_manifest = json.loads(GLOBAL_MANIFEST_PATH.read_text(encoding="utf-8")) + binding = global_manifest.get("s2_40_fixture_binding") + self.assertIsInstance(binding, dict) + self.assertEqual(binding["binding_status"], "OFFLINE_BYTES_BOUND_LEGAL_AND_LIVE_PENDING") + self.assertEqual(binding["logical_fixture_count"], 15) + self.assertEqual(binding["payload_file_count"], 15) + self.assertEqual(ROOT / binding["fixture_manifest_path"], S2_40_MANIFEST_PATH) + self.assertEqual(binding["fixture_manifest_sha256"], sha256(S2_40_MANIFEST_PATH)) + local = json.loads(S2_40_MANIFEST_PATH.read_text(encoding="utf-8")) + expected_payloads = {row["path"]: row["raw_sha256"] for row in local["rows"]} + self.assertEqual({row["path"]: row["sha256"] for row in binding["payloads"]}, expected_payloads) + for path, expected in expected_payloads.items(): + self.assertEqual(sha256(ROOT / path), expected) + s2_40_test_rows = [row for row in global_manifest["test_sources"] if row["path"].startswith("tests/s2_40/")] + self.assertEqual(len(s2_40_test_rows), 7) + self.assertEqual({row["path"] for row in s2_40_test_rows}, {row["path"] for row in local["test_sources"]}) + for row in s2_40_test_rows: + self.assertEqual(row["sha256"], sha256(ROOT / row["path"])) + if __name__ == "__main__": unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_agent_contract.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_agent_contract.py index 1714cc49..173c7570 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_agent_contract.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_agent_contract.py @@ -31,6 +31,7 @@ FIXTURE_FILENAMES = ( "invalid_reference_output.json", "owner_singleton_dispatch.json", "partial_write_publish_barrier.json", + "persisted_handoff_chain.json", "rule_requirement_admission_gap.json", "technical_failure.json", "valid_joint_draft_output.json", @@ -60,7 +61,7 @@ class AgentContractTests(unittest.TestCase): hashlib.sha256(binding_raw).hexdigest(), ROOT, ) - self.assertEqual(report["deterministic_stage_ids"], ["S2_00", "S2_20"]) + self.assertEqual(report["deterministic_stage_ids"], ["S2_00", "S2_20", "S2_40"]) self.assertEqual( report["embedded_execution_unit_id"], "S2_30::Task_S2_30_dispatch_planner", @@ -177,7 +178,7 @@ class AgentContractTests(unittest.TestCase): physical_fixtures = sorted( path for path in fixtures.glob("*.json") if path.name != "regression_manifest.json" ) - self.assertEqual(manifest["fixture_count_excluding_manifest"], 13) + self.assertEqual(manifest["fixture_count_excluding_manifest"], 14) self.assertEqual( [row["filename"] for row in manifest["fixtures"]], [path.name for path in physical_fixtures], @@ -209,6 +210,14 @@ class AgentContractTests(unittest.TestCase): contract.validate_instance(item["s30_source_refs"], "s30_source_refs", schema) contract.validate_raw_output(valid, item, schema) + handoff = documents["persisted_handoff_chain.json"]["contract"] + self.assertEqual(handoff["rows_per_claim_group"], len(contract.PART_FAMILIES)) + self.assertEqual(set(handoff["part_families"]), contract.PART_FAMILIES) + self.assertEqual(set(handoff["group_provenance_fields"]), contract.GROUP_PROVENANCE_FIELDS) + self.assertTrue(handoff["manifest_receipt_free"]) + self.assertFalse(handoff["runtime_directory_scan_allowed"]) + self.assertFalse(handoff["runtime_glob_allowed"]) + for row in documents["adverse_fact_worknote_policy.json"]["cases"]: contract.validate_instance(row["input"], "adverse_fact_row", schema) for row in documents["rule_requirement_admission_gap.json"]["cases"]: diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_agent_contract.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_agent_contract.txt index 1714cc49..173c7570 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_agent_contract.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_agent_contract.txt @@ -31,6 +31,7 @@ FIXTURE_FILENAMES = ( "invalid_reference_output.json", "owner_singleton_dispatch.json", "partial_write_publish_barrier.json", + "persisted_handoff_chain.json", "rule_requirement_admission_gap.json", "technical_failure.json", "valid_joint_draft_output.json", @@ -60,7 +61,7 @@ class AgentContractTests(unittest.TestCase): hashlib.sha256(binding_raw).hexdigest(), ROOT, ) - self.assertEqual(report["deterministic_stage_ids"], ["S2_00", "S2_20"]) + self.assertEqual(report["deterministic_stage_ids"], ["S2_00", "S2_20", "S2_40"]) self.assertEqual( report["embedded_execution_unit_id"], "S2_30::Task_S2_30_dispatch_planner", @@ -177,7 +178,7 @@ class AgentContractTests(unittest.TestCase): physical_fixtures = sorted( path for path in fixtures.glob("*.json") if path.name != "regression_manifest.json" ) - self.assertEqual(manifest["fixture_count_excluding_manifest"], 13) + self.assertEqual(manifest["fixture_count_excluding_manifest"], 14) self.assertEqual( [row["filename"] for row in manifest["fixtures"]], [path.name for path in physical_fixtures], @@ -209,6 +210,14 @@ class AgentContractTests(unittest.TestCase): contract.validate_instance(item["s30_source_refs"], "s30_source_refs", schema) contract.validate_raw_output(valid, item, schema) + handoff = documents["persisted_handoff_chain.json"]["contract"] + self.assertEqual(handoff["rows_per_claim_group"], len(contract.PART_FAMILIES)) + self.assertEqual(set(handoff["part_families"]), contract.PART_FAMILIES) + self.assertEqual(set(handoff["group_provenance_fields"]), contract.GROUP_PROVENANCE_FIELDS) + self.assertTrue(handoff["manifest_receipt_free"]) + self.assertFalse(handoff["runtime_directory_scan_allowed"]) + self.assertFalse(handoff["runtime_glob_allowed"]) + for row in documents["adverse_fact_worknote_policy.json"]["cases"]: contract.validate_instance(row["input"], "adverse_fact_row", schema) for row in documents["rule_requirement_admission_gap.json"]["cases"]: diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_prompt_cache_and_boundaries.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_prompt_cache_and_boundaries.py index 6d3f1992..7abadf58 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_prompt_cache_and_boundaries.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_prompt_cache_and_boundaries.py @@ -5,6 +5,7 @@ from pathlib import Path import re import sys import unittest +import yaml ROOT = Path(__file__).resolve().parents[2] @@ -116,6 +117,22 @@ class PromptCacheBoundaryTests(unittest.TestCase): self.assertIn("file_write_allowed: false", workflow) self.assertIn("permanent_id_mint_allowed: false", workflow) + def test_persisted_handoff_echoes_exact_mode_and_producer_provenance(self) -> None: + document = yaml.safe_load(WORKFLOW.read_text(encoding="utf-8")) + contract = document["output_contract"]["handoff_provenance_contract"] + group_fields = contract["group_fields"] + common_fields = contract["common_fields"] + expected_common = [ + "compile_mode", "parent_stage2_release_sha256", "s2_30_release_sha256", + "s2_30_agent_sha256", "s2_30_binding_sha256", "p00_prompt_sha256", + "p30_prompt_sha256", "s2_30_producer_contract_digest", + ] + expected_group_only = ["p31_rule_and_pack_sha256", "p32_common_authority_sha256", "s30_group_slice_sha256"] + self.assertEqual(common_fields, expected_common) + self.assertEqual(group_fields, expected_common[:-1] + expected_group_only + ["s2_30_producer_contract_digest"]) + self.assertEqual(contract["exact_echo_chain"], "PART_TO_MANIFEST_TO_RECEIPT_TO_PUBLISH_STATUS_TO_S2_40_REQUEST") + self.assertEqual(document["output_contract"]["artifact_manifest_core_contract"]["receipt_free"], True) + @unittest.skipUnless(S2_10_AGENT.is_file() and S2_30_AGENT.is_file(), "derived Agent pair not built yet") def test_s2_10_and_s2_30_common_prefix_raw_scalars_are_byte_equal(self) -> None: self.assertEqual( diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_prompt_cache_and_boundaries.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_prompt_cache_and_boundaries.txt index 6d3f1992..7abadf58 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_prompt_cache_and_boundaries.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_prompt_cache_and_boundaries.txt @@ -5,6 +5,7 @@ from pathlib import Path import re import sys import unittest +import yaml ROOT = Path(__file__).resolve().parents[2] @@ -116,6 +117,22 @@ class PromptCacheBoundaryTests(unittest.TestCase): self.assertIn("file_write_allowed: false", workflow) self.assertIn("permanent_id_mint_allowed: false", workflow) + def test_persisted_handoff_echoes_exact_mode_and_producer_provenance(self) -> None: + document = yaml.safe_load(WORKFLOW.read_text(encoding="utf-8")) + contract = document["output_contract"]["handoff_provenance_contract"] + group_fields = contract["group_fields"] + common_fields = contract["common_fields"] + expected_common = [ + "compile_mode", "parent_stage2_release_sha256", "s2_30_release_sha256", + "s2_30_agent_sha256", "s2_30_binding_sha256", "p00_prompt_sha256", + "p30_prompt_sha256", "s2_30_producer_contract_digest", + ] + expected_group_only = ["p31_rule_and_pack_sha256", "p32_common_authority_sha256", "s30_group_slice_sha256"] + self.assertEqual(common_fields, expected_common) + self.assertEqual(group_fields, expected_common[:-1] + expected_group_only + ["s2_30_producer_contract_digest"]) + self.assertEqual(contract["exact_echo_chain"], "PART_TO_MANIFEST_TO_RECEIPT_TO_PUBLISH_STATUS_TO_S2_40_REQUEST") + self.assertEqual(document["output_contract"]["artifact_manifest_core_contract"]["receipt_free"], True) + @unittest.skipUnless(S2_10_AGENT.is_file() and S2_30_AGENT.is_file(), "derived Agent pair not built yet") def test_s2_10_and_s2_30_common_prefix_raw_scalars_are_byte_equal(self) -> None: self.assertEqual( diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_release_adapter_retry.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_release_adapter_retry.py index 685726ac..7e632fe4 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_release_adapter_retry.py +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_release_adapter_retry.py @@ -27,6 +27,190 @@ def producer_material() -> dict: } +def build_handoff_chain() -> dict: + schema = contract.load_schema() + owner = json.loads((FIXTURES / "owner_singleton_dispatch.json").read_text(encoding="utf-8")) + raw_fixture = json.loads((FIXTURES / "valid_joint_draft_output.json").read_text(encoding="utf-8")) + batch = owner["input"] + item = batch["items"][0] + raw_output = raw_fixture["model_output"] + producer_digest = contract.compute_producer_contract_digest(producer_material()) + adapted = contract.adapt_model_output(raw_output, item, producer_digest, schema) + group_id = item["claim_group_id"] + common = { + "compile_mode": batch["compile_mode"], + "parent_stage2_release_sha256": batch["parent_stage2_release_sha256"], + "s2_30_release_sha256": "5" * 64, + "s2_30_agent_sha256": batch["s2_30_agent_sha256"], + "s2_30_binding_sha256": batch["s2_30_binding_sha256"], + "p00_prompt_sha256": batch["p00_prompt_sha256"], + "p30_prompt_sha256": batch["p30_prompt_sha256"], + "s2_30_producer_contract_digest": producer_digest, + } + provenance = { + **common, + "p31_rule_and_pack_sha256": item["p31_rule_and_pack_ref"]["sha256"], + "p32_common_authority_sha256": item["p32_common_authority_ref"]["sha256"], + "s30_group_slice_sha256": item["s30_group_slice_ref"]["sha256"], + } + worknote_ids = sorted( + atom["atom_id"] + for atom in adapted["atoms"] + if atom["drafting_disposition"] == "WORKNOTE_ONLY" + ) + parts = { + "DRAFT_PART": { + "schema_version": "stage2_s2_30_draft_part.v1", + "claim_group_id": group_id, + "provenance": provenance, + "source_plan_sha256": item["source_plan_sha256"], + "drafting_permission": item["drafting_permission"], + "canonical_atoms": adapted["atoms"], + "atomic_claim_coverage": adapted["atomic_claim_coverage"], + }, + "ISSUE_PATCH": { + "schema_version": "stage2_s2_30_issue_patch_part.v1", + "claim_group_id": group_id, + "provenance": provenance, + "source_plan_sha256": item["source_plan_sha256"], + "review_flags": raw_output["review_flags"], + "missing_inputs": raw_output["missing_inputs"], + "adverse_fact_rows": raw_output["adverse_fact_rows"], + }, + "WORKNOTE_PART": { + "schema_version": "stage2_s2_30_worknote_part.v1", + "claim_group_id": group_id, + "provenance": provenance, + "source_plan_sha256": item["source_plan_sha256"], + "worknote_atom_ids": worknote_ids, + "review_flags": raw_output["review_flags"], + "missing_inputs": raw_output["missing_inputs"], + }, + "USAGE_PART": { + "schema_version": "stage2_s2_30_usage_part.v1", + "claim_group_id": group_id, + "provenance": provenance, + "request_id": batch["request_id"], + "model": "gpt-5.6-sol", + "reasoning_effort": "xhigh", + "verbosity": "medium", + "endpoint": "responses", + "input_tokens": 100, + "cached_input_tokens": 80, + "output_tokens": 40, + "usage_observed": True, + }, + } + part_bytes: dict[str, bytes] = {} + rows: list[dict] = [] + for family in sorted(parts): + part = parts[family] + part["part_sha256"] = contract.compute_object_self_hash(part, "part_sha256") + path = f"map_s2_30/{contract.PART_FILENAMES[family]}/{group_id}.json" + raw = contract.canonical_json_bytes(part) + part_bytes[path] = raw + rows.append( + { + "claim_group_id": group_id, + "part_family": family, + "path": path, + "sha256": contract.sha256_bytes(raw), + "schema_ref": contract.PART_SCHEMA_REFS[family], + } + ) + rows.sort(key=lambda row: (row["claim_group_id"], row["part_family"], row["path"])) + manifest = { + "schema_version": "stage2_s2_30_part_manifest_core.v1", + "request_id": batch["request_id"], + "run_binding_digest": batch["run_binding_digest"], + "provenance": common, + "expected_claim_group_ids": [group_id], + "part_rows": rows, + } + manifest["part_manifest_core_sha256"] = contract.compute_object_self_hash( + manifest, "part_manifest_core_sha256" + ) + item_receipt = { + "schema_version": "stage2_s2_30_item_receipt.v1", + "request_id": batch["request_id"], + "run_binding_digest": batch["run_binding_digest"], + "cohort_id": batch["cohort_id"], + "attempt_no": batch["attempt_no"], + "claim_group_id": group_id, + "provenance": provenance, + "dispatch_sha256": "a" * 64, + "raw_model_output_sha256": contract.sha256_bytes(contract.canonical_json_bytes(raw_output)), + "source_plan_sha256": item["source_plan_sha256"], + "canonical_atom_ids": sorted(atom["atom_id"] for atom in adapted["atoms"]), + "part_manifest_core_sha256": manifest["part_manifest_core_sha256"], + "validation_status": "PASS", + "persistence_status": "PUBLISHED", + "read_back_verified": True, + } + item_receipt["receipt_sha256"] = contract.compute_object_self_hash(item_receipt, "receipt_sha256") + item_path = f"map_s2_30/item_receipts/{group_id}.json" + item_raw = contract.canonical_json_bytes(item_receipt) + cohort_receipt = { + "schema_version": "stage2_s2_30_cohort_receipt.v1", + "request_id": batch["request_id"], + "run_binding_digest": batch["run_binding_digest"], + "cohort_id": batch["cohort_id"], + "dispatch_phase": batch["dispatch_phase"], + "attempt_no": batch["attempt_no"], + "provenance": common, + "part_manifest_core_sha256": manifest["part_manifest_core_sha256"], + "input_claim_group_ids": [group_id], + "valid_claim_group_ids": [group_id], + "repair_required_claim_group_ids": [], + "terminal_failure_claim_group_ids": [], + "owner_claim_group_id": group_id, + "owner_complete_verified": True, + "next_action": "FINALIZE_S2_30", + } + cohort_receipt["receipt_sha256"] = contract.compute_object_self_hash(cohort_receipt, "receipt_sha256") + cohort_path = f"map_s2_30/cohort_receipts/{batch['cohort_id']}/attempt-{batch['attempt_no']}.json" + cohort_raw = contract.canonical_json_bytes(cohort_receipt) + publish_status = { + "schema_version": "stage2_s2_30_publish_status.v1", + "request_id": batch["request_id"], + "run_binding_digest": batch["run_binding_digest"], + "parent_stage2_release_sha256": common["parent_stage2_release_sha256"], + "s2_30_release_sha256": common["s2_30_release_sha256"], + "compile_mode": common["compile_mode"], + "provenance": common, + "expected_claim_group_ids": [group_id], + "published_claim_group_ids": [group_id], + "terminal_failure_claim_group_ids": [], + "artifact_manifest_path": "map_s2_30/artifact_manifest.json", + "artifact_manifest_schema_ref": "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", + "artifact_manifest_sha256": contract.sha256_bytes(contract.canonical_json_bytes(manifest)), + "ordered_item_receipts": [ + {"claim_group_id": group_id, "path": item_path, "sha256": contract.sha256_bytes(item_raw)} + ], + "ordered_cohort_receipts": [ + {"path": cohort_path, "sha256": contract.sha256_bytes(cohort_raw)} + ], + "status": "S2_30_COMPLETE", + "route": "TO_S2_40", + "status_written_last": True, + } + publish_status["status_sha256"] = contract.compute_object_self_hash( + publish_status, "status_sha256" + ) + return { + "expected_group_ids": [group_id], + "succeeded_group_ids": [group_id], + "failed_group_ids": [], + "artifact_manifest": manifest, + "part_bytes_by_path": part_bytes, + "item_receipt_bytes_by_path": {item_path: item_raw}, + "cohort_receipt_bytes_by_path": {cohort_path: cohort_raw}, + "publish_status": publish_status, + "publish_status_written": True, + "schema": schema, + } + + class ReleaseAdapterRetryTests(unittest.TestCase): def test_producer_digest_is_deterministic_and_excludes_cycles(self) -> None: material = producer_material() @@ -76,63 +260,75 @@ class ReleaseAdapterRetryTests(unittest.TestCase): self.assertEqual(second["retry_group_ids"], []) def test_status_last_barrier_requires_complete_verified_partition(self) -> None: - group_ids = ["CG-1111111111111111", "CG-2222222222222222"] - def artifact_row(group_id: str, family: str) -> dict: - artifact_hash = contract.sha256_bytes( - contract.canonical_json_bytes({"group": group_id, "family": family}) - ) - receipt_hash = contract.sha256_bytes( - contract.canonical_json_bytes({"group": group_id, "receipt": True}) - ) - row = { - "claim_group_id": group_id, - "artifact_family": family, - "artifact_path": f"map_s2_30/{contract.SUCCESS_ARTIFACT_FILENAMES[family]}/{group_id}.json", - "artifact_sha256": artifact_hash, - "read_back_sha256": artifact_hash, - "immutable_write_status": "CREATED", - "read_back_status": "PASS", - "item_receipt_path": f"map_s2_30/item_receipts/{group_id}.json", - "item_receipt_sha256": receipt_hash, - "item_receipt_persistence_status": "PUBLISHED", - } - if family == "ITEM_RECEIPT": - row["artifact_sha256"] = receipt_hash - row["read_back_sha256"] = receipt_hash - row["artifact_receipt_sha256"] = contract.compute_object_self_hash( - row, "artifact_receipt_sha256" - ) - return row - - success = { - "expected_group_ids": group_ids, - "succeeded_group_ids": group_ids, - "failed_group_ids": [], - "artifact_rows": [ - artifact_row(group_id, family) - for group_id in group_ids - for family in sorted(contract.SUCCESS_ARTIFACT_FAMILIES) - ], - "publish_status_written": True, - } + success = build_handoff_chain() report = contract.validate_publish_barrier(success) self.assertTrue(report["publish_status_allowed"]) + self.assertEqual(report["part_count"], 4) self.assertFalse(report["physical_atomicity_attested"]) early = copy.deepcopy(success) - early["artifact_rows"].pop() + missing_path = next(iter(early["part_bytes_by_path"])) + del early["part_bytes_by_path"][missing_path] with self.assertRaises(contract.ContractError) as caught: contract.validate_publish_barrier(early) - self.assertEqual(caught.exception.code, "STATUS_LAST_BARRIER_VIOLATION") + self.assertEqual(caught.exception.code, "MANIFEST_PART_BYTES_MISSING") forged = copy.deepcopy(success) - forged["artifact_rows"][0]["read_back_sha256"] = "f" * 64 - forged["artifact_rows"][0]["artifact_receipt_sha256"] = contract.compute_object_self_hash( - forged["artifact_rows"][0], "artifact_receipt_sha256" + forged["artifact_manifest"]["part_rows"][0]["sha256"] = "f" * 64 + forged["artifact_manifest"]["part_manifest_core_sha256"] = contract.compute_object_self_hash( + forged["artifact_manifest"], "part_manifest_core_sha256" ) with self.assertRaises(contract.ContractError) as caught: contract.validate_publish_barrier(forged) - self.assertEqual(caught.exception.code, "ARTIFACT_READ_BACK_HASH_MISMATCH") + self.assertEqual(caught.exception.code, "MANIFEST_PART_RAW_HASH_MISMATCH") + + def test_manifest_is_receipt_free_and_chain_is_exactly_enumerated(self) -> None: + bundle = build_handoff_chain() + manifest = bundle["artifact_manifest"] + self.assertFalse(any("receipt" in key.lower() for key in manifest)) + self.assertEqual( + len(manifest["part_rows"]), + len(manifest["expected_claim_group_ids"]) * len(contract.PART_FAMILIES), + ) + + extra = copy.deepcopy(bundle) + extra["part_bytes_by_path"]["map_s2_30/draft_parts/CG-ffffffffffffffff.json"] = b"{}\n" + with self.assertRaises(contract.ContractError) as caught: + contract.validate_publish_barrier(extra) + self.assertEqual(caught.exception.code, "UNENUMERATED_PART_INPUT_FORBIDDEN") + + drift = copy.deepcopy(bundle) + path = next(iter(drift["item_receipt_bytes_by_path"])) + receipt = contract.parse_canonical_json_object(drift["item_receipt_bytes_by_path"][path]) + receipt["part_manifest_core_sha256"] = "f" * 64 + receipt["receipt_sha256"] = contract.compute_object_self_hash(receipt, "receipt_sha256") + raw = contract.canonical_json_bytes(receipt) + drift["item_receipt_bytes_by_path"][path] = raw + drift["publish_status"]["ordered_item_receipts"][0]["sha256"] = contract.sha256_bytes(raw) + drift["publish_status"]["status_sha256"] = contract.compute_object_self_hash( + drift["publish_status"], "status_sha256" + ) + with self.assertRaises(contract.ContractError) as caught: + contract.validate_publish_barrier(drift) + self.assertEqual(caught.exception.code, "RECEIPT_MANIFEST_CORE_HASH_MISMATCH") + + def test_compile_mode_and_full_producer_provenance_echo(self) -> None: + bundle = build_handoff_chain() + manifest = bundle["artifact_manifest"] + first_path = manifest["part_rows"][0]["path"] + part = contract.parse_canonical_json_object(bundle["part_bytes_by_path"][first_path]) + for field in contract.GROUP_PROVENANCE_FIELDS: + self.assertIn(field, part["provenance"]) + self.assertEqual(part["provenance"]["compile_mode"], manifest["provenance"]["compile_mode"]) + + mismatch = copy.deepcopy(bundle) + mismatch["publish_status"]["compile_mode"] = "PRODUCTION" + mismatch["publish_status"]["status_sha256"] = contract.compute_object_self_hash( + mismatch["publish_status"], "status_sha256" + ) + with self.assertRaises(contract.ContractError) as caught: + contract.validate_publish_barrier(mismatch) + self.assertEqual(caught.exception.code, "PUBLISH_COMPILE_MODE_MISMATCH") def test_retry_and_partial_write_fixtures_are_executable_oracles(self) -> None: technical = json.loads((FIXTURES / "technical_failure.json").read_text(encoding="utf-8")) diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_release_adapter_retry.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_release_adapter_retry.txt index 685726ac..7e632fe4 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_release_adapter_retry.txt +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_30/test_release_adapter_retry.txt @@ -27,6 +27,190 @@ def producer_material() -> dict: } +def build_handoff_chain() -> dict: + schema = contract.load_schema() + owner = json.loads((FIXTURES / "owner_singleton_dispatch.json").read_text(encoding="utf-8")) + raw_fixture = json.loads((FIXTURES / "valid_joint_draft_output.json").read_text(encoding="utf-8")) + batch = owner["input"] + item = batch["items"][0] + raw_output = raw_fixture["model_output"] + producer_digest = contract.compute_producer_contract_digest(producer_material()) + adapted = contract.adapt_model_output(raw_output, item, producer_digest, schema) + group_id = item["claim_group_id"] + common = { + "compile_mode": batch["compile_mode"], + "parent_stage2_release_sha256": batch["parent_stage2_release_sha256"], + "s2_30_release_sha256": "5" * 64, + "s2_30_agent_sha256": batch["s2_30_agent_sha256"], + "s2_30_binding_sha256": batch["s2_30_binding_sha256"], + "p00_prompt_sha256": batch["p00_prompt_sha256"], + "p30_prompt_sha256": batch["p30_prompt_sha256"], + "s2_30_producer_contract_digest": producer_digest, + } + provenance = { + **common, + "p31_rule_and_pack_sha256": item["p31_rule_and_pack_ref"]["sha256"], + "p32_common_authority_sha256": item["p32_common_authority_ref"]["sha256"], + "s30_group_slice_sha256": item["s30_group_slice_ref"]["sha256"], + } + worknote_ids = sorted( + atom["atom_id"] + for atom in adapted["atoms"] + if atom["drafting_disposition"] == "WORKNOTE_ONLY" + ) + parts = { + "DRAFT_PART": { + "schema_version": "stage2_s2_30_draft_part.v1", + "claim_group_id": group_id, + "provenance": provenance, + "source_plan_sha256": item["source_plan_sha256"], + "drafting_permission": item["drafting_permission"], + "canonical_atoms": adapted["atoms"], + "atomic_claim_coverage": adapted["atomic_claim_coverage"], + }, + "ISSUE_PATCH": { + "schema_version": "stage2_s2_30_issue_patch_part.v1", + "claim_group_id": group_id, + "provenance": provenance, + "source_plan_sha256": item["source_plan_sha256"], + "review_flags": raw_output["review_flags"], + "missing_inputs": raw_output["missing_inputs"], + "adverse_fact_rows": raw_output["adverse_fact_rows"], + }, + "WORKNOTE_PART": { + "schema_version": "stage2_s2_30_worknote_part.v1", + "claim_group_id": group_id, + "provenance": provenance, + "source_plan_sha256": item["source_plan_sha256"], + "worknote_atom_ids": worknote_ids, + "review_flags": raw_output["review_flags"], + "missing_inputs": raw_output["missing_inputs"], + }, + "USAGE_PART": { + "schema_version": "stage2_s2_30_usage_part.v1", + "claim_group_id": group_id, + "provenance": provenance, + "request_id": batch["request_id"], + "model": "gpt-5.6-sol", + "reasoning_effort": "xhigh", + "verbosity": "medium", + "endpoint": "responses", + "input_tokens": 100, + "cached_input_tokens": 80, + "output_tokens": 40, + "usage_observed": True, + }, + } + part_bytes: dict[str, bytes] = {} + rows: list[dict] = [] + for family in sorted(parts): + part = parts[family] + part["part_sha256"] = contract.compute_object_self_hash(part, "part_sha256") + path = f"map_s2_30/{contract.PART_FILENAMES[family]}/{group_id}.json" + raw = contract.canonical_json_bytes(part) + part_bytes[path] = raw + rows.append( + { + "claim_group_id": group_id, + "part_family": family, + "path": path, + "sha256": contract.sha256_bytes(raw), + "schema_ref": contract.PART_SCHEMA_REFS[family], + } + ) + rows.sort(key=lambda row: (row["claim_group_id"], row["part_family"], row["path"])) + manifest = { + "schema_version": "stage2_s2_30_part_manifest_core.v1", + "request_id": batch["request_id"], + "run_binding_digest": batch["run_binding_digest"], + "provenance": common, + "expected_claim_group_ids": [group_id], + "part_rows": rows, + } + manifest["part_manifest_core_sha256"] = contract.compute_object_self_hash( + manifest, "part_manifest_core_sha256" + ) + item_receipt = { + "schema_version": "stage2_s2_30_item_receipt.v1", + "request_id": batch["request_id"], + "run_binding_digest": batch["run_binding_digest"], + "cohort_id": batch["cohort_id"], + "attempt_no": batch["attempt_no"], + "claim_group_id": group_id, + "provenance": provenance, + "dispatch_sha256": "a" * 64, + "raw_model_output_sha256": contract.sha256_bytes(contract.canonical_json_bytes(raw_output)), + "source_plan_sha256": item["source_plan_sha256"], + "canonical_atom_ids": sorted(atom["atom_id"] for atom in adapted["atoms"]), + "part_manifest_core_sha256": manifest["part_manifest_core_sha256"], + "validation_status": "PASS", + "persistence_status": "PUBLISHED", + "read_back_verified": True, + } + item_receipt["receipt_sha256"] = contract.compute_object_self_hash(item_receipt, "receipt_sha256") + item_path = f"map_s2_30/item_receipts/{group_id}.json" + item_raw = contract.canonical_json_bytes(item_receipt) + cohort_receipt = { + "schema_version": "stage2_s2_30_cohort_receipt.v1", + "request_id": batch["request_id"], + "run_binding_digest": batch["run_binding_digest"], + "cohort_id": batch["cohort_id"], + "dispatch_phase": batch["dispatch_phase"], + "attempt_no": batch["attempt_no"], + "provenance": common, + "part_manifest_core_sha256": manifest["part_manifest_core_sha256"], + "input_claim_group_ids": [group_id], + "valid_claim_group_ids": [group_id], + "repair_required_claim_group_ids": [], + "terminal_failure_claim_group_ids": [], + "owner_claim_group_id": group_id, + "owner_complete_verified": True, + "next_action": "FINALIZE_S2_30", + } + cohort_receipt["receipt_sha256"] = contract.compute_object_self_hash(cohort_receipt, "receipt_sha256") + cohort_path = f"map_s2_30/cohort_receipts/{batch['cohort_id']}/attempt-{batch['attempt_no']}.json" + cohort_raw = contract.canonical_json_bytes(cohort_receipt) + publish_status = { + "schema_version": "stage2_s2_30_publish_status.v1", + "request_id": batch["request_id"], + "run_binding_digest": batch["run_binding_digest"], + "parent_stage2_release_sha256": common["parent_stage2_release_sha256"], + "s2_30_release_sha256": common["s2_30_release_sha256"], + "compile_mode": common["compile_mode"], + "provenance": common, + "expected_claim_group_ids": [group_id], + "published_claim_group_ids": [group_id], + "terminal_failure_claim_group_ids": [], + "artifact_manifest_path": "map_s2_30/artifact_manifest.json", + "artifact_manifest_schema_ref": "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", + "artifact_manifest_sha256": contract.sha256_bytes(contract.canonical_json_bytes(manifest)), + "ordered_item_receipts": [ + {"claim_group_id": group_id, "path": item_path, "sha256": contract.sha256_bytes(item_raw)} + ], + "ordered_cohort_receipts": [ + {"path": cohort_path, "sha256": contract.sha256_bytes(cohort_raw)} + ], + "status": "S2_30_COMPLETE", + "route": "TO_S2_40", + "status_written_last": True, + } + publish_status["status_sha256"] = contract.compute_object_self_hash( + publish_status, "status_sha256" + ) + return { + "expected_group_ids": [group_id], + "succeeded_group_ids": [group_id], + "failed_group_ids": [], + "artifact_manifest": manifest, + "part_bytes_by_path": part_bytes, + "item_receipt_bytes_by_path": {item_path: item_raw}, + "cohort_receipt_bytes_by_path": {cohort_path: cohort_raw}, + "publish_status": publish_status, + "publish_status_written": True, + "schema": schema, + } + + class ReleaseAdapterRetryTests(unittest.TestCase): def test_producer_digest_is_deterministic_and_excludes_cycles(self) -> None: material = producer_material() @@ -76,63 +260,75 @@ class ReleaseAdapterRetryTests(unittest.TestCase): self.assertEqual(second["retry_group_ids"], []) def test_status_last_barrier_requires_complete_verified_partition(self) -> None: - group_ids = ["CG-1111111111111111", "CG-2222222222222222"] - def artifact_row(group_id: str, family: str) -> dict: - artifact_hash = contract.sha256_bytes( - contract.canonical_json_bytes({"group": group_id, "family": family}) - ) - receipt_hash = contract.sha256_bytes( - contract.canonical_json_bytes({"group": group_id, "receipt": True}) - ) - row = { - "claim_group_id": group_id, - "artifact_family": family, - "artifact_path": f"map_s2_30/{contract.SUCCESS_ARTIFACT_FILENAMES[family]}/{group_id}.json", - "artifact_sha256": artifact_hash, - "read_back_sha256": artifact_hash, - "immutable_write_status": "CREATED", - "read_back_status": "PASS", - "item_receipt_path": f"map_s2_30/item_receipts/{group_id}.json", - "item_receipt_sha256": receipt_hash, - "item_receipt_persistence_status": "PUBLISHED", - } - if family == "ITEM_RECEIPT": - row["artifact_sha256"] = receipt_hash - row["read_back_sha256"] = receipt_hash - row["artifact_receipt_sha256"] = contract.compute_object_self_hash( - row, "artifact_receipt_sha256" - ) - return row - - success = { - "expected_group_ids": group_ids, - "succeeded_group_ids": group_ids, - "failed_group_ids": [], - "artifact_rows": [ - artifact_row(group_id, family) - for group_id in group_ids - for family in sorted(contract.SUCCESS_ARTIFACT_FAMILIES) - ], - "publish_status_written": True, - } + success = build_handoff_chain() report = contract.validate_publish_barrier(success) self.assertTrue(report["publish_status_allowed"]) + self.assertEqual(report["part_count"], 4) self.assertFalse(report["physical_atomicity_attested"]) early = copy.deepcopy(success) - early["artifact_rows"].pop() + missing_path = next(iter(early["part_bytes_by_path"])) + del early["part_bytes_by_path"][missing_path] with self.assertRaises(contract.ContractError) as caught: contract.validate_publish_barrier(early) - self.assertEqual(caught.exception.code, "STATUS_LAST_BARRIER_VIOLATION") + self.assertEqual(caught.exception.code, "MANIFEST_PART_BYTES_MISSING") forged = copy.deepcopy(success) - forged["artifact_rows"][0]["read_back_sha256"] = "f" * 64 - forged["artifact_rows"][0]["artifact_receipt_sha256"] = contract.compute_object_self_hash( - forged["artifact_rows"][0], "artifact_receipt_sha256" + forged["artifact_manifest"]["part_rows"][0]["sha256"] = "f" * 64 + forged["artifact_manifest"]["part_manifest_core_sha256"] = contract.compute_object_self_hash( + forged["artifact_manifest"], "part_manifest_core_sha256" ) with self.assertRaises(contract.ContractError) as caught: contract.validate_publish_barrier(forged) - self.assertEqual(caught.exception.code, "ARTIFACT_READ_BACK_HASH_MISMATCH") + self.assertEqual(caught.exception.code, "MANIFEST_PART_RAW_HASH_MISMATCH") + + def test_manifest_is_receipt_free_and_chain_is_exactly_enumerated(self) -> None: + bundle = build_handoff_chain() + manifest = bundle["artifact_manifest"] + self.assertFalse(any("receipt" in key.lower() for key in manifest)) + self.assertEqual( + len(manifest["part_rows"]), + len(manifest["expected_claim_group_ids"]) * len(contract.PART_FAMILIES), + ) + + extra = copy.deepcopy(bundle) + extra["part_bytes_by_path"]["map_s2_30/draft_parts/CG-ffffffffffffffff.json"] = b"{}\n" + with self.assertRaises(contract.ContractError) as caught: + contract.validate_publish_barrier(extra) + self.assertEqual(caught.exception.code, "UNENUMERATED_PART_INPUT_FORBIDDEN") + + drift = copy.deepcopy(bundle) + path = next(iter(drift["item_receipt_bytes_by_path"])) + receipt = contract.parse_canonical_json_object(drift["item_receipt_bytes_by_path"][path]) + receipt["part_manifest_core_sha256"] = "f" * 64 + receipt["receipt_sha256"] = contract.compute_object_self_hash(receipt, "receipt_sha256") + raw = contract.canonical_json_bytes(receipt) + drift["item_receipt_bytes_by_path"][path] = raw + drift["publish_status"]["ordered_item_receipts"][0]["sha256"] = contract.sha256_bytes(raw) + drift["publish_status"]["status_sha256"] = contract.compute_object_self_hash( + drift["publish_status"], "status_sha256" + ) + with self.assertRaises(contract.ContractError) as caught: + contract.validate_publish_barrier(drift) + self.assertEqual(caught.exception.code, "RECEIPT_MANIFEST_CORE_HASH_MISMATCH") + + def test_compile_mode_and_full_producer_provenance_echo(self) -> None: + bundle = build_handoff_chain() + manifest = bundle["artifact_manifest"] + first_path = manifest["part_rows"][0]["path"] + part = contract.parse_canonical_json_object(bundle["part_bytes_by_path"][first_path]) + for field in contract.GROUP_PROVENANCE_FIELDS: + self.assertIn(field, part["provenance"]) + self.assertEqual(part["provenance"]["compile_mode"], manifest["provenance"]["compile_mode"]) + + mismatch = copy.deepcopy(bundle) + mismatch["publish_status"]["compile_mode"] = "PRODUCTION" + mismatch["publish_status"]["status_sha256"] = contract.compute_object_self_hash( + mismatch["publish_status"], "status_sha256" + ) + with self.assertRaises(contract.ContractError) as caught: + contract.validate_publish_barrier(mismatch) + self.assertEqual(caught.exception.code, "PUBLISH_COMPILE_MODE_MISMATCH") def test_retry_and_partial_write_fixtures_are_executable_oracles(self) -> None: technical = json.loads((FIXTURES / "technical_failure.json").read_text(encoding="utf-8")) diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_agent_and_inline_parity.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_agent_and_inline_parity.py new file mode 100644 index 00000000..df301392 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_agent_and_inline_parity.py @@ -0,0 +1,603 @@ +from __future__ import annotations + +import copy +from datetime import datetime, timedelta, timezone +import importlib.util +import json +from pathlib import Path +import sys +import unittest + +import yaml + + +ROOT = Path(__file__).resolve().parents[2] +MAIN = ROOT.parent.parent +sys.path.insert(0, str(ROOT)) +from runtime.validation.invariant_runner import validate_status_only_paths # noqa: E402 + + +class FakeLocalDocs: + def __init__(self, documents: dict[str, bytes]) -> None: + self.documents = documents + + def read_binary(self, path: str) -> bytes: + return self.documents[path] + + +def load_inline_namespace() -> dict: + authoring = yaml.safe_load((MAIN / "Stage_2_S2_40.yml").read_text(encoding="utf-8"))["Agent"] + code = authoring["Stages"][0]["tasks"][0]["parameters"]["code"] + namespace = {"__name__": "s2_40_inline_contract_test"} + exec(compile(code, "Stage_2_S2_40.yml::", "exec"), namespace) + return namespace + + +def load_s2_30_fixture_builder(): + path = ROOT / "tests/s2_30/test_release_adapter_retry.py" + spec = importlib.util.spec_from_file_location("s2_30_handoff_fixture_builder", path) + if spec is None or spec.loader is None: + raise RuntimeError("cannot load the S2_30 canonical fixture builder") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def build_integrated_handoff(namespace: dict) -> tuple[FakeLocalDocs, dict, dict]: + fixture_builder = load_s2_30_fixture_builder() + bundle = fixture_builder.build_handoff_chain() + contract = fixture_builder.contract + report = contract.validate_handoff_chain( + bundle["publish_status"], bundle["artifact_manifest"], bundle["part_bytes_by_path"], + bundle["item_receipt_bytes_by_path"], bundle["cohort_receipt_bytes_by_path"], bundle["schema"], + ) + if report["status"] != "PASS": + raise AssertionError(report) + canonical = namespace["canonical_bytes"] + sha = namespace["digest"] + # This helper isolates canonical S2_30 handoff behavior. Release/schema-member + # verification is covered independently and remains mandatory in production. + release_values = {path: {} for path in namespace["INPUT_SCHEMA_RELS"]} + release_values[namespace["AUTHORITY_RELEASE_REL"]] = {"status": "DEV_UNAVAILABLE"} + release_values[namespace["CASE_TYPE_COVERAGE_REL"]] = { + "status": "DEV_UNAVAILABLE", "release_eligible": False, "coverage_rows": [], + } + release_values[namespace["CASE_TYPE_REGISTRY_REL"]] = {"rows": []} + release_values[namespace["CASE_TYPE_RULE_REGISTRY_REL"]] = {"rows": []} + release_raws = {path: canonical(value) for path, value in release_values.items()} + namespace["read_release_bound_jsons"] = lambda _client, _paths: (release_values, release_raws, []) + namespace["validate_schema_instance"] = lambda *_args, **_kwargs: None + group_id = bundle["expected_group_ids"][0] + root = f"stage2_runs/by-binding/{bundle['artifact_manifest']['run_binding_digest']}" + atoms = json.loads(bundle["part_bytes_by_path"][f"map_s2_30/draft_parts/{group_id}.json"])["canonical_atoms"] + renderer_id = atoms[0]["text_or_slots"]["renderer_id"] + branch_id = atoms[0]["text_or_slots"]["template_branch_id"] + slot_names = sorted({slot["slot_id"] for atom in atoms for slot in atom["text_or_slots"]["slots"]}) + renderer = { + "renderer_id": renderer_id, "status": "APPROVED_LEGAL_CONTENT", "execution_eligible": True, + "typed_slot_contract": {"slot_definitions": [ + {"name": name, "cardinality": "ZERO_OR_ONE"} for name in slot_names + ]}, + "branch_rows": [{ + "branch_id": branch_id, "approval_status": "APPROVED", + "segments": [{"kind": "SLOT", "name": name, "escape": "TEXT"} for name in slot_names], + }], + } + structured_rule = {"status": "APPROVED", "execution_eligible": True} + review_policy = { + "schema_version": "test.review_policy.v1", "registry_id": "S2-20-REVIEW-POLICY", + "status": "APPROVED_LEGAL_CONTENT", "execution_eligible": True, + } + calculation = { + "calculation_receipt_id": "CALC:CR-001", "calculation_status": "CALCULATED", + "missing_law_values": [], + } + plan_objects: dict[str, dict] = { + "plan/renderers/rr001.json": renderer, + "plan/case_type_relief_rules/rule.json": structured_rule, + "plan/review_policy.json": review_policy, + "plan/calculation_receipt.json": calculation, + "plan/exhibit_register.json": {"rows": []}, + "plan/requirements.json": { + "schema_version": "stage2_requirement_fact_pack.v1", "corpus_release_sha256": "9" * 64, + }, + } + atomic_claim_ids = sorted({atom["atomic_claim_id"] for atom in atoms}) + option_ids = sorted({atom["claim_option_id"] for atom in atoms}) + rule_pack = { + "renderer_refs": [{"path": "renderers/rr001.json", "sha256": sha(renderer)}], + "structured_relief_rule_refs": [{ + "path": "case_type_relief_rules/rule.json", "sha256": sha(structured_rule), + }], + "review_policy_refs": [{"path": "review_policy.json", "sha256": sha(review_policy)}], + "ce13_branch_refs": [], + "binding_rows": [{ + "atomic_claim_id": claim_id, "case_type_binding_status": "BOUND", + "sub_rule_binding_status": "BOUND", + } for claim_id in atomic_claim_ids], + } + plan_objects[f"plan/rule_context_packs/{group_id}.json"] = rule_pack + group_slice = { + "claim_group_id": group_id, + "rule_context_pack_ref": { + "path": f"rule_context_packs/{group_id}.json", "sha256": sha(rule_pack), + }, + "calculation_receipt_refs": [{ + "path": "calculation_receipt.json", "sha256": sha(calculation), + }], + "claim_group": { + "claim_option_ids": option_ids, + "option_partition": {"selected": option_ids, "alternative": [], "excluded": [], "deferred": []}, + }, + } + plan_objects[f"plan/group_slices/{group_id}.json"] = group_slice + plan_rows = [] + for path, value in sorted(plan_objects.items()): + raw = canonical(value) + plan_rows.append({ + "path": path, "schema_ref": None, "raw_sha256": sha(raw), + "byte_size": len(raw), "producer_component": "S2_20_FIXTURE", + }) + run_binding_digest = bundle["artifact_manifest"]["run_binding_digest"] + parent_release = bundle["publish_status"]["parent_stage2_release_sha256"] + namespace["EXPECTED_STAGE2_RELEASE_SHA256"] = parent_release + plan_core = { + "schema_version": "stage2_plan_publish_status.v1", "workflow_id": "S2_20", + "run_binding_digest": run_binding_digest, "input_snapshot_digest": "7" * 64, + "parent_stage2_release_sha256": parent_release, + "s2_10_publish_status_sha256": "0" * 64, + "s2_20_agent_sha256": "1" * 64, "s2_20_code_sha256": "2" * 64, + "plan_status": "PLAN_COMPLETE", "route": "TO_S2_30", "consumer_authorized": True, + "group_ids": [group_id], "artifact_rows": plan_rows, + "artifact_set_digest": sha(plan_rows), + "clean_draft_group_ids": [group_id], "review_draft_group_ids": [], + "worknote_only_group_ids": [], "issue_summary": {"issue_count": 0}, + } + plan = {**plan_core, "barrier_sha256": sha(plan_core)} + ingress = { + "schema_version": "stage2_s2_00_ingress_status.v1", "route": "TO_S2_10", + "executable_cluster_ids": ["CL-001"], + "output_barrier": { + "branch": "NORMAL", "written_last": True, + "non_status_artifacts_read_back_verified": True, + }, + "run_binding_receipt": { + "run_binding_digest": run_binding_digest, "stage2_release_digest": parent_release, + }, + } + s210_core = { + "schema_version": "stage2_s2_10_publish_status.v2", + "producer_id": "S2_10_NATIVE_RESULT_ADAPTER", "run_binding_digest": run_binding_digest, + "parent_stage2_release_sha256": parent_release, "status": "COMPLETE", + "route": "TO_S2_20", "status_written_last": True, + } + s210 = {**s210_core, "status_sha256": sha(s210_core)} + manifest_raw = canonical(bundle["artifact_manifest"]) + s230_raw = canonical(bundle["publish_status"]) + documents = { + f"{root}/ingress/ingress_status.json": canonical(ingress), + f"{root}/map_s2_10/s2_10_publish_status.json": canonical(s210), + f"{root}/plan/plan_publish_status.json": canonical(plan), + f"{root}/map_s2_30/s2_30_publish_status.json": s230_raw, + f"{root}/map_s2_30/artifact_manifest.json": manifest_raw, + } + plan["s2_10_publish_status_sha256"] = sha(documents[f"{root}/map_s2_10/s2_10_publish_status.json"]) + plan_core = {key: value for key, value in plan.items() if key != "barrier_sha256"} + plan["barrier_sha256"] = sha(plan_core) + documents[f"{root}/plan/plan_publish_status.json"] = canonical(plan) + for path, raw in bundle["part_bytes_by_path"].items(): + documents[f"{root}/{path}"] = raw + for mapping in (bundle["item_receipt_bytes_by_path"], bundle["cohort_receipt_bytes_by_path"]): + for path, raw in mapping.items(): + documents[f"{root}/{path}"] = raw + for path, value in plan_objects.items(): + documents[f"{root}/{path}"] = canonical(value) + request = { + "run_binding_digest": bundle["artifact_manifest"]["run_binding_digest"], + "stage2_run_root_ref": root, "compile_mode": bundle["artifact_manifest"]["provenance"]["compile_mode"], + "expected_ingress_status_sha256": sha(documents[f"{root}/ingress/ingress_status.json"]), + "expected_s2_10_publish_status_sha256": sha(documents[f"{root}/map_s2_10/s2_10_publish_status.json"]), + "expected_plan_publish_status_sha256": sha(documents[f"{root}/plan/plan_publish_status.json"]), + "expected_s2_30_publish_status_sha256": sha(s230_raw), + "expected_s2_30_artifact_manifest_sha256": sha(manifest_raw), + } + ingress_documents = { + "context/cluster_plan.json": {"executable_cluster_ids": ["CL-001"]}, + "review/issue_ledger.base.json": {"issues": []}, + } + ingress_raws = {path: canonical(value) for path, value in ingress_documents.items()} + namespace["hydrate_ingress_barrier_artifacts"] = lambda *_args, **_kwargs: ( + ingress_documents, ingress_raws, [], + ) + namespace["hydrate_s210_artifacts"] = lambda *_args, **_kwargs: { + "cluster_ids": ["CL-001"], "verdicts": {}, "item_receipts": {}, + "issue_parts": {}, "assumption_parts": {}, "usage_parts": {}, + "wave_receipts": [], "raw_by_path": {}, "source_rows": [], "closure_rows": [], + } + return FakeLocalDocs(documents), request, bundle + + +def assert_static_schema_shape(test: unittest.TestCase, value, schema, defs) -> None: + if "$ref" in schema: + ref = schema["$ref"] + if ref.startswith("#/$defs/"): + return assert_static_schema_shape(test, value, defs[ref.rsplit("/", 1)[1]], defs) + return + if "const" in schema: + test.assertEqual(value, schema["const"]) + schema_type = schema.get("type") + if schema_type == "object": + test.assertIsInstance(value, dict) + required = set(schema.get("required", [])) + test.assertTrue(required <= set(value), required - set(value)) + properties = schema.get("properties", {}) + if schema.get("additionalProperties") is False: + test.assertEqual(set(value), set(properties)) + for key, child in properties.items(): + if key in value: + assert_static_schema_shape(test, value[key], child, defs) + elif schema_type == "array": + test.assertIsInstance(value, list) + for index, child in enumerate(schema.get("prefixItems", [])): + if index < len(value): + assert_static_schema_shape(test, value[index], child, defs) + if isinstance(schema.get("items"), dict): + for child_value in value[len(schema.get("prefixItems", [])):]: + assert_static_schema_shape(test, child_value, schema["items"], defs) + + +class AgentAndContractTests(unittest.TestCase): + def test_inline_freeze_forbids_review_receipts_and_previous_status(self) -> None: + namespace = load_inline_namespace() + namespace["INLINE_USER_HASH"] = "8" * 64 + namespace["INLINE_WORKSPACE_HASH"] = "9" * 64 + request = { + "schema_version": "stage2_s2_40_request.v1", "request_id": "REQ-1", + "run_binding_digest": "a" * 64, "user_identity_hash": namespace["INLINE_USER_HASH"], + "workspace_identity_hash": namespace["INLINE_WORKSPACE_HASH"], + "stage2_run_root_ref": f"stage2_runs/by-binding/{'a' * 64}", + "entry_route": "TO_S2_40", "compile_mode": "PRODUCTION", "requested_transition": "FREEZE", + "expected_previous_run_status_sha256": "b" * 64, "expected_candidate_content_digest": None, + "expected_ingress_status_sha256": "c" * 64, "expected_s2_10_publish_status_sha256": "d" * 64, + "expected_plan_publish_status_sha256": "e" * 64, "expected_s2_30_publish_status_sha256": "f" * 64, + "expected_s2_30_artifact_manifest_sha256": "1" * 64, + "expected_parent_stage2_release_sha256": "2" * 64, "expected_s2_40_agent_sha256": "3" * 64, + "expected_s2_40_executor_binding_sha256": "4" * 64, + "expected_s2_40_inline_code_receipt_sha256": "5" * 64, + "host_cas_receipt_ref": f"stage2_control/host_cas/{'a' * 64}/S2_40/ATTEMPT-1/FREEZE.json", + "host_cas_receipt_sha256": "6" * 64, + "detached_admission_receipt_ref": "Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json", + "detached_admission_receipt_sha256": "7" * 64, + "outer_execution_receipt_target_ref": f"stage2_runs/by-binding/{'a' * 64}/control/s2_40_outer_execution_receipt.json", + "candidate_attempt_id": "ATTEMPT-1", "review_receipt_refs": ["review/receipt.json"], + } + with self.assertRaises(namespace["S240Error"]) as caught: + namespace["validate_request"](namespace["canonical_bytes"](request)) + self.assertEqual(caught.exception.code, "REQUEST_FREEZE_SCOPE") + + def test_inline_mcp_parser_accepts_concatenated_json_and_selects_exact_id(self) -> None: + namespace = load_inline_namespace() + raw = (b'{"jsonrpc":"2.0","id":1,"result":{}}' + b'{"jsonrpc":"2.0","id":2,"result":{"ok":true}}') + parsed = namespace["_parse_mcp_payload"](raw, 2) + self.assertEqual(parsed["result"], {"ok": True}) + + def test_resume_branch_is_frozen_candidate_only(self) -> None: + namespace = load_inline_namespace() + self.assertIn("hydrate_frozen_candidate", namespace) + names = set(namespace["normal_route"].__code__.co_names) + self.assertIn("hydrate_frozen_candidate", names) + self.assertIn("hydrate_normal", names) + + def test_status_only_fixture_executes_exact_five_oracle(self) -> None: + fixture = json.loads((ROOT / "tests/fixtures/s2_40/valid_status_only_diagnostic.json").read_text(encoding="utf-8")) + self.assertEqual(fixture["header"]["compile_mode"], "STRUCTURAL_FIXTURE") + validate_status_only_paths(fixture["input"]["exact_paths"]) + self.assertEqual(fixture["expected"]["expected_reason_codes"], ["STATUS_ONLY_EXACT_FIVE"]) + + def test_inline_schema_engine_enforces_const_and_closed_shape(self) -> None: + namespace = load_inline_namespace() + store = {"schemas/test.schema.json": {"$defs": {"root": { + "type": "object", "additionalProperties": False, "required": ["schema_version"], + "properties": {"schema_version": {"const": "test.v1"}}, + }}}} + namespace["validate_schema_instance"]( + {"schema_version": "test.v1"}, "schemas/test.schema.json#/$defs/root", store, + code="TEST_SCHEMA", + ) + with self.assertRaises(namespace["S240Error"]) as caught: + namespace["validate_schema_instance"]( + {"schema_version": "wrong", "extra": True}, + "schemas/test.schema.json#/$defs/root", store, code="TEST_SCHEMA", + ) + self.assertEqual(caught.exception.code, "TEST_SCHEMA") + + def test_review_receipt_zero_multi_and_invalid_are_closed(self) -> None: + namespace = load_inline_namespace() + review_schema = json.loads((ROOT / "schemas/review_status.schema.json").read_text(encoding="utf-8")) + basis = { + "required_receipt_types": [], "scope_ids": ["CG-1"], "finding_ids": [], + "policy_version": "test.policy.v1", "policy_sha256": "3" * 64, + "reviewer_role": "KOREAN_LAWYER", "reviewer_qualification": "QUALIFIED_KOREAN_LAWYER", + "release_snapshot_sha256s": { + "parent": "4" * 64, "authority": "5" * 64, + "corpus": "6" * 64, "case_type_coverage": "7" * 64, + }, + } + zero_review = namespace["review_subject"]("2" * 64, "8" * 64, "9" * 64, basis) + self.assertEqual(zero_review["requests"], []) + base = { + "review": zero_review, + "candidate_digest": "2" * 64, + "review_policy_result": {"required_receipt_types": []}, + "schema_store": {"schemas/review_status.schema.json": review_schema}, + } + approved, changed, rows = namespace["validate_review_receipts"]( + FakeLocalDocs({}), {"review_receipt_refs": []}, base, + ) + self.assertTrue(approved) + self.assertFalse(changed) + self.assertEqual(rows, []) + required = copy.deepcopy(base) + required["review_policy_result"]["required_receipt_types"] = [ + "STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW", + ] + multi_basis = dict(basis) + multi_basis["required_receipt_types"] = required["review_policy_result"]["required_receipt_types"] + required["review"] = namespace["review_subject"]("2" * 64, "8" * 64, "9" * 64, multi_basis) + self.assertEqual(len(required["review"]["requests"]), 2) + invalid_path = "review/invalid.json" + approved, changed, rows = namespace["validate_review_receipts"]( + FakeLocalDocs({invalid_path: b"{not-json"}), {"review_receipt_refs": [invalid_path]}, required, + ) + self.assertFalse(approved) + self.assertFalse(changed) + self.assertEqual(rows[0]["validation_status"], "INVALID") + + def test_invalid_content_change_receipt_cannot_select_restart_route(self) -> None: + namespace = load_inline_namespace() + review_schema = json.loads((ROOT / "schemas/review_status.schema.json").read_text(encoding="utf-8")) + basis = { + "required_receipt_types": ["STANDARD_ATTORNEY_REVIEW"], + "scope_ids": ["CG-1"], "finding_ids": [], "policy_version": "test.policy.v1", + "policy_sha256": "3" * 64, "reviewer_role": "KOREAN_LAWYER", + "reviewer_qualification": "QUALIFIED_KOREAN_LAWYER", + "release_snapshot_sha256s": { + "parent": "4" * 64, "authority": "5" * 64, + "corpus": "6" * 64, "case_type_coverage": "7" * 64, + }, + } + review = namespace["review_subject"]("2" * 64, "8" * 64, "9" * 64, basis) + expected = review["requests"][0] + now = datetime.now(timezone.utc) + receipt = { + "schema_version": "stage2_s2_40_review_receipt.v1", "receipt_id": "RCPT-1", + "request_id": "WRONG-REQUEST", "receipt_type": expected["receipt_type"], + "candidate_content_digest": "2" * 64, + "review_subject_digest": review["review_subject_digest"], + "finding_ids": expected["core"]["finding_ids"], "scope_ids": expected["core"]["scope_ids"], + "reviewer_role": "KOREAN_LAWYER", "reviewer_qualification": "QUALIFIED_KOREAN_LAWYER", + "issuer_id": "AGENTBACKEND_STAGE2_REVIEW_AUTHORITY", + "key_id": "AGENTBACKEND_STAGE2_REVIEW_KEY_V1", + "signature_algorithm": "AGENTBACKEND_TRUSTED_ATTESTATION_V1", + "signed_material_digest": "a" * 64, "external_verification_attestation_sha256": "b" * 64, + "issued_at": (now - timedelta(minutes=1)).isoformat(), + "expires_at": (now + timedelta(minutes=30)).isoformat(), + "revocation_status": "NOT_REVOKED", + "cryptographic_verification_status": "VERIFIED_BY_EXTERNAL_ADAPTER", + "review_disposition": "CONTENT_CHANGE_REQUIRED", "change_scope": "STAGE1_CONTEXT", + "reason_codes": ["ATTORNEY_CORRECTION_REQUIRED"], + } + path = "review/invalid-content-change.json" + material = { + "review": review, "candidate_digest": "2" * 64, + "review_policy_result": {"required_receipt_types": ["STANDARD_ATTORNEY_REVIEW"]}, + "schema_store": {"schemas/review_status.schema.json": review_schema}, + } + approved, changed, rows = namespace["validate_review_receipts"]( + FakeLocalDocs({path: namespace["canonical_bytes"](receipt)}), + {"review_receipt_refs": [path]}, material, + ) + self.assertFalse(approved) + self.assertFalse(changed) + self.assertEqual(rows[0]["validation_status"], "INVALID") + + def test_frozen_candidate_digest_chain_rejects_mutated_payload(self) -> None: + namespace = load_inline_namespace() + sha = namespace["digest"] + canonical = namespace["canonical_bytes"] + ordered_hashes = ["1" * 64, "2" * 64] + dependency = { + "parent_release_sha256": "3" * 64, + "upstream_barrier_sha256s": ["4" * 64, "5" * 64, "6" * 64, "7" * 64], + "ordered_source_digest": sha(ordered_hashes), + } + manifest = {"run_binding_digest": "8" * 64, "dependency_snapshot": dependency} + worknotes_core = {"rows": []} + ledger = {"issues": []} + assumptions = {"rows": []} + validation_core = {"invariant_results": []} + pre_payloads = { + "upstream_dependency_snapshot.json": (canonical(dependency), None, "application/json"), + "ordered_source_snapshot_preimage.json": (canonical({ + "ordered_sha256s": ordered_hashes, "snapshot_digest": sha(ordered_hashes), + }), None, "application/json"), + "attorney_worknotes.core.json": (canonical(worknotes_core), None, "application/json"), + "issue_ledger.final.json": (canonical(ledger), None, "application/json"), + "assumption_ledger.json": (canonical(assumptions), None, "application/json"), + } + documents = {"claim_relief.md": b"relief\n", "claim_cause.md": b"cause\n", "pleading_draft.md": b"draft\n"} + core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + "run_binding_digest": "8" * 64, + "dependency_snapshot_sha256": sha(dependency), + "candidate_manifest_core_sha256": sha(manifest), + "document_sha256s": { + "claim_relief": sha(documents["claim_relief.md"]), + "claim_cause": sha(documents["claim_cause.md"]), + "pleading_draft": sha(documents["pleading_draft.md"]), + }, + "attorney_worknotes_core_sha256": sha(worknotes_core), + "final_issue_ledger_sha256": sha(ledger), "assumption_ledger_sha256": sha(assumptions), + "validation_core_sha256": sha(validation_core), + "ordered_source_dependency_snapshot_digest": sha(ordered_hashes), + } + expected = sha(core) + envelope = {**core, "candidate_content_digest": expected} + namespace["verify_frozen_candidate_digest_chain"]( + expected, manifest, envelope, pre_payloads, documents, validation_core, + ) + mutated = dict(pre_payloads) + mutated["issue_ledger.final.json"] = (canonical({"issues": ["changed"]}), None, "application/json") + with self.assertRaises(namespace["S240Error"]) as caught: + namespace["verify_frozen_candidate_digest_chain"]( + expected, manifest, envelope, mutated, documents, validation_core, + ) + self.assertEqual(caught.exception.code, "RESUME_CANDIDATE_DIGEST_CHAIN") + + def test_authority_and_full_137_gates_are_release_driven_not_hardcoded(self) -> None: + namespace = load_inline_namespace() + approved = "APPROVED" + coverage_rows = [{ + "case_type_id": f"CT-{index:03d}", "catalog_mapping_status": approved, + "legal_signoff": approved, "technical_verification": "PASS", "release_status": approved, + "downstream_coverage": { + "relief_rule": approved, "renderer": approved, "corpus": approved, + "substantive_profile": approved, "special_law_or_overlay": approved, + "calculation": approved, "review_policy": approved, + }, + "issue_codes": [], + } for index in range(1, 138)] + case_rows = [{ + "catalog_row_id": f"CAT-{index:03d}", "source_ordinal": index, + "source_label": f"case-{index}", "case_type_id": f"CT-{index:03d}", + "claim_capable_disposition": "CLAIM_CAPABLE", + "legal_classification_status": approved, "legal_content_status": approved, + } for index in range(1, 138)] + for index, row in enumerate(coverage_rows, 1): + row["canonical_name_ko"] = f"case-{index}" + rule_rows = [{ + "case_type_id": f"CT-{index:03d}", "legal_classification_status": approved, + "legal_content_status": approved, "rule_branches": [{"legal_content_status": approved}], + "non_claim_disposition": None, "companion_case_type_ids": [], + } for index in range(1, 138)] + registry_hash = "8" * 64 + inputs = { + "rule_packs": {"CG-1": {"binding_rows": [{ + "case_type_binding_status": "BOUND", "sub_rule_binding_status": "BOUND", + }]}}, + "frozen_assets": { + "case_type_relief_rules/rule.yml": {"status": approved, "execution_eligible": True}, + "review_policy.yml": {"registry_id": "S2-20-REVIEW-POLICY", "status": "APPROVED_LEGAL_CONTENT", "execution_eligible": True}, + }, + "calculation_receipts": {}, + "plan_documents": {"requirements.json": { + "schema_version": "stage2_requirement_fact_pack.v1", "corpus_release_sha256": "3" * 64, + }}, + "authority_release": { + "status": "PRODUCTION_ADMITTED", "release_class": "PRODUCTION_RELEASE", + "sealed": True, "signed": True, "executable": True, + "unresolved": [], "signature": "signed", "registry": {"required_status": "VERIFIED"}, + "hash_binding_status": "PRODUCTION_ADMITTED", + }, + "case_type_registry": { + "catalog_source_sha256": "9" * 64, + "catalog_row_ids": [f"CAT-{index:03d}" for index in range(1, 138)], + "rows": case_rows, + }, + "case_type_registry_sha256": registry_hash, + "case_type_rule_registry": { + "case_type_registry_ref": "manifest/case_type_registry.yml", + "case_type_registry_sha256": registry_hash, "rows": rule_rows, + }, + "case_type_rule_registry_sha256": "a" * 64, + "case_type_coverage": { + "status": "FULL_137_PRODUCTION_READY", "release_eligible": True, + "catalog": {"sha256": "9" * 64}, + "registry_dependency": {"path": "manifest/case_type_registry.yml", "sha256": registry_hash}, + "summary": {"total_case_type_rows": 137, "markdown_doc_count": 137}, + "release_scope_catalog_row_ids": [f"CAT-{index:03d}" for index in range(1, 138)], + "excluded_catalog_row_ids": [], + "release_scope_claim_capable_ids": [f"CT-{index:03d}" for index in range(1, 138)], + "coverage_rows": coverage_rows, + }, + } + gates = namespace["legal_gate_snapshot"](inputs, {"legal_assets_admitted": True}) + self.assertTrue(gates["authority"]) + self.assertTrue(gates["case_type_coverage_137"]) + self.assertFalse(gates["required_receipts"]) + + def test_workflow_is_one_deterministic_task_with_two_closed_routes(self) -> None: + workflow = yaml.safe_load((ROOT / "workflows/S2_40_final_review_render_and_commit.yml").read_text(encoding="utf-8"))["Agent"] + self.assertEqual(len(workflow["Stages"]), 1) + stage = workflow["Stages"][0] + self.assertEqual(stage["entry_contract"]["accepted_routes"], ["TO_S2_40", "TO_S2_40_STATUS_ONLY"]) + self.assertEqual(len(stage["tasks"]), 1) + self.assertEqual(stage["tasks"][0]["mcp"], "code-executor") + self.assertEqual(stage["tasks"][0]["tool_name"], "run_code") + self.assertFalse(stage["tasks"][0]["llm_call_allowed"]) + + def test_schema_bundle_has_required_s2_40_defs(self) -> None: + deployment = json.loads((ROOT / "schemas/deployment.schema.json").read_text()) + required = {"s2_40_request", "s2_40_execution_receipt", "s2_40_inline_code_receipt", "s2_40_commit_intent", "s2_40_commit_result"} + self.assertTrue(required <= set(deployment["$defs"])) + request = deployment["$defs"]["s2_40_request"] + self.assertIn("review_receipt_refs", request["required"]) + self.assertEqual(len(request["allOf"]), 3) + receipt = deployment["$defs"]["s2_40_inline_code_receipt"] + self.assertEqual(receipt["properties"]["authoring"]["properties"]["path"]["const"], "Stage_2_S2_40.yml") + actual = json.loads((ROOT / "manifest/s2_40_inline_code_receipt.json").read_text(encoding="utf-8")) + self.assertEqual(set(actual), set(receipt["required"])) + assert_static_schema_shape(self, actual, receipt, deployment["$defs"]) + self.assertEqual(actual["canonical_code"]["code_sha256"], actual["task_contract"]["task"]["code_sha256"]) + review = json.loads((ROOT / "schemas/review_status.schema.json").read_text()) + self.assertTrue({"evaluation_result", "review_request", "review_receipt", "run_status"} <= set(review["$defs"])) + + def test_legal_assets_remain_pending_and_non_executable(self) -> None: + for path in sorted((ROOT / "renderers").glob("R*.yml")): + renderer = json.loads(path.read_text()) + self.assertEqual(renderer["status"], "PENDING_LEGAL_CONTENT") + self.assertFalse(renderer["execution_eligible"]) + self.assertEqual(renderer["branch_rows"], []) + policy = json.loads((ROOT / "registry/review/review_policy_registry.yml").read_text()) + self.assertFalse(policy["execution_eligible"]) + + def test_authoring_contract_when_present(self) -> None: + authoring = MAIN / "Stage_2_S2_40.yml" + if not authoring.is_file(): + self.skipTest("N3 authoring projection not created yet") + agent = yaml.safe_load(authoring.read_text(encoding="utf-8"))["Agent"] + self.assertEqual(len(agent["Stages"]), 1) + tasks = agent["Stages"][0]["tasks"] + self.assertEqual(len(tasks), 1) + self.assertEqual(tasks[0]["mcp"], "code-executor") + + def test_inline_hydrates_schema_valid_canonical_s2_30_handoff(self) -> None: + namespace = load_inline_namespace() + client, request, _ = build_integrated_handoff(namespace) + with self.assertRaises(namespace["S240Error"]) as caught: + namespace["hydrate_normal"](client, request) + self.assertEqual(caught.exception.code, "S220_S230_GROUP_SLICE_HASH") + self.assertIn("frozen S2_20 bytes", caught.exception.message) + + def test_inline_rejects_schema_valid_part_bytes_that_drift_from_manifest(self) -> None: + namespace = load_inline_namespace() + client, request, bundle = build_integrated_handoff(namespace) + group_id = bundle["expected_group_ids"][0] + relative = f"map_s2_30/usage_parts/{group_id}.json" + full_path = f"{request['stage2_run_root_ref']}/{relative}" + usage = json.loads(client.documents[full_path]) + usage["input_tokens"] += 1 + usage["part_sha256"] = namespace["digest"]({key: value for key, value in usage.items() if key != "part_sha256"}) + load_s2_30_fixture_builder().contract.validate_persisted_part( + usage, "USAGE_PART", schema=bundle["schema"], + ) + client.documents[full_path] = namespace["canonical_bytes"](usage) + with self.assertRaises(namespace["S240Error"]) as caught: + namespace["hydrate_normal"](client, request) + self.assertEqual(caught.exception.code, "BOUND_HASH_MISMATCH") + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_agent_and_inline_parity.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_agent_and_inline_parity.txt new file mode 100644 index 00000000..df301392 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_agent_and_inline_parity.txt @@ -0,0 +1,603 @@ +from __future__ import annotations + +import copy +from datetime import datetime, timedelta, timezone +import importlib.util +import json +from pathlib import Path +import sys +import unittest + +import yaml + + +ROOT = Path(__file__).resolve().parents[2] +MAIN = ROOT.parent.parent +sys.path.insert(0, str(ROOT)) +from runtime.validation.invariant_runner import validate_status_only_paths # noqa: E402 + + +class FakeLocalDocs: + def __init__(self, documents: dict[str, bytes]) -> None: + self.documents = documents + + def read_binary(self, path: str) -> bytes: + return self.documents[path] + + +def load_inline_namespace() -> dict: + authoring = yaml.safe_load((MAIN / "Stage_2_S2_40.yml").read_text(encoding="utf-8"))["Agent"] + code = authoring["Stages"][0]["tasks"][0]["parameters"]["code"] + namespace = {"__name__": "s2_40_inline_contract_test"} + exec(compile(code, "Stage_2_S2_40.yml::", "exec"), namespace) + return namespace + + +def load_s2_30_fixture_builder(): + path = ROOT / "tests/s2_30/test_release_adapter_retry.py" + spec = importlib.util.spec_from_file_location("s2_30_handoff_fixture_builder", path) + if spec is None or spec.loader is None: + raise RuntimeError("cannot load the S2_30 canonical fixture builder") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def build_integrated_handoff(namespace: dict) -> tuple[FakeLocalDocs, dict, dict]: + fixture_builder = load_s2_30_fixture_builder() + bundle = fixture_builder.build_handoff_chain() + contract = fixture_builder.contract + report = contract.validate_handoff_chain( + bundle["publish_status"], bundle["artifact_manifest"], bundle["part_bytes_by_path"], + bundle["item_receipt_bytes_by_path"], bundle["cohort_receipt_bytes_by_path"], bundle["schema"], + ) + if report["status"] != "PASS": + raise AssertionError(report) + canonical = namespace["canonical_bytes"] + sha = namespace["digest"] + # This helper isolates canonical S2_30 handoff behavior. Release/schema-member + # verification is covered independently and remains mandatory in production. + release_values = {path: {} for path in namespace["INPUT_SCHEMA_RELS"]} + release_values[namespace["AUTHORITY_RELEASE_REL"]] = {"status": "DEV_UNAVAILABLE"} + release_values[namespace["CASE_TYPE_COVERAGE_REL"]] = { + "status": "DEV_UNAVAILABLE", "release_eligible": False, "coverage_rows": [], + } + release_values[namespace["CASE_TYPE_REGISTRY_REL"]] = {"rows": []} + release_values[namespace["CASE_TYPE_RULE_REGISTRY_REL"]] = {"rows": []} + release_raws = {path: canonical(value) for path, value in release_values.items()} + namespace["read_release_bound_jsons"] = lambda _client, _paths: (release_values, release_raws, []) + namespace["validate_schema_instance"] = lambda *_args, **_kwargs: None + group_id = bundle["expected_group_ids"][0] + root = f"stage2_runs/by-binding/{bundle['artifact_manifest']['run_binding_digest']}" + atoms = json.loads(bundle["part_bytes_by_path"][f"map_s2_30/draft_parts/{group_id}.json"])["canonical_atoms"] + renderer_id = atoms[0]["text_or_slots"]["renderer_id"] + branch_id = atoms[0]["text_or_slots"]["template_branch_id"] + slot_names = sorted({slot["slot_id"] for atom in atoms for slot in atom["text_or_slots"]["slots"]}) + renderer = { + "renderer_id": renderer_id, "status": "APPROVED_LEGAL_CONTENT", "execution_eligible": True, + "typed_slot_contract": {"slot_definitions": [ + {"name": name, "cardinality": "ZERO_OR_ONE"} for name in slot_names + ]}, + "branch_rows": [{ + "branch_id": branch_id, "approval_status": "APPROVED", + "segments": [{"kind": "SLOT", "name": name, "escape": "TEXT"} for name in slot_names], + }], + } + structured_rule = {"status": "APPROVED", "execution_eligible": True} + review_policy = { + "schema_version": "test.review_policy.v1", "registry_id": "S2-20-REVIEW-POLICY", + "status": "APPROVED_LEGAL_CONTENT", "execution_eligible": True, + } + calculation = { + "calculation_receipt_id": "CALC:CR-001", "calculation_status": "CALCULATED", + "missing_law_values": [], + } + plan_objects: dict[str, dict] = { + "plan/renderers/rr001.json": renderer, + "plan/case_type_relief_rules/rule.json": structured_rule, + "plan/review_policy.json": review_policy, + "plan/calculation_receipt.json": calculation, + "plan/exhibit_register.json": {"rows": []}, + "plan/requirements.json": { + "schema_version": "stage2_requirement_fact_pack.v1", "corpus_release_sha256": "9" * 64, + }, + } + atomic_claim_ids = sorted({atom["atomic_claim_id"] for atom in atoms}) + option_ids = sorted({atom["claim_option_id"] for atom in atoms}) + rule_pack = { + "renderer_refs": [{"path": "renderers/rr001.json", "sha256": sha(renderer)}], + "structured_relief_rule_refs": [{ + "path": "case_type_relief_rules/rule.json", "sha256": sha(structured_rule), + }], + "review_policy_refs": [{"path": "review_policy.json", "sha256": sha(review_policy)}], + "ce13_branch_refs": [], + "binding_rows": [{ + "atomic_claim_id": claim_id, "case_type_binding_status": "BOUND", + "sub_rule_binding_status": "BOUND", + } for claim_id in atomic_claim_ids], + } + plan_objects[f"plan/rule_context_packs/{group_id}.json"] = rule_pack + group_slice = { + "claim_group_id": group_id, + "rule_context_pack_ref": { + "path": f"rule_context_packs/{group_id}.json", "sha256": sha(rule_pack), + }, + "calculation_receipt_refs": [{ + "path": "calculation_receipt.json", "sha256": sha(calculation), + }], + "claim_group": { + "claim_option_ids": option_ids, + "option_partition": {"selected": option_ids, "alternative": [], "excluded": [], "deferred": []}, + }, + } + plan_objects[f"plan/group_slices/{group_id}.json"] = group_slice + plan_rows = [] + for path, value in sorted(plan_objects.items()): + raw = canonical(value) + plan_rows.append({ + "path": path, "schema_ref": None, "raw_sha256": sha(raw), + "byte_size": len(raw), "producer_component": "S2_20_FIXTURE", + }) + run_binding_digest = bundle["artifact_manifest"]["run_binding_digest"] + parent_release = bundle["publish_status"]["parent_stage2_release_sha256"] + namespace["EXPECTED_STAGE2_RELEASE_SHA256"] = parent_release + plan_core = { + "schema_version": "stage2_plan_publish_status.v1", "workflow_id": "S2_20", + "run_binding_digest": run_binding_digest, "input_snapshot_digest": "7" * 64, + "parent_stage2_release_sha256": parent_release, + "s2_10_publish_status_sha256": "0" * 64, + "s2_20_agent_sha256": "1" * 64, "s2_20_code_sha256": "2" * 64, + "plan_status": "PLAN_COMPLETE", "route": "TO_S2_30", "consumer_authorized": True, + "group_ids": [group_id], "artifact_rows": plan_rows, + "artifact_set_digest": sha(plan_rows), + "clean_draft_group_ids": [group_id], "review_draft_group_ids": [], + "worknote_only_group_ids": [], "issue_summary": {"issue_count": 0}, + } + plan = {**plan_core, "barrier_sha256": sha(plan_core)} + ingress = { + "schema_version": "stage2_s2_00_ingress_status.v1", "route": "TO_S2_10", + "executable_cluster_ids": ["CL-001"], + "output_barrier": { + "branch": "NORMAL", "written_last": True, + "non_status_artifacts_read_back_verified": True, + }, + "run_binding_receipt": { + "run_binding_digest": run_binding_digest, "stage2_release_digest": parent_release, + }, + } + s210_core = { + "schema_version": "stage2_s2_10_publish_status.v2", + "producer_id": "S2_10_NATIVE_RESULT_ADAPTER", "run_binding_digest": run_binding_digest, + "parent_stage2_release_sha256": parent_release, "status": "COMPLETE", + "route": "TO_S2_20", "status_written_last": True, + } + s210 = {**s210_core, "status_sha256": sha(s210_core)} + manifest_raw = canonical(bundle["artifact_manifest"]) + s230_raw = canonical(bundle["publish_status"]) + documents = { + f"{root}/ingress/ingress_status.json": canonical(ingress), + f"{root}/map_s2_10/s2_10_publish_status.json": canonical(s210), + f"{root}/plan/plan_publish_status.json": canonical(plan), + f"{root}/map_s2_30/s2_30_publish_status.json": s230_raw, + f"{root}/map_s2_30/artifact_manifest.json": manifest_raw, + } + plan["s2_10_publish_status_sha256"] = sha(documents[f"{root}/map_s2_10/s2_10_publish_status.json"]) + plan_core = {key: value for key, value in plan.items() if key != "barrier_sha256"} + plan["barrier_sha256"] = sha(plan_core) + documents[f"{root}/plan/plan_publish_status.json"] = canonical(plan) + for path, raw in bundle["part_bytes_by_path"].items(): + documents[f"{root}/{path}"] = raw + for mapping in (bundle["item_receipt_bytes_by_path"], bundle["cohort_receipt_bytes_by_path"]): + for path, raw in mapping.items(): + documents[f"{root}/{path}"] = raw + for path, value in plan_objects.items(): + documents[f"{root}/{path}"] = canonical(value) + request = { + "run_binding_digest": bundle["artifact_manifest"]["run_binding_digest"], + "stage2_run_root_ref": root, "compile_mode": bundle["artifact_manifest"]["provenance"]["compile_mode"], + "expected_ingress_status_sha256": sha(documents[f"{root}/ingress/ingress_status.json"]), + "expected_s2_10_publish_status_sha256": sha(documents[f"{root}/map_s2_10/s2_10_publish_status.json"]), + "expected_plan_publish_status_sha256": sha(documents[f"{root}/plan/plan_publish_status.json"]), + "expected_s2_30_publish_status_sha256": sha(s230_raw), + "expected_s2_30_artifact_manifest_sha256": sha(manifest_raw), + } + ingress_documents = { + "context/cluster_plan.json": {"executable_cluster_ids": ["CL-001"]}, + "review/issue_ledger.base.json": {"issues": []}, + } + ingress_raws = {path: canonical(value) for path, value in ingress_documents.items()} + namespace["hydrate_ingress_barrier_artifacts"] = lambda *_args, **_kwargs: ( + ingress_documents, ingress_raws, [], + ) + namespace["hydrate_s210_artifacts"] = lambda *_args, **_kwargs: { + "cluster_ids": ["CL-001"], "verdicts": {}, "item_receipts": {}, + "issue_parts": {}, "assumption_parts": {}, "usage_parts": {}, + "wave_receipts": [], "raw_by_path": {}, "source_rows": [], "closure_rows": [], + } + return FakeLocalDocs(documents), request, bundle + + +def assert_static_schema_shape(test: unittest.TestCase, value, schema, defs) -> None: + if "$ref" in schema: + ref = schema["$ref"] + if ref.startswith("#/$defs/"): + return assert_static_schema_shape(test, value, defs[ref.rsplit("/", 1)[1]], defs) + return + if "const" in schema: + test.assertEqual(value, schema["const"]) + schema_type = schema.get("type") + if schema_type == "object": + test.assertIsInstance(value, dict) + required = set(schema.get("required", [])) + test.assertTrue(required <= set(value), required - set(value)) + properties = schema.get("properties", {}) + if schema.get("additionalProperties") is False: + test.assertEqual(set(value), set(properties)) + for key, child in properties.items(): + if key in value: + assert_static_schema_shape(test, value[key], child, defs) + elif schema_type == "array": + test.assertIsInstance(value, list) + for index, child in enumerate(schema.get("prefixItems", [])): + if index < len(value): + assert_static_schema_shape(test, value[index], child, defs) + if isinstance(schema.get("items"), dict): + for child_value in value[len(schema.get("prefixItems", [])):]: + assert_static_schema_shape(test, child_value, schema["items"], defs) + + +class AgentAndContractTests(unittest.TestCase): + def test_inline_freeze_forbids_review_receipts_and_previous_status(self) -> None: + namespace = load_inline_namespace() + namespace["INLINE_USER_HASH"] = "8" * 64 + namespace["INLINE_WORKSPACE_HASH"] = "9" * 64 + request = { + "schema_version": "stage2_s2_40_request.v1", "request_id": "REQ-1", + "run_binding_digest": "a" * 64, "user_identity_hash": namespace["INLINE_USER_HASH"], + "workspace_identity_hash": namespace["INLINE_WORKSPACE_HASH"], + "stage2_run_root_ref": f"stage2_runs/by-binding/{'a' * 64}", + "entry_route": "TO_S2_40", "compile_mode": "PRODUCTION", "requested_transition": "FREEZE", + "expected_previous_run_status_sha256": "b" * 64, "expected_candidate_content_digest": None, + "expected_ingress_status_sha256": "c" * 64, "expected_s2_10_publish_status_sha256": "d" * 64, + "expected_plan_publish_status_sha256": "e" * 64, "expected_s2_30_publish_status_sha256": "f" * 64, + "expected_s2_30_artifact_manifest_sha256": "1" * 64, + "expected_parent_stage2_release_sha256": "2" * 64, "expected_s2_40_agent_sha256": "3" * 64, + "expected_s2_40_executor_binding_sha256": "4" * 64, + "expected_s2_40_inline_code_receipt_sha256": "5" * 64, + "host_cas_receipt_ref": f"stage2_control/host_cas/{'a' * 64}/S2_40/ATTEMPT-1/FREEZE.json", + "host_cas_receipt_sha256": "6" * 64, + "detached_admission_receipt_ref": "Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json", + "detached_admission_receipt_sha256": "7" * 64, + "outer_execution_receipt_target_ref": f"stage2_runs/by-binding/{'a' * 64}/control/s2_40_outer_execution_receipt.json", + "candidate_attempt_id": "ATTEMPT-1", "review_receipt_refs": ["review/receipt.json"], + } + with self.assertRaises(namespace["S240Error"]) as caught: + namespace["validate_request"](namespace["canonical_bytes"](request)) + self.assertEqual(caught.exception.code, "REQUEST_FREEZE_SCOPE") + + def test_inline_mcp_parser_accepts_concatenated_json_and_selects_exact_id(self) -> None: + namespace = load_inline_namespace() + raw = (b'{"jsonrpc":"2.0","id":1,"result":{}}' + b'{"jsonrpc":"2.0","id":2,"result":{"ok":true}}') + parsed = namespace["_parse_mcp_payload"](raw, 2) + self.assertEqual(parsed["result"], {"ok": True}) + + def test_resume_branch_is_frozen_candidate_only(self) -> None: + namespace = load_inline_namespace() + self.assertIn("hydrate_frozen_candidate", namespace) + names = set(namespace["normal_route"].__code__.co_names) + self.assertIn("hydrate_frozen_candidate", names) + self.assertIn("hydrate_normal", names) + + def test_status_only_fixture_executes_exact_five_oracle(self) -> None: + fixture = json.loads((ROOT / "tests/fixtures/s2_40/valid_status_only_diagnostic.json").read_text(encoding="utf-8")) + self.assertEqual(fixture["header"]["compile_mode"], "STRUCTURAL_FIXTURE") + validate_status_only_paths(fixture["input"]["exact_paths"]) + self.assertEqual(fixture["expected"]["expected_reason_codes"], ["STATUS_ONLY_EXACT_FIVE"]) + + def test_inline_schema_engine_enforces_const_and_closed_shape(self) -> None: + namespace = load_inline_namespace() + store = {"schemas/test.schema.json": {"$defs": {"root": { + "type": "object", "additionalProperties": False, "required": ["schema_version"], + "properties": {"schema_version": {"const": "test.v1"}}, + }}}} + namespace["validate_schema_instance"]( + {"schema_version": "test.v1"}, "schemas/test.schema.json#/$defs/root", store, + code="TEST_SCHEMA", + ) + with self.assertRaises(namespace["S240Error"]) as caught: + namespace["validate_schema_instance"]( + {"schema_version": "wrong", "extra": True}, + "schemas/test.schema.json#/$defs/root", store, code="TEST_SCHEMA", + ) + self.assertEqual(caught.exception.code, "TEST_SCHEMA") + + def test_review_receipt_zero_multi_and_invalid_are_closed(self) -> None: + namespace = load_inline_namespace() + review_schema = json.loads((ROOT / "schemas/review_status.schema.json").read_text(encoding="utf-8")) + basis = { + "required_receipt_types": [], "scope_ids": ["CG-1"], "finding_ids": [], + "policy_version": "test.policy.v1", "policy_sha256": "3" * 64, + "reviewer_role": "KOREAN_LAWYER", "reviewer_qualification": "QUALIFIED_KOREAN_LAWYER", + "release_snapshot_sha256s": { + "parent": "4" * 64, "authority": "5" * 64, + "corpus": "6" * 64, "case_type_coverage": "7" * 64, + }, + } + zero_review = namespace["review_subject"]("2" * 64, "8" * 64, "9" * 64, basis) + self.assertEqual(zero_review["requests"], []) + base = { + "review": zero_review, + "candidate_digest": "2" * 64, + "review_policy_result": {"required_receipt_types": []}, + "schema_store": {"schemas/review_status.schema.json": review_schema}, + } + approved, changed, rows = namespace["validate_review_receipts"]( + FakeLocalDocs({}), {"review_receipt_refs": []}, base, + ) + self.assertTrue(approved) + self.assertFalse(changed) + self.assertEqual(rows, []) + required = copy.deepcopy(base) + required["review_policy_result"]["required_receipt_types"] = [ + "STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW", + ] + multi_basis = dict(basis) + multi_basis["required_receipt_types"] = required["review_policy_result"]["required_receipt_types"] + required["review"] = namespace["review_subject"]("2" * 64, "8" * 64, "9" * 64, multi_basis) + self.assertEqual(len(required["review"]["requests"]), 2) + invalid_path = "review/invalid.json" + approved, changed, rows = namespace["validate_review_receipts"]( + FakeLocalDocs({invalid_path: b"{not-json"}), {"review_receipt_refs": [invalid_path]}, required, + ) + self.assertFalse(approved) + self.assertFalse(changed) + self.assertEqual(rows[0]["validation_status"], "INVALID") + + def test_invalid_content_change_receipt_cannot_select_restart_route(self) -> None: + namespace = load_inline_namespace() + review_schema = json.loads((ROOT / "schemas/review_status.schema.json").read_text(encoding="utf-8")) + basis = { + "required_receipt_types": ["STANDARD_ATTORNEY_REVIEW"], + "scope_ids": ["CG-1"], "finding_ids": [], "policy_version": "test.policy.v1", + "policy_sha256": "3" * 64, "reviewer_role": "KOREAN_LAWYER", + "reviewer_qualification": "QUALIFIED_KOREAN_LAWYER", + "release_snapshot_sha256s": { + "parent": "4" * 64, "authority": "5" * 64, + "corpus": "6" * 64, "case_type_coverage": "7" * 64, + }, + } + review = namespace["review_subject"]("2" * 64, "8" * 64, "9" * 64, basis) + expected = review["requests"][0] + now = datetime.now(timezone.utc) + receipt = { + "schema_version": "stage2_s2_40_review_receipt.v1", "receipt_id": "RCPT-1", + "request_id": "WRONG-REQUEST", "receipt_type": expected["receipt_type"], + "candidate_content_digest": "2" * 64, + "review_subject_digest": review["review_subject_digest"], + "finding_ids": expected["core"]["finding_ids"], "scope_ids": expected["core"]["scope_ids"], + "reviewer_role": "KOREAN_LAWYER", "reviewer_qualification": "QUALIFIED_KOREAN_LAWYER", + "issuer_id": "AGENTBACKEND_STAGE2_REVIEW_AUTHORITY", + "key_id": "AGENTBACKEND_STAGE2_REVIEW_KEY_V1", + "signature_algorithm": "AGENTBACKEND_TRUSTED_ATTESTATION_V1", + "signed_material_digest": "a" * 64, "external_verification_attestation_sha256": "b" * 64, + "issued_at": (now - timedelta(minutes=1)).isoformat(), + "expires_at": (now + timedelta(minutes=30)).isoformat(), + "revocation_status": "NOT_REVOKED", + "cryptographic_verification_status": "VERIFIED_BY_EXTERNAL_ADAPTER", + "review_disposition": "CONTENT_CHANGE_REQUIRED", "change_scope": "STAGE1_CONTEXT", + "reason_codes": ["ATTORNEY_CORRECTION_REQUIRED"], + } + path = "review/invalid-content-change.json" + material = { + "review": review, "candidate_digest": "2" * 64, + "review_policy_result": {"required_receipt_types": ["STANDARD_ATTORNEY_REVIEW"]}, + "schema_store": {"schemas/review_status.schema.json": review_schema}, + } + approved, changed, rows = namespace["validate_review_receipts"]( + FakeLocalDocs({path: namespace["canonical_bytes"](receipt)}), + {"review_receipt_refs": [path]}, material, + ) + self.assertFalse(approved) + self.assertFalse(changed) + self.assertEqual(rows[0]["validation_status"], "INVALID") + + def test_frozen_candidate_digest_chain_rejects_mutated_payload(self) -> None: + namespace = load_inline_namespace() + sha = namespace["digest"] + canonical = namespace["canonical_bytes"] + ordered_hashes = ["1" * 64, "2" * 64] + dependency = { + "parent_release_sha256": "3" * 64, + "upstream_barrier_sha256s": ["4" * 64, "5" * 64, "6" * 64, "7" * 64], + "ordered_source_digest": sha(ordered_hashes), + } + manifest = {"run_binding_digest": "8" * 64, "dependency_snapshot": dependency} + worknotes_core = {"rows": []} + ledger = {"issues": []} + assumptions = {"rows": []} + validation_core = {"invariant_results": []} + pre_payloads = { + "upstream_dependency_snapshot.json": (canonical(dependency), None, "application/json"), + "ordered_source_snapshot_preimage.json": (canonical({ + "ordered_sha256s": ordered_hashes, "snapshot_digest": sha(ordered_hashes), + }), None, "application/json"), + "attorney_worknotes.core.json": (canonical(worknotes_core), None, "application/json"), + "issue_ledger.final.json": (canonical(ledger), None, "application/json"), + "assumption_ledger.json": (canonical(assumptions), None, "application/json"), + } + documents = {"claim_relief.md": b"relief\n", "claim_cause.md": b"cause\n", "pleading_draft.md": b"draft\n"} + core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + "run_binding_digest": "8" * 64, + "dependency_snapshot_sha256": sha(dependency), + "candidate_manifest_core_sha256": sha(manifest), + "document_sha256s": { + "claim_relief": sha(documents["claim_relief.md"]), + "claim_cause": sha(documents["claim_cause.md"]), + "pleading_draft": sha(documents["pleading_draft.md"]), + }, + "attorney_worknotes_core_sha256": sha(worknotes_core), + "final_issue_ledger_sha256": sha(ledger), "assumption_ledger_sha256": sha(assumptions), + "validation_core_sha256": sha(validation_core), + "ordered_source_dependency_snapshot_digest": sha(ordered_hashes), + } + expected = sha(core) + envelope = {**core, "candidate_content_digest": expected} + namespace["verify_frozen_candidate_digest_chain"]( + expected, manifest, envelope, pre_payloads, documents, validation_core, + ) + mutated = dict(pre_payloads) + mutated["issue_ledger.final.json"] = (canonical({"issues": ["changed"]}), None, "application/json") + with self.assertRaises(namespace["S240Error"]) as caught: + namespace["verify_frozen_candidate_digest_chain"]( + expected, manifest, envelope, mutated, documents, validation_core, + ) + self.assertEqual(caught.exception.code, "RESUME_CANDIDATE_DIGEST_CHAIN") + + def test_authority_and_full_137_gates_are_release_driven_not_hardcoded(self) -> None: + namespace = load_inline_namespace() + approved = "APPROVED" + coverage_rows = [{ + "case_type_id": f"CT-{index:03d}", "catalog_mapping_status": approved, + "legal_signoff": approved, "technical_verification": "PASS", "release_status": approved, + "downstream_coverage": { + "relief_rule": approved, "renderer": approved, "corpus": approved, + "substantive_profile": approved, "special_law_or_overlay": approved, + "calculation": approved, "review_policy": approved, + }, + "issue_codes": [], + } for index in range(1, 138)] + case_rows = [{ + "catalog_row_id": f"CAT-{index:03d}", "source_ordinal": index, + "source_label": f"case-{index}", "case_type_id": f"CT-{index:03d}", + "claim_capable_disposition": "CLAIM_CAPABLE", + "legal_classification_status": approved, "legal_content_status": approved, + } for index in range(1, 138)] + for index, row in enumerate(coverage_rows, 1): + row["canonical_name_ko"] = f"case-{index}" + rule_rows = [{ + "case_type_id": f"CT-{index:03d}", "legal_classification_status": approved, + "legal_content_status": approved, "rule_branches": [{"legal_content_status": approved}], + "non_claim_disposition": None, "companion_case_type_ids": [], + } for index in range(1, 138)] + registry_hash = "8" * 64 + inputs = { + "rule_packs": {"CG-1": {"binding_rows": [{ + "case_type_binding_status": "BOUND", "sub_rule_binding_status": "BOUND", + }]}}, + "frozen_assets": { + "case_type_relief_rules/rule.yml": {"status": approved, "execution_eligible": True}, + "review_policy.yml": {"registry_id": "S2-20-REVIEW-POLICY", "status": "APPROVED_LEGAL_CONTENT", "execution_eligible": True}, + }, + "calculation_receipts": {}, + "plan_documents": {"requirements.json": { + "schema_version": "stage2_requirement_fact_pack.v1", "corpus_release_sha256": "3" * 64, + }}, + "authority_release": { + "status": "PRODUCTION_ADMITTED", "release_class": "PRODUCTION_RELEASE", + "sealed": True, "signed": True, "executable": True, + "unresolved": [], "signature": "signed", "registry": {"required_status": "VERIFIED"}, + "hash_binding_status": "PRODUCTION_ADMITTED", + }, + "case_type_registry": { + "catalog_source_sha256": "9" * 64, + "catalog_row_ids": [f"CAT-{index:03d}" for index in range(1, 138)], + "rows": case_rows, + }, + "case_type_registry_sha256": registry_hash, + "case_type_rule_registry": { + "case_type_registry_ref": "manifest/case_type_registry.yml", + "case_type_registry_sha256": registry_hash, "rows": rule_rows, + }, + "case_type_rule_registry_sha256": "a" * 64, + "case_type_coverage": { + "status": "FULL_137_PRODUCTION_READY", "release_eligible": True, + "catalog": {"sha256": "9" * 64}, + "registry_dependency": {"path": "manifest/case_type_registry.yml", "sha256": registry_hash}, + "summary": {"total_case_type_rows": 137, "markdown_doc_count": 137}, + "release_scope_catalog_row_ids": [f"CAT-{index:03d}" for index in range(1, 138)], + "excluded_catalog_row_ids": [], + "release_scope_claim_capable_ids": [f"CT-{index:03d}" for index in range(1, 138)], + "coverage_rows": coverage_rows, + }, + } + gates = namespace["legal_gate_snapshot"](inputs, {"legal_assets_admitted": True}) + self.assertTrue(gates["authority"]) + self.assertTrue(gates["case_type_coverage_137"]) + self.assertFalse(gates["required_receipts"]) + + def test_workflow_is_one_deterministic_task_with_two_closed_routes(self) -> None: + workflow = yaml.safe_load((ROOT / "workflows/S2_40_final_review_render_and_commit.yml").read_text(encoding="utf-8"))["Agent"] + self.assertEqual(len(workflow["Stages"]), 1) + stage = workflow["Stages"][0] + self.assertEqual(stage["entry_contract"]["accepted_routes"], ["TO_S2_40", "TO_S2_40_STATUS_ONLY"]) + self.assertEqual(len(stage["tasks"]), 1) + self.assertEqual(stage["tasks"][0]["mcp"], "code-executor") + self.assertEqual(stage["tasks"][0]["tool_name"], "run_code") + self.assertFalse(stage["tasks"][0]["llm_call_allowed"]) + + def test_schema_bundle_has_required_s2_40_defs(self) -> None: + deployment = json.loads((ROOT / "schemas/deployment.schema.json").read_text()) + required = {"s2_40_request", "s2_40_execution_receipt", "s2_40_inline_code_receipt", "s2_40_commit_intent", "s2_40_commit_result"} + self.assertTrue(required <= set(deployment["$defs"])) + request = deployment["$defs"]["s2_40_request"] + self.assertIn("review_receipt_refs", request["required"]) + self.assertEqual(len(request["allOf"]), 3) + receipt = deployment["$defs"]["s2_40_inline_code_receipt"] + self.assertEqual(receipt["properties"]["authoring"]["properties"]["path"]["const"], "Stage_2_S2_40.yml") + actual = json.loads((ROOT / "manifest/s2_40_inline_code_receipt.json").read_text(encoding="utf-8")) + self.assertEqual(set(actual), set(receipt["required"])) + assert_static_schema_shape(self, actual, receipt, deployment["$defs"]) + self.assertEqual(actual["canonical_code"]["code_sha256"], actual["task_contract"]["task"]["code_sha256"]) + review = json.loads((ROOT / "schemas/review_status.schema.json").read_text()) + self.assertTrue({"evaluation_result", "review_request", "review_receipt", "run_status"} <= set(review["$defs"])) + + def test_legal_assets_remain_pending_and_non_executable(self) -> None: + for path in sorted((ROOT / "renderers").glob("R*.yml")): + renderer = json.loads(path.read_text()) + self.assertEqual(renderer["status"], "PENDING_LEGAL_CONTENT") + self.assertFalse(renderer["execution_eligible"]) + self.assertEqual(renderer["branch_rows"], []) + policy = json.loads((ROOT / "registry/review/review_policy_registry.yml").read_text()) + self.assertFalse(policy["execution_eligible"]) + + def test_authoring_contract_when_present(self) -> None: + authoring = MAIN / "Stage_2_S2_40.yml" + if not authoring.is_file(): + self.skipTest("N3 authoring projection not created yet") + agent = yaml.safe_load(authoring.read_text(encoding="utf-8"))["Agent"] + self.assertEqual(len(agent["Stages"]), 1) + tasks = agent["Stages"][0]["tasks"] + self.assertEqual(len(tasks), 1) + self.assertEqual(tasks[0]["mcp"], "code-executor") + + def test_inline_hydrates_schema_valid_canonical_s2_30_handoff(self) -> None: + namespace = load_inline_namespace() + client, request, _ = build_integrated_handoff(namespace) + with self.assertRaises(namespace["S240Error"]) as caught: + namespace["hydrate_normal"](client, request) + self.assertEqual(caught.exception.code, "S220_S230_GROUP_SLICE_HASH") + self.assertIn("frozen S2_20 bytes", caught.exception.message) + + def test_inline_rejects_schema_valid_part_bytes_that_drift_from_manifest(self) -> None: + namespace = load_inline_namespace() + client, request, bundle = build_integrated_handoff(namespace) + group_id = bundle["expected_group_ids"][0] + relative = f"map_s2_30/usage_parts/{group_id}.json" + full_path = f"{request['stage2_run_root_ref']}/{relative}" + usage = json.loads(client.documents[full_path]) + usage["input_tokens"] += 1 + usage["part_sha256"] = namespace["digest"]({key: value for key, value in usage.items() if key != "part_sha256"}) + load_s2_30_fixture_builder().contract.validate_persisted_part( + usage, "USAGE_PART", schema=bundle["schema"], + ) + client.documents[full_path] = namespace["canonical_bytes"](usage) + with self.assertRaises(namespace["S240Error"]) as caught: + namespace["hydrate_normal"](client, request) + self.assertEqual(caught.exception.code, "BOUND_HASH_MISMATCH") + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c40_reduce_and_conservation.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c40_reduce_and_conservation.py new file mode 100644 index 00000000..a6be2731 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c40_reduce_and_conservation.py @@ -0,0 +1,55 @@ +from __future__ import annotations + +import json +from pathlib import Path +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +from runtime.c45_document_assembler import AssemblyError, reduce_immutable_rows, validate_exact_group_part_set, validate_option_partition # noqa: E402 + + +class C40Tests(unittest.TestCase): + def test_part_set_fixture_executes_missing_duplicate_and_cross_group_oracles(self) -> None: + fixture = json.loads((ROOT / "tests/fixtures/s2_40/part_set_missing_duplicate_or_cross_group.json").read_text(encoding="utf-8")) + groups = fixture["input"]["expected_groups"] + families = ("DRAFT_PART", "ISSUE_PATCH", "WORKNOTE_PART", "USAGE_PART") + parts = [{"part_id": f"{group}-{family}", "group_id": group, "part_family": family} for group in groups for family in families] + validate_exact_group_part_set(parts, expected_group_ids=groups) + for mutation in fixture["mutations"]: + mutated = [dict(row) for row in parts] + if mutation["mutation_id"] == "MISSING": + mutated.pop() + elif mutation["mutation_id"] == "DUP": + mutated.append(dict(mutated[0])) + else: + mutated[0]["group_id"] = "CROSS_GROUP" + with self.subTest(mutation=mutation["mutation_id"]), self.assertRaisesRegex(AssemblyError, "PART_SET"): + validate_exact_group_part_set(mutated, expected_group_ids=groups) + self.assertEqual(fixture["expected"]["expected_reason_codes"], ["PART_SET_NOT_EXACT"]) + + def test_stable_reduce_and_equivalent_duplicate(self) -> None: + parts = [ + {"part_id": "P2", "group_id": "G2", "rows": [{"row_id": "R2", "value": 2}]}, + {"part_id": "P1", "group_id": "G1", "rows": [{"row_id": "R1", "value": 1}, {"row_id": "R2", "value": 2}]}, + ] + self.assertEqual([row["row_id"] for row in reduce_immutable_rows(parts, id_field="row_id", row_field="rows")], ["R1", "R2"]) + + def test_conflicting_duplicate_and_part_duplicate_are_rejected(self) -> None: + with self.assertRaisesRegex(AssemblyError, "IMMUTABLE_ROW_CONFLICT"): + reduce_immutable_rows([ + {"part_id": "P1", "rows": [{"row_id": "R1", "value": 1}]}, + {"part_id": "P2", "rows": [{"row_id": "R1", "value": 2}]}, + ], id_field="row_id", row_field="rows") + with self.assertRaisesRegex(AssemblyError, "PART_ID"): + reduce_immutable_rows([{"part_id": "P1", "rows": []}, {"part_id": "P1", "rows": []}], id_field="row_id", row_field="rows") + + def test_option_partition_is_exact(self) -> None: + validate_option_partition(["O1", "O2"], {"selected": ["O1"], "alternative": ["O2"], "excluded": [], "deferred": []}) + with self.assertRaisesRegex(AssemblyError, "OVERLAP"): + validate_option_partition(["O1"], {"selected": ["O1"], "alternative": ["O1"], "excluded": [], "deferred": []}) + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c40_reduce_and_conservation.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c40_reduce_and_conservation.txt new file mode 100644 index 00000000..a6be2731 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c40_reduce_and_conservation.txt @@ -0,0 +1,55 @@ +from __future__ import annotations + +import json +from pathlib import Path +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +from runtime.c45_document_assembler import AssemblyError, reduce_immutable_rows, validate_exact_group_part_set, validate_option_partition # noqa: E402 + + +class C40Tests(unittest.TestCase): + def test_part_set_fixture_executes_missing_duplicate_and_cross_group_oracles(self) -> None: + fixture = json.loads((ROOT / "tests/fixtures/s2_40/part_set_missing_duplicate_or_cross_group.json").read_text(encoding="utf-8")) + groups = fixture["input"]["expected_groups"] + families = ("DRAFT_PART", "ISSUE_PATCH", "WORKNOTE_PART", "USAGE_PART") + parts = [{"part_id": f"{group}-{family}", "group_id": group, "part_family": family} for group in groups for family in families] + validate_exact_group_part_set(parts, expected_group_ids=groups) + for mutation in fixture["mutations"]: + mutated = [dict(row) for row in parts] + if mutation["mutation_id"] == "MISSING": + mutated.pop() + elif mutation["mutation_id"] == "DUP": + mutated.append(dict(mutated[0])) + else: + mutated[0]["group_id"] = "CROSS_GROUP" + with self.subTest(mutation=mutation["mutation_id"]), self.assertRaisesRegex(AssemblyError, "PART_SET"): + validate_exact_group_part_set(mutated, expected_group_ids=groups) + self.assertEqual(fixture["expected"]["expected_reason_codes"], ["PART_SET_NOT_EXACT"]) + + def test_stable_reduce_and_equivalent_duplicate(self) -> None: + parts = [ + {"part_id": "P2", "group_id": "G2", "rows": [{"row_id": "R2", "value": 2}]}, + {"part_id": "P1", "group_id": "G1", "rows": [{"row_id": "R1", "value": 1}, {"row_id": "R2", "value": 2}]}, + ] + self.assertEqual([row["row_id"] for row in reduce_immutable_rows(parts, id_field="row_id", row_field="rows")], ["R1", "R2"]) + + def test_conflicting_duplicate_and_part_duplicate_are_rejected(self) -> None: + with self.assertRaisesRegex(AssemblyError, "IMMUTABLE_ROW_CONFLICT"): + reduce_immutable_rows([ + {"part_id": "P1", "rows": [{"row_id": "R1", "value": 1}]}, + {"part_id": "P2", "rows": [{"row_id": "R1", "value": 2}]}, + ], id_field="row_id", row_field="rows") + with self.assertRaisesRegex(AssemblyError, "PART_ID"): + reduce_immutable_rows([{"part_id": "P1", "rows": []}, {"part_id": "P1", "rows": []}], id_field="row_id", row_field="rows") + + def test_option_partition_is_exact(self) -> None: + validate_option_partition(["O1", "O2"], {"selected": ["O1"], "alternative": ["O2"], "excluded": [], "deferred": []}) + with self.assertRaisesRegex(AssemblyError, "OVERLAP"): + validate_option_partition(["O1"], {"selected": ["O1"], "alternative": ["O1"], "excluded": [], "deferred": []}) + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c45_closed_render.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c45_closed_render.py new file mode 100644 index 00000000..0646693a --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c45_closed_render.py @@ -0,0 +1,116 @@ +from __future__ import annotations + +from copy import deepcopy +import json +from pathlib import Path +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +from runtime.c45_document_assembler import AssemblyError, assemble_documents, build_usage_projection, relief_cause_crossmatch # noqa: E402 +from runtime.rendering.closed_renderer import ClosedRenderError, escape_slot_value, provisional_execution_eligible, render_closed # noqa: E402 +from runtime.validation.invariant_runner import InvariantError, validate_reference_closure # noqa: E402 + + +def fixture_renderer(): + return { + "schema_version": "fixture.v1", "renderer_id": "RF", "renderer_kind": "STRUCTURAL", + "status": "STRUCTURAL_FIXTURE_ONLY", "execution_eligible": True, + "stage2_20_role": "SELECT_AND_SEAL_ONLY", "stage2_40_role": "CLOSED_RENDER", + "typed_slot_contract": {"slot_definitions": [{"name": "value", "type": "STRING", "cardinality": "EXACTLY_ONE"}]}, + "closed_ast_contract": {"normalization_version": "NFC_LF_UTF8_V1", "allowed_atom_types": ["RELIEF_ATOM"]}, + "branch_rows": [{"branch_id": "B1", "approval_status": "APPROVED", "predicates": [{"field": "kind", "op": "EQ", "value": "X"}], "segments": [{"kind": "LITERAL", "value": "["}, {"kind": "SLOT", "name": "value", "escape": "PLAIN_TEXT"}, {"kind": "LITERAL", "value": "]"}]}], + "closure": {"zero_match_issue_code": "ZERO", "multi_match_issue_code": "MULTI"}, "review": {"status": "FIXTURE_ONLY"}, + } + + +class C45Tests(unittest.TestCase): + def test_renderer_fixture_mutations_execute_closed_oracles(self) -> None: + fixture = json.loads((ROOT / "tests/fixtures/s2_40/renderer_ast_slot_branch_mutations.json").read_text(encoding="utf-8")) + for mutation in fixture["mutations"]: + descriptor, slots = fixture_renderer(), {"value": "A"} + if mutation["mutation_id"] == "ZERO": + descriptor["branch_rows"] = [] + elif mutation["mutation_id"] == "MULTI": + duplicate = deepcopy(descriptor["branch_rows"][0]); duplicate["branch_id"] = "B2" + descriptor["branch_rows"].append(duplicate) + else: + slots["unknown"] = "B" + with self.subTest(mutation=mutation["mutation_id"]), self.assertRaises(ClosedRenderError): + render_closed(descriptor, {"kind": "X"}, slots, atom_type="RELIEF_ATOM", allow_fixture=True) + + def test_crossmatch_numbering_and_reference_fixtures_execute(self) -> None: + cross = json.loads((ROOT / "tests/fixtures/s2_40/relief_cause_crossmatch_mutations.json").read_text(encoding="utf-8")) + findings = relief_cause_crossmatch( + [{"atomic_claim_id": "A1", "claimant_ref": "P1", "defendant_ref": "P2", "amount_ref": "M1"}], + [{"atomic_claim_id": "A1", "claimant_ref": "P1", "defendant_ref": "P2", "amount_ref": "M2"}], + ) + self.assertIn("RELIEF_CAUSE_AMOUNT_REF_MISMATCH::A1", findings) + self.assertEqual(cross["expected"]["expected_reason_codes"], ["RELIEF_CAUSE_MISMATCH"]) + + numbering = json.loads((ROOT / "tests/fixtures/s2_40/cost_provisional_execution_numbering.json").read_text(encoding="utf-8")) + base = {"proprietary_claim": True, "performance_atom": True, "atomic_branch_provisional_execution_policy": "ALLOW", "approved_authority_ref_is_valid": True, "dependent_on_constitutive_judgment": False, "renderer_id": "R03"} + self.assertFalse(provisional_execution_eligible(base)) + self.assertIn("INELIGIBLE", {row["mutation_id"] for row in numbering["mutations"]}) + + refs = json.loads((ROOT / "tests/fixtures/s2_40/exhibit_object_party_title_completeness.json").read_text(encoding="utf-8")) + validate_reference_closure(refs["input"]["refs"], refs["input"]["refs"]) + with self.assertRaisesRegex(InvariantError, "DANGLING"): + validate_reference_closure(refs["input"]["refs"], refs["input"]["refs"][:-1]) + + def test_closed_render_and_document_order(self) -> None: + rendered = render_closed(fixture_renderer(), {"kind": "X"}, {"value": "A"}, atom_type="RELIEF_ATOM", allow_fixture=True) + self.assertEqual(rendered["rendered_text"], "[A]") + docs = assemble_documents( + [{"atomic_claim_id": "A1", "relation": "PRIMARY", "plan_order": 0, "rendered_text": rendered["rendered_text"], "claimant_ref": "P1", "defendant_ref": "P2"}], + [{"atom_id": "C1", "atomic_claim_id": "A1", "section_kind": "PARTY_AND_TITLE", "atom_order": 0, "text": "fixture-source-text", "source_refs": ["fixture://C1"], "claimant_ref": "P1", "defendant_ref": "P2"}], + cost_text="fixture-cost", provisional_rows=[], + ) + self.assertEqual(docs["ordered_atomic_claim_ids"], ["A1"]) + self.assertEqual(relief_cause_crossmatch([{"atomic_claim_id": "A1", "claimant_ref": "P1", "defendant_ref": "P2"}], [{"atomic_claim_id": "A1", "claimant_ref": "P1", "defendant_ref": "P2"}]), []) + + def test_pending_renderer_and_unknown_slot_fail_closed(self) -> None: + descriptor = fixture_renderer() + descriptor["execution_eligible"] = False + with self.assertRaisesRegex(ClosedRenderError, "NOT_EXECUTION_ELIGIBLE"): + render_closed(descriptor, {"kind": "X"}, {"value": "A"}, atom_type="RELIEF_ATOM", allow_fixture=True) + with self.assertRaisesRegex(ClosedRenderError, "UNKNOWN_SLOT"): + render_closed(fixture_renderer(), {"kind": "X"}, {"value": "A", "other": "B"}, atom_type="RELIEF_ATOM", allow_fixture=True) + + def test_provisional_execution_closed_formula(self) -> None: + base = {"proprietary_claim": True, "performance_atom": True, "atomic_branch_provisional_execution_policy": "ALLOW", "approved_authority_ref_is_valid": True, "dependent_on_constitutive_judgment": False, "renderer_id": "R01"} + self.assertTrue(provisional_execution_eligible(base)) + self.assertFalse(provisional_execution_eligible({**base, "renderer_id": "R03"})) + + def test_plain_and_markdown_escape_semantics_are_exact(self) -> None: + self.assertEqual(escape_slot_value("A_B[1]#", "PLAIN_TEXT"), "A_B[1]#") + self.assertEqual(escape_slot_value("A_B[1]#", "MARKDOWN_TEXT"), r"A\_B\[1\]\#") + with self.assertRaisesRegex(ClosedRenderError, "DANGLING_TEMPLATE_TOKEN"): + escape_slot_value("{{unbound}}", "MARKDOWN_TEXT") + descriptor = fixture_renderer() + descriptor["typed_slot_contract"]["slot_definitions"][0]["cardinality"] = "ONE_OR_MORE" + descriptor["branch_rows"][0]["segments"][1]["escape"] = "MARKDOWN_TEXT" + rendered = render_closed(descriptor, {"kind": "X"}, {"value": ["A_B", "C[D]"]}, atom_type="RELIEF_ATOM", allow_fixture=True) + self.assertEqual(rendered["rendered_text"], r"[A\_B, C\[D\]]") + + def test_usage_projection_binds_source_parts_and_conserves_rows(self) -> None: + projection = build_usage_projection( + [ + {"part_id": "U2", "raw_sha256": "2" * 64, "rows": [{"usage_id": "ROW-2", "tokens": 2}]}, + {"part_id": "U1", "raw_sha256": "1" * 64, "rows": [{"usage_id": "ROW-1", "tokens": 1}]}, + ], + run_binding_digest="a" * 64, + ) + self.assertEqual(projection["schema_version"], "stage2_s2_40_usage_projection.v1") + self.assertEqual(projection["source_usage_part_sha256s"], ["1" * 64, "2" * 64]) + self.assertEqual([row["usage_id"] for row in projection["rows"]], ["ROW-1", "ROW-2"]) + with self.assertRaisesRegex(AssemblyError, "CONSERVATION"): + build_usage_projection( + [{"part_id": "U1", "raw_sha256": "1" * 64, "rows": [{"usage_id": "ROW-1"}, {"usage_id": "ROW-1"}]}], + run_binding_digest="a" * 64, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c45_closed_render.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c45_closed_render.txt new file mode 100644 index 00000000..0646693a --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_c45_closed_render.txt @@ -0,0 +1,116 @@ +from __future__ import annotations + +from copy import deepcopy +import json +from pathlib import Path +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +from runtime.c45_document_assembler import AssemblyError, assemble_documents, build_usage_projection, relief_cause_crossmatch # noqa: E402 +from runtime.rendering.closed_renderer import ClosedRenderError, escape_slot_value, provisional_execution_eligible, render_closed # noqa: E402 +from runtime.validation.invariant_runner import InvariantError, validate_reference_closure # noqa: E402 + + +def fixture_renderer(): + return { + "schema_version": "fixture.v1", "renderer_id": "RF", "renderer_kind": "STRUCTURAL", + "status": "STRUCTURAL_FIXTURE_ONLY", "execution_eligible": True, + "stage2_20_role": "SELECT_AND_SEAL_ONLY", "stage2_40_role": "CLOSED_RENDER", + "typed_slot_contract": {"slot_definitions": [{"name": "value", "type": "STRING", "cardinality": "EXACTLY_ONE"}]}, + "closed_ast_contract": {"normalization_version": "NFC_LF_UTF8_V1", "allowed_atom_types": ["RELIEF_ATOM"]}, + "branch_rows": [{"branch_id": "B1", "approval_status": "APPROVED", "predicates": [{"field": "kind", "op": "EQ", "value": "X"}], "segments": [{"kind": "LITERAL", "value": "["}, {"kind": "SLOT", "name": "value", "escape": "PLAIN_TEXT"}, {"kind": "LITERAL", "value": "]"}]}], + "closure": {"zero_match_issue_code": "ZERO", "multi_match_issue_code": "MULTI"}, "review": {"status": "FIXTURE_ONLY"}, + } + + +class C45Tests(unittest.TestCase): + def test_renderer_fixture_mutations_execute_closed_oracles(self) -> None: + fixture = json.loads((ROOT / "tests/fixtures/s2_40/renderer_ast_slot_branch_mutations.json").read_text(encoding="utf-8")) + for mutation in fixture["mutations"]: + descriptor, slots = fixture_renderer(), {"value": "A"} + if mutation["mutation_id"] == "ZERO": + descriptor["branch_rows"] = [] + elif mutation["mutation_id"] == "MULTI": + duplicate = deepcopy(descriptor["branch_rows"][0]); duplicate["branch_id"] = "B2" + descriptor["branch_rows"].append(duplicate) + else: + slots["unknown"] = "B" + with self.subTest(mutation=mutation["mutation_id"]), self.assertRaises(ClosedRenderError): + render_closed(descriptor, {"kind": "X"}, slots, atom_type="RELIEF_ATOM", allow_fixture=True) + + def test_crossmatch_numbering_and_reference_fixtures_execute(self) -> None: + cross = json.loads((ROOT / "tests/fixtures/s2_40/relief_cause_crossmatch_mutations.json").read_text(encoding="utf-8")) + findings = relief_cause_crossmatch( + [{"atomic_claim_id": "A1", "claimant_ref": "P1", "defendant_ref": "P2", "amount_ref": "M1"}], + [{"atomic_claim_id": "A1", "claimant_ref": "P1", "defendant_ref": "P2", "amount_ref": "M2"}], + ) + self.assertIn("RELIEF_CAUSE_AMOUNT_REF_MISMATCH::A1", findings) + self.assertEqual(cross["expected"]["expected_reason_codes"], ["RELIEF_CAUSE_MISMATCH"]) + + numbering = json.loads((ROOT / "tests/fixtures/s2_40/cost_provisional_execution_numbering.json").read_text(encoding="utf-8")) + base = {"proprietary_claim": True, "performance_atom": True, "atomic_branch_provisional_execution_policy": "ALLOW", "approved_authority_ref_is_valid": True, "dependent_on_constitutive_judgment": False, "renderer_id": "R03"} + self.assertFalse(provisional_execution_eligible(base)) + self.assertIn("INELIGIBLE", {row["mutation_id"] for row in numbering["mutations"]}) + + refs = json.loads((ROOT / "tests/fixtures/s2_40/exhibit_object_party_title_completeness.json").read_text(encoding="utf-8")) + validate_reference_closure(refs["input"]["refs"], refs["input"]["refs"]) + with self.assertRaisesRegex(InvariantError, "DANGLING"): + validate_reference_closure(refs["input"]["refs"], refs["input"]["refs"][:-1]) + + def test_closed_render_and_document_order(self) -> None: + rendered = render_closed(fixture_renderer(), {"kind": "X"}, {"value": "A"}, atom_type="RELIEF_ATOM", allow_fixture=True) + self.assertEqual(rendered["rendered_text"], "[A]") + docs = assemble_documents( + [{"atomic_claim_id": "A1", "relation": "PRIMARY", "plan_order": 0, "rendered_text": rendered["rendered_text"], "claimant_ref": "P1", "defendant_ref": "P2"}], + [{"atom_id": "C1", "atomic_claim_id": "A1", "section_kind": "PARTY_AND_TITLE", "atom_order": 0, "text": "fixture-source-text", "source_refs": ["fixture://C1"], "claimant_ref": "P1", "defendant_ref": "P2"}], + cost_text="fixture-cost", provisional_rows=[], + ) + self.assertEqual(docs["ordered_atomic_claim_ids"], ["A1"]) + self.assertEqual(relief_cause_crossmatch([{"atomic_claim_id": "A1", "claimant_ref": "P1", "defendant_ref": "P2"}], [{"atomic_claim_id": "A1", "claimant_ref": "P1", "defendant_ref": "P2"}]), []) + + def test_pending_renderer_and_unknown_slot_fail_closed(self) -> None: + descriptor = fixture_renderer() + descriptor["execution_eligible"] = False + with self.assertRaisesRegex(ClosedRenderError, "NOT_EXECUTION_ELIGIBLE"): + render_closed(descriptor, {"kind": "X"}, {"value": "A"}, atom_type="RELIEF_ATOM", allow_fixture=True) + with self.assertRaisesRegex(ClosedRenderError, "UNKNOWN_SLOT"): + render_closed(fixture_renderer(), {"kind": "X"}, {"value": "A", "other": "B"}, atom_type="RELIEF_ATOM", allow_fixture=True) + + def test_provisional_execution_closed_formula(self) -> None: + base = {"proprietary_claim": True, "performance_atom": True, "atomic_branch_provisional_execution_policy": "ALLOW", "approved_authority_ref_is_valid": True, "dependent_on_constitutive_judgment": False, "renderer_id": "R01"} + self.assertTrue(provisional_execution_eligible(base)) + self.assertFalse(provisional_execution_eligible({**base, "renderer_id": "R03"})) + + def test_plain_and_markdown_escape_semantics_are_exact(self) -> None: + self.assertEqual(escape_slot_value("A_B[1]#", "PLAIN_TEXT"), "A_B[1]#") + self.assertEqual(escape_slot_value("A_B[1]#", "MARKDOWN_TEXT"), r"A\_B\[1\]\#") + with self.assertRaisesRegex(ClosedRenderError, "DANGLING_TEMPLATE_TOKEN"): + escape_slot_value("{{unbound}}", "MARKDOWN_TEXT") + descriptor = fixture_renderer() + descriptor["typed_slot_contract"]["slot_definitions"][0]["cardinality"] = "ONE_OR_MORE" + descriptor["branch_rows"][0]["segments"][1]["escape"] = "MARKDOWN_TEXT" + rendered = render_closed(descriptor, {"kind": "X"}, {"value": ["A_B", "C[D]"]}, atom_type="RELIEF_ATOM", allow_fixture=True) + self.assertEqual(rendered["rendered_text"], r"[A\_B, C\[D\]]") + + def test_usage_projection_binds_source_parts_and_conserves_rows(self) -> None: + projection = build_usage_projection( + [ + {"part_id": "U2", "raw_sha256": "2" * 64, "rows": [{"usage_id": "ROW-2", "tokens": 2}]}, + {"part_id": "U1", "raw_sha256": "1" * 64, "rows": [{"usage_id": "ROW-1", "tokens": 1}]}, + ], + run_binding_digest="a" * 64, + ) + self.assertEqual(projection["schema_version"], "stage2_s2_40_usage_projection.v1") + self.assertEqual(projection["source_usage_part_sha256s"], ["1" * 64, "2" * 64]) + self.assertEqual([row["usage_id"] for row in projection["rows"]], ["ROW-1", "ROW-2"]) + with self.assertRaisesRegex(AssemblyError, "CONSERVATION"): + build_usage_projection( + [{"part_id": "U1", "raw_sha256": "1" * 64, "rows": [{"usage_id": "ROW-1"}, {"usage_id": "ROW-1"}]}], + run_binding_digest="a" * 64, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_commit_barrier_and_idempotence.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_commit_barrier_and_idempotence.py new file mode 100644 index 00000000..3e703630 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_commit_barrier_and_idempotence.py @@ -0,0 +1,141 @@ +from __future__ import annotations + +import json +from pathlib import Path +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +from runtime.c45_document_assembler import build_usage_projection # noqa: E402 +from runtime.validation.invariant_runner import InvariantError, artifact_set_digest, candidate_content_digest, commit_write_order, validate_jsonschema_instance, validate_readback_rows # noqa: E402 + + +def candidate_material(): + return { + "run_binding_digest": "a" * 64, + "dependency_snapshot_sha256": "b" * 64, + "candidate_manifest_core_sha256": "c" * 64, + "document_sha256s": {"claim_relief": "d" * 64, "claim_cause": "e" * 64, "pleading_draft": "f" * 64}, + "attorney_worknotes_core_sha256": "1" * 64, + "final_issue_ledger_sha256": "2" * 64, + "assumption_ledger_sha256": "3" * 64, + "validation_core_sha256": "4" * 64, + "ordered_source_dependency_snapshot_digest": "5" * 64, + } + + +class CommitTests(unittest.TestCase): + def test_candidate_material_is_noncyclic(self) -> None: + digest = candidate_content_digest(candidate_material()) + self.assertEqual(len(digest), 64) + with self.assertRaisesRegex(InvariantError, "CYCLE"): + candidate_content_digest({"candidate_content_digest": "a" * 64}) + + def test_commit_fixtures_execute_digest_readback_and_conflict_oracles(self) -> None: + fixture_root = ROOT / "tests/fixtures/s2_40" + valid = json.loads((fixture_root / "valid_full_candidate_and_commit.json").read_text(encoding="utf-8")) + self.assertEqual(valid["expected"]["route"], "PACKAGE_COMMITTED") + self.assertEqual(len(candidate_content_digest(candidate_material())), 64) + + row = {"path": "final/stage2_package.json", "raw_sha256": "a" * 64, "content_type": "application/json", "size_bytes": 12, "schema_ref": "schemas/package.schema.json#/$defs/stage2_package"} + validate_readback_rows([row], [dict(row)]) + partial = json.loads((fixture_root / "partial_write_readback_barrier.json").read_text(encoding="utf-8")) + with self.assertRaisesRegex(InvariantError, "READBACK_MISMATCH"): + validate_readback_rows([row], [{**row, "size_bytes": 11}]) + self.assertIn("PARTIAL", {item["mutation_id"] for item in partial["mutations"]}) + + conflict = json.loads((fixture_root / "same_binding_idempotence_and_commit_conflict.json").read_text(encoding="utf-8")) + with self.assertRaisesRegex(InvariantError, "READBACK_MISMATCH"): + validate_readback_rows([row], [{**row, "raw_sha256": "b" * 64}]) + self.assertEqual(conflict["input"]["same_binding_same_bytes"], "IDEMPOTENT_SUCCESS") + + noncycle = json.loads((fixture_root / "candidate_digest_noncycle.json").read_text(encoding="utf-8")) + cyclic = candidate_material(); cyclic["candidate_content_digest"] = "9" * 64 + with self.assertRaisesRegex(InvariantError, "CYCLE"): + candidate_content_digest(cyclic) + self.assertEqual(noncycle["mutations"][0]["mutation_id"], "CYCLE") + + def test_artifact_digest_is_order_independent_and_conflict_closed(self) -> None: + rows = [ + {"path": "final/b", "raw_sha256": "b" * 64, "content_type": "application/json", "size_bytes": 1, "schema_ref": None}, + {"path": "final/a", "raw_sha256": "a" * 64, "content_type": "text/markdown", "size_bytes": 1, "schema_ref": None}, + ] + self.assertEqual(artifact_set_digest(rows), artifact_set_digest(list(reversed(rows)))) + with self.assertRaisesRegex(InvariantError, "DUPLICATE"): + artifact_set_digest([rows[0], rows[0]]) + + def test_barrier_is_always_last(self) -> None: + order = commit_write_order(["final/stage2_package.json", "final/claim_relief.md"]) + self.assertEqual(order[0], "commit/commit_intent.json") + self.assertEqual(order[-2:], ["commit/stage2_commit_result.json", "control/run_status.json"]) + + def test_candidate_usage_package_and_commit_objects_validate_against_schemas(self) -> None: + package_schema = json.loads((ROOT / "schemas/package.schema.json").read_text()) + review_schema = json.loads((ROOT / "schemas/review_status.schema.json").read_text()) + deployment_schema = json.loads((ROOT / "schemas/deployment.schema.json").read_text()) + store = {"review_status.schema.json": review_schema, "package.schema.json": package_schema, "deployment.schema.json": deployment_schema} + material = candidate_material() + digest = candidate_content_digest(material) + envelope = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + **material, + "candidate_content_digest": digest, + } + validate_jsonschema_instance(envelope, package_schema, schema_store=store) + usage = build_usage_projection( + [{"part_id": "USAGE-CG1", "raw_sha256": "6" * 64, "rows": [{"usage_id": "U-001", "model": "fixture"}]}], + run_binding_digest="a" * 64, + ) + validate_jsonschema_instance(usage, package_schema, schema_store=store) + artifact_rows = [ + { + "path": f"stage2_runs/by-binding/{'a' * 64}/final/{name}", + "raw_sha256": char * 64, + "content_type": "application/json" if name.endswith("json") else "text/markdown; charset=utf-8", + "size_bytes": 1, + "schema_ref": None, + } + for name, char in ( + ("candidate_package_manifest.json", "1"), ("candidate_content_digest.json", "2"), + ("claim_relief.md", "3"), ("claim_cause.md", "4"), ("pleading_draft.md", "5"), + ("attorney_worknotes.json", "6"), ("lawyer_review_packet.json", "7"), + ("stage2_final_validation_report.json", "8"), ("stage2_package.json", "9"), + ) + ] + package = { + "schema_version": "stage2_s2_40_package.v1", "producer_id": "S2_40", + "run_binding_digest": "a" * 64, "candidate_content_digest": digest, + "compile_mode": "STRUCTURAL_FIXTURE", "candidate_manifest_core_sha256": "c" * 64, + "artifacts": [{**row, "producer_id": "S2_40"} for row in artifact_rows[:-1]], + "validation_report_sha256": "4" * 64, "review_policy_result_sha256": "5" * 64, + "review_receipt_sha256s": ["6" * 64], "filing_decision_receipt_sha256": None, + "run_technical_status": "CONSISTENT", "artifact_technical_status": "CONSISTENT", + "legal_readiness": "LAWYER_REVIEW_REQUIRED", "filing_permission": "NOT_GRANTED", + } + validate_jsonschema_instance(package, package_schema, schema_store=store) + intent_core = { + "schema_version": "stage2_s2_40_commit_intent.v1", "producer_id": "S2_40", + "run_binding_digest": "a" * 64, "candidate_content_digest": digest, + "candidate_attempt_id": "ATTEMPT-001", "candidate_manifest_core_sha256": "c" * 64, + "validation_report_sha256": "4" * 64, "review_subject_digest": "b" * 64, + "review_receipt_sha256s": ["6" * 64], "stage2_package_sha256": "9" * 64, + "expected_artifacts": artifact_rows, "previous_run_status_sha256": None, + "request_sha256": "d" * 64, "host_cas_receipt_sha256": "e" * 64, + } + intent = {**intent_core, "intent_digest": "f" * 64} + validate_jsonschema_instance(intent, deployment_schema, schema_store=store) + result = { + "schema_version": "stage2_s2_40_commit_result.v1", "producer_id": "S2_40", + "run_binding_digest": "a" * 64, "candidate_content_digest": digest, + "commit_intent_sha256": "f" * 64, "artifact_rows": artifact_rows, + "artifact_set_digest": artifact_set_digest(artifact_rows), "readback_status": "PASS", + "conflicting_target_count": 0, "missing_target_count_after_write": 0, + "commit_result_digest": "0" * 64, + } + validate_jsonschema_instance(result, deployment_schema, schema_store=store) + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_commit_barrier_and_idempotence.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_commit_barrier_and_idempotence.txt new file mode 100644 index 00000000..3e703630 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_commit_barrier_and_idempotence.txt @@ -0,0 +1,141 @@ +from __future__ import annotations + +import json +from pathlib import Path +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +from runtime.c45_document_assembler import build_usage_projection # noqa: E402 +from runtime.validation.invariant_runner import InvariantError, artifact_set_digest, candidate_content_digest, commit_write_order, validate_jsonschema_instance, validate_readback_rows # noqa: E402 + + +def candidate_material(): + return { + "run_binding_digest": "a" * 64, + "dependency_snapshot_sha256": "b" * 64, + "candidate_manifest_core_sha256": "c" * 64, + "document_sha256s": {"claim_relief": "d" * 64, "claim_cause": "e" * 64, "pleading_draft": "f" * 64}, + "attorney_worknotes_core_sha256": "1" * 64, + "final_issue_ledger_sha256": "2" * 64, + "assumption_ledger_sha256": "3" * 64, + "validation_core_sha256": "4" * 64, + "ordered_source_dependency_snapshot_digest": "5" * 64, + } + + +class CommitTests(unittest.TestCase): + def test_candidate_material_is_noncyclic(self) -> None: + digest = candidate_content_digest(candidate_material()) + self.assertEqual(len(digest), 64) + with self.assertRaisesRegex(InvariantError, "CYCLE"): + candidate_content_digest({"candidate_content_digest": "a" * 64}) + + def test_commit_fixtures_execute_digest_readback_and_conflict_oracles(self) -> None: + fixture_root = ROOT / "tests/fixtures/s2_40" + valid = json.loads((fixture_root / "valid_full_candidate_and_commit.json").read_text(encoding="utf-8")) + self.assertEqual(valid["expected"]["route"], "PACKAGE_COMMITTED") + self.assertEqual(len(candidate_content_digest(candidate_material())), 64) + + row = {"path": "final/stage2_package.json", "raw_sha256": "a" * 64, "content_type": "application/json", "size_bytes": 12, "schema_ref": "schemas/package.schema.json#/$defs/stage2_package"} + validate_readback_rows([row], [dict(row)]) + partial = json.loads((fixture_root / "partial_write_readback_barrier.json").read_text(encoding="utf-8")) + with self.assertRaisesRegex(InvariantError, "READBACK_MISMATCH"): + validate_readback_rows([row], [{**row, "size_bytes": 11}]) + self.assertIn("PARTIAL", {item["mutation_id"] for item in partial["mutations"]}) + + conflict = json.loads((fixture_root / "same_binding_idempotence_and_commit_conflict.json").read_text(encoding="utf-8")) + with self.assertRaisesRegex(InvariantError, "READBACK_MISMATCH"): + validate_readback_rows([row], [{**row, "raw_sha256": "b" * 64}]) + self.assertEqual(conflict["input"]["same_binding_same_bytes"], "IDEMPOTENT_SUCCESS") + + noncycle = json.loads((fixture_root / "candidate_digest_noncycle.json").read_text(encoding="utf-8")) + cyclic = candidate_material(); cyclic["candidate_content_digest"] = "9" * 64 + with self.assertRaisesRegex(InvariantError, "CYCLE"): + candidate_content_digest(cyclic) + self.assertEqual(noncycle["mutations"][0]["mutation_id"], "CYCLE") + + def test_artifact_digest_is_order_independent_and_conflict_closed(self) -> None: + rows = [ + {"path": "final/b", "raw_sha256": "b" * 64, "content_type": "application/json", "size_bytes": 1, "schema_ref": None}, + {"path": "final/a", "raw_sha256": "a" * 64, "content_type": "text/markdown", "size_bytes": 1, "schema_ref": None}, + ] + self.assertEqual(artifact_set_digest(rows), artifact_set_digest(list(reversed(rows)))) + with self.assertRaisesRegex(InvariantError, "DUPLICATE"): + artifact_set_digest([rows[0], rows[0]]) + + def test_barrier_is_always_last(self) -> None: + order = commit_write_order(["final/stage2_package.json", "final/claim_relief.md"]) + self.assertEqual(order[0], "commit/commit_intent.json") + self.assertEqual(order[-2:], ["commit/stage2_commit_result.json", "control/run_status.json"]) + + def test_candidate_usage_package_and_commit_objects_validate_against_schemas(self) -> None: + package_schema = json.loads((ROOT / "schemas/package.schema.json").read_text()) + review_schema = json.loads((ROOT / "schemas/review_status.schema.json").read_text()) + deployment_schema = json.loads((ROOT / "schemas/deployment.schema.json").read_text()) + store = {"review_status.schema.json": review_schema, "package.schema.json": package_schema, "deployment.schema.json": deployment_schema} + material = candidate_material() + digest = candidate_content_digest(material) + envelope = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + **material, + "candidate_content_digest": digest, + } + validate_jsonschema_instance(envelope, package_schema, schema_store=store) + usage = build_usage_projection( + [{"part_id": "USAGE-CG1", "raw_sha256": "6" * 64, "rows": [{"usage_id": "U-001", "model": "fixture"}]}], + run_binding_digest="a" * 64, + ) + validate_jsonschema_instance(usage, package_schema, schema_store=store) + artifact_rows = [ + { + "path": f"stage2_runs/by-binding/{'a' * 64}/final/{name}", + "raw_sha256": char * 64, + "content_type": "application/json" if name.endswith("json") else "text/markdown; charset=utf-8", + "size_bytes": 1, + "schema_ref": None, + } + for name, char in ( + ("candidate_package_manifest.json", "1"), ("candidate_content_digest.json", "2"), + ("claim_relief.md", "3"), ("claim_cause.md", "4"), ("pleading_draft.md", "5"), + ("attorney_worknotes.json", "6"), ("lawyer_review_packet.json", "7"), + ("stage2_final_validation_report.json", "8"), ("stage2_package.json", "9"), + ) + ] + package = { + "schema_version": "stage2_s2_40_package.v1", "producer_id": "S2_40", + "run_binding_digest": "a" * 64, "candidate_content_digest": digest, + "compile_mode": "STRUCTURAL_FIXTURE", "candidate_manifest_core_sha256": "c" * 64, + "artifacts": [{**row, "producer_id": "S2_40"} for row in artifact_rows[:-1]], + "validation_report_sha256": "4" * 64, "review_policy_result_sha256": "5" * 64, + "review_receipt_sha256s": ["6" * 64], "filing_decision_receipt_sha256": None, + "run_technical_status": "CONSISTENT", "artifact_technical_status": "CONSISTENT", + "legal_readiness": "LAWYER_REVIEW_REQUIRED", "filing_permission": "NOT_GRANTED", + } + validate_jsonschema_instance(package, package_schema, schema_store=store) + intent_core = { + "schema_version": "stage2_s2_40_commit_intent.v1", "producer_id": "S2_40", + "run_binding_digest": "a" * 64, "candidate_content_digest": digest, + "candidate_attempt_id": "ATTEMPT-001", "candidate_manifest_core_sha256": "c" * 64, + "validation_report_sha256": "4" * 64, "review_subject_digest": "b" * 64, + "review_receipt_sha256s": ["6" * 64], "stage2_package_sha256": "9" * 64, + "expected_artifacts": artifact_rows, "previous_run_status_sha256": None, + "request_sha256": "d" * 64, "host_cas_receipt_sha256": "e" * 64, + } + intent = {**intent_core, "intent_digest": "f" * 64} + validate_jsonschema_instance(intent, deployment_schema, schema_store=store) + result = { + "schema_version": "stage2_s2_40_commit_result.v1", "producer_id": "S2_40", + "run_binding_digest": "a" * 64, "candidate_content_digest": digest, + "commit_intent_sha256": "f" * 64, "artifact_rows": artifact_rows, + "artifact_set_digest": artifact_set_digest(artifact_rows), "readback_status": "PASS", + "conflicting_target_count": 0, "missing_target_count_after_write": 0, + "commit_result_digest": "0" * 64, + } + validate_jsonschema_instance(result, deployment_schema, schema_store=store) + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_release_closure.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_release_closure.py new file mode 100644 index 00000000..dcb5df4e --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_release_closure.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python3 +"""S2_40 owner-aware parent closure and detached admission tests.""" + +from __future__ import annotations + +import importlib.util +import hashlib +import json +import os +from pathlib import Path +import tempfile +import unittest + + +ROOT = Path(__file__).resolve().parents[2] +BUILDER_PATH = ROOT / "offline_build/build_release_manifests.py" +VALIDATOR_PATH = ROOT / "release_ops/release_validator.py" + + +def load_module(name: str, path: Path): + spec = importlib.util.spec_from_file_location(name, path) + if spec is None or spec.loader is None: + raise RuntimeError(path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +BUILDER = load_module("s2_40_release_builder", BUILDER_PATH) +VALIDATOR = load_module("s2_40_release_validator", VALIDATOR_PATH) + + +def module_template(rows: list[dict[str, object]]) -> dict[str, object]: + return { + "schema_version": "stage2_module_manifest.v1", + "manifest_digest": "0" * 64, + "closure_summary": {}, + "documentation_mirrors": [], + "modules": rows, + } + + +class ReleaseClosureTest(unittest.TestCase): + def test_finding_map_closes_eighteen_v_codes_and_twenty_fixture_families(self) -> None: + mapping = json.loads((ROOT / "registry/regression/finding_fixture_map.yml").read_text(encoding="utf-8")) + rows = mapping["mapping_rows"] + self.assertEqual({row["invariant_id"] for row in rows}, {f"V{index:02d}" for index in range(1, 19)}) + self.assertTrue(all(row["source_locator"] and row["mutation_id"] for row in rows)) + families = mapping["s2_40_fixture_family_coverage_rows"] + self.assertEqual({row["family_id"] for row in families}, {f"S40-FAMILY-{index:02d}" for index in range(1, 21)}) + self.assertFalse(mapping["execution_eligible"]) + self.assertIn("PENDING", mapping["status"]) + + def test_s2_40_regression_manifest_binds_all_payload_and_seven_test_oracles(self) -> None: + manifest_path = ROOT / "tests/fixtures/s2_40/regression_manifest.json" + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + physical = sorted(path for path in (manifest_path.parent).glob("*.json") if path.name != "regression_manifest.json") + self.assertEqual(len(physical), 15) + self.assertEqual(len(manifest["rows"]), 15) + self.assertEqual({row["fixture_case_id"] for row in manifest["rows"]}, {f"S40-F{index:03d}" for index in range(1, 16)}) + for row in manifest["rows"]: + path = ROOT / row["path"] + self.assertTrue(path.is_file()) + self.assertEqual(row["raw_sha256"], hashlib.sha256(path.read_bytes()).hexdigest()) + fixture = json.loads(path.read_text(encoding="utf-8")) + self.assertEqual(fixture["header"]["fixture_case_id"], row["fixture_case_id"]) + self.assertEqual(fixture["header"]["oracle_kind"], row["oracle_kind"]) + self.assertEqual(fixture["expected"]["route"], row["expected_route"]) + self.assertEqual(set(fixture["expected"]["expected_invariant_results"]), set(row["expected_invariant_ids"])) + self.assertTrue(fixture["header"]["fixture_only"]) + self.assertFalse(fixture["header"]["production_admissible"]) + expected_tests = {f"tests/s2_40/{path.name}" for path in (ROOT / "tests/s2_40").glob("test_*.py")} + self.assertEqual(len(expected_tests), 7) + self.assertEqual({row["path"] for row in manifest["test_sources"]}, expected_tests) + for row in manifest["test_sources"]: + self.assertEqual(row["raw_sha256"], hashlib.sha256((ROOT / row["path"]).read_bytes()).hexdigest()) + material = {key: value for key, value in manifest.items() if key != "manifest_digest"} + raw = (json.dumps(material, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8") + self.assertEqual(manifest["manifest_digest"], hashlib.sha256(raw).hexdigest()) + + def test_release_sources_have_exact_documentation_mirrors(self) -> None: + for path in (BUILDER_PATH, VALIDATOR_PATH): + with self.subTest(path=path): + self.assertEqual(path.read_bytes(), path.with_suffix(".txt").read_bytes()) + + def test_s2_40_detached_members_are_forbidden_from_parent(self) -> None: + expected = { + "agent_scripts/Stage_2_S2_40.yml", + "runtime/s2_40_commit.py", + "runtime/s2_40_commit.txt", + "manifest/s2_40_inline_code_receipt.json", + "deployment/stage2_code_executor_binding.yml", + "manifest/stage2_deterministic_admission_receipt.json", + } + self.assertTrue(expected.issubset(BUILDER.FORBIDDEN_PARENT_MEMBERS)) + self.assertEqual(BUILDER.FORBIDDEN_PARENT_MEMBERS, VALIDATOR.FORBIDDEN_PARENT_MEMBERS) + + def test_owner_aware_builder_repairs_old_s2_30_generic_rows(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + s30 = "tests/s2_30/example.json" + s40 = "tests/s2_40/example.json" + for relative in (s30, s40): + path = root / relative + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("{}\n", encoding="utf-8") + wrong = BUILDER._generic_module_row(s30, "S2_20") + manifest = BUILDER.build_module_manifest( + root, + module_template([wrong]), + [s30, s40], + path_owners={s30: "S2_30", s40: "S2_40"}, + ) + rows = {row["path"]: row for row in manifest["modules"]} + self.assertEqual(rows[s30]["owner"], "Stage_2_S2_30_owner") + self.assertEqual(rows[s30]["asset_version"], "s2_30.1") + self.assertTrue(rows[s30]["module_id"].startswith("S2_30-ASSET-")) + self.assertEqual(rows[s30]["scope_predicate"], "workflow_id == S2_30") + self.assertEqual(rows[s40]["owner"], "Stage_2_S2_40_owner") + self.assertEqual(rows[s40]["schema_version"], "stage2_s2_40_generic_asset.v1") + self.assertEqual( + manifest["closure_summary"]["generic_module_counts_by_stage"], + {"S2_20": 0, "S2_30": 1, "S2_40": 1}, + ) + + def test_builder_replaces_transitioned_s2_40_stub_with_full_workflow_row(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + workflow = root / BUILDER.S2_40_WORKFLOW_PATH + workflow.parent.mkdir(parents=True) + workflow.write_text("Agent:\n name: S2_40_final_review_render_and_commit\n", encoding="utf-8") + stub = { + "asset_version": "s2_40.status_only.1", + "authority_ids": [], + "consumed_schema_ids": [], + "dependency_module_ids": [], + "forbidden_contract_codes": [], + "implementation_status": "DRAFT_HANDOFF_STUB_HASH_BOUND", + "incompatible_module_ids": [], + "inputs": ["ingress/ingress_status.json"], + "module_id": "WF-S2_40-STATUS-ONLY", + "module_kind": "WORKFLOW", + "outputs": ["control/run_status.json"], + "owner": "Stage_2_S2_40_owner", + "path": BUILDER.S2_40_WORKFLOW_PATH, + "produced_schema_ids": [], + "schema_version": "stage2_workflow_contract.v1", + "scope_predicate": "entrypoint_id == S2_40_STATUS_ONLY", + "semantic_review_status": "PENDING_CROSS_AUDIT", + } + manifest = BUILDER.build_module_manifest( + root, + module_template([stub]), + [BUILDER.S2_40_WORKFLOW_PATH], + path_owners={BUILDER.S2_40_WORKFLOW_PATH: "S2_40"}, + ) + row = manifest["modules"][0] + for key, expected in BUILDER.S2_40_WORKFLOW_METADATA.items(): + self.assertEqual(row[key], expected, key) + self.assertTrue(row["sha256"]) + self.assertEqual(row["size_bytes"], len(workflow.read_bytes())) + self.assertFalse( + { + row["module_id"], + row["asset_version"], + row["implementation_status"], + row["scope_predicate"], + } + & BUILDER.S2_40_TRANSITIONED_STUB_VALUES + ) + + def test_validator_rejects_transitioned_stub_and_accepts_authoritative_metadata(self) -> None: + stub = dict(BUILDER.S2_40_WORKFLOW_METADATA) + stub.update( + { + "module_id": "WF-S2_40-STATUS-ONLY", + "asset_version": "s2_40.status_only.1", + "implementation_status": "DRAFT_HANDOFF_STUB_HASH_BOUND", + "scope_predicate": "entrypoint_id == S2_40_STATUS_ONLY", + } + ) + errors = VALIDATOR._validate_s2_40_workflow_module_row([stub]) + codes = {row["code"] for row in errors} + self.assertIn("S2_40_TRANSITIONED_STUB_METADATA_FORBIDDEN", codes) + self.assertIn("S2_40_WORKFLOW_MODULE_METADATA_MISMATCH", codes) + self.assertEqual( + VALIDATOR._validate_s2_40_workflow_module_row( + [dict(BUILDER.S2_40_WORKFLOW_METADATA)] + ), + [], + ) + + def test_validator_requires_workflow_anchor_only_after_s2_40_family_activation(self) -> None: + pre_s2_40 = [{"module_id": "SCHEMA-CONTEXT", "owner": "Stage_2_shared"}] + self.assertEqual( + VALIDATOR._validate_s2_40_workflow_module_row(pre_s2_40), + [], + ) + activated_without_anchor = [ + { + "module_id": "S2_40-ASSET-EXAMPLE", + "owner": "Stage_2_S2_40_owner", + "schema_version": "stage2_s2_40_generic_asset.v1", + } + ] + errors = VALIDATOR._validate_s2_40_workflow_module_row( + activated_without_anchor + ) + self.assertEqual( + {row["code"] for row in errors}, + {"S2_40_WORKFLOW_MODULE_ROW_EXACT_ONE_REQUIRED"}, + ) + + def test_validator_resolves_relative_root_before_authoring_derivation(self) -> None: + relative = Path(os.path.relpath(ROOT, Path.cwd())) + self.assertFalse(relative.is_absolute()) + self.assertEqual(VALIDATOR._resolve_root(relative), ROOT.resolve(strict=True)) + self.assertEqual( + VALIDATOR._resolve_root(relative).parent.parent / "Stage_2_S2_40.yml", + ROOT.resolve(strict=True).parent.parent / "Stage_2_S2_40.yml", + ) + + def test_owner_mapping_rejects_unknown_or_nonclosure_paths(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / "data/example.json" + path.parent.mkdir(parents=True) + path.write_text("{}\n", encoding="utf-8") + template = module_template([]) + with self.assertRaises(BUILDER.ReleaseBuildError): + BUILDER.build_module_manifest(root, template, ["data/example.json"], {"data/example.json": "S2_99"}) + with self.assertRaises(BUILDER.ReleaseBuildError): + BUILDER.build_module_manifest(root, template, ["data/example.json"], {"data/other.json": "S2_40"}) + + def test_three_allowlists_are_sorted_unique_and_pairwise_disjoint(self) -> None: + observed: dict[str, set[str]] = {} + for stage in ("s2_20", "s2_30", "s2_40"): + values = json.loads((ROOT / f"manifest/{stage}_parent_member_paths.json").read_text(encoding="utf-8")) + self.assertEqual(values, sorted(set(values))) + observed[stage] = set(values) + self.assertFalse(observed["s2_20"] & observed["s2_30"]) + self.assertFalse(observed["s2_20"] & observed["s2_40"]) + self.assertFalse(observed["s2_30"] & observed["s2_40"]) + + def test_release_validator_requires_complete_detached_family_once_allowlist_is_live(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + (root / "manifest").mkdir(parents=True) + (root / "manifest/s2_40_parent_member_paths.json").write_text('["schemas/package.schema.json"]\n', encoding="utf-8") + errors, pending, counts = VALIDATOR._validate_s2_40_detached(root, b"{}\n") + self.assertFalse(pending) + self.assertEqual(counts["s2_40_run_code_task_count"], 0) + self.assertIn("S2_40_DETACHED_ASSET_MISSING", {row["code"] for row in errors}) + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_release_closure.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_release_closure.txt new file mode 100644 index 00000000..dcb5df4e --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_release_closure.txt @@ -0,0 +1,257 @@ +#!/usr/bin/env python3 +"""S2_40 owner-aware parent closure and detached admission tests.""" + +from __future__ import annotations + +import importlib.util +import hashlib +import json +import os +from pathlib import Path +import tempfile +import unittest + + +ROOT = Path(__file__).resolve().parents[2] +BUILDER_PATH = ROOT / "offline_build/build_release_manifests.py" +VALIDATOR_PATH = ROOT / "release_ops/release_validator.py" + + +def load_module(name: str, path: Path): + spec = importlib.util.spec_from_file_location(name, path) + if spec is None or spec.loader is None: + raise RuntimeError(path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +BUILDER = load_module("s2_40_release_builder", BUILDER_PATH) +VALIDATOR = load_module("s2_40_release_validator", VALIDATOR_PATH) + + +def module_template(rows: list[dict[str, object]]) -> dict[str, object]: + return { + "schema_version": "stage2_module_manifest.v1", + "manifest_digest": "0" * 64, + "closure_summary": {}, + "documentation_mirrors": [], + "modules": rows, + } + + +class ReleaseClosureTest(unittest.TestCase): + def test_finding_map_closes_eighteen_v_codes_and_twenty_fixture_families(self) -> None: + mapping = json.loads((ROOT / "registry/regression/finding_fixture_map.yml").read_text(encoding="utf-8")) + rows = mapping["mapping_rows"] + self.assertEqual({row["invariant_id"] for row in rows}, {f"V{index:02d}" for index in range(1, 19)}) + self.assertTrue(all(row["source_locator"] and row["mutation_id"] for row in rows)) + families = mapping["s2_40_fixture_family_coverage_rows"] + self.assertEqual({row["family_id"] for row in families}, {f"S40-FAMILY-{index:02d}" for index in range(1, 21)}) + self.assertFalse(mapping["execution_eligible"]) + self.assertIn("PENDING", mapping["status"]) + + def test_s2_40_regression_manifest_binds_all_payload_and_seven_test_oracles(self) -> None: + manifest_path = ROOT / "tests/fixtures/s2_40/regression_manifest.json" + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + physical = sorted(path for path in (manifest_path.parent).glob("*.json") if path.name != "regression_manifest.json") + self.assertEqual(len(physical), 15) + self.assertEqual(len(manifest["rows"]), 15) + self.assertEqual({row["fixture_case_id"] for row in manifest["rows"]}, {f"S40-F{index:03d}" for index in range(1, 16)}) + for row in manifest["rows"]: + path = ROOT / row["path"] + self.assertTrue(path.is_file()) + self.assertEqual(row["raw_sha256"], hashlib.sha256(path.read_bytes()).hexdigest()) + fixture = json.loads(path.read_text(encoding="utf-8")) + self.assertEqual(fixture["header"]["fixture_case_id"], row["fixture_case_id"]) + self.assertEqual(fixture["header"]["oracle_kind"], row["oracle_kind"]) + self.assertEqual(fixture["expected"]["route"], row["expected_route"]) + self.assertEqual(set(fixture["expected"]["expected_invariant_results"]), set(row["expected_invariant_ids"])) + self.assertTrue(fixture["header"]["fixture_only"]) + self.assertFalse(fixture["header"]["production_admissible"]) + expected_tests = {f"tests/s2_40/{path.name}" for path in (ROOT / "tests/s2_40").glob("test_*.py")} + self.assertEqual(len(expected_tests), 7) + self.assertEqual({row["path"] for row in manifest["test_sources"]}, expected_tests) + for row in manifest["test_sources"]: + self.assertEqual(row["raw_sha256"], hashlib.sha256((ROOT / row["path"]).read_bytes()).hexdigest()) + material = {key: value for key, value in manifest.items() if key != "manifest_digest"} + raw = (json.dumps(material, ensure_ascii=False, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8") + self.assertEqual(manifest["manifest_digest"], hashlib.sha256(raw).hexdigest()) + + def test_release_sources_have_exact_documentation_mirrors(self) -> None: + for path in (BUILDER_PATH, VALIDATOR_PATH): + with self.subTest(path=path): + self.assertEqual(path.read_bytes(), path.with_suffix(".txt").read_bytes()) + + def test_s2_40_detached_members_are_forbidden_from_parent(self) -> None: + expected = { + "agent_scripts/Stage_2_S2_40.yml", + "runtime/s2_40_commit.py", + "runtime/s2_40_commit.txt", + "manifest/s2_40_inline_code_receipt.json", + "deployment/stage2_code_executor_binding.yml", + "manifest/stage2_deterministic_admission_receipt.json", + } + self.assertTrue(expected.issubset(BUILDER.FORBIDDEN_PARENT_MEMBERS)) + self.assertEqual(BUILDER.FORBIDDEN_PARENT_MEMBERS, VALIDATOR.FORBIDDEN_PARENT_MEMBERS) + + def test_owner_aware_builder_repairs_old_s2_30_generic_rows(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + s30 = "tests/s2_30/example.json" + s40 = "tests/s2_40/example.json" + for relative in (s30, s40): + path = root / relative + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("{}\n", encoding="utf-8") + wrong = BUILDER._generic_module_row(s30, "S2_20") + manifest = BUILDER.build_module_manifest( + root, + module_template([wrong]), + [s30, s40], + path_owners={s30: "S2_30", s40: "S2_40"}, + ) + rows = {row["path"]: row for row in manifest["modules"]} + self.assertEqual(rows[s30]["owner"], "Stage_2_S2_30_owner") + self.assertEqual(rows[s30]["asset_version"], "s2_30.1") + self.assertTrue(rows[s30]["module_id"].startswith("S2_30-ASSET-")) + self.assertEqual(rows[s30]["scope_predicate"], "workflow_id == S2_30") + self.assertEqual(rows[s40]["owner"], "Stage_2_S2_40_owner") + self.assertEqual(rows[s40]["schema_version"], "stage2_s2_40_generic_asset.v1") + self.assertEqual( + manifest["closure_summary"]["generic_module_counts_by_stage"], + {"S2_20": 0, "S2_30": 1, "S2_40": 1}, + ) + + def test_builder_replaces_transitioned_s2_40_stub_with_full_workflow_row(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + workflow = root / BUILDER.S2_40_WORKFLOW_PATH + workflow.parent.mkdir(parents=True) + workflow.write_text("Agent:\n name: S2_40_final_review_render_and_commit\n", encoding="utf-8") + stub = { + "asset_version": "s2_40.status_only.1", + "authority_ids": [], + "consumed_schema_ids": [], + "dependency_module_ids": [], + "forbidden_contract_codes": [], + "implementation_status": "DRAFT_HANDOFF_STUB_HASH_BOUND", + "incompatible_module_ids": [], + "inputs": ["ingress/ingress_status.json"], + "module_id": "WF-S2_40-STATUS-ONLY", + "module_kind": "WORKFLOW", + "outputs": ["control/run_status.json"], + "owner": "Stage_2_S2_40_owner", + "path": BUILDER.S2_40_WORKFLOW_PATH, + "produced_schema_ids": [], + "schema_version": "stage2_workflow_contract.v1", + "scope_predicate": "entrypoint_id == S2_40_STATUS_ONLY", + "semantic_review_status": "PENDING_CROSS_AUDIT", + } + manifest = BUILDER.build_module_manifest( + root, + module_template([stub]), + [BUILDER.S2_40_WORKFLOW_PATH], + path_owners={BUILDER.S2_40_WORKFLOW_PATH: "S2_40"}, + ) + row = manifest["modules"][0] + for key, expected in BUILDER.S2_40_WORKFLOW_METADATA.items(): + self.assertEqual(row[key], expected, key) + self.assertTrue(row["sha256"]) + self.assertEqual(row["size_bytes"], len(workflow.read_bytes())) + self.assertFalse( + { + row["module_id"], + row["asset_version"], + row["implementation_status"], + row["scope_predicate"], + } + & BUILDER.S2_40_TRANSITIONED_STUB_VALUES + ) + + def test_validator_rejects_transitioned_stub_and_accepts_authoritative_metadata(self) -> None: + stub = dict(BUILDER.S2_40_WORKFLOW_METADATA) + stub.update( + { + "module_id": "WF-S2_40-STATUS-ONLY", + "asset_version": "s2_40.status_only.1", + "implementation_status": "DRAFT_HANDOFF_STUB_HASH_BOUND", + "scope_predicate": "entrypoint_id == S2_40_STATUS_ONLY", + } + ) + errors = VALIDATOR._validate_s2_40_workflow_module_row([stub]) + codes = {row["code"] for row in errors} + self.assertIn("S2_40_TRANSITIONED_STUB_METADATA_FORBIDDEN", codes) + self.assertIn("S2_40_WORKFLOW_MODULE_METADATA_MISMATCH", codes) + self.assertEqual( + VALIDATOR._validate_s2_40_workflow_module_row( + [dict(BUILDER.S2_40_WORKFLOW_METADATA)] + ), + [], + ) + + def test_validator_requires_workflow_anchor_only_after_s2_40_family_activation(self) -> None: + pre_s2_40 = [{"module_id": "SCHEMA-CONTEXT", "owner": "Stage_2_shared"}] + self.assertEqual( + VALIDATOR._validate_s2_40_workflow_module_row(pre_s2_40), + [], + ) + activated_without_anchor = [ + { + "module_id": "S2_40-ASSET-EXAMPLE", + "owner": "Stage_2_S2_40_owner", + "schema_version": "stage2_s2_40_generic_asset.v1", + } + ] + errors = VALIDATOR._validate_s2_40_workflow_module_row( + activated_without_anchor + ) + self.assertEqual( + {row["code"] for row in errors}, + {"S2_40_WORKFLOW_MODULE_ROW_EXACT_ONE_REQUIRED"}, + ) + + def test_validator_resolves_relative_root_before_authoring_derivation(self) -> None: + relative = Path(os.path.relpath(ROOT, Path.cwd())) + self.assertFalse(relative.is_absolute()) + self.assertEqual(VALIDATOR._resolve_root(relative), ROOT.resolve(strict=True)) + self.assertEqual( + VALIDATOR._resolve_root(relative).parent.parent / "Stage_2_S2_40.yml", + ROOT.resolve(strict=True).parent.parent / "Stage_2_S2_40.yml", + ) + + def test_owner_mapping_rejects_unknown_or_nonclosure_paths(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + path = root / "data/example.json" + path.parent.mkdir(parents=True) + path.write_text("{}\n", encoding="utf-8") + template = module_template([]) + with self.assertRaises(BUILDER.ReleaseBuildError): + BUILDER.build_module_manifest(root, template, ["data/example.json"], {"data/example.json": "S2_99"}) + with self.assertRaises(BUILDER.ReleaseBuildError): + BUILDER.build_module_manifest(root, template, ["data/example.json"], {"data/other.json": "S2_40"}) + + def test_three_allowlists_are_sorted_unique_and_pairwise_disjoint(self) -> None: + observed: dict[str, set[str]] = {} + for stage in ("s2_20", "s2_30", "s2_40"): + values = json.loads((ROOT / f"manifest/{stage}_parent_member_paths.json").read_text(encoding="utf-8")) + self.assertEqual(values, sorted(set(values))) + observed[stage] = set(values) + self.assertFalse(observed["s2_20"] & observed["s2_30"]) + self.assertFalse(observed["s2_20"] & observed["s2_40"]) + self.assertFalse(observed["s2_30"] & observed["s2_40"]) + + def test_release_validator_requires_complete_detached_family_once_allowlist_is_live(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + (root / "manifest").mkdir(parents=True) + (root / "manifest/s2_40_parent_member_paths.json").write_text('["schemas/package.schema.json"]\n', encoding="utf-8") + errors, pending, counts = VALIDATOR._validate_s2_40_detached(root, b"{}\n") + self.assertFalse(pending) + self.assertEqual(counts["s2_40_run_code_task_count"], 0) + self.assertIn("S2_40_DETACHED_ASSET_MISSING", {row["code"] for row in errors}) + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_review_state_machine.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_review_state_machine.py new file mode 100644 index 00000000..74ae687b --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_review_state_machine.py @@ -0,0 +1,165 @@ +from __future__ import annotations + +from datetime import datetime, timezone +import json +from pathlib import Path +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +from runtime.validation.invariant_runner import ( # noqa: E402 + derive_review_requirements, + review_receipt_signed_material_digest, + review_subject_digest, + transition_review_state, + validate_jsonschema_instance, +) + +DIGEST = "a" * 64 +SUBJECT = "b" * 64 +NOW = datetime(2030, 1, 1, 12, 0, tzinfo=timezone.utc) +FINDINGS = ["F-V13-AUTHORITY"] +SCOPES = ["CG-001"] +REQUEST_IDS = { + "STANDARD_ATTORNEY_REVIEW": "RR40-STANDARD", + "MANDATORY_SPECIALIST_REVIEW": "RR40-SPECIALIST", +} + + +def valid_receipt( + receipt_type: str = "STANDARD_ATTORNEY_REVIEW", + *, disposition: str = "APPROVE_AS_IS", change_scope: str = "NONE", +) -> dict[str, object]: + value: dict[str, object] = { + "schema_version": "stage2_s2_40_review_receipt.v1", + "receipt_id": "RECEIPT-" + receipt_type, + "request_id": REQUEST_IDS[receipt_type], + "receipt_type": receipt_type, + "candidate_content_digest": DIGEST, + "review_subject_digest": SUBJECT, + "finding_ids": FINDINGS, + "scope_ids": SCOPES, + "reviewer_role": "KOREAN_LAWYER", + "reviewer_qualification": "QUALIFIED_KOREAN_LAWYER", + "issuer_id": "AGENTBACKEND_STAGE2_REVIEW_AUTHORITY", + "key_id": "AGENTBACKEND_STAGE2_REVIEW_KEY_V1", + "signature_algorithm": "AGENTBACKEND_TRUSTED_ATTESTATION_V1", + "signed_material_digest": "0" * 64, + "external_verification_attestation_sha256": "c" * 64, + "issued_at": "2030-01-01T10:00:00Z", + "expires_at": "2030-01-01T14:00:00Z", + "revocation_status": "NOT_REVOKED", + "cryptographic_verification_status": "VERIFIED_BY_EXTERNAL_ADAPTER", + "review_disposition": disposition, + "change_scope": change_scope, + "reason_codes": [], + } + value["signed_material_digest"] = review_receipt_signed_material_digest(value) + return value + + +def transition(receipts: list[dict[str, object]], required: list[str] | None = None) -> dict[str, object]: + required = required or ["STANDARD_ATTORNEY_REVIEW"] + return transition_review_state( + candidate_digest=DIGEST, + required_receipt_types=required, + receipts=receipts, + expected_review_subject_digest=SUBJECT, + expected_request_ids={key: REQUEST_IDS[key] for key in required}, + expected_finding_ids=FINDINGS, + expected_scope_ids=SCOPES, + now=NOW, + ) + + +class ReviewStateTests(unittest.TestCase): + def test_noncyclic_review_objects_validate_against_physical_schemas(self) -> None: + package_schema = json.loads((ROOT / "schemas/package.schema.json").read_text()) + review_schema = json.loads((ROOT / "schemas/review_status.schema.json").read_text()) + store = {"review_status.schema.json": review_schema, "package.schema.json": package_schema} + release_hashes = {"parent": "1" * 64, "authority": "2" * 64, "corpus": "3" * 64, "case_type_coverage": "4" * 64} + request_core = { + "candidate_content_digest": DIGEST, "receipt_type": "STANDARD_ATTORNEY_REVIEW", + "scope_ids": SCOPES, "finding_ids": FINDINGS, "policy_version": "review-policy.v1", + "policy_sha256": "5" * 64, "reviewer_role": "KOREAN_LAWYER", + "reviewer_qualification": "QUALIFIED_KOREAN_LAWYER", + "release_snapshot_sha256s": release_hashes, + } + packet_core = { + "schema_version": "stage2_s2_40_lawyer_review_packet_core.v1", + "candidate_content_digest": DIGEST, "finding_ids": FINDINGS, "scope_ids": SCOPES, + "document_refs": ["claim_relief.md", "claim_cause.md", "pleading_draft.md"], + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + validation_core = { + "schema_version": "stage2_s2_40_validation_envelope_core.v1", + "candidate_content_digest": DIGEST, "validation_core_sha256": "6" * 64, + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + subject = review_subject_digest( + candidate_digest=DIGEST, review_request_core_sha256="7" * 64, + lawyer_review_packet_core_sha256="8" * 64, validation_envelope_core_sha256="9" * 64, + finding_ids=FINDINGS, scope_ids=SCOPES, policy_sha256="5" * 64, + release_sha256s=release_hashes, + ) + packet = { + "schema_version": "stage2_s2_40_lawyer_review_packet.v1", + "lawyer_review_packet_core": packet_core, "lawyer_review_packet_core_sha256": "8" * 64, + "review_subject_digest": subject, + } + validation_envelope = { + "schema_version": "stage2_s2_40_validation_envelope.v1", + "validation_envelope_core": validation_core, "validation_envelope_core_sha256": "9" * 64, + "review_subject_digest": subject, + } + review_request = { + "schema_version": "stage2_s2_40_review_request.v1", "request_id": REQUEST_IDS["STANDARD_ATTORNEY_REVIEW"], + "review_subject_digest": subject, "review_request_core": request_core, + "review_request_core_sha256": "7" * 64, + } + for produced in (packet_core, packet, validation_core, validation_envelope): + validate_jsonschema_instance(produced, package_schema, schema_store=store) + validate_jsonschema_instance(review_request, review_schema, schema_store=store) + validate_jsonschema_instance(valid_receipt(), review_schema, schema_store=store) + + def test_pending_policy_wait_valid_resume_and_no_rerender_fixture(self) -> None: + policy = json.loads((ROOT / "registry/review/review_policy_registry.yml").read_text()) + self.assertEqual(derive_review_requirements(policy, [], []), ["STANDARD_ATTORNEY_REVIEW"]) + self.assertEqual(transition([])["workflow_phase"], "AWAITING_EXTERNAL_REVIEW") + approved = transition([valid_receipt()]) + self.assertEqual((approved["workflow_phase"], approved["route"]), ("READY_TO_COMMIT", "CONTINUE_TO_COMMIT")) + fixture = json.loads((ROOT / "tests/fixtures/s2_40/review_receipt_approve_resume.json").read_text()) + self.assertTrue(fixture["input"]["candidate_bytes_unchanged"]) + self.assertEqual(fixture["input"]["rerender_call_count_on_resume"], 0) + + def test_full_receipt_trust_time_revocation_and_signed_material_mutations_wait(self) -> None: + mutations = { + "issuer_id": "UNTRUSTED", "key_id": "UNKNOWN", "reviewer_role": "NON_LAWYER", + "reviewer_qualification": "NONE", "signature_algorithm": "NONE", + "revocation_status": "REVOKED", "cryptographic_verification_status": "PENDING_PLATFORM_ADMISSION", + "external_verification_attestation_sha256": "bad", "expires_at": "2029-12-31T00:00:00Z", + "candidate_content_digest": "f" * 64, "review_subject_digest": "e" * 64, "request_id": "WRONG", + } + for field, replacement in mutations.items(): + receipt = valid_receipt() + receipt[field] = replacement + if field != "external_verification_attestation_sha256": + receipt["signed_material_digest"] = review_receipt_signed_material_digest(receipt) + with self.subTest(field=field): + outcome = transition([receipt]) + self.assertEqual(outcome["workflow_phase"], "AWAITING_EXTERNAL_REVIEW") + self.assertTrue(outcome["invalid_receipt_ids"]) + receipt = valid_receipt() + receipt["signed_material_digest"] = "d" * 64 + self.assertEqual(transition([receipt])["workflow_phase"], "AWAITING_EXTERNAL_REVIEW") + + def test_content_change_uses_earliest_owner_across_valid_receipts(self) -> None: + standard = valid_receipt(disposition="CONTENT_CHANGE_REQUIRED", change_scope="DRAFTING_TEXT_ATOM") + specialist = valid_receipt("MANDATORY_SPECIALIST_REVIEW", disposition="CONTENT_CHANGE_REQUIRED", change_scope="STAGE1_CONTEXT") + outcome = transition([standard, specialist], ["STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW"]) + self.assertEqual((outcome["workflow_phase"], outcome["route"]), ("SUPERSEDED", "RESTART_FROM_S2_00")) + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_review_state_machine.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_review_state_machine.txt new file mode 100644 index 00000000..74ae687b --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_review_state_machine.txt @@ -0,0 +1,165 @@ +from __future__ import annotations + +from datetime import datetime, timezone +import json +from pathlib import Path +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +from runtime.validation.invariant_runner import ( # noqa: E402 + derive_review_requirements, + review_receipt_signed_material_digest, + review_subject_digest, + transition_review_state, + validate_jsonschema_instance, +) + +DIGEST = "a" * 64 +SUBJECT = "b" * 64 +NOW = datetime(2030, 1, 1, 12, 0, tzinfo=timezone.utc) +FINDINGS = ["F-V13-AUTHORITY"] +SCOPES = ["CG-001"] +REQUEST_IDS = { + "STANDARD_ATTORNEY_REVIEW": "RR40-STANDARD", + "MANDATORY_SPECIALIST_REVIEW": "RR40-SPECIALIST", +} + + +def valid_receipt( + receipt_type: str = "STANDARD_ATTORNEY_REVIEW", + *, disposition: str = "APPROVE_AS_IS", change_scope: str = "NONE", +) -> dict[str, object]: + value: dict[str, object] = { + "schema_version": "stage2_s2_40_review_receipt.v1", + "receipt_id": "RECEIPT-" + receipt_type, + "request_id": REQUEST_IDS[receipt_type], + "receipt_type": receipt_type, + "candidate_content_digest": DIGEST, + "review_subject_digest": SUBJECT, + "finding_ids": FINDINGS, + "scope_ids": SCOPES, + "reviewer_role": "KOREAN_LAWYER", + "reviewer_qualification": "QUALIFIED_KOREAN_LAWYER", + "issuer_id": "AGENTBACKEND_STAGE2_REVIEW_AUTHORITY", + "key_id": "AGENTBACKEND_STAGE2_REVIEW_KEY_V1", + "signature_algorithm": "AGENTBACKEND_TRUSTED_ATTESTATION_V1", + "signed_material_digest": "0" * 64, + "external_verification_attestation_sha256": "c" * 64, + "issued_at": "2030-01-01T10:00:00Z", + "expires_at": "2030-01-01T14:00:00Z", + "revocation_status": "NOT_REVOKED", + "cryptographic_verification_status": "VERIFIED_BY_EXTERNAL_ADAPTER", + "review_disposition": disposition, + "change_scope": change_scope, + "reason_codes": [], + } + value["signed_material_digest"] = review_receipt_signed_material_digest(value) + return value + + +def transition(receipts: list[dict[str, object]], required: list[str] | None = None) -> dict[str, object]: + required = required or ["STANDARD_ATTORNEY_REVIEW"] + return transition_review_state( + candidate_digest=DIGEST, + required_receipt_types=required, + receipts=receipts, + expected_review_subject_digest=SUBJECT, + expected_request_ids={key: REQUEST_IDS[key] for key in required}, + expected_finding_ids=FINDINGS, + expected_scope_ids=SCOPES, + now=NOW, + ) + + +class ReviewStateTests(unittest.TestCase): + def test_noncyclic_review_objects_validate_against_physical_schemas(self) -> None: + package_schema = json.loads((ROOT / "schemas/package.schema.json").read_text()) + review_schema = json.loads((ROOT / "schemas/review_status.schema.json").read_text()) + store = {"review_status.schema.json": review_schema, "package.schema.json": package_schema} + release_hashes = {"parent": "1" * 64, "authority": "2" * 64, "corpus": "3" * 64, "case_type_coverage": "4" * 64} + request_core = { + "candidate_content_digest": DIGEST, "receipt_type": "STANDARD_ATTORNEY_REVIEW", + "scope_ids": SCOPES, "finding_ids": FINDINGS, "policy_version": "review-policy.v1", + "policy_sha256": "5" * 64, "reviewer_role": "KOREAN_LAWYER", + "reviewer_qualification": "QUALIFIED_KOREAN_LAWYER", + "release_snapshot_sha256s": release_hashes, + } + packet_core = { + "schema_version": "stage2_s2_40_lawyer_review_packet_core.v1", + "candidate_content_digest": DIGEST, "finding_ids": FINDINGS, "scope_ids": SCOPES, + "document_refs": ["claim_relief.md", "claim_cause.md", "pleading_draft.md"], + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + validation_core = { + "schema_version": "stage2_s2_40_validation_envelope_core.v1", + "candidate_content_digest": DIGEST, "validation_core_sha256": "6" * 64, + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + subject = review_subject_digest( + candidate_digest=DIGEST, review_request_core_sha256="7" * 64, + lawyer_review_packet_core_sha256="8" * 64, validation_envelope_core_sha256="9" * 64, + finding_ids=FINDINGS, scope_ids=SCOPES, policy_sha256="5" * 64, + release_sha256s=release_hashes, + ) + packet = { + "schema_version": "stage2_s2_40_lawyer_review_packet.v1", + "lawyer_review_packet_core": packet_core, "lawyer_review_packet_core_sha256": "8" * 64, + "review_subject_digest": subject, + } + validation_envelope = { + "schema_version": "stage2_s2_40_validation_envelope.v1", + "validation_envelope_core": validation_core, "validation_envelope_core_sha256": "9" * 64, + "review_subject_digest": subject, + } + review_request = { + "schema_version": "stage2_s2_40_review_request.v1", "request_id": REQUEST_IDS["STANDARD_ATTORNEY_REVIEW"], + "review_subject_digest": subject, "review_request_core": request_core, + "review_request_core_sha256": "7" * 64, + } + for produced in (packet_core, packet, validation_core, validation_envelope): + validate_jsonschema_instance(produced, package_schema, schema_store=store) + validate_jsonschema_instance(review_request, review_schema, schema_store=store) + validate_jsonschema_instance(valid_receipt(), review_schema, schema_store=store) + + def test_pending_policy_wait_valid_resume_and_no_rerender_fixture(self) -> None: + policy = json.loads((ROOT / "registry/review/review_policy_registry.yml").read_text()) + self.assertEqual(derive_review_requirements(policy, [], []), ["STANDARD_ATTORNEY_REVIEW"]) + self.assertEqual(transition([])["workflow_phase"], "AWAITING_EXTERNAL_REVIEW") + approved = transition([valid_receipt()]) + self.assertEqual((approved["workflow_phase"], approved["route"]), ("READY_TO_COMMIT", "CONTINUE_TO_COMMIT")) + fixture = json.loads((ROOT / "tests/fixtures/s2_40/review_receipt_approve_resume.json").read_text()) + self.assertTrue(fixture["input"]["candidate_bytes_unchanged"]) + self.assertEqual(fixture["input"]["rerender_call_count_on_resume"], 0) + + def test_full_receipt_trust_time_revocation_and_signed_material_mutations_wait(self) -> None: + mutations = { + "issuer_id": "UNTRUSTED", "key_id": "UNKNOWN", "reviewer_role": "NON_LAWYER", + "reviewer_qualification": "NONE", "signature_algorithm": "NONE", + "revocation_status": "REVOKED", "cryptographic_verification_status": "PENDING_PLATFORM_ADMISSION", + "external_verification_attestation_sha256": "bad", "expires_at": "2029-12-31T00:00:00Z", + "candidate_content_digest": "f" * 64, "review_subject_digest": "e" * 64, "request_id": "WRONG", + } + for field, replacement in mutations.items(): + receipt = valid_receipt() + receipt[field] = replacement + if field != "external_verification_attestation_sha256": + receipt["signed_material_digest"] = review_receipt_signed_material_digest(receipt) + with self.subTest(field=field): + outcome = transition([receipt]) + self.assertEqual(outcome["workflow_phase"], "AWAITING_EXTERNAL_REVIEW") + self.assertTrue(outcome["invalid_receipt_ids"]) + receipt = valid_receipt() + receipt["signed_material_digest"] = "d" * 64 + self.assertEqual(transition([receipt])["workflow_phase"], "AWAITING_EXTERNAL_REVIEW") + + def test_content_change_uses_earliest_owner_across_valid_receipts(self) -> None: + standard = valid_receipt(disposition="CONTENT_CHANGE_REQUIRED", change_scope="DRAFTING_TEXT_ATOM") + specialist = valid_receipt("MANDATORY_SPECIALIST_REVIEW", disposition="CONTENT_CHANGE_REQUIRED", change_scope="STAGE1_CONTEXT") + outcome = transition([standard, specialist], ["STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW"]) + self.assertEqual((outcome["workflow_phase"], outcome["route"]), ("SUPERSEDED", "RESTART_FROM_S2_00")) + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_v01_v18.py b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_v01_v18.py new file mode 100644 index 00000000..69ba06e4 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_v01_v18.py @@ -0,0 +1,81 @@ +from __future__ import annotations + +import json +from pathlib import Path +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +from runtime.validation.invariant_runner import INVARIANT_IDS, InvariantError, aggregate_status, run_invariants # noqa: E402 + + +def all_pass_checks(): + return { + key: { + "evaluable": True, + "passed": True, + "impact_scope": "OK", + "source_refs": [f"fixture://{key}/normal"], + "finding_ids": [], + "expected": {"contract_state": "BOUND"}, + "observed": {"contract_state": "BOUND"}, + "reason_codes": [], + } + for key in INVARIANT_IDS + } + + +class InvariantTests(unittest.TestCase): + def test_exact_eighteen_and_each_mutation(self) -> None: + fixture = json.loads((ROOT / "tests/fixtures/s2_40/v01_v18_invariant_matrix.json").read_text(encoding="utf-8")) + self.assertEqual(tuple(fixture["input"]["invariant_ids"]), INVARIANT_IDS) + results = run_invariants(all_pass_checks()) + self.assertEqual(len(results), 18) + fixture_rows = {row["mutation_id"].split("-", 1)[0]: row for row in fixture["mutations"]} + self.assertEqual(set(fixture_rows), set(INVARIANT_IDS)) + for target in INVARIANT_IDS: + oracle = fixture_rows[target] + self.assertEqual(oracle["contradiction"]["evaluation_status"], "FAIL") + self.assertEqual(oracle["absence"]["evaluation_status"], "UNEVALUABLE") + self.assertTrue(oracle["source_finding_ids"]) + checks = all_pass_checks() + checks[target] = { + "evaluable": True, + "passed": False, + "impact_scope": "REVIEW_REQUIRED", + "source_refs": [f"fixture://{target}/contradiction"], + "finding_ids": [f"F-{target}-CONTRADICTION"], + "expected": {"contract_state": "BOUND"}, + "observed": {"contract_state": "DRIFT"}, + "reason_codes": [f"{target}_CONTRADICTION"], + } + mutated = run_invariants(checks) + self.assertEqual(mutated[INVARIANT_IDS.index(target)]["evaluation_status"], "FAIL") + checks[target] = { + "evaluable": False, + "passed": False, + "impact_scope": "REVIEW_REQUIRED", + "source_refs": [f"fixture://{target}/absence"], + "finding_ids": [f"F-{target}-ABSENCE"], + "expected": {"contract_state": "BOUND"}, + "observed": None, + "reason_codes": [f"{target}_ABSENT_UNEVALUABLE"], + } + unevaluable = run_invariants(checks) + self.assertEqual(unevaluable[INVARIANT_IDS.index(target)]["evaluation_status"], "UNEVALUABLE") + with self.assertRaisesRegex(InvariantError, "EXACT_V01_V18"): + run_invariants({}) + + def test_ready_formula_has_no_fixture_or_pending_asset_loophole(self) -> None: + results = run_invariants(all_pass_checks()) + gates = {name: True for name in {"binding", "authority", "renderer_branch", "rule_sub_rule", "review_policy", "case_type_coverage_137", "corpus", "law_value", "calculator", "required_receipts"}} + self.assertEqual(aggregate_status(results, compile_mode="STRUCTURAL_FIXTURE", legal_gates=gates)["legal_readiness"], "LAWYER_REVIEW_REQUIRED") + gates["renderer_branch"] = False + self.assertEqual(aggregate_status(results, compile_mode="PRODUCTION", legal_gates=gates)["legal_readiness"], "LAWYER_REVIEW_REQUIRED") + gates["renderer_branch"] = True + self.assertEqual(aggregate_status(results, compile_mode="PRODUCTION", legal_gates=gates)["legal_readiness"], "READY_FOR_LAWYER_FILING_DECISION") + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_v01_v18.txt b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_v01_v18.txt new file mode 100644 index 00000000..69ba06e4 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/tests/s2_40/test_v01_v18.txt @@ -0,0 +1,81 @@ +from __future__ import annotations + +import json +from pathlib import Path +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +from runtime.validation.invariant_runner import INVARIANT_IDS, InvariantError, aggregate_status, run_invariants # noqa: E402 + + +def all_pass_checks(): + return { + key: { + "evaluable": True, + "passed": True, + "impact_scope": "OK", + "source_refs": [f"fixture://{key}/normal"], + "finding_ids": [], + "expected": {"contract_state": "BOUND"}, + "observed": {"contract_state": "BOUND"}, + "reason_codes": [], + } + for key in INVARIANT_IDS + } + + +class InvariantTests(unittest.TestCase): + def test_exact_eighteen_and_each_mutation(self) -> None: + fixture = json.loads((ROOT / "tests/fixtures/s2_40/v01_v18_invariant_matrix.json").read_text(encoding="utf-8")) + self.assertEqual(tuple(fixture["input"]["invariant_ids"]), INVARIANT_IDS) + results = run_invariants(all_pass_checks()) + self.assertEqual(len(results), 18) + fixture_rows = {row["mutation_id"].split("-", 1)[0]: row for row in fixture["mutations"]} + self.assertEqual(set(fixture_rows), set(INVARIANT_IDS)) + for target in INVARIANT_IDS: + oracle = fixture_rows[target] + self.assertEqual(oracle["contradiction"]["evaluation_status"], "FAIL") + self.assertEqual(oracle["absence"]["evaluation_status"], "UNEVALUABLE") + self.assertTrue(oracle["source_finding_ids"]) + checks = all_pass_checks() + checks[target] = { + "evaluable": True, + "passed": False, + "impact_scope": "REVIEW_REQUIRED", + "source_refs": [f"fixture://{target}/contradiction"], + "finding_ids": [f"F-{target}-CONTRADICTION"], + "expected": {"contract_state": "BOUND"}, + "observed": {"contract_state": "DRIFT"}, + "reason_codes": [f"{target}_CONTRADICTION"], + } + mutated = run_invariants(checks) + self.assertEqual(mutated[INVARIANT_IDS.index(target)]["evaluation_status"], "FAIL") + checks[target] = { + "evaluable": False, + "passed": False, + "impact_scope": "REVIEW_REQUIRED", + "source_refs": [f"fixture://{target}/absence"], + "finding_ids": [f"F-{target}-ABSENCE"], + "expected": {"contract_state": "BOUND"}, + "observed": None, + "reason_codes": [f"{target}_ABSENT_UNEVALUABLE"], + } + unevaluable = run_invariants(checks) + self.assertEqual(unevaluable[INVARIANT_IDS.index(target)]["evaluation_status"], "UNEVALUABLE") + with self.assertRaisesRegex(InvariantError, "EXACT_V01_V18"): + run_invariants({}) + + def test_ready_formula_has_no_fixture_or_pending_asset_loophole(self) -> None: + results = run_invariants(all_pass_checks()) + gates = {name: True for name in {"binding", "authority", "renderer_branch", "rule_sub_rule", "review_policy", "case_type_coverage_137", "corpus", "law_value", "calculator", "required_receipts"}} + self.assertEqual(aggregate_status(results, compile_mode="STRUCTURAL_FIXTURE", legal_gates=gates)["legal_readiness"], "LAWYER_REVIEW_REQUIRED") + gates["renderer_branch"] = False + self.assertEqual(aggregate_status(results, compile_mode="PRODUCTION", legal_gates=gates)["legal_readiness"], "LAWYER_REVIEW_REQUIRED") + gates["renderer_branch"] = True + self.assertEqual(aggregate_status(results, compile_mode="PRODUCTION", legal_gates=gates)["legal_readiness"], "READY_FOR_LAWYER_FILING_DECISION") + + +if __name__ == "__main__": + unittest.main() diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/workflows/S2_30_claim_group_draft_map.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/workflows/S2_30_claim_group_draft_map.yml index 02933f70..d89a2864 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/workflows/S2_30_claim_group_draft_map.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/workflows/S2_30_claim_group_draft_map.yml @@ -307,19 +307,24 @@ native_adapter_contract: - S2_30_CACHE_OWNER_SEQUENCE_V1 - S2_30_STRICT_SCHEMA_REF_PROVENANCE_VALIDATOR_V1 - S2_30_DETERMINISTIC_ATOM_ID_TWO_PASS_PERSIST_V1 + - S2_30_TYPED_PART_WRAPPER_PERSIST_V1 + - S2_30_RECEIPT_FREE_PART_MANIFEST_CORE_V1 - S2_30_GROUP_RETRY_CONTROLLER_V1 - S2_30_GROUP_BARRIER_COORDINATOR_V1 + - S2_30_ORDERED_RECEIPT_INDEX_V1 - S2_30_CANARY_AUTHORIZATION_SIGNATURE_VERIFY_V1 missing_capability_action: STOP_BEFORE_LLM_CALL deterministic_atom_id_algorithm: S2_30-DETERMINISTIC-ATOM-ID-V1 local_ref_rewrite_algorithm: S2_30-TWO-PASS-LOCAL-REF-REWRITE-V1 persistence_policy: IMMUTABLE_IDEMPOTENT_READ_BACK_VERIFIED + handoff_index_policy: BARRIER_TO_RECEIPT_FREE_MANIFEST_TO_EXACT_PARTS_NO_SCAN status_policy: STATUS_LAST_AFTER_ALL_EXPECTED_GROUPS_TERMINAL output_contract: root: map_s2_30 group_path_token: paths: + artifact_manifest: map_s2_30/artifact_manifest.json draft_parts: map_s2_30/draft_parts/.json issue_patches: map_s2_30/issue_patches/.json worknote_parts: map_s2_30/worknote_parts/.json @@ -330,6 +335,11 @@ output_contract: cohort_receipts: map_s2_30/cohort_receipts//attempt-.json publish_status: map_s2_30/s2_30_publish_status.json cohort_receipt_schema_ref: schemas/draft_atoms.schema.json#/$defs/cohort_receipt + draft_part_schema_ref: schemas/draft_atoms.schema.json#/$defs/draft_part + issue_patch_part_schema_ref: schemas/draft_atoms.schema.json#/$defs/issue_patch_part + worknote_part_schema_ref: schemas/draft_atoms.schema.json#/$defs/worknote_part + usage_part_schema_ref: schemas/draft_atoms.schema.json#/$defs/usage_part + artifact_manifest_schema_ref: schemas/draft_atoms.schema.json#/$defs/part_manifest_core cache_owner_completion_receipt_schema_ref: schemas/draft_atoms.schema.json#/$defs/cache_owner_completion_receipt publish_status_schema_ref: schemas/draft_atoms.schema.json#/$defs/publish_status successful_route: TO_S2_40 @@ -337,6 +347,49 @@ output_contract: overwrite_allowed: false read_back_required: true partial_write_preservation_required: true + artifact_manifest_core_contract: + receipt_free: true + exact_part_families: [DRAFT_PART, ISSUE_PATCH, WORKNOTE_PART, USAGE_PART] + exact_rows_per_published_group: 4 + stable_sort_keys: [claim_group_id, part_family, path] + self_hash_field: part_manifest_core_sha256 + item_and_cohort_receipt_hashes_forbidden: true + receipt_binding_contract: + item_and_cohort_receipts_reference_field: part_manifest_core_sha256 + reverse_receipt_reference_from_manifest_forbidden: true + publish_status_orders_item_receipts_by: [claim_group_id, path] + publish_status_orders_cohort_receipts_by: [path] + immutable_write_order: + - EXACT_FOUR_PART_WRAPPERS_PER_SUCCESS_GROUP + - RECEIPT_FREE_ARTIFACT_MANIFEST_CORE + - ITEM_RECEIPTS_REFERENCING_CORE_HASH + - COHORT_RECEIPTS_REFERENCING_CORE_HASH + - S2_30_PUBLISH_STATUS_LAST + handoff_provenance_contract: + group_fields: + - compile_mode + - parent_stage2_release_sha256 + - s2_30_release_sha256 + - s2_30_agent_sha256 + - s2_30_binding_sha256 + - p00_prompt_sha256 + - p30_prompt_sha256 + - p31_rule_and_pack_sha256 + - p32_common_authority_sha256 + - s30_group_slice_sha256 + - s2_30_producer_contract_digest + common_fields: + - compile_mode + - parent_stage2_release_sha256 + - s2_30_release_sha256 + - s2_30_agent_sha256 + - s2_30_binding_sha256 + - p00_prompt_sha256 + - p30_prompt_sha256 + - s2_30_producer_contract_digest + exact_echo_chain: PART_TO_MANIFEST_TO_RECEIPT_TO_PUBLISH_STATUS_TO_S2_40_REQUEST + directory_scan_allowed: false + glob_allowed: false status_written_last: true guards: diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/workflows/S2_40_final_review_render_and_commit.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/workflows/S2_40_final_review_render_and_commit.yml index 1c5b665c..e47aa24e 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/workflows/S2_40_final_review_render_and_commit.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/workflows/S2_40_final_review_render_and_commit.yml @@ -1,103 +1,89 @@ Agent: name: S2_40_final_review_render_and_commit description: >- - S2_00 diagnostic route를 정확한 5개 artifact로만 종결하는 S2_40 - deterministic status-only entry. 이 entry는 법률판단이나 pleading을 수행하지 않는다. - version: "1.0.0-draft" + S2_30 immutable parts 또는 S2_00 exact-five diagnostic handoff를 소비하는 + deterministic final reduce, closed render, V01-V18, review-state, seal 및 logical commit 계약. + version: "2.0.0" metadata: workflow_id: S2_40 - entrypoint_id: S2_40_STATUS_ONLY workflow_schema_version: stage2_workflow_contract.v1 - asset_version: s2_40.status_only.1 - owner: Stage_2_S2_40_owner - implementation_status: DETERMINISTIC_STUB_NOT_EXECUTABLE - upstream_handoff_id: S2_00_TO_S2_40_STATUS_ONLY_V1 + execution_class: NON-LLM-DETERMINISTIC + implementation_status: IMPLEMENTED_OFFLINE_CONTRACT_LIVE_ADMISSION_PENDING + legal_content_status: PENDING_LEGAL_CONTENT final_status_single_writer: S2_40 - + runtime_external_python_import_count: 0 + legacy_stage2_v0_v3_dependency_count: 0 Stages: - - name: S2_40_STATUS_ONLY - description: technical diagnostic를 deterministic 3축 status로 기록한다. - prevs: - - S2_00 + - name: S2_40_FINALIZE + description: exactly one inline Code Executor task owns both closed entry routes. + prevs: [S2_00, S2_30] nexts: [] - - handoff_contract: - handoff_id: S2_00_TO_S2_40_STATUS_ONLY_V1 - accepted_route: TO_S2_40_STATUS_ONLY - exact_input_count: 5 - exact_inputs: + entry_contract: + accepted_routes: [TO_S2_40, TO_S2_40_STATUS_ONLY] + route_cardinality: EXACTLY_ONE + request_path: stage2_control/s2_40_request.json + request_schema_ref: schemas/deployment.schema.json#/$defs/s2_40_request + directory_scan_allowed: false + glob_allowed: false + basename_fallback_allowed: false + status_only_exact_inputs: - ingress/ingress_status.json - ingress/technical_diagnostic.json - ingress/stage1_input_manifest.json - ingress/intake_report.json - review/issue_ledger.base.json - additional_input_allowed: false - directory_scan_allowed: false - glob_allowed: false - raw_stage1_input_allowed: false - context_artifact_input_allowed: false - output_path: control/run_status.json - output_schema_ref: schemas/review_status.schema.json#/$defs/status_only_commit - final_status_fields: - run_technical_status: - - CONSISTENT - - TECHNICAL_REVIEW_REQUIRED - - TECHNICAL_INCOMPLETE - artifact_technical_status: - - CONSISTENT - - TECHNICAL_REVIEW_REQUIRED - - NOT_PRODUCED - legal_readiness: - - NOT_ASSESSED - pleading_render_allowed: false - final_filing_decision_allowed: false - + status_only_exact_input_count: 5 + status_only_additional_input_allowed: false + normal_input_index: map_s2_30/artifact_manifest.json + normal_input_index_must_be_bound_by: map_s2_30/s2_30_publish_status.json task_procedure: - IN: - nexts: - - Task_S2_40_status_only_commit - wait_until: [] - Task_S2_40_status_only_commit: - nexts: - - OUT - wait_until: - - IN - OUT: - nexts: [] - wait_until: - - Task_S2_40_status_only_commit - + IN: {nexts: [Task_S2_40_deterministic_finalizer], wait_until: []} + Task_S2_40_deterministic_finalizer: {nexts: [OUT], wait_until: [IN]} + OUT: {nexts: [], wait_until: [Task_S2_40_deterministic_finalizer]} tasks: - - task_name: Task_S2_40_status_only_commit + - task_name: Task_S2_40_deterministic_finalizer execution_class: NON-LLM-DETERMINISTIC - implementation_status: STUB_NOT_IMPLEMENTED - implementation_ref: PENDING_SEQUENTIAL_BIND - invocation_allowed: false - exact_input_files: - - ingress/ingress_status.json - - ingress/technical_diagnostic.json - - ingress/stage1_input_manifest.json - - ingress/intake_report.json - - review/issue_ledger.base.json - output_file: control/run_status.json - output_schema_ref: schemas/review_status.schema.json#/$defs/status_only_commit - deterministic_rules: - - VERIFY_EXACT_FIVE_INPUT_PATHS_AND_HASHES - - VERIFY_RUN_ID_INPUT_SET_DIGEST_ROUTE_AND_BARRIER - - PRESERVE_ALL_DIAGNOSTIC_AND_ISSUE_REFS - - SET_LEGAL_READINESS_NOT_ASSESSED - - WRITE_SCHEMA_VALID_JSON_ONCE - - ATOMIC_SINGLE_WRITER_COMMIT - - prohibitions: - additional_input_count: 0 - raw_stage1_reread_allowed: false - context_read_allowed: false - pleading_render_allowed: false - legal_conclusion_allowed: false - llm_call_allowed: false - tool_call_allowed: false - dynamic_code_allowed: false - final_status_writer_other_than_s2_40_allowed: false - output_paths: - - control/run_status.json + mcp: code-executor + tool_name: run_code + implementation_ref: Stage_2_S2_40.yml#/Agent/Stages/0/tasks/0/parameters/code + parameters_contract: {language: python, requirements: httpx==0.28.1, network: agent-network, timeout: 300} + internal_components: + - C40_IMMUTABLE_PART_REDUCE + - C45_CLOSED_DOCUMENT_ASSEMBLY_AND_RERENDER + - C46_V01_V18_INVARIANT_RUNNER + - C47_CANDIDATE_REVIEW_STATE_MACHINE + - C48_LOGICAL_COMMIT_AND_BARRIER_LAST + llm_call_allowed: false + shell_or_subprocess_allowed: false + external_python_import_allowed: false + dynamic_code_generation_allowed: false + normal_route_contract: + reduce_order: STABLE_GROUP_PART_ROW_ID + last_write_wins_allowed: false + option_partition: [selected, alternative, excluded, deferred] + renderer_branch_cardinality: EXACTLY_ONE + free_text_relief_fallback_allowed: false + independent_rerender_byte_equality_required: true + invariant_ids: [V01, V02, V03, V04, V05, V06, V07, V08, V09, V10, V11, V12, V13, V14, V15, V16, V17, V18] + candidate_digest_cycle_allowed: false + state_machine: [FREEZE, WAIT, RESUME_VALIDATE, READY_TO_COMMIT, SUPERSEDED, COMMIT] + external_review_receipt_writer: EXTERNAL_QUALIFIED_REVIEWER_ONLY + content_change_in_place_allowed: false + output_contract: + candidate_root: candidates/by-content-digest// + final_root: final/ + status_event_root: control/status_events/ + final_barrier_path: control/run_status.json + final_barrier_schema_ref: schemas/review_status.schema.json#/$defs/run_status + status_only_schema_ref: schemas/review_status.schema.json#/$defs/status_only_commit + barrier_written_last: true + final_status_single_writer: S2_40 + physical_atomicity_claimed_by_inline_code: false + host_cas_required: true + admission_ceiling: + offline_contract_tests_can_grant: IMPLEMENTED_OFFLINE_VERIFIED + live_platform_evidence_required: true + korean_lawyer_legal_asset_approval_required: true + pending_renderer_or_review_policy_can_be_ready: false + structural_fixture_can_be_ready: false + filing_requires_separate_filing_decision_receipt: true diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/MEMORY.md b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/MEMORY.md index 00f5ade4..59daea57 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/MEMORY.md +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/MEMORY.md @@ -16,6 +16,18 @@ - 하위 에이전트(subagents)를 사용하여 핵심 테마와 교훈을 식별하고 MEMORY.md에 섹션으로 저장하라. - 향후 세션 시작 시 MEMORY.md의 이전 섹션을 참조하라. +## 2026-09-01 — S2_40 deterministic 최종검증·render·review·commit package offline 구현 + +한 줄 요약: S2_30의 group-parallel immutable part를 무손실 reduce하고 closed render·V01∼V18·review freeze/resume·비순환 seal·content-addressed commit을 수행하는 exactly-one MCP Code Executor S2_40을 구현해 전체 240개 회귀시험과 release 재현성을 통과했으며, live·법률 admission은 증거가 없어 의도적으로 대기 상태로 유지했다. + +- 핵심 산출물: `S2_40_SOW.md` 879행/SHA-256 `6930cd6438ae29187d01c7bf463cf308d34e90c73d4e755b5573ab92090f4a04`, `S2_40_assets.md` 528행/`ed518213100971fde44aca385890761d8b7b2f86ad2c18a29b5f960d46ec8787`, authoring `Stage_2_S2_40.yml` 3,575행/`5cbe2ac9aa73d95a5fa4e6cf71d7d8f0ad83aa05536f573c13e42505ef5d46f7`이다. version-free Agent·runtime mirror·workflow·schema·renderer·fixture·test·builder·binding·receipt는 `Default_Agent/Stage_2_Clean/`에 배포했다. +- 실행헌법 결정: 사용자 prompt의 `[LLM: group-parallel, immutable parts]` 표기는 controlling `stage_2_optimal_update_strategy_v.5-1.md`와 충돌하므로 S2_30 생산특성으로 해석했다. S2_40 자체는 LLM 설정 없이 exactly-one `mcp: code-executor`/`run_code` task이며, inline Python 내부 `C40→C45→C46→C47→C48`과 S2_00 exact-five status-only route만 수행한다. +- 신뢰·보존 계약: S2_00·S2_10·S2_20·S2_30 barrier/manifest/part를 release-bound schema·canonical bytes·hash·producer·ID 집합으로 재검증한다. issue·assumption·usage occurrence를 보존하고 모든 생성 JSON을 write 전 runtime schema 검증하며, `ordered_source_snapshot_preimage`로 FREEZE digest를 RESUME에서 완전 재계산한다. review는 receipt type별 zero/N request를 비순환 ID로 만들고 유효한 `CONTENT_CHANGE_REQUIRED`만 immutable supersession route를 연다. +- final writer 경계: S2_40은 상류 법리·claim·문안을 새로 만들지 않는다. closed renderer와 V01∼V18을 통과한 candidate만 digest-qualified checkpoint로 동결하고, external review가 필요하면 draft/worknote/packet을 보존한 채 WAIT한다. 승인 후 exact final bytes·commit result를 read-back한 다음 `control/run_status.json`을 마지막 유일 소비허가 barrier로 쓴다. +- release 재봉인: module manifest 222개/raw hash `2041e150b1e78c06cb7f24cde1eeb3eaa5ca172a4b740f6b20c1e6dda99bfd38`, parent raw hash `9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53`, S2_10 child `cb49a4501116e46d935933b739b6679b11d961ff8e36abefea35dab6b25508fb`, S2_30 child `e6dd6abe44b39de462ea01f5e78aa39c70bbf47e0b75e08d224615a297d2135f`, shared executor binding `a1062e9db242747c75a4362fb95eeba6c65f78ac647d4571ed774d2ee3af40f7`이다. 임시 output 재생성으로 module/parent bytes 재현성도 확인했다. +- 검증 이력: 요청된 문서 2회, 자산 2회, YAML 2회 독립 검증·증분개정을 정확히 종료했다. no-write builder check 8개와 cumulative release build, release validator errors 0, S2_00 70/70·S2_10 42/42·S2_20 42/42·S2_30 37/37·S2_40 49/49(총 240/240), `.py/.txt` 62/62, S2_00/S2_20/S2_30/S2_40 authoring/projection 4/4가 PASS했다. 구 Stage 2 v.0∼v.3 실행·배포·release dependency는 0이고, v.3 문자열 1건은 legacy 주입 거부를 검증하는 음성 fixture다. +- 상태 경계: `IMPLEMENTED_OFFLINE_VERIFIED / LIVE_AND_LEGAL_ADMISSION_PENDING`이다. validator의 예상 PENDING 4건은 137개 승인 relief-rule 문서 0/137, parent production admission, signed deterministic backend admission, S2_40 live secret/Code Executor binding이다. live MCP/AgentBackend 실행, Stage 1→S2_40 E2E, 대한민국 변호사 검수·filing decision·production promotion은 수행하거나 증명하지 않았다. + ## 2026-08-31 — S2_30 claim-group 공동작성 package offline 구현 한 줄 요약: S2_20의 frozen claim group과 exact P32/P31/S30 자료를 소비해 청구취지·청구원인을 함께 작성하는 GPT-5.6 Sol wildcard Agent를 구현하고, non-legal dispatch planner·schema·native-adapter oracle·shared admission·parent/child hash chain을 재봉인했으며, 전체 186개 회귀시험을 통과했지만 live·법률 admission은 대기 상태로 유지했다. diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/S2_40_SOW.md b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/S2_40_SOW.md new file mode 100644 index 00000000..717249d3 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/S2_40_SOW.md @@ -0,0 +1,879 @@ +# S2_40 YAML·assets·sources 생성 작업명세서 + +> 기준 전략: `stage_2_optimal_update_strategy_v.5-1.md` +> +> 대상 단계: `S2_40 — deterministic final reduce / closed render / V01~V18 / review state / seal / logical commit` +> +> canonical 배포 root: `Default_Agent/Stage_2_Clean/` +> +> 문서 상태: `SPECIFICATION_DRAFT / IMPLEMENTATION_PENDING` +> +> 법률·운영 상태: `OFFLINE_IMPLEMENTATION_ALLOWED / LIVE_PLATFORM_AND_LEGAL_ADMISSION_PENDING` + +--- + +## 0. 집행 결론 + +S2_40은 S2_00·S2_10·S2_20·S2_30이 생성한 immutable part와 barrier를 소비하여 최종 issue ledger를 reduce하고, typed draft atom을 closed renderer로 재구성하며, V01~V18과 review policy를 검증한 뒤 candidate를 동결한다. 필수 외부 review receipt가 없거나 무효하면 같은 candidate digest의 checkpoint를 보존하고 대기한다. 모든 필수 receipt가 유효하면 sealed package를 exact final path에 기록·read-back하고 `control/run_status.json`을 마지막 barrier로 발행한다. + +S2_40 Agent YAML은 **exactly one Stage + exactly one `mcp: code-executor` / `tool_name: run_code` task**만 가진다. C40·C45·C46·C47·C48은 AgentBackend task가 아니라 그 1개 task의 완전한 static inline Python 안에 전개되는 named deterministic component다. LLM task, map/reduce, 외부 `.py` import, shell/subprocess, 사건별 code 생성은 금지한다. + +사용자 prompt의 S2_40 목표를 “group-parallel LLM”로 표현한 부분은 v5-1의 실행 헌법과 충돌한다. S2_40에는 LLM model·reasoning·verbosity·prompt cache 설정을 두지 않는다. group-parallel LLM drafting은 상류 S2_30에서 종료되고 S2_40은 순수 deterministic finalizer로 유지한다. + +### 0.1 내부 DAG + +```text +release/admission/request preflight + | + +---------------- route=TO_S2_40_STATUS_ONLY ----------------+ + | | + | v + | exact 5-input diagnostic + | | + | v + | run_status barrier last + | + v +C40 immutable-part reduce + final issue/assumption/worknote/usage ledger + | + v +C45 closed AST/template assembly + canonical render + independent re-render + | + v +C46 V01~V18 + package/dependency/renderer/calculation/provenance validation + | + v +C47 candidate manifest/core -> candidate_content_digest -> review policy + | + +-------+--------------------------+ + | | + | required receipts absent/invalid | none or all valid APPROVE_AS_IS + v v +FREEZE -> WAIT RESUME_VALIDATE -> READY_TO_COMMIT + | | + | CONTENT_CHANGE_REQUIRED + | v + | SUPERSEDED + earliest-owner route + | | + +----------------------------------+ + v +C48 commit intent -> exact final writes -> read-back -> artifact-set digest + -> commit result -> control/run_status.json COMMITTED barrier last +``` + +### 0.2 Stage 2 헌법과의 정합 + +```text +Stage 2 = deterministic inline Python 3개(S2_00, S2_20, S2_40) + + LLM-DIRECT 2개(S2_10, S2_30) +``` + +S2_40은 법리를 새로 판단하거나 S2_30 문안을 재작성하지 않는다. 검증 결과가 `FAIL` 또는 `UNEVALUABLE`이라도 기술적으로 일관된 review draft를 만들 수 있으면 candidate·worknote·review packet을 보존한다. 반면 schema/hash/producer 불일치, immutable conflict, renderer의 미결합 slot, 근거 없는 사실 삽입 등으로 일관된 산출물을 만들 수 없는 범위만 `TECHNICAL_INCOMPLETE`로 분류한다. + +### 0.3 우선계약 + +1. authoring `Stage_2_S2_40.yml#/Agent/Stages/0/tasks/0/parameters/code`가 runtime Python의 유일 편집 정본이다. +2. deployment Agent, `runtime/s2_40_commit.py/.txt`는 authoring YAML에서 byte-identical로 기계 투영한다. +3. `runtime/c45_document_assembler.py`, `runtime/rendering/closed_renderer.py`, `runtime/validation/invariant_runner.py`는 offline pure-core oracle이며 사건 runtime import target이 아니다. +4. `control/run_status.json`은 S2_40의 유일 downstream 소비 허가 barrier이고 각 invocation에서 마지막에 쓴다. +5. candidate content, review receipt, package, commit result와 run status는 순환 없는 방향성 hash graph를 갖는다. +6. 법률적 불확실성은 전역 no-save 사유가 아니다. 미확정 사실·금액·날짜를 clean pleading의 확정 문장으로 올리지 않고 review material로 보존한다. +7. 현재 존재하는 `workflows/S2_40_final_review_render_and_commit.yml`의 status-only stub은 신규 full workflow에 통합·대체한다. status-only를 두 번째 top-level task로 만들지 않는다. + +--- + +## 1. 절대 범위와 비범위 + +### 1.1 S2_40이 수행한다 + +1. S2_00 status-only handoff 또는 S2_30 `TO_S2_40` barrier중 정확히 하나의 entry route를 검증한다. +2. upstream barrier가 열거한 exact artifact set, path, schema, producer, raw hash를 다시 검증한다. +3. base→plan→S2_10/S2_30 issue patch를 stable ID 순으로 reduce하고 silent loss·중복 writer를 검사한다. +4. S2_30 raw/canonical draft atom과 S2_20 frozen plan/rule/renderer/calculation/exhibit binding을 교차 검증한다. +5. 청구취지 정형부를 closed AST/template로 조립하고, 청구원인은 typed atom 순서·provenance를 보존하여 deterministic 문서로 조립한다. +6. 소송비용, 가집행, 별지, 외부 호증 label을 exact rule branch와 frozen token에서만 확정한다. +7. V01~V18을 각각 `PASS|FAIL|UNEVALUABLE`로 평가하고 finding·impact scope·evidence ref를 기록한다. +8. candidate content를 동결하고 review policy에 따라 required receipt type과 deterministic review request ID를 도출한다. +9. 외부 변호사/전문가 receipt의 schema·issuer·role·scope·signature attestation·expiry·candidate digest·disposition을 검증한다. +10. FREEZE·WAIT·RESUME·COMMIT과 `CONTENT_CHANGE_REQUIRED`에 따른 supersession/restart route를 결정적으로 집행한다. +11. final artifact set을 canonical bytes로 쓰고 read-back hash를 검증한 뒤 commit result와 run-status barrier를 순서대로 기록한다. +12. 동일 binding/digest/transition 재실행은 byte-identical idempotent success로, 다른 bytes는 no-overwrite conflict로 처리한다. + +### 1.2 S2_40이 수행하지 않는다 + +- LLM 호출, 법률판단, 새 claim·party·fact·evidence·authority·금액·날짜 생성 +- S2_10 verdict, S2_20 ReliefPlan·case-type/rule/calculation, S2_30 source atom의 의미 수정 +- free-text 청구취지 fallback, fuzzy renderer/rule/corpus 선택, directory scan·glob·basename fallback +- 미확정 slot을 추정값으로 채우기, 호증·별지·가집행·소송비용 문구를 미승인 generic 문구로 생성 +- review receipt를 스스로 작성·서명하거나 전문가 내용판단을 대신하기 +- `CONTENT_CHANGE_REQUIRED`를 같은 candidate bytes의 현장 수정 권한으로 해석하기 +- `READY_FOR_LAWYER_FILING_DECISION`을 자동 제출·법률가 승인·승소 보증으로 표현하기 +- 물리적 atomic rename/fsync, host CAS, 서명 검증능력을 offline test만으로 증명하기 +- old Stage 2 `v.0~v.3` YAML·prompt·loader·asset을 runtime에서 읽기 + +--- + +## 2. 경로·실행·신뢰경계 + +```text +M = Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/ +R = Default_Agent/Stage_2_Clean/ +Q = stage2_control/s2_40_request.json +O = stage2_runs/by-binding// +T = Code Executor 실행별 isolated temporary filesystem +``` + +`O`와 canonical `run_id`는 S2_00의 `run_binding_digest`로부터 파생한다. caller의 `request_id`, `attempt_id`, `candidate_content_digest`는 추적·상태 선택용이며 output root를 바꾸지 못한다. absolute path, `..`, backslash, symlink escape, arbitrary receipt path는 거부한다. + +### 2.1 authoring·배포 자산 계약 + +| logical asset | canonical path | 책임 | +|---|---|---| +| authoring Agent | `M/Stage_2_S2_40.yml` | exactly-one inline `run_code` task의 유일 편집 정본 | +| deployment Agent | `R/agent_scripts/Stage_2_S2_40.yml` | authoring byte-identical projection | +| declarative workflow | `R/workflows/S2_40_final_review_render_and_commit.yml` | normal+status-only entry, C40~C48, IO·state·route·barrier 선언; code 없음 | +| full-code mirror | `R/runtime/s2_40_commit.py/.txt` | inline code byte-identical offline oracle; runtime import 0 | +| pure-core oracle | `R/runtime/c45_document_assembler.py/.txt` | typed atom→document AST/section assembly 시험 | +| pure-core oracle | `R/runtime/rendering/closed_renderer.py/.txt` | closed relief/cost/provisional/annex renderer 시험 | +| pure-core oracle | `R/runtime/validation/invariant_runner.py/.txt` | V01~V18·status aggregation·finding mapping 시험 | +| projection builder | `R/offline_build/build_s2_40_inline_projection.py/.txt` | authoring→deployment/mirror/receipt 투영·check; 사건 runtime 0 | +| schemas | `R/schemas/review_status.schema.json`, `package.schema.json`, `deployment.schema.json` | request/state/review/validation/package/commit/barrier contract | +| reused input schemas | `R/schemas/ingress.schema.json`, `context.schema.json`, `s2_10.schema.json`, `domain_verdict.schema.json`, `relief_plan.schema.json`, `binding_retrieval.schema.json`, `calculation.schema.json`, `draft_atoms.schema.json` | upstream artifact와 V01~V18 검증 root | +| review policy | `R/registry/review/review_policy_registry.yml` | base/tag/runtime trigger→required receipt type closed mapping | +| renderer family | `R/renderers/R01_money_payment.yml` ~ `R06_constitutive_judgment_challenge.yml` | approved template/branch/slot/escaping/provisional rule | +| executor binding | `R/deployment/stage2_code_executor_binding.yml` | S2_40 Agent/code/release/request/localdocs-only egress/timeout/secret binding | +| inline receipt | `R/manifest/s2_40_inline_code_receipt.json` | authoring/deployment/code/mirror/task semantics 결속 | +| parent allowlist | `R/manifest/s2_40_parent_member_paths.json` | S2_40 parent raw closure member와 downstream-of-parent 제외 분리 | +| detached admission | `R/manifest/stage2_deterministic_admission_receipt.json` | S2_00·S2_20·S2_40 전부와 backend capability를 외부 서명 계층에서 결속 | +| per-run outer receipt | `O/control/s2_40_outer_execution_receipt.json` | host CAS·actual Agent/code/binding·outer/inner result·workspace isolation; inline writer 아님 | + +모든 `.py`는 같은 bytes의 `.txt` mirror를 가진다. authoring YAML code를 하위 oracle의 import로 대체하지 않고, offline build가 검증된 core를 full inline code에 완전 전개한다. + +### 2.2 direct MCP Code Executor contract + +```yaml +tasks: + - task_name: Task_S2_40_deterministic_finalizer + mcp: code-executor + tool_name: run_code + parameters: + language: python + requirements: "httpx==0.28.1" + network: agent-network + timeout: 300 + code: |- + #!/usr/bin/env python3 + # 실제 Agent에는 생략 없는 complete static Python을 기입한다. +``` + +Agent YAML은 `SKILL.md`의 Stage/task shape와 `test_code_executor.ipynb`의 MCP 세션 순서를 따른다. JSON-RPC `initialize`→`mcp-session-id` 보존→`notifications/initialized`→`tools/call`을 사용하고 matching response ID, JSON-RPC `error`, MCP `isError`, content cardinality, SSE/JSON terminal response를 strict 검증한다. notebook의 bearer secret는 절대 복사하지 않는다. + +### 2.3 localdocs·egress·secret + +- localdocs endpoint는 `http://mcp-localdocs:8012/mcp`만 허용한다. +- initialize `clientInfo`에 `user_id={{__user_hash__}}`, `workspace_id={{__workspace_hash__}}`를 필수 주입한다. +- raw hash source와 output byte 정본은 `read_binary_doc`, `write_binary_file`로만 처리한다. +- `read_docs`, `list_docs`, `list_folders`, Weaviate, web, arbitrary HTTP는 S2_40 runtime allowlist에서 제외한다. +- backend `egress_profile_id`는 localdocs exact host/port/operation만 허용해야 한다. code 내부 allowlist만으로 egress 차단을 증명하지 않는다. +- credential은 AgentBackend secret injection 또는 사전 등록 MCP config가 소유한다. YAML/code/receipt의 plaintext secret는 release failure다. + +### 2.4 single-flight·single writer + +outer orchestrator는 `(run_binding_digest, stage_id=S2_40, candidate_attempt_id, requested_transition)`에 대한 host atomic CAS/mutex를 획득한 뒤 task를 호출한다. JSON lock file이나 read-then-write만으로 concurrency safety를 주장하지 않는다. S2_40은 final ledger, candidate, review request/packet, validation, final, commit operational receipt와 run status의 single writer다. 외부 reviewer만 review receipt와 lawyer judgment를 쓸 수 있다. + +`control/run_status.json`은 state 전이 시 바이트가 변하는 operational latest-barrier이다. 각 이전 상태는 content-addressed status-event row와 request/CAS/previous-barrier hash로 보존하고, latest barrier 교체는 host CAS와 expected-previous-hash 검증을 필수로 한다. localdocs write 한 번만으로 물리 atomic replacement를 주장하지 않으며, live CEG-07 증거 전에는 운영 admission을 `PENDING`으로 둔다. + +--- + +## 3. runtime request·input allowlist·preflight + +### 3.1 고정 request path와 closed shape + +S2_40은 `Q=stage2_control/s2_40_request.json`만 읽는다. request는 `schemas/deployment.schema.json#/$defs/s2_40_request`의 exact instance이고 additional property를 허용하지 않는다. + +```yaml +schema_version: stage2_s2_40_request.v1 +request_id: nonempty-string +candidate_attempt_id: nonempty-string +run_binding_digest: 64-lower-hex +user_identity_hash: 64-lower-hex +workspace_identity_hash: 64-lower-hex +stage2_run_root_ref: stage2_runs/by-binding/ +entry_route: TO_S2_40 | TO_S2_40_STATUS_ONLY +compile_mode: null | STRUCTURAL_FIXTURE | SUBSET_CANARY | PRODUCTION +requested_transition: FREEZE | RESUME +expected_previous_run_status_sha256: null | 64-lower-hex +expected_candidate_content_digest: null | 64-lower-hex +expected_ingress_status_sha256: 64-lower-hex +expected_s2_10_publish_status_sha256: null | 64-lower-hex +expected_plan_publish_status_sha256: null | 64-lower-hex +expected_s2_30_publish_status_sha256: null | 64-lower-hex +expected_s2_30_artifact_manifest_sha256: null | 64-lower-hex +expected_parent_stage2_release_sha256: 64-lower-hex +expected_s2_40_agent_sha256: 64-lower-hex +expected_s2_40_executor_binding_sha256: 64-lower-hex +expected_s2_40_inline_code_receipt_sha256: 64-lower-hex +host_cas_receipt_ref: stage2_control/host_cas//S2_40//.json +host_cas_receipt_sha256: 64-lower-hex +detached_admission_receipt_ref: Default_Agent/Stage_2_Clean/manifest/stage2_deterministic_admission_receipt.json +detached_admission_receipt_sha256: 64-lower-hex-or-PENDING_SEQUENTIAL_BIND +outer_execution_receipt_target_ref: stage2_runs/by-binding//control/s2_40_outer_execution_receipt.json +review_receipt_refs: [] # RESUME에서만 barrier가 아닌 외부 receipt exact path allowlist +``` + +`TO_S2_40_STATUS_ONLY`는 `requested_transition=FREEZE`, `compile_mode=null`, candidate digest·S2_10/S2_20/S2_30 hash가 null이고 `review_receipt_refs=[]`여야 한다. normal `FREEZE|RESUME`는 non-null `compile_mode`를 요구한다. normal `FREEZE`는 candidate digest가 null이고 모든 upstream barrier·artifact-manifest hash가 필수이며 receipt ref가 비어 있다. `RESUME`는 exact previous run-status hash, expected candidate digest와 barrier가 열거한 review receipt exact path 목록이 필수이며 upstream/dependency hash와 `compile_mode`가 FREEZE snapshot과 동일해야 한다. + +`compile_mode`는 S2_30 publish barrier·artifact manifest·part wrapper와 exact equality여야 하며 candidate, package, commit result, run status까지 그대로 보존한다. `STRUCTURAL_FIXTURE`는 `READY_FOR_LAWYER_FILING_DECISION`과 filing/export를 금지한다. `SUBSET_CANARY`는 signed coverage가 승인한 case-type/sub-rule/renderer 범위 밖의 문서 생성·승격을 금지한다. `PRODUCTION`만 모든 live·법률 gate 충족 시 READY 후보가 될 수 있다. + +### 3.2 normal entry input + +normal entry는 barrier가 exact row로 열거한 다음 family만 읽는다. + +| family | 필수 검증 | +|---|---| +| S2_00 | `ingress_status`, input manifest, case/evidence/object/party-title/slot/cluster/bundle context, base issue ledger의 path/hash/schema/producer | +| S2_10 | global publish status, exact domain verdict/issue/assumption/item/wave receipt set의 completeness와 hash | +| S2_20 | `plan_publish_status`, frozen ReliefPlan, claim groups, binding/rule/corpus/calculation/exhibit/filing/party/option report, group slice/P31/P32의 exact set | +| S2_30 | `s2_30_publish_status`, barrier가 결속한 `artifact_manifest.json`, exact group별 typed draft/issue/worknote/usage wrapper와 item/cohort receipt set, group coverage/read-back, mode/producer provenance | +| release | module/case-type/authority/corpus/parent release, case-type coverage, Agent/binding/inline receipt, review policy, R01~R06 renderer, schema bundle의 exact hash/admission | + +S2_30 group set과 S2_20 frozen group set은 exact equality여야 한다. 각 draft part의 claim option/atomic claim/plan/rule/renderer/source hash echo는 S2_20과 동일해야 한다. S2_30 `part_manifest_core`는 네 physical part wrapper만 exact row로 열거한다. item/cohort receipt는 그 core hash를 참조하고 receipt hash를 manifest core에 역삽입하지 않는다. status-last publish barrier만 manifest core의 exact relative path/raw hash/schema, ordered receipt path/hash와 expected/published group set을 함께 결속한다. 각 wrapper는 `compile_mode`, parent/child release, S2_30 Agent/binding, P00/P30/P31/P32/S30 hash를 보존한다. runtime directory scan이나 “보이는 모든 파일”은 input set이 아니다. + +### 3.3 status-only entry exact five + +S2_00 `TO_S2_40_STATUS_ONLY`는 다음 run artifact 5개만 읽는다. + +1. `ingress/ingress_status.json` +2. `ingress/technical_diagnostic.json` +3. `ingress/stage1_input_manifest.json` +4. `ingress/intake_report.json` +5. `review/issue_ledger.base.json` + +이 경로는 context, S2_10/S2_20/S2_30, renderer, candidate/final content를 읽거나 쓰지 않는다. 단, 자신의 Agent/code/release/admission/request와 exact five input의 integrity는 검증한다. output은 `control/run_status.json` 하나이며 `workflow_phase=DIAGNOSTIC_ONLY`, `artifact_technical_status=NOT_PRODUCED`, `legal_readiness=NOT_ASSESSED`다. + +v5-1의 outer route 계약상 S2_10·S2_20·S2_30 terminal technical failure는 각 stage의 terminal barrier에서 정지하며 S2_40 status-only 입력으로 확장하지 않는다. 이 세 경로를 추가하려면 먼저 strategy/orchestrator/request/schema를 별도로 개정해야 한다. + +### 3.4 preflight 순서 + +1. `{{__user_hash__}}`/`{{__workspace_hash__}}`와 request identity exact equality +2. request duplicate-key/UTF-8/schema/path/resource-limit 검증 +3. host CAS receipt, actual deployment Agent/code/binding, inline receipt의 external admission +4. build-time `EXPECTED_STAGE2_RELEASE_SHA256`와 parent release raw hash 대조 +5. common technical trust로 module manifest·request/run schema·Agent/binding/admission membership 검증 +6. entry route 분기: status-only이면 exact five만 hydrate하고 법률 renderer·corpus·review-policy 승인을 요구하지 않음 +7. normal이면 case-type coverage·renderer·rule·review policy·authority/corpus/law-value/calculator의 path/hash/schema/release membership만 기술 preflight로 검증 +8. normal이면 S2_20/S2_30 barrier→artifact manifest→physical part의 exact set을 hydrate +9. read-A/hash/schema 검증 후 read-B/hash 재검증으로 TOCTOU 감지 +10. 첫 output write 전 `publication_guard.external_trust_verified=true`와 input snapshot digest 확정 + +preflight의 기술적 무결성 실패 전에는 run root에 아무 파일도 쓰지 않는다. 법률자산의 semantic approval·execution eligibility는 preflight 차단조건이 아니라 V06·V12·V13·V18과 READY aggregation에서 평가한다. 미승인 renderer로 clean pleading/final package를 만들지는 않지만 upstream draft·worknote·issue와 affected-scope diagnostic candidate는 보존한다. 외부 technical trust가 확인된 후의 기술 실패만 closed diagnostic/status를 기록할 수 있다. + +--- + +## 4. Agent YAML과 `task_procedure` 정본 + +```yaml +task_procedure: + IN: + nexts: + - Task_S2_40_deterministic_finalizer + wait_until: [] + Task_S2_40_deterministic_finalizer: + nexts: + - OUT + wait_until: + - IN + OUT: + nexts: [] + wait_until: + - Task_S2_40_deterministic_finalizer +``` + +`task_procedure` 내에 C40~C48, FREEZE, WAIT, RESUME, COMMIT을 별도 node로 쓰지 않는다. 그들은 inline Python 내부 state/component이다. status-only도 별도 task가 아니라 같은 task의 closed route branch다. `map_reduce`, wildcard, reduce task, conditional `when`을 두지 않는다. + +### 4.1 single JSON stdout + +inline Python은 library/MCP/debug stdout을 `redirect_stdout` 등으로 격리하고 마지막에 canonical JSON object 하나만 stdout으로 출력한다. + +```json +{ + "schema_version": "stage2_s2_40_execution_receipt.v1", + "ok": true, + "workflow_id": "S2_40", + "entry_route": "TO_S2_40", + "requested_transition": "FREEZE", + "workflow_phase": "COMMITTED", + "run_binding_digest": "", + "candidate_content_digest": "", + "artifact_set_digest": "", + "run_technical_status": "CONSISTENT", + "artifact_technical_status": "CONSISTENT", + "legal_readiness": "READY_FOR_LAWYER_FILING_DECISION", + "route": "PACKAGE_COMMITTED", + "run_status_path": "control/run_status.json", + "run_status_sha256": "", + "error": null +} +``` + +outer MCP success와 inner `ok`/route를 분리하며, `run_status_sha256=null`인 실패를 committed/status-only success로 해석하지 않는다. + +--- + +## 5. inline Python 공통 구현 계약 + +### 5.1 strict parser·canonical bytes + +- JSON duplicate key, trailing garbage, non-finite number, invalid UTF-8를 거부한다. +- 파일별, 전체 input, JSON depth/item/string 크기 상한을 release-bound constant로 둔다. +- Unicode는 NFC, line ending은 LF, JSON은 sorted key·compact separator·final newline으로 canonicalize한다. +- Markdown는 UTF-8/NFC/LF, no BOM, final newline exactly one을 적용하고 renderer가 허용한 escaping만 사용한다. +- hash는 항상 raw bytes SHA-256를 기록한다. 파싱 후 object hash와 원문 hash를 혼동하지 않는다. + +### 5.2 path·producer·schema allowlist + +모든 runtime ref는 `(canonical relative path, raw sha256, schema $id/$defs, producer_id, release/module row)` 5-tuple로 검증한다. run-scoped path는 `O` 아래이고 deployment asset은 `R` 아래여야 한다. barrier/request/manifest가 열거하지 않은 path, additional file, wildcard, symlink, normalized-path collision, Unicode-normalization alias는 거부한다. + +### 5.3 immutable/idempotent write + +1. target이 없으면 canonical bytes를 `write_binary_file` 한 뒤 `read_binary_doc`로 다시 읽어 exact equality를 검증한다. +2. target이 있고 expected bytes와 같으면 idempotent success다. +3. target이 있고 bytes가 다르면 overwrite하지 않고 `IMMUTABLE_OUTPUT_CONFLICT`를 남긴다. +4. `control/run_status.json`만 host-CAS-protected latest barrier로 예외를 가지며, request의 expected previous hash를 먼저 검증한다. +5. timestamp, random UUID, unordered thread completion으로 ID/path/bytes를 만들지 않는다. + +### 5.4 resource·determinism·금지 code + +C40~C48은 일반적으로 순차 실행한다. 독립 검증의 내부 병렬화가 필요하더라도 output은 invariant ID/path stable sort로 reduce하고 thread completion 순서를 저장하지 않는다. `exec`, `eval`, `compile`, dynamic import, workspace Python import, shell, subprocess, network client의 arbitrary URL, filesystem discovery를 금지한다. + +--- + +## 6. 내부 component 계약 + +### 6.1 C40 — immutable part reduce + +C40은 다음을 stable ID/path 순으로 reduce한다. + +- `issue_ledger.base` + `issue_ledger.plan` + S2_10/S2_30 issue patch +- S2_10 assumption part + S2_30 worknote/usage part +- frozen claim option/atomic claim/group disposition +- S2_30 atom·coverage·adverse fact·procedural declaration·counter-performance + +각 input row의 producer·source self-hash·immutable receipt를 검증하고, 같은 ID에 byte-equivalent duplicate만 허용한다. 충돌 row를 last-write-wins로 합치거나 LLM 문장을 사용해 해결하지 않는다. option은 `selected|alternative|excluded|deferred` 중 정확히 하나에 있어야 하고, atomic claim·group·draft coverage와 exact partition을 이룬다. + +C40 output은 `review/issue_ledger.final.json`, `review/assumption_ledger.json`, canonical `attorney_worknotes` core, `llm_usage.jsonl` projection이다. JSONL을 concurrent append하지 않고 immutable usage part를 ID-sort한 완전 projection을 한 번에 쓴다. + +### 6.2 C45 — closed document assembly·independent re-render + +조립 순서는 다음으로 고정한다. + +1. 청구취지 본안 항과 주위·예비·선택 관계 +2. 소송비용 부담 항 +3. eligible performance atom만 참조하는 가집행 항 +4. 당사자관계와 권원 +5. 공통·group별 사실관계 +6. 청구별 요건→사실→증거→항변·재항변 +7. 결론과 별지·호증 reference + +청구취지·비용·가집행·별지 토큰은 renderer row의 immutable literal, typed slot, branch predicate, cardinality, escaping, allowed atom type, exhibit/object resolution만으로 렌더링한다. 청구원인 자유서술은 byte template로 고정하지 않지만 source atom/provenance/section order 밖 문장을 삽입할 수 없다. + +primary assembler는 S2_30 atom에서 document AST를 만들고, independent verifier renderer는 frozen plan·rule·renderer·calculation·exhibit·typed atom으로부터 정형 AST를 별도로 재전개한다. 두 구현은 final relief bytes를 공유하거나 같은 완성 문자열을 input으로 써서는 안 된다. 정형부 canonical bytes가 다르면 V18 `FAIL`이다. + +가집행 허용식은 atomic relief별로 닫힌 함수로 검사한다. + +```text +provisional_execution_eligible = + proprietary_claim + AND performance_atom + AND atomic_branch.provisional_execution_policy == ALLOW + AND approved_authority_ref_is_valid + AND NOT dependent_on_constitutive_judgment + AND renderer_id NOT IN {R03, R05, R06} +``` + +위 식은 모두 충족해야 하는 필요조건이다. renderer ID만으로 허용하지 않고 원자 branch별 승인정책과 현행 authority를 요구한다. 형성판결에 종속하는 사해행위 가액배상이나 공유물분할 가격배상, R04 내부 의사표시·특별 비금전 branch에 기계적으로 가집행을 붙이지 않는다. + +### 6.3 C46 — V01~V18 invariant runner + +| ID | 실행 검증 | +|---|---| +| V01 | ingress allowlist path/hash/schema/producer와 actual bytes exact equality | +| V02 | BO↔LES↔Ledger↔signal↔evidence와 review universe conservation | +| V03 | active domain config, slot crosswalk, namespace owner completeness | +| V04 | defense→opposing fact→rebuttal→evidence, polarity/admission/presentation linkage | +| V05 | cluster dependency/precondition/incompatibility, wave verdict, group relation consistency | +| V06 | atomic claim별 case-type/sub-rule exact one-match, FK/hash, zero/multi issue and READY prohibition | +| V07 | output value가 approved calculator receipt/operand/law-value에서만 유래 | +| V08 | same-recovery duplicate 0, relation/partial-claim disposition consistency | +| V09 | relief party/object/amount/period가 frozen plan/rule contract와 exact match | +| V10 | cost/provisional/numbering/annex/cause order와 closed-template scope | +| V11 | relief↔cause claim/party/amount/interest/counter-performance cross-match | +| V12 | corpus snapshot/hash/locator/approval/injection isolation/slot crosswalk | +| V13 | authority temporal scope/addenda/negative treatment/law-value/specialist receipt dependency | +| V14 | candidate→validation→review→content-addressed status-event→intent→write/read-back→commit result→final `run_status` barrier의 non-cycle; 중간 status-event는 consumer barrier가 아님 | +| V15 | atom-type allowed provenance, unsourced fact/dangling evidence 0 | +| V16 | option selected/alternative/excluded/deferred exact partition | +| V17 | party set/title/liability/object/exhibit token completeness | +| V18 | closed AST/template, independent re-render, frozen plan/calculator receipt equality | + +각 result는 `invariant_id`, `evaluation_status`, `finding_ids`, `impact_scope`, `source_refs`, `expected`, `observed`, `reason_codes`, `validator_algorithm_id`를 가진다. `UNEVALUABLE`은 평가값이지 기술상태가 아니다. READY 필수 축의 `UNEVALUABLE`은 scope를 최소 `REVIEW_REQUIRED`로 올리지만 일관된 draft가 가능하면 `INCOMPLETE`로 자동 올리지 않는다. + +scope aggregation은 닫힌 함수다. + +```text +any scope=INCOMPLETE + -> run_technical_status=TECHNICAL_INCOMPLETE +else any scope=REVIEW_REQUIRED or mandatory evaluation=UNEVALUABLE + -> run_technical_status=TECHNICAL_REVIEW_REQUIRED +else + -> run_technical_status=CONSISTENT +``` + +run incomplete면 clean pleading/final sealed package의 `artifact_technical_status=NOT_PRODUCED`, `legal_readiness=NOT_ASSESSED`다. 다만 정상 group의 draft/worknote/issue와 affected-scope diagnostic은 candidate diagnostic 영역에 보존한다. 일관된 artifact가 있지만 review가 남으면 `TECHNICAL_REVIEW_REQUIRED` / `LAWYER_REVIEW_REQUIRED`다. run/artifact consistent, `compile_mode=PRODUCTION`, V01~V18 PASS, binding/authority/required receipt뿐 아니라 selected renderer branch, rule/sub-rule, review policy, 137-row case-type coverage, corpus, law-value, calculator가 모두 execution-eligible이고 대한민국 변호사 승인 상태인 경우만 `READY_FOR_LAWYER_FILING_DECISION`다. candidate-level review receipt는 release-level 미승인 법률자산을 치유하거나 승인 상태로 바꿀 수 없다. + +### 6.4 C47 — candidate digest·review·state + +#### 6.4.1 non-cyclic candidate material + +candidate content digest material은 다음 ordered tuple이다. + +```text +domain separator = STAGE2_S2_40_CANDIDATE_CONTENT_V1 +run binding digest +parent release + upstream barrier hashes +candidate manifest core hash +claim_relief / claim_cause / pleading_draft raw hashes +attorney_worknotes core hash +issue_ledger.final / assumption_ledger hashes +V01~V18 validation-core hash +ordered source/dependency snapshot digest +``` + +`candidate_package_manifest` core는 자신의 hash나 candidate digest를 포함하지 않는다. `candidate_content_digest.json`은 위 material의 digest를 담지만 digest material에 자신을 다시 넣지 않는다. review request/receipt, lawyer packet, validation envelope, package, commit intent/result, run status는 candidate material에서 제외하되 각각 candidate digest를 역참조한다. + +candidate checkpoint는 다음 digest-qualified root에 immutable로 쓴다. + +```text +O/candidates/by-content-digest// +``` + +소비자는 `control/run_status.json` 없이 candidate root를 final package로 읽을 수 없다. + +#### 6.4.2 review policy·external receipt + +`review_policy_base`, active `review_tags[]`, runtime triggers를 release-bound registry로 reduce하여 `required_receipt_types[]`를 만든다. missing/unapproved policy는 permission을 상향하지 못하며 closed issue를 남긴다. + +먼저 `review_subject_digest`와 `request_id`를 포함하지 않는 `review_request_core`를 만든다. core에는 candidate digest, receipt type, scope/finding, policy version/hash, reviewer role/qualification, release snapshot을 넣고 canonical hash를 계산한다. 이 core hash를 아래 subject preimage에 넣은 뒤 `review_subject_digest`를 계산하고, `request_id = H(domain + review_subject_digest + receipt_type + scope_id)`로 발급한다. 마지막 envelope만 `review_request_core`, `review_subject_digest`, `request_id`를 함께 가진다. 따라서 core나 subject가 자신을 hash하는 순환이 없다. + +review packet이 candidate digest material 밖에 있으므로 별도 서명대상을 닫는다. + +```text +review_subject_digest = H( + domain STAGE2_S2_40_REVIEW_SUBJECT_V1 + + candidate_content_digest + + review_request_core_hash # subject/request_id fields excluded + + lawyer_review_packet_core_hash + + validation_envelope_hash + + ordered finding_ids/scope_ids + + review_policy_hash + + parent/authority/corpus/case_type_coverage release hashes +) +``` + +receipt는 candidate digest뿐 아니라 `review_subject_digest`를 서명해야 한다. request/packet/validation/policy/release 중 하나라도 바뀌면 기존 receipt는 유효하지 않다. + +외부 receipt는 최소 다음을 가진다. + +```text +receipt_id, request_id, receipt_type, candidate_content_digest, review_subject_digest, +finding_ids, scope, reviewer_role, reviewer_qualification, +issuer_id, key_id, signature_algorithm, signed_material_digest, +issued_at, expires_at, revocation_status, +review_disposition = APPROVE_AS_IS | CONTENT_CHANGE_REQUIRED, +change_scope, reason_codes +``` + +S2_40 inline code는 schema, exact request/digest/scope, issuer/key allowlist, expiry/revocation, signed-material digest와 AgentBackend가 발급한 external cryptographic-verification attestation을 검증한다. workspace 내 자기서명 JSON 하나만으로 trust를 증명하지 않는다. 실제 서명 검증 capability가 미구현이면 external review 승격은 `PENDING_PLATFORM_ADMISSION`이다. + +#### 6.4.3 state transition + +| operation | precondition | result | +|---|---|---| +| `FREEZE` | normal upstream closure 완전 | candidate·validation·packet·request를 동결 | +| `WAIT` | required receipt 중 미도착/무효 존재 | `AWAITING_EXTERNAL_REVIEW`, checkpoint barrier last | +| `RESUME_VALIDATE` | same candidate/dependency/status hash | external receipt만 신규 검증; candidate 재렌더 0 | +| `READY_TO_COMMIT` | receipt 불필요 또는 모두 `APPROVE_AS_IS` | C48 진입 | +| `SUPERSEDED` | 하나라도 `CONTENT_CHANGE_REQUIRED` | old candidate immutable 보존, 새 attempt route | + +change scope에 따른 earliest-owner route는 closed mapping으로 둔다. + +| change scope | route | +|---|---| +| Stage 1/context 정정 | `RESTART_FROM_S2_00` | +| legal judgment/claim option 정정 | `RESTART_FROM_S2_10` | +| plan/rule/calculation/binding 정정 | `RESTART_FROM_S2_20` | +| drafting text/atom 정정 | `RESTART_FROM_S2_30` | + +새 attempt는 `supersedes_candidate_digest`를 가지며 같은 candidate를 수정하지 않는다. + +### 6.5 C48 — logical commit·barrier-last + +C48은 다음 순서를 지킨다. + +1. candidate/dependency/review/validation snapshot을 다시 검증 +2. `commit/commit_intent.json` 기록·read-back +3. exact final artifact bytes를 쓰고 각 path read-back/hash 검증 +4. ordered `(path, raw sha256, schema/content type, size)` 행으로 `artifact_set_digest` 계산 +5. `commit/stage2_commit_result.json` 기록·read-back +6. `control/run_status.json` COMMITTED barrier를 마지막에 기록·read-back + +`control/run_status.json`은 WAIT, SUPERSEDED, DIAGNOSTIC_ONLY 또는 COMMITTED로 invocation이 종료될 때 해당 invocation의 마지막 write다. commit 진행 중간에는 content-addressed `control/status_events/.json`만 쓸 수 있고 이를 latest consumer barrier로 해석하지 않는다. + +final `stage2_package.json`은 candidate digest, validation/review receipt hash, exact artifact row, legal/technical axes를 참조하지만 `artifact_set_digest`, commit result 또는 run-status hash를 포함하지 않는다. 그런 후 artifact-set digest→commit result→run status 순으로 결속하여 자기참조를 피한다. + +부분 write 후 중단된 경우 재실행은 commit intent의 expected row와 실제 bytes를 대조하여 missing target만 보충한다. conflicting target는 덮어쓰지 않는다. commit result가 있어도 final barrier가 없거나 hash가 다르면 downstream은 소비하지 않는다. + +--- + +## 7. output IO·physical tree + +### 7.1 normal candidate/checkpoint + +```text +O/ +├── review/ +│ ├── issue_ledger.final.json +│ ├── assumption_ledger.json +│ ├── llm_usage.jsonl +│ ├── review_requests/.json +│ ├── review_receipts/.json # external writer +│ └── lawyer_judgment_record.json # external writer/validated ref +├── candidates/by-content-digest// +│ ├── candidate_package_manifest.json +│ ├── candidate_content_digest.json +│ ├── claim_relief.md +│ ├── claim_cause.md +│ ├── pleading_draft.md +│ ├── attorney_worknotes.json +│ ├── lawyer_review_packet.json +│ └── stage2_final_validation_report.json +├── commit/ +│ ├── commit_intent.json +│ └── stage2_commit_result.json +└── control/ + ├── status_events/.json + └── run_status.json +``` + +candidate path의 `lawyer_review_packet` 및 validation envelope는 candidate digest를 역참조하므로 candidate digest material에서 제외한다. candidate manifest core·document·worknote core·ledger·validation core의 hash는 candidate digest material에 포함한다. + +### 7.2 committed final set + +```text +O/final/ +├── candidate_package_manifest.json +├── candidate_content_digest.json +├── claim_relief.md +├── claim_cause.md +├── pleading_draft.md +├── attorney_worknotes.json +├── lawyer_review_packet.json +├── stage2_final_validation_report.json +└── stage2_package.json +``` + +`final/` target은 exact path/hash row로 content-addressed된 immutable set이다. final path에 중복 content 복사를 쓰더라도 candidate bytes와 byte-identical해야 한다. `stage2_package.json`은 sealed package envelope이고 actual filing 결정서나 승소 보증이 아니다. + +### 7.3 run-status closed route + +| workflow phase | route | downstream meaning | +|---|---|---| +| `DIAGNOSTIC_ONLY` | `STOP_TECHNICAL_INCOMPLETE` | pleading/package 없음 | +| `CANDIDATE_FROZEN` | `CHECKPOINT_FROZEN` | candidate 소비 금지 | +| `AWAITING_EXTERNAL_REVIEW` | `WAIT_EXTERNAL_REVIEW` | exact candidate receipt 대기 | +| `READY_TO_COMMIT` | `CONTINUE_TO_COMMIT` | 동일 invocation에서 즉시 C48 진입; 종료 barrier로 사용 금지 | +| `SUPERSEDED` | `RESTART_FROM_S2_00|S2_10|S2_20|S2_30` | old candidate 불변, 새 attempt 필요 | +| `COMMITTED` | `PACKAGE_COMMITTED` | byte-level package 소비만 허가; filing/export 권한은 별도 | + +`CANDIDATE_FROZEN`과 `READY_TO_COMMIT`은 내부 transition이며 일반적으로 독립 terminal invocation으로 남기지 않는다. receipt wait가 필요한 경우만 `AWAITING_EXTERNAL_REVIEW`로 종료한다. + +법원 제출·대외 export 권한은 `workflow_phase=COMMITTED ∧ legal_readiness=READY_FOR_LAWYER_FILING_DECISION ∧ 별도 대한민국 변호사 filing_decision_receipt=APPROVE_FOR_FILING`을 모두 요구한다. `LAWYER_REVIEW_REQUIRED` 상태의 committed package는 review·보존용일 뿐 제출 권한이 없다. + +filing decision의 exact path는 `O/review/filing_decisions/.json`, schema는 `review_status.schema.json#/$defs/filing_decision_receipt`다. manifest가 지정한 대한민국 변호사만 작성하며 S2_40은 생성·수정하지 않는다. 서명 preimage는 candidate digest, final package raw hash, artifact-set digest, committed run-status raw hash, filing scope, reviewer identity/qualification, issued/expiry/revocation을 포함한다. 후속 filing/export validator가 schema·issuer/key·signature attestation·scope·hash·expiry를 검증한 뒤에만 제출권한을 발급한다. + +--- + +## 8. schema 계약 + +| schema | S2_40 필수 `$defs` | +|---|---| +| `schemas/review_status.schema.json` | evaluation result, final issue/assumption ledger, review policy result, request/receipt/judgment, filing-decision receipt, status event, run status | +| `schemas/package.schema.json` | candidate manifest core, candidate digest envelope, rendered documents metadata, worknotes, review packet, validation core/envelope, stage2 package | +| `schemas/deployment.schema.json` | S2_40 request, execution/outer receipt, code binding/inline receipt, commit intent/result, host CAS echo | +| `schemas/draft_atoms.schema.json` | canonical atom, coverage, adverse fact, procedural declaration, counter-performance, persisted draft/issue/worknote/usage wrapper, artifact manifest, item/cohort receipt, publish barrier의 mode/provenance | +| `schemas/relief_plan.schema.json` | frozen plan/group/binding and plan barrier | +| `schemas/binding_retrieval.schema.json` | case-type/sub-rule/rule/corpus/renderer binding | +| `schemas/calculation.schema.json` | calculation/law-value/filing metrics receipt | +| `schemas/ingress.schema.json` | normal ingress barrier and exact status-only handoff | + +모든 physical output은 named `$id/$defs` root, `schema_version`, producer, run binding, source/dependency hash, self-hash 규칙을 가진다. schema validation과 V01~V18 semantic validation을 같은 PASS 값으로 합치지 않는다. + +--- + +## 9. release·hash·admission 계약 + +### 9.1 projection + +`build_s2_40_inline_projection.py` 소원은 다음이다. + +1. duplicate-key rejecting parser로 authoring YAML을 읽는다. +2. exactly-one Stage/task/`run_code`, exact `task_procedure`·parameters·endpoint를 검증한다. +3. parser가 반환한 `parameters.code` string을 dedent/개행 변환 없이 UTF-8 encode한다. +4. deployment Agent와 full `.py/.txt` mirror를 투영한다. +5. compile/AST, prohibited import/call, localdocs-only endpoint, plaintext credential, task semantics를 검사한다. +6. authoring/deployment/code/mirror hash와 build algorithm을 `s2_40_inline_code_receipt.json`에 기록한다. + +### 9.2 non-cyclic reseal 순서 + +1. S2_30 persisted part wrapper·artifact manifest·publish-barrier mode/provenance 계약과 그 validator/fixture/test를 제한 개정한다. +2. workflow/schema/renderer/review policy/runtime oracle/fixture/test를 확정한다. +3. release builder가 allowlist provenance에서 stage별 owner를 계산하도록 고쳐 기존 S2_30 row의 S2_20 오기재를 교정하고, S2_40 detached Agent/full mirror/receipt/binding을 forbidden-parent set에 추가한다. +4. `module_manifest.json`과 S2_40 parent-member allowlist를 갱신한다. +5. parent `stage2_release.json` raw closure를 확정한다. +6. build-time parent raw hash를 S2_00/S2_20/S2_40 inline constant에 결속하고 세 Agent/projection/mirror/inline receipt를 재생성한다. +7. S2_10·S2_30 child release, binding, projection/platform/model/legal receipt를 새 parent로 재봉인한다. +8. shared executor binding에 S2_40 stage row를 추가하고 S2_00·S2_20 row를 보존한다. +9. detached deterministic admission이 S2_00·S2_20·S2_40 Agent/code receipt와 backend capability를 외부 신뢰 계층에서 결속하도록 갱신한다. + +parent release가 parent hash를 내장한 Agent/binding hash를 다시 raw dependency로 포함하는 자기참조를 금지한다. Agent/code/binding/admission은 detached external trust layer에서 결속한다. + +### 9.3 admission boundary + +offline YAML parse, code compile, fixture, mirror parity, hash closure가 PASS해도 상태는 `IMPLEMENTED_OFFLINE_VERIFIED`일 뿐이다. 다음 증거 전에 `LIVE_CANARY_ADMITTED` 또는 `PRODUCTION_READY`로 표현하지 않는다. + +- actual Code Executor outer/inner receipt와 pinned runtime image/request-size/300초 +- user/workspace isolation, binary byte preservation, localdocs-only egress +- host CAS/latest-barrier transition, partial-write resume, same-binding concurrency +- AgentBackend external receipt cryptographic validation capability +- approved R01~R06 branch, 137 rule Markdown/projection, authority/law-value/corpus +- Stage 1→S2_40 normal/status-only live E2E와 대표적 review resume +- 자격 있는 대한민국 변호사의 semantic review·filing-decision workflow + +--- + +## 10. fixture·test·acceptance 계약 + +### 10.1 필수 fixture family + +1. status-only exact-five success, additional input/read mutation +2. normal single-group clean candidate→no-receipt immediate commit +3. multi-group primary/alternative/accessory rendering and stable numbering +4. review-required legal/evidence gap의 draft/worknote preservation +5. V01~V18 각 PASS/FAIL/UNEVALUABLE 지배 mutation +6. case-type/sub-rule/renderer zero·multi·stale hash·free-text fallback mutation +7. cost/provisional/annex/exhibit/object/party dangling token mutation +8. relief↔cause amount/interest/party/counter-performance mismatch +9. corpus/authority/law-value/calculation/provenance drift +10. option silent loss·duplicate recovery·issue-ledger collision +11. candidate digest determinism, manifest self-cycle and digest-tamper mutation +12. mandatory receipt absent→WAIT, valid APPROVE_AS_IS→RESUME→COMMIT +13. wrong candidate/scope/issuer/role/signature-attestation/expiry/revocation receipt mutation +14. CONTENT_CHANGE_REQUIRED→SUPERSEDED→earliest-owner route +15. partial final write, commit intent only, commit result only, early barrier mutation +16. same binding idempotence, conflicting bytes no-overwrite, concurrent transition +17. old Stage 2 v.0~v.3 path/external `.py`/directory scan/secret injection mutation +18. ACTIO route/recipient/two periods/3-cap/provisional-execution dependency fixture +19. 유류분·강제 사죄광고·동시이행·CE-01/13·대부계약 temporal fixture +20. 137 case-type row/sub-rule branch/renderer/corpus coverage fixture + +당사자·금액·날짜는 fixture 외부 payload와 source locator/hash를 가지며 general Python/renderer에 hardcode하지 않는다. `tests/fixtures/s2_40/regression_manifest.json`이 `fixture_case_id→payload/mutation path→expected V/finding/route→oracle hash`를 결속한다. + +승인 전 renderer/rule을 사용한 golden payload는 별도 `tests/fixtures/s2_40/test_release/`에 두고 `fixture_only:true`, `production_admissible:false`, `compile_mode:STRUCTURAL_FIXTURE`를 필수화한다. 이 fixture의 commit은 test namespace의 논리 commit일 뿐 실제 R01~R06·137종 coverage·법률승인의 증거가 아니다. + +### 10.2 최소 test physical family + +```text +tests/s2_40/test_agent_and_inline_parity.py/.txt +tests/s2_40/test_c40_reduce_and_conservation.py/.txt +tests/s2_40/test_c45_closed_render.py/.txt +tests/s2_40/test_v01_v18.py/.txt +tests/s2_40/test_review_state_machine.py/.txt +tests/s2_40/test_commit_barrier_and_idempotence.py/.txt +tests/s2_40/test_release_closure.py/.txt +``` + +### 10.3 acceptance gates + +| gate | 통과조건 | +|---|---| +| G40-00 Agent shape | 1 Stage, 1 `run_code`, 0 LLM/map/wildcard/reduce, exact `task_procedure` | +| G40-01 Code parity | authoring/deployment/full mirror byte equality, compile/AST, prohibited call 0 | +| G40-02 Input closure | normal/status-only exact barrier/set/path/schema/producer/hash/release closure | +| G40-03 C40 conservation | issue/option/group/atom/assumption/worknote/usage silent loss 0 | +| G40-04 Closed render | exact branch/slot/cardinality/escaping, independent re-render byte equality | +| G40-05 V01~V18 | 18/18 result·finding·scope, mutation oracle, READY loophole 0 | +| G40-06 Review state | deterministic candidate/request, receipt validation, wait/resume/supersede/restart closure | +| G40-07 Commit | intent→write/read-back→result→barrier-last, partial/idempotence/conflict property | +| G40-08 Non-cycle | candidate/package/artifact-set/commit/status hash graph cycle 0 | +| G40-09 Release | module/parent/children/three deterministic Agents/binding/admission closure, v0~v3 edge 0 | +| G40-10 Live admission | actual Code Executor/CAS/egress/receipt-crypto/E2E/legal evidence PASS | + +G40-00~09 offline PASS는 G40-10 또는 법률가 filing decision을 대체하지 않는다. + +--- + +## 11. 단계별 생성 작업 + +### Phase S40-0 — contract lock + +1. normal/status-only request·entry route·input allowlist를 고정 +2. `C40→C45→C46→C47→C48` internal DAG와 exactly-one task를 고정 +3. candidate digest material·review policy·receipt·state transition·restart route를 고정 +4. V01~V18 result/impact/status aggregation을 고정 +5. final artifact set, write order, run-status latest barrier/CAS, non-cycle graph를 고정 +6. release reseal graph와 external trust/admission boundary를 고정 + +Exit: 미확인 platform/legal capability는 OPEN+owner+evidence로 남기고 임의 trust primitive를 창작하지 않는다. + +### Phase S40-1 — schema·fixture first + +1. S2_30 `draft_atoms.schema.json`에 persisted part wrapper·artifact manifest·publish-barrier mode/provenance `$defs`를 추가하고 workflow/validator/fixture/test를 개정 +2. review/package/deployment schema의 S2_40 `$defs` 작성 +3. normal/status-only, candidate/wait/resume/supersede/commit golden shape 작성 +4. V01~V18·renderer·receipt·partial-write mutation을 작성 +5. candidate/package/commit/status non-cycle oracle와 regression manifest 작성 + +Exit: runtime code 없이도 모든 input/output/state/route를 기계적으로 판정할 수 있다. + +### Phase S40-2 — pure core·inline runtime + +1. strict localdocs MCP binary adapter, release/request preflight, TOCTOU snapshot +2. C40 reducer·conservation +3. C45 assembler·closed renderer·independent re-render +4. C46 V01~V18·status aggregation +5. C47 candidate digest·review policy·receipt·state machine +6. C48 commit intent·write/read-back·artifact set·result·barrier +7. status-only exact-five branch +8. one-JSON stdout·idempotent retry·conflict handling + +Exit: pure-core/property/mutation tests PASS, LLM/Weaviate/web/shell/external `.py` import 0. + +### Phase S40-3 — Agent·projection·release reseal + +1. authoring `Stage_2_S2_40.yml`에 complete static code와 exact `task_procedure` 기입 +2. deployment Agent/full mirror/builder/inline receipt/parent allowlist 생성 +3. workflow stub을 normal+status-only full declarative contract로 대체 +4. shared executor binding에 S2_40 row 추가 +5. module→parent→S2_00/S2_20/S2_40→S2_10/S2_30 children→detached admission 순으로 reseal +6. old Stage 2/external code/secret/fuzzy fallback/hash cycle scanner 실행 + +Exit: builders `--check`, full regression, release validator, parity/non-cycle closure PASS. + +### Phase S40-4 — live canary·review resume + +1. actual Code Executor outer/inner receipt, runtime image/request size/300초 +2. workspace cross-isolation·binary byte preservation·localdocs-only egress +3. host CAS, same-binding concurrency, latest-barrier transition, partial retry +4. status-only live route와 normal S2_30→S2_40 route +5. trusted external receipt 서명 검증·WAIT→RESUME→COMMIT +6. subset-approved renderer/rule/authority/corpus/legal review + +Exit: signed canary admission. subset canary를 full-137 production으로 표현하지 않는다. + +--- + +## 12. Definition of Done + +### 12.1 `IMPLEMENTED_OFFLINE_VERIFIED` + +- [ ] authoring Agent에 complete static inline Python task가 정확히 1개다. +- [ ] exact `IN→Task_S2_40_deterministic_finalizer→OUT` task procedure다. +- [ ] C40→C45→C46→C47→C48와 status-only branch가 workflow/code/test에 동일하다. +- [ ] authoring/deployment/code/full `.py/.txt` mirror가 byte-identical하고 compile/AST PASS다. +- [ ] LLM, shell/subprocess, dynamic code/import, arbitrary network, v0~v3 dependency가 0이다. +- [ ] normal/status-only input allowlist·barrier·producer/hash/schema/release closure가 PASS다. +- [ ] S2_30 barrier→artifact manifest→physical wrapper의 exact set·mode·producer provenance가 scan 없이 PASS다. +- [ ] C40 issue/option/group/atom/review conservation과 single-writer가 PASS다. +- [ ] closed renderer의 branch/slot/cardinality/escaping과 independent re-render equality가 PASS다. +- [ ] V01~V18 모두가 result/finding/scope를 가지고 READY loophole가 0이다. +- [ ] candidate digest·review request·receipt·state·supersession이 deterministic하다. +- [ ] partial write/idempotence/conflict·commit result·barrier-last property가 PASS다. +- [ ] candidate→package→artifact set→commit→status hash graph에 cycle이 0이다. +- [ ] parent/children/S2_00/S2_20/S2_40/binding/detached admission 오프라인 closure가 PASS다. +- [ ] module manifest의 S2_30 row가 S2_30 owner/scope/version으로 기록되고 S2_40 detached asset은 parent closure에서 제외된다. +- [ ] live/platform/legal evidence가 없다는 상태를 명시한다. + +### 12.2 `LIVE_CANARY_ADMITTED` + +- [ ] actual `run_code` outer success + inner receipt PASS +- [ ] runtime image/httpx/timeout/request-size·workspace·binary byte I/O PASS +- [ ] localdocs-only egress, secret injection, host CAS/latest barrier PASS +- [ ] partial write/resume/concurrent same binding PASS +- [ ] external receipt cryptographic attestation·expiry/revocation·scope PASS +- [ ] status-only와 normal/review-resume route E2E PASS +- [ ] canary 범위 renderer/rule/authority/corpus·대한민국 변호사 review evidence 존재 + +### 12.3 `PRODUCTION_READY` + +- signed parent/children/detached admission trust chain +- S2_00·S2_20·S2_40 3 deterministic Agent live admission +- S2_10·S2_30 platform/model/native-adapter live admission +- release scope authority/law-value/rule/renderer/corpus/calculator semantic review +- `FULL_137_PRODUCTION_READY` 8개 조건 +- representative Stage 1→S2_40 normal/status-only/review resume E2E +- security·latency·cost·rollback·tamper gate +- 자격 있는 대한민국 변호사의 complete-record filing decision workflow admission + +--- + +## 13. 금지규칙 + +1. S2_40 Agent에 두 번째 task, LLM, wildcard, map/reduce를 추가하지 않는다. +2. C40~C48을 AgentBackend top-level task로 분할하지 않는다. +3. authoring YAML code를 placeholder·요약·외부 `.py` import로 대체하지 않는다. +4. S2_40이 upstream legal/factual/plan content를 보정·생성하지 않는다. +5. closed renderer zero/multi/missing slot을 free-text generic fallback으로 덮지 않는다. +6. 미확정 금액·이율·날짜·당사자·목적물을 clean pleading의 확정값으로 작성하지 않는다. +7. 형성판결 종속 atom·R03/R05/R06에 가집행을 기계적으로 붙이지 않는다. +8. review·adverse fact·excluded/deferred option·missing evidence를 silent drop하지 않는다. +9. 외부 receipt를 자기 작성·자기 서명·boolean 플래그만으로 승인하지 않는다. +10. `CONTENT_CHANGE_REQUIRED`일 때 기존 candidate를 overwrite하지 않는다. +11. candidate digest에 자신, review receipt, package, commit result, run status를 넣어 hash cycle을 만들지 않는다. +12. commit result 또는 run status hash를 `stage2_package.json`에 넣어 artifact-set self-cycle을 만들지 않는다. +13. status barrier를 non-barrier artifact/read-back/commit result보다 먼저 쓰지 않는다. +14. same-binding conflicting target을 overwrite하지 않는다. +15. status-only entry에서 exact five 이외의 run artifact를 읽거나 pleading을 생성하지 않는다. +16. directory scan·glob·basename·fuzzy path로 dependency를 찾지 않는다. +17. notebook secret, arbitrary endpoint, plaintext credential을 YAML/code/receipt에 기록하지 않는다. +18. old Stage 2 `v.0~v.3` YAML·prompt·loader·asset을 runtime dependency로 사용하지 않는다. +19. offline fixture/hash PASS를 live/production/변호사 검수 완료로 표현하지 않는다. +20. `READY_FOR_LAWYER_FILING_DECISION`을 자동 제출 권한이나 법률적 무결함 보증으로 해석하지 않는다. + +--- + +## 14. 잔여 OPEN·위험 + +| OPEN | owner | 필요 evidence | 영향 | +|---|---|---|---| +| S40-O01 host CAS/latest-barrier primitive | AgentBackend owner | actual handler/version/digest/concurrency/transition receipt | live blocker | +| S40-O02 external receipt crypto validation | AgentBackend/release owner | trusted key registry, verify algorithm, expiry/revocation live receipt | review-resume production blocker | +| S40-O03 Code Executor live admission | AgentBackend/Code Executor owner | secret/image/timeout/request-size/outer-inner receipt | live blocker | +| S40-O04 R01~R06 approved renderer branch | 대한민국 변호사/release owner | template/slot/branch/provisional/legal sign-off | clean render/full coverage blocker | +| S40-O05 review policy approval | 대한민국 변호사 | base/tag/trigger→receipt mapping과 fixture sign-off | READY/review route blocker | +| S40-O06 137 rule/corpus/authority release | legal/corpus/release owners | full coverage·hash·semantic review | full-137 blocker | +| S40-O07 existing exhibit label handoff | Stage 1/S2_00 owner | existing label/source/conflict contract | existing-label E2E blocker | +| S40-O08 typed calculation operands/law values | Stage 1/S2_20/calculation owner | operand/value/unit/effective date/authority receipt | value-ready E2E blocker | +| S40-O09 complete S2_30 native publish adapter | AgentBackend/S2_30 owner | canonical group parts/barrier/retry live receipt | normal S2_40 E2E blocker | +| S40-O10 final downstream consumer barrier check | filing workflow owner | `run_status` exact schema/hash/COMMITTED enforcement test | package consumption blocker | + +현행 renderer/review policy는 `PENDING_LEGAL_CONTENT`, S2_40 workflow는 status-only `STUB_NOT_EXECUTABLE`이다. 이를 숨기기 위해 빈 branch, generic relief, unsigned receipt를 승인하지 않는다. 구조 fixture·mock으로 offline 구현은 가능하지만 production data와 분리한다. + +--- + +## 15. 최종 판정 + +본 SOW는 S2_40을 **정확히 1개의 release-bound inline MCP `run_code` task**로 구현하기 위한 self-contained 명세다. AgentBackend `task_procedure`는 `IN→Task_S2_40_deterministic_finalizer→OUT`만 표현하고, 정상 경로의 `C40→C45→C46→C47→C48`과 S2_00 status-only 분기는 inline Python 내부에서 실행한다. + +candidate digest→validation/review→package→artifact-set digest→commit result→run-status barrier를 비순환으로 결속하고, `FREEZE→WAIT→RESUME→COMMIT`을 같은 candidate bytes에 대한 idempotent state machine으로 닫는다. 법률 불확실성은 review package로 보존하되 허위 clean pleading이나 READY로 승격하지 않는다. + +이 문서를 작성한 시점에 S2_40 full Agent/inline runtime/assets/test/reseal/live admission은 완료되지 않았다. 후속 구현은 먼저 offline `IMPLEMENTED_OFFLINE_VERIFIED`를 입증하고, 실제 Code Executor·CAS·external receipt crypto·approved renderer/rule/corpus/authority·대한민국 변호사 filing workflow에 대한 별도 evidence가 있을 때만 live/production 상태를 상향한다. diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/S2_40_assets.md b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/S2_40_assets.md new file mode 100644 index 00000000..84eaa67d --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/S2_40_assets.md @@ -0,0 +1,528 @@ +# S2_40 deterministic final review·render·seal·commit 자산 inventory + +> 기준 전략: `stage_2_optimal_update_strategy_v.5-1.md` §0.5, §3, §4.7–§4.8, §9, §12–§16, §20 +> +> 선행 구현: `S2_20_assets.md`, `S2_30_assets.md` +> +> canonical 배포 root: `R = Default_Agent/Stage_2_Clean/` +> +> authoring root: `M = YAML_Prompts/2. Stage_2/` +> +> 현재 상태: `S2_40_STATUS_ONLY_STUB_HASH_BOUND / FULL_S2_40_NOT_IMPLEMENTED` +> +> 목표 상태: `IMPLEMENTED_OFFLINE_VERIFIED / LIVE_AND_LEGAL_ADMISSION_PENDING` + +--- + +## 0. 판독 기준과 절대 경계 + +```text +P = Case_02_Comparison_Research/ +M = P/YAML_Prompts/2. Stage_2/ +R = M/Default_Agent/Stage_2_Clean/ +O = stage2_runs/by-binding// +Q = stage2_control/s2_40_request.json +``` + +| disposition | 의미 | +|---|---| +| `NEW` | 현재 물리 파일이 없으며 S2_40 구현 시 새로 생성 | +| `UPDATE-RESEAL` | 현재 파일의 소유권은 유지하되 S2_40 계약·hash·dependency를 반영하여 재봉인 | +| `REUSE-BOUND` | 현재 bytes를 변경하지 않고 exact path/schema/hash로 소비 | +| `REUSE-PENDING-LEGAL` | 구조는 재사용하되 법률가 승인 전 production 실행 금지 | +| `RUN-NO-BYTE-CHANGE` | 새 hash chain을 검증하기 위해 helper/test를 실행하되 source bytes는 원칙적으로 변경하지 않음 | +| `EXTERNAL-PENDING` | AgentBackend·release operator·대한민국 변호사 등 외부 owner의 실측·서명·법률 승인이 필요 | +| `RUNTIME-ARTIFACT` | 개별 사건 run에서 생성되는 출력; 고정 배포 자산 수량에서 제외 | + +S2_40은 `NON-LLM-DETERMINISTIC` stage다. `M/Stage_2_S2_40.yml` 내에 `mcp: code-executor`, `tool_name: run_code`인 task를 **정확히 1개**만 둔다. 완전한 static Python은 그 task의 `parameters.code` 내에 있으며, 외부 `.py` import, `exec`, `eval`, 동적 code generation과 런타임 스크립트 생성은 0이다. `runtime/*.py/.txt`는 byte-identical full mirror 또는 pure-core offline oracle일 뿐 사건 runtime dependency가 아니다. + +S2_40의 단독 책은 다음과 같다. + +```text +normal route: +S2_20 plan_publish_status + frozen plan + + S2_30 s2_30_publish_status + immutable group parts + | + v + C40 deterministic part reduce / final ledger + | + v + C45 closed render + independent canonical re-render + | + v + C46 V01–V18 / package conformance + | + v + C47 candidate freeze / optional external-review wait-resume + | + v + C48 content-addressed write / read-back / commit result + | + v + control/run_status.json LAST barrier + +diagnostic/status-only route: +S2_00 exact five diagnostic artifacts + | + v + same one inline task -> control/run_status.json LAST barrier +``` + +S2_10·S2_20·S2_30 terminal technical failure는 각 stage의 terminal barrier에서 정지하며 S2_40 input으로 확장하지 않는다. + +S2_40은 S2_30의 청구취지·청구원인 atom을 법률적으로 다시 작성하거나 새 claim을 추가하지 않는다. S2_30 group-parallel part를 ID-sort로 줄이고, frozen plan·renderer·rule·calculation receipt와 대조한 후에만 문서를 조립하는 final single writer다. + +### 0.1 source-of-truth 순위 + +| 순위 | source of truth | 경계 | +|---:|---|---| +| 1 | `M/Stage_2_S2_40.yml#/Agent/Stages/0/tasks/0/parameters/code` | 실행 code bytes의 유일 편집 정본 | +| 2 | `R/agent_scripts/Stage_2_S2_40.yml` | authoring의 byte-identical version-free 배포 projection | +| 3 | `R/workflows/S2_40_final_review_render_and_commit.yml` | route·IO·C40∼C48·barrier·single-writer의 선언형 계약; code source가 아님 | +| 4 | `R/schemas/*.schema.json`, `R/renderers/*.yml`, `R/registry/review/review_policy_registry.yml` | typed output·closed renderer·review-state data 계약 | +| 5 | S2_20/S2_30 barrier가 열거한 exact runtime artifact path/hash/schema set | 사건별 유일 입력; directory scan·glob·fuzzy fallback 금지 | + +`R/runtime/s2_40_commit.py/.txt`는 1순위 code를 그대로 추출한 parity oracle이다. mirror를 편집하여 authoring YAML을 역생성하지 않는다. + +--- + +## 1. S2_40 전용 유한 구현 inventory + +### 1.1 authoring·projection·workflow·receipt 9개 + +| exact path | 조치 | 작업 성격 | writer / consumer | 역할·검증 | +|---|---|---|---|---| +| `M/Stage_2_S2_40.yml` | `NEW` | `NON-LLM-DETERMINISTIC / INLINE-CODE-EXECUTOR / AUTHORING-SOT` | S2_40 authoring owner / AgentBackend | exactly-one `run_code`, `httpx==0.28.1`, `agent-network`, 300초, 완전한 inline Python, build-time parent release hash, normal route와 S2_00 exact-five status-only route를 포함 | +| `R/agent_scripts/Stage_2_S2_40.yml` | `NEW` | `EXECUTABLE-AGENT-PROJECTION` | projection builder / AgentBackend | authoring과 byte-identical하고 task semantics가 정확히 1개인 version-free 실행본 | +| `R/workflows/S2_40_final_review_render_and_commit.yml` | `UPDATE-RESEAL` | `NON-LLM-DETERMINISTIC / DECLARATIVE-CONTRACT` | workflow owner / builder·validator | 현행 `DETERMINISTIC_STUB_NOT_EXECUTABLE`을 full normal route + S2_00 exact-five status-only route로 교체; Python code는 넣지 않음. S2_10/S2_20/S2_30 terminal technical failure 뒤에는 S2_40을 호출하지 않음 | +| `R/runtime/s2_40_commit.py` | `NEW` | `FULL-INLINE-CODE-MIRROR` | projection builder / offline test | YAML parser가 반환한 entire `parameters.code`의 UTF-8 byte-identical mirror; runtime import 0 | +| `R/runtime/s2_40_commit.txt` | `NEW` | `DOCUMENTATION-MIRROR` | projection builder / 사람 검토·parity test | 위 `.py`와 byte-identical | +| `R/offline_build/build_s2_40_inline_projection.py` | `NEW` | `OFFLINE-BUILD` | release build owner / CI | unique-key YAML parse, exactly-one task, code extraction·compile·AST, authoring→projection·mirror·receipt, `--check` | +| `R/offline_build/build_s2_40_inline_projection.txt` | `NEW` | `OFFLINE-BUILD-MIRROR` | release build owner / parity test | 위 `.py`와 byte-identical | +| `R/manifest/s2_40_inline_code_receipt.json` | `NEW` | `DERIVED-RECEIPT` | projection builder / executor binding·release validator | authoring/projection/code/mirror path·hash·size, compile/AST, task count, parent-release constant를 기록 | +| `R/manifest/s2_40_parent_member_paths.json` | `NEW` | `PARENT-CLOSURE-ALLOWLIST` | release build owner / `build_release_manifests.py` | S2_20·S2_30 allowlist와 disjoint인 S2_40 parent-independent source만 정렬 열거; Agent·full mirror·inline receipt·binding·admission·`stage2_release.json`은 제외하고 allowlist 파일 자체는 기존 convention처럼 열거 | + +### 1.2 inline에 완전 전개할 pure-core offline oracle 6개 + +| exact path pair | 조치 | 작업 성격 | brief 역할 | +|---|---|---|---| +| `R/runtime/c45_document_assembler.py/.txt` | `NEW` | `NON-LLM-DETERMINISTIC / PURE-CORE-ORACLE` | C40의 sorted atom set을 청구취지→비용→가집행→당사자/권원→사실→요건·증거·항변→결론/별지 순으로 deterministic assembly | +| `R/runtime/rendering/closed_renderer.py/.txt` | `NEW` | `NON-LLM-DETERMINISTIC / PURE-CORE-ORACLE` | R01∼R06 closed AST/template, typed slot, branch cardinality, NFC/LF/escaping, independent canonical re-render byte equality | +| `R/runtime/validation/invariant_runner.py/.txt` | `NEW` | `NON-LLM-DETERMINISTIC / PURE-CORE-ORACLE` | V01∼V18, producer ownership, option conservation, party/object/exhibit, law-value/calculation/rule/corpus/package hash를 closed result로 판정 | + +각 pair는 동일 source bytes로 생성한다. 이 파일은 독립 시험 정본이며 S2_40 사건 runtime은 이를 읽거나 import하지 않는다. C40 part reduce, C47 review/seal, C48 logical commit은 외부 helper를 추가하지 않고 full inline code 내의 static function으로 구현한다. + +### 1.3 schema bundle + +| exact path | 조치 | 작업 성격 | S2_40 책 | +|---|---|---|---| +| `R/schemas/package.schema.json` | `NEW` | `NON-LLM-DETERMINISTIC / DATA-CONTRACT` | candidate manifest/digest, claim relief/cause/pleading document descriptor, worknote/review packet, validation report, sealed package의 named `$defs` | +| `R/schemas/migration_regression.schema.json` | `NEW` | `NON-LLM-DETERMINISTIC / TEST-CONTRACT` | S2_40 fixture manifest/result, finding→V-code oracle, mutation·expected-result·source locator를 검증; runtime 법리 source가 아님 | +| `R/schemas/review_status.schema.json` | `UPDATE-RESEAL` | `NON-LLM-DETERMINISTIC / DATA-CONTRACT` | final issue/assumption ledger, V01∼V18 result, review request/receipt, lawyer judgment, candidate state, three status axes, full/status-only `run_status` | +| `R/schemas/deployment.schema.json` | `UPDATE-RESEAL` | `NON-LLM-DETERMINISTIC / DEPLOYMENT-CONTRACT` | `s2_40_request`, outer execution receipt, inline-code receipt, S2_40 `stage_binding`, content-addressed commit intent/result, detached admission row | +| `R/schemas/draft_atoms.schema.json` | `UPDATE-RESEAL / UPSTREAM-HANDOFF-FIX` | `UPSTREAM-INPUT-CONTRACT` | persisted `draft_part`, `issue_patch_part`, `worknote_part`, `usage_part`, `artifact_manifest`, item/cohort receipt 및 publish barrier의 exact path/hash/schema/mode/provenance 계약을 추가하여 S2_40의 무검색 소비를 가능하게 함 | +| `R/schemas/relief_plan.schema.json` | `REUSE-BOUND` | `UPSTREAM-INPUT-CONTRACT` | S2_20 frozen plan·group·barrier·plan ledger exact validation | +| `R/schemas/binding_retrieval.schema.json` | `REUSE-BOUND` | `UPSTREAM-INPUT-CONTRACT` | exact case type/sub-rule/corpus pack·retrieval receipt 대조 | +| `R/schemas/calculation.schema.json` | `REUSE-BOUND` | `UPSTREAM-INPUT-CONTRACT` | calculator operand/law-value/receipt independent check | +| `R/schemas/ingress.schema.json`, `R/schemas/context.schema.json`, `R/schemas/s2_10.schema.json` | `REUSE-BOUND` | `UPSTREAM-LINEAGE-CONTRACT` | V01∼V05·V15·V17의 S2_00/S2_10 lineage를 barrier-bound path로 대조 | + +Schema는 exact `$id`/`$defs` root를 가지고 module manifest에 path/raw hash로 봉인된다. 같은 object를 둘 이상의 schema에 복제하지 말고 `$ref`로 소유권을 고정한다. + +### 1.4 closed renderer·review policy 자산 + +| exact path/family | 조치 | 작업 성격 | 역할·상태 경계 | +|---|---|---|---| +| `R/renderers/R01_money_payment.yml` | `UPDATE-RESEAL / REUSE-PENDING-LEGAL` | `NON-LLM-DETERMINISTIC / CLOSED-RENDERER-DATA` | 금전지급 AST/template·typed slots·이자 period·counter-performance·가집행 branch | +| `R/renderers/R02_delivery_possession.yml` | 동일 | 동일 | 인도·명도·퇴거, 목적물/상환이행/별지 branch | +| `R/renderers/R03_declaration_registry.yml` | 동일 | 동일 | 이전·말소·회복·경정 등기와 실체 귀속/주문상 절차이행 상대방 분리 | +| `R/renderers/R04_special_nonmoney_performance.yml` | 동일 | 동일 | 특별 비금전 이행·의사표시 branch | +| `R/renderers/R05_declaratory.yml` | 동일 | 동일 | 확인의 이익·확인 범위 typed branch | +| `R/renderers/R06_constitutive_judgment_challenge.yml` | 동일 | 동일 | 형성·불복·공유물분할, 가집행 금지, method preference | +| `R/registry/review/review_policy_registry.yml` | `UPDATE-RESEAL / REUSE-PENDING-LEGAL` | `NON-LLM-DETERMINISTIC / REVIEW-POLICY-DATA` | `STANDARD_ATTORNEY_REVIEW` 또는 `MANDATORY_SPECIALIST_REVIEW`, closed tags, trigger→required receipt, `ready_eligible` 함수; 현행 S2_20 drafting permission 필드는 소거하지 않고 final-review section을 병합 | +| `R/registry/regression/finding_fixture_map.yml` | `UPDATE-RESEAL` | `NON-LLM-DETERMINISTIC / TEST-DATA` | discrepancy/eval finding→V01∼V18→S2_40 fixture expected code를 exact mapping | + +각 renderer row는 `template_id`, immutable literal fragments, typed slot definitions, branch predicates, cardinality, escaping policy, allowed atom types, required exhibit resolution, normalization version을 가져야 한다. 현행 renderer 6개는 `PENDING_LEGAL_CONTENT`, `execution_eligible:false`, `branch_rows:[]`이므로 구조를 보강해도 대한민국 변호사가 literal·predicate·authority를 승인하기 전 production render를 열지 않는다. + +### 1.5 offline test source 14개 + +아래 `.py/.txt` pair는 전부 `NEW`이고 각 pair는 byte-identical이어야 한다. + +| exact path pair | 검증축 | +|---|---| +| `R/tests/s2_40/test_agent_and_inline_parity.py/.txt` | unique YAML key, exactly-one `run_code`, timeout/dependency/network, inline compile/AST, authoring↔projection↔full mirror, v0∼v3 ref 0 | +| `R/tests/s2_40/test_c40_reduce_and_conservation.py/.txt` | S2_20/S2_30 barrier, expected group exact equality, immutable part ID/hash/schema, duplicate/missing/cross-group 거부, S2_00 exact-five status-only | +| `R/tests/s2_40/test_c45_closed_render.py/.txt` | C45 조립 순서, closed slot/branch, independent re-render bytes, 청구취지↔원인 party/amount/interest/counter-performance 일치 | +| `R/tests/s2_40/test_v01_v18.py/.txt` | V01∼V18 each PASS/FAIL/UNEVALUABLE, status 3축 closed aggregation, READY 최소식 | +| `R/tests/s2_40/test_review_state_machine.py/.txt` | required receipt·review subject 파생, digest/scope/role/signature/expiry, `APPROVE_AS_IS`, `CONTENT_CHANGE_REQUIRED`, immutable supersession/resume | +| `R/tests/s2_40/test_commit_barrier_and_idempotence.py/.txt` | candidate non-cycle, content-addressed write/read-back, intent/result/barrier-last, same-binding idempotence, conflict | +| `R/tests/s2_40/test_release_closure.py/.txt` | stage별 module ownership, S2_30 handoff provenance, S2_40 forbidden-parent members, module→parent→detached binding/admission 비순환 closure | + +### 1.6 fixture 16개 + +배포 위치는 `R/tests/fixtures/s2_40/`이다. + +| filename | 단일 oracle | +|---|---| +| `valid_full_candidate_and_commit.json` | 정상 C40→C48, canonical professional-draft artifact set·validation·status/commit closure | +| `valid_status_only_diagnostic.json` | S2_00 exact-five closed input만 소비하여 `NOT_PRODUCED/NOT_ASSESSED` run status를 마지막에 기록; 추가 파일 열람을 거부 | +| `part_set_missing_duplicate_or_cross_group.json` | expected group/part set 누락·중복·다른 group ID·hash drift 거부 | +| `renderer_ast_slot_branch_mutations.json` | zero/multi branch, unknown/unbound slot, escaping/NFC/LF, free-text template injection 거부 | +| `relief_cause_crossmatch_mutations.json` | party·급부·금액·기산일·상환이행 불일치로 V09/V11/V18 실패 | +| `v01_v18_invariant_matrix.json` | V01∼V18 각각의 normal·mutation·expected evaluation/status code | +| `cost_provisional_execution_numbering.json` | 소송비용, atomic relief별 가집행 eligibility, 번호/주위·예비·선택 조립 | +| `exhibit_object_party_title_completeness.json` | 호증·목적물·등기·party/title/liability token completeness와 dangling ref 거부 | +| `review_policy_state_aggregation.json` | base/tag/runtime trigger→required receipt, PASS/FAIL/UNEVALUABLE→3축 state→legal readiness | +| `review_receipt_missing_or_invalid.json` | missing, wrong candidate digest/scope/role, expired/invalid signature를 `LAWYER_REVIEW_REQUIRED`로 보존 | +| `review_receipt_approve_resume.json` | 동일 candidate bytes에 결속된 `APPROVE_AS_IS` receipt만 resume·READY_TO_COMMIT 허용 | +| `review_receipt_content_change_supersede.json` | `CONTENT_CHANGE_REQUIRED`는 in-place edit를 금지하고 새 S2_20 또는 S2_30 attempt로 복귀 | +| `partial_write_readback_barrier.json` | partial write/read-back mismatch에서 early `run_status` 금지·진단 보존 | +| `same_binding_idempotence_and_commit_conflict.json` | 동일 binding+동일 bytes idempotent, 동일 target+다른 bytes overwrite 금지 | +| `candidate_digest_noncycle.json` | candidate manifest→content digest→review→intent→result→final barrier의 비순환 결속 | +| `regression_manifest.json` | 앞 15 payload·7 test pair·source locator·hash·expected V/status/route를 exact 봉인 | + +fixture에 당사자·금액·날짜를 general rule로 hard-code하지 않는다. 사건별 값은 `EXPLICIT|DERIVED`, source locator, operand, calculator receipt와 hash를 가져야 한다. + +승인 전 renderer/rule로 구성한 golden fixture는 `tests/fixtures/s2_40/test_release/` namespace에만 두고 모든 root에 `fixture_only:true`, `production_admissible:false`, `compile_mode:STRUCTURAL_FIXTURE`를 봉인한다. 이 fixture의 PASS는 R01~R06, 137종 coverage 또는 법률자산의 production 승인을 의미하지 않는다. + +### 1.7 전용 신규 물리량 + +| 범주 | `NEW` 물리 파일 수 | +|---|---:| +| authoring·projection·full mirror·builder·receipt·allowlist | 8 | +| pure-core `.py/.txt` | 6 | +| 신규 schema | 2 | +| test `.py/.txt` | 14 | +| fixture | 16 | +| **합계** | **46** | + +`UPDATE-RESEAL`, shared cascade와 runtime artifact는 이 46개에 포함하지 않는다. + +--- + +## 2. S2_40이 exact binding으로 재사용할 고정 상류·공유 자산 + +### 2.1 release·deployment trust anchor + +| exact path | 조치 | S2_40 소비 목적 | +|---|---|---| +| `R/manifest/stage2_release.json` | `UPDATE-RESEAL` | inline build-time constant과 actual parent raw hash의 exact equality; 유일 release oracle | +| `R/manifest/module_manifest.json` | `UPDATE-RESEAL` | workflow/schema/renderer/core/test의 physical path/hash/dependency/status closure | +| `R/deployment/stage2_code_executor_binding.yml` | `UPDATE-RESEAL` | S2_40 stage row, Agent/code/workflow/receipt/schema, localdocs-only egress, 300초, no fallback 결속 | +| `R/manifest/stage2_deterministic_admission_receipt.json` | `UPDATE-RESEAL / EXTERNAL-PENDING` | `present_deterministic_stage_ids=[S2_00,S2_20,S2_40]`과 S2_30 helper를 detached 결속; live signed evidence 전 `PENDING` | +| `R/deployment/stage2_loader_binding.yml` | `REUSE-BOUND` | O-06 superseded reference-only pointer; S2_40 runtime invocation 권한 0 | + +S2_40은 S2_00·S2_20과 같은 deterministic parent-release + detached-executor-admission lane을 사용하므로 별도 `manifest/s2_40_release.json`·model benchmark receipt를 새로 만들지 않는다. live 실행 증거는 shared deterministic admission receipt, 법률 승인은 module/case-type coverage·renderer/rule/review-policy semantic receipt의 소유권으로 유지한다. + +### 2.2 S2_00·S2_10·S2_20·S2_30 producer 자산 + +| exact path/family | 조치 | 사용 경계 | +|---|---|---| +| `R/agent_scripts/Stage_2_S2_00.yml`, `R/manifest/s2_00_inline_code_receipt.json` | `UPDATE-RESEAL` | ingress/status-only producer identity를 새 parent hash로 재결속 | +| `R/agent_scripts/Stage_2_S2_10.yml`, `R/deployment/stage2_s2_10_llm_binding.yml` | `REUSE-BOUND` | S2_10 Agent/prompt/model bytes는 변경하지 않고 S2_20/S2_30 lineage로만 대조 | +| `R/agent_scripts/Stage_2_S2_20.yml`, `R/manifest/s2_20_inline_code_receipt.json` | `UPDATE-RESEAL` | frozen plan·group·renderer/rule/calculation·plan barrier producer identity | +| `R/agent_scripts/Stage_2_S2_30.yml`, `R/deployment/stage2_s2_30_llm_binding.yml`, `R/manifest/s2_30_release.json` | `UPDATE-RESEAL` | group-parallel immutable draft producer, P00/P30/planner/result-adapter identity를 새 parent hash와 결속 | +| `R/manifest/s2_30_inline_prompt_projection_receipt.json`, `R/manifest/s2_30_inline_code_receipt.json` | `UPDATE-RESEAL` | parent hash가 든 authoring Agent bytes의 prompt/code projection parity를 재기록 | +| `R/manifest/s2_30_platform_adapter_receipt.json`, `R/manifest/s2_30_model_benchmark_receipt.json`, `R/manifest/s2_30_legal_review_receipt.json` | `UPDATE-RESEAL / EXTERNAL-PENDING` | 새 parent/child/binding hash를 반영하되 실측·법률 승인 status는 `PENDING` 유지 | + +S2_30→S2_40 인계는 이번 S2_40 구현에 선행하는 제한적 upstream fix다. 다음 물리 파일을 함께 개정한다. + +| exact path pair/family | 조치 | 인계 보강 | +|---|---|---| +| `R/offline_build/validate_s2_30_contract.py/.txt` | `UPDATE-RESEAL` | persisted manifest와 네 part wrapper의 exact membership·self/raw hash·schema·read-back·mode/provenance를 검증 | +| `R/tests/s2_30/test_agent_contract.py/.txt` | `UPDATE-RESEAL` | wrapper schema, manifest path, status-last, 추가/누락/중복 part를 검증 | +| `R/tests/s2_30/test_prompt_cache_and_boundaries.py/.txt` | `UPDATE-RESEAL` | `compile_mode`, parent/child release, Agent/binding, P00/P30/P31/P32/S30 hash의 physical output echo를 검증 | +| `R/tests/fixtures/s2_30/`의 관련 payload·`regression_manifest.json` | `UPDATE-RESEAL` | normal·canary·fixture mode와 manifest/part provenance mutation oracle 추가 | + +`artifact_manifest`는 barrier가 열거하는 유일 part index다. manifest와 item receipt가 서로의 hash를 양방향으로 포함하지 않도록 `part_manifest_core → item/cohort receipts → s2_30_publish_status`의 비순환 순서를 사용한다. publish status는 manifest의 exact path/raw hash/schema와 expected/published group set을 결속하고 마지막에 기록한다. + +### 2.3 renderer·rule·calculation·authority·corpus + +| exact path/family | 조치 | S2_40 사용 | +|---|---|---| +| `R/manifest/case_type_registry.yml`, `R/manifest/case_type_rule_registry.yml` | `REUSE-BOUND` | V06의 `case_type_id::sub_rule_id` exact FK/hash | +| `R/registry/drafting/case_type_relief_rules.yml` | `REUSE-PENDING-LEGAL` | selected branch·required slot·renderer·금지조건 typed validation | +| `R/registry/drafting/forbidden_relief_rules.yml` | `REUSE-PENDING-LEGAL` | 강제 사죄·사과광고 등 forbidden atom 검증 | +| `R/registry/drafting/counter_performance_rules.yml` | `REUSE-PENDING-LEGAL` | 동시이행·상환이행·CE-01 linkage와 relief/cause cross-match | +| `R/registry/drafting/procedural_declaration_rules.yml` | `REUSE-PENDING-LEGAL` | actor 권한·예정 송달 `PLANNED`·도달/효과 상태 | +| `R/registry/calculations/*.yml`, `R/law_values/*.yml` | `REUSE-PENDING-LEGAL` | V07/V09/V11/V13/V18의 exact operand·period·law-value receipt; S2_40 산술 재수행 금지 | +| `R/routing/*.yml`, `R/validators/actio_value_compensation_invariants.yml` | `REUSE-PENDING-LEGAL` | ACTIO route·recipient·두 기간·3-cap·담보 branch 대조 | +| `R/manifest/authority_release.json` | `REUSE-PENDING-LEGAL` | temporal authority·negative treatment·law-value 봉인; runtime web fetch 0 | +| `R/manifest/corpus_release.json` | `REUSE-PENDING-LEGAL` | approved snapshot/chunk/crosswalk/retrieval receipt의 exact hash; live Weaviate 재검색 0 | +| `R/manifest/case_type_coverage.json` | `REUSE-PENDING-LEGAL / UPDATE-RESEAL` | 137 row별 case type→sub-rule→renderer→corpus/profile→CE/SL→review/sign-off의 production eligibility; 승인되지 않은 row는 READY 승격 불가 | +| `R/rules/relief/.md` | `EXTERNAL-PENDING`, 137 family | structured branch의 human-readable 승인 source; directory scan·filename match 0 | + +현 snapshot의 137 relief Markdown, structured rule branch, renderer branch, authority/corpus/legal sign-off가 production용으로 닫히지 않았다. S2_40 code·schema·fixture를 offline PASS해도 이 legal content gap을 자동으로 `READY_FOR_LAWYER_FILING_DECISION`으로 올리지 않는다. + +--- + +## 3. mandatory shared update·reseal inventory + +### 3.1 parent-independent shared source update + +| exact path | 조치 | 변경 내용 | +|---|---|---| +| `R/workflows/S2_40_final_review_render_and_commit.yml` | `UPDATE-RESEAL` | status-only stub을 full normal route + S2_00 exact-five diagnostic route의 exactly-one-task contract로 교체 | +| `R/workflows/S2_30_claim_group_draft_map.yml` | `UPDATE-RESEAL / UPSTREAM-HANDOFF-FIX` | canonical part wrapper와 `artifact_manifest.json`을 exact path로 열거하고 status-last publish barrier가 manifest를 결속하도록 개정 | +| `R/schemas/draft_atoms.schema.json` | `UPDATE-RESEAL / UPSTREAM-HANDOFF-FIX` | physical part wrapper·artifact manifest·mode/admission provenance의 closed `$defs` 추가 | +| `R/schemas/review_status.schema.json` | `UPDATE-RESEAL` | final ledger·V result·review·3축 state·run barrier `$defs` | +| `R/schemas/deployment.schema.json` | `UPDATE-RESEAL` | S2_40 request/outer receipt/binding/inline receipt/commit contract | +| `R/registry/review/review_policy_registry.yml` | `UPDATE-RESEAL` | drafting permission을 보존하면서 v5-1 closed final-review policy 추가 | +| `R/renderers/R01_money_payment.yml`∼`R06_constitutive_judgment_challenge.yml` | `UPDATE-RESEAL` | closed AST/template field를 완전화하되 legal admission pending 유지 | +| `R/registry/regression/finding_fixture_map.yml` | `UPDATE-RESEAL` | S2_40 V-code·fixture exact mapping 추가 | +| `R/tests/fixtures/regression_manifest.json` | `UPDATE-RESEAL` | S2_40 test/fixture path/hash/expected oracle를 global manifest에 추가 | + +### 3.2 cumulative parent closure builder·validator + +| exact path pair | 조치 | 변경 내용 | +|---|---|---| +| `R/offline_build/build_release_manifests.py/.txt` | `UPDATE-RESEAL` | S2_20+S2_30+S2_40 parent-member allowlist의 sorted disjoint union, duplicate/forbidden downstream member 거부 | +| `R/release_ops/release_validator.py/.txt` | `UPDATE-RESEAL` | S2_40 Agent count·inline receipt·binding·schema·parent closure·legacy dependency 0를 독립 재검증 | +| `R/tests/s2_20/test_plan_publish_and_release.py/.txt` | `UPDATE-RESEAL` | cumulative allowlist에 S2_40 parent-independent member가 누락/중복되지 않음을 회귀검증 | +| `R/tests/s2_20/test_regression_manifest_closure.py/.txt` | `UPDATE-RESEAL` | global fixture manifest, changed builder/validator/test hash closure 재검증 | +| `R/manifest/module_manifest.json` | `UPDATE-RESEAL` | S2_40 parent-independent source row·changed source hash·implementation/legal status 재조립 | +| `R/manifest/stage2_release.json` | `UPDATE-RESEAL` | 새 module manifest와 cumulative parent source closure를 묶는 parent raw hash/digest 생성 | + +`R/manifest/s2_40_parent_member_paths.json`에는 이미 S2_20 allowlist가 소유한 renderer·deployment schema·release builder/validator를 중복 열거하지 않는다. 파일이 변경되어도 기존 owner allowlist row의 hash만 재봉인한다. + +`build_release_manifests.py`의 generic row 생성기는 stage를 S2_20으로 고정하지 않는다. 각 parent-member allowlist의 provenance에서 `owner_stage`를 계산하여 `module_id`, `asset_version`, `owner`, `scope_predicate`, `schema_version`을 stage별로 생성한다. 기존 S2_30 workflow·schema·builder·fixture·test row의 잘못된 S2_20 소유권도 같은 빌드에서 S2_30으로 교정하며 stage별 row count와 path-disjointness를 회귀검증한다. + +### 3.3 parent hash cascade — S2_00·S2_20 + +| exact path | 조치 | 이유 | +|---|---|---| +| `M/Stage_2_S2_00_v.2.yml` | `UPDATE-RESEAL` | inline `EXPECTED_STAGE2_RELEASE_SHA256` 교체 | +| `R/agent_scripts/Stage_2_S2_00.yml` | `UPDATE-RESEAL` | 변경 authoring byte-identical 재투영 | +| `R/runtime/s2_00_ingress.py/.txt` | `UPDATE-RESEAL` | 새 inline code exact mirror | +| `R/manifest/s2_00_inline_code_receipt.json` | `UPDATE-RESEAL` | Agent/code/parent hash 갱신 | +| `M/Stage_2_S2_20.yml` | `UPDATE-RESEAL` | inline `EXPECTED_STAGE2_RELEASE_SHA256` 교체 | +| `R/agent_scripts/Stage_2_S2_20.yml` | `UPDATE-RESEAL` | 변경 authoring byte-identical 재투영 | +| `R/runtime/s2_20_reduce.py/.txt` | `UPDATE-RESEAL` | 새 inline code exact mirror | +| `R/manifest/s2_20_inline_code_receipt.json` | `UPDATE-RESEAL` | Agent/code/parent hash 갱신 | + +S2_00 ingress·cluster 알고리즘과 S2_20 option·binding·retrieval·calculation 알고리즘은 변경하지 않는다. parent raw hash constant과 그 파생물만 재생성한다. + +### 3.4 parent hash cascade — S2_10 child + +| exact path | 조치 | 이유 | +|---|---|---| +| `R/manifest/s2_10_release.json` | `UPDATE-RESEAL` | 새 parent raw hash로 child release 재봉인 | +| `R/manifest/s2_10_agent_receipt.json` | `UPDATE-RESEAL` | 새 child hash와 현행 Agent/binding parity 기록 | +| `R/manifest/s2_10_platform_adapter_receipt.json` | `UPDATE-RESEAL / EXTERNAL-PENDING` | 새 parent/child hash; live status `PENDING` 유지 | +| `R/manifest/s2_10_model_benchmark_receipt.json` | `UPDATE-RESEAL / EXTERNAL-PENDING` | 새 parent/child hash; benchmark status `PENDING` 유지 | +| `R/manifest/s2_10_legal_review_receipt.json` | `UPDATE-RESEAL / EXTERNAL-PENDING` | 새 parent/child hash; 변호사 review status `PENDING` 유지 | + +`M/Stage_2_S2_10_v.1.yml`, S2_10 deployment Agent, P00/P10, prompt receipt, LLM binding은 S2_40 도입으로 bytes를 바꾸지 않는다. S2_40이 S2_10의 법률판단을 재실행하지도 않는다. + +### 3.5 parent hash cascade — S2_30 Agent·child + +| exact path | 조치 | 이유 | +|---|---|---| +| `M/Stage_2_S2_30.yml` | `UPDATE-RESEAL` | dispatch planner inline parent release constant 교체 | +| `R/agent_scripts/Stage_2_S2_30.yml` | `UPDATE-RESEAL` | 변경 authoring byte-identical 재투영 | +| `R/runtime/s2_30_dispatch_planner.py/.txt` | `UPDATE-RESEAL` | 새 planner code exact mirror | +| `R/manifest/s2_30_inline_code_receipt.json` | `UPDATE-RESEAL` | Agent/code/mirror hash 갱신 | +| `R/manifest/s2_30_inline_prompt_projection_receipt.json` | `UPDATE-RESEAL` | P00/P30 scalar bytes는 불변이지만 새 authoring Agent hash를 재기록 | +| `R/deployment/stage2_s2_30_llm_binding.yml` | `UPDATE-RESEAL` | 새 Agent·code receipt hash를 재결속; model/prompt 의미계약 불변 | +| `R/manifest/s2_30_release.json` | `UPDATE-RESEAL` | 새 parent·Agent·binding·receipt로 child 재봉인 | +| `R/manifest/s2_30_agent_receipt.json` | `UPDATE-RESEAL` | authoring/deployment parity와 child/binding hash 갱신 | +| `R/manifest/s2_30_platform_adapter_receipt.json` | `UPDATE-RESEAL / EXTERNAL-PENDING` | 새 hash를 반영하되 live adapter status는 `PENDING` | +| `R/manifest/s2_30_model_benchmark_receipt.json` | `UPDATE-RESEAL / EXTERNAL-PENDING` | 새 hash를 반영하되 model benchmark는 `PENDING` | +| `R/manifest/s2_30_legal_review_receipt.json` | `UPDATE-RESEAL / EXTERNAL-PENDING` | 새 hash를 반영하되 대한민국 변호사 review는 `PENDING` | + +### 3.6 shared deterministic trust chain + +| exact path | 조치 | 변경 내용 | +|---|---|---| +| `R/deployment/stage2_code_executor_binding.yml` | `UPDATE-RESEAL` | top-level `stage_bindings[]`에 S2_40 exact-one row를 추가하고 S2_00/S2_20/S2_30 helper의 새 hash를 갱신 | +| `R/manifest/stage2_deterministic_admission_receipt.json` | `UPDATE-RESEAL / EXTERNAL-PENDING` | S2_00/S2_20/S2_40와 S2_30 helper의 Agent/code/outer evidence를 detached 결속; signature/live evidence가 없으면 production block | + +S2_40 binding의 `active_runtime_authority`는 offline 구현 단계에서 `false`로 둔다. `localdocs_contract` 외 external MCP는 `null`이고 `egress_profile_id` 후보는 `S2_40_LOCALDOCS_ONLY_V1`이다. live `run_code`, secret injection, workspace isolation, binary preservation, request-size/timeout, logical barrier·route 실증 전에는 이를 active production authority로 표현하지 않는다. + +### 3.7 helper를 실행하되 bytes는 원칙적으로 유지할 파일 + +| exact path pair/family | 조치 | 원칙 | +|---|---|---| +| `R/offline_build/build_s2_00_inline_projection.py/.txt` | `RUN-NO-BYTE-CHANGE` | 새 parent hash authoring에 대한 projection·mirror·receipt 재생성 | +| `R/offline_build/build_s2_20_inline_projection.py/.txt` | `RUN-NO-BYTE-CHANGE` | 새 parent hash authoring에 대한 projection·mirror·receipt 재생성 | +| `R/offline_build/build_s2_10_agent_projection.py/.txt` | `RUN-NO-BYTE-CHANGE` | Agent/prompt bytes 불변와 child reseal 전제 검증 | +| `R/offline_build/build_s2_30_agent_projection.py/.txt` | `RUN-NO-BYTE-CHANGE` | parent hash 변경에 따른 Agent/mirror/receipt/binding/child 재생성 | +| 기존 `R/tests/s2_00/`, `R/tests/s2_10/`, `R/tests/s2_20/`, `R/tests/s2_30/` | `RUN-NO-BYTE-CHANGE` | 누적 5-task contract 회귀; hard-coded hash/allowlist assertion이 실제로 깨질 때만 해당 pair를 `UPDATE-RESEAL` | + +--- + +## 4. runtime IO — 고정 배포 자산 수량 제외 + +### 4.1 outer request·execution evidence + +| runtime path | writer | S2_40 소비 조건 | +|---|---|---| +| `Q` | outer orchestrator / AgentBackend | `deployment.schema.json#/$defs/s2_40_request`; request ID, canonical run binding, route, resume/candidate ref, output root, host CAS echo | +| `stage2_control/host_cas//S2_40//.json` | AgentBackend CAS owner | actual Agent/code/binding/parent hash와 candidate/transition별 single-flight attempt를 결속 | +| `O/control/s2_40_outer_execution_receipt.json` | AgentBackend | actual outer MCP result, user/workspace isolation, Agent/code/release/binding hash; inline code가 자기가 작성하지 않음 | + +### 4.2 normal route 입력 + +S2_40은 barrier가 열거하고 module/release가 봉인한 exact path만 읽는다. + +```text +O/ingress/ingress_status.json +O/context/case_context.json +O/context/evidence_inventory.json +O/context/object_registry.json +O/context/party_and_title_context.json +O/context/slot_crosswalk.json +O/context/cluster_plan.json +O/review/issue_ledger.base.json + +O/map_s2_10/s2_10_publish_status.json +O/map_s2_10/domain_verdicts/.json +O/map_s2_10/issue_patches/.json +O/map_s2_10/assumption_parts/.json +O/map_s2_10/usage_parts/.json +O/map_s2_10/item_receipts/.json +O/map_s2_10/wave_receipts/wave-.json + +O/plan/plan_publish_status.json +O/plan/canonical_relief_plan.json +O/plan/claim_groups.json +O/plan/case_type_bindings.json +O/plan/issue_ledger.plan.json +O/plan/rule_context_packs/.json +O/plan/requirement_fact_packs/.json +O/plan/element_evidence_gap/.json +O/plan/calculation_receipts/.json +O/plan/calculation_report.json +O/plan/filing_metrics.json +O/plan/exhibit_register.json +O/plan/option_conservation_report.json +O/plan/party_completeness_report.json +O/plan/group_slices/.json + +O/map_s2_30/s2_30_publish_status.json +O/map_s2_30/artifact_manifest.json +O/map_s2_30/draft_parts/.json +O/map_s2_30/issue_patches/.json +O/map_s2_30/worknote_parts/.json +O/map_s2_30/usage_parts/.json +O/map_s2_30/item_receipts/.json +O/map_s2_30/cohort_receipts//attempt-.json + +O/review/review_receipts/.json # resume 시에만 external input +O/review/lawyer_judgment_record.json # 필요하고 유효한 external input일 때만 +``` + +S2_40은 S2_20·S2_30 publish barrier의 expected/published exact set을 먼저 대조한다. S2_30 barrier가 결속한 `artifact_manifest.json`만 물리 part index로 사용하며 directory scan으로 누락 part를 보충하거나 terminal failure part를 정상 part로 대체하지 않는다. `compile_mode ∈ {STRUCTURAL_FIXTURE,SUBSET_CANARY,PRODUCTION}`와 parent/child release, Agent/binding, prompt/code receipt, P00/P30/P31/P32/S30 hash는 S2_30 barrier→manifest/part→S2_40 request→candidate/package/run-status까지 exact echo한다. fixture는 READY 금지, subset canary는 승인 scope 밖 출력 금지, production은 모든 live/legal gate를 요구한다. + +### 4.3 status-only route exact input + +현행 stub의 exact-five 계약을 full S2_40 Agent 내에 그대로 승계한다. + +```text +O/ingress/ingress_status.json +O/ingress/technical_diagnostic.json +O/ingress/stage1_input_manifest.json +O/ingress/intake_report.json +O/review/issue_ledger.base.json +``` + +추가 context·S2_10·plan·draft input은 0이고 pleading render·법률판단·filing readiness 판정은 하지 않는다. 출력은 `O/control/run_status.json` 하나이며 `legal_readiness=NOT_ASSESSED`, `artifact_technical_status=NOT_PRODUCED`다. + +v5-1의 outer route 계약에 따라 status-only는 S2_00 exact-five 하나뿐이다. S2_10·S2_20·S2_30이 terminal technical failure로 끝나면 각 stage의 terminal barrier에서 정지하고 S2_40을 호출하지 않는다. 별도 전략 개정 없이 S2_40이 불완전한 중간 산출물을 diagnostic input으로 읽는 확장은 금지한다. + +### 4.4 candidate·review·final output과 single writer + +| runtime family | single writer | 핵심 계약 | +|---|---|---| +| `O/review/issue_ledger.final.json`, `assumption_ledger.json`, `llm_usage.jsonl` | S2_40 | base·plan·S2_10·S2_30 part의 ID-sort deterministic reduce; append-only lineage | +| digest-qualified candidate checkpoint | S2_40 | candidate manifest/content digest/documents/worknote/review packet/validation; external receipt 대기 중 final target으로 승격 금지 | +| `O/review/review_requests/.json` | S2_40 | `required_receipt_types` non-empty인 경우만 candidate digest-bound request 생성 | +| `O/review/review_receipts/.json`, `lawyer_judgment_record.json` | manifest-designated external reviewer | S2_40은 생성·수정하지 않고 schema/signature/scope/digest/expiry만 검증 | +| `O/review/filing_decisions/.json` | manifest-designated 대한민국 변호사 | `review_status.schema.json#/$defs/filing_decision_receipt`; candidate/package/artifact-set/run-status hash와 `APPROVE_FOR_FILING|DO_NOT_FILE`을 서명. S2_40은 생성하지 않고 후속 filing/export validator가 소비 | +| `O/final/candidate_package_manifest.json`, `candidate_content_digest.json` | S2_40 | commit된 candidate의 exact content root | +| `O/final/claim_relief.md`, `claim_cause.md`, `pleading_draft.md` | S2_40 | canonical UTF-8/NFC/LF closed render·assembly의 최종 bytes | +| `O/final/attorney_worknotes.json`, `lawyer_review_packet.json`, `stage2_final_validation_report.json`, `stage2_package.json` | S2_40 | 불확실성·검토필요·V result·package refs 보존 | +| `O/commit/commit_intent.json` | S2_40 | 시도 전 의도·target set·candidate digest; 성공 증명이 아님 | +| `O/commit/stage2_commit_result.json` | S2_40 | actual artifact-set digest·read-back result·candidate/final package digest | +| `O/control/run_status.json` | S2_40 | 최종 유일 consumer barrier; 모든 해당 output/read-back·commit result 후 마지막에 작성 | + +법률 불확실성·증거 gap·binding conflict가 있어도 기술적으로 일관된 candidate를 만들 수 있으면 draft/worknote/review packet을 보존하고 `LAWYER_REVIEW_REQUIRED`로 둔다. 물리적으로 일관된 package를 만들 수 없는 affected scope만 `TECHNICAL_INCOMPLETE`다. 이때 정상 group의 draft/worknote/issue와 affected-scope diagnostic은 candidate diagnostic 영역에 보존하되 clean pleading과 final sealed package는 만들지 않는다. + +`COMMITTED`는 byte-level logical commit 완료만 뜻한다. filing/export 소비 권한은 `COMMITTED ∧ READY_FOR_LAWYER_FILING_DECISION ∧ 별도 대한민국 변호사 filing-decision receipt=APPROVE_FOR_FILING`을 모두 요구하며 review용 committed package에는 제출 권한이 없다. receipt의 서명 preimage는 candidate digest, final package raw hash, artifact-set digest, committed run-status raw hash, filing scope, reviewer identity/qualification, issued/expiry/revocation을 포함한다. + +--- + +## 5. non-cyclic seal rule + +생성 dependency의 유일 정본은 §6.1의 `N1/N2 병렬 → join → N3 derived reseal` DAG다. + +parent `stage2_release.json` raw closure에는 S2_40 schema·workflow·pure-core·fixture·test·builder와 shared declarative source만 포함한다. parent hash를 내장하는 다음 자산은 parent closure에 역으로 넣지 않는다. + +```text +M/Stage_2_S2_40.yml +R/agent_scripts/Stage_2_S2_40.yml +R/runtime/s2_40_commit.py +R/runtime/s2_40_commit.txt +R/manifest/s2_40_inline_code_receipt.json +R/deployment/stage2_code_executor_binding.yml +R/manifest/stage2_deterministic_admission_receipt.json +R/manifest/stage2_release.json +``` + +detached binding/admission layer가 parent raw hash와 실제 Agent/code/receipt를 결속한다. 양방향 final hash를 서로 넣어 cycle을 만들지 않는다. + +--- + +## 6. 필수 검증 matrix + +| 검증축 | PASS 조건 | +|---|---| +| YAML/Agent | duplicate key 0, exactly-one stage/task/`run_code`, `language: python`, `httpx==0.28.1`, `agent-network`, 300초, LLM task 0, external Python import 0 | +| inline code | unique parser가 반환한 entire scalar bytes→compile/AST PASS, `exec/eval/subprocess/dynamic code` 0 | +| parity | authoring↔deployment byte-identical, extracted code↔`s2_40_commit.py/.txt` byte-identical, 모든 new/updated `.py/.txt` pair byte-identical | +| upstream closure | S2_20/S2_30 status-last barrier, run/parent/producer/binding, expected/published IDs, artifact path/hash/schema exact equality | +| single writer | S2_30 group part immutable, S2_40만 final ledger/document/state/seal/commit writer, external reviewer receipt를 S2_40이 작성하지 않음 | +| closed render | renderer branch exact one, slot unknown/unbound/dangling 0, eligible atom exactly once, free-text template injection 0, independent re-render byte equality | +| invariants | V01∼V18 각각의 closed PASS/FAIL/UNEVALUABLE + issue code; READY는 18개 모두 PASS이고 renderer/rule/review-policy/case-type coverage/corpus/authority/law-value/calculator가 실행가능·법률승인일 때만 | +| state | 3축 aggregation·workflow phase closed enum, `UNEVALUABLE`을 임의로 `INCOMPLETE`로 변환하지 않음 | +| review | required receipt exact type, candidate digest/scope/role/signature/expiry, `CONTENT_CHANGE_REQUIRED`의 immutable supersession | +| logical commit | content-addressed write/read-back, intent→result→`run_status` last, same-binding idempotence, conflicting bytes overwrite 0 | +| release | cumulative allowlist disjoint, parent forbidden downstream member 0, module/parent hash reproducible, S2_40 row가 shared binding/admission에 exact one | +| clean-slate | `YAML_Prompts/2. Stage_2/v.0`∼`v.3` runtime dependency/import/fallback 0 | +| security | path traversal/symlink escape/directory scan/glob/fuzzy fallback 0, localdocs-only egress, plaintext credential 0, one JSON object stdout | + +Offline integrated regression은 S2_00→S2_10→S2_20→S2_30→S2_40 모든 existing/new test를 실행하고 exact PASS 수를 기록한다. 아직 실행하지 않은 test count를 예상치로 미리 기재하지 않는다. + +### 6.1 생성 dependency와 병렬 단위 + +독립 생성 단위 `N`은 물리 파일 수가 아니라 동일 계약·hash chain을 공유하는 세 family다. + +| 병렬 family | 먼저 생성 | family 내부 순차 후속 | +|---|---|---| +| `N1 UPSTREAM_HANDOFF` | S2_30 physical-wrapper/manifest schema·workflow | validator→fixture/test→S2_30 projection/receipt/child reseal | +| `N2 S2_40_RUNTIME_CONTRACT` | S2_40 schema·workflow·pure-core oracle | fixture→test→authoring inline code→projection/mirror/inline receipt | +| `N3 RELEASE_AND_ADMISSION` | owner-aware module builder·release validator·parent allowlist | N1/N2 bytes 확정 뒤 module→parent→S2_00/S2_20/S2_40 projection→S2_10/S2_30 child/binding/receipt→detached admission | + +N1과 N2는 병렬 착수할 수 있다. N3의 source code는 병렬 작성 가능하지만 manifest·release·binding의 실제 생성은 N1/N2가 고정된 뒤에만 순차 실행한다. fixture는 schema 뒤, test는 fixture/core 뒤, projection receipt는 authoring 뒤, child/binding/admission은 parent 뒤에 생성한다. + +--- + +## 7. 상태·admission 경계 + +| 상태 | 의미 | +|---|---| +| `ASSET_SPECIFICATION_COMPLETE` | 본 inventory의 경로·소유권·순서·경계가 고정됨; 파일 구현 완료를 뜻하지 않음 | +| `IMPLEMENTED_OFFLINE_VERIFIED` | Agent/projection/mirror/schema/core/fixture/test·hash chain이 offline PASS | +| `LIVE_CODE_EXECUTOR_PENDING` | actual `run_code`, secret, workspace isolation, binary preservation, 300초/request-size, localdocs egress, same-binding/barrier route 미실증 | +| `PENDING_LEGAL_ADMISSION` | 137 rule Markdown·renderer branch·review policy·authority/corpus/case fixture의 대한민국 변호사 승인 미완료 | +| `PRODUCTION_ADMITTED` | signed parent/detached admission, live evidence, legal/corpus/renderer approval와 complete-record filing workflow가 모두 닫힘 | + +다음은 S2_40 production 완료 증거가 아니다. + +- authoring/deployment YAML이 존재하는 사실 +- inline Python compile·offline fixture PASS만 있는 상태 +- renderer 6개의 filename이 존재하지만 `branch_rows:[]`이고 legal status가 `PENDING`인 상태 +- `case_type_coverage.json`에 137행이 존재하는 사실 +- S2_30 group part가 실제 live Sol 호출·native adapter·legal admission 없이 생성된 fixture인 상태 +- `PENDING` receipt에 예상 signature·benchmark·변호사 승인을 미리 적은 것 + +S2_40 구현의 최소 offline 성공은 S2_30 immutable parts의 silent loss/duplication 0, closed renderer·independent re-render, V01∼V18, review-aware state, non-cyclic candidate seal, content-addressed read-back와 final barrier-last logical commit을 재현하는 것이다. 그러나 실제 제출 가능성은 자격 있는 대한민국 변호사의 complete-record filing decision까지 자동화하지 않는다. diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_00_v.2.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_00_v.2.yml index 13248d63..b8c468d2 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_00_v.2.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_00_v.2.yml @@ -192,7 +192,7 @@ Agent: # literal placeholders in the offline parity mirror and its unit tests. INLINE_USER_HASH = "{{__user_hash__}}" INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}" - EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" + EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" INLINE_REQUEST_PATH = "stage2_control/s2_00_request.json" INLINE_STAGE2_ASSET_ROOT = "Default_Agent/Stage_2_Clean" INLINE_STAGE2_RELEASE_PATH = ( diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_20.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_20.yml index 2b14d329..eb547a7e 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_20.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_20.yml @@ -71,7 +71,7 @@ Agent: WORKFLOW_ID = "S2_20" ALGORITHM_VERSION = "s2_20_relief_plan/1.0.0" - EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" + EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" WEAVIATE_MCP_URL = "https://weaviate.eroomai.com/mcp" MCP_PROTOCOL_VERSION = "2025-03-26" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_30.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_30.yml index 1c34ce9a..55c36d46 100644 --- a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_30.yml +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_30.yml @@ -73,7 +73,7 @@ Agent: from typing import Any, Mapping - EXPECTED_STAGE2_RELEASE_SHA256 = "579e4c896cf16bf2fab1482bc6327319035b1c320528bb818d36d3f9036c1b81" + EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" MCP_PROTOCOL_VERSION = "2025-03-26" INLINE_USER_HASH = "{{__user_hash__}}" diff --git a/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_40.yml b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_40.yml new file mode 100644 index 00000000..57d65722 --- /dev/null +++ b/Case_02_Comparison_Research/YAML_Prompts/2. Stage_2/Stage_2_S2_40.yml @@ -0,0 +1,3575 @@ +Agent: + name: Stage_2_S2_40 + version: "1.0.0" + description: >- + S2_20 frozen plan과 S2_30 immutable group parts를 exact manifest로 reduce하고, + closed renderer 재전개, V01~V18, review state, content-addressed seal과 + barrier-last logical commit을 수행하는 S2_40 NON-LLM-DETERMINISTIC Agent. + metadata: + workflow_id: S2_40 + execution_class: NON-LLM-DETERMINISTIC + execution_authority: MCP_CODE_EXECUTOR_INLINE + task_constitution: S2_40_EXACTLY_ONE_INLINE_RUN_CODE_V1 + implementation_status: IMPLEMENTED_OFFLINE_VERIFIED_LIVE_AND_LEGAL_ADMISSION_PENDING + legacy_stage2_v0_v3_runtime_dependency_count: 0 + Stages: + - name: S2_40 + description: >- + 단일 Code Executor 호출 내부에서 C40 -> C45 -> C46 -> C47 -> C48을 + 실행한다. S2_00 exact-five status-only route도 같은 task의 닫힌 branch다. + prevs: [] + nexts: [] + skip_confirm: true + tools: + mcpServers: + localdocs: + type: streamable-http + url: http://mcp-localdocs:8012/mcp + code-executor: + type: streamable-http + url: https://code-executor.mcp.eroomai.com/mcp + tasks: + - task_name: Task_S2_40_deterministic_finalizer + description: >- + release-bound request와 barrier가 열거한 immutable input만 읽어 + candidate/review/package를 봉인하고 run_status를 마지막에 발행한다. + mcp: code-executor + tool_name: run_code + parameters: + language: python + requirements: "httpx==0.28.1" + network: agent-network + timeout: 300 + code: |- + #!/usr/bin/env python3 + """Release-bound deterministic S2_40 finalizer. + + This module is self-contained. It never imports workspace Python, calls + an LLM, scans directories, invokes a shell, or invents legal content. + All runtime reads and writes use the localdocs MCP binary contract. + """ + + from __future__ import annotations + + import base64 + import binascii + import contextlib + from datetime import datetime, timezone + import hashlib + import io + import itertools + import json + import re + import sys + import unicodedata + from pathlib import PurePosixPath + from typing import Any, Iterable, Mapping, Sequence + + + WORKFLOW_ID = "S2_40" + ALGORITHM_VERSION = "s2_40_finalizer/1.0.0" + EXPECTED_STAGE2_RELEASE_SHA256 = "9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53" + LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp" + MCP_PROTOCOL_VERSION = "2025-03-26" + INLINE_USER_HASH = "{{__user_hash__}}" + INLINE_WORKSPACE_HASH = "{{__workspace_hash__}}" + REQUEST_PATH = "stage2_control/s2_40_request.json" + ASSET_ROOT = "Default_Agent/Stage_2_Clean" + AGENT_PATH = f"{ASSET_ROOT}/agent_scripts/Stage_2_S2_40.yml" + BINDING_PATH = f"{ASSET_ROOT}/deployment/stage2_code_executor_binding.yml" + INLINE_RECEIPT_PATH = f"{ASSET_ROOT}/manifest/s2_40_inline_code_receipt.json" + PARENT_RELEASE_PATH = f"{ASSET_ROOT}/manifest/stage2_release.json" + MODULE_MANIFEST_PATH = f"{ASSET_ROOT}/manifest/module_manifest.json" + AUTHORITY_RELEASE_REL = "manifest/authority_release.json" + CASE_TYPE_COVERAGE_REL = "manifest/case_type_coverage.json" + CASE_TYPE_REGISTRY_REL = "manifest/case_type_registry.yml" + CASE_TYPE_RULE_REGISTRY_REL = "manifest/case_type_rule_registry.yml" + INPUT_SCHEMA_RELS = ( + "schemas/ingress.schema.json", + "schemas/context.schema.json", + "schemas/domain_verdict.schema.json", + "schemas/s2_10.schema.json", + "schemas/relief_plan.schema.json", + "schemas/binding_retrieval.schema.json", + "schemas/calculation.schema.json", + "schemas/draft_atoms.schema.json", + "schemas/package.schema.json", + "schemas/review_status.schema.json", + "schemas/deployment.schema.json", + ) + MAX_FILE_BYTES = 32 * 1024 * 1024 + MAX_TOTAL_BYTES = 256 * 1024 * 1024 + MAX_ARTIFACT_ROWS = 20000 + HEX64 = re.compile(r"^[a-f0-9]{64}$") + IDENT = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$") + PLACEHOLDER = re.compile(r"\{\{([A-Za-z][A-Za-z0-9_]*)\}\}") + ENTRY_ROUTES = {"TO_S2_40", "TO_S2_40_STATUS_ONLY"} + COMPILE_MODES = {"STRUCTURAL_FIXTURE", "SUBSET_CANARY", "PRODUCTION"} + TRANSITIONS = {"FREEZE", "RESUME"} + V_IDS = tuple(f"V{i:02d}" for i in range(1, 19)) + PART_FAMILIES = ("DRAFT_PART", "ISSUE_PATCH", "USAGE_PART", "WORKNOTE_PART") + PART_DIRECTORIES = { + "DRAFT_PART": "draft_parts", + "ISSUE_PATCH": "issue_patches", + "USAGE_PART": "usage_parts", + "WORKNOTE_PART": "worknote_parts", + } + PART_SCHEMA_REFS = { + "DRAFT_PART": "schemas/draft_atoms.schema.json#/$defs/draft_part", + "ISSUE_PATCH": "schemas/draft_atoms.schema.json#/$defs/issue_patch_part", + "USAGE_PART": "schemas/draft_atoms.schema.json#/$defs/usage_part", + "WORKNOTE_PART": "schemas/draft_atoms.schema.json#/$defs/worknote_part", + } + COMMON_PROVENANCE_FIELDS = { + "compile_mode", "parent_stage2_release_sha256", "s2_30_release_sha256", + "s2_30_agent_sha256", "s2_30_binding_sha256", "p00_prompt_sha256", + "p30_prompt_sha256", "s2_30_producer_contract_digest", + } + GROUP_PROVENANCE_FIELDS = COMMON_PROVENANCE_FIELDS | { + "p31_rule_and_pack_sha256", "p32_common_authority_sha256", + "s30_group_slice_sha256", + } + TRUSTED_REVIEW_ISSUER = "AGENTBACKEND_STAGE2_REVIEW_AUTHORITY" + TRUSTED_REVIEW_KEY_IDS = {"AGENTBACKEND_STAGE2_REVIEW_KEY_V1"} + TRUSTED_REVIEW_SIGNATURE_ALGORITHM = "AGENTBACKEND_TRUSTED_ATTESTATION_V1" + TRUSTED_REVIEW_ROLE = "KOREAN_LAWYER" + TRUSTED_REVIEW_QUALIFICATION = "QUALIFIED_KOREAN_LAWYER" + REQUIRED_LEGAL_GATES = { + "binding", "authority", "renderer_branch", "rule_sub_rule", + "review_policy", "case_type_coverage_137", "corpus", "law_value", + "calculator", "required_receipts", + } + + + class S240Error(Exception): + def __init__(self, code: str, message: str, *, details: Any | None = None) -> None: + super().__init__(message) + self.code = code + self.message = message + self.details = details + + def as_dict(self) -> dict[str, Any]: + row: dict[str, Any] = {"code": self.code, "message": self.message} + if self.details is not None: + row["details"] = self.details + return row + + + def nfc(value: str) -> str: + return unicodedata.normalize("NFC", value) + + + def no_duplicates(pairs: list[tuple[str, Any]]) -> dict[str, Any]: + result: dict[str, Any] = {} + for key, value in pairs: + if key in result: + raise S240Error("DUPLICATE_JSON_KEY", f"duplicate JSON key: {key}") + result[key] = value + return result + + + def load_json(raw: bytes, *, label: str) -> Any: + if len(raw) > MAX_FILE_BYTES: + raise S240Error("SOURCE_SIZE_LIMIT", f"file exceeds limit: {label}") + try: + text = raw.decode("utf-8", errors="strict") + return json.loads( + text, + object_pairs_hook=no_duplicates, + parse_constant=lambda token: (_ for _ in ()).throw( + S240Error("NON_FINITE_NUMBER", f"non-finite number: {token}") + ), + ) + except (UnicodeDecodeError, json.JSONDecodeError) as exc: + raise S240Error("JSON_PARSE_ERROR", f"strict JSON parse failed: {label}") from exc + + + def canonical_bytes(value: Any) -> bytes: + return ( + json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False) + + "\n" + ).encode("utf-8") + + + def canonical_markdown(value: str) -> bytes: + if not isinstance(value, str): + raise S240Error("MARKDOWN_TYPE", "markdown must be a string") + text = nfc(value.replace("\r\n", "\n").replace("\r", "\n")).lstrip("\ufeff") + if "\x00" in text: + raise S240Error("MARKDOWN_NUL", "markdown contains NUL") + return (text.rstrip("\n") + "\n").encode("utf-8") + + + def digest(value: Any) -> str: + payload = value if isinstance(value, bytes) else canonical_bytes(value) + return hashlib.sha256(payload).hexdigest() + + + def require_hex(value: Any, *, code: str) -> str: + if not isinstance(value, str) or HEX64.fullmatch(value) is None: + raise S240Error(code, "expected lower-case SHA-256") + return value + + + def require_ident(value: Any, *, code: str) -> str: + if not isinstance(value, str) or IDENT.fullmatch(value) is None: + raise S240Error(code, "invalid identifier") + return value + + + def require_text(value: Any, *, code: str) -> str: + if not isinstance(value, str) or not value.strip(): + raise S240Error(code, "non-empty text required") + return nfc(value) + + + def safe_path(value: Any, *, code: str = "PATH_INVALID") -> str: + if not isinstance(value, str) or not value or "\x00" in value: + raise S240Error(code, "path must be a non-empty string") + if value.startswith("/") or "\\" in value: + raise S240Error(code, "absolute or backslash path is forbidden") + normalized = PurePosixPath(value) + if any(part in {"", ".", ".."} for part in normalized.parts): + raise S240Error(code, "path traversal or ambiguous component") + return normalized.as_posix() + + + def join_path(*parts: str) -> str: + return safe_path("/".join(part.strip("/") for part in parts if part)) + + + def stable_id(prefix: str, *parts: Any) -> str: + return f"{prefix}-{digest([nfc(str(part)) for part in parts])[:24]}" + + + def utc_now() -> str: + return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") + + + def require_object(value: Any, *, code: str) -> dict[str, Any]: + if not isinstance(value, dict): + raise S240Error(code, "object required") + return value + + + def require_list(value: Any, *, code: str) -> list[Any]: + if not isinstance(value, list): + raise S240Error(code, "array required") + return value + + + def _parse_mcp_payload(raw: bytes, expected_id: int) -> Mapping[str, Any]: + candidates: list[Any] + if raw.lstrip().startswith(b"{"): + try: + candidates = [load_json(raw, label="mcp-json")] + except S240Error as exc: + if exc.code != "JSON_PARSE_ERROR": + raise + try: + text = raw.decode("utf-8", errors="strict") + decoder = json.JSONDecoder(object_pairs_hook=no_duplicates) + first, offset = decoder.raw_decode(text.lstrip()) + tail = text.lstrip()[offset:].strip() + candidates = [first] + while tail: + extra, offset = decoder.raw_decode(tail) + candidates.append(extra) + tail = tail[offset:].strip() + except (UnicodeDecodeError, json.JSONDecodeError) as parse_exc: + raise S240Error("MCP_JSON_EXTRA_DATA", "invalid concatenated MCP JSON") from parse_exc + else: + try: + text = raw.decode("utf-8", errors="strict") + except UnicodeDecodeError as exc: + raise S240Error("MCP_SSE_UTF8", "invalid MCP SSE UTF-8") from exc + events: list[bytes] = [] + data_lines: list[str] = [] + for line in text.replace("\r\n", "\n").split("\n"): + if not line: + if data_lines: + events.append("\n".join(data_lines).encode("utf-8")) + data_lines = [] + continue + if line.startswith((":", "event:", "id:", "retry:")): + continue + if not line.startswith("data:"): + raise S240Error("MCP_SSE_SHAPE", "unexpected SSE line") + data_lines.append(line[5:].lstrip()) + if data_lines: + events.append("\n".join(data_lines).encode("utf-8")) + candidates = [load_json(event, label="mcp-sse-event") for event in events] + matches = [row for row in candidates if isinstance(row, dict) and row.get("id") == expected_id] + if len(matches) != 1: + raise S240Error("MCP_RESPONSE_ID", "exactly one matching JSON-RPC result required") + row = matches[0] + if row.get("jsonrpc") != "2.0" or row.get("error") is not None: + raise S240Error("MCP_JSONRPC_ERROR", "MCP returned an invalid/error response") + if not isinstance(row.get("result"), dict): + raise S240Error("MCP_RESULT_SHAPE", "MCP result must be an object") + return row + + + def _tool_text(result: Mapping[str, Any], tool: str) -> str: + if result.get("isError") is True: + rendered = str(result.get("content", "")) + code = "LOCALDOCS_NOT_FOUND" if "not found" in rendered.lower() else "MCP_TOOL_ERROR" + raise S240Error(code, f"{tool} returned isError=true") + content = result.get("content") + if not isinstance(content, list) or len(content) != 1: + raise S240Error("MCP_CONTENT_CARDINALITY", "one content block required") + block = content[0] + if not isinstance(block, dict) or block.get("type") != "text" or not isinstance(block.get("text"), str): + raise S240Error("MCP_CONTENT_SHAPE", "one text block required") + return block["text"] + + + def _binary_from_text(text: str, path: str) -> bytes: + value = load_json(text.encode("utf-8"), label=path) + if isinstance(value, dict) and isinstance(value.get("results"), list): + rows = value["results"] + if len(rows) != 1 or not isinstance(rows[0], dict): + raise S240Error("LOCALDOCS_RESULT_CARDINALITY", "one binary result required") + value = rows[0].get("content", rows[0].get("text")) + if isinstance(value, str): + value = load_json(value.encode("utf-8"), label=path) + if not isinstance(value, dict) or not isinstance(value.get("content_base64"), str): + raise S240Error("LOCALDOCS_BINARY_ENVELOPE", "content_base64 is required") + try: + raw = base64.b64decode(value["content_base64"].encode("ascii"), validate=True) + except (UnicodeEncodeError, binascii.Error, ValueError) as exc: + raise S240Error("LOCALDOCS_BASE64", "strict base64 required") from exc + if value.get("byte_length", value.get("size", len(raw))) != len(raw): + raise S240Error("LOCALDOCS_LENGTH", f"byte length mismatch: {path}") + if value.get("sha256", digest(raw)) != digest(raw): + raise S240Error("LOCALDOCS_HASH", f"raw hash mismatch: {path}") + return raw + + + class McpClient: + def __init__(self, endpoint: str, name: str) -> None: + try: + import httpx # type: ignore + except ImportError as exc: + raise S240Error("HTTPX_UNAVAILABLE", "httpx==0.28.1 is required") from exc + self.endpoint = endpoint + self.name = name + self.client = httpx.Client(timeout=60) + self.headers = {"Content-Type": "application/json", "Accept": "application/json, text/event-stream"} + self.ids = itertools.count(10) + self.initialized = False + + def close(self) -> None: + self.client.close() + + def _post(self, body: Mapping[str, Any], expected_id: int | None) -> Mapping[str, Any] | None: + try: + response = self.client.post(self.endpoint, json=dict(body), headers=dict(self.headers)) + response.raise_for_status() + except Exception as exc: + raise S240Error("MCP_TRANSPORT", f"{self.name} transport failed") from exc + session = response.headers.get("mcp-session-id") + if session: + self.headers["mcp-session-id"] = session + if expected_id is None: + return None + return _parse_mcp_payload(bytes(response.content), expected_id) + + def initialize(self) -> None: + row = self._post( + { + "jsonrpc": "2.0", "id": 1, "method": "initialize", + "params": { + "protocolVersion": MCP_PROTOCOL_VERSION, + "capabilities": {}, + "clientInfo": { + "name": "liti-s2-40-inline", "version": "1.0.0", + "user_id": INLINE_USER_HASH, "workspace_id": INLINE_WORKSPACE_HASH, + }, + }, + }, + 1, + ) + if row is None or row["result"].get("protocolVersion") != MCP_PROTOCOL_VERSION: + raise S240Error("MCP_PROTOCOL", "MCP protocol negotiation failed") + self._post({"jsonrpc": "2.0", "method": "notifications/initialized"}, None) + self.initialized = True + + def call(self, tool: str, arguments: Mapping[str, Any]) -> Mapping[str, Any]: + if not self.initialized: + raise S240Error("MCP_NOT_INITIALIZED", "initialize before tools/call") + message_id = next(self.ids) + row = self._post( + {"jsonrpc": "2.0", "id": message_id, "method": "tools/call", "params": {"name": tool, "arguments": dict(arguments)}}, + message_id, + ) + if row is None: + raise S240Error("MCP_EMPTY", f"empty response: {tool}") + return row["result"] + + def read_binary(self, path: str) -> bytes: + safe = safe_path(path) + return _binary_from_text(_tool_text(self.call("read_binary_doc", {"doc_name": safe}), "read_binary_doc"), safe) + + def read_optional(self, path: str) -> bytes | None: + try: + return self.read_binary(path) + except S240Error as exc: + if exc.code == "LOCALDOCS_NOT_FOUND": + return None + raise + + def write_immutable(self, path: str, payload: bytes) -> str: + safe = safe_path(path) + existing = self.read_optional(safe) + if existing is not None: + if existing != payload: + raise S240Error("IMMUTABLE_CONFLICT", f"existing bytes differ: {safe}") + return digest(existing) + encoded = base64.b64encode(payload).decode("ascii") + _tool_text( + self.call("write_binary_file", {"path": safe, "content_base64": encoded, "overwrite": False}), + "write_binary_file", + ) + observed = self.read_binary(safe) + if observed != payload: + raise S240Error("WRITE_READBACK_MISMATCH", f"read-back differs: {safe}") + return digest(observed) + + def write_latest(self, path: str, payload: bytes, expected_previous: str | None) -> str: + safe = safe_path(path) + existing = self.read_optional(safe) + if expected_previous is None: + if existing is not None and existing != payload: + raise S240Error("LATEST_BARRIER_CONFLICT", "unexpected previous latest barrier") + else: + if existing is None or digest(existing) != expected_previous: + raise S240Error("LATEST_BARRIER_CAS", "previous latest barrier hash mismatch") + if existing == payload: + return digest(existing) + encoded = base64.b64encode(payload).decode("ascii") + _tool_text( + self.call("write_binary_file", {"path": safe, "content_base64": encoded, "overwrite": existing is not None}), + "write_binary_file", + ) + observed = self.read_binary(safe) + if observed != payload: + raise S240Error("LATEST_READBACK_MISMATCH", "latest barrier read-back mismatch") + return digest(observed) + + + REQUEST_KEYS = { + "schema_version", "request_id", "candidate_attempt_id", "run_binding_digest", + "user_identity_hash", "workspace_identity_hash", "stage2_run_root_ref", + "entry_route", "compile_mode", "requested_transition", + "expected_previous_run_status_sha256", "expected_candidate_content_digest", + "expected_ingress_status_sha256", "expected_s2_10_publish_status_sha256", + "expected_plan_publish_status_sha256", "expected_s2_30_publish_status_sha256", + "expected_s2_30_artifact_manifest_sha256", "expected_parent_stage2_release_sha256", + "expected_s2_40_agent_sha256", "expected_s2_40_executor_binding_sha256", + "expected_s2_40_inline_code_receipt_sha256", "host_cas_receipt_ref", + "host_cas_receipt_sha256", "detached_admission_receipt_ref", + "detached_admission_receipt_sha256", "outer_execution_receipt_target_ref", + "review_receipt_refs", + } + + + def validate_request(raw: bytes) -> dict[str, Any]: + value = load_json(raw, label=REQUEST_PATH) + if not isinstance(value, dict) or set(value) != REQUEST_KEYS: + keys = set(value) if isinstance(value, dict) else set() + raise S240Error("REQUEST_CLOSED_SHAPE", "request keys differ", details={"missing": sorted(REQUEST_KEYS - keys), "extra": sorted(keys - REQUEST_KEYS)}) + if value["schema_version"] != "stage2_s2_40_request.v1": + raise S240Error("REQUEST_VERSION", "unsupported request schema") + for key in ("request_id", "candidate_attempt_id"): + require_ident(value[key], code="REQUEST_IDENTIFIER") + run_digest = require_hex(value["run_binding_digest"], code="RUN_BINDING_DIGEST") + for key in ( + "user_identity_hash", "workspace_identity_hash", "expected_ingress_status_sha256", + "expected_parent_stage2_release_sha256", "expected_s2_40_agent_sha256", + "expected_s2_40_executor_binding_sha256", "expected_s2_40_inline_code_receipt_sha256", + "host_cas_receipt_sha256", "detached_admission_receipt_sha256", + ): + require_hex(value[key], code=f"REQUEST_{key.upper()}") + for key in ( + "expected_previous_run_status_sha256", "expected_candidate_content_digest", + "expected_s2_10_publish_status_sha256", "expected_plan_publish_status_sha256", + "expected_s2_30_publish_status_sha256", "expected_s2_30_artifact_manifest_sha256", + ): + if value[key] is not None: + require_hex(value[key], code=f"REQUEST_{key.upper()}") + if value["user_identity_hash"] != INLINE_USER_HASH or value["workspace_identity_hash"] != INLINE_WORKSPACE_HASH: + raise S240Error("REQUEST_IDENTITY", "request identity differs from AgentBackend substitution") + expected_root = f"stage2_runs/by-binding/{run_digest}" + if value["stage2_run_root_ref"] != expected_root: + raise S240Error("REQUEST_RUN_ROOT", "run root must derive from binding digest") + if value["entry_route"] not in ENTRY_ROUTES or value["requested_transition"] not in TRANSITIONS: + raise S240Error("REQUEST_ENUM", "unsupported entry route or transition") + receipt_refs = require_list(value["review_receipt_refs"], code="REQUEST_REVIEW_REFS") + if len(receipt_refs) > 64 or len(set(receipt_refs)) != len(receipt_refs): + raise S240Error("REQUEST_REVIEW_REFS", "review receipt refs must be unique and bounded") + for ref in receipt_refs: + safe_path(ref, code="REQUEST_REVIEW_REF_PATH") + expected_cas = f"stage2_control/host_cas/{run_digest}/S2_40/{value['candidate_attempt_id']}/{value['requested_transition']}.json" + if value["host_cas_receipt_ref"] != expected_cas: + raise S240Error("REQUEST_CAS_PATH", "host CAS path mismatch") + if value["outer_execution_receipt_target_ref"] != f"{expected_root}/control/s2_40_outer_execution_receipt.json": + raise S240Error("REQUEST_OUTER_RECEIPT_PATH", "outer receipt target mismatch") + status_only = value["entry_route"] == "TO_S2_40_STATUS_ONLY" + upstream_keys = ( + "expected_s2_10_publish_status_sha256", "expected_plan_publish_status_sha256", + "expected_s2_30_publish_status_sha256", "expected_s2_30_artifact_manifest_sha256", + ) + if status_only: + if value["compile_mode"] is not None or value["requested_transition"] != "FREEZE": + raise S240Error("REQUEST_STATUS_ONLY_MODE", "status-only requires null mode and FREEZE") + if any(value[key] is not None for key in upstream_keys) or value["expected_candidate_content_digest"] is not None or receipt_refs: + raise S240Error("REQUEST_STATUS_ONLY_SCOPE", "status-only forbids normal input and review refs") + else: + if value["compile_mode"] not in COMPILE_MODES or any(value[key] is None for key in upstream_keys): + raise S240Error("REQUEST_NORMAL_SCOPE", "normal route requires mode and all upstream hashes") + if value["requested_transition"] == "FREEZE": + if value["expected_candidate_content_digest"] is not None: + raise S240Error("REQUEST_FREEZE_DIGEST", "FREEZE must not supply candidate digest") + if value["expected_previous_run_status_sha256"] is not None or receipt_refs: + raise S240Error("REQUEST_FREEZE_SCOPE", "FREEZE forbids previous status and review receipts") + if value["requested_transition"] == "RESUME": + if value["expected_candidate_content_digest"] is None or value["expected_previous_run_status_sha256"] is None: + raise S240Error("REQUEST_RESUME_SCOPE", "RESUME requires candidate and previous status digests") + return value + + + def read_bound_json(client: McpClient, path: str, expected_sha256: str | None = None) -> tuple[dict[str, Any], bytes]: + raw_a = client.read_binary(path) + if expected_sha256 is not None and digest(raw_a) != expected_sha256: + raise S240Error("BOUND_HASH_MISMATCH", f"raw hash mismatch: {path}") + value = require_object(load_json(raw_a, label=path), code="BOUND_OBJECT") + raw_b = client.read_binary(path) + if raw_b != raw_a: + raise S240Error("TOCTOU_INPUT_CHANGED", f"input changed between reads: {path}") + return value, raw_a + + + def read_release_bound_jsons( + client: McpClient, relative_paths: Sequence[str], + ) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], list[dict[str, Any]]]: + """Read exact module-manifest members; directory discovery is never used.""" + parent_raw = client.read_binary(PARENT_RELEASE_PATH) + if digest(parent_raw) != EXPECTED_STAGE2_RELEASE_SHA256: + raise S240Error("BOUND_PARENT_DRIFT", "parent release differs from inline constant") + parent = require_object(load_json(parent_raw, label=PARENT_RELEASE_PATH), code="BOUND_PARENT_OBJECT") + require_self_hash(parent, "release_digest", code="BOUND_PARENT_SELF_HASH") + module_ref = require_object(parent.get("module_manifest_ref"), code="BOUND_MODULE_REF") + module_raw = client.read_binary(MODULE_MANIFEST_PATH) + if digest(module_raw) != require_hex(module_ref.get("sha256"), code="BOUND_MODULE_HASH"): + raise S240Error("BOUND_MODULE_HASH", "module manifest differs from parent binding") + module = require_object(load_json(module_raw, label=MODULE_MANIFEST_PATH), code="BOUND_MODULE_OBJECT") + require_self_hash(module, "manifest_digest", code="BOUND_MODULE_SELF_HASH") + rows = require_list(module.get("modules"), code="BOUND_MODULE_ROWS") + values: dict[str, dict[str, Any]] = {} + raws: dict[str, bytes] = {} + source_rows: list[dict[str, Any]] = [] + for relative in relative_paths: + relative = safe_path(relative, code="BOUND_MEMBER_PATH") + matches = [row for row in rows if isinstance(row, dict) and row.get("path") == relative] + if len(matches) != 1: + raise S240Error("BOUND_MEMBER_CARDINALITY", f"release member must be exact-one: {relative}") + member = matches[0] + expected = require_hex(member.get("sha256"), code="BOUND_MEMBER_HASH") + raw = client.read_binary(join_path(ASSET_ROOT, relative)) + if digest(raw) != expected or member.get("size_bytes") != len(raw): + raise S240Error("BOUND_MEMBER_DRIFT", f"release member bytes differ: {relative}") + value = require_object(load_json(raw, label=relative), code="BOUND_MEMBER_OBJECT") + values[relative] = value + raws[relative] = raw + source_rows.append({"path": relative, "sha256": expected, "size_bytes": len(raw)}) + return values, raws, sorted(source_rows, key=lambda row: row["path"]) + + + def json_pointer(document: Any, fragment: str) -> Any: + if fragment in {"", "#"}: + return document + pointer = fragment[1:] if fragment.startswith("#") else fragment + if not pointer.startswith("/"): + raise S240Error("SCHEMA_POINTER", f"unsupported JSON pointer: {fragment}") + current = document + for token in pointer[1:].split("/"): + token = token.replace("~1", "/").replace("~0", "~") + if isinstance(current, dict) and token in current: + current = current[token] + elif isinstance(current, list) and token.isdigit() and int(token) < len(current): + current = current[int(token)] + else: + raise S240Error("SCHEMA_POINTER", f"unresolvable JSON pointer: {fragment}") + return current + + + def resolve_schema_ref( + ref: str, current_path: str, store: Mapping[str, Mapping[str, Any]], + ) -> tuple[Mapping[str, Any], str]: + if "#" in ref: + file_ref, fragment = ref.split("#", 1) + fragment = "#" + fragment + else: + file_ref, fragment = ref, "#" + if file_ref: + if file_ref.startswith("schemas/"): + target_path = safe_path(file_ref, code="SCHEMA_REF_PATH") + else: + target_path = safe_path( + str(PurePosixPath(current_path).parent / file_ref), code="SCHEMA_REF_PATH", + ) + else: + target_path = current_path + target_document = store.get(target_path) + if not isinstance(target_document, dict): + raise S240Error("SCHEMA_REF_UNBOUND", f"schema is not release-bound: {target_path}") + target = json_pointer(target_document, fragment) + return require_object(target, code="SCHEMA_REF_TARGET"), target_path + + + def schema_errors( + value: Any, + schema: Mapping[str, Any], + current_path: str, + store: Mapping[str, Mapping[str, Any]], + *, + location: str = "$", + depth: int = 0, + ) -> list[str]: + """Deterministic JSON-Schema subset covering every keyword used by Stage 2 input roots.""" + if depth > 160: + return [f"{location}:schema recursion limit"] + if "$ref" in schema: + target, target_path = resolve_schema_ref(str(schema["$ref"]), current_path, store) + return schema_errors(value, target, target_path, store, location=location, depth=depth + 1) + errors: list[str] = [] + if "const" in schema and value != schema["const"]: + errors.append(f"{location}:const") + if "enum" in schema and value not in schema["enum"]: + errors.append(f"{location}:enum") + expected_type = schema.get("type") + allowed_types = [expected_type] if isinstance(expected_type, str) else expected_type + if isinstance(allowed_types, list): + def type_ok(name: str) -> bool: + return { + "object": isinstance(value, dict), + "array": isinstance(value, list), + "string": isinstance(value, str), + "integer": isinstance(value, int) and not isinstance(value, bool), + "number": isinstance(value, (int, float)) and not isinstance(value, bool), + "boolean": isinstance(value, bool), + "null": value is None, + }.get(name, True) + if not any(type_ok(str(name)) for name in allowed_types): + return errors + [f"{location}:type"] + if isinstance(value, dict): + required = schema.get("required", []) + if isinstance(required, list): + errors.extend(f"{location}.{key}:required" for key in required if key not in value) + properties = schema.get("properties", {}) + if isinstance(properties, dict): + for key, child in properties.items(): + if key in value and isinstance(child, dict): + errors.extend(schema_errors(value[key], child, current_path, store, location=f"{location}.{key}", depth=depth + 1)) + if schema.get("additionalProperties") is False: + errors.extend(f"{location}.{key}:additional" for key in value if key not in properties) + if isinstance(schema.get("minProperties"), int) and len(value) < schema["minProperties"]: + errors.append(f"{location}:minProperties") + if isinstance(value, list): + if isinstance(schema.get("minItems"), int) and len(value) < schema["minItems"]: + errors.append(f"{location}:minItems") + if isinstance(schema.get("maxItems"), int) and len(value) > schema["maxItems"]: + errors.append(f"{location}:maxItems") + if schema.get("uniqueItems") is True: + serialized = [canonical_bytes(item) for item in value] + if len(serialized) != len(set(serialized)): + errors.append(f"{location}:uniqueItems") + prefix = schema.get("prefixItems") + if isinstance(prefix, list): + for index, child in enumerate(prefix): + if index < len(value) and isinstance(child, dict): + errors.extend(schema_errors(value[index], child, current_path, store, location=f"{location}[{index}]", depth=depth + 1)) + if schema.get("items") is False and len(value) > len(prefix): + errors.append(f"{location}:additionalItems") + elif isinstance(schema.get("items"), dict): + for index, item in enumerate(value): + errors.extend(schema_errors(item, schema["items"], current_path, store, location=f"{location}[{index}]", depth=depth + 1)) + contains = schema.get("contains") + if isinstance(contains, dict) and not any(not schema_errors(item, contains, current_path, store, location=location, depth=depth + 1) for item in value): + errors.append(f"{location}:contains") + if isinstance(value, str): + if isinstance(schema.get("minLength"), int) and len(value) < schema["minLength"]: + errors.append(f"{location}:minLength") + if isinstance(schema.get("maxLength"), int) and len(value) > schema["maxLength"]: + errors.append(f"{location}:maxLength") + if isinstance(schema.get("pattern"), str) and re.search(schema["pattern"], value) is None: + errors.append(f"{location}:pattern") + if isinstance(value, (int, float)) and not isinstance(value, bool): + if isinstance(schema.get("minimum"), (int, float)) and value < schema["minimum"]: + errors.append(f"{location}:minimum") + if isinstance(schema.get("maximum"), (int, float)) and value > schema["maximum"]: + errors.append(f"{location}:maximum") + for child in schema.get("allOf", []) if isinstance(schema.get("allOf"), list) else []: + if isinstance(child, dict): + errors.extend(schema_errors(value, child, current_path, store, location=location, depth=depth + 1)) + any_of = schema.get("anyOf") + if isinstance(any_of, list) and not any(isinstance(child, dict) and not schema_errors(value, child, current_path, store, location=location, depth=depth + 1) for child in any_of): + errors.append(f"{location}:anyOf") + one_of = schema.get("oneOf") + if isinstance(one_of, list) and sum(1 for child in one_of if isinstance(child, dict) and not schema_errors(value, child, current_path, store, location=location, depth=depth + 1)) != 1: + errors.append(f"{location}:oneOf") + forbidden = schema.get("not") + if isinstance(forbidden, dict) and not schema_errors(value, forbidden, current_path, store, location=location, depth=depth + 1): + errors.append(f"{location}:not") + condition = schema.get("if") + if isinstance(condition, dict): + branch_name = "then" if not schema_errors(value, condition, current_path, store, location=location, depth=depth + 1) else "else" + branch = schema.get(branch_name) + if isinstance(branch, dict): + errors.extend(schema_errors(value, branch, current_path, store, location=location, depth=depth + 1)) + return errors[:96] + + + def validate_schema_instance( + value: Any, schema_ref: str, store: Mapping[str, Mapping[str, Any]], *, code: str, + ) -> None: + target, path = resolve_schema_ref(schema_ref, "schemas/ingress.schema.json", store) + errors = schema_errors(value, target, path, store) + if errors: + raise S240Error(code, f"schema validation failed: {schema_ref}", details=errors[:16]) + + + def preflight(client: McpClient, request: Mapping[str, Any]) -> str: + if request["expected_parent_stage2_release_sha256"] != EXPECTED_STAGE2_RELEASE_SHA256: + raise S240Error("PARENT_CONSTANT_REQUEST", "request parent hash differs from inline constant") + fixed = ( + (PARENT_RELEASE_PATH, request["expected_parent_stage2_release_sha256"]), + (AGENT_PATH, request["expected_s2_40_agent_sha256"]), + (BINDING_PATH, request["expected_s2_40_executor_binding_sha256"]), + (INLINE_RECEIPT_PATH, request["expected_s2_40_inline_code_receipt_sha256"]), + (request["host_cas_receipt_ref"], request["host_cas_receipt_sha256"]), + (request["detached_admission_receipt_ref"], request["detached_admission_receipt_sha256"]), + ) + snapshot_rows: list[dict[str, Any]] = [] + fixed_raw: dict[str, bytes] = {} + for path, expected in fixed: + raw = client.read_binary(path) + if digest(raw) != expected: + raise S240Error("PREFLIGHT_HASH", f"preflight hash mismatch: {path}") + fixed_raw[path] = raw + snapshot_rows.append({"path": path, "sha256": expected, "size": len(raw)}) + parent = require_object(load_json(fixed_raw[PARENT_RELEASE_PATH], label=PARENT_RELEASE_PATH), code="PARENT_RELEASE_OBJECT") + require_self_hash(parent, "release_digest", code="PARENT_RELEASE_SELF_HASH") + module_ref = require_object(parent.get("module_manifest_ref"), code="PARENT_MODULE_REF") + if module_ref.get("path") != "manifest/module_manifest.json" or module_ref.get("binding_status") != "BOUND": + raise S240Error("PARENT_MODULE_REF", "parent does not bind canonical module manifest") + module_raw = client.read_binary(MODULE_MANIFEST_PATH) + if digest(module_raw) != require_hex(module_ref.get("sha256"), code="PARENT_MODULE_HASH"): + raise S240Error("PARENT_MODULE_HASH", "module manifest raw hash differs from parent") + module = require_object(load_json(module_raw, label=MODULE_MANIFEST_PATH), code="MODULE_MANIFEST_OBJECT") + require_self_hash(module, "manifest_digest", code="MODULE_MANIFEST_SELF_HASH") + modules = require_list(module.get("modules"), code="MODULE_ROWS") + workflow_rows = [row for row in modules if isinstance(row, dict) and row.get("module_id") == "WF-S2_40"] + if len(workflow_rows) != 1 or workflow_rows[0].get("path") != "workflows/S2_40_final_review_render_and_commit.yml": + raise S240Error("S240_MODULE_MEMBERSHIP", "exact S2_40 workflow module membership missing") + + inline_receipt = require_object(load_json(fixed_raw[INLINE_RECEIPT_PATH], label=INLINE_RECEIPT_PATH), code="INLINE_RECEIPT_OBJECT") + if (inline_receipt.get("schema_version") != "stage2_s2_40_inline_code_receipt.v1" + or inline_receipt.get("parity_status") != "PASS" + or inline_receipt.get("expected_parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or inline_receipt.get("deployment_projection", {}).get("sha256") != request["expected_s2_40_agent_sha256"] + or inline_receipt.get("deployment_projection", {}).get("path") != AGENT_PATH): + raise S240Error("INLINE_RECEIPT_MEMBERSHIP", "inline receipt does not bind parent and actual Agent") + binding_text = fixed_raw[BINDING_PATH].decode("utf-8", errors="strict") + required_binding_literals = ( + "stage_id: S2_40", "binding_id: S2-BINDING-S2_40-CODE-EXECUTOR-V1", + "path: agent_scripts/Stage_2_S2_40.yml", request["expected_s2_40_agent_sha256"], + "path: manifest/s2_40_inline_code_receipt.json", request["expected_s2_40_inline_code_receipt_sha256"], + "path: manifest/stage2_release.json", EXPECTED_STAGE2_RELEASE_SHA256, + ) + if any(literal not in binding_text for literal in required_binding_literals): + raise S240Error("BINDING_MEMBERSHIP", "binding does not bind exact S2_40 Agent/parent/receipt") + + admission = require_object(load_json(fixed_raw[request["detached_admission_receipt_ref"]], label="detached-admission"), code="ADMISSION_OBJECT") + admitted_status = "PRODUCTION_ADMITTED" if request.get("compile_mode") == "PRODUCTION" else "CANARY_ADMITTED" + if (admission.get("schema_version") != "stage2_deterministic_admission_receipt.v1" + or admission.get("parent_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or admission.get("executor_binding_sha256") != request["expected_s2_40_executor_binding_sha256"] + or admission.get("admission_status") not in {admitted_status, "PRODUCTION_ADMITTED"} + or admission.get("signature_verification_status") != "BACKEND_VERIFIED" + or admission.get("external_trust_verified") is not True + or not isinstance(admission.get("signature"), str) + or admission.get("signature", "").startswith("PENDING")): + raise S240Error("DETACHED_ADMISSION_NOT_TRUSTED", "release-bound external admission is absent or invalid") + signed_admission = { + key: value for key, value in admission.items() + if key not in {"signature", "signature_verification_status", "signed_payload_sha256"} + } + if (admission.get("signed_payload_sha256") != digest(signed_admission) + or HEX64.fullmatch(str(admission.get("backend_capability_receipt_sha256", ""))) is None): + raise S240Error("DETACHED_ADMISSION_SIGNATURE_SCOPE", "admission signed payload scope/hash differs") + receipt_matches = [row for row in admission.get("stage_receipts", []) if isinstance(row, dict) + and row.get("path") == "manifest/s2_40_inline_code_receipt.json" + and row.get("sha256") == request["expected_s2_40_inline_code_receipt_sha256"]] + if len(receipt_matches) != 1 or "S2_40" not in admission.get("present_deterministic_stage_ids", []): + raise S240Error("DETACHED_ADMISSION_S240", "admission does not bind exact S2_40 receipt") + + cas = require_object(load_json(fixed_raw[request["host_cas_receipt_ref"]], label="host-cas"), code="HOST_CAS_OBJECT") + if (cas.get("schema_version") != "stage2_s2_40_host_cas_receipt.v1" + or cas.get("run_binding_digest") != request["run_binding_digest"] + or cas.get("stage_id") != "S2_40" + or cas.get("candidate_attempt_id") != request["candidate_attempt_id"] + or cas.get("requested_transition") != request["requested_transition"] + or cas.get("expected_previous_run_status_sha256") != request["expected_previous_run_status_sha256"] + or cas.get("lease_status") != "ACQUIRED" + or HEX64.fullmatch(str(cas.get("signature_attestation", ""))) is None): + raise S240Error("HOST_CAS_NOT_BOUND", "host CAS receipt does not bind request transition") + try: + issued = datetime.fromisoformat(str(cas.get("issued_at")).replace("Z", "+00:00")) + expires = datetime.fromisoformat(str(cas.get("expires_at")).replace("Z", "+00:00")) + now = datetime.now(timezone.utc) + if issued.tzinfo is None or expires.tzinfo is None or issued > now or expires <= now or expires <= issued: + raise S240Error("HOST_CAS_TIME", "host CAS lease is not currently valid") + except (TypeError, ValueError) as exc: + raise S240Error("HOST_CAS_TIME", "host CAS timestamps are invalid") from exc + snapshot_rows.append({"path": MODULE_MANIFEST_PATH, "sha256": digest(module_raw), "size": len(module_raw)}) + return digest(snapshot_rows) + + + def load_output_schema_store(client: McpClient) -> dict[str, Mapping[str, Any]]: + values, _, _ = read_release_bound_jsons(client, INPUT_SCHEMA_RELS) + return {path: value for path, value in values.items() if path.startswith("schemas/")} + + + def write_terminal_status( + client: McpClient, + request: Mapping[str, Any], + *, + workflow_phase: str, + route: str, + candidate_content_digest: str | None, + run_technical_status: str, + artifact_technical_status: str, + legal_readiness: str, + validation_report_sha256: str | None = None, + review_subject_digest: str | None = None, + review_receipt_sha256s: Sequence[str] = (), + stage2_package_sha256: str | None = None, + artifact_set_digest: str | None = None, + commit_intent_sha256: str | None = None, + commit_result_sha256: str | None = None, + emit_status_event: bool = True, + schema_store: Mapping[str, Mapping[str, Any]] | None = None, + ) -> dict[str, Any]: + """Write one immutable transition event and the latest barrier last.""" + output_schemas = dict(schema_store) if schema_store is not None else load_output_schema_store(client) + root = request["stage2_run_root_ref"] + event_core = { + "schema_version": "stage2_s2_40_status_event.v1", + "writer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "workflow_phase": workflow_phase, "route": route, + "candidate_content_digest": candidate_content_digest, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "request_sha256": require_hex(request.get("_request_sha256"), code="REQUEST_RAW_HASH"), + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + } + event_raw_hash: str | None = None + if emit_status_event: + event = {**event_core, "event_digest": digest(event_core)} + validate_schema_instance( + event, "schemas/review_status.schema.json#/$defs/status_event", + output_schemas, code="GENERATED_STATUS_EVENT_SCHEMA", + ) + event_payload = canonical_bytes(event) + event_path = join_path(root, "control/status_events", f"{event['event_digest']}.json") + event_raw_hash = client.write_immutable(event_path, event_payload) + status = { + "schema_version": "stage2_s2_40_run_status.v1", "writer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "entry_route": request["entry_route"], "compile_mode": request["compile_mode"], + "workflow_phase": workflow_phase, "route": route, + "candidate_content_digest": candidate_content_digest, + "run_technical_status": run_technical_status, + "artifact_technical_status": artifact_technical_status, + "legal_readiness": legal_readiness, + "validation_report_sha256": validation_report_sha256, + "review_subject_digest": review_subject_digest, + "review_receipt_sha256s": sorted(set(review_receipt_sha256s)), + "stage2_package_sha256": stage2_package_sha256, + "artifact_set_digest": artifact_set_digest, + "commit_intent_sha256": commit_intent_sha256, + "commit_result_sha256": commit_result_sha256, + "request_sha256": request["_request_sha256"], + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + "outer_execution_receipt_sha256": None, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "status_event_sha256": event_raw_hash, + "barrier_written_last": True, "readback_verified": True, + } + validate_schema_instance( + status, "schemas/review_status.schema.json#/$defs/run_status", + output_schemas, code="GENERATED_RUN_STATUS_SCHEMA", + ) + status_payload = canonical_bytes(status) + status_path = join_path(root, "control/run_status.json") + status_hash = client.write_latest( + status_path, status_payload, request["expected_previous_run_status_sha256"], + ) + return {"status": status, "status_sha256": status_hash, "status_path": status_path} + + + def ingress_schema_ref(path: str) -> str: + exact = { + "ingress/stage1_input_manifest.json": "schemas/ingress.schema.json#/$defs/stage1_input_manifest", + "ingress/intake_report.json": "schemas/ingress.schema.json#/$defs/intake_report", + "ingress/technical_diagnostic.json": "schemas/ingress.schema.json#/$defs/technical_diagnostic", + "context/case_context.json": "schemas/context.schema.json#/$defs/case_context", + "context/evidence_inventory.json": "schemas/context.schema.json#/$defs/evidence_inventory", + "context/object_registry.json": "schemas/context.schema.json#/$defs/object_registry", + "context/party_and_title_context.json": "schemas/context.schema.json#/$defs/party_and_title_context", + "context/slot_crosswalk.json": "schemas/context.schema.json#/$defs/slot_crosswalk", + "context/cluster_plan.json": "schemas/context.schema.json#/$defs/cluster_plan", + "context/bundle_plan.json": "schemas/context.schema.json#/$defs/bundle_plan", + "review/issue_ledger.base.json": "schemas/review_status.schema.json#/$defs/issue_ledger_base", + } + if path in exact: + return exact[path] + if re.fullmatch(r"context/cluster_slices/[A-Za-z0-9][A-Za-z0-9._:-]{0,255}\.json", path): + return "schemas/context.schema.json#/$defs/cluster_slice" + raise S240Error("INGRESS_ARTIFACT_PATH", f"unrecognized ingress artifact path: {path}") + + + def hydrate_ingress_barrier_artifacts( + client: McpClient, + root: str, + ingress: Mapping[str, Any], + schema_store: Mapping[str, Mapping[str, Any]], + *, + exact_paths: set[str] | None = None, + ) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], list[dict[str, Any]]]: + barrier = require_object(ingress.get("output_barrier"), code="INGRESS_OUTPUT_BARRIER") + rows = require_list(barrier.get("artifacts"), code="INGRESS_OUTPUT_ROWS") + if barrier.get("artifact_set_digest") != digest(rows): + raise S240Error("INGRESS_OUTPUT_SET_DIGEST", "ingress artifact-set digest differs") + paths = [safe_path(row.get("path"), code="INGRESS_OUTPUT_PATH") for row in rows if isinstance(row, dict)] + if len(paths) != len(rows) or len(paths) != len(set(paths)) or paths != sorted(paths): + raise S240Error("INGRESS_OUTPUT_SET", "ingress artifact rows must be unique and sorted") + if exact_paths is not None and set(paths) != exact_paths: + raise S240Error("INGRESS_OUTPUT_EXACT_SET", "ingress barrier does not bind the exact expected paths") + values: dict[str, dict[str, Any]] = {} + raws: dict[str, bytes] = {} + normalized_rows: list[dict[str, Any]] = [] + for row in rows: + row = require_object(row, code="INGRESS_OUTPUT_ROW") + path = safe_path(row.get("path"), code="INGRESS_OUTPUT_PATH") + if row.get("logical_artifact_id") != path: + raise S240Error("INGRESS_OUTPUT_LOGICAL_ID", "logical artifact id must equal canonical path") + schema_ref = ingress_schema_ref(path) + schema_path = schema_ref.split("#", 1)[0] + if row.get("schema_id") != schema_store[schema_path].get("$id"): + raise S240Error("INGRESS_OUTPUT_SCHEMA_ID", f"schema id differs: {path}") + raw_a = client.read_binary(join_path(root, path)) + raw_b = client.read_binary(join_path(root, path)) + if raw_a != raw_b: + raise S240Error("INGRESS_OUTPUT_TOCTOU", f"ingress artifact changed between reads: {path}") + if digest(raw_a) != require_hex(row.get("raw_sha256"), code="INGRESS_OUTPUT_HASH"): + raise S240Error("INGRESS_OUTPUT_HASH", f"ingress artifact hash differs: {path}") + if row.get("byte_length", len(raw_a)) != len(raw_a): + raise S240Error("INGRESS_OUTPUT_SIZE", f"ingress artifact size differs: {path}") + value = require_object(load_json(raw_a, label=path), code="INGRESS_OUTPUT_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="INGRESS_OUTPUT_SCHEMA") + values[path] = value + raws[path] = raw_a + normalized_rows.append({ + "path": path, "raw_sha256": digest(raw_a), "byte_length": len(raw_a), + "schema_id": row.get("schema_id"), "schema_ref": schema_ref, + }) + return values, raws, normalized_rows + + + def status_only(client: McpClient, request: Mapping[str, Any], preflight_digest: str) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + schema_values, _, schema_rows = read_release_bound_jsons(client, INPUT_SCHEMA_RELS) + schema_store: dict[str, Mapping[str, Any]] = dict(schema_values) + rels_and_refs = ( + ("ingress/ingress_status.json", "schemas/ingress.schema.json#/$defs/ingress_status"), + ("ingress/technical_diagnostic.json", "schemas/ingress.schema.json#/$defs/technical_diagnostic"), + ("ingress/stage1_input_manifest.json", "schemas/ingress.schema.json#/$defs/stage1_input_manifest"), + ("ingress/intake_report.json", "schemas/ingress.schema.json#/$defs/intake_report"), + ("review/issue_ledger.base.json", "schemas/review_status.schema.json#/$defs/issue_ledger_base"), + ) + rows: list[dict[str, Any]] = [] + values: dict[str, dict[str, Any]] = {} + for rel, schema_ref in rels_and_refs: + path = join_path(root, rel) + raw = client.read_binary(path) + if rel == "ingress/ingress_status.json" and digest(raw) != request["expected_ingress_status_sha256"]: + raise S240Error("STATUS_ONLY_INGRESS_HASH", "ingress status hash mismatch") + value = require_object(load_json(raw, label=path), code="STATUS_ONLY_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="STATUS_ONLY_SCHEMA") + values[rel] = value + rows.append({ + "path": rel, "sha256": digest(raw), "size": len(raw), + "schema_ref": schema_ref, "schema_version": value.get("schema_version"), + }) + ingress = values["ingress/ingress_status.json"] + diagnostic = values["ingress/technical_diagnostic.json"] + manifest = values["ingress/stage1_input_manifest.json"] + intake = values["ingress/intake_report.json"] + ledger = values["review/issue_ledger.base.json"] + run_receipt = require_object(ingress.get("run_binding_receipt"), code="STATUS_ONLY_RUN_RECEIPT") + run_id = ingress.get("run_id") + input_set_digest = manifest.get("input_set_digest") + if ( + ingress.get("route") != "TO_S2_40_STATUS_ONLY" + or require_object(ingress.get("output_barrier"), code="STATUS_ONLY_BARRIER").get("branch") != "DIAGNOSTIC" + or ingress["output_barrier"].get("written_last") is not True + or diagnostic.get("route") != "TO_S2_40_STATUS_ONLY" + or diagnostic.get("context_published") is not False + or diagnostic.get("minimum_coherent_package_possible") is not False + or intake.get("minimum_coherent_package_possible") is not False + ): + raise S240Error("STATUS_ONLY_ROUTE_CONTRACT", "diagnostic route semantics differ") + if ( + run_receipt.get("run_binding_digest") != request["run_binding_digest"] + or run_receipt.get("stage2_release_digest") != EXPECTED_STAGE2_RELEASE_SHA256 + or run_receipt.get("run_id") != run_id + or run_receipt.get("input_set_digest") != input_set_digest + or manifest.get("run_id") != run_id + or intake.get("run_id") != run_id + or diagnostic.get("run_id") != run_id + or ledger.get("run_id") != run_id + or ledger.get("producer_id") != "S2_00" + or ledger.get("input_set_digest") != input_set_digest + ): + raise S240Error("STATUS_ONLY_CROSS_BINDING", "exact-five inputs do not bind one run/input/release") + if set(diagnostic.get("reason_codes", [])) - set(ingress.get("issue_codes", [])): + raise S240Error("STATUS_ONLY_REASON_CONSERVATION", "diagnostic reasons are absent from ingress issue codes") + _, barrier_raws, barrier_rows = hydrate_ingress_barrier_artifacts( + client, root, ingress, schema_store, + exact_paths={ + "ingress/technical_diagnostic.json", "ingress/stage1_input_manifest.json", + "ingress/intake_report.json", "review/issue_ledger.base.json", + }, + ) + for row in rows[1:]: + if barrier_raws.get(row["path"]) is None or digest(barrier_raws[row["path"]]) != row["sha256"]: + raise S240Error("STATUS_ONLY_BARRIER_BINDING", f"barrier/raw mismatch: {row['path']}") + status_only_digest = digest({ + "domain_separator": "STAGE2_S2_40_STATUS_ONLY_EXACT_FIVE_V1", + "preflight_snapshot_digest": preflight_digest, + "run_id": run_id, "input_set_digest": input_set_digest, + "input_rows": rows, "barrier_rows": barrier_rows, + "release_schema_rows": schema_rows, + }) + return write_terminal_status( + client, request, + workflow_phase="DIAGNOSTIC_ONLY", route="STOP_TECHNICAL_INCOMPLETE", + candidate_content_digest=None, run_technical_status="TECHNICAL_INCOMPLETE", + artifact_technical_status="NOT_PRODUCED", legal_readiness="NOT_ASSESSED", + validation_report_sha256=status_only_digest, + emit_status_event=False, + schema_store=schema_store, + ) + + + def require_self_hash(value: Mapping[str, Any], field: str, *, code: str) -> None: + observed = require_hex(value.get(field), code=code) + material = {key: item for key, item in value.items() if key != field} + if observed != digest(material): + raise S240Error(code, f"self hash mismatch: {field}") + + + def hydrate_s210_artifacts( + client: McpClient, + root: str, + ingress: Mapping[str, Any], + ingress_documents: Mapping[str, Mapping[str, Any]], + ingress_raws: Mapping[str, bytes], + s210: Mapping[str, Any], + request: Mapping[str, Any], + schema_store: Mapping[str, Mapping[str, Any]], + ) -> dict[str, Any]: + """Hydrate the exact S2_10 universe named by the S2_00 plans.""" + cluster_plan = require_object( + ingress_documents.get("context/cluster_plan.json"), code="S210_CLUSTER_PLAN", + ) + bundle_plan = require_object( + ingress_documents.get("context/bundle_plan.json"), code="S210_BUNDLE_PLAN", + ) + cluster_ids = [ + require_ident(value, code="S210_CLUSTER_ID") + for value in require_list(cluster_plan.get("executable_cluster_ids"), code="S210_CLUSTER_IDS") + ] + if ( + cluster_ids != sorted(cluster_ids) + or len(cluster_ids) != len(set(cluster_ids)) + or cluster_ids != ingress.get("executable_cluster_ids") + or sorted(s210.get("expected_executable_cluster_ids", [])) != cluster_ids + or sorted(s210.get("valid_domain_verdict_cluster_ids", [])) != cluster_ids + or s210.get("terminal_technical_failure_cluster_ids") != [] + ): + raise S240Error("S210_CLUSTER_CLOSURE", "S2_00/S2_10 executable cluster sets differ") + + wave_by_cluster: dict[str, int] = {} + for cohort in require_list(bundle_plan.get("cohorts"), code="S210_BUNDLE_COHORTS"): + cohort = require_object(cohort, code="S210_BUNDLE_COHORT") + if cohort.get("cohort_status") != "EXECUTABLE": + continue + members = require_list(cohort.get("member_slices"), code="S210_BUNDLE_MEMBERS") + for member in members: + member = require_object(member, code="S210_BUNDLE_MEMBER") + cluster_id = require_ident(member.get("cluster_id"), code="S210_BUNDLE_CLUSTER") + ordinal = member.get("dependency_wave_ordinal") + if cluster_id in wave_by_cluster or cluster_id not in cluster_ids or not isinstance(ordinal, int) or ordinal < 0: + raise S240Error("S210_BUNDLE_WAVE", "bundle member/wave mapping is not exact") + expected_slice = f"context/cluster_slices/{cluster_id}.json" + if ( + member.get("path") != expected_slice + or member.get("sha256") != digest(ingress_raws[expected_slice]) + ): + raise S240Error("S210_BUNDLE_SLICE", f"bundle slice hash differs: {cluster_id}") + wave_by_cluster[cluster_id] = ordinal + if set(wave_by_cluster) != set(cluster_ids): + raise S240Error("S210_BUNDLE_COVERAGE", "bundle does not cover the exact executable cluster set") + wave_ordinals = sorted(set(wave_by_cluster.values())) + if wave_ordinals != list(range(len(wave_ordinals))): + raise S240Error("S210_WAVE_ORDINALS", "dependency-wave ordinals are not contiguous from zero") + + def stable_json(path: str, schema_ref: str) -> tuple[dict[str, Any], bytes]: + raw_a = client.read_binary(join_path(root, path)) + raw_b = client.read_binary(join_path(root, path)) + if raw_a != raw_b: + raise S240Error("S210_TOCTOU", f"S2_10 artifact changed between reads: {path}") + value = require_object(load_json(raw_a, label=path), code="S210_ARTIFACT_OBJECT") + validate_schema_instance(value, schema_ref, schema_store, code="S210_ARTIFACT_SCHEMA") + closure_rows.append({ + "path": path, "sha256": digest(raw_a), "expected_sha256": digest(raw_a), + "schema_ref": schema_ref, "schema_version": value.get("schema_version"), + "producer_id": value.get("producer_id", "S2_10"), + "schema_valid": True, "hash_match": True, + }) + return value, raw_a + + verdicts: dict[str, dict[str, Any]] = {} + item_receipts: dict[str, dict[str, Any]] = {} + issue_parts: dict[str, dict[str, Any]] = {} + assumption_parts: dict[str, dict[str, Any]] = {} + usage_parts: dict[str, dict[str, Any]] = {} + raw_by_path: dict[str, bytes] = {} + closure_rows: list[dict[str, Any]] = [] + request_ids: set[str] = set() + producer_contract_digests: set[str] = set() + for cluster_id in cluster_ids: + paths = { + "verdict": f"map_s2_10/domain_verdicts/{cluster_id}.json", + "item": f"map_s2_10/item_receipts/{cluster_id}.json", + "issue": f"map_s2_10/issue_patches/{cluster_id}.json", + "assumption": f"map_s2_10/assumption_parts/{cluster_id}.json", + "usage": f"map_s2_10/usage_parts/{cluster_id}.json", + } + verdict, verdict_raw = stable_json(paths["verdict"], "schemas/s2_10.schema.json#/$defs/canonical_domain_verdict") + item, item_raw = stable_json(paths["item"], "schemas/s2_10.schema.json#/$defs/item_receipt") + issue, issue_raw = stable_json(paths["issue"], "schemas/s2_10.schema.json#/$defs/issue_part") + assumption, assumption_raw = stable_json(paths["assumption"], "schemas/s2_10.schema.json#/$defs/assumption_part") + usage, usage_raw = stable_json(paths["usage"], "schemas/s2_10.schema.json#/$defs/usage_part") + require_self_hash(verdict, "domain_verdict_sha256", code="S210_VERDICT_SELF_HASH") + require_self_hash(item, "receipt_sha256", code="S210_ITEM_SELF_HASH") + for part, label in ((issue, "ISSUE"), (assumption, "ASSUMPTION"), (usage, "USAGE")): + require_self_hash(part, "part_sha256", code=f"S210_{label}_SELF_HASH") + producer_contract_digest = require_hex( + verdict.get("producer_contract_digest"), code="S210_PRODUCER_CONTRACT", + ) + producer_contract_digests.add(producer_contract_digest) + verdict_hash = verdict["domain_verdict_sha256"] + if ( + verdict.get("cluster_id") != cluster_id + or verdict.get("run_binding_digest") != request["run_binding_digest"] + or verdict.get("cluster_slice_sha256") != digest(ingress_raws[f"context/cluster_slices/{cluster_id}.json"]) + or verdict.get("wave_ordinal") != wave_by_cluster[cluster_id] + or item.get("cluster_id") != cluster_id + or item.get("run_binding_digest") != request["run_binding_digest"] + or item.get("domain_verdict_path") != paths["verdict"] + or item.get("domain_verdict_sha256") != verdict_hash + or item.get("read_back_sha256") != verdict_hash + or item.get("request_id") != verdict.get("request_id") + or item.get("wave_ordinal") != verdict.get("wave_ordinal") + or item.get("attempt_no") != verdict.get("attempt_no") + or item.get("raw_model_output_sha256") != verdict.get("raw_model_output_sha256") + or item.get("validation_status") != "PASS" + or item.get("persistence_status") not in {"PUBLISHED", "IDEMPOTENT_BYTE_IDENTICAL"} + ): + raise S240Error("S210_ITEM_LINK", f"S2_10 verdict/item link differs: {cluster_id}") + for part, expected_hash, label in ( + (issue, item.get("issue_part_sha256"), "ISSUE"), + (assumption, item.get("assumption_part_sha256"), "ASSUMPTION"), + (usage, item.get("usage_part_sha256"), "USAGE"), + ): + header = require_object(part.get("header"), code=f"S210_{label}_HEADER") + if ( + part.get("part_sha256") != expected_hash + or header.get("producer_contract_digest") != producer_contract_digest + or header.get("request_id") != item.get("request_id") + or header.get("run_binding_digest") != request["run_binding_digest"] + or header.get("wave_ordinal") != item.get("wave_ordinal") + or header.get("attempt_no") != item.get("attempt_no") + or header.get("cluster_id") != cluster_id + or header.get("domain_verdict_sha256") != verdict_hash + ): + raise S240Error(f"S210_{label}_LINK", f"S2_10 {label.lower()} part link differs: {cluster_id}") + if assumption.get("assumptions") != verdict.get("assumptions"): + raise S240Error("S210_ASSUMPTION_CONTENT", f"assumption part differs from verdict: {cluster_id}") + request_ids.add(str(item.get("request_id"))) + verdicts[cluster_id] = verdict + item_receipts[cluster_id] = item + issue_parts[cluster_id] = issue + assumption_parts[cluster_id] = assumption + usage_parts[cluster_id] = usage + raw_by_path.update({ + paths["verdict"]: verdict_raw, paths["item"]: item_raw, + paths["issue"]: issue_raw, paths["assumption"]: assumption_raw, + paths["usage"]: usage_raw, + }) + if len(request_ids) != 1 or len(producer_contract_digests) != 1: + raise S240Error("S210_REQUEST_PRODUCER_SET", "S2_10 items do not share one request/producer contract") + + wave_receipts: list[dict[str, Any]] = [] + covered: set[str] = set() + for ordinal in wave_ordinals: + path = f"map_s2_10/wave_receipts/wave-{ordinal:04d}.json" + wave, raw = stable_json(path, "schemas/s2_10.schema.json#/$defs/wave_receipt") + require_self_hash(wave, "receipt_sha256", code="S210_WAVE_SELF_HASH") + expected_clusters = sorted(key for key, value in wave_by_cluster.items() if value == ordinal) + if ( + wave.get("request_id") not in request_ids + or wave.get("run_binding_digest") != request["run_binding_digest"] + or wave.get("wave_ordinal") != ordinal + or wave.get("is_final_wave") != (ordinal == wave_ordinals[-1]) + or sorted(wave.get("expected_wave_cluster_ids", [])) != expected_clusters + or sorted(wave.get("valid_domain_verdict_cluster_ids", [])) != expected_clusters + or wave.get("terminal_technical_failure_cluster_ids") != [] + or wave.get("wave_status") != "WAVE_COMPLETE" + or wave.get("route") != ("TO_S2_20" if ordinal == wave_ordinals[-1] else "NEXT_WAVE") + or wave.get("written_once") is not True + ): + raise S240Error("S210_WAVE_LINK", f"S2_10 wave receipt differs: {ordinal}") + covered.update(expected_clusters) + wave_receipts.append(wave) + raw_by_path[path] = raw + if covered != set(cluster_ids) or s210.get("terminal_wave_receipt_sha256s") != [ + row["receipt_sha256"] for row in wave_receipts + ]: + raise S240Error("S210_WAVE_CLOSURE", "S2_10 terminal wave receipt closure differs") + return { + "cluster_ids": cluster_ids, "verdicts": verdicts, + "item_receipts": item_receipts, "issue_parts": issue_parts, + "assumption_parts": assumption_parts, "usage_parts": usage_parts, + "wave_receipts": wave_receipts, "raw_by_path": raw_by_path, + "source_rows": [ + {"path": path, "sha256": digest(raw), "ref_family": "s2_10_runtime"} + for path, raw in sorted(raw_by_path.items()) + ], + "closure_rows": sorted(closure_rows, key=lambda row: row["path"]), + } + + + def validate_handoff_provenance( + value: Any, *, common_only: bool, expected_mode: str, code: str, + ) -> dict[str, Any]: + row = require_object(value, code=code) + expected = COMMON_PROVENANCE_FIELDS if common_only else GROUP_PROVENANCE_FIELDS + if set(row) != expected: + raise S240Error(code, "handoff provenance is not closed", details=sorted(set(row) ^ expected)) + if row.get("compile_mode") != expected_mode: + raise S240Error("COMPILE_MODE_DRIFT", "handoff compile mode differs") + for key in expected - {"compile_mode"}: + require_hex(row.get(key), code=code) + return row + + + def common_provenance(value: Mapping[str, Any]) -> dict[str, Any]: + return {key: value[key] for key in sorted(COMMON_PROVENANCE_FIELDS)} + + + def artifact_rows(manifest: Mapping[str, Any]) -> list[dict[str, Any]]: + rows = require_list(manifest.get("part_rows"), code="S230_MANIFEST_ROWS") + if len(rows) > MAX_ARTIFACT_ROWS: + raise S240Error("S230_MANIFEST_LIMIT", "too many artifact rows") + result: list[dict[str, Any]] = [] + seen_pairs: set[tuple[str, str]] = set() + seen_paths: set[str] = set() + for value in rows: + row = require_object(value, code="S230_MANIFEST_ROW") + if set(row) != {"claim_group_id", "part_family", "path", "sha256", "schema_ref"}: + raise S240Error("S230_MANIFEST_ROW_SHAPE", "manifest row is not closed") + group_id = require_ident(row.get("claim_group_id"), code="S230_MANIFEST_GROUP") + family = row.get("part_family") + if family not in PART_FAMILIES: + raise S240Error("S230_MANIFEST_KIND", f"unsupported part family: {family}") + path = safe_path(row.get("path"), code="S230_MANIFEST_PATH") + expected_path = f"map_s2_30/{PART_DIRECTORIES[family]}/{group_id}.json" + if path != expected_path or row.get("schema_ref") != PART_SCHEMA_REFS[family]: + raise S240Error("S230_MANIFEST_BINDING", "part path/schema differs from canonical binding") + pair = (group_id, family) + if pair in seen_pairs or path in seen_paths: + raise S240Error("S230_MANIFEST_DUPLICATE", "duplicate part pair/path") + seen_pairs.add(pair) + seen_paths.add(path) + result.append({ + "path": path, + "sha256": require_hex(row.get("sha256"), code="S230_MANIFEST_HASH"), + "schema_ref": row["schema_ref"], + "part_family": family, + "claim_group_id": group_id, + }) + if result != sorted(result, key=lambda row: (row["claim_group_id"], row["part_family"], row["path"])): + raise S240Error("S230_MANIFEST_ORDER", "part rows must be canonically sorted") + return result + + + def plan_artifact_rows(plan: Mapping[str, Any]) -> list[dict[str, Any]]: + rows = require_list(plan.get("artifact_rows"), code="S220_ARTIFACT_ROWS") + result: list[dict[str, Any]] = [] + seen: set[str] = set() + for value in rows: + row = require_object(value, code="S220_ARTIFACT_ROW") + path = safe_path(row.get("path"), code="S220_ARTIFACT_PATH") + if path in seen: + raise S240Error("S220_ARTIFACT_DUPLICATE", f"duplicate plan artifact: {path}") + seen.add(path) + result.append({ + "path": path, + "schema_ref": row.get("schema_ref"), + "raw_sha256": require_hex(row.get("raw_sha256"), code="S220_ARTIFACT_HASH"), + "byte_size": row.get("byte_size"), + "producer_component": row.get("producer_component"), + }) + if result != sorted(result, key=lambda row: row["path"]): + raise S240Error("S220_ARTIFACT_ORDER", "plan artifact rows must be sorted") + if plan.get("artifact_set_digest") != digest(result): + raise S240Error("S220_ARTIFACT_SET_DIGEST", "plan artifact set digest mismatch") + return result + + + def read_plan_artifacts( + client: McpClient, root: str, plan: Mapping[str, Any], total: int, + schema_store: Mapping[str, Mapping[str, Any]], + ) -> tuple[dict[str, dict[str, Any]], dict[str, bytes], int]: + rows = plan_artifact_rows(plan) + documents: dict[str, dict[str, Any]] = {} + raw_by_path: dict[str, bytes] = {} + for row in rows: + value, raw = read_bound_json(client, join_path(root, row["path"]), row["raw_sha256"]) + if isinstance(row.get("schema_ref"), str) and row["schema_ref"].startswith("schemas/"): + validate_schema_instance(value, row["schema_ref"], schema_store, code="S220_ARTIFACT_SCHEMA") + if row["byte_size"] != len(raw): + raise S240Error("S220_ARTIFACT_SIZE", f"plan artifact size mismatch: {row['path']}") + total += len(raw) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + documents[row["path"]] = value + raw_by_path[row["path"]] = raw + return documents, raw_by_path, total + + + def resolve_frozen_ref( + client: McpClient, + root: str, + plan_rows: Mapping[str, bytes], + ref: Mapping[str, Any], + *, + code: str, + ) -> tuple[dict[str, Any], bytes, str]: + relative = safe_path(ref.get("path"), code=code) + expected = require_hex(ref.get("sha256"), code=code) + plan_path = relative if relative.startswith("plan/") else f"plan/{relative}" + if plan_path in plan_rows: + raw = plan_rows[plan_path] + if digest(raw) != expected: + raise S240Error(code, f"frozen plan ref hash mismatch: {relative}") + return require_object(load_json(raw, label=plan_path), code=code), raw, plan_path + asset_path = relative if relative.startswith(f"{ASSET_ROOT}/") else join_path(ASSET_ROOT, relative) + value, raw = read_bound_json(client, asset_path, expected) + return value, raw, asset_path + + + def hydrate_normal(client: McpClient, request: Mapping[str, Any]) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + ingress, ingress_raw = read_bound_json(client, join_path(root, "ingress/ingress_status.json"), request["expected_ingress_status_sha256"]) + s210, s210_raw = read_bound_json(client, join_path(root, "map_s2_10/s2_10_publish_status.json"), request["expected_s2_10_publish_status_sha256"]) + plan, plan_raw = read_bound_json(client, join_path(root, "plan/plan_publish_status.json"), request["expected_plan_publish_status_sha256"]) + s230, s230_raw = read_bound_json(client, join_path(root, "map_s2_30/s2_30_publish_status.json"), request["expected_s2_30_publish_status_sha256"]) + manifest_path = join_path(root, "map_s2_30/artifact_manifest.json") + manifest, manifest_raw = read_bound_json(client, manifest_path, request["expected_s2_30_artifact_manifest_sha256"]) + release_values, release_raws, release_rows = read_release_bound_jsons( + client, ( + *INPUT_SCHEMA_RELS, AUTHORITY_RELEASE_REL, CASE_TYPE_COVERAGE_REL, + CASE_TYPE_REGISTRY_REL, CASE_TYPE_RULE_REGISTRY_REL, + ), + ) + schema_store: dict[str, Mapping[str, Any]] = { + path: value for path, value in release_values.items() if path.startswith("schemas/") + } + validate_schema_instance(ingress, "schemas/ingress.schema.json#/$defs/ingress_status", schema_store, code="V01_INGRESS_SCHEMA") + validate_schema_instance(s210, "schemas/s2_10.schema.json#/$defs/global_publish_status", schema_store, code="V01_S210_SCHEMA") + validate_schema_instance(plan, "schemas/relief_plan.schema.json#/$defs/plan_publish_status", schema_store, code="V01_S220_SCHEMA") + validate_schema_instance(s230, "schemas/draft_atoms.schema.json#/$defs/publish_status", schema_store, code="V01_S230_SCHEMA") + validate_schema_instance(manifest, "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", schema_store, code="V01_S230_MANIFEST_SCHEMA") + executable_cluster_ids = [ + require_ident(value, code="INGRESS_EXECUTABLE_CLUSTER") + for value in require_list(ingress.get("executable_cluster_ids"), code="INGRESS_EXECUTABLE_CLUSTERS") + ] + normal_ingress_paths = { + "ingress/stage1_input_manifest.json", "ingress/intake_report.json", + "context/case_context.json", "context/evidence_inventory.json", + "context/object_registry.json", "context/party_and_title_context.json", + "context/slot_crosswalk.json", "context/cluster_plan.json", + "context/bundle_plan.json", "review/issue_ledger.base.json", + *{f"context/cluster_slices/{cluster_id}.json" for cluster_id in executable_cluster_ids}, + } + ingress_documents, ingress_raws, ingress_artifact_rows = hydrate_ingress_barrier_artifacts( + client, root, ingress, schema_store, exact_paths=normal_ingress_paths, + ) + ingress_barrier = require_object(ingress.get("output_barrier"), code="INGRESS_NORMAL_BARRIER") + if ( + ingress_barrier.get("branch") != "NORMAL" + or ingress_barrier.get("written_last") is not True + or ingress_barrier.get("non_status_artifacts_read_back_verified", True) is not True + or ingress_documents["context/cluster_plan.json"].get("executable_cluster_ids") != executable_cluster_ids + ): + raise S240Error("INGRESS_NORMAL_CLOSURE", "normal ingress barrier/context closure differs") + ingress_receipt = require_object(ingress.get("run_binding_receipt"), code="V01_INGRESS_RUN_BINDING") + if ( + ingress.get("route") not in {"TO_S2_10", "TO_S2_10_WITH_ISSUES"} + or ingress_receipt.get("run_binding_digest") != request["run_binding_digest"] + or ingress_receipt.get("stage2_release_digest") != EXPECTED_STAGE2_RELEASE_SHA256 + or s210.get("producer_id") != "S2_10_NATIVE_RESULT_ADAPTER" + or s210.get("run_binding_digest") != request["run_binding_digest"] + or s210.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or s210.get("status") != "COMPLETE" or s210.get("route") != "TO_S2_20" + or s210.get("status_written_last") is not True + or plan.get("workflow_id") != "S2_20" + or plan.get("run_binding_digest") != request["run_binding_digest"] + or plan.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or plan.get("s2_10_publish_status_sha256") != request["expected_s2_10_publish_status_sha256"] + or s230.get("run_binding_digest") != request["run_binding_digest"] + or s230.get("parent_stage2_release_sha256") != EXPECTED_STAGE2_RELEASE_SHA256 + or manifest.get("run_binding_digest") != request["run_binding_digest"] + ): + raise S240Error("V01_INPUT_LINEAGE", "normal barriers do not share exact producer/run/release lineage") + require_self_hash(s210, "status_sha256", code="S210_STATUS_SELF_HASH") + s210_handoff = hydrate_s210_artifacts( + client, root, ingress, ingress_documents, ingress_raws, + s210, request, schema_store, + ) + require_self_hash(plan, "barrier_sha256", code="S220_STATUS_SELF_HASH") + if plan.get("plan_status") == "TECHNICAL_INCOMPLETE" or plan.get("route") != "TO_S2_30" or plan.get("consumer_authorized") is not True: + raise S240Error("S220_BARRIER_NOT_CONSUMABLE", "S2_20 barrier is not consumer-authorized") + if s230.get("status") != "S2_30_COMPLETE" or s230.get("route") != "TO_S2_40" or s230.get("status_written_last") is not True: + raise S240Error("S230_BARRIER_NOT_CONSUMABLE", "S2_30 barrier is not complete") + require_self_hash(s230, "status_sha256", code="S230_STATUS_SELF_HASH") + require_self_hash(manifest, "part_manifest_core_sha256", code="S230_MANIFEST_SELF_HASH") + common = validate_handoff_provenance( + manifest.get("provenance"), common_only=True, + expected_mode=request["compile_mode"], code="S230_COMMON_PROVENANCE", + ) + if s230.get("compile_mode") != request["compile_mode"] or s230.get("provenance") != common: + raise S240Error("COMPILE_MODE_DRIFT", "S2_30 barrier/manifest mode or provenance differs") + if ( + s230.get("artifact_manifest_path") != "map_s2_30/artifact_manifest.json" + or s230.get("artifact_manifest_schema_ref") != "schemas/draft_atoms.schema.json#/$defs/part_manifest_core" + or s230.get("artifact_manifest_sha256") != digest(manifest_raw) + ): + raise S240Error("S230_BARRIER_MANIFEST", "S2_30 barrier does not bind exact manifest bytes") + expected_groups = require_list(manifest.get("expected_claim_group_ids"), code="S230_EXPECTED_GROUPS") + if expected_groups != sorted(expected_groups) or len(expected_groups) != len(set(expected_groups)): + raise S240Error("S230_EXPECTED_GROUP_ORDER", "manifest group ids must be unique and sorted") + if ( + s230.get("expected_claim_group_ids") != expected_groups + or s230.get("published_claim_group_ids") != expected_groups + or s230.get("terminal_failure_claim_group_ids") != [] + ): + raise S240Error("S230_GROUP_SET", "publish expected/published group set differs") + if sorted(plan.get("group_ids", [])) != expected_groups: + raise S240Error("S220_S230_GROUP_SET", "S2_20 and S2_30 group sets differ") + rows = artifact_rows(manifest) + expected_pairs = {(group_id, family) for group_id in expected_groups for family in PART_FAMILIES} + if {(row["claim_group_id"], row["part_family"]) for row in rows} != expected_pairs: + raise S240Error("S230_PART_COVERAGE", "manifest must contain exactly four part families per group") + parts: dict[str, list[dict[str, Any]]] = {family: [] for family in PART_FAMILIES} + group_provenance: dict[str, dict[str, Any]] = {} + total = ( + sum(len(raw) for raw in (ingress_raw, s210_raw, plan_raw, s230_raw, manifest_raw)) + + sum(len(raw) for raw in release_raws.values()) + + sum(len(raw) for raw in ingress_raws.values()) + + sum(len(raw) for raw in s210_handoff["raw_by_path"].values()) + ) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + for row in rows: + value, raw = read_bound_json(client, join_path(root, row["path"]), row["sha256"]) + validate_schema_instance(value, row["schema_ref"], schema_store, code="S230_PART_SCHEMA") + total += len(raw) + if total > MAX_TOTAL_BYTES: + raise S240Error("TOTAL_INPUT_LIMIT", "input bytes exceed limit") + require_self_hash(value, "part_sha256", code="S230_PART_SELF_HASH") + provenance = validate_handoff_provenance( + value.get("provenance"), common_only=False, + expected_mode=request["compile_mode"], code="S230_GROUP_PROVENANCE", + ) + if common_provenance(provenance) != common: + raise S240Error("S230_PART_COMMON_PROVENANCE", "part common provenance differs") + if value.get("claim_group_id") != row["claim_group_id"]: + raise S240Error("S230_PART_GROUP", "part group mismatch") + prior = group_provenance.setdefault(row["claim_group_id"], provenance) + if prior != provenance: + raise S240Error("S230_PART_GROUP_PROVENANCE", "part family provenance differs within group") + parts[row["part_family"]].append(value) + item_refs = require_list(s230.get("ordered_item_receipts"), code="S230_ITEM_RECEIPT_REFS") + cohort_refs = require_list(s230.get("ordered_cohort_receipts"), code="S230_COHORT_RECEIPT_REFS") + if item_refs != sorted(item_refs, key=lambda row: (row.get("claim_group_id"), row.get("path"))): + raise S240Error("S230_ITEM_RECEIPT_ORDER", "item receipt refs are not sorted") + if cohort_refs != sorted(cohort_refs, key=lambda row: row.get("path")): + raise S240Error("S230_COHORT_RECEIPT_ORDER", "cohort receipt refs are not sorted") + if [row.get("claim_group_id") for row in item_refs] != expected_groups: + raise S240Error("S230_ITEM_RECEIPT_GROUP_SET", "item receipt group set differs") + receipt_rows: list[dict[str, Any]] = [] + for kind, refs in (("ITEM", item_refs), ("COHORT", cohort_refs)): + for ref in refs: + receipt_path = safe_path(ref.get("path"), code="S230_RECEIPT_PATH") + receipt, receipt_raw = read_bound_json(client, join_path(root, receipt_path), require_hex(ref.get("sha256"), code="S230_RECEIPT_HASH")) + require_self_hash(receipt, "receipt_sha256", code="S230_RECEIPT_SELF_HASH") + if receipt.get("part_manifest_core_sha256") != manifest["part_manifest_core_sha256"]: + raise S240Error("S230_RECEIPT_CORE_HASH", "receipt references a different manifest core") + receipt_provenance = validate_handoff_provenance( + receipt.get("provenance"), common_only=kind == "COHORT", + expected_mode=request["compile_mode"], code="S230_RECEIPT_PROVENANCE", + ) + if common_provenance(receipt_provenance) != common: + raise S240Error("S230_RECEIPT_COMMON_PROVENANCE", "receipt provenance differs") + if kind == "ITEM": + group_id = ref.get("claim_group_id") + if receipt.get("claim_group_id") != group_id or receipt_provenance != group_provenance.get(group_id): + raise S240Error("S230_ITEM_RECEIPT_GROUP", "item receipt group/provenance differs") + total += len(receipt_raw) + receipt_rows.append({"kind": kind, "path": receipt_path, "sha256": digest(receipt_raw)}) + plan_documents, plan_raw_by_path, total = read_plan_artifacts(client, root, plan, total, schema_store) + rule_packs: dict[str, dict[str, Any]] = {} + group_slices: dict[str, dict[str, Any]] = {} + renderer_descriptors: dict[str, dict[str, Any]] = {} + frozen_assets: dict[str, dict[str, Any]] = {} + frozen_source_rows: list[dict[str, Any]] = [dict(row) for row in release_rows] + frozen_source_rows.extend({ + "path": row["path"], "sha256": row["raw_sha256"], "ref_family": "s2_00_runtime", + } for row in ingress_artifact_rows) + frozen_source_rows.extend(s210_handoff["source_rows"]) + frozen_source_rows.append({ + "path": "map_s2_30/artifact_manifest.json", + "sha256": digest(manifest_raw), "ref_family": "upstream_manifest", + }) + calculation_receipts: dict[str, dict[str, Any]] = {} + for group_id in expected_groups: + group_path = f"plan/group_slices/{group_id}.json" + group_slice = require_object(plan_documents.get(group_path), code="S220_GROUP_SLICE") + if group_slice.get("claim_group_id") != group_id: + raise S240Error("S220_GROUP_SLICE_ID", "group slice id differs") + group_echo = require_object(group_provenance.get(group_id), code="S230_GROUP_ECHO") + if (request["compile_mode"] != "STRUCTURAL_FIXTURE" + and digest(plan_raw_by_path[group_path]) != group_echo.get("s30_group_slice_sha256")): + raise S240Error("S220_S230_GROUP_SLICE_HASH", "S2_30 group-slice echo differs from frozen S2_20 bytes") + group_slices[group_id] = group_slice + rule_pack, rule_raw, resolved = resolve_frozen_ref( + client, root, plan_raw_by_path, + require_object(group_slice.get("rule_context_pack_ref"), code="S220_RULE_PACK_REF"), + code="S220_RULE_PACK_REF", + ) + if (request["compile_mode"] != "STRUCTURAL_FIXTURE" + and digest(rule_raw) != group_echo.get("p31_rule_and_pack_sha256")): + raise S240Error("S220_S230_RULE_PACK_HASH", "S2_30 rule-pack echo differs from frozen S2_20 bytes") + rule_packs[group_id] = rule_pack + frozen_source_rows.append({"path": resolved, "sha256": digest(rule_raw)}) + for ref in require_list(rule_pack.get("renderer_refs"), code="S220_RENDERER_REFS"): + descriptor, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_RENDERER_REF"), code="S220_RENDERER_REF") + renderer_id = require_ident(descriptor.get("renderer_id"), code="S220_RENDERER_ID") + if renderer_id in renderer_descriptors and canonical_bytes(renderer_descriptors[renderer_id]) != canonical_bytes(descriptor): + raise S240Error("S220_RENDERER_CONFLICT", "renderer id binds conflicting bytes") + renderer_descriptors[renderer_id] = descriptor + frozen_assets[resolved] = descriptor + frozen_source_rows.append({"path": resolved, "sha256": digest(raw)}) + for ref_name in ("structured_relief_rule_refs", "review_policy_refs", "ce13_branch_refs"): + for ref in require_list(rule_pack.get(ref_name), code="S220_RULE_ASSET_REFS"): + asset, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_RULE_ASSET_REF"), code="S220_RULE_ASSET_REF") + frozen_assets[resolved] = asset + frozen_source_rows.append({"path": resolved, "sha256": digest(raw), "ref_family": ref_name}) + for ref in require_list(group_slice.get("calculation_receipt_refs"), code="S220_CALC_REFS"): + receipt, raw, resolved = resolve_frozen_ref(client, root, plan_raw_by_path, require_object(ref, code="S220_CALC_REF"), code="S220_CALC_REF") + receipt_id = require_ident(receipt.get("calculation_receipt_id"), code="S220_CALC_ID") + calculation_receipts[receipt_id] = receipt + frozen_source_rows.append({"path": resolved, "sha256": digest(raw), "ref_family": "calculation"}) + exhibit_register = require_object(plan_documents.get("plan/exhibit_register.json"), code="S220_EXHIBIT_REGISTER") + authority_release = release_values[AUTHORITY_RELEASE_REL] + case_type_coverage = release_values[CASE_TYPE_COVERAGE_REL] + case_type_registry = release_values[CASE_TYPE_REGISTRY_REL] + case_type_rule_registry = release_values[CASE_TYPE_RULE_REGISTRY_REL] + input_closure_rows = [ + { + "path": "ingress/ingress_status.json", "sha256": digest(ingress_raw), + "expected_sha256": request["expected_ingress_status_sha256"], + "schema_ref": "schemas/ingress.schema.json#/$defs/ingress_status", + "schema_version": ingress.get("schema_version"), "producer_id": "S2_00", + "schema_valid": True, "hash_match": digest(ingress_raw) == request["expected_ingress_status_sha256"], + }, + { + "path": "map_s2_10/s2_10_publish_status.json", "sha256": digest(s210_raw), + "expected_sha256": request["expected_s2_10_publish_status_sha256"], + "schema_ref": "schemas/s2_10.schema.json#/$defs/global_publish_status", + "schema_version": s210.get("schema_version"), "producer_id": s210.get("producer_id"), + "schema_valid": True, "hash_match": digest(s210_raw) == request["expected_s2_10_publish_status_sha256"], + }, + { + "path": "plan/plan_publish_status.json", "sha256": digest(plan_raw), + "expected_sha256": request["expected_plan_publish_status_sha256"], + "schema_ref": "schemas/relief_plan.schema.json#/$defs/plan_publish_status", + "schema_version": plan.get("schema_version"), "producer_id": plan.get("workflow_id"), + "schema_valid": True, "hash_match": digest(plan_raw) == request["expected_plan_publish_status_sha256"], + }, + { + "path": "map_s2_30/s2_30_publish_status.json", "sha256": digest(s230_raw), + "expected_sha256": request["expected_s2_30_publish_status_sha256"], + "schema_ref": "schemas/draft_atoms.schema.json#/$defs/publish_status", + "schema_version": s230.get("schema_version"), "producer_id": "S2_30", + "schema_valid": True, "hash_match": digest(s230_raw) == request["expected_s2_30_publish_status_sha256"], + }, + { + "path": "map_s2_30/artifact_manifest.json", "sha256": digest(manifest_raw), + "expected_sha256": request["expected_s2_30_artifact_manifest_sha256"], + "schema_ref": "schemas/draft_atoms.schema.json#/$defs/part_manifest_core", + "schema_version": manifest.get("schema_version"), "producer_id": "S2_30", + "schema_valid": True, "hash_match": digest(manifest_raw) == request["expected_s2_30_artifact_manifest_sha256"], + }, + ] + input_closure_rows.extend({ + "path": row["path"], "sha256": row["raw_sha256"], + "expected_sha256": row["raw_sha256"], "schema_ref": row["schema_ref"], + "schema_version": ingress_documents[row["path"]].get("schema_version"), + "producer_id": ingress_documents[row["path"]].get("producer_id", "S2_00"), + "schema_valid": True, "hash_match": True, + } for row in ingress_artifact_rows) + input_closure_rows.extend(s210_handoff["closure_rows"]) + input_snapshot_preimage = [ + digest(ingress_raw), digest(s210_raw), digest(plan_raw), digest(s230_raw), + digest(manifest_raw), *[row["sha256"] for row in rows], + *[row["sha256"] for row in receipt_rows], + *[digest(ingress_raws[path]) for path in sorted(ingress_raws)], + *[digest(s210_handoff["raw_by_path"][path]) for path in sorted(s210_handoff["raw_by_path"])], + *[digest(plan_raw_by_path[path]) for path in sorted(plan_raw_by_path)], + *[row["sha256"] for row in sorted(frozen_source_rows, key=lambda item: (item["path"], item["sha256"]))], + ] + return { + "ingress": ingress, "s210": s210, "plan": plan, "s230": s230, + "manifest": manifest, "manifest_sha256": digest(manifest_raw), "rows": rows, + "parts": parts, "group_ids": expected_groups, "group_provenance": group_provenance, + "receipt_rows": receipt_rows, "plan_documents": plan_documents, + "plan_raw_by_path": plan_raw_by_path, + "group_slices": group_slices, "rule_packs": rule_packs, + "renderer_descriptors": renderer_descriptors, + "frozen_assets": frozen_assets, + "calculation_receipts": calculation_receipts, + "exhibit_register": exhibit_register, + "ingress_documents": ingress_documents, "ingress_raws": ingress_raws, + "ingress_artifact_rows": ingress_artifact_rows, + "s210_handoff": s210_handoff, + "authority_release": authority_release, + "authority_release_sha256": digest(release_raws[AUTHORITY_RELEASE_REL]), + "case_type_coverage": case_type_coverage, + "case_type_coverage_sha256": digest(release_raws[CASE_TYPE_COVERAGE_REL]), + "case_type_registry": case_type_registry, + "case_type_registry_sha256": digest(release_raws[CASE_TYPE_REGISTRY_REL]), + "case_type_rule_registry": case_type_rule_registry, + "case_type_rule_registry_sha256": digest(release_raws[CASE_TYPE_RULE_REGISTRY_REL]), + "schema_store": schema_store, + "frozen_source_rows": sorted(frozen_source_rows, key=lambda row: (row["path"], row["sha256"])), + "input_closure_rows": input_closure_rows, + "input_snapshot_preimage": input_snapshot_preimage, + "input_snapshot_digest": digest(input_snapshot_preimage), + } + + + def flatten(parts: Iterable[Mapping[str, Any]], keys: Sequence[str]) -> list[Any]: + result: list[Any] = [] + for part in parts: + value: Any = None + for key in keys: + if key in part: + value = part[key] + break + if value is None: + continue + if not isinstance(value, list): + raise S240Error("PART_PAYLOAD_TYPE", f"part payload must be an array: {keys[0]}") + result.extend(value) + return result + + + def unique_sorted(rows: Iterable[Any], id_keys: Sequence[str], *, code: str) -> list[dict[str, Any]]: + by_id: dict[str, dict[str, Any]] = {} + for value in rows: + row = require_object(value, code=code) + row_id: Any = None + for key in id_keys: + if key in row: + row_id = row[key] + break + row_id = require_ident(row_id, code=code) + if row_id in by_id and canonical_bytes(by_id[row_id]) != canonical_bytes(row): + raise S240Error("IMMUTABLE_ID_CONFLICT", f"conflicting immutable row: {row_id}") + by_id[row_id] = row + return [by_id[key] for key in sorted(by_id)] + + + def provenance_source_refs(rows: Any) -> list[str]: + refs: set[str] = set() + for row in rows if isinstance(rows, list) else []: + if not isinstance(row, dict): + continue + for key, value in row.items(): + if key.endswith("_ref") and isinstance(value, str) and value: + refs.add(value) + elif key.endswith("_refs") and isinstance(value, list): + refs.update(item for item in value if isinstance(item, str) and item) + elif key == "locator" and isinstance(value, dict): + refs.add("locator:" + digest(value)) + return sorted(refs) + + + def slot_values(text_or_slots: Mapping[str, Any]) -> dict[str, str | list[str]]: + rows = require_list(text_or_slots.get("slots"), code="ATOM_TYPED_SLOTS") + values: dict[str, str | list[str]] = {} + for value in rows: + row = require_object(value, code="ATOM_TYPED_SLOT") + slot_id = require_ident(row.get("slot_id"), code="ATOM_SLOT_ID") + if slot_id in values: + raise S240Error("ATOM_SLOT_DUPLICATE", f"duplicate typed slot: {slot_id}") + raw = row.get("value") + if raw is None: + continue + if not isinstance(raw, str): + raise S240Error("ATOM_SLOT_VALUE", "typed slot value must be string or null") + rendered = nfc(raw) + if any(token in rendered for token in ("{{", "}}", "\x00")): + raise S240Error("ATOM_SLOT_INJECTION", "typed slot contains forbidden token") + values[slot_id] = rendered + return values + + + def select_renderer_branch( + descriptor: Mapping[str, Any], branch_id: str, *, allow_fixture: bool, + ) -> Mapping[str, Any]: + status = descriptor.get("status") + eligible = descriptor.get("execution_eligible") is True + if not eligible or status not in ({"APPROVED_LEGAL_CONTENT", "STRUCTURAL_FIXTURE_ONLY"} if allow_fixture else {"APPROVED_LEGAL_CONTENT"}): + raise S240Error("RENDERER_NOT_ELIGIBLE", "frozen renderer is not approved/execution-eligible") + branches = require_list(descriptor.get("branch_rows"), code="RENDER_BRANCH_ROWS") + matches = [row for row in branches if isinstance(row, dict) and row.get("branch_id") == branch_id] + if len(matches) != 1: + raise S240Error("RENDER_BRANCH_CARDINALITY", "template_branch_id must match exactly one frozen branch") + branch = matches[0] + if branch.get("approval_status") != "APPROVED": + raise S240Error("RENDER_BRANCH_NOT_APPROVED", "selected branch is not approved") + return branch + + + def render_segments( + descriptor: Mapping[str, Any], branch: Mapping[str, Any], slots: Mapping[str, Any], + ) -> tuple[str, str]: + definitions = { + row.get("name"): row + for row in descriptor.get("typed_slot_contract", {}).get("slot_definitions", []) + if isinstance(row, dict) and isinstance(row.get("name"), str) + } + if set(slots) - set(definitions): + raise S240Error("RENDERER_UNKNOWN_SLOT", "atom supplies a slot outside frozen descriptor") + for name, definition in definitions.items(): + if definition.get("cardinality") in {"EXACTLY_ONE", "ONE_OR_MORE"} and name not in slots: + raise S240Error("RENDERER_REQUIRED_SLOT_MISSING", f"missing frozen slot: {name}") + segments = require_list(branch.get("segments"), code="RENDER_SEGMENTS") + + def render_a() -> str: + pieces: list[str] = [] + for segment in segments: + row = require_object(segment, code="RENDER_SEGMENT") + if row.get("kind") == "LITERAL" and set(row) == {"kind", "value"} and isinstance(row.get("value"), str): + pieces.append(nfc(row["value"])) + elif row.get("kind") == "SLOT" and set(row) == {"kind", "name", "escape"}: + name = row.get("name") + if name not in slots: + if definitions.get(name, {}).get("cardinality") == "ZERO_OR_ONE": + continue + raise S240Error("RENDERER_REQUIRED_SLOT_MISSING", f"missing segment slot: {name}") + value = slots[name] + pieces.append(", ".join(value) if isinstance(value, list) else str(value)) + else: + raise S240Error("RENDER_SEGMENT_SHAPE", "closed renderer segment is invalid") + return nfc("".join(pieces)) + + primary = render_a() + independent_segments = [dict(row) for row in segments] + independent_slots = {key: (list(value) if isinstance(value, list) else value) for key, value in slots.items()} + independent = "".join( + nfc(str(row["value"])) if row.get("kind") == "LITERAL" + else ( + ", ".join(independent_slots[row["name"]]) + if isinstance(independent_slots.get(row["name"]), list) + else str(independent_slots.get(row["name"], "")) + ) + for row in independent_segments + ) + independent = nfc(independent) + if primary.encode("utf-8") != independent.encode("utf-8"): + raise S240Error("RENDERER_INDEPENDENT_RERENDER_MISMATCH", "independent renderer bytes differ") + if PLACEHOLDER.search(primary): + raise S240Error("RENDER_DANGLING_SLOT", "closed renderer left a template token") + return primary, independent + + + def reduce_and_render(inputs: Mapping[str, Any], request: Mapping[str, Any]) -> dict[str, Any]: + parts = inputs["parts"] + atoms = unique_sorted( + flatten(parts["DRAFT_PART"], ("canonical_atoms",)), + ("atom_id",), code="DRAFT_ATOM_ID", + ) + atom_by_id: dict[str, dict[str, Any]] = {} + source_plan_hashes: set[str] = set() + for part in parts["DRAFT_PART"]: + source_plan_hashes.add(require_hex(part.get("source_plan_sha256"), code="DRAFT_SOURCE_PLAN_HASH")) + for atom in part["canonical_atoms"]: + require_self_hash(atom, "canonical_atom_sha256", code="CANONICAL_ATOM_SELF_HASH") + if "legal_admission" in atom or "closed_renderer" in atom: + raise S240Error("ATOM_SELF_ASSERTED_LEGAL_ADMISSION", "atom may not carry legal admission or renderer bytes") + atom_by_id[atom["atom_id"]] = atom + base_ledger = require_object( + inputs["ingress_documents"].get("review/issue_ledger.base.json"), + code="BASE_ISSUE_LEDGER", + ) + plan_ledger = require_object( + inputs["plan_documents"].get("plan/issue_ledger.plan.json"), + code="PLAN_ISSUE_LEDGER", + ) + base_issues = [dict(row) for row in require_list(base_ledger.get("issues"), code="BASE_ISSUES")] + base_issue_ids = sorted(str(row.get("issue_id")) for row in base_issues) + if ( + len(base_issue_ids) != len(set(base_issue_ids)) + or plan_ledger.get("preserved_base_issue_ids") != base_issue_ids + or plan_ledger.get("base_ledger_sha256") != digest(inputs["ingress_raws"]["review/issue_ledger.base.json"]) + ): + raise S240Error("ISSUE_LEDGER_BASE_CONSERVATION", "S2_20 did not preserve the exact S2_00 issue universe") + issues: list[dict[str, Any]] = list(base_issues) + issue_source_keys: list[str] = [f"S2_00:{value}" for value in base_issue_ids] + for row in require_list(plan_ledger.get("plan_issues"), code="PLAN_ISSUES"): + row = require_object(row, code="PLAN_ISSUE") + source_id = require_ident(row.get("issue_id"), code="PLAN_ISSUE_ID") + issue_id = source_id if re.fullmatch(r"ISS-[A-Fa-f0-9]{16,64}", source_id) else stable_id("ISS", "S2_20", source_id) + code = require_ident(row.get("code"), code="PLAN_ISSUE_CODE") + scope_ref = require_ident(row.get("scope_ref"), code="PLAN_ISSUE_SCOPE") + issues.append({ + "issue_id": issue_id, "issue_code": code, + "technical_severity": "REVIEW", "review_partition": "UNRESOLVED", + "impact_scope": "REVIEW_ITEM", "scope_refs": [scope_ref], + "source_contract_row_refs": [f"S2_20:{source_id}"], + "reason_codes": [code], "downstream_allowed_actions": ["REVIEW"], + "source_refs": [f"S2_20:{source_id}"], "status": "CARRIED_FORWARD", + }) + issue_source_keys.append(f"S2_20:{source_id}") + s210_impact = {"RUN_WIDE": "GLOBAL", "CLUSTER_LOCAL": "CLUSTER", "OPTION_ONLY": "REVIEW_ITEM"} + s210_severity = {"INFO": "INFO", "WARNING": "REVIEW", "BLOCKING": "BLOCK"} + for cluster_id, part in sorted(inputs["s210_handoff"]["issue_parts"].items()): + for row in require_list(part.get("issues"), code="S210_ISSUES"): + row = require_object(row, code="S210_ISSUE") + source_id = require_ident(row.get("issue_id"), code="S210_ISSUE_ID") + issue_id = stable_id("ISS", "S2_10", cluster_id, source_id) + issue_code = require_ident(row.get("issue_code"), code="S210_ISSUE_CODE") + source_refs = sorted(set(str(value) for value in row.get("source_refs", []) if isinstance(value, str) and value)) + issues.append({ + "issue_id": issue_id, "issue_code": issue_code, + "technical_severity": s210_severity.get(str(row.get("severity")), "REVIEW"), + "review_partition": "SUPPORTED" if row.get("status") == "RESOLVED" else "UNRESOLVED", + "impact_scope": s210_impact.get(str(row.get("impact_scope")), "REVIEW_ITEM"), + "scope_refs": [cluster_id], "source_contract_row_refs": [f"S2_10:{source_id}"], + "reason_codes": sorted(set([issue_code, *[str(value) for value in row.get("resolution_condition_codes", [])]])), + "downstream_allowed_actions": ["REVIEW"], + "source_refs": source_refs or [f"S2_10:{cluster_id}"], + "status": "CARRIED_FORWARD", + "upstream_review_key": source_id, "raw_item_sha256": digest(row), + }) + issue_source_keys.append(f"S2_10:{cluster_id}:{source_id}") + for part in parts["ISSUE_PATCH"]: + for code in sorted(set(part.get("review_flags", [])) | set(part.get("missing_inputs", []))): + issues.append({ + "issue_id": stable_id("ISS", part["claim_group_id"], code), + "issue_code": str(code), "technical_severity": "REVIEW", + "review_partition": "UNRESOLVED", "impact_scope": "REVIEW_ITEM", + "scope_refs": [part["claim_group_id"]], + "source_contract_row_refs": [f"S2_30:{part['claim_group_id']}"], + "reason_codes": [str(code)], + "downstream_allowed_actions": ["REVIEW"], + "source_refs": [f"S2_30:{part['claim_group_id']}"], "status": "OPEN", + }) + issue_source_keys.append(f"S2_30:{part['claim_group_id']}:CODE:{code}") + for row in part.get("adverse_fact_rows", []): + adverse_digest = digest(row) + issues.append({ + "issue_id": stable_id("ISS", part["claim_group_id"], adverse_digest), + "issue_code": "ADVERSE_FACT_PRESERVED", "technical_severity": "REVIEW", + "review_partition": "CONDITIONAL", "impact_scope": "FACT", + "scope_refs": [part["claim_group_id"]], + "source_contract_row_refs": [f"S2_30:{part['claim_group_id']}"], + "reason_codes": ["ADVERSE_FACT_PRESERVED"], + "downstream_allowed_actions": ["REVIEW"], + "source_refs": provenance_source_refs([row]) or [f"S2_30:{part['claim_group_id']}"], + "status": "OPEN", + }) + issue_source_keys.append(f"S2_30:{part['claim_group_id']}:ADVERSE:{adverse_digest}") + issues = unique_sorted(issues, ("issue_id",), code="ISSUE_ID") if issues else [] + worknotes: list[dict[str, Any]] = [] + for part in parts["WORKNOTE_PART"]: + for atom_id in part.get("worknote_atom_ids", []): + atom = atom_by_id.get(atom_id) + if atom is None or atom.get("output_section") != "worknote_only": + raise S240Error("WORKNOTE_ATOM_REF", "worknote part references a missing/non-worknote atom") + text = atom.get("text_or_slots", {}).get("draft_text") + if not isinstance(text, str) or not text: + text = canonical_bytes(atom.get("text_or_slots", {}).get("slots", [])).decode("utf-8").strip() + worknotes.append({ + "worknote_id": atom_id, "text": nfc(text), + "source_refs": provenance_source_refs(atom.get("provenance")) or [f"ATOM:{atom_id}"], + }) + assumptions: list[dict[str, Any]] = [] + assumption_source_keys: list[str] = [] + assumption_impact = {"RUN_WIDE": "GLOBAL", "CLUSTER_LOCAL": "CLAIM_GROUP", "OPTION_ONLY": "ATOMIC_CLAIM"} + for cluster_id, part in sorted(inputs["s210_handoff"]["assumption_parts"].items()): + for row in require_list(part.get("assumptions"), code="S210_ASSUMPTIONS"): + row = require_object(row, code="S210_ASSUMPTION") + local_ref = require_ident(row.get("assumption_local_ref"), code="S210_ASSUMPTION_REF") + basis = sorted(set(str(value) for value in row.get("basis_refs", []) if isinstance(value, str) and value)) + assumptions.append({ + "assumption_id": stable_id("ASM", cluster_id, local_ref), + "text": require_text(row.get("statement"), code="S210_ASSUMPTION_TEXT"), + "status": "OPEN", "source_refs": basis or [f"S2_10:{cluster_id}"], + "impact_scope": assumption_impact.get(str(row.get("impact_scope")), "CLAIM_GROUP"), + }) + assumption_source_keys.append(f"S2_10:{cluster_id}:{local_ref}") + assumptions = unique_sorted(assumptions, ("assumption_id",), code="ASSUMPTION_ID") if assumptions else [] + usage: list[dict[str, Any]] = [] + usage_source_keys: list[str] = [] + for cluster_id, part in sorted(inputs["s210_handoff"]["usage_parts"].items()): + usage.append({ + "source_stage": "S2_10", "source_scope_id": cluster_id, + "source_part_sha256": part["part_sha256"], "payload": dict(part), + }) + usage_source_keys.append(f"S2_10:{cluster_id}:{part['part_sha256']}") + for part in sorted(parts["USAGE_PART"], key=lambda row: row["claim_group_id"]): + usage.append({ + "source_stage": "S2_30", "source_scope_id": part["claim_group_id"], + "source_part_sha256": part["part_sha256"], "payload": dict(part), + }) + usage_source_keys.append(f"S2_30:{part['claim_group_id']}:{part['part_sha256']}") + relief_rows: list[dict[str, Any]] = [] + cause_rows: list[dict[str, Any]] = [] + render_errors: list[str] = [] + render_absences: list[str] = [] + rerender_equal = True + group_contracts = { + group_id: require_object(group_slice.get("claim_group"), code="GROUP_CONTRACT") + for group_id, group_slice in inputs["group_slices"].items() + } + for atom in atoms: + if atom.get("drafting_disposition") == "WORKNOTE_ONLY" or atom.get("output_section") == "worknote_only": + continue + text_slots = require_object(atom.get("text_or_slots"), code="ATOM_TEXT_OR_SLOTS") + renderer_id = require_ident(text_slots.get("renderer_id"), code="ATOM_RENDERER_ID") + branch_id = require_ident(text_slots.get("template_branch_id"), code="ATOM_BRANCH_ID") + descriptor = inputs["renderer_descriptors"].get(renderer_id) + rendered: str | None = None + try: + if descriptor is None: + raise S240Error("RENDERER_DESCRIPTOR_MISSING", "S2_20 did not freeze selected renderer") + branch = select_renderer_branch(descriptor, branch_id, allow_fixture=request["compile_mode"] == "STRUCTURAL_FIXTURE") + rendered, independent = render_segments(descriptor, branch, slot_values(text_slots)) + rerender_equal = rerender_equal and rendered.encode("utf-8") == independent.encode("utf-8") + except S240Error as exc: + if exc.code in {"RENDERER_NOT_ELIGIBLE", "RENDERER_DESCRIPTOR_MISSING", "RENDER_BRANCH_NOT_APPROVED"}: + render_absences.append(f"{atom['atom_id']}:{exc.code}") + else: + render_errors.append(f"{atom['atom_id']}:{exc.code}") + section = atom.get("output_section") + group_contract = require_object(group_contracts.get(atom["claim_group_id"]), code="ATOM_GROUP_CONTRACT") + typed_group_projection = { + "party_refs": group_contract.get("party_refs", []), + "object_refs": group_contract.get("object_refs", []), + "amount_slots": group_contract.get("amount_slots", []), + "period_slots": group_contract.get("period_slots", []), + "calculation_receipt_ids": group_contract.get("calculation_receipt_ids", []), + "counter_performance_refs": group_contract.get("counter_performance_refs", []), + } + if section in {"relief_main", "relief_cost", "relief_provisional_execution"}: + if rendered is not None: + relief_rows.append({ + "atom_id": atom["atom_id"], "atomic_claim_id": atom["atomic_claim_id"], + "claim_group_id": atom["claim_group_id"], "output_section": section, + "renderer_id": renderer_id, "branch_id": branch_id, "text": rendered, + **typed_group_projection, + }) + elif section.startswith("cause_") or section == "procedural_declaration": + text = text_slots.get("draft_text") if text_slots.get("rendering_mode") == "REVIEW_TEXT_WITH_SLOTS" else rendered + if isinstance(text, str) and text and not PLACEHOLDER.search(text): + cause_rows.append({ + "atom_id": atom["atom_id"], "atomic_claim_id": atom["atomic_claim_id"], + "claim_group_id": atom["claim_group_id"], "output_section": section, + "text": nfc(text), "source_refs": provenance_source_refs(atom.get("provenance")), + **typed_group_projection, + }) + elif rendered is None: + render_absences.append(f"{atom['atom_id']}:CAUSE_TEXT_UNAVAILABLE") + relief_rows.sort(key=lambda row: (row["claim_group_id"], row["atomic_claim_id"], row["output_section"], row["atom_id"])) + cause_rows.sort(key=lambda row: (row["claim_group_id"], row["atomic_claim_id"], row["output_section"], row["atom_id"])) + legal_assets_admitted = bool(atoms) and not render_errors and not render_absences and all( + descriptor.get("status") == "APPROVED_LEGAL_CONTENT" and descriptor.get("execution_eligible") is True + for descriptor in inputs["renderer_descriptors"].values() + ) + clean_render_allowed = request["compile_mode"] in {"SUBSET_CANARY", "PRODUCTION"} and legal_assets_admitted + relief = "\n".join(f"{index}. {row['text']}" for index, row in enumerate(relief_rows, 1)) if clean_render_allowed else "" + cause = "\n\n".join(row["text"] for row in cause_rows) if clean_render_allowed else "" + pleading = f"# 청구취지\n\n{relief}\n\n# 청구원인\n\n{cause}" if clean_render_allowed else "" + return { + "atoms": atoms, "issues": issues, "worknotes": worknotes, "usage": usage, + "assumptions": assumptions, + "conservation": { + "issue_source_keys": sorted(issue_source_keys), + "issue_ids": sorted(str(row["issue_id"]) for row in issues), + "assumption_source_keys": sorted(assumption_source_keys), + "assumption_ids": sorted(str(row["assumption_id"]) for row in assumptions), + "usage_source_keys": sorted(usage_source_keys), + }, + "relief_rows": relief_rows, "cause_rows": cause_rows, + "relief": relief, "cause": cause, "pleading": pleading, + "render_errors": sorted(set(render_errors)), "render_absences": sorted(set(render_absences)), + "rerender_equal": rerender_equal, "clean_render_allowed": clean_render_allowed, + "legal_assets_admitted": legal_assets_admitted, + "source_plan_hashes": sorted(source_plan_hashes), + } + + + def invariant_result( + invariant_id: str, observed: bool | None, reason: str, + *, source_refs: Sequence[str] = (), incomplete: bool = False, + ) -> dict[str, Any]: + status = "UNEVALUABLE" if observed is None else ("PASS" if observed else "FAIL") + scope = "OK" if status == "PASS" else ("INCOMPLETE" if incomplete else "REVIEW_REQUIRED") + return { + "invariant_id": invariant_id, "evaluation_status": status, + "finding_ids": [] if status == "PASS" else [stable_id("F40", invariant_id, reason)], + "impact_scope": scope, "source_refs": sorted(set(source_refs)), + "expected": True, "observed": observed, "reason_codes": [reason], + "validator_algorithm_id": f"{ALGORITHM_VERSION}::{invariant_id}", + } + + + def invariant_results(inputs: Mapping[str, Any], reduced: Mapping[str, Any], request: Mapping[str, Any]) -> list[dict[str, Any]]: + atoms = reduced["atoms"] + relief_claims = {row["atomic_claim_id"] for row in reduced["relief_rows"]} + cause_claims = {row["atomic_claim_id"] for row in reduced["cause_rows"]} + slot_rows = [row for atom in atoms for row in atom.get("text_or_slots", {}).get("slots", []) if isinstance(row, dict)] + slot_ids = [(atom["atom_id"], row.get("slot_id")) for atom in atoms for row in atom.get("text_or_slots", {}).get("slots", []) if isinstance(row, dict)] + legal_provenance = [row for atom in atoms for row in atom.get("provenance", []) if isinstance(row, dict) and row.get("proposition_kind") == "LEGAL_PROPOSITION"] + defense_rows = [row for atom in atoms for row in atom.get("provenance", []) if isinstance(row, dict) and "REBUTTAL" in str(row.get("proposition_kind", ""))] + binding_rows = [row for pack in inputs["rule_packs"].values() for row in pack.get("binding_rows", []) if isinstance(row, dict)] + binding_by_claim: dict[str, list[dict[str, Any]]] = {} + for row in binding_rows: + binding_by_claim.setdefault(str(row.get("atomic_claim_id")), []).append(row) + selected_claims = {str(row.get("atomic_claim_id")) for row in binding_rows if row.get("case_type_binding_status") == "BOUND" and row.get("sub_rule_binding_status") == "BOUND"} + all_claims = {str(atom.get("atomic_claim_id")) for atom in atoms} + calculation_tokens = [row for row in slot_rows if row.get("value_kind") == "CALCULATION_TOKEN"] + calc_observed: bool | None = None if not calculation_tokens else bool(inputs["calculation_receipts"]) + provenance_complete = all(bool(provenance_source_refs(atom.get("provenance"))) for atom in atoms) + option_ids: list[str] = [] + partition_ids: list[str] = [] + option_evaluable = False + for group_slice in inputs["group_slices"].values(): + claim_group = group_slice.get("claim_group", {}) + if isinstance(claim_group, dict): + ids = claim_group.get("claim_option_ids", claim_group.get("option_ids", [])) + if isinstance(ids, list): + option_ids.extend(str(item) for item in ids) + partition = claim_group.get("option_partition", {}) + if isinstance(partition, dict): + option_evaluable = True + for name in ("selected", "alternative", "excluded", "deferred"): + values = partition.get(name, []) + if isinstance(values, list): + partition_ids.extend(str(item) for item in values) + option_ok = None if not option_evaluable else len(partition_ids) == len(set(partition_ids)) and set(partition_ids) == set(option_ids) + exhibit_rows = inputs["exhibit_register"].get("rows") + exhibit_ok = None if not isinstance(exhibit_rows, list) else all(isinstance(row, dict) for row in exhibit_rows) + authority_ok = None if not legal_provenance else all(row.get("authority_id") and row.get("locator") for row in legal_provenance) + closure_rows = inputs.get("input_closure_rows", []) + expected_closure = { + "ingress/ingress_status.json": ("stage2_s2_00_ingress_status.v1", "stage2_s2_00_ingress_status.v1.1", "S2_00"), + "map_s2_10/s2_10_publish_status.json": ("stage2_s2_10_publish_status.v2", "S2_10_NATIVE_RESULT_ADAPTER"), + "plan/plan_publish_status.json": ("stage2_plan_publish_status.v1", "S2_20"), + "map_s2_30/s2_30_publish_status.json": ("stage2_s2_30_publish_status.v1", "S2_30"), + "map_s2_30/artifact_manifest.json": ("stage2_s2_30_part_manifest_core.v1", "S2_30"), + } + closure_by_path = {str(row.get("path")): row for row in closure_rows if isinstance(row, dict)} + v01 = ( + len(closure_rows) == len(closure_by_path) + and set(expected_closure).issubset(closure_by_path) + and all( + row.get("schema_valid") is True + and row.get("hash_match") is True + and row.get("sha256") == row.get("expected_sha256") + and HEX64.fullmatch(str(row.get("sha256", ""))) + and isinstance(row.get("schema_ref"), str) + for row in closure_rows if isinstance(row, dict) + ) + ) + if v01: + for path, allowed in expected_closure.items(): + row = closure_by_path[path] + version_allowed = allowed[:-1] + producer = allowed[-1] + if not ( + row.get("schema_version") in version_allowed + and row.get("producer_id") == producer + and row.get("schema_valid") is True + and row.get("hash_match") is True + and row.get("sha256") == row.get("expected_sha256") + and HEX64.fullmatch(str(row.get("sha256", ""))) + and isinstance(row.get("schema_ref"), str) + ): + v01 = False + break + atom_groups = {str(atom.get("claim_group_id")) for atom in atoms} + source_atoms = [row for part in inputs["parts"]["DRAFT_PART"] for row in part.get("canonical_atoms", [])] + source_atom_ids = [str(row.get("atom_id")) for row in source_atoms if isinstance(row, dict)] + reduced_atom_ids = [str(row.get("atom_id")) for row in atoms] + source_worknote_ids = sorted( + str(atom_id) for part in inputs["parts"]["WORKNOTE_PART"] + for atom_id in part.get("worknote_atom_ids", []) + ) + conservation = require_object(reduced.get("conservation"), code="V02_CONSERVATION") + issue_source_keys = require_list(conservation.get("issue_source_keys"), code="V02_ISSUE_KEYS") + assumption_source_keys = require_list(conservation.get("assumption_source_keys"), code="V02_ASSUMPTION_KEYS") + usage_source_keys = require_list(conservation.get("usage_source_keys"), code="V02_USAGE_KEYS") + v02 = ( + bool(atoms) + and atom_groups == set(inputs["group_ids"]) + and len(source_atom_ids) == len(set(source_atom_ids)) + and sorted(source_atom_ids) == sorted(reduced_atom_ids) + and len(issue_source_keys) == len(set(issue_source_keys)) == len(reduced["issues"]) + and len(assumption_source_keys) == len(set(assumption_source_keys)) == len(reduced["assumptions"]) + and len(usage_source_keys) == len(set(usage_source_keys)) == len(reduced["usage"]) + and source_worknote_ids == sorted(str(row.get("worknote_id")) for row in reduced["worknotes"]) + and inputs["s210_handoff"]["cluster_ids"] == inputs["ingress"]["executable_cluster_ids"] + ) + v03 = all(row.get("slot_id") and row.get("namespace_owner") and row.get("domain_id") for row in slot_rows) if slot_rows else None + v04 = all( + row.get("opposing_fact_id") and row.get("rebuttal_id") and row.get("evidence_refs") + and row.get("polarity") and row.get("presentation_status") + for row in defense_rows + ) if defense_rows else None + v05 = all( + isinstance(group_slice.get("claim_group"), dict) + and group_slice.get("claim_group", {}).get("dependency_wave_id") + and group_slice.get("claim_group", {}).get("relation_consistency_status") == "PASS" + for group_slice in inputs["group_slices"].values() + ) if inputs["group_slices"] else None + v07 = all( + token.get("calculation_receipt_id") in inputs["calculation_receipts"] + and token.get("operand_digest") == inputs["calculation_receipts"][token["calculation_receipt_id"]].get("operand_digest") + and inputs["calculation_receipts"][token["calculation_receipt_id"]].get("missing_law_values") in ([], None) + for token in calculation_tokens + ) if calculation_tokens else None + recovery_keys = [(atom.get("recovery_object_id"), atom.get("recovery_scope")) for atom in atoms if atom.get("recovery_object_id")] + v08 = len(recovery_keys) == len(set(recovery_keys)) if recovery_keys else None + canonical_plan = inputs["plan_documents"].get("plan/canonical_relief_plan.json") + canonical_plan_raw = inputs["plan_raw_by_path"].get("plan/canonical_relief_plan.json") + plan_claims = { + str(row.get("atomic_claim_id")): row + for row in (canonical_plan.get("atomic_claims", []) if isinstance(canonical_plan, dict) else []) + if isinstance(row, dict) + } + plan_hash = digest(canonical_plan_raw) if isinstance(canonical_plan_raw, bytes) else None + v09 = all( + atom.get("source_plan_sha256") == plan_hash + and atom.get("atomic_claim_id") in plan_claims + and plan_claims[atom["atomic_claim_id"]].get("claim_group_id") == atom.get("claim_group_id") + and atom.get("claim_option_id") in plan_claims[atom["atomic_claim_id"]].get("source_claim_option_ids", []) + and len(binding_by_claim.get(str(atom.get("atomic_claim_id")), [])) == 1 + for atom in atoms + ) if atoms else None + v10 = (not reduced["render_errors"] and not reduced["render_absences"] and + all(row.get("output_section") and row.get("text") for row in reduced["relief_rows"] + reduced["cause_rows"])) if atoms else None + def relation_signature(row: Mapping[str, Any]) -> tuple[str, str, str, str, str, str, str]: + return ( + str(row.get("atomic_claim_id")), digest(row.get("party_refs", [])), + digest(row.get("object_refs", [])), digest(row.get("amount_slots", [])), + digest(row.get("period_slots", [])), digest(row.get("calculation_receipt_ids", [])), + digest(row.get("counter_performance_refs", [])), + ) + relief_relation = {relation_signature(row) for row in reduced["relief_rows"]} + cause_relation = {relation_signature(row) for row in reduced["cause_rows"]} + v11 = relief_relation == cause_relation if relief_relation or cause_relation else None + v12 = all(pack.get("corpus_release_sha256") and pack.get("slot_crosswalk_status") == "PASS" and pack.get("injection_isolation_status") == "PASS" for pack in inputs["plan_documents"].values() if isinstance(pack, dict) and pack.get("schema_version") == "stage2_requirement_fact_pack.v1") or None + v13 = all(row.get("authority_id") and row.get("locator") and row.get("temporal_scope_status") == "PASS" and row.get("negative_treatment_status") == "CLEAR" for row in legal_provenance) if legal_provenance else None + def contains_downstream_key(value: Any) -> bool: + forbidden_keys = { + "candidate_content_digest", "review_subject_digest", "review_receipt_sha256s", + "stage2_package_sha256", "commit_intent_sha256", + "commit_result_sha256", "status_event_sha256", + } + if isinstance(value, dict): + return any(key in forbidden_keys or contains_downstream_key(item) for key, item in value.items()) + if isinstance(value, list): + return any(contains_downstream_key(item) for item in value) + return False + v14 = not contains_downstream_key({ + "parts": inputs.get("parts"), "group_slices": inputs.get("group_slices"), + "rule_packs": inputs.get("rule_packs"), "plan_documents": inputs.get("plan_documents"), + "ingress_documents": inputs.get("ingress_documents"), + "s210_handoff": inputs.get("s210_handoff"), + }) and inputs.get("frozen_source_rows") == sorted( + inputs.get("frozen_source_rows", []), key=lambda row: (row["path"], row["sha256"]) + ) if atoms else None + v15 = all(atom.get("provenance") and all(row.get("source_ref") or row.get("source_refs") for row in atom.get("provenance", []) if isinstance(row, dict)) for atom in atoms) if atoms else None + v17 = all(row.get("party_id") and row.get("object_id") and row.get("exhibit_id") and row.get("party_title") for row in exhibit_rows) if isinstance(exhibit_rows, list) and exhibit_rows else None + renderer_observed: bool | None = ( + False if reduced["render_errors"] else + (None if reduced["render_absences"] else bool(reduced["relief_rows"] or reduced["cause_rows"]) and reduced["rerender_equal"]) + ) + checks = { + "V01": invariant_result("V01", v01, "BOUND_INPUT_HASH_SCHEMA_PRODUCER", incomplete=True), + "V02": invariant_result("V02", v02, "REVIEW_UNIVERSE_CONSERVED", incomplete=True), + "V03": invariant_result("V03", v03, "DOMAIN_SLOT_NAMESPACE_BOUND"), + "V04": invariant_result("V04", v04, "DEFENSE_REBUTTAL_PROVENANCE_BOUND"), + "V05": invariant_result("V05", v05, "DEPENDENCY_WAVE_BOUND"), + "V06": invariant_result("V06", all(len(binding_by_claim.get(claim, [])) == 1 and claim in selected_claims for claim in all_claims) if all_claims else None, "CASE_TYPE_SUB_RULE_EXACT"), + "V07": invariant_result("V07", v07, "CALCULATION_RECEIPT_BOUND"), + "V08": invariant_result("V08", v08, "DUPLICATE_RECOVERY_ABSENT"), + "V09": invariant_result("V09", v09, "RELIEF_PLAN_MATCH"), + "V10": invariant_result("V10", v10, "DOCUMENT_ORDER_TEMPLATE_MATCH"), + "V11": invariant_result("V11", v11, "RELIEF_CAUSE_CROSSMATCH"), + "V12": invariant_result("V12", v12, "CORPUS_BOUND"), + "V13": invariant_result("V13", v13, "AUTHORITY_TEMPORAL_BOUND"), + "V14": invariant_result("V14", v14, "NON_CYCLIC_DIGEST_GRAPH"), + "V15": invariant_result("V15", v15, "PROVENANCE_COMPLETE"), + "V16": invariant_result("V16", option_ok, "OPTION_PARTITION_EXACT"), + "V17": invariant_result("V17", v17, "PARTY_OBJECT_EXHIBIT_COMPLETE"), + "V18": invariant_result("V18", renderer_observed, "CLOSED_RENDER_AND_RERENDER_EQUAL"), + } + return [checks[invariant_id] for invariant_id in V_IDS] + + + def review_request_basis( + inputs: Mapping[str, Any], + validation: Sequence[Mapping[str, Any]], + review_policy_contract: Mapping[str, Any], + parent_release_sha256: str, + ) -> dict[str, Any]: + review_policies = [ + value for value in inputs.get("frozen_assets", {}).values() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + if len(review_policies) > 1: + raise S240Error("REVIEW_POLICY_CARDINALITY", "multiple frozen review policies") + policy = review_policies[0] if review_policies else None + policy_sha256 = digest(policy) if policy is not None else digest({"status": "MISSING_REVIEW_POLICY"}) + corpus_hashes = sorted({ + str(value.get("corpus_release_sha256")) for value in inputs.get("plan_documents", {}).values() + if isinstance(value, dict) and value.get("schema_version") == "stage2_requirement_fact_pack.v1" + }) + release_sha256s = { + "parent": parent_release_sha256, + "authority": require_hex(inputs.get("authority_release_sha256"), code="REVIEW_AUTHORITY_RELEASE_HASH"), + "corpus": corpus_hashes[0] if len(corpus_hashes) == 1 and HEX64.fullmatch(corpus_hashes[0]) else digest(corpus_hashes), + "case_type_coverage": require_hex(inputs.get("case_type_coverage_sha256"), code="REVIEW_CASE_TYPE_COVERAGE_HASH"), + } + return { + "schema_version": "stage2_s2_40_review_request_basis.v1", + "required_receipt_types": review_policy_contract["required_receipt_types"], + "scope_ids": inputs["group_ids"], + "finding_ids": sorted(row["finding_ids"][0] for row in validation if row["finding_ids"]), + "policy_version": str(policy.get("schema_version")) if policy is not None else "MISSING_REVIEW_POLICY", + "policy_sha256": policy_sha256, + "reviewer_role": TRUSTED_REVIEW_ROLE, + "reviewer_qualification": TRUSTED_REVIEW_QUALIFICATION, + "release_snapshot_sha256s": release_sha256s, + } + + + def review_subject( + candidate_digest: str, + lawyer_review_packet_core_sha256: str, + validation_envelope_core_sha256: str, + basis: Mapping[str, Any], + ) -> dict[str, Any]: + cores: list[dict[str, Any]] = [] + bindings: list[dict[str, str]] = [] + for receipt_type in require_list(basis.get("required_receipt_types"), code="REVIEW_REQUIRED_TYPES"): + core = { + "candidate_content_digest": candidate_digest, "receipt_type": receipt_type, + "scope_ids": basis["scope_ids"], "finding_ids": basis["finding_ids"], + "policy_version": basis["policy_version"], "policy_sha256": basis["policy_sha256"], + "reviewer_role": basis["reviewer_role"], + "reviewer_qualification": basis["reviewer_qualification"], + "release_snapshot_sha256s": basis["release_snapshot_sha256s"], + } + cores.append(core) + bindings.append({ + "receipt_type": str(receipt_type), + "review_request_core_sha256": digest(core), + }) + bindings.sort(key=lambda row: row["receipt_type"]) + if len(bindings) != len({row["receipt_type"] for row in bindings}): + raise S240Error("REVIEW_REQUEST_TYPE_DUPLICATE", "review request receipt types must be unique") + subject_core = { + "schema_version": "stage2_s2_40_review_subject.v1", + "domain_separator": "STAGE2_S2_40_REVIEW_SUBJECT_V1", + "candidate_content_digest": candidate_digest, + "review_request_core_bindings": bindings, + "lawyer_review_packet_core_sha256": lawyer_review_packet_core_sha256, + "validation_envelope_core_sha256": validation_envelope_core_sha256, + "finding_ids": basis["finding_ids"], "scope_ids": basis["scope_ids"], + "review_policy_sha256": basis["policy_sha256"], + "release_sha256s": basis["release_snapshot_sha256s"], + } + subject = digest(subject_core) + core_by_type = {str(core["receipt_type"]): core for core in cores} + requests = [ + { + "request_id": stable_id( + "RR40", "STAGE2_S2_40_REVIEW_REQUEST_V1", subject, + binding["receipt_type"], *sorted(basis["scope_ids"]), + ), + "receipt_type": binding["receipt_type"], + "core": core_by_type[binding["receipt_type"]], + "core_sha256": binding["review_request_core_sha256"], + "review_subject_digest": subject, + } + for binding in bindings + ] + return { + "review_subject_digest": subject, + "subject": {**subject_core, "review_subject_digest": subject}, + "bindings": bindings, "requests": requests, + } + + + def aggregate_validation(validation: Sequence[Mapping[str, Any]]) -> dict[str, str]: + scopes = {row.get("impact_scope") for row in validation} + if "INCOMPLETE" in scopes: + run_status = "TECHNICAL_INCOMPLETE" + elif any(row.get("evaluation_status") != "PASS" for row in validation): + run_status = "TECHNICAL_REVIEW_REQUIRED" + else: + run_status = "CONSISTENT" + artifact_status = ( + "NOT_PRODUCED" if run_status == "TECHNICAL_INCOMPLETE" + else ("TECHNICAL_REVIEW_REQUIRED" if run_status == "TECHNICAL_REVIEW_REQUIRED" else "CONSISTENT") + ) + return {"run_technical_status": run_status, "artifact_technical_status": artifact_status} + + + def legal_gate_snapshot(inputs: Mapping[str, Any], reduced: Mapping[str, Any]) -> dict[str, bool]: + binding_rows = [ + row for pack in inputs["rule_packs"].values() + for row in pack.get("binding_rows", []) if isinstance(row, dict) + ] + review_policies = [ + value for value in inputs.get("frozen_assets", {}).values() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + structured_rules = [ + value for path, value in inputs.get("frozen_assets", {}).items() + if "case_type_relief_rules" in path + ] + calculations = list(inputs.get("calculation_receipts", {}).values()) + requirement_packs = [ + value for value in inputs.get("plan_documents", {}).values() + if isinstance(value, dict) and value.get("schema_version") == "stage2_requirement_fact_pack.v1" + ] + authority_release = require_object(inputs.get("authority_release"), code="AUTHORITY_RELEASE_OBJECT") + authority_signature = authority_release.get("signature") + authority_ok = ( + authority_release.get("status") == "PRODUCTION_ADMITTED" + and authority_release.get("release_class") == "PRODUCTION_RELEASE" + and authority_release.get("sealed") is True + and authority_release.get("signed") is True + and authority_release.get("executable") is True + and authority_release.get("unresolved") == [] + and isinstance(authority_signature, str) and bool(authority_signature) + and not authority_signature.startswith("PENDING") + and require_object(authority_release.get("registry"), code="AUTHORITY_REGISTRY_REF").get("required_status") == "VERIFIED" + and authority_release.get("hash_binding_status") == "PRODUCTION_ADMITTED" + ) + coverage = require_object(inputs.get("case_type_coverage"), code="CASE_TYPE_COVERAGE_OBJECT") + coverage_rows = require_list(coverage.get("coverage_rows"), code="CASE_TYPE_COVERAGE_ROWS") + case_registry = require_object(inputs.get("case_type_registry"), code="CASE_TYPE_REGISTRY_OBJECT") + rule_registry = require_object(inputs.get("case_type_rule_registry"), code="CASE_TYPE_RULE_REGISTRY_OBJECT") + case_rows = require_list(case_registry.get("rows"), code="CASE_TYPE_REGISTRY_ROWS") + rule_rows = require_list(rule_registry.get("rows"), code="CASE_TYPE_RULE_REGISTRY_ROWS") + approved_values = {"APPROVED", "VERIFIED", "IMPLEMENTED", "RELEASED", "PRODUCTION_ADMITTED", "PASS"} + downstream_keys = { + "relief_rule", "renderer", "corpus", "substantive_profile", + "special_law_or_overlay", "calculation", "review_policy", + } + expected_case_ids = [f"CT-{index:03d}" for index in range(1, 138)] + expected_catalog_ids = [f"CAT-{index:03d}" for index in range(1, 138)] + coverage_ids = [row.get("case_type_id") for row in coverage_rows if isinstance(row, dict)] + case_ids = [row.get("case_type_id") for row in case_rows if isinstance(row, dict)] + rule_ids = [row.get("case_type_id") for row in rule_rows if isinstance(row, dict)] + claim_capable_ids = [ + str(row.get("case_type_id")) for row in case_rows if isinstance(row, dict) + and row.get("claim_capable_disposition") == "CLAIM_CAPABLE" + ] + coverage_rows_ok = ( + coverage_ids == expected_case_ids + and case_ids == expected_case_ids + and rule_ids == expected_case_ids + and case_registry.get("catalog_row_ids") == expected_catalog_ids + and [row.get("catalog_row_id") for row in case_rows] == expected_catalog_ids + and [row.get("source_ordinal") for row in case_rows] == list(range(1, 138)) + and [row.get("canonical_name_ko") for row in coverage_rows] + == [row.get("source_label") for row in case_rows] + ) + for row, registry_row, rule_row in zip(coverage_rows, case_rows, rule_rows): + if not isinstance(row, dict): + coverage_rows_ok = False + continue + downstream = row.get("downstream_coverage") + rule_branches = rule_row.get("rule_branches") if isinstance(rule_row, dict) else None + branch_or_nonclaim_ok = ( + isinstance(rule_branches, list) + and bool(rule_branches) + and all(isinstance(branch, dict) and branch.get("legal_content_status") == "APPROVED" for branch in rule_branches) + ) or ( + isinstance(rule_row, dict) + and rule_row.get("non_claim_disposition") in {"COMPANION_ONLY", "CLASSIFICATION_ONLY"} + and isinstance(rule_row.get("companion_case_type_ids"), list) + ) + if ( + row.get("catalog_mapping_status") not in approved_values + or row.get("legal_signoff") not in approved_values + or row.get("technical_verification") not in approved_values + or row.get("release_status") not in approved_values + or not isinstance(downstream, dict) + or set(downstream) != downstream_keys + or any(value not in approved_values for value in downstream.values()) + or row.get("issue_codes") != [] + or not isinstance(registry_row, dict) + or registry_row.get("legal_classification_status") != "APPROVED" + or registry_row.get("legal_content_status") != "APPROVED" + or not isinstance(rule_row, dict) + or rule_row.get("legal_classification_status") != "APPROVED" + or rule_row.get("legal_content_status") != "APPROVED" + or not branch_or_nonclaim_ok + ): + coverage_rows_ok = False + coverage_catalog = require_object(coverage.get("catalog"), code="CASE_TYPE_COVERAGE_CATALOG") + coverage_dependency = require_object(coverage.get("registry_dependency"), code="CASE_TYPE_COVERAGE_REGISTRY_DEPENDENCY") + coverage_summary = require_object(coverage.get("summary"), code="CASE_TYPE_COVERAGE_SUMMARY") + coverage_ok = ( + coverage.get("release_eligible") is True + and coverage.get("status") == "FULL_137_PRODUCTION_READY" + and coverage_catalog.get("sha256") == case_registry.get("catalog_source_sha256") + and coverage_dependency.get("path") == CASE_TYPE_REGISTRY_REL + and coverage_dependency.get("sha256") == inputs.get("case_type_registry_sha256") + and rule_registry.get("case_type_registry_ref") == CASE_TYPE_REGISTRY_REL + and rule_registry.get("case_type_registry_sha256") == inputs.get("case_type_registry_sha256") + and coverage_summary.get("total_case_type_rows") == 137 + and coverage_summary.get("markdown_doc_count") == 137 + and coverage.get("release_scope_catalog_row_ids") == expected_catalog_ids + and coverage.get("excluded_catalog_row_ids") == [] + and coverage.get("release_scope_claim_capable_ids") == claim_capable_ids + and coverage_rows_ok + ) + gates = { + "binding": bool(binding_rows) and all(row.get("case_type_binding_status") == "BOUND" and row.get("sub_rule_binding_status") == "BOUND" for row in binding_rows), + "authority": authority_ok, + "renderer_branch": reduced["legal_assets_admitted"], + "rule_sub_rule": bool(structured_rules) and all(value.get("execution_eligible") is True and value.get("status") in {"APPROVED", "LEGAL_CONTENT_ADMITTED"} for value in structured_rules), + "review_policy": len(review_policies) == 1 and review_policies[0].get("execution_eligible") is True and review_policies[0].get("status") == "APPROVED_LEGAL_CONTENT", + "case_type_coverage_137": coverage_ok, + "corpus": bool(requirement_packs) and all(require_hex(value.get("corpus_release_sha256"), code="CORPUS_RELEASE_HASH") for value in requirement_packs), + "law_value": all(row.get("calculation_status") == "CALCULATED" and not row.get("missing_law_values") for row in calculations) if calculations else True, + "calculator": all(row.get("calculation_status") == "CALCULATED" for row in calculations) if calculations else True, + "required_receipts": False, + } + if set(gates) != REQUIRED_LEGAL_GATES: + raise S240Error("LEGAL_GATE_SET", "legal gate set is not closed") + return gates + + + def resolve_review_policy_contract( + inputs: Mapping[str, Any], validation: Sequence[Mapping[str, Any]], legal_gates: Mapping[str, bool], + ) -> dict[str, Any]: + policy_values = [ + (path, value) for path, value in inputs.get("frozen_assets", {}).items() + if isinstance(value, dict) and value.get("registry_id") == "S2-20-REVIEW-POLICY" + ] + if len(policy_values) > 1: + raise S240Error("REVIEW_POLICY_CARDINALITY", "multiple frozen review policies") + policy_path, policy = policy_values[0] if len(policy_values) == 1 else ( + "MISSING_REVIEW_POLICY", {"status": "MISSING_REVIEW_POLICY"}, + ) + active_tags = sorted({ + str(reason) for row in validation if row.get("evaluation_status") != "PASS" + for reason in row.get("reason_codes", []) + }) + runtime_triggers = sorted( + str(row.get("invariant_id")) for row in validation if row.get("evaluation_status") != "PASS" + ) + approved = policy.get("execution_eligible") is True and policy.get("status") == "APPROVED_LEGAL_CONTENT" + final_contract = policy.get("final_review_contract") if isinstance(policy.get("final_review_contract"), dict) else {} + allowed_types = set(final_contract.get("policy_result_enum", [ + "STANDARD_ATTORNEY_REVIEW", "MANDATORY_SPECIALIST_REVIEW", + ])) + if approved: + required_types = list(final_contract.get("base_required_receipt_types", [])) + for row in policy.get("policy_rows", []) if isinstance(policy.get("policy_rows"), list) else []: + if not isinstance(row, dict): + raise S240Error("REVIEW_POLICY_ROW", "review policy row must be an object") + row_tags = set(row.get("trigger_tags", row.get("active_tags", []))) + row_triggers = set(row.get("runtime_triggers", row.get("invariant_ids", []))) + if row.get("always_required") is True or row_tags.intersection(active_tags) or row_triggers.intersection(runtime_triggers): + required_types.extend(row.get("required_receipt_types", [])) + else: + default = policy.get("default_unapproved_result") if isinstance(policy.get("default_unapproved_result"), dict) else {} + required_types = list(default.get("required_receipt_types", ["STANDARD_ATTORNEY_REVIEW"])) + if any(not isinstance(value, str) or value not in allowed_types for value in required_types): + raise S240Error("REVIEW_POLICY_RECEIPT_TYPE", "policy emitted a receipt type outside its closed enum") + required_types = sorted(set(required_types)) + if "MANDATORY_SPECIALIST_REVIEW" in required_types: + base_policy = "MANDATORY_SPECIALIST_REVIEW" + elif "STANDARD_ATTORNEY_REVIEW" in required_types: + base_policy = "STANDARD_ATTORNEY_REVIEW" + else: + fallback = final_contract.get("missing_or_unapproved_policy_result", "STANDARD_ATTORNEY_REVIEW") + base_policy = fallback if fallback in allowed_types else "STANDARD_ATTORNEY_REVIEW" + pre_receipt_ready = ( + approved + and not active_tags + and all(value for key, value in legal_gates.items() if key != "required_receipts") + ) + return { + "policy_path": policy_path, "policy": policy, + "policy_registry_sha256": digest(policy), "base_policy": base_policy, + "active_tags": active_tags, "runtime_triggers": runtime_triggers, + "required_receipt_types": required_types, + "pre_receipt_ready_eligible": pre_receipt_ready, + } + + + def candidate_material(inputs: Mapping[str, Any], reduced: Mapping[str, Any], validation: Sequence[Mapping[str, Any]], request: Mapping[str, Any]) -> dict[str, Any]: + schema_store = require_object(inputs.get("schema_store"), code="OUTPUT_SCHEMA_STORE") + documents: dict[str, bytes] = {} + if reduced["clean_render_allowed"]: + documents = { + "claim_relief.md": canonical_markdown(reduced["relief"]), + "claim_cause.md": canonical_markdown(reduced["cause"]), + "pleading_draft.md": canonical_markdown(reduced["pleading"]), + } + legal_gates = legal_gate_snapshot(inputs, reduced) + review_contract = resolve_review_policy_contract(inputs, validation, legal_gates) + conservation = require_object(reduced.get("conservation"), code="CONSERVATION_OBJECT") + issue_source_keys = require_list(conservation.get("issue_source_keys"), code="ISSUE_SOURCE_KEYS") + assumption_source_keys = require_list(conservation.get("assumption_source_keys"), code="ASSUMPTION_SOURCE_KEYS") + usage_source_keys = require_list(conservation.get("usage_source_keys"), code="USAGE_SOURCE_KEYS") + if ( + len(issue_source_keys) != len(set(issue_source_keys)) + or len(issue_source_keys) != len(reduced["issues"]) + or len(assumption_source_keys) != len(set(assumption_source_keys)) + or len(assumption_source_keys) != len(reduced["assumptions"]) + or len(usage_source_keys) != len(set(usage_source_keys)) + or len(usage_source_keys) != len(reduced["usage"]) + ): + raise S240Error("REVIEW_UNIVERSE_CONSERVATION", "issue/assumption/usage occurrence universe was not conserved") + source_ledger_hashes = sorted({ + digest(inputs["ingress_raws"]["review/issue_ledger.base.json"]), + digest(inputs["plan_raw_by_path"]["plan/issue_ledger.plan.json"]), + }) + s210_issue_hashes = { + digest(raw) for path, raw in inputs["s210_handoff"]["raw_by_path"].items() + if path.startswith("map_s2_10/issue_patches/") + } + s230_issue_hashes = { + row["sha256"] for row in inputs["rows"] if row["part_family"] == "ISSUE_PATCH" + } + ledger = { + "schema_version": "stage2_s2_40_final_issue_ledger.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "source_ledger_sha256s": source_ledger_hashes, + "source_issue_part_sha256s": sorted(s210_issue_hashes | s230_issue_hashes), + "issues": reduced["issues"], "conservation_status": "PASS", + } + s210_assumption_hashes = sorted({ + digest(raw) for path, raw in inputs["s210_handoff"]["raw_by_path"].items() + if path.startswith("map_s2_10/assumption_parts/") + }) + assumptions = { + "schema_version": "stage2_s2_40_assumption_ledger.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "source_assumption_part_sha256s": s210_assumption_hashes, + "rows": reduced["assumptions"], "conservation_status": "PASS", + } + source_usage_hashes = sorted({ + row["source_part_sha256"] for row in reduced["usage"] + }) + usage_projection = { + "schema_version": "stage2_s2_40_usage_projection.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "source_usage_part_sha256s": source_usage_hashes, + "rows": reduced["usage"], "conservation_status": "PASS", + } + worknotes_core = { + "schema_version": "stage2_s2_40_attorney_worknotes_core.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "rows": reduced["worknotes"], + } + render_diagnostic = { + "schema_version": "stage2_s2_40_render_diagnostic.v1", + "render_errors": reduced["render_errors"], "render_absences": reduced["render_absences"], + "independent_rerender_equal": reduced["rerender_equal"], + } + review_policy_core = { + "schema_version": "stage2_s2_40_review_policy_core.v1", + "policy_registry_sha256": review_contract["policy_registry_sha256"], + "base_policy": review_contract["base_policy"], + "active_tags": review_contract["active_tags"], + "runtime_triggers": review_contract["runtime_triggers"], + "required_receipt_types": review_contract["required_receipt_types"], + "pre_receipt_ready_eligible": review_contract["pre_receipt_ready_eligible"], + } + review_basis = review_request_basis( + inputs, validation, review_contract, request["expected_parent_stage2_release_sha256"], + ) + dependency_snapshot = { + "parent_release_sha256": request["expected_parent_stage2_release_sha256"], + "upstream_barrier_sha256s": [ + request["expected_ingress_status_sha256"], request["expected_s2_10_publish_status_sha256"], + request["expected_plan_publish_status_sha256"], request["expected_s2_30_publish_status_sha256"], + ], + "ordered_source_digest": inputs["input_snapshot_digest"], + } + ordered_source_preimage = { + "schema_version": "stage2_s2_40_ordered_source_snapshot_preimage.v1", + "ordered_sha256s": inputs["input_snapshot_preimage"], + "snapshot_digest": inputs["input_snapshot_digest"], + } + generated_pre_manifest = ( + (ledger, "schemas/review_status.schema.json#/$defs/final_issue_ledger", "GENERATED_FINAL_ISSUE_SCHEMA"), + (assumptions, "schemas/review_status.schema.json#/$defs/assumption_ledger", "GENERATED_ASSUMPTION_SCHEMA"), + (usage_projection, "schemas/package.schema.json#/$defs/usage_projection", "GENERATED_USAGE_SCHEMA"), + (worknotes_core, "schemas/package.schema.json#/$defs/attorney_worknotes_core", "GENERATED_WORKNOTES_CORE_SCHEMA"), + (render_diagnostic, "schemas/package.schema.json#/$defs/render_diagnostic", "GENERATED_RENDER_DIAGNOSTIC_SCHEMA"), + (review_policy_core, "schemas/package.schema.json#/$defs/review_policy_core", "GENERATED_REVIEW_POLICY_CORE_SCHEMA"), + (dependency_snapshot, "schemas/package.schema.json#/$defs/dependency_snapshot", "GENERATED_DEPENDENCY_SCHEMA"), + (ordered_source_preimage, "schemas/package.schema.json#/$defs/ordered_source_snapshot_preimage", "GENERATED_ORDERED_SOURCE_SCHEMA"), + (review_basis, "schemas/package.schema.json#/$defs/review_request_basis", "GENERATED_REVIEW_BASIS_SCHEMA"), + (inputs["frozen_source_rows"], "schemas/package.schema.json#/$defs/frozen_source_rows", "GENERATED_FROZEN_SOURCE_SCHEMA"), + (legal_gates, "schemas/package.schema.json#/$defs/legal_gate_snapshot", "GENERATED_LEGAL_GATE_SCHEMA"), + ) + for value, schema_ref, code in generated_pre_manifest: + validate_schema_instance(value, schema_ref, schema_store, code=code) + pre_payloads: dict[str, tuple[bytes, str | None, str]] = { + "issue_ledger.final.json": (canonical_bytes(ledger), "schemas/review_status.schema.json#/$defs/final_issue_ledger", "application/json"), + "assumption_ledger.json": (canonical_bytes(assumptions), "schemas/review_status.schema.json#/$defs/assumption_ledger", "application/json"), + "llm_usage_projection.json": (canonical_bytes(usage_projection), "schemas/package.schema.json#/$defs/usage_projection", "application/json"), + "attorney_worknotes.core.json": (canonical_bytes(worknotes_core), "schemas/package.schema.json#/$defs/attorney_worknotes_core", "application/json"), + "render_diagnostic.json": (canonical_bytes(render_diagnostic), "schemas/package.schema.json#/$defs/render_diagnostic", "application/json"), + "review_policy_core.json": (canonical_bytes(review_policy_core), "schemas/package.schema.json#/$defs/review_policy_core", "application/json"), + "upstream_dependency_snapshot.json": (canonical_bytes(dependency_snapshot), "schemas/package.schema.json#/$defs/dependency_snapshot", "application/json"), + "ordered_source_snapshot_preimage.json": ( + canonical_bytes(ordered_source_preimage), + "schemas/package.schema.json#/$defs/ordered_source_snapshot_preimage", + "application/json", + ), + "review_request_basis.json": (canonical_bytes(review_basis), "schemas/package.schema.json#/$defs/review_request_basis", "application/json"), + "frozen_source_rows.json": (canonical_bytes(inputs["frozen_source_rows"]), "schemas/package.schema.json#/$defs/frozen_source_rows", "application/json"), + "legal_gate_snapshot.json": (canonical_bytes(legal_gates), "schemas/package.schema.json#/$defs/legal_gate_snapshot", "application/json"), + } + for name, payload in documents.items(): + pre_payloads[name] = (payload, None, "text/markdown; charset=utf-8") + artifact_rows = [ + { + "path": name, "raw_sha256": digest(payload), "content_type": content_type, + "size_bytes": len(payload), "schema_ref": schema_ref, "producer_id": "S2_40", + } + for name, (payload, schema_ref, content_type) in sorted(pre_payloads.items()) + ] + manifest_core = { + "schema_version": "stage2_s2_40_candidate_manifest_core.v1", + "producer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], "candidate_attempt_id": request["candidate_attempt_id"], + "dependency_snapshot": dependency_snapshot, "artifacts": artifact_rows, + } + validate_schema_instance( + manifest_core, "schemas/package.schema.json#/$defs/candidate_manifest_core", + schema_store, code="GENERATED_CANDIDATE_MANIFEST_SCHEMA", + ) + manifest_hash = digest(manifest_core) + statuses = aggregate_validation(validation) + validation_core = { + "schema_version": "stage2_s2_40_validation_core.v1", + "run_binding_digest": request["run_binding_digest"], + "compile_mode": request["compile_mode"], + "candidate_manifest_core_sha256": manifest_hash, + "invariant_results": list(validation), + "run_technical_status": statuses["run_technical_status"], + "artifact_technical_status": statuses["artifact_technical_status"], + } + validate_schema_instance( + validation_core, "schemas/package.schema.json#/$defs/validation_core", + schema_store, code="GENERATED_VALIDATION_CORE_SCHEMA", + ) + validation_hash = digest(validation_core) + document_sha256s = { + "claim_relief": digest(documents.get("claim_relief.md", b"")), + "claim_cause": digest(documents.get("claim_cause.md", b"")), + "pleading_draft": digest(documents.get("pleading_draft.md", b"")), + } + digest_core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + "run_binding_digest": request["run_binding_digest"], + "dependency_snapshot_sha256": digest(dependency_snapshot), + "candidate_manifest_core_sha256": manifest_hash, + "document_sha256s": document_sha256s, + "attorney_worknotes_core_sha256": digest(worknotes_core), + "final_issue_ledger_sha256": digest(ledger), + "assumption_ledger_sha256": digest(assumptions), + "validation_core_sha256": validation_hash, + "ordered_source_dependency_snapshot_digest": inputs["input_snapshot_digest"], + } + candidate_digest = digest(digest_core) + digest_envelope = { + **digest_core, + "candidate_content_digest": candidate_digest, + } + validate_schema_instance( + digest_envelope, "schemas/package.schema.json#/$defs/candidate_digest_envelope", + schema_store, code="GENERATED_CANDIDATE_DIGEST_SCHEMA", + ) + worknotes = { + "schema_version": "stage2_s2_40_attorney_worknotes.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], "candidate_content_digest": candidate_digest, + "rows": reduced["worknotes"], + } + validate_schema_instance( + worknotes, "schemas/package.schema.json#/$defs/attorney_worknotes", + schema_store, code="GENERATED_ATTORNEY_WORKNOTES_SCHEMA", + ) + packet_core = { + "schema_version": "stage2_s2_40_lawyer_review_packet_core.v1", + "candidate_content_digest": candidate_digest, + "finding_ids": sorted(row["finding_ids"][0] for row in validation if row["finding_ids"]), + "scope_ids": inputs["group_ids"], + "document_refs": sorted(documents) or ["issue_ledger.final.json"], + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + validation_envelope_core = { + "schema_version": "stage2_s2_40_validation_envelope_core.v1", + "candidate_content_digest": candidate_digest, + "validation_core_sha256": validation_hash, + "legal_readiness": "LAWYER_REVIEW_REQUIRED", + } + subject = review_subject( + candidate_digest, digest(packet_core), digest(validation_envelope_core), review_basis, + ) + validate_schema_instance( + packet_core, "schemas/package.schema.json#/$defs/lawyer_review_packet_core", + schema_store, code="GENERATED_REVIEW_PACKET_CORE_SCHEMA", + ) + validate_schema_instance( + validation_envelope_core, "schemas/package.schema.json#/$defs/validation_envelope_core", + schema_store, code="GENERATED_VALIDATION_ENVELOPE_CORE_SCHEMA", + ) + validate_schema_instance( + subject["subject"], "schemas/package.schema.json#/$defs/review_subject", + schema_store, code="GENERATED_REVIEW_SUBJECT_SCHEMA", + ) + packet = { + "schema_version": "stage2_s2_40_lawyer_review_packet.v1", + "lawyer_review_packet_core": packet_core, + "lawyer_review_packet_core_sha256": digest(packet_core), + "review_subject_digest": subject["review_subject_digest"], + } + validation_envelope = { + "schema_version": "stage2_s2_40_validation_envelope.v1", + "validation_envelope_core": validation_envelope_core, + "validation_envelope_core_sha256": digest(validation_envelope_core), + "review_subject_digest": subject["review_subject_digest"], + } + review_policy_result = { + "schema_version": "stage2_s2_40_review_policy_result.v1", + "candidate_content_digest": candidate_digest, + "policy_registry_sha256": review_contract["policy_registry_sha256"], + "base_policy": review_contract["base_policy"], + "active_tags": review_contract["active_tags"], + "runtime_triggers": review_contract["runtime_triggers"], + "required_receipt_types": review_contract["required_receipt_types"], + "ready_eligible": review_contract["pre_receipt_ready_eligible"], + } + for value, schema_ref, code in ( + (packet, "schemas/package.schema.json#/$defs/lawyer_review_packet", "GENERATED_REVIEW_PACKET_SCHEMA"), + (validation_envelope, "schemas/package.schema.json#/$defs/validation_envelope", "GENERATED_VALIDATION_ENVELOPE_SCHEMA"), + (review_policy_result, "schemas/review_status.schema.json#/$defs/review_policy_result", "GENERATED_REVIEW_POLICY_RESULT_SCHEMA"), + ): + validate_schema_instance(value, schema_ref, schema_store, code=code) + return { + "documents": documents, "pre_payloads": pre_payloads, "ledger": ledger, + "assumptions": assumptions, "usage_projection": usage_projection, "worknotes": worknotes, + "validation_core": validation_core, "manifest_core": manifest_core, + "validation_envelope": validation_envelope, + "candidate_digest_envelope": digest_envelope, "candidate_digest": candidate_digest, + "review": subject, "packet": packet, "legal_gates": legal_gates, + "review_policy_result": review_policy_result, "review_policy_path": review_contract["policy_path"], + "schema_store": schema_store, + } + + + def publish_candidate(client: McpClient, request: Mapping[str, Any], material: Mapping[str, Any]) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + candidate_digest = material["candidate_digest"] + candidate_root = join_path(root, "candidates/by-content-digest", candidate_digest) + outputs: list[tuple[str, bytes]] = [ + ("candidate_package_manifest.json", canonical_bytes(material["manifest_core"])), + ("candidate_content_digest.json", canonical_bytes(material["candidate_digest_envelope"])), + ("attorney_worknotes.json", canonical_bytes(material["worknotes"])), + ("validation_core.json", canonical_bytes(material["validation_core"])), + ("validation_envelope.json", canonical_bytes(material["validation_envelope"])), + ("review_subject.json", canonical_bytes(material["review"]["subject"])), + ("lawyer_review_packet.json", canonical_bytes(material["packet"])), + ] + outputs.extend((name, payload[0]) for name, payload in sorted(material["pre_payloads"].items())) + outputs.extend(sorted(material["documents"].items())) + deduplicated: dict[str, bytes] = {} + for name, payload in outputs: + if name in deduplicated and deduplicated[name] != payload: + raise S240Error("CANDIDATE_ARTIFACT_CONFLICT", f"candidate path conflicts: {name}") + deduplicated[name] = payload + rows: list[dict[str, Any]] = [] + for rel, payload in sorted(deduplicated.items()): + path = join_path(candidate_root, rel) + observed = client.write_immutable(path, payload) + rows.append({"path": path, "raw_sha256": observed, "size_bytes": len(payload), "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8"}) + review = material["review"] + review_publications: list[dict[str, Any]] = [] + for request_row in review["requests"]: + request_envelope = { + "schema_version": "stage2_s2_40_review_request.v1", + "request_id": request_row["request_id"], + "review_request_core": request_row["core"], + "review_request_core_sha256": request_row["core_sha256"], + "review_subject_digest": request_row["review_subject_digest"], + } + validate_schema_instance( + request_envelope, "schemas/review_status.schema.json#/$defs/review_request", + material["schema_store"], code="GENERATED_REVIEW_REQUEST_SCHEMA", + ) + review_path = join_path(root, "review/review_requests", f"{request_row['request_id']}.json") + review_hash = client.write_immutable(review_path, canonical_bytes(request_envelope)) + review_publications.append({ + "receipt_type": request_row["receipt_type"], "path": review_path, + "sha256": review_hash, "request": request_envelope, + }) + return { + "candidate_root": candidate_root, "artifact_rows": rows, + "review_requests": review_publications, + } + + + def validate_review_receipts(client: McpClient, request: Mapping[str, Any], material: Mapping[str, Any]) -> tuple[bool, bool, list[dict[str, Any]]]: + refs = request["review_receipt_refs"] + required_types = set(material["review_policy_result"].get("required_receipt_types", [])) + expected_requests = { + str(row["receipt_type"]): row + for row in require_list(material["review"].get("requests"), code="REVIEW_EXPECTED_REQUESTS") + } + if set(expected_requests) != required_types or len(expected_requests) != len(material["review"]["requests"]): + raise S240Error("REVIEW_REQUEST_SET", "review request map differs from required receipt types") + if not refs: + return not required_types, False, [] + rows: list[dict[str, Any]] = [] + content_change = False + approved_types: set[str] = set() + seen_types: set[str] = set() + schema_store = require_object(material.get("schema_store"), code="REVIEW_SCHEMA_STORE") + for ref in refs: + raw: bytes | None = None + value: dict[str, Any] = {} + reasons: list[str] = [] + try: + raw = client.read_binary(ref) + value = require_object(load_json(raw, label=ref), code="REVIEW_RECEIPT_OBJECT") + if client.read_binary(ref) != raw: + reasons.append("REVIEW_RECEIPT_TOCTOU") + if canonical_bytes(value) != raw: + reasons.append("REVIEW_RECEIPT_NON_CANONICAL") + try: + validate_schema_instance( + value, "schemas/review_status.schema.json#/$defs/review_receipt", + schema_store, code="REVIEW_RECEIPT_SCHEMA", + ) + except S240Error as exc: + reasons.append(exc.code) + receipt_type = value.get("receipt_type") + expected_request = expected_requests.get(str(receipt_type)) + if expected_request is None: + reasons.append("REVIEW_RECEIPT_TYPE_NOT_REQUIRED") + if receipt_type in seen_types: + reasons.append("REVIEW_RECEIPT_TYPE_DUPLICATE") + seen_types.add(str(receipt_type)) + expected_core = expected_request.get("core", {}) if expected_request is not None else {} + if expected_request is None or ( + value.get("request_id") != expected_request.get("request_id") + or value.get("candidate_content_digest") != material["candidate_digest"] + or value.get("review_subject_digest") != material["review"]["review_subject_digest"] + or value.get("finding_ids") != expected_core.get("finding_ids") + or value.get("scope_ids") != expected_core.get("scope_ids") + or value.get("reviewer_role") != expected_core.get("reviewer_role") + or value.get("reviewer_qualification") != expected_core.get("reviewer_qualification") + ): + reasons.append("REVIEW_RECEIPT_SUBJECT") + if ( + value.get("reviewer_role") != TRUSTED_REVIEW_ROLE + or value.get("reviewer_qualification") != TRUSTED_REVIEW_QUALIFICATION + or value.get("issuer_id") != TRUSTED_REVIEW_ISSUER + or value.get("key_id") not in TRUSTED_REVIEW_KEY_IDS + or value.get("signature_algorithm") != TRUSTED_REVIEW_SIGNATURE_ALGORITHM + ): + reasons.append("REVIEW_RECEIPT_ISSUER") + if value.get("cryptographic_verification_status") != "VERIFIED_BY_EXTERNAL_ADAPTER" or value.get("revocation_status") != "NOT_REVOKED": + reasons.append("REVIEW_RECEIPT_TRUST") + if HEX64.fullmatch(str(value.get("external_verification_attestation_sha256", ""))) is None: + reasons.append("REVIEW_RECEIPT_EXTERNAL_ATTESTATION") + try: + issued = datetime.fromisoformat(str(value.get("issued_at")).replace("Z", "+00:00")) + expires = datetime.fromisoformat(str(value.get("expires_at")).replace("Z", "+00:00")) + now = datetime.now(timezone.utc) + if issued.tzinfo is None or expires.tzinfo is None or issued > now or expires <= now or expires <= issued: + reasons.append("REVIEW_RECEIPT_TIME") + except (TypeError, ValueError): + reasons.append("REVIEW_RECEIPT_TIME") + disposition = value.get("review_disposition") + change_scope = value.get("change_scope") + expected_signed_material = digest([ + "STAGE2_S2_40_REVIEW_RECEIPT_V1", value.get("request_id"), + value.get("candidate_content_digest"), value.get("review_subject_digest"), + value.get("receipt_type"), value.get("finding_ids"), value.get("scope_ids"), + value.get("reviewer_role"), value.get("reviewer_qualification"), + value.get("issuer_id"), value.get("key_id"), value.get("signature_algorithm"), + value.get("external_verification_attestation_sha256"), + value.get("issued_at"), value.get("expires_at"), + value.get("revocation_status"), value.get("cryptographic_verification_status"), + disposition, change_scope, value.get("reason_codes"), + ]) + if value.get("signed_material_digest") != expected_signed_material: + reasons.append("REVIEW_RECEIPT_SIGNED_SCOPE") + if disposition == "CONTENT_CHANGE_REQUIRED": + if change_scope not in {"STAGE1_CONTEXT", "LEGAL_JUDGMENT", "PLAN_RULE_CALCULATION_BINDING", "DRAFTING_TEXT_ATOM"}: + reasons.append("REVIEW_CHANGE_SCOPE") + elif disposition != "APPROVE_AS_IS" or change_scope != "NONE": + reasons.append("REVIEW_RECEIPT_DISPOSITION") + except (S240Error, TypeError, ValueError) as exc: + reasons.append(exc.code if isinstance(exc, S240Error) else "REVIEW_RECEIPT_PARSE") + if not reasons and value.get("review_disposition") == "CONTENT_CHANGE_REQUIRED": + content_change = True + if not reasons and value.get("review_disposition") == "APPROVE_AS_IS": + approved_types.add(str(value.get("receipt_type"))) + row = { + "path": ref, "receipt_id": value.get("receipt_id"), + "receipt_type": value.get("receipt_type"), + "disposition": value.get("review_disposition"), + "change_scope": value.get("change_scope"), + "validation_status": "VALID" if not reasons else "INVALID", + "reason_codes": sorted(set(reasons)), + } + if raw is not None: + row["sha256"] = digest(raw) + rows.append(row) + approved = not content_change and approved_types == required_types and len(rows) == len(required_types) and all( + row.get("validation_status") == "VALID" for row in rows + ) + return approved, content_change, rows + + + def final_status( + client: McpClient, + request: Mapping[str, Any], + preflight_digest: str, + inputs: Mapping[str, Any], + material: Mapping[str, Any], + publication: Mapping[str, Any], + approved: bool, + content_change: bool, + review_rows: Sequence[Mapping[str, Any]], + ) -> dict[str, Any]: + root = request["stage2_run_root_ref"] + candidate_digest = material["candidate_digest"] + validation_rows = material["validation_core"]["invariant_results"] + all_pass = len(validation_rows) == 18 and all( + row["evaluation_status"] == "PASS" for row in validation_rows + ) + effective_gates = dict(material["legal_gates"]) + effective_gates["required_receipts"] = approved + full_production_gates = ( + request["compile_mode"] == "PRODUCTION" + and all_pass + and bool(material["documents"]) + and effective_gates == {key: True for key in REQUIRED_LEGAL_GATES} + and material["review_policy_result"]["ready_eligible"] + ) + receipt_hashes = sorted({ + str(row["sha256"]) for row in review_rows + if row.get("validation_status") == "VALID" + and HEX64.fullmatch(str(row.get("sha256", ""))) + }) + validation_hash = digest(material["validation_core"]) + review_subject_digest = material["review"]["review_subject_digest"] + if content_change: + scope_order = { + "STAGE1_CONTEXT": (0, "RESTART_FROM_S2_00"), + "LEGAL_JUDGMENT": (1, "RESTART_FROM_S2_10"), + "PLAN_RULE_CALCULATION_BINDING": (2, "RESTART_FROM_S2_20"), + "DRAFTING_TEXT_ATOM": (3, "RESTART_FROM_S2_30"), + } + scopes = [ + row["change_scope"] for row in review_rows + if row.get("validation_status") == "VALID" + and row.get("disposition") == "CONTENT_CHANGE_REQUIRED" + and row.get("change_scope") in scope_order + ] + if not scopes: + raise S240Error("REVIEW_CHANGE_SCOPE_MISSING", "content-change receipt lacks earliest-owner scope") + phase, route = "SUPERSEDED", scope_order[min(scopes, key=lambda value: scope_order[value][0])][1] + elif not full_production_gates: + phase, route = "AWAITING_EXTERNAL_REVIEW", "WAIT_EXTERNAL_REVIEW" + else: + phase, route = "READY_TO_COMMIT", "CONTINUE_TO_COMMIT" + artifact_set_digest: str | None = None + stage2_package_sha256: str | None = None + commit_intent_sha256: str | None = None + commit_result_sha256: str | None = None + if phase == "READY_TO_COMMIT": + final_payloads: dict[str, bytes] = { + "candidate_package_manifest.json": canonical_bytes(material["manifest_core"]), + "candidate_content_digest.json": canonical_bytes(material["candidate_digest_envelope"]), + "attorney_worknotes.json": canonical_bytes(material["worknotes"]), + "lawyer_review_packet.json": canonical_bytes(material["packet"]), + "stage2_final_validation_report.json": canonical_bytes(material["validation_core"]), + "review_policy_result.json": canonical_bytes(material["review_policy_result"]), + } + for rel, value in sorted(material["pre_payloads"].items()): + if rel in final_payloads and final_payloads[rel] != value[0]: + raise S240Error("FINAL_ARTIFACT_CONFLICT", f"final artifact path conflicts: {rel}") + final_payloads[rel] = value[0] + final_payloads.update(material["documents"]) + package_artifacts = [ + { + "path": join_path(root, "final", rel), "raw_sha256": digest(payload), + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, "producer_id": "S2_40", + } + for rel, payload in sorted(final_payloads.items()) + ] + package = { + "schema_version": "stage2_s2_40_package.v1", + "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "compile_mode": request["compile_mode"], + "candidate_manifest_core_sha256": digest(material["manifest_core"]), + "artifacts": package_artifacts, + "validation_report_sha256": validation_hash, + "review_policy_result_sha256": digest(material["review_policy_result"]), + "review_receipt_sha256s": receipt_hashes, + "filing_decision_receipt_sha256": None, + "run_technical_status": "CONSISTENT", + "artifact_technical_status": "CONSISTENT", + "legal_readiness": "READY_FOR_LAWYER_FILING_DECISION", + "filing_permission": "NOT_GRANTED", + } + validate_schema_instance( + package, "schemas/package.schema.json#/$defs/stage2_package", + material["schema_store"], code="GENERATED_STAGE2_PACKAGE_SCHEMA", + ) + package_payload = canonical_bytes(package) + stage2_package_sha256 = digest(package_payload) + final_payloads["stage2_package.json"] = package_payload + expected_rows = [ + { + "path": join_path(root, "final", rel), "raw_sha256": digest(payload), + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, + } + for rel, payload in sorted(final_payloads.items()) + ] + intent_core = { + "schema_version": "stage2_s2_40_commit_intent.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "candidate_attempt_id": request["candidate_attempt_id"], + "candidate_manifest_core_sha256": digest(material["manifest_core"]), + "validation_report_sha256": validation_hash, + "review_subject_digest": review_subject_digest, + "review_receipt_sha256s": receipt_hashes, + "stage2_package_sha256": stage2_package_sha256, + "expected_artifacts": expected_rows, + "previous_run_status_sha256": request["expected_previous_run_status_sha256"], + "request_sha256": request["_request_sha256"], + "host_cas_receipt_sha256": request["host_cas_receipt_sha256"], + } + intent = {**intent_core, "intent_digest": digest(intent_core)} + validate_schema_instance( + intent, "schemas/deployment.schema.json#/$defs/s2_40_commit_intent", + material["schema_store"], code="GENERATED_COMMIT_INTENT_SCHEMA", + ) + intent_path = join_path(root, "commit/commit_intent.json") + commit_intent_sha256 = client.write_immutable(intent_path, canonical_bytes(intent)) + final_rows: list[dict[str, Any]] = [] + for rel, payload in sorted(final_payloads.items()): + path = join_path(root, "final", rel) + observed = client.write_immutable(path, payload) + final_rows.append({ + "path": path, "raw_sha256": observed, + "content_type": "application/json" if rel.endswith(".json") else "text/markdown; charset=utf-8", + "size_bytes": len(payload), "schema_ref": None, + }) + if final_rows != expected_rows: + raise S240Error("COMMIT_EXPECTED_ROWS", "written final rows differ from commit intent") + artifact_set_digest = digest(final_rows) + result_core = { + "schema_version": "stage2_s2_40_commit_result.v1", "producer_id": "S2_40", + "run_binding_digest": request["run_binding_digest"], + "candidate_content_digest": candidate_digest, + "commit_intent_sha256": commit_intent_sha256, + "artifact_set_digest": artifact_set_digest, + "artifact_rows": final_rows, + "readback_status": "PASS", "conflicting_target_count": 0, + "missing_target_count_after_write": 0, + } + result = {**result_core, "commit_result_digest": digest(result_core)} + validate_schema_instance( + result, "schemas/deployment.schema.json#/$defs/s2_40_commit_result", + material["schema_store"], code="GENERATED_COMMIT_RESULT_SCHEMA", + ) + commit_result_sha256 = client.write_immutable( + join_path(root, "commit/stage2_commit_result.json"), canonical_bytes(result), + ) + phase, route = "COMMITTED", "PACKAGE_COMMITTED" + aggregate = aggregate_validation(validation_rows) + if aggregate["run_technical_status"] == "TECHNICAL_INCOMPLETE": + artifact_status, legal_readiness = "NOT_PRODUCED", "NOT_ASSESSED" + else: + artifact_status = aggregate["artifact_technical_status"] + legal_readiness = "READY_FOR_LAWYER_FILING_DECISION" if full_production_gates else "LAWYER_REVIEW_REQUIRED" + return write_terminal_status( + client, request, workflow_phase=phase, route=route, + candidate_content_digest=candidate_digest, + run_technical_status=aggregate["run_technical_status"], + artifact_technical_status=artifact_status, legal_readiness=legal_readiness, + validation_report_sha256=validation_hash, + review_subject_digest=review_subject_digest, + review_receipt_sha256s=receipt_hashes, + stage2_package_sha256=stage2_package_sha256, + artifact_set_digest=artifact_set_digest, + commit_intent_sha256=commit_intent_sha256, + commit_result_sha256=commit_result_sha256, + schema_store=material["schema_store"], + ) + + + def verify_frozen_candidate_digest_chain( + expected: str, + manifest: Mapping[str, Any], + envelope: Mapping[str, Any], + pre_payloads: Mapping[str, tuple[bytes, str | None, str]], + documents: Mapping[str, bytes], + validation_core: Mapping[str, Any], + ) -> dict[str, Any]: + """Recompute every pre-review candidate digest edge from frozen bytes.""" + def payload_json(name: str) -> Any: + if name not in pre_payloads: + raise S240Error("RESUME_REQUIRED_ARTIFACT", f"required frozen artifact missing: {name}") + raw = pre_payloads[name][0] + value = load_json(raw, label=name) + if canonical_bytes(value) != raw: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {name}") + return value + + dependency = require_object(manifest.get("dependency_snapshot"), code="RESUME_DEPENDENCY_SNAPSHOT") + persisted_dependency = require_object( + payload_json("upstream_dependency_snapshot.json"), code="RESUME_PERSISTED_DEPENDENCY", + ) + if persisted_dependency != dependency: + raise S240Error("RESUME_DEPENDENCY_SNAPSHOT_DRIFT", "embedded and persisted dependency snapshots differ") + ordered_preimage = require_object( + payload_json("ordered_source_snapshot_preimage.json"), code="RESUME_ORDERED_SOURCE_PREIMAGE", + ) + ordered_hashes = require_list(ordered_preimage.get("ordered_sha256s"), code="RESUME_ORDERED_SOURCE_HASHES") + for value in ordered_hashes: + require_hex(value, code="RESUME_ORDERED_SOURCE_HASH") + ordered_digest = digest(ordered_hashes) + if ( + ordered_preimage.get("snapshot_digest") != ordered_digest + or dependency.get("ordered_source_digest") != ordered_digest + ): + raise S240Error("RESUME_ORDERED_SOURCE_DIGEST", "ordered source preimage digest differs") + worknotes_core = require_object( + payload_json("attorney_worknotes.core.json"), code="RESUME_WORKNOTES_CORE", + ) + ledger = require_object(payload_json("issue_ledger.final.json"), code="RESUME_FINAL_ISSUE_LEDGER") + assumptions = require_object(payload_json("assumption_ledger.json"), code="RESUME_ASSUMPTION_LEDGER") + document_sha256s = { + "claim_relief": digest(documents.get("claim_relief.md", b"")), + "claim_cause": digest(documents.get("claim_cause.md", b"")), + "pleading_draft": digest(documents.get("pleading_draft.md", b"")), + } + digest_core = { + "schema_version": "stage2_s2_40_candidate_content_digest.v1", + "domain_separator": "STAGE2_S2_40_CANDIDATE_CONTENT_V1", + "run_binding_digest": manifest.get("run_binding_digest"), + "dependency_snapshot_sha256": digest(dependency), + "candidate_manifest_core_sha256": digest(manifest), + "document_sha256s": document_sha256s, + "attorney_worknotes_core_sha256": digest(worknotes_core), + "final_issue_ledger_sha256": digest(ledger), + "assumption_ledger_sha256": digest(assumptions), + "validation_core_sha256": digest(validation_core), + "ordered_source_dependency_snapshot_digest": ordered_digest, + } + recomputed = digest(digest_core) + if recomputed != expected or envelope != {**digest_core, "candidate_content_digest": recomputed}: + raise S240Error("RESUME_CANDIDATE_DIGEST_CHAIN", "frozen candidate digest chain does not recompute exactly") + return { + "dependency": dependency, "ordered_source_preimage": ordered_preimage, + "worknotes_core": worknotes_core, "ledger": ledger, "assumptions": assumptions, + } + + + def hydrate_frozen_candidate(client: McpClient, request: Mapping[str, Any]) -> dict[str, Any]: + """RESUME validates and re-derives the frozen candidate without upstream rerendering.""" + root = request["stage2_run_root_ref"] + expected = require_hex(request["expected_candidate_content_digest"], code="RESUME_CANDIDATE_HASH") + schema_store = load_output_schema_store(client) + + def canonical_bound_json(path: str, expected_sha256: str | None = None) -> tuple[dict[str, Any], bytes]: + value, raw = read_bound_json(client, path, expected_sha256) + if canonical_bytes(value) != raw: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {path}") + return value, raw + + previous, _ = canonical_bound_json( + join_path(root, "control/run_status.json"), request["expected_previous_run_status_sha256"], + ) + validate_schema_instance( + previous, "schemas/review_status.schema.json#/$defs/run_status", + schema_store, code="RESUME_PREVIOUS_STATUS_SCHEMA", + ) + if ( + previous.get("candidate_content_digest") != expected + or previous.get("workflow_phase") != "AWAITING_EXTERNAL_REVIEW" + or previous.get("compile_mode") != request["compile_mode"] + or previous.get("run_binding_digest") != request["run_binding_digest"] + or previous.get("candidate_attempt_id") != request["candidate_attempt_id"] + ): + raise S240Error("RESUME_CHECKPOINT", "previous status does not bind the frozen candidate") + candidate_root = join_path(root, "candidates/by-content-digest", expected) + if PurePosixPath(candidate_root).name != expected: + raise S240Error("RESUME_CANDIDATE_DIRECTORY", "candidate directory basename differs from expected digest") + manifest, _ = canonical_bound_json(join_path(candidate_root, "candidate_package_manifest.json")) + envelope, _ = canonical_bound_json(join_path(candidate_root, "candidate_content_digest.json")) + validate_schema_instance( + manifest, "schemas/package.schema.json#/$defs/candidate_manifest_core", + schema_store, code="RESUME_CANDIDATE_MANIFEST_SCHEMA", + ) + validate_schema_instance( + envelope, "schemas/package.schema.json#/$defs/candidate_digest_envelope", + schema_store, code="RESUME_CANDIDATE_ENVELOPE_SCHEMA", + ) + expected_upstream = [ + request["expected_ingress_status_sha256"], request["expected_s2_10_publish_status_sha256"], + request["expected_plan_publish_status_sha256"], request["expected_s2_30_publish_status_sha256"], + ] + dependency = require_object(manifest.get("dependency_snapshot"), code="RESUME_DEPENDENCY_SNAPSHOT") + if ( + manifest.get("producer_id") != "S2_40" + or manifest.get("run_binding_digest") != request["run_binding_digest"] + or manifest.get("compile_mode") != request["compile_mode"] + or manifest.get("candidate_attempt_id") != request["candidate_attempt_id"] + or dependency.get("parent_release_sha256") != request["expected_parent_stage2_release_sha256"] + or dependency.get("upstream_barrier_sha256s") != expected_upstream + ): + raise S240Error("RESUME_DEPENDENCY_DRIFT", "RESUME request differs from the frozen dependency snapshot") + pre_payloads: dict[str, tuple[bytes, str | None, str]] = {} + documents: dict[str, bytes] = {} + artifact_rows = require_list(manifest.get("artifacts"), code="RESUME_ARTIFACT_ROWS") + artifact_paths = [safe_path(row.get("path"), code="RESUME_ARTIFACT_PATH") for row in artifact_rows if isinstance(row, dict)] + if len(artifact_paths) != len(artifact_rows) or artifact_paths != sorted(artifact_paths) or len(set(artifact_paths)) != len(artifact_paths): + raise S240Error("RESUME_ARTIFACT_SET", "candidate artifact paths must be unique and sorted") + for row in artifact_rows: + row = require_object(row, code="RESUME_ARTIFACT_ROW") + rel = safe_path(row.get("path"), code="RESUME_ARTIFACT_PATH") + raw_a = client.read_binary(join_path(candidate_root, rel)) + raw_b = client.read_binary(join_path(candidate_root, rel)) + if raw_a != raw_b: + raise S240Error("RESUME_ARTIFACT_TOCTOU", f"frozen candidate artifact changed: {rel}") + if digest(raw_a) != require_hex(row.get("raw_sha256"), code="RESUME_ARTIFACT_HASH") or len(raw_a) != row.get("size_bytes"): + raise S240Error("RESUME_ARTIFACT_DRIFT", f"frozen candidate artifact differs: {rel}") + content_type = str(row.get("content_type")) + schema_ref = row.get("schema_ref") + if content_type.startswith("text/markdown"): + if schema_ref is not None: + raise S240Error("RESUME_MARKDOWN_SCHEMA_REF", f"markdown must not declare JSON schema: {rel}") + documents[rel] = raw_a + else: + if not isinstance(schema_ref, str): + raise S240Error("RESUME_JSON_SCHEMA_REF", f"JSON artifact lacks schema binding: {rel}") + value = load_json(raw_a, label=rel) + if canonical_bytes(value) != raw_a: + raise S240Error("RESUME_NON_CANONICAL_JSON", f"frozen JSON is not canonical: {rel}") + validate_schema_instance(value, schema_ref, schema_store, code="RESUME_ARTIFACT_SCHEMA") + pre_payloads[rel] = (raw_a, schema_ref, content_type) + + def auxiliary_json(name: str, schema_ref: str) -> dict[str, Any]: + value, _ = canonical_bound_json(join_path(candidate_root, name)) + validate_schema_instance(value, schema_ref, schema_store, code="RESUME_AUXILIARY_SCHEMA") + return value + + validation_core = auxiliary_json("validation_core.json", "schemas/package.schema.json#/$defs/validation_core") + packet = auxiliary_json("lawyer_review_packet.json", "schemas/package.schema.json#/$defs/lawyer_review_packet") + worknotes = auxiliary_json("attorney_worknotes.json", "schemas/package.schema.json#/$defs/attorney_worknotes") + validation_envelope = auxiliary_json("validation_envelope.json", "schemas/package.schema.json#/$defs/validation_envelope") + stored_subject = auxiliary_json("review_subject.json", "schemas/package.schema.json#/$defs/review_subject") + chain = verify_frozen_candidate_digest_chain( + expected, manifest, envelope, pre_payloads, documents, validation_core, + ) + if ( + worknotes.get("candidate_content_digest") != expected + or worknotes.get("rows") != chain["worknotes_core"].get("rows") + or packet.get("lawyer_review_packet_core_sha256") != digest(packet.get("lawyer_review_packet_core")) + or validation_envelope.get("validation_envelope_core_sha256") != digest(validation_envelope.get("validation_envelope_core")) + or validation_envelope.get("validation_envelope_core", {}).get("validation_core_sha256") != digest(validation_core) + ): + raise S240Error("RESUME_AUXILIARY_DIGEST_CHAIN", "frozen auxiliary candidate objects do not recompute") + review_basis = require_object( + load_json(pre_payloads["review_request_basis.json"][0], label="review_request_basis"), + code="RESUME_REVIEW_BASIS", + ) + rebuilt_review = review_subject( + expected, packet["lawyer_review_packet_core_sha256"], + validation_envelope["validation_envelope_core_sha256"], review_basis, + ) + if ( + rebuilt_review["subject"] != stored_subject + or packet.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + or validation_envelope.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + or previous.get("review_subject_digest") != rebuilt_review["review_subject_digest"] + ): + raise S240Error("RESUME_REVIEW_SUBJECT", "frozen review subject does not re-derive exactly") + for request_row in rebuilt_review["requests"]: + request_path = join_path(root, "review/review_requests", f"{request_row['request_id']}.json") + review_request, _ = canonical_bound_json(request_path) + validate_schema_instance( + review_request, "schemas/review_status.schema.json#/$defs/review_request", + schema_store, code="RESUME_REVIEW_REQUEST_SCHEMA", + ) + expected_request = { + "schema_version": "stage2_s2_40_review_request.v1", + "request_id": request_row["request_id"], + "review_request_core": request_row["core"], + "review_request_core_sha256": request_row["core_sha256"], + "review_subject_digest": request_row["review_subject_digest"], + } + if review_request != expected_request: + raise S240Error("RESUME_REVIEW_REQUEST_DRIFT", f"frozen review request differs: {request_row['receipt_type']}") + review_policy_core = require_object( + load_json(pre_payloads["review_policy_core.json"][0], label="review_policy_core"), + code="RESUME_REVIEW_POLICY_CORE", + ) + policy_result = { + "schema_version": "stage2_s2_40_review_policy_result.v1", + "candidate_content_digest": expected, + "policy_registry_sha256": review_policy_core.get("policy_registry_sha256"), + "base_policy": review_policy_core.get("base_policy"), + "active_tags": review_policy_core.get("active_tags"), + "runtime_triggers": review_policy_core.get("runtime_triggers"), + "required_receipt_types": review_policy_core.get("required_receipt_types"), + "ready_eligible": review_policy_core.get("pre_receipt_ready_eligible") is True, + } + validate_schema_instance( + policy_result, "schemas/review_status.schema.json#/$defs/review_policy_result", + schema_store, code="RESUME_REVIEW_POLICY_RESULT_SCHEMA", + ) + frozen_sources = require_list( + load_json(pre_payloads["frozen_source_rows.json"][0], label="frozen_source_rows"), + code="RESUME_FROZEN_SOURCE_ROWS", + ) + manifest_rows = [ + row for row in frozen_sources if isinstance(row, dict) + and row.get("path") == "map_s2_30/artifact_manifest.json" + and row.get("ref_family") == "upstream_manifest" + ] + if len(manifest_rows) != 1 or manifest_rows[0].get("sha256") != request["expected_s2_30_artifact_manifest_sha256"]: + raise S240Error("RESUME_MANIFEST_DRIFT", "RESUME request differs from frozen S2_30 artifact manifest") + legal_gates = require_object( + load_json(pre_payloads["legal_gate_snapshot.json"][0], label="legal_gate_snapshot"), + code="RESUME_LEGAL_GATES", + ) + return { + "documents": documents, "pre_payloads": pre_payloads, + "manifest_core": manifest, "candidate_digest_envelope": envelope, + "candidate_digest": expected, "validation_core": validation_core, + "packet": packet, "worknotes": worknotes, "legal_gates": legal_gates, + "review_policy_result": policy_result, "review": rebuilt_review, + "schema_store": schema_store, + } + + + def normal_route(client: McpClient, request: Mapping[str, Any], preflight_digest: str) -> dict[str, Any]: + if request["requested_transition"] == "RESUME": + inputs: dict[str, Any] = {} + material = hydrate_frozen_candidate(client, request) + publication: dict[str, Any] = {"resume_reused_frozen_candidate": True} + else: + inputs = hydrate_normal(client, request) + reduced = reduce_and_render(inputs, request) + validation = invariant_results(inputs, reduced, request) + material = candidate_material(inputs, reduced, validation, request) + publication = publish_candidate(client, request, material) + approved, content_change, review_rows = validate_review_receipts(client, request, material) + return final_status(client, request, preflight_digest, inputs, material, publication, approved, content_change, review_rows) + + + def publish_post_preflight_failure( + client: McpClient, request: Mapping[str, Any], preflight_digest: str, error: Mapping[str, Any], + ) -> dict[str, Any]: + """Preserve a closed diagnostic, then publish the failure barrier last.""" + root = request["stage2_run_root_ref"] + diagnostic = { + "schema_version": "stage2_s2_40_technical_diagnostic.v1", + "writer_id": "S2_40", "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "reason_codes": [str(error.get("code", "INLINE_RUNTIME_ERROR"))], + "error": dict(error), "preflight_snapshot_digest": preflight_digest, + } + diagnostic_id = digest(diagnostic) + client.write_immutable( + join_path(root, "diagnostic", f"failure-{diagnostic_id}.json"), + canonical_bytes(diagnostic), + ) + return write_terminal_status( + client, request, workflow_phase="DIAGNOSTIC_ONLY", + route="STOP_TECHNICAL_INCOMPLETE", candidate_content_digest=None, + run_technical_status="TECHNICAL_INCOMPLETE", + artifact_technical_status="NOT_PRODUCED", legal_readiness="NOT_ASSESSED", + ) + + + def run() -> int: + localdocs: McpClient | None = None + request: dict[str, Any] | None = None + receipt: dict[str, Any] + exit_code = 0 + preflight_digest: str | None = None + output_schema_store: dict[str, Mapping[str, Any]] | None = None + try: + with contextlib.redirect_stdout(io.StringIO()): + if HEX64.fullmatch(INLINE_USER_HASH) is None or HEX64.fullmatch(INLINE_WORKSPACE_HASH) is None: + raise S240Error("INLINE_CONTEXT_UNBOUND", "AgentBackend user/workspace substitutions are required") + localdocs = McpClient(LOCALDOCS_URL, "localdocs") + localdocs.initialize() + request_raw = localdocs.read_binary(REQUEST_PATH) + request = validate_request(request_raw) + request["_request_sha256"] = digest(request_raw) + preflight_digest = preflight(localdocs, request) + output_schema_store = load_output_schema_store(localdocs) + publication = status_only(localdocs, request, preflight_digest) if request["entry_route"] == "TO_S2_40_STATUS_ONLY" else normal_route(localdocs, request, preflight_digest) + status = publication["status"] + receipt = { + "schema_version": "stage2_s2_40_execution_receipt.v1", + "ok": True, + "workflow_id": WORKFLOW_ID, + "request_id": request["request_id"], + "run_binding_digest": request["run_binding_digest"], + "candidate_attempt_id": request["candidate_attempt_id"], + "requested_transition": request["requested_transition"], + "workflow_phase": status["workflow_phase"], + "candidate_content_digest": status["candidate_content_digest"], + "route": status["route"], + "run_status_path": publication["status_path"], + "run_status_sha256": publication["status_sha256"], + "error": None, + } + except Exception as exc: + error = exc.as_dict() if isinstance(exc, S240Error) else {"code": "INLINE_RUNTIME_ERROR", "message": str(exc)} + failure_publication: dict[str, Any] | None = None + if localdocs is not None and request is not None and preflight_digest is not None: + try: + failure_publication = publish_post_preflight_failure(localdocs, request, preflight_digest, error) + except Exception as close_exc: + error = { + "code": "POST_PREFLIGHT_FAILURE_AND_SAFE_CLOSE_FAILED", + "message": str(exc), + "safe_close_error": close_exc.as_dict() if isinstance(close_exc, S240Error) else {"message": str(close_exc)}, + } + fallback_binding = request["run_binding_digest"] if request is not None else "0" * 64 + receipt = { + "schema_version": "stage2_s2_40_execution_receipt.v1", + "ok": False, + "workflow_id": WORKFLOW_ID, + "request_id": request["request_id"] if request is not None else "UNBOUND", + "run_binding_digest": fallback_binding, + "candidate_attempt_id": request["candidate_attempt_id"] if request is not None else "UNBOUND", + "requested_transition": request["requested_transition"] if request is not None else "FREEZE", + "workflow_phase": "DIAGNOSTIC_ONLY", + "candidate_content_digest": None, + "route": "STOP_TECHNICAL_INCOMPLETE", + "run_status_path": failure_publication["status_path"] if failure_publication is not None else None, + "run_status_sha256": failure_publication["status_sha256"] if failure_publication is not None else None, + "error": error, + } + exit_code = 2 + finally: + if localdocs is not None: + localdocs.close() + if output_schema_store is not None: + validate_schema_instance( + receipt, "schemas/deployment.schema.json#/$defs/s2_40_execution_receipt", + output_schema_store, code="GENERATED_EXECUTION_RECEIPT_SCHEMA", + ) + sys.stdout.buffer.write(canonical_bytes(receipt)) + return exit_code + + + if __name__ == "__main__": + raise SystemExit(run()) + task_procedure: + IN: + nexts: + - Task_S2_40_deterministic_finalizer + wait_until: [] + Task_S2_40_deterministic_finalizer: + nexts: + - OUT + wait_until: + - IN + OUT: + nexts: [] + wait_until: + - Task_S2_40_deterministic_finalizer diff --git a/Case_02_Comparison_Research/plans/s2-40-final-validation-package.md b/Case_02_Comparison_Research/plans/s2-40-final-validation-package.md new file mode 100644 index 00000000..ecafba45 --- /dev/null +++ b/Case_02_Comparison_Research/plans/s2-40-final-validation-package.md @@ -0,0 +1,122 @@ +# S2_40 Final Validation Package + +## Objective + +Implement the S2_40 deterministic final-validation, closed-rendering, review-state, sealing, and logical-commit package specified by `stage_2_optimal_update_strategy_v.5-1.md`. + +## Deliverables + +- `YAML_Prompts/2. Stage_2/S2_40_SOW.md` +- `YAML_Prompts/2. Stage_2/S2_40_assets.md` +- `YAML_Prompts/2. Stage_2/Stage_2_S2_40.yml` +- Version-free S2_40 runtime, schema, workflow, renderer, validator, release, fixture, and test assets under `YAML_Prompts/2. Stage_2/Default_Agent/Stage_2_Clean/` +- Updated shared release/hash-chain assets required to admit S2_40 without introducing a legacy v0-v3 runtime dependency +- A compact Stage 2 `MEMORY.md` entry + +## Scope and Non-Scope + +In scope: offline-contract implementation, deterministic inline Python, closed rendering, V01-V18 validation, candidate freeze/resume, external-receipt validation, content-addressed writes, read-back verification, and status-last barrier behavior. + +Out of scope: live AgentBackend/MCP admission, real Korean-lawyer sign-off, filing, external publication, production credential binding, and claims that 137-case legal coverage is complete when the physical rule/corpus approvals remain pending. + +## Known Inputs + +- `stage_2_optimal_update_strategy_v.5-1.md` +- `S2_00_SOW_v.2.md`, `S2_10_SOW_v.1.md`, `S2_20_SOW.md`, `S2_30_SOW.md` +- `S2_00_assets_v.2.md`, `S2_10_assets_v.1.md`, `S2_20_assets.md`, `S2_30_assets.md` +- `Stage_2_S2_00_v.2.yml`, `Stage_2_S2_10_v.1.yml`, `Stage_2_S2_20.yml`, `Stage_2_S2_30.yml` +- Current `Default_Agent/Stage_2_Clean/` release closure +- Local `SKILL.md` and `test_code_executor.ipynb` + +## Material Assumptions + +- Despite the prompt label `[LLM: group-parallel, immutable parts]`, S2_40 follows the controlling v5-1 contract and is a deterministic, exactly-one Code Executor task. It consumes S2_30 group-parallel immutable parts. +- Existing unrelated dirty-worktree changes remain untouched. +- Existing pending live/legal receipts stay pending unless this task produces actual external evidence, which it does not. + +## Questions That Could Change the Outcome + +- Whether the deployed localdocs platform supports every claimed binary-read/write and barrier behavior is a live-admission question; offline implementation must preserve it as pending rather than assume success. +- Any upstream S2_30 contract defect that prevents trustworthy S2_40 admission must be either repaired and resealed or surfaced as a blocking upstream dependency; it may not be silently accepted. + +## Workstreams and Dependencies + +1. Analyze controlling contracts and current package closure. +2. Draft SOW and asset inventory independently in parallel. +3. Perform exactly two independent review rounds over both documents; apply only evidenced incremental revisions. +4. Generate S2_40 assets and the authoring YAML in parallel. +5. Perform two asset-validation rounds and two YAML-validation rounds as requested, respecting available concurrency and using stable asset-family assignments. +6. Rebuild/reseal dependent manifests, bindings, receipts, and upstream hash echoes. +7. Run targeted and full regression, parity, unique-key parse, inline-code compile, release-closure, and legacy-dependency checks. +8. Update `MEMORY.md` with verified results and residual boundaries. + +## Source and Tool Plan + +- Use local repository sources as the controlling implementation record. +- Use `rg`/`rg --files` for discovery and existing builder/test scripts for mechanical generation and validation. +- Use `apply_patch` for authored edits; use formatting/build scripts only for mechanical projections and resealing. +- Do not use live network or external legal sources unless a newly introduced legal proposition requires verification. + +## Validation Plan + +- YAML unique-key parse and exact `task_procedure`/task semantics. +- Exactly one S2_40 `mcp: code-executor` / `run_code` task; no LLM fields or external Python runtime import. +- Inline Python compile, static AST guard, single-JSON stdout, localdocs user/workspace binding, and `.py`/`.txt` byte parity. +- Closed schema and path/hash/producer membership for all S2_40 inputs/outputs. +- V01-V18 fixtures, candidate freeze/resume, receipt mismatch, supersession, partial write, idempotent re-entry, barrier-last, and commit-conflict tests. +- Authoring/deployment projection parity and release/hash-chain reproducibility. +- Full S2_00-S2_40 offline regression and zero runtime references to Stage 2 v0-v3. + +## Approval Boundaries + +- Local file creation and non-destructive tests are authorized. +- No external write, filing, publication, production promotion, secret access, or dependency installation. + +## Progress + +- [x] Read governing repository rules and Stage 2 memory. +- [x] Identify the controlling S2_40 deterministic boundary. +- [x] Draft SOW and asset inventory. +- [x] Complete document review round 1. +- [x] Complete document review round 2. +- [x] Implement assets and authoring YAML. +- [x] Complete asset validation rounds 1 and 2. +- [x] Complete YAML validation rounds 1 and 2. +- [x] Reseal the package and run full validation. +- [x] Update Stage 2 memory. + +## Decision Log + +| Date/Stage | Decision | Basis | Consequence | +|---|---|---|---| +| 2026-09-01 / intake | Treat S2_40 as deterministic rather than LLM-direct | v5-1 §§0, 2, 9, 16 and the five-task execution constitution | GPT-5.6 settings do not appear in the S2_40 task; S2_30 remains the group-parallel LLM owner | +| 2026-09-01 / trust boundary | Preserve live and legal admission as pending | No live Code Executor, external receipt, corpus approval, or lawyer sign-off is authorized or available | Offline verification cannot be reported as production readiness | +| 2026-09-01 / final YAML audit | Apply the second YAML audit without opening a third review loop | The requested two YAML review/revision loops are complete; remaining work is implementation correction and deterministic verification | Finish full S2_00/S2_10 hydration, zero/N review requests, RESUME digest recomputation, generated-output schema checks, and strict production gates locally | + +## Evidence Ledger + +| Claim/Issue | Source or Test | Status | Notes | +|---|---|---|---| +| S2_40 is deterministic | v5-1 §§0, 2, 9, 16, 20 | VERIFIED | Exactly one release-bound inline Python task | +| S2_40 is the final single writer | v5-1 §§3.4, 9.4 | VERIFIED | Owns final ledger, documents, status, seal, and commit receipts | +| S2_40 barrier is `control/run_status.json` | v5-1 §§0.5, 3.3, 9.5 | VERIFIED | Must be written last after content read-back | +| Live/legal readiness | Current manifests/receipts and later tests | PENDING | Must remain evidence-separated | + +## Risks and Failure Modes + +- Mixing S2_30 LLM fan-out semantics into S2_40. +- Treating an untrusted upstream part, external receipt, or workspace-local manifest as its own trust anchor. +- Hash cycles among parent release, module manifest, bindings, admission receipts, candidate package, and operational commit receipts. +- Partial writes becoming consumable before the final status barrier. +- Renderer accepting arbitrary free text in structured relief sections. +- Review-required legal uncertainty being converted into global no-save. +- Existing user changes being overwritten or staged accidentally. + +## Results and Residual Uncertainty + +- Final authoring artifacts: `S2_40_SOW.md` 879 lines / SHA-256 `6930cd6438ae29187d01c7bf463cf308d34e90c73d4e755b5573ab92090f4a04`, `S2_40_assets.md` 528 lines / `ed518213100971fde44aca385890761d8b7b2f86ad2c18a29b5f960d46ec8787`, and `Stage_2_S2_40.yml` 3,575 lines / `5cbe2ac9aa73d95a5fa4e6cf71d7d8f0ad83aa05536f573c13e42505ef5d46f7`. +- The rebuilt module manifest contains 222 modules. Raw parent release SHA-256 is `9fa85bb94c5f14f675dcdaa0cf94d06745b21675d97797539ffc14015dcc9f53`; S2_10 and S2_30 child raw hashes are `cb49a4501116e46d935933b739b6679b11d961ff8e36abefea35dab6b25508fb` and `e6dd6abe44b39de462ea01f5e78aa39c70bbf47e0b75e08d224615a297d2135f`. +- Eight no-write projection/child/shared checks and an independent temporary-output module/parent reproducibility build passed. The release validator returned `PASS`, zero errors, and four expected pending findings. +- Offline regression passed 240/240: S2_00 70, S2_10 42, S2_20 42, S2_30 37, and S2_40 49. Python/documentation mirrors passed 62/62 and S2_00/S2_20/S2_30/S2_40 authoring/deployment projection parity passed 4/4. +- Runtime/deployment/release dependency on legacy Stage 2 v0-v3 is zero. A v.3 path remains only inside a negative fixture that proves such an injected dependency is rejected. +- Final state is `IMPLEMENTED_OFFLINE_VERIFIED / LIVE_AND_LEGAL_ADMISSION_PENDING`. The four pending validator findings are full-137 approved relief-rule coverage, parent production admission, signed deterministic backend admission, and live S2_40 secret/Code Executor binding. No live execution, legal sign-off, filing, or production promotion was performed.