From e73802d333e9e67365e7a50ffc312771f6b9a01b Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Wed, 30 Sep 2026 07:00:25 +0200 Subject: [PATCH 1/3] fix: reject unprovable required evidence media types --- .../entries/experiment-capture-spec-v1.json | 6 +- .../entries/sdl-authoring-input-v1.json | 6 +- .../experiment-capture-spec-v1.json | 12 +++ .../schemas/sdl/sdl-authoring-input-v1.json | 12 +++ docs/migration/required-capture-admission.md | 45 ++++++++++ docs/requirements/DSL-124/requirement.md | 1 + docs/requirements/EXP-707/requirement.md | 1 + docs/requirements/EXP-708/requirement.md | 1 + docs/requirements/EXP-715/requirement.md | 1 + .../packages/raes/evidence_requirements.py | 2 + .../raes_contracts/contracts/bundle.py | 16 ++++ .../contracts/experiment_capture.py | 2 + .../evidence_output_validation.py | 19 ++++ ..._dsl_124_authored_evidence_requirements.py | 7 +- ...exp_731_evidence_requirement_refinement.py | 26 +++++- .../test_issue_1112_capture_admission.py | 3 +- .../tests/test_issue_1237_output_registry.py | 5 +- .../test_issue_1401_media_type_coherence.py | 86 +++++++++++++++++++ 18 files changed, 237 insertions(+), 14 deletions(-) create mode 100644 implementations/python/tests/test_issue_1401_media_type_coherence.py diff --git a/contracts/schema-publication/entries/experiment-capture-spec-v1.json b/contracts/schema-publication/entries/experiment-capture-spec-v1.json index 0a8807e53..13b216685 100644 --- a/contracts/schema-publication/entries/experiment-capture-spec-v1.json +++ b/contracts/schema-publication/entries/experiment-capture-spec-v1.json @@ -1,9 +1,9 @@ { - "content_hash": "3b62a12fa613afa8fd26dc4d5577b5597bf59f5e01d0aaf170b151fe754b7516", + "content_hash": "107ae56109f33854c4e35d0d7a095af544fd86b95efb9206f932420c08a889fe", "contract_id": "experiment-capture-spec-v1", "last_change": { - "content_hash": "3b62a12fa613afa8fd26dc4d5577b5597bf59f5e01d0aaf170b151fe754b7516", - "summary": "Add the distinct materialization-attestation reference kind to portable artifact joins; it never replaces the original scenario-snapshot identity (#1241)." + "content_hash": "107ae56109f33854c4e35d0d7a095af544fd86b95efb9206f932420c08a889fe", + "summary": "Constrain required evidence media types to registered, content-provable output contracts (#1401)." }, "schema_path": "contracts/schemas/experiment-core/experiment-capture-spec-v1.json", "stability": "draft" diff --git a/contracts/schema-publication/entries/sdl-authoring-input-v1.json b/contracts/schema-publication/entries/sdl-authoring-input-v1.json index 99be5161a..5c664b249 100644 --- a/contracts/schema-publication/entries/sdl-authoring-input-v1.json +++ b/contracts/schema-publication/entries/sdl-authoring-input-v1.json @@ -1,9 +1,9 @@ { - "content_hash": "ec16ef507c579c16f81e499965255e1ac013f2826bc0b975f1413ce79cb70b74", + "content_hash": "643052d648a1afd04f50e70f0127cc467bf20084156754aceec5964a78529d81", "contract_id": "sdl-authoring-input-v1", "last_change": { - "summary": "Add participant-local outcomes and identity assignment alongside opt-in bounded shared-time guarantees.", - "content_hash": "ec16ef507c579c16f81e499965255e1ac013f2826bc0b975f1413ce79cb70b74" + "content_hash": "643052d648a1afd04f50e70f0127cc467bf20084156754aceec5964a78529d81", + "summary": "Constrain required evidence media types to registered, content-provable output contracts (#1401)." }, "schema_path": "contracts/schemas/sdl/sdl-authoring-input-v1.json", "stability": "draft" diff --git a/contracts/schemas/experiment-core/experiment-capture-spec-v1.json b/contracts/schemas/experiment-core/experiment-capture-spec-v1.json index 237329c51..c6caf3090 100644 --- a/contracts/schemas/experiment-core/experiment-capture-spec-v1.json +++ b/contracts/schemas/experiment-core/experiment-capture-spec-v1.json @@ -1407,6 +1407,18 @@ ], "level": "error", "validator": "raes_contracts.contracts.ExperimentCaptureSpecModel._validate_capture_spec" + }, + { + "description": "Every required media type must have a registered content-proof path and be supported by its declared output_contract.", + "id": "capture-media-type-provable", + "inputs": [ + { + "contract_id": "experiment-capture-spec-v1", + "instance_path": "#/capture_requirements" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.ExperimentCaptureRequirementModel._validate_capture_requirement" } ], "x-raes-plane": "authored_evidence_requirement", diff --git a/contracts/schemas/sdl/sdl-authoring-input-v1.json b/contracts/schemas/sdl/sdl-authoring-input-v1.json index 3b1fa9c5c..0758956ef 100644 --- a/contracts/schemas/sdl/sdl-authoring-input-v1.json +++ b/contracts/schemas/sdl/sdl-authoring-input-v1.json @@ -27415,6 +27415,18 @@ "type": "object", "x-raes-document-phase": "normalized-authoring-object", "x-raes-invariants": [ + { + "description": "Every declared required evidence media type must have a registered content-proof path; an explicit output_contract must support every declared type.", + "id": "required-evidence-media-type-provable", + "inputs": [ + { + "contract_id": "sdl-authoring-input-v1", + "instance_path": "#/evidence_requirements" + } + ], + "level": "error", + "validator": "raes.evidence_requirements.EvidenceRequirement._validate_capture_intent" + }, { "description": "Generated artifact output names and paths, consumers, and dependency entries must be unique, and generated artifact consumers must be read-only. Explicit selections must name declared consumer-selectable outputs; SSH artifact consumers must select outputs and every consumer-selectable SSH output must be selected.", "id": "stateful-generated-artifact-semantics", diff --git a/docs/migration/required-capture-admission.md b/docs/migration/required-capture-admission.md index a6a1a851e..13e054616 100644 --- a/docs/migration/required-capture-admission.md +++ b/docs/migration/required-capture-admission.md @@ -55,6 +55,51 @@ validated requirement-to-artifact bindings. Historical `satisfies_refs`, payload summaries, and backend assertions remain metadata; they are not proof of emitted content. +## Media-type coherence (issue #1401) + +Required capture currently has a closed, JSON-based output-proof vocabulary. +Until a separately governed byte contract and verifier exist for another +encoding, the eligible media types are `application/json` and the registered +array-root `application/jsonl` encoding. Reject an entire authored +SDL `media_types` list or experiment `expected_media_types` list if any member +is unsupported; a supported alternative must not mask an impossible one. +`text/plain`, `application/x-ndjson`, and PCAP are therefore invalid required +capture declarations. This tightens earlier SDL authoring behavior, including +the PCAP example in the DSL-124 test, and needs an explicit authoring diagnostic. +An omitted SDL media-type list remains unconstrained on this dimension. + +The authoritative eligibility source is +`raes_contracts.evidence_output_validation.evidence_output_registrations()`: +registry resolution couples each output-contract id to its published schema, +semantic validator, and JSON root, from which the supported encodings derive. +An explicit SDL `output_contract` or a +capture-spec `output_contract` must resolve there, and every declared media +type must be valid for that specific contract. An SDL requirement with no +output contract retains its existing intent-only semantics, but its declared +media types must still belong to the union of eligible encodings. In particular, +`application/jsonl` cannot be paired with the object-root +`experiment-evidence-record-v1`. Neither that record contract nor an arbitrary +`application/json` label licenses unrelated JSON or text artifact bytes. + +Keep one eligibility rule shared by SDL and capture-spec validation and the +existing offer and content validators. The model validators must expose an +explicit unsupported-media or incompatible-contract error; the published SDL, +capture-spec, and backend-manifest schemas and their semantic-invariant metadata +must not imply broader eligibility. Preserve the existing atomic offer matcher, +admission diagnostics, bounded byte reader, checksum and locator checks, schema +and semantic validation, RFC 6901 field checks, and process-local proof object. +The field selectors address the decoded JSON document; for JSON Lines they +address the decoded array. Do not interpret them as selectors into arbitrary +text, or use an evidence-record envelope as a stand-in for the artifact bytes. + +This decision governs required-capture proof, not descriptive legacy +`supported_media_types` summaries, runtime capture implementation, storage, +export, or a generic non-JSON contract framework. A future encoding belongs as +an explicit registry-owned contract/encoding plus bounded byte parser and +content proof, with publication and conformance evidence before it becomes +eligible at authoring or in an offer. No URI fetch, credential handling, or +serialized proof token is introduced here. + ## Shared proof and extension points Issue #1237 makes `validate_experiment_run_evidence()` and diff --git a/docs/requirements/DSL-124/requirement.md b/docs/requirements/DSL-124/requirement.md index 775002724..7514a4b51 100644 --- a/docs/requirements/DSL-124/requirement.md +++ b/docs/requirements/DSL-124/requirement.md @@ -37,3 +37,4 @@ Scenario authors may need to require that particular data be captured from parti - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/capture_dimensions.py` (Shared authored capture dimension projection) - TESTS → TEST `implementations/python/tests/test_issue_1237_capture_dimensions.py` (Independent authored demand projection and admission parity) - TESTS → TEST `implementations/python/tests/test_issue_1112_capture_admission.py` (Authored evidence demand admission and non-demand boundaries) +- TESTS → TEST `implementations/python/tests/test_issue_1401_media_type_coherence.py` (Authored required media types reject unprovable encodings) diff --git a/docs/requirements/EXP-707/requirement.md b/docs/requirements/EXP-707/requirement.md index cf67afbae..650c00e6b 100644 --- a/docs/requirements/EXP-707/requirement.md +++ b/docs/requirements/EXP-707/requirement.md @@ -28,3 +28,4 @@ Requirement inventory expansion. Experiment data capture requirements are distin - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/experiment_capture.py` (Field- and output-contract-qualified capture requirements) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_processor/trial_compiler/inputs.py` (Digest-bound capture specification admission) - TESTS → TEST `implementations/python/tests/test_sce_002_trial_compiler.py` (Capture specification identity and backend admission tests) +- TESTS → TEST `implementations/python/tests/test_issue_1401_media_type_coherence.py` (Required media declarations reject unprovable encodings and accept content-provable JSON encodings) diff --git a/docs/requirements/EXP-708/requirement.md b/docs/requirements/EXP-708/requirement.md index d5f5e872c..b5935fd22 100644 --- a/docs/requirements/EXP-708/requirement.md +++ b/docs/requirements/EXP-708/requirement.md @@ -54,3 +54,4 @@ Requirement inventory expansion. Raw captured evidence must be modeled explicitl - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/experiment_conditions.py` (Condition matching excludes unsupported evidence-id claims) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/evidence_satisfaction.py` (Content-backed emitted evidence satisfaction validation) - TESTS → TEST `implementations/python/tests/test_issue_1112_capture_admission.py` (Evidence record, artifact byte, digest, and field proof coverage) +- TESTS → TEST `implementations/python/tests/test_issue_1401_media_type_coherence.py` (Registered media declarations reach content-backed evidence proof) diff --git a/docs/requirements/EXP-715/requirement.md b/docs/requirements/EXP-715/requirement.md index 0ff40d3d8..3b5b2d9ce 100644 --- a/docs/requirements/EXP-715/requirement.md +++ b/docs/requirements/EXP-715/requirement.md @@ -42,3 +42,4 @@ Requirement inventory expansion. Observation support must be declared explicitly - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_conformance/conformance/target_manifest_probe.py` (Fail-closed capture-offer manifest conformance validation) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_processor/capture_admission.py` (Conjunctive required-capture capability admission) - TESTS → TEST `implementations/python/tests/test_issue_1112_capture_admission.py` (Capture-offer manifest and admission failure coverage) +- TESTS → TEST `implementations/python/tests/test_issue_1401_media_type_coherence.py` (Every eligible media declaration can be represented by a valid capture offer) diff --git a/implementations/python/packages/raes/evidence_requirements.py b/implementations/python/packages/raes/evidence_requirements.py index fe2a6f980..9581213c0 100644 --- a/implementations/python/packages/raes/evidence_requirements.py +++ b/implementations/python/packages/raes/evidence_requirements.py @@ -10,6 +10,7 @@ from enum import Enum from pydantic import Field, ValidationInfo, field_validator, model_validator +from raes_contracts.evidence_output_validation import validate_evidence_media_declaration from raes_contracts.observation_demand import ObservationDemandRule from ._base import SDLModel, parse_enum_or_var @@ -215,6 +216,7 @@ def _validate_capture_contract(requirement: EvidenceRequirement) -> None: raise ValueError("capture_spec_ref and capture_requirement_ref must be declared together") if any(re.fullmatch(r"(?:/(?:[^~/]|~[01])*)*", selector) is None for selector in requirement.field_selectors): raise ValueError("field_selectors must be canonical RFC 6901 JSON Pointers") + validate_evidence_media_declaration(requirement.output_contract, requirement.media_types) __all__ = [ diff --git a/implementations/python/packages/raes_contracts/contracts/bundle.py b/implementations/python/packages/raes_contracts/contracts/bundle.py index 7ead050fa..6ae6986c3 100644 --- a/implementations/python/packages/raes_contracts/contracts/bundle.py +++ b/implementations/python/packages/raes_contracts/contracts/bundle.py @@ -257,6 +257,22 @@ def _schema_bundle_template() -> dict[str, dict[str, Any]]: # NOSONAR """Build the immutable-in-practice template used by :func:`schema_bundle`.""" bundle = _raw_schema_bundle() + _add_raes_invariant( + bundle["sdl-authoring-input-v1"], + "required-evidence-media-type-provable", + "Every declared required evidence media type must have a registered content-proof path; an explicit " + "output_contract must support every declared type.", + validator="raes.evidence_requirements.EvidenceRequirement._validate_capture_intent", + inputs=[{"contract_id": "sdl-authoring-input-v1", "instance_path": "#/evidence_requirements"}], + ) + _add_raes_invariant( + bundle["experiment-capture-spec-v1"], + "capture-media-type-provable", + "Every required media type must have a registered content-proof path and be supported by its " + "declared output_contract.", + validator="raes_contracts.contracts.ExperimentCaptureRequirementModel._validate_capture_requirement", + inputs=[{"contract_id": "experiment-capture-spec-v1", "instance_path": "#/capture_requirements"}], + ) _add_raes_invariant( bundle["behavioral-relations-v1"], "behavioral-relations-reference-resolution", diff --git a/implementations/python/packages/raes_contracts/contracts/experiment_capture.py b/implementations/python/packages/raes_contracts/contracts/experiment_capture.py index e7bdcb108..4ae22b46d 100644 --- a/implementations/python/packages/raes_contracts/contracts/experiment_capture.py +++ b/implementations/python/packages/raes_contracts/contracts/experiment_capture.py @@ -9,6 +9,7 @@ from pydantic.json_schema import JsonSchemaValue from pydantic_core import CoreSchema +from ..evidence_output_validation import validate_evidence_media_declaration from ..observation_demand import ObservationDemandRule from ..versions import EXPERIMENT_CAPTURE_SPEC_SCHEMA_VERSION from .base import ContractModel, NonEmptyString, Rfc3339DateTimeString, _parse_rfc3339_datetime @@ -122,6 +123,7 @@ def _validate_capture_requirement(self) -> ExperimentCaptureRequirementModel: _validate_unique_string_values("field_selectors", self.field_selectors) if any(re.fullmatch(r"(?:/(?:[^~/]|~[01])*)*", selector) is None for selector in self.field_selectors): raise ValueError("field_selectors must be canonical RFC 6901 JSON Pointers") + validate_evidence_media_declaration(self.output_contract, self.expected_media_types) if self.sensitivity == "redacted" and self.redaction_policy is None: raise ValueError("redacted capture requirements must declare redaction_policy") return self diff --git a/implementations/python/packages/raes_contracts/evidence_output_validation.py b/implementations/python/packages/raes_contracts/evidence_output_validation.py index d0029369e..75383dfed 100644 --- a/implementations/python/packages/raes_contracts/evidence_output_validation.py +++ b/implementations/python/packages/raes_contracts/evidence_output_validation.py @@ -109,10 +109,29 @@ def validate_evidence_output_offer(output_contract: str, media_types: Collection raise ValueError("capture offer media types cannot be validated against its output_contract") +def validate_evidence_media_declaration(output_contract: str, media_types: Collection[str]) -> None: + """Reject required encodings with no registered content-proof path.""" + + declared = set(media_types) + if not declared and not output_contract: + return + supported = set().union( + *(resolve_evidence_output_contract(contract_id).media_types for contract_id in evidence_output_registrations()) + ) + unsupported = sorted(declared - supported) + if unsupported: + raise ValueError("unsupported required evidence media type(s): " + ", ".join(unsupported)) + if output_contract: + contract = resolve_evidence_output_contract(output_contract) + if not declared.issubset(contract.media_types): + raise ValueError("required evidence media types cannot be validated against its output_contract") + + __all__ = [ "EvidenceOutputContract", "evidence_output_registrations", "resolve_evidence_output_contract", "validate_evidence_output_contract", "validate_evidence_output_offer", + "validate_evidence_media_declaration", ] diff --git a/implementations/python/tests/test_dsl_124_authored_evidence_requirements.py b/implementations/python/tests/test_dsl_124_authored_evidence_requirements.py index 2fbacd02a..99ea6ea3e 100644 --- a/implementations/python/tests/test_dsl_124_authored_evidence_requirements.py +++ b/implementations/python/tests/test_dsl_124_authored_evidence_requirements.py @@ -54,7 +54,7 @@ def _scenario_yaml(*, source_ref: str = OBSERVABILITY_REF, trigger: str | None = {trigger_line} channel: packet_capture artifact_role: network_trace media_types: - - application/vnd.tcpdump.pcap + - application/json sensitivity: plain redaction: none integrity: checksum @@ -78,6 +78,11 @@ def test_dsl_124_accepts_authored_evidence_requirement_independent_of_objectives assert OBSERVABILITY_REF in collect_scenario_native_observability_refs(scenario) +def test_dsl_124_rejects_unprovable_pcap_declaration() -> None: + with pytest.raises(SDLParseError, match="unsupported required evidence media type"): + parse_sdl(_scenario_yaml().replace("application/json", "application/vnd.tcpdump.pcap")) + + def test_dsl_124_evidence_requirements_are_not_objective_targets() -> None: payload = ( _scenario_yaml() diff --git a/implementations/python/tests/test_exp_731_evidence_requirement_refinement.py b/implementations/python/tests/test_exp_731_evidence_requirement_refinement.py index dc54aca37..f76d561cb 100644 --- a/implementations/python/tests/test_exp_731_evidence_requirement_refinement.py +++ b/implementations/python/tests/test_exp_731_evidence_requirement_refinement.py @@ -12,6 +12,7 @@ from raes.parser import parse_sdl from raes.scenario import ExpandedScenario from raes.validator import SemanticValidator +from raes_contracts._evidence_content_validation import _json_pointer_resolves, _parse_contract_document from raes_contracts.canonical import canonical_json_digest from raes_contracts.contracts import ( ExperimentCaptureSpecModel, @@ -65,9 +66,9 @@ def _scenario(): integrity: checksum retention: run_lifetime loss_disclosure: best_effort - output_contract: event-stream-v1 + output_contract: participant-behavior-history-event-stream-v1 field_selectors: - - /events + - /0 """ ) @@ -158,8 +159,8 @@ def _capture_spec( "window_refs": ["run-window"], "expected_media_types": ["application/json"], "required_artifact_roles": artifact_roles or ["event-log"], - "output_contract": "event-stream-v1", - "field_selectors": ["/events", "/events/0"], + "output_contract": "participant-behavior-history-event-stream-v1", + "field_selectors": ["/0", "/0/action_contract_address"], "sensitivity": "internal", "integrity_requirements": integrity or ["checksum", "sha256-digest"], "loss_disclosure_required": True, @@ -222,6 +223,23 @@ def test_refinement_resolves_exact_lineage_and_preserves_the_authored_scenario() assert scenario.model_dump(mode="json") == before +def test_refinement_selectors_resolve_against_registered_stream_content() -> None: + scenario = _scenario() + capture_spec = _capture_spec(_authority_ref("task", _fixture("experiment-task-v1"))) + requirement = capture_spec.capture_requirements["event-log-detail"] + payload = ( + REPO_ROOT + / "contracts/fixtures/control-plane/participant-behavior-history-event-stream-v1/valid/terminal-observation.json" + ).read_bytes() + document = _parse_contract_document( + payload, + media_type="application/json", + output_contract=requirement.output_contract, + ) + selectors = scenario.evidence_requirements["event-log"].field_selectors + requirement.field_selectors + assert all(_json_pointer_resolves(document, selector) for selector in selectors) + + def test_refinement_fails_closed_when_a_declared_dimension_is_not_monotone() -> None: scenario = _scenario() task_payload = _fixture("experiment-task-v1") diff --git a/implementations/python/tests/test_issue_1112_capture_admission.py b/implementations/python/tests/test_issue_1112_capture_admission.py index 4f3ec2e48..877bfdebf 100644 --- a/implementations/python/tests/test_issue_1112_capture_admission.py +++ b/implementations/python/tests/test_issue_1112_capture_admission.py @@ -492,9 +492,8 @@ def test_output_contract_shape_and_registry_are_enforced_before_selectors() -> N with pytest.raises(ValueError, match="output_contract"): _validate_evidence_bundle(*invalid) - unknown = _evidence_bundle(output_contract="unknown-output-contract-v1") with pytest.raises(ValueError, match="authoritative contract registry"): - _validate_evidence_bundle(*unknown) + _evidence_bundle(output_contract="unknown-output-contract-v1") def test_output_contract_semantic_invariants_are_enforced() -> None: diff --git a/implementations/python/tests/test_issue_1237_output_registry.py b/implementations/python/tests/test_issue_1237_output_registry.py index 11e390d9c..159c482a1 100644 --- a/implementations/python/tests/test_issue_1237_output_registry.py +++ b/implementations/python/tests/test_issue_1237_output_registry.py @@ -23,7 +23,10 @@ def _validation_call(ingress, payload, bundle, **offer_updates): @pytest.mark.parametrize("ingress", ["protocol", "model", "content"]) def test_missing_output_owner_is_rejected_at_every_boundary(contract: str, ingress: str) -> None: payload = {**_offer().to_payload(), "output_contract": contract} - bundle = _evidence_bundle(output_contract=contract) + bundle = _evidence_bundle() + if ingress == "content": + bundle[2].capture_requirements["auth-log-evidence"].output_contract = contract + bundle[3].output_contract = contract validate = _validation_call(ingress, payload, bundle, output_contract=contract) with pytest.raises(ValueError, match="output_contract"): validate() diff --git a/implementations/python/tests/test_issue_1401_media_type_coherence.py b/implementations/python/tests/test_issue_1401_media_type_coherence.py new file mode 100644 index 000000000..f155f1f89 --- /dev/null +++ b/implementations/python/tests/test_issue_1401_media_type_coherence.py @@ -0,0 +1,86 @@ +"""Required media declarations must be offerable and content-provable.""" + +from __future__ import annotations + +import io +import json + +import pytest +from pydantic import ValidationError +from raes_contracts.contracts import ExperimentCaptureSpecModel +from raes_contracts.evidence_satisfaction import validate_experiment_run_evidence +from test_issue_1112_capture_admission import ( + EVENT_STREAM_FIXTURE, + _capture_scenario, + _evidence_bundle, + _fixture, + _offer, +) + + +@pytest.mark.parametrize("media_type", ["text/plain", "application/x-ndjson", "application/vnd.tcpdump.pcap"]) +def test_sdl_rejects_unprovable_required_media_type(media_type: str) -> None: + scenario = _capture_scenario() + payload = scenario.evidence_requirements["attacker-action-log"].model_dump(mode="json") + payload["media_types"] = ["application/json", media_type] + with pytest.raises(ValidationError, match="unsupported.*media type"): + type(scenario.evidence_requirements["attacker-action-log"]).model_validate(payload) + + +@pytest.mark.parametrize("media_type", ["text/plain", "application/x-ndjson", "application/vnd.tcpdump.pcap"]) +def test_capture_spec_rejects_unprovable_required_media_type(media_type: str) -> None: + payload = _fixture("experiment-capture-spec-v1") + requirement = next(iter(payload["capture_requirements"].values())) + requirement["expected_media_types"] = ["application/json", media_type] + with pytest.raises(ValidationError, match="unsupported.*media type"): + ExperimentCaptureSpecModel.model_validate(payload) + + +@pytest.mark.parametrize("media_type", ["application/json", "application/jsonl"]) +def test_explicit_contract_rejects_misleading_encoding(media_type: str) -> None: + payload = _fixture("experiment-capture-spec-v1") + requirement = next(iter(payload["capture_requirements"].values())) + requirement["output_contract"] = "experiment-evidence-record-v1" + requirement["expected_media_types"] = [media_type] + if media_type == "application/json": + ExperimentCaptureSpecModel.model_validate(payload) + else: + with pytest.raises(ValidationError, match="media.*output_contract"): + ExperimentCaptureSpecModel.model_validate(payload) + + +@pytest.mark.parametrize("media_type", ["application/json", "application/jsonl"]) +def test_accepted_declaration_has_offer_and_content_proof(media_type: str) -> None: + events = json.loads(EVENT_STREAM_FIXTURE.read_text(encoding="utf-8")) + payload = ( + EVENT_STREAM_FIXTURE.read_bytes() + if media_type == "application/json" + else b"\n".join(json.dumps(event).encode() for event in events) + ) + task, run, spec, record, _ = _evidence_bundle(payload, media_type=media_type) + offer = _offer(media_types=frozenset({media_type})) + assert media_type in offer.media_types + proof = validate_experiment_run_evidence( + task, + run, + capture_specs={spec.capture_spec_id: spec}, + evidence_records={record.evidence_record_id: record}, + artifact_readers={run.evidence_artifacts[0].artifact_id: io.BytesIO(payload)}, + ) + assert proof.bindings + + +def test_unknown_sdl_output_contract_is_rejected_at_authoring() -> None: + scenario = _capture_scenario() + payload = scenario.evidence_requirements["attacker-action-log"].model_dump(mode="json") + payload["output_contract"] = "unknown-output-contract-v1" + with pytest.raises(ValidationError, match="output_contract"): + type(scenario.evidence_requirements["attacker-action-log"]).model_validate(payload) + + +def test_sdl_object_contract_rejects_json_lines_at_authoring() -> None: + scenario = _capture_scenario(output_contract="experiment-evidence-record-v1") + payload = scenario.evidence_requirements["attacker-action-log"].model_dump(mode="json") + payload["media_types"] = ["application/jsonl"] + with pytest.raises(ValidationError, match="media.*output_contract"): + type(scenario.evidence_requirements["attacker-action-log"]).model_validate(payload) From d7f52de8d97e3a80ab9335f6d184cc2de7cb0812 Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Thu, 1 Oct 2026 00:43:44 +0200 Subject: [PATCH 2/3] test: republish research evidence captures above the #1405 releases --- .../analysis-v67.json | 158 ++++ .../bundles/retest-v67.json | 122 +++ .../execution-snapshot-v67.json | 652 ++++++++++++++++ .../formal-semantic-validation/index.md | 8 +- .../specification-coverage/analysis-v66.json | 107 +++ ...specification-coverage-issue-1401-v66.json | 10 + .../execution-snapshot-v66.json | 700 ++++++++++++++++++ docs/research/specification-coverage/index.md | 9 +- .../tests/test_formal_semantic_validation.py | 5 +- .../test_issue_989_versioned_evidence.py | 22 +- .../tests/test_specification_coverage.py | 2 +- tools/check_specification_coverage.py | 5 +- tools/formal_semantic_validation/_baseline.py | 1 + tools/formal_semantic_validation/_loading.py | 4 +- .../_release_revisions.py | 4 +- tools/formal_semantic_validation/_releases.py | 5 +- tools/formal_semantic_validation/_retest.py | 2 +- 17 files changed, 1793 insertions(+), 23 deletions(-) create mode 100644 docs/research/formal-semantic-validation/analysis-v67.json create mode 100644 docs/research/formal-semantic-validation/bundles/retest-v67.json create mode 100644 docs/research/formal-semantic-validation/execution-snapshot-v67.json create mode 100644 docs/research/specification-coverage/analysis-v66.json create mode 100644 docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1401-v66.json create mode 100644 docs/research/specification-coverage/execution-snapshot-v66.json diff --git a/docs/research/formal-semantic-validation/analysis-v67.json b/docs/research/formal-semantic-validation/analysis-v67.json new file mode 100644 index 000000000..6d930e623 --- /dev/null +++ b/docs/research/formal-semantic-validation/analysis-v67.json @@ -0,0 +1,158 @@ +{ + "analysis_id": "issue-1401-analysis-v67", + "claim": { + "allowed_evidence": [ + "production parser and semantic-validator results", + "canonical compiled digests", + "participant contract regression tests", + "pinned protocol, corpus, and execution snapshot" + ], + "claim_id": "asr-530-formal-semantic-validation-retest", + "disallowed_evidence": [ + "schema success as semantic proof", + "workflow reachability as network or exploit reachability", + "FM labels as gate outcomes", + "attribution as counterfactual proof", + "formal prose or maintainer confidence alone" + ], + "evidence_artifacts": [ + "docs/research/formal-semantic-validation/protocol-v2.json", + "docs/research/formal-semantic-validation/corpus/manifest-v4.json", + "docs/research/formal-semantic-validation/execution-snapshot-v67.json", + "docs/research/formal-semantic-validation/evidence/finite-domain-satisfiable-v4.json", + "docs/research/formal-semantic-validation/evidence/finite-domain-unsatisfiable-v4.json", + "docs/research/formal-semantic-validation/evidence/typed-exploit-path-valid-v4.json", + "docs/research/formal-semantic-validation/evidence/typed-exploit-path-invalid-v4.json" + ], + "falsification_protocol": "Replay every retained and new case through its production entrypoint, require complete digest and evidence joins, execute participant fixtures, and derive status from the recorded outcomes.", + "objective_fail_criteria": "A supported negative passes, a positive fails, an observation drifts, a required participant case is missing, or weaker evidence is promoted to solver, exploit-path, runtime-stability, or counterfactual assurance.", + "objective_pass_criteria": "Every claim class has positive and negative cases, all supported cases reproduce the frozen outcome, every participant obligation has passing positive and negative fixtures, and unsupported classes remain untested.", + "statement": "At the recorded source-state digest, the retained RAES controls have the bounded statuses recorded here; historical releases are integrity evidence, not current replay evidence.", + "threats_to_validity": [ + "The issue-specific corpus is intentionally small and does not enumerate every validator invariant.", + "The participant fixtures exercise reference production contracts and tests, not every independent backend realization.", + "The replay gate runs on one Python reference configuration and one pinned RAES revision.", + "Unsupported solver-level classes have protocol cases but no executable observations." + ] + }, + "claim_results": [ + { + "case_count": 2, + "claim_class_id": "schema-validity", + "evidence_status": "demonstrated", + "limitations": [ + "Bounded to the named source/model structural controls." + ], + "matching_case_count": 2, + "participant_obligation_count": 0, + "replayable_case_count": 2, + "unsupported_case_count": 0 + }, + { + "case_count": 4, + "claim_class_id": "semantic-consistency", + "evidence_status": "partial", + "limitations": [ + "Partial coverage of named static semantics and participant obligations, not universal consistency." + ], + "matching_case_count": 4, + "participant_obligation_count": 7, + "replayable_case_count": 4, + "unsupported_case_count": 0 + }, + { + "case_count": 2, + "claim_class_id": "graph-reachability", + "evidence_status": "partial", + "limitations": [ + "Partial workflow control-flow reachability only; not network, service, or exploit reachability." + ], + "matching_case_count": 2, + "participant_obligation_count": 0, + "replayable_case_count": 2, + "unsupported_case_count": 0 + }, + { + "case_count": 4, + "claim_class_id": "constraint-satisfiability", + "evidence_status": "demonstrated", + "limitations": [ + "Demonstrated only for raes-finite-domain-satisfiability-v1 and its pinned solver configuration." + ], + "matching_case_count": 4, + "participant_obligation_count": 0, + "replayable_case_count": 2, + "unsupported_case_count": 2 + }, + { + "case_count": 4, + "claim_class_id": "exploit-path-validity", + "evidence_status": "demonstrated", + "limitations": [ + "Demonstrated only for the admitted snapshot, typed graph, query, semantics, and bounded search profile." + ], + "matching_case_count": 4, + "participant_obligation_count": 0, + "replayable_case_count": 2, + "unsupported_case_count": 2 + }, + { + "case_count": 2, + "claim_class_id": "determinism-stability", + "evidence_status": "partial", + "limitations": [ + "Partial parse-to-compile repeatability only; runtime and backend determinism are untested." + ], + "matching_case_count": 2, + "participant_obligation_count": 0, + "replayable_case_count": 2, + "unsupported_case_count": 0 + }, + { + "case_count": 2, + "claim_class_id": "counterfactual-necessity", + "evidence_status": "untested", + "limitations": [ + "Untested because no governed intervention or ablation entrypoint ran." + ], + "matching_case_count": 2, + "participant_obligation_count": 0, + "replayable_case_count": 0, + "unsupported_case_count": 2 + } + ], + "corpus_revision": "4.0.0", + "evidence_status": "partial", + "execution_id": "issue-1401-execution-v67", + "generated_at": "2026-09-30T22:41:24.312224+00:00", + "limitations": [ + "Satisfiability is limited to raes-finite-domain-satisfiability-v1 and its exact translation, theory, and Z3 configuration.", + "The subset-minimal unsatisfiable core is not a universal proof certificate.", + "Exploit-path results are limited to the admitted snapshot, normalized graph, query, transition semantics, and bounded search profile.", + "A valid path is not backend execution and an invalid path is not real-world non-exploitability.", + "The production exploit-path JSON loader permits duplicate keys; the research loader rejects them without claiming stronger production behavior.", + "Participant replay inherits the host environment and is not described as hermetic.", + "Counterfactual necessity remains untested.", + "Scoped observation demand is not a claim class in this preregistration and is not promoted to demonstrated by this retest.", + "EXP-732 provenance joins are verified by their dedicated regression suite; this retained corpus makes no universal run, apparatus, source, or augmentation assurance claim.", + "This retained corpus does not establish native backend attestation fidelity; materialization contract checks remain separate operational provenance, not experimental observations.", + "Capture admission and evidence-proof authority are verified by issue-1237 regression tests, not promoted to a new claim class by this retained corpus.", + "Evidence-requirement refinement lineage is outside this retained formal claim set; this retest refreshes integrated source provenance without promoting that feature to a formal claim.", + "Authoring-adapter transport behavior is outside this retained formal claim set.", + "Operational recovery observation and startup reconciliation are verified by their API-404 regression suite, not promoted to a new formal claim class by this retained corpus.", + "Single-owner store admission, immutable target/run scope, and provider shutdown ordering are verified by their API-404 CP-5 regression suite, not promoted to a formal claim by this retained corpus.", + "Mixed and staged trial admission is verified by its SEM-234/SCE-002/API-407 regression suite, not promoted to a new formal claim class by this retained corpus.", + "Offline control-plane maintenance, readiness, and bounded audit behavior are verified by issue #1186 runtime tests, not promoted to a formal claim by this retained corpus.", + "Issue #1187 control-plane crash/profile conformance and HTTP security changes are covered by their dedicated regression suite, not promoted to new claims by this retained corpus.", + "Issue #1189 profile declarations and capability admission are covered by dedicated runtime tests; the retained formal corpus does not execute control-plane profile composition.", + "Issue #1016 mixed-runtime coordination is covered by dedicated runtime tests; the retained formal corpus does not establish backend-native mixed realization, multi-controller coordination, IFC, or equivalence.", + "Issue #610's reconciliation demonstration harness is covered by its dedicated processor and CLI suite, not promoted to new claims by the retained language corpus.", + "Participant identity, organization ownership, and participant assignment are separated by issue #1338. This retained offline corpus does not establish participant autonomy, execution authority, live backend fidelity, or causal attribution.", + "Issue #1389 temporal-subject admission is verified by dedicated compiler tests and adds no new formal-semantic claim to this retained corpus.", + "Issue #971 model construction is verified by its own tests; this retained corpus establishes no participant-crossing equivalence or runtime-realization claim.", + "Issue #1359 control-plane route authority, participant-view scoping, and no-store HTTP boundary are verified by their dedicated HTTP-boundary suite and add no new formal-semantic claim to this retained corpus.", + "Issue #1401 required-evidence media-type coherence is verified by its dedicated suite and adds no new formal-semantic claim to this retained corpus." + ], + "plain_language_outcome": "The retained formal cases reproduce their prior outcomes against source that rejects required evidence whose declared media type the output registry cannot prove; outcomes and bounded claim limits are unchanged.", + "protocol_revision": "2.0.0" +} diff --git a/docs/research/formal-semantic-validation/bundles/retest-v67.json b/docs/research/formal-semantic-validation/bundles/retest-v67.json new file mode 100644 index 000000000..7ec50969b --- /dev/null +++ b/docs/research/formal-semantic-validation/bundles/retest-v67.json @@ -0,0 +1,122 @@ +{ + "analysis_path": "docs/research/formal-semantic-validation/analysis-v67.json", + "analysis_sha256": "37d4daba9c7270169d343a7c36725e779dbae141132e928786a048d4083682d7", + "artifacts": [ + { + "artifact_id": "finite-domain-satisfiable-v2-input", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/satisfiable-control.sdl.yaml", + "sha256": "0ca9eaba9dc47171f7a042dc6753faa6c820c65ee966538f9d65fac5342202e8" + }, + { + "artifact_id": "finite-domain-satisfiable-v2-evidence", + "kind": "production-evidence", + "path": "docs/research/formal-semantic-validation/evidence/finite-domain-satisfiable-v4.json", + "sha256": "554202313d678046958b5c028e2de26ff03c74895cfac552677eed74e8153add" + }, + { + "artifact_id": "finite-domain-unsatisfiable-v2-input", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/unsatisfiable-control.sdl.yaml", + "sha256": "cfef56a1f56d5f0db9da195377fd75694bdd0f0b92932fdb8fafcbd3f7baf6c5" + }, + { + "artifact_id": "finite-domain-unsatisfiable-v2-evidence", + "kind": "production-evidence", + "path": "docs/research/formal-semantic-validation/evidence/finite-domain-unsatisfiable-v4.json", + "sha256": "c972725ef64822a75a60380afc11f08eac25b7fe9b091d39b058b3c9f7c8031d" + }, + { + "artifact_id": "typed-exploit-path-valid-v2-input", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/exploit-path-valid-v3.json", + "sha256": "0afe635a63db5b6e6380ac70982fd61d09790745d51a10d670321304121e7c39" + }, + { + "artifact_id": "typed-exploit-path-valid-v2-evidence", + "kind": "production-evidence", + "path": "docs/research/formal-semantic-validation/evidence/typed-exploit-path-valid-v4.json", + "sha256": "1b7f55d04db172da32658187c64a88c13b5f4d565267ce2be7cb86a9d04cb70c" + }, + { + "artifact_id": "typed-exploit-path-invalid-v2-input", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/exploit-path-invalid-v3.json", + "sha256": "0b2293d4a8983515ff05c516be6e6b418a4f3f09e055250a00bf15fda861aab3" + }, + { + "artifact_id": "typed-exploit-path-invalid-v2-evidence", + "kind": "production-evidence", + "path": "docs/research/formal-semantic-validation/evidence/typed-exploit-path-invalid-v4.json", + "sha256": "244f895a64f14c10916ab0533ab462ce80a328021cd6a50c30a4aa59266d5533" + }, + { + "artifact_id": "schema-valid-control-fixture", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/schema-valid.sdl.yaml", + "sha256": "41a9adffdf9f5f2ccc2f887dcf7b15fba3b47c83a1af15f33db872c4a2449d67" + }, + { + "artifact_id": "schema-unknown-field-fixture", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/schema-invalid-unknown-field.sdl.yaml", + "sha256": "51cf62319a86c95a2517995939d1f370573051835e4b55bb6d5beaf049640481" + }, + { + "artifact_id": "semantic-resolved-objective-fixture", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/semantic-valid-participant-identity-v2.sdl.yaml", + "sha256": "75834bdc883e2003e1c473870bdf75700978955bb83095c6bd718ba6bd3908a6" + }, + { + "artifact_id": "semantic-dangling-assertion-fixture", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/semantic-invalid-dangling-ref-participant-identity-v2.sdl.yaml", + "sha256": "1d25bee5f556054e5f0a518df025e4c62e080e1964035e3c1a12e074d88d3a5d" + }, + { + "artifact_id": "semantic-ambiguous-reference-fixture", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/semantic-invalid-ambiguous-ref.sdl.yaml", + "sha256": "653cbd2fd62e220d49fb86f80133884207df5ae6752846345ae3085b93f6e4ed" + }, + { + "artifact_id": "semantic-feature-cycle-fixture", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/semantic-invalid-feature-cycle.sdl.yaml", + "sha256": "e1f66d95a9ad039687aec8cccbc8843b514072ff08e006c1b4ca6aa5cd8d4ed1" + }, + { + "artifact_id": "workflow-reachable-control-fixture", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/workflow-reachable.sdl.yaml", + "sha256": "54c40ceb98ad47247447d737973b2c55e8fb2045e209c7545c4fb20cf42dc3dc" + }, + { + "artifact_id": "workflow-unreachable-step-fixture", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/workflow-unreachable.sdl.yaml", + "sha256": "ef22ef2e260f1a7fd92d286f9b571716436b192ddfd54aea7bdfcfdda4ca52a2" + }, + { + "artifact_id": "compile-repeatability-control-fixture", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/determinism-a.sdl.yaml", + "sha256": "0bc40900d598c1af7a405d798ca19710405e53ced262d8733081abf12edf89fe" + }, + { + "artifact_id": "compile-non-vacuity-control-comparison-fixture", + "kind": "corpus-input", + "path": "docs/research/formal-semantic-validation/corpus/determinism-b.sdl.yaml", + "sha256": "d85338f89f20a45515b12da8640173c1a52e47eb17ca0f4f6b4f8f3306e863a1" + } + ], + "bundle_id": "raes-formal-semantic-validation", + "corpus_path": "docs/research/formal-semantic-validation/corpus/manifest-v4.json", + "corpus_sha256": "c57207af72406aa4f70882b9bbeb7cedcc79cf3854c878a95e3eb1fa59ea7a72", + "protocol_path": "docs/research/formal-semantic-validation/protocol-v2.json", + "protocol_sha256": "abf94093e344bf495dfb04e8b0c5985c0beaab8ebb17a75e15c8674fa81b1a7c", + "revision": "67.0.0", + "snapshot_path": "docs/research/formal-semantic-validation/execution-snapshot-v67.json", + "snapshot_sha256": "ae71c86b50ce858a505908f760fe8f6bb76a6a07302b6fb1797015838a00e0dd" +} diff --git a/docs/research/formal-semantic-validation/execution-snapshot-v67.json b/docs/research/formal-semantic-validation/execution-snapshot-v67.json new file mode 100644 index 000000000..a78c158c6 --- /dev/null +++ b/docs/research/formal-semantic-validation/execution-snapshot-v67.json @@ -0,0 +1,652 @@ +{ + "baseline": { + "execution_id": "supply-chain-execution-v66", + "release_path": "docs/research/formal-semantic-validation/bundles/retest-v66.json", + "release_revision": "66.0.0", + "release_sha256": "752bcf4ac0c3528e5213d9edfde6d76a58a1848f80348b5442cbc7985e2673b0" + }, + "captured_at": "2026-09-30T22:41:24.312224+00:00", + "commands": [ + { + "argv": [ + "implementations/python/.venv/bin/python", + "tools/check_formal_semantic_validation.py" + ], + "command_id": "bundle-replay", + "network": "disabled" + }, + { + "argv": [ + "implementations/python/.venv/bin/pytest", + "-q", + "implementations/python/tests/test_sem_208_participant_behavior.py::test_hidden_truth_disclosure_is_separate_from_observable_projection", + "implementations/python/tests/test_sem_208_participant_behavior.py::test_hidden_truth_cannot_be_observed_without_explicit_disclosure_rule", + "implementations/python/tests/test_sem_211_participant_action_semantics.py::test_action_contract_declares_sem_211_classes_and_compiles_them", + "implementations/python/tests/test_sem_211_participant_action_semantics.py::test_action_result_rejects_success_when_preconditions_are_unresolved", + "implementations/python/tests/test_run_308_concurrent_participant_execution.py::test_runtime_snapshot_publishes_joint_action_and_time_context_records", + "implementations/python/tests/test_run_308_concurrent_participant_execution.py::test_joint_action_record_contract_rejects_unordered_conflicting_writes", + "implementations/python/tests/test_participant_runtime_invariants.py::test_order_discipline_accepts_supported_order_claim_strengths", + "implementations/python/tests/test_participant_runtime_invariants.py::test_order_discipline_rejects_wall_clock_causality", + "implementations/python/tests/test_sem_212_participant_attribution_semantics.py::test_attribution_edge_round_trips_on_terminal_observation", + "implementations/python/tests/test_sem_212_participant_attribution_semantics.py::test_timestamp_adjacency_cannot_be_reported_as_strong_causality", + "implementations/python/tests/test_sem_215_participant_outcome_interpretation.py::test_outcome_interpretation_rule_parses_and_compiles_explicit_layers", + "implementations/python/tests/test_sem_215_participant_outcome_interpretation.py::test_local_action_success_does_not_imply_objective_success_without_rule_record", + "implementations/python/tests/test_realization_honesty_conformance.py::test_constructive_envelope_runs_positive_and_negative_honesty_probes", + "implementations/python/tests/test_realization_honesty_conformance.py::test_only_native_live_can_support_native_conformance" + ], + "command_id": "participant-fixtures", + "network": "disabled" + }, + { + "argv": [ + "implementations/python/.venv/bin/raes", + "processor", + "satisfiability", + "docs/research/formal-semantic-validation/corpus/satisfiable-control.sdl.yaml", + "--profile", + "raes-finite-domain-satisfiability-v1" + ], + "command_id": "finite-domain-satisfiable-v2", + "network": "disabled" + }, + { + "argv": [ + "implementations/python/.venv/bin/raes", + "processor", + "satisfiability", + "docs/research/formal-semantic-validation/corpus/unsatisfiable-control.sdl.yaml", + "--profile", + "raes-finite-domain-satisfiability-v1" + ], + "command_id": "finite-domain-unsatisfiable-v2", + "network": "disabled" + }, + { + "argv": [ + "implementations/python/.venv/bin/raes", + "processor", + "exploit-path", + "docs/research/formal-semantic-validation/corpus/exploit-path-valid-v3.json", + "--profile", + "raes-exploit-path-analysis-v1" + ], + "command_id": "typed-exploit-path-valid-v2", + "network": "disabled" + }, + { + "argv": [ + "implementations/python/.venv/bin/raes", + "processor", + "exploit-path", + "docs/research/formal-semantic-validation/corpus/exploit-path-invalid-v3.json", + "--profile", + "raes-exploit-path-analysis-v1" + ], + "command_id": "typed-exploit-path-invalid-v2", + "network": "disabled" + } + ], + "configuration_id": "raes-python-reference-offline-v41", + "corpus_revision": "4.0.0", + "deviations": [], + "execution_id": "issue-1401-execution-v67", + "execution_status": "complete", + "observations": [ + { + "actual_outcome": "accepted", + "analysis_profile": null, + "case_id": "schema-valid-control", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/schema-valid.sdl.yaml" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "A passing minimal source does not establish semantic correctness." + ], + "replayable": true, + "result_digest": "f7d364ef384df8a1526b489501835b635021c860793b5764f91d956710d2250c", + "source_digest": null + }, + { + "actual_outcome": "rejected", + "analysis_profile": null, + "case_id": "schema-unknown-field", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": "SDLParseError", + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/schema-invalid-unknown-field.sdl.yaml" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "The observation covers one unknown-field defect only." + ], + "replayable": true, + "result_digest": "f55d834b458f8e069e1c69061b4cc0a6d61e0e052bf90c670f2e6a5ad8b5bd98", + "source_digest": null + }, + { + "actual_outcome": "accepted", + "analysis_profile": null, + "case_id": "semantic-resolved-objective", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/semantic-valid-participant-identity-v2.sdl.yaml" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "This is a positive control for one objective-reference slice." + ], + "replayable": true, + "result_digest": "652288785dc09095955ed3649f6407d616fb7c4d4f4188df4ed513ccb7537e0b", + "source_digest": null + }, + { + "actual_outcome": "rejected", + "analysis_profile": null, + "case_id": "semantic-dangling-assertion", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": "SDLValidationError", + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/semantic-invalid-dangling-ref-participant-identity-v2.sdl.yaml" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "A single dangling reference does not prove complete semantic coverage." + ], + "replayable": true, + "result_digest": "0207cf616b56708ca9b8c4499d3301abe22dbe52162cf8d58d3bec429d9db024", + "source_digest": null + }, + { + "actual_outcome": "rejected", + "analysis_profile": null, + "case_id": "semantic-ambiguous-reference", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": "SDLValidationError", + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/semantic-invalid-ambiguous-ref.sdl.yaml" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "One namespace collision does not enumerate every ambiguity surface." + ], + "replayable": true, + "result_digest": "9da4a87797d228e0012ab6b30459f4892e41aa6f224a9840be035fee4a2eea73", + "source_digest": null + }, + { + "actual_outcome": "rejected", + "analysis_profile": null, + "case_id": "semantic-feature-cycle", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": "SDLValidationError", + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/semantic-invalid-feature-cycle.sdl.yaml" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "One static dependency cycle does not establish general constraint satisfiability." + ], + "replayable": true, + "result_digest": "d15dbcd99fb4f20b965d7031b07dd6534576302270399c3fa656d29e7de02b83", + "source_digest": null + }, + { + "actual_outcome": "accepted", + "analysis_profile": null, + "case_id": "workflow-reachable-control", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/workflow-reachable.sdl.yaml" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "The graph is workflow control flow only." + ], + "replayable": true, + "result_digest": "b1b49649b54bd59d4ef357b39cf9158da90f4eae560f8dd756acf97bd0827a06", + "source_digest": null + }, + { + "actual_outcome": "rejected", + "analysis_profile": null, + "case_id": "workflow-unreachable-step", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": "SDLValidationError", + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/workflow-unreachable.sdl.yaml" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "The result does not establish network, service, participant, or exploit reachability." + ], + "replayable": true, + "result_digest": "bb931d19346ef9193408ae6c85deb4079704378fc5f00dc5f47a2817cff21943", + "source_digest": null + }, + { + "actual_outcome": "unsupported", + "analysis_profile": null, + "case_id": "whole-scenario-satisfiable-request", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/decisions/issue-168-formal-semantic-validation-reachability-preflight.md" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "No governed whole-scenario constraint theory or solver exists." + ], + "replayable": false, + "result_digest": null, + "source_digest": null + }, + { + "actual_outcome": "unsupported", + "analysis_profile": null, + "case_id": "whole-scenario-unsatisfiable-request", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/decisions/issue-168-formal-semantic-validation-reachability-preflight.md" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Local checks cannot produce a whole-scenario unsat certificate." + ], + "replayable": false, + "result_digest": null, + "source_digest": null + }, + { + "actual_outcome": "unsupported", + "analysis_profile": null, + "case_id": "valid-exploit-path-request", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/decisions/issue-168-formal-semantic-validation-reachability-preflight.md" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "The issue-168 baseline had no canonical typed attack graph or path-query entrypoint." + ], + "replayable": false, + "result_digest": null, + "source_digest": null + }, + { + "actual_outcome": "unsupported", + "analysis_profile": null, + "case_id": "invalid-exploit-path-request", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/decisions/issue-168-formal-semantic-validation-reachability-preflight.md" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Vulnerability and topology declarations are not an invalid-path proof." + ], + "replayable": false, + "result_digest": null, + "source_digest": null + }, + { + "actual_outcome": "stable", + "analysis_profile": null, + "case_id": "compile-repeatability-control", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/determinism-a.sdl.yaml" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "The witness ends at compiled output." + ], + "replayable": true, + "result_digest": "11264a648a949917c0e84a2a1e5d116139a35e6cb941844735a422df95141d6c", + "source_digest": null + }, + { + "actual_outcome": "distinguishable", + "analysis_profile": null, + "case_id": "compile-non-vacuity-control", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/determinism-a.sdl.yaml", + "docs/research/formal-semantic-validation/corpus/determinism-b.sdl.yaml" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Distinct digests are a non-vacuity control, not semantic non-equivalence proof." + ], + "replayable": true, + "result_digest": "72c1ee8c7bbc1f970216fa232b3d4ae917bcb003bd823439bbac8a5db94214e2", + "source_digest": null + }, + { + "actual_outcome": "unsupported", + "analysis_profile": null, + "case_id": "necessity-witness-request", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/decisions/issue-168-formal-semantic-validation-reachability-preflight.md" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "No governed intervention or ablation protocol exists." + ], + "replayable": false, + "result_digest": null, + "source_digest": null + }, + { + "actual_outcome": "unsupported", + "analysis_profile": null, + "case_id": "non-necessity-control-request", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/decisions/issue-168-formal-semantic-validation-reachability-preflight.md" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Attribution and negative fixtures do not demonstrate non-necessity." + ], + "replayable": false, + "result_digest": null, + "source_digest": null + }, + { + "actual_outcome": "satisfiable", + "analysis_profile": "raes-finite-domain-satisfiability-v1", + "case_id": "finite-domain-satisfiable-v2", + "configuration_digest": "sha256:1204635e17e759e9ad3bd6be2ecb28c6de05c07ead6dfdd15936ed5d3d5b81b2", + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": "scenario-satisfiability-evidence/v1", + "evidence_artifact_path": "docs/research/formal-semantic-validation/evidence/finite-domain-satisfiable-v4.json", + "evidence_artifact_sha256": "554202313d678046958b5c028e2de26ff03c74895cfac552677eed74e8153add", + "evidence_digest": "sha256:23c2cae7d95d4cc83d77ca576e3911477b169ecc311c977cb45490345f633b5a", + "evidence_profile": "scenario-satisfiability-evidence/v1", + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/satisfiable-control.sdl.yaml", + "docs/research/formal-semantic-validation/evidence/finite-domain-satisfiable-v4.json", + "specs/formal/scenario-satisfiability/README.md" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Demonstrates only the pinned finite-domain theory, translation, solver profile, and source." + ], + "replayable": true, + "result_digest": "sha256:23c2cae7d95d4cc83d77ca576e3911477b169ecc311c977cb45490345f633b5a", + "source_digest": "sha256:0ca9eaba9dc47171f7a042dc6753faa6c820c65ee966538f9d65fac5342202e8" + }, + { + "actual_outcome": "unsatisfiable", + "analysis_profile": "raes-finite-domain-satisfiability-v1", + "case_id": "finite-domain-unsatisfiable-v2", + "configuration_digest": "sha256:1204635e17e759e9ad3bd6be2ecb28c6de05c07ead6dfdd15936ed5d3d5b81b2", + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": "scenario-satisfiability-evidence/v1", + "evidence_artifact_path": "docs/research/formal-semantic-validation/evidence/finite-domain-unsatisfiable-v4.json", + "evidence_artifact_sha256": "c972725ef64822a75a60380afc11f08eac25b7fe9b091d39b058b3c9f7c8031d", + "evidence_digest": "sha256:317b5cad00aa7f4f7868dca66127611ba19d40ffd86f35815502622814df54c1", + "evidence_profile": "scenario-satisfiability-evidence/v1", + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/unsatisfiable-control.sdl.yaml", + "docs/research/formal-semantic-validation/evidence/finite-domain-unsatisfiable-v4.json", + "specs/formal/scenario-satisfiability/README.md" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "The subset-minimal core is evidence for the pinned translation and solver, not a proof certificate for arbitrary SDL." + ], + "replayable": true, + "result_digest": "sha256:317b5cad00aa7f4f7868dca66127611ba19d40ffd86f35815502622814df54c1", + "source_digest": "sha256:cfef56a1f56d5f0db9da195377fd75694bdd0f0b92932fdb8fafcbd3f7baf6c5" + }, + { + "actual_outcome": "valid-path", + "analysis_profile": "raes-exploit-path-analysis-v1", + "case_id": "typed-exploit-path-valid-v2", + "configuration_digest": "sha256:7f8876d81feb77d3a3239be2fb8337de8885e2744f8786728ba23e4e6027bc0a", + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": "exploit-path-analysis-evidence/v1", + "evidence_artifact_path": "docs/research/formal-semantic-validation/evidence/typed-exploit-path-valid-v4.json", + "evidence_artifact_sha256": "1b7f55d04db172da32658187c64a88c13b5f4d565267ce2be7cb86a9d04cb70c", + "evidence_digest": "sha256:2d4d1a362751abd9544beb8af7f8c6331d04dac8f4abc315fb261f81fbaf4387", + "evidence_profile": "exploit-path-analysis-evidence/v1", + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/exploit-path-valid-v3.json", + "docs/research/formal-semantic-validation/evidence/typed-exploit-path-valid-v4.json", + "specs/formal/exploit-path-analysis/README.md" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "The witness is bounded to the admitted snapshot, normalized graph, query, semantics, and search profile; it does not establish backend execution." + ], + "replayable": true, + "result_digest": "sha256:2d4d1a362751abd9544beb8af7f8c6331d04dac8f4abc315fb261f81fbaf4387", + "source_digest": "sha256:0afe635a63db5b6e6380ac70982fd61d09790745d51a10d670321304121e7c39" + }, + { + "actual_outcome": "invalid-path", + "analysis_profile": "raes-exploit-path-analysis-v1", + "case_id": "typed-exploit-path-invalid-v2", + "configuration_digest": "sha256:7f8876d81feb77d3a3239be2fb8337de8885e2744f8786728ba23e4e6027bc0a", + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": "exploit-path-analysis-evidence/v1", + "evidence_artifact_path": "docs/research/formal-semantic-validation/evidence/typed-exploit-path-invalid-v4.json", + "evidence_artifact_sha256": "244f895a64f14c10916ab0533ab462ce80a328021cd6a50c30a4aa59266d5533", + "evidence_digest": "sha256:1b416bb5a4d29d57c961b769cc9d3af5d9328624e3eebf104d57f39a94c5bb97", + "evidence_profile": "exploit-path-analysis-evidence/v1", + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/exploit-path-invalid-v3.json", + "docs/research/formal-semantic-validation/evidence/typed-exploit-path-invalid-v4.json", + "specs/formal/exploit-path-analysis/README.md" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Structured rejection proves only that this bounded graph/query cannot reach its goal; it does not establish real-world non-exploitability." + ], + "replayable": true, + "result_digest": "sha256:1b416bb5a4d29d57c961b769cc9d3af5d9328624e3eebf104d57f39a94c5bb97", + "source_digest": "sha256:0b2293d4a8983515ff05c516be6e6b418a4f3f09e055250a00bf15fda861aab3" + } + ], + "participant_observations": [ + { + "evidence_refs": [ + "implementations/python/tests/test_sem_208_participant_behavior.py::test_hidden_truth_disclosure_is_separate_from_observable_projection", + "implementations/python/tests/test_sem_208_participant_behavior.py::test_hidden_truth_cannot_be_observed_without_explicit_disclosure_rule" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Covers the reference SDL/contract path, not every backend projection." + ], + "negative_outcome": "passed", + "obligation_id": "hidden-vs-visible-projection", + "positive_outcome": "passed" + }, + { + "evidence_refs": [ + "implementations/python/tests/test_sem_211_participant_action_semantics.py::test_action_contract_declares_sem_211_classes_and_compiles_them", + "implementations/python/tests/test_sem_211_participant_action_semantics.py::test_action_result_rejects_success_when_preconditions_are_unresolved" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Covers declared applicability and one unresolved-precondition failure." + ], + "negative_outcome": "passed", + "obligation_id": "fail-closed-action-applicability", + "positive_outcome": "passed" + }, + { + "evidence_refs": [ + "implementations/python/tests/test_run_308_concurrent_participant_execution.py::test_runtime_snapshot_publishes_joint_action_and_time_context_records", + "implementations/python/tests/test_run_308_concurrent_participant_execution.py::test_joint_action_record_contract_rejects_unordered_conflicting_writes" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Contract evidence does not prove every backend's live concurrency fidelity." + ], + "negative_outcome": "passed", + "obligation_id": "shared-state-effects", + "positive_outcome": "passed" + }, + { + "evidence_refs": [ + "implementations/python/tests/test_participant_runtime_invariants.py::test_order_discipline_accepts_supported_order_claim_strengths", + "implementations/python/tests/test_participant_runtime_invariants.py::test_order_discipline_rejects_wall_clock_causality" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Rejecting timestamp-only causality does not supply counterfactual proof." + ], + "negative_outcome": "passed", + "obligation_id": "ordering-before-causality", + "positive_outcome": "passed" + }, + { + "evidence_refs": [ + "implementations/python/tests/test_sem_212_participant_attribution_semantics.py::test_attribution_edge_round_trips_on_terminal_observation", + "implementations/python/tests/test_sem_212_participant_attribution_semantics.py::test_timestamp_adjacency_cannot_be_reported_as_strong_causality" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Attribution labels disclose basis; they do not demonstrate necessity." + ], + "negative_outcome": "passed", + "obligation_id": "evidence-labeled-attribution", + "positive_outcome": "passed" + }, + { + "evidence_refs": [ + "implementations/python/tests/test_sem_215_participant_outcome_interpretation.py::test_outcome_interpretation_rule_parses_and_compiles_explicit_layers", + "implementations/python/tests/test_sem_215_participant_outcome_interpretation.py::test_local_action_success_does_not_imply_objective_success_without_rule_record" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "The fixtures establish layer separation, not outcome validity in every realization." + ], + "negative_outcome": "passed", + "obligation_id": "participant-local-outcome-separation", + "positive_outcome": "passed" + }, + { + "evidence_refs": [ + "implementations/python/tests/test_realization_honesty_conformance.py::test_constructive_envelope_runs_positive_and_negative_honesty_probes", + "implementations/python/tests/test_realization_honesty_conformance.py::test_only_native_live_can_support_native_conformance" + ], + "execution_id": "issue-1401-execution-v67", + "limitations": [ + "Reference conformance evidence remains bounded to declared realization profiles." + ], + "negative_outcome": "passed", + "obligation_id": "realization-profile-honesty", + "positive_outcome": "passed" + } + ], + "protocol_revision": "2.0.0", + "raes_revision": "6d55d336eb9f39eb7718834e2645888f965adc8d", + "source_state": { + "base_revision": "6d55d336eb9f39eb7718834e2645888f965adc8d", + "checkout_state": "modified", + "implementation_digest": "8c1153320260a66058dcc38a2dcf6efd417f1c133b6d052df022ea85a6ae027d", + "profile": "python-reference-source/v2" + }, + "versions": { + "python": "3.14.4", + "raes": "5.0.0", + "z3_engine": "4.16.0", + "z3_solver": "4.16.0.0" + } +} diff --git a/docs/research/formal-semantic-validation/index.md b/docs/research/formal-semantic-validation/index.md index 02a973a5d..089d5a93c 100644 --- a/docs/research/formal-semantic-validation/index.md +++ b/docs/research/formal-semantic-validation/index.md @@ -336,7 +336,7 @@ outcomes and claim limits, recording the positive successor's changed result digest; the dangling-reference diagnostic remains identical. It establishes no autonomy threshold, authority grant, or realized attribution. -Current validation requires explicit release 66.0.0, rejects unsupported future +Current validation requires explicit release 67.0.0, rejects unsupported future or duplicate revisions, and never accepts an old/new output-digest pair as a substitute for replay. Historical releases (including the issue-826 supplement) undergo pin, shape, control, and internal-join checks without executing current @@ -564,3 +564,9 @@ upgrade to 2.15.1 and the urllib3 upgrade to 2.8.0 in [`execution-snapshot-v66.json`](execution-snapshot-v66.json) and [`analysis-v66.json`](analysis-v66.json). Outcomes and claim limits remain unchanged. + +Release 67.0.0 replays the retained formal cases after issue #1401 began +rejecting required evidence whose declared media type the output registry +cannot prove, in [`execution-snapshot-v67.json`](execution-snapshot-v67.json) +and [`analysis-v67.json`](analysis-v67.json). Outcomes and claim limits remain +unchanged. diff --git a/docs/research/specification-coverage/analysis-v66.json b/docs/research/specification-coverage/analysis-v66.json new file mode 100644 index 000000000..26493b001 --- /dev/null +++ b/docs/research/specification-coverage/analysis-v66.json @@ -0,0 +1,107 @@ +{ + "analysis_id": "raes-standardized-specification-coverage-issue-1401-v66", + "backend_leakage": [], + "claim": { + "allowed_evidence": [ + "pinned source metadata and bounded paraphrases", + "production parser, semantic, instantiation, admission, compiler, contract, and profile results", + "exact artifact digests and typed pointers", + "documented missing-concept and backend-specific dispositions" + ], + "claim_id": "raes-standardized-configurable-specification-coverage", + "disallowed_evidence": [ + "field-count or schema breadth alone", + "the existing scenario stress corpus as the representative request corpus", + "free-form metadata as typed coverage", + "backend-private interpretation", + "post-hoc removal or repair of falsifying concepts" + ], + "evidence_artifacts": [ + "docs/research/specification-coverage/protocol-v1.json", + "docs/research/specification-coverage/execution-snapshot-v66.json", + "docs/research/specification-coverage/analysis-v66.json" + ], + "falsification_protocol": "docs/research/specification-coverage/protocol-v1.json", + "objective_fail_criteria": "A load-bearing concept is missing or lossy, an applicable stage fails, or backend vocabulary is required in core SDL while the result claims success.", + "objective_pass_criteria": "Every load-bearing concept passes at every owning stage, backend-specific mechanics stay outside core SDL, and no requested concept is silently lost.", + "statement": "RAES provides a standardized configurable portable specification surface for the preregistered representative cyber-agent evaluation environment requirements without backend vocabulary in core SDL.", + "threats_to_validity": [ + "The representative corpus contains four source strata and sixteen atomic concepts rather than every cyber-range requirement.", + "The reference processor and repository fixtures are not independent backend implementations.", + "No live range, simulator federation, or participant execution was part of this offline specification-coverage test." + ] + }, + "classification_counts": { + "deliberately-backend-specific": 1, + "directly-expressible": 10, + "missing": 3, + "profile-or-manifest-constraint": 2 + }, + "evidence_status": "partial", + "execution_status": "complete", + "generated_at": "2026-09-30T22:41:24.312224+00:00", + "limitations": [ + "This result demonstrates bounded specification coverage, not universal cyber-range coverage, usability, adoption, backend substitution, or behavioral equivalence.", + "The three missing concepts are evidence, not implementation tasks within this snapshot.", + "The retained protocol does not test recursive realization or plan-level profile semantics; this release only re-establishes its original bounded coverage result against the current implementation.", + "The retained protocol does not test evidence-requirement refinement lineage; the dedicated EXP-731 regression suite covers that production boundary.", + "Authoring-adapter transport behavior is outside this retained protocol.", + "Reviewed OCI mirror and pre-seed admission is covered by its own regression suites and the development artifact policy gate, not a new claim in this preregistered matrix.", + "Operational recovery observation and startup reconciliation are covered by their API-404 regression suite, not a new claim in this preregistered matrix.", + "Store ownership, immutable runtime scope, and provider shutdown ordering are covered by the API-404 CP-5 regression suite, not by this retained specification-coverage protocol.", + "Mixed/staged trial compilation and admission are covered by issue #1015 regression tests, not by this retained specification-coverage corpus; no live mixed-runtime result is claimed.", + "Issue #1186 control-plane recovery operations are covered by their runtime regression suite, not by this retained specification-coverage corpus.", + "Issue #1187 control-plane crash/profile conformance and HTTP security changes are covered by their dedicated regression suite, not promoted to new claims by this retained corpus.", + "Issue #1189 control-plane profile declarations are covered by their dedicated runtime suite, not promoted to new claims by the retained language corpus.", + "Issue #610's reconciliation demonstration harness is covered by its dedicated processor and CLI suite, not promoted to new claims by the retained language corpus.", + "Participant identity, organization ownership, and participant assignment are separated by issue #1338. This retained offline corpus does not establish participant autonomy, execution authority, live backend fidelity, or causal attribution.", + "Participant-local outcome state is verified by the ACT-618 tests; this retained corpus makes no additional outcome-state claim.", + "Backend operation supervision contracts are covered by issue #1360 contract tests; this retained offline corpus establishes no live backend supervision or recovery guarantee.", + "This capture replays the merged issue #1360 and #1357 source; the protocol makes no live backend execution or supervision claim.", + "This capture replays the merged issue #1360 and #1358 source; the protocol makes no live backend execution or supervision claim.", + "Issue #1389 participant inject delivery temporal-subject admission is covered by dedicated compiler tests; this retained matrix makes no new timing or execution claim.", + "Issue #971 adds offline crossing model construction; this retained protocol establishes no crossing equivalence or runtime-realization claim.", + "Issue #1359 control-plane route authority, participant-view scoping, and no-store HTTP boundary are covered by their dedicated HTTP-boundary suite; this retained matrix makes no new exposure or execution claim.", + "Issue #1401 required-evidence media-type coherence is verified by its dedicated suite; this retained matrix makes no new admission or capture claim." + ], + "load_bearing_results": { + "failed": 0, + "missing": 0, + "passed": 10, + "total": 10 + }, + "plain_language_outcome": "The retained specification-coverage matrix reproduces its prior classifications against source that rejects required evidence whose declared media type the output registry cannot prove; classifications and claim limits are unchanged.", + "protocol_revision": "1.0.0", + "request_results": [ + { + "concept_count": 6, + "failed_stage_count": 0, + "missing_count": 0, + "request_id": "survey-representative-range", + "status": "demonstrated" + }, + { + "concept_count": 5, + "failed_stage_count": 1, + "missing_count": 1, + "request_id": "cyborg-participant-evaluation", + "status": "partial" + }, + { + "concept_count": 3, + "failed_stage_count": 1, + "missing_count": 1, + "request_id": "vsdl-configurable-infrastructure", + "status": "partial" + }, + { + "concept_count": 2, + "failed_stage_count": 1, + "missing_count": 1, + "request_id": "cyber-dem-federation", + "status": "partial" + } + ], + "snapshot_id": "raes-standardized-specification-coverage-issue-1401-v66", + "snapshot_sha256": "1c923ff0c8de6f25f672c732667ddce6362ef243c63415810b29bea42fd55f38" +} diff --git a/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1401-v66.json b/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1401-v66.json new file mode 100644 index 000000000..094765f73 --- /dev/null +++ b/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1401-v66.json @@ -0,0 +1,10 @@ +{ + "analysis_path": "docs/research/specification-coverage/analysis-v66.json", + "analysis_sha256": "8410282e4ae5b6ffc590dcb8c447b33ef9ee66ac687c3318b7b2d3b84af0d237", + "bundle_id": "raes-standardized-specification-coverage", + "protocol_path": "docs/research/specification-coverage/protocol-v1.json", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "revision": "66.0.0", + "snapshot_path": "docs/research/specification-coverage/execution-snapshot-v66.json", + "snapshot_sha256": "be6f6c95160944d2134a683954ef3ee7d8a8393b033ff1b1dbfe2227a623ed5d" +} diff --git a/docs/research/specification-coverage/execution-snapshot-v66.json b/docs/research/specification-coverage/execution-snapshot-v66.json new file mode 100644 index 000000000..a3e6b0ba1 --- /dev/null +++ b/docs/research/specification-coverage/execution-snapshot-v66.json @@ -0,0 +1,700 @@ +{ + "artifacts": [ + { + "artifact_id": "enterprise-participant-sdl", + "kind": "sdl", + "path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "sha256": "f7a8897beec243e188ee081975006fad32725f469f267db6e75a1e1cf5727032", + "validator": "raes parse, semantic, instantiation/admission, and compiler pipeline" + }, + { + "artifact_id": "port-range-sdl", + "kind": "sdl", + "path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "sha256": "0d5497ec946b863e6985284ec487dde7d7f6bf710a985be51401ac0e5e79dc4f", + "validator": "raes parse, semantic, instantiation/admission, and compiler pipeline" + }, + { + "artifact_id": "experiment-task-contract", + "kind": "experiment-task", + "path": "contracts/fixtures/experiment-core/experiment-task-v1/valid/reference.json", + "sha256": "f3edf713ac6af26bad609136851c6dd434bfb87ce919a2d8c4414c1035deeafc", + "validator": "raes_contracts.contracts.ExperimentTaskModel" + }, + { + "artifact_id": "apparatus-context-contract", + "kind": "experiment-apparatus-context", + "path": "contracts/fixtures/experiment-core/experiment-apparatus-context-v1/valid/reference.json", + "sha256": "e6fa559c5e961f0aab448d0f70dead24aa74fa8ba5f20e1b72f88e11473c9299", + "validator": "raes_contracts.contracts.ExperimentApparatusContextModel" + }, + { + "artifact_id": "backend-profile", + "kind": "backend-profile", + "path": "contracts/profiles/backend/orchestration-capable.json", + "sha256": "f70b8505a5c0055416db86c533e2e5bf08b11e5a514f076223b6d6c36215a092", + "validator": "raes_contracts.backend_profiles.BackendProfileModel" + }, + { + "artifact_id": "known-limitations", + "kind": "documentation", + "path": "docs/explain/sdl/limitations.md", + "sha256": "489eeab3ce682627682311581eb98af9abb9ff42a437145af266eefb71dc7fc4", + "validator": "documentation evidence only" + } + ], + "baseline": { + "release_revision": "1.1.0", + "release_sha256": "4020a1d56c7fe2831cec59ea64a12bbda9d38ccd94f93b916dd90f1a28f17fcb" + }, + "captured_at": "2026-09-30T22:41:24.312224+00:00", + "concept_results": [ + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "directly-expressible", + "completeness_disposition": "implemented", + "concept_id": "range-topology", + "rationale": "SDL nodes and infrastructure own host, network, link, and dependency meaning; the compiler emits canonical node deployment addresses.", + "stage_results": [ + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Typed VM declaration.", + "outcome": "passed", + "pointer": "/nodes/shipping-portal", + "stage_id": "authored", + "validation_strength": "structural" + }, + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Links and dependencies resolved.", + "outcome": "passed", + "pointer": "/infrastructure/shipping-portal", + "stage_id": "semantic", + "validation_strength": "semantic" + }, + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Published instantiated shape admitted.", + "outcome": "passed", + "pointer": "/nodes/shipping-portal", + "stage_id": "instantiated", + "validation_strength": "phase-admitted" + }, + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Canonical deployment address retained.", + "outcome": "passed", + "pointer": "/node_deployments/provision.node.shipping-portal", + "stage_id": "compiled", + "validation_strength": "compiled" + } + ], + "typed_pointer": "/nodes/shipping-portal" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "directly-expressible", + "completeness_disposition": "implemented", + "concept_id": "exercise-roles", + "rationale": "SDL entity roles own exercise responsibility without becoming control-plane identity or authorization.", + "stage_results": [ + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Typed red role.", + "outcome": "passed", + "pointer": "/entities/enterprise-participant/role", + "stage_id": "authored", + "validation_strength": "structural" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Entity references validated.", + "outcome": "passed", + "pointer": "/entities/enterprise-participant", + "stage_id": "semantic", + "validation_strength": "semantic" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Role retained after instantiation.", + "outcome": "passed", + "pointer": "/entities/enterprise-participant/role", + "stage_id": "instantiated", + "validation_strength": "phase-admitted" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Role retained in entity specification.", + "outcome": "passed", + "pointer": "/entity_specs/enterprise-participant/role", + "stage_id": "compiled", + "validation_strength": "compiled" + } + ], + "typed_pointer": "/entities/enterprise-participant/role" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "directly-expressible", + "completeness_disposition": "implemented", + "concept_id": "evaluation-objectives", + "rationale": "SDL objectives own organization ownership, participant assignment, targets, windows, and assertion-based success; measures remain experiment contracts.", + "stage_results": [ + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Typed objective declaration.", + "outcome": "passed", + "pointer": "/objectives/demonstrate-handoff", + "stage_id": "authored", + "validation_strength": "structural" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Owner, participant assignment, targets, assertions, and workflow refs resolved.", + "outcome": "passed", + "pointer": "/objectives/demonstrate-handoff/success", + "stage_id": "semantic", + "validation_strength": "semantic" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Objective retained in admitted artifact.", + "outcome": "passed", + "pointer": "/objectives/demonstrate-handoff", + "stage_id": "instantiated", + "validation_strength": "phase-admitted" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Canonical objective address retained.", + "outcome": "passed", + "pointer": "/objectives/evaluation.objective.demonstrate-handoff", + "stage_id": "compiled", + "validation_strength": "compiled" + } + ], + "typed_pointer": "/objectives/demonstrate-handoff" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "directly-expressible", + "completeness_disposition": "implemented", + "concept_id": "control-workflows", + "rationale": "SDL workflows own the portable control graph and compile to canonical orchestration state contracts.", + "stage_results": [ + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Typed control graph.", + "outcome": "passed", + "pointer": "/workflows/yard-recovery", + "stage_id": "authored", + "validation_strength": "structural" + }, + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Step graph and objective refs validated.", + "outcome": "passed", + "pointer": "/workflows/yard-recovery/steps", + "stage_id": "semantic", + "validation_strength": "semantic" + }, + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Workflow retained after instantiation.", + "outcome": "passed", + "pointer": "/workflows/yard-recovery", + "stage_id": "instantiated", + "validation_strength": "phase-admitted" + }, + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Canonical control graph retained.", + "outcome": "passed", + "pointer": "/workflows/orchestration.workflow.yard-recovery", + "stage_id": "compiled", + "validation_strength": "compiled" + } + ], + "typed_pointer": "/workflows/yard-recovery" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "directly-expressible", + "completeness_disposition": "implemented", + "concept_id": "authored-evidence-expectations", + "rationale": "SDL evidence requirements own portable capture intent and remain distinct from evidence records and measures.", + "stage_results": [ + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Typed capture obligation.", + "outcome": "passed", + "pointer": "/evidence_requirements/objective-truth-evidence", + "stage_id": "authored", + "validation_strength": "structural" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Source refs and bindings validated.", + "outcome": "passed", + "pointer": "/evidence_requirements/objective-truth-evidence", + "stage_id": "semantic", + "validation_strength": "semantic" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Evidence intent retained in admitted artifact.", + "outcome": "passed", + "pointer": "/evidence_requirements/objective-truth-evidence", + "stage_id": "instantiated", + "validation_strength": "phase-admitted" + } + ], + "typed_pointer": "/evidence_requirements/objective-truth-evidence" + }, + { + "backend_support": "profile-bound", + "backend_vocabulary_occurrences": [], + "classification": "profile-or-manifest-constraint", + "completeness_disposition": "implemented", + "concept_id": "apparatus-selection-constraints", + "rationale": "The experiment task contract binds processor/backend identities, manifest refs, and capabilities outside SDL.", + "stage_results": [ + { + "artifact_path": "contracts/fixtures/experiment-core/experiment-task-v1/valid/reference.json", + "diagnostic_codes": [], + "note": "Closed ExperimentTaskModel validated.", + "outcome": "passed", + "pointer": "/apparatus_constraints/allowed_backend_refs/0", + "stage_id": "contract", + "validation_strength": "contract" + } + ], + "typed_pointer": "/apparatus_constraints/allowed_backend_refs/0" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "directly-expressible", + "completeness_disposition": "implemented", + "concept_id": "participant-agent", + "rationale": "SDL agents own participant entity, knowledge, actions, observation boundaries, and operating scope.", + "stage_results": [ + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Typed participant declaration.", + "outcome": "passed", + "pointer": "/agents/participant-agent", + "stage_id": "authored", + "validation_strength": "structural" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Participant refs and scope validated.", + "outcome": "passed", + "pointer": "/agents/participant-agent/observation_boundaries", + "stage_id": "semantic", + "validation_strength": "semantic" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Participant retained in admitted artifact.", + "outcome": "passed", + "pointer": "/agents/participant-agent", + "stage_id": "instantiated", + "validation_strength": "phase-admitted" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Compiled participant scope retained.", + "outcome": "passed", + "pointer": "/agent_specs/participant-agent", + "stage_id": "compiled", + "validation_strength": "compiled" + } + ], + "typed_pointer": "/agents/participant-agent" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "directly-expressible", + "completeness_disposition": "implemented", + "concept_id": "participant-action-contract", + "rationale": "The action contract declares portable preconditions, effects, observations, evidence, and failure classes without a runner command.", + "stage_results": [ + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Typed action contract.", + "outcome": "passed", + "pointer": "/action_contracts/probe-customer-portal-login", + "stage_id": "authored", + "validation_strength": "structural" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Action refs and evidence bindings validated.", + "outcome": "passed", + "pointer": "/action_contracts/probe-customer-portal-login/effects", + "stage_id": "semantic", + "validation_strength": "semantic" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Action retained in admitted artifact.", + "outcome": "passed", + "pointer": "/action_contracts/probe-customer-portal-login", + "stage_id": "instantiated", + "validation_strength": "phase-admitted" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Canonical action address retained.", + "outcome": "passed", + "pointer": "/action_contracts/participant.action-contract.probe-customer-portal-login", + "stage_id": "compiled", + "validation_strength": "compiled" + } + ], + "typed_pointer": "/action_contracts/probe-customer-portal-login" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "directly-expressible", + "completeness_disposition": "implemented", + "concept_id": "participant-observation-boundary", + "rationale": "The observation boundary separately declares visible, hidden, and evidence-only information with transition rules.", + "stage_results": [ + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Typed observation boundary.", + "outcome": "passed", + "pointer": "/observation_boundaries/participant-view", + "stage_id": "authored", + "validation_strength": "structural" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Information refs and transitions validated.", + "outcome": "passed", + "pointer": "/observation_boundaries/participant-view/view_rules", + "stage_id": "semantic", + "validation_strength": "semantic" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Boundary retained in admitted artifact.", + "outcome": "passed", + "pointer": "/observation_boundaries/participant-view", + "stage_id": "instantiated", + "validation_strength": "phase-admitted" + }, + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "diagnostic_codes": [], + "note": "Canonical boundary address retained.", + "outcome": "passed", + "pointer": "/observation_boundaries/participant.observation-boundary.participant-view", + "stage_id": "compiled", + "validation_strength": "compiled" + } + ], + "typed_pointer": "/observation_boundaries/participant-view" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "directly-expressible", + "completeness_disposition": "implemented", + "concept_id": "evaluation-measure", + "rationale": "ExperimentTaskModel owns metric construct, unit, direction, aggregation, and evidence requirements outside SDL objectives.", + "stage_results": [ + { + "artifact_path": "contracts/fixtures/experiment-core/experiment-task-v1/valid/reference.json", + "diagnostic_codes": [], + "note": "Closed task contract validated.", + "outcome": "passed", + "pointer": "/evaluation_protocol/metric_definitions/foothold-achieved", + "stage_id": "contract", + "validation_strength": "contract" + } + ], + "typed_pointer": "/evaluation_protocol/metric_definitions/foothold-achieved" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "missing", + "completeness_disposition": "documented-gap", + "concept_id": "participant-tool-affordance", + "rationale": "This preregistered matrix has no tested carrier for participant tool affordances. The retained missing classification records missing coverage evidence, not the absence of current participant-behavior capabilities.", + "stage_results": [ + { + "artifact_path": "docs/explain/sdl/limitations.md", + "diagnostic_codes": [], + "note": "The preregistered carrier slot was not run; metadata does not substitute for a typed coverage test.", + "outcome": "not_run", + "pointer": null, + "stage_id": "authored", + "validation_strength": "not-applicable" + } + ], + "typed_pointer": null + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "directly-expressible", + "completeness_disposition": "implemented", + "concept_id": "resource-constrained-topology", + "rationale": "SDL node resources and infrastructure dependencies express portable resource intent without provider resource identifiers.", + "stage_results": [ + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Typed CPU and memory declaration.", + "outcome": "passed", + "pointer": "/nodes/shipping-portal/resources", + "stage_id": "authored", + "validation_strength": "structural" + }, + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Resource-bearing topology validated.", + "outcome": "passed", + "pointer": "/infrastructure/shipping-portal", + "stage_id": "semantic", + "validation_strength": "semantic" + }, + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Constraints retained in admitted artifact.", + "outcome": "passed", + "pointer": "/nodes/shipping-portal/resources", + "stage_id": "instantiated", + "validation_strength": "phase-admitted" + }, + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "diagnostic_codes": [], + "note": "Deployment specification retains resource intent.", + "outcome": "passed", + "pointer": "/node_deployments/provision.node.shipping-portal", + "stage_id": "compiled", + "validation_strength": "compiled" + } + ], + "typed_pointer": "/nodes/shipping-portal/resources" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "missing", + "completeness_disposition": "documented-gap", + "concept_id": "formal-constraint-satisfiability", + "rationale": "This coverage matrix did not exercise a solver-backed carrier. The separate formal-semantic-validation release demonstrates its bounded finite-domain profile; that result is not silently imported into this protocol's missing carrier slot.", + "stage_results": [ + { + "artifact_path": "docs/explain/sdl/limitations.md", + "diagnostic_codes": [], + "note": "No coverage-carrier execution was performed here; independent solver evidence does not change this preregistered denominator.", + "outcome": "not_run", + "pointer": null, + "stage_id": "semantic", + "validation_strength": "not-applicable" + } + ], + "typed_pointer": null + }, + { + "backend_support": "profile-bound", + "backend_vocabulary_occurrences": [ + { + "allowed": true, + "artifact_path": "source:vsdl-paper", + "pointer": "source sections 4-5", + "reason": "Legitimate VSDL realization vocabulary, not RAES core SDL structure.", + "term": "OpenStack/Terraform/Packer" + } + ], + "classification": "deliberately-backend-specific", + "completeness_disposition": "external", + "concept_id": "provider-specific-provisioning", + "rationale": "Provider image selection and provisioning engines are realization mechanics and therefore remain outside core SDL.", + "stage_results": [ + { + "artifact_path": "contracts/profiles/backend/orchestration-capable.json", + "diagnostic_codes": [], + "note": "The portable boundary requires backend contracts; it does not standardize a provider engine.", + "outcome": "not_applicable", + "pointer": "/required_contracts", + "stage_id": "realization-disclosure", + "validation_strength": "profile" + } + ], + "typed_pointer": null + }, + { + "backend_support": "profile-bound", + "backend_vocabulary_occurrences": [], + "classification": "profile-or-manifest-constraint", + "completeness_disposition": "implemented", + "concept_id": "apparatus-clock-context", + "rationale": "ExperimentApparatusContextModel records clock authority, time domain, and synchronization as apparatus facts outside scenario meaning.", + "stage_results": [ + { + "artifact_path": "contracts/fixtures/experiment-core/experiment-apparatus-context-v1/valid/reference.json", + "diagnostic_codes": [], + "note": "Closed apparatus context contract validated.", + "outcome": "passed", + "pointer": "/clocks/0", + "stage_id": "contract", + "validation_strength": "contract" + } + ], + "typed_pointer": "/clocks/0" + }, + { + "backend_support": "not-evaluated", + "backend_vocabulary_occurrences": [], + "classification": "missing", + "completeness_disposition": "documented-gap", + "concept_id": "federated-object-event-exchange", + "rationale": "The federated cyber object/event exchange carrier was not exercised by this preregistered matrix. Runtime event internals are not treated as equivalent evidence.", + "stage_results": [ + { + "artifact_path": "docs/explain/sdl/limitations.md", + "diagnostic_codes": [], + "note": "The missing coverage-carrier test is recorded explicitly, without inferring an ecosystem-wide capability absence.", + "outcome": "not_run", + "pointer": null, + "stage_id": "contract", + "validation_strength": "not-applicable" + } + ], + "typed_pointer": null + } + ], + "deviations": [ + { + "artifact_path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "baseline_sha256": "54ba1a60220e27a55da9cd2a407d7d3ab836fa54460d0b0c6cad87c2e744ddbb", + "rationale": "Migrate participant affiliations and explicit objective assignment, retaining organizational intent and portable action-contract declarations without granting execution authority.", + "retest_sha256": "f7a8897beec243e188ee081975006fad32725f469f267db6e75a1e1cf5727032" + }, + { + "artifact_path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "baseline_sha256": "a27c7a64e0c5c618fadaccafdf1a4e71600170a8b77b983190822b5141f00dec", + "rationale": "Migrate participant affiliations and explicit objective assignment, retaining organizational intent and portable action-contract declarations without granting execution authority.", + "retest_sha256": "0d5497ec946b863e6985284ec487dde7d7f6bf710a985be51401ac0e5e79dc4f" + }, + { + "artifact_path": "contracts/fixtures/experiment-core/experiment-task-v1/valid/reference.json", + "baseline_sha256": "21952a752f4e8581a9fc3b872e4bc308150548170d38bcfc83dbbe35ff5e0b9f", + "rationale": "Replay the retained preregistered artifact against the current evidence-provenance validation implementation.", + "retest_sha256": "f3edf713ac6af26bad609136851c6dd434bfb87ce919a2d8c4414c1035deeafc" + }, + { + "artifact_path": "contracts/fixtures/experiment-core/experiment-apparatus-context-v1/valid/reference.json", + "baseline_sha256": "9536d897a09cbc6920e667e4f8f9371e51307aa0b3b5ff3c7de682dd783420ab", + "rationale": "Replay the retained preregistered artifact against the current evidence-provenance validation implementation.", + "retest_sha256": "e6fa559c5e961f0aab448d0f70dead24aa74fa8ba5f20e1b72f88e11473c9299" + }, + { + "artifact_path": "docs/explain/sdl/limitations.md", + "baseline_sha256": "129cf17810aad4c51988bc872e28fe43ae95019a80053c42d800ff7e2b9cc93e", + "rationale": "Correct historical mandatory-profile guidance after issue #1207; retain the preregistered missing-concept classifications and coverage limits.", + "retest_sha256": "489eeab3ce682627682311581eb98af9abb9ff42a437145af266eefb71dc7fc4" + } + ], + "execution_status": "complete", + "implementation_surfaces": [ + { + "content_sha256": "a64212a253972c4869d65b206f5751f06e4a2b25b43e1f6bd4eb2c1bd8be5e7c", + "path": "implementations/python/packages/raes_contracts", + "surface_id": "contract-models" + }, + { + "content_sha256": "27cf5d5bac07ef4b79d922e7c924832c89f13f12ab7e3a441b1a97557dba2b14", + "path": "implementations/python/packages/raes_processor", + "surface_id": "processor-pipeline" + }, + { + "content_sha256": "92efe6d6eaf0a680b8f8517344e0c677886cd56163b3fe86d27458c3c4dfb24b", + "path": "implementations/python/packages/raes", + "surface_id": "sdl-pipeline" + } + ], + "limitations": [ + "The execution validates the pinned reference implementation and published contracts, not an independent backend.", + "Repository-owned examples are exact execution artifacts but are not themselves the literature-derived request corpus; the protocol's requests and concepts are.", + "No live range, participant, simulator federation, or provider provisioning engine was executed.", + "Missing concepts remain frozen in this snapshot and require separately scoped product work before a later rerun.", + "This capture replays the retained protocol after EXP-732 run, apparatus, measurement-channel, and augmentation-producer provenance validation; it adds no independent backend or universal provenance assurance claim.", + "Materialization attestation is covered by its dedicated regression suite, not a new claim in this preregistered matrix.", + "This capture refreshes the corrected runtime limitations prose for issue #959; the protocol, coverage classifications and implementation source are unchanged.", + "This capture replays open-by-default augmentation scope integrated with the EXP-731 evidence refinements after composition type refinement; it does not evaluate native backend scope enforcement or broaden the preregistered coverage claims.", + "This capture replays the retained protocol after merging ACT-612 participant relationships with open-by-default augmentation scope; it adds no claim of realized participant relationships or native backend scope enforcement.", + "This capture replays issue #1299 partial listener descriptions on the integrated source state; endpoint completeness and backend admission remain outside this protocol's claims.", + "This capture also binds authoring-adapter semantic conformance to the integrated source; adapter transport behavior remains outside this protocol's claims.", + "Reviewed OCI mirror and pre-seed admission is covered by its own regression suites and the development artifact policy gate, not a new claim in this preregistered matrix.", + "This capture binds issue #1297 service-manager identity, native-name, and explicitly selected systemd-state contract changes to the integrated source. It exercises no live service manager and adds no backend-execution claim.", + "This capture replays the retained specification-coverage protocol after API-404 startup reconciliation added an operational recovery-observation contract. It does not evaluate crash recovery, classify provider effects, or broaden EXP-715 experiment-observation claims.", + "This capture binds API-404 single-owner store admission and immutable target/run scope to the integrated source. The retained offline protocol does not exercise process leases, SQLite lifecycle ordering, or crash recovery.", + "This capture binds issue #1015 deterministic mixed and staged trial admission to the integrated source. The retained offline language corpus does not execute mixed runtimes, phase transitions, backend handoff, or scheduler-driven realization.", + "This replay binds issue #1186 offline control-plane maintenance, readiness, and bounded audit code to the integrated source. The retained language corpus does not execute store recovery, HTTP health behavior, or audit redaction.", + "Issue #1187 control-plane crash/profile conformance and HTTP security changes are covered by their dedicated regression suite, not promoted to new claims by this retained corpus.", + "Issue #1189 control-plane profile declarations are covered by their dedicated runtime suite, not promoted to new claims by the retained language corpus.", + "Issue #1016 mixed-runtime coordination is covered by its dedicated runtime suite. The retained language corpus does not execute mixed providers or establish backend-native realization, multi-controller coordination, IFC, or equivalence.", + "Issue #610's reconciliation demonstration harness is covered by its dedicated processor and CLI suite, not promoted to new claims by the retained language corpus.", + "Participant identity, organization ownership, and participant assignment are separated by issue #1338. This retained offline corpus does not establish participant autonomy, execution authority, live backend fidelity, or causal attribution." + ], + "protocol_revision": "1.0.0", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "raes_revision": "6d55d336eb9f39eb7718834e2645888f965adc8d", + "snapshot_id": "raes-standardized-specification-coverage-issue-1401-v66", + "snapshot_revision": "66.0.0", + "source_state": { + "base_revision": "6d55d336eb9f39eb7718834e2645888f965adc8d", + "checkout_state": "modified", + "implementation_digest": "8c1153320260a66058dcc38a2dcf6efd417f1c133b6d052df022ea85a6ae027d", + "profile": "python-reference-source/v2" + } +} diff --git a/docs/research/specification-coverage/index.md b/docs/research/specification-coverage/index.md index c59479b2e..0ae53d6ae 100644 --- a/docs/research/specification-coverage/index.md +++ b/docs/research/specification-coverage/index.md @@ -292,7 +292,7 @@ the port scenario. Historical captures and archived example bytes are retained. The matrix classifications and untested concepts are unchanged; no execution authority, successful action, or live backend fidelity is inferred. -Current validation requires release 65.0.0 and rejects duplicate or unsupported +Current validation requires release 66.0.0 and rejects duplicate or unsupported future revisions. It executes current artifacts, requires exact source and package hashes, and checks all passing stage pointers. `source_state` discloses the base Git commit, modified checkout state, and exact implementation digest; @@ -507,3 +507,10 @@ upgrade to 2.15.1 and the urllib3 upgrade to 2.8.0 in [`execution-snapshot-v65.json`](execution-snapshot-v65.json) and [`analysis-v65.json`](analysis-v65.json). Classifications and claim limits remain unchanged. + +Release 66.0.0 replays the retained matrix after issue #1401 began rejecting +required evidence whose declared media type the output registry cannot prove. +Classifications and claim limits remain unchanged; media-type coherence is +verified by its dedicated suite in +[`execution-snapshot-v66.json`](execution-snapshot-v66.json) and +[`analysis-v66.json`](analysis-v66.json). diff --git a/implementations/python/tests/test_formal_semantic_validation.py b/implementations/python/tests/test_formal_semantic_validation.py index 8e95d783f..925e8dffd 100644 --- a/implementations/python/tests/test_formal_semantic_validation.py +++ b/implementations/python/tests/test_formal_semantic_validation.py @@ -145,6 +145,7 @@ def test_atomic_release_index_validates_every_historical_bundle() -> None: "64.0.0", "65.0.0", "66.0.0", + "67.0.0", ] assert all(validate_release_bundle(REPO_ROOT, release) == [] for release in releases) @@ -153,10 +154,10 @@ def test_atomic_release_index_validates_every_historical_bundle() -> None: def test_current_retest_bundle_is_coherent_and_clean() -> None: release, protocol, corpus, snapshot, analysis = copy_bundle(load_retest_bundle, REPO_ROOT) - assert release.manifest["revision"] == "66.0.0" + assert release.manifest["revision"] == "67.0.0" assert protocol["revision"] == "2.0.0" assert corpus["revision"] == "4.0.0" - assert snapshot["baseline"]["release_revision"] == "65.0.0" + assert snapshot["baseline"]["release_revision"] == "66.0.0" assert snapshot["deviations"] == [] assert validate_retest_bundle(REPO_ROOT, release, protocol, corpus, snapshot, analysis) == [] diff --git a/implementations/python/tests/test_issue_989_versioned_evidence.py b/implementations/python/tests/test_issue_989_versioned_evidence.py index 1ac036a74..a2e4faa46 100644 --- a/implementations/python/tests/test_issue_989_versioned_evidence.py +++ b/implementations/python/tests/test_issue_989_versioned_evidence.py @@ -241,18 +241,18 @@ def _stub_release(revision: str, *, protocol_revision: str = "2.0.0"): [ pytest.param([], "selects no v2 retest release", id="no-release"), pytest.param( - [_stub_release("64.0.0"), _stub_release("65.0.0")], - "must be the explicit 66.0.0 retest", + [_stub_release("65.0.0"), _stub_release("66.0.0")], + "must be the explicit 67.0.0 retest", id="stale-current", ), pytest.param( - [_stub_release("65.0.0"), _stub_release("67.0.0")], - "must be the explicit 66.0.0 retest", + [_stub_release("66.0.0"), _stub_release("68.0.0")], + "must be the explicit 67.0.0 retest", id="unsupported-future", ), pytest.param( - [_stub_release("66.0.0", protocol_revision="1.0.0")], - "must be the explicit 66.0.0 retest", + [_stub_release("67.0.0", protocol_revision="1.0.0")], + "must be the explicit 67.0.0 retest", id="wrong-protocol", ), ], @@ -269,8 +269,8 @@ def test_current_formal_release_selection_is_explicit(monkeypatch, releases, mes def test_current_formal_release_selection_returns_the_explicit_retest(monkeypatch): from tools.formal_semantic_validation import _loading - current = _stub_release("66.0.0") - monkeypatch.setattr(_loading, "load_release_bundles", lambda _root: [_stub_release("65.0.0"), current]) + current = _stub_release("67.0.0") + monkeypatch.setattr(_loading, "load_release_bundles", lambda _root: [_stub_release("66.0.0"), current]) assert _loading.load_retest_bundle(ROOT)[0] is current @@ -282,7 +282,7 @@ def test_latest_current_release_is_versioned_and_strict(monkeypatch): from tools.formal_semantic_validation._releases import validate_retest_bundle release, protocol, corpus, snapshot, analysis = copy_bundle(load_retest_bundle, ROOT) - assert release.manifest["revision"] == "66.0.0" + assert release.manifest["revision"] == "67.0.0" original = _retest.replay_case def changed_result(root, case): @@ -335,7 +335,7 @@ def test_specification_current_capture_does_not_accept_old_artifact_digest(artif from tools.check_specification_coverage import load_bundle, validate_bundle manifest, protocol, snapshot, analysis = copy_bundle(load_bundle, ROOT) - assert manifest["revision"] == "65.0.0" + assert manifest["revision"] == "66.0.0" snapshot = deepcopy(snapshot) artifact = next(a for a in snapshot["artifacts"] if a["artifact_id"] == artifact_id) artifact["sha256"] = old_digest @@ -570,6 +570,7 @@ def test_no_capture_can_be_silently_dropped(monkeypatch, family, removed): "64.0.0", "65.0.0", "66.0.0", + "67.0.0", ] if family == "formal" else [ @@ -639,6 +640,7 @@ def test_no_capture_can_be_silently_dropped(monkeypatch, family, removed): "63.0.0", "64.0.0", "65.0.0", + "66.0.0", ] ) revisions.pop(-1 if removed == "current" else 0) diff --git a/implementations/python/tests/test_specification_coverage.py b/implementations/python/tests/test_specification_coverage.py index 1241865c2..4867c713e 100644 --- a/implementations/python/tests/test_specification_coverage.py +++ b/implementations/python/tests/test_specification_coverage.py @@ -53,7 +53,7 @@ def test_immutable_bundle_index_preserves_concurrent_captures() -> None: bundles = copy_bundle(load_bundles, REPO_ROOT) assert {manifest["revision"] for manifest, *_rest in bundles} >= {"1.0.0", "1.1.0", "19.0.0"} manifest, *_rest = copy_bundle(load_bundle, REPO_ROOT) - assert manifest["revision"] == "65.0.0" + assert manifest["revision"] == "66.0.0" def test_historical_failures_name_the_revision_specific_documents() -> None: diff --git a/tools/check_specification_coverage.py b/tools/check_specification_coverage.py index e88129ee8..99a5e51cd 100644 --- a/tools/check_specification_coverage.py +++ b/tools/check_specification_coverage.py @@ -170,12 +170,13 @@ def _load_bundle_index(repo_root: Path) -> list[tuple[str, dict[str, object]]]: "63.0.0", "64.0.0", "65.0.0", + "66.0.0", } if ( - dict(records)[current_path].get("revision") != "65.0.0" + dict(records)[current_path].get("revision") != "66.0.0" or {record.get("revision") for _, record in records} != supported_revisions ): - raise ValueError("coverage evidence requires the explicit current 65.0.0 release and supported history") + raise ValueError("coverage evidence requires the explicit current 66.0.0 release and supported history") return records diff --git a/tools/formal_semantic_validation/_baseline.py b/tools/formal_semantic_validation/_baseline.py index dad5e5b89..30507976b 100644 --- a/tools/formal_semantic_validation/_baseline.py +++ b/tools/formal_semantic_validation/_baseline.py @@ -202,6 +202,7 @@ def _selected_baseline_manifest( "64.0.0", "65.0.0", "66.0.0", + "67.0.0", }: expected_corpus_path = "docs/research/formal-semantic-validation/corpus/manifest-v4.json" elif baseline_revision in _V3_CORPUS_REVISIONS: diff --git a/tools/formal_semantic_validation/_loading.py b/tools/formal_semantic_validation/_loading.py index 70b94ee98..28c84abca 100644 --- a/tools/formal_semantic_validation/_loading.py +++ b/tools/formal_semantic_validation/_loading.py @@ -75,6 +75,6 @@ def load_retest_bundle( if not releases: raise ValueError("the formal semantic-validation index selects no v2 retest release") release = max(releases, key=lambda item: revision_key(item.manifest.get("revision"))) - if release.manifest.get("revision") != "66.0.0" or release.protocol.get("revision") != "2.0.0": - raise ValueError("the current formal evidence release must be the explicit 66.0.0 retest") + if release.manifest.get("revision") != "67.0.0" or release.protocol.get("revision") != "2.0.0": + raise ValueError("the current formal evidence release must be the explicit 67.0.0 retest") return release, release.protocol, release.corpus, release.snapshot, release.analysis diff --git a/tools/formal_semantic_validation/_release_revisions.py b/tools/formal_semantic_validation/_release_revisions.py index 69394e790..b4fb7c5bb 100644 --- a/tools/formal_semantic_validation/_release_revisions.py +++ b/tools/formal_semantic_validation/_release_revisions.py @@ -67,9 +67,10 @@ "63.0.0", "64.0.0", "65.0.0", + "66.0.0", } -_SUPPORTED_RETEST_REVISIONS = _HISTORICAL_RETEST_REVISIONS | {"66.0.0"} +_SUPPORTED_RETEST_REVISIONS = _HISTORICAL_RETEST_REVISIONS | {"67.0.0"} _SOURCE_BOUND_RETEST_REVISIONS = _SUPPORTED_RETEST_REVISIONS - {"3.0.0"} _RETEST_BASELINE_REVISIONS = { @@ -138,4 +139,5 @@ "64.0.0": "63.0.0", "65.0.0": "64.0.0", "66.0.0": "65.0.0", + "67.0.0": "66.0.0", } diff --git a/tools/formal_semantic_validation/_releases.py b/tools/formal_semantic_validation/_releases.py index a08be6613..2d130c6f6 100644 --- a/tools/formal_semantic_validation/_releases.py +++ b/tools/formal_semantic_validation/_releases.py @@ -160,7 +160,7 @@ def validate_release_bundle(repo_root: Path, release: EvidenceRelease) -> list[P release.corpus, release.snapshot, release.analysis, - replay_current=manifest.get("revision") == "66.0.0", + replay_current=manifest.get("revision") == "67.0.0", ) ) else: @@ -284,6 +284,7 @@ def _expected_corpus_revision(release_revision: object) -> str: "64.0.0", "65.0.0", "66.0.0", + "67.0.0", }: expected_corpus_revision = "4.0.0" return expected_corpus_revision @@ -311,7 +312,7 @@ def validate_retest_bundle( return [ _failure( "formal-validation-current-replay-required", - "only releases 3.0.0 through 65.0.0 can use integrated historical validation", + "only releases 3.0.0 through 66.0.0 can use integrated historical validation", snapshot_path, ) ] diff --git a/tools/formal_semantic_validation/_retest.py b/tools/formal_semantic_validation/_retest.py index 2e4ae9078..77812ad00 100644 --- a/tools/formal_semantic_validation/_retest.py +++ b/tools/formal_semantic_validation/_retest.py @@ -37,7 +37,7 @@ ) from tools.policy.common import PolicyFailure -_SOURCE_STATE_REVISIONS = frozenset(f"{revision}.0.0" for revision in range(4, 67)) +_SOURCE_STATE_REVISIONS = frozenset(f"{revision}.0.0" for revision in range(4, 68)) @dataclasses.dataclass(frozen=True) From ffcec5a25128dc0917463e474254ec4b21c568a2 Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Thu, 1 Oct 2026 01:11:22 +0200 Subject: [PATCH 3/3] Fix SonarCloud findings: isolate the raising call in exception tests --- .../tests/test_dsl_124_authored_evidence_requirements.py | 3 ++- .../python/tests/test_issue_1401_media_type_coherence.py | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/implementations/python/tests/test_dsl_124_authored_evidence_requirements.py b/implementations/python/tests/test_dsl_124_authored_evidence_requirements.py index 99ea6ea3e..3be1bf456 100644 --- a/implementations/python/tests/test_dsl_124_authored_evidence_requirements.py +++ b/implementations/python/tests/test_dsl_124_authored_evidence_requirements.py @@ -79,8 +79,9 @@ def test_dsl_124_accepts_authored_evidence_requirement_independent_of_objectives def test_dsl_124_rejects_unprovable_pcap_declaration() -> None: + payload = _scenario_yaml().replace("application/json", "application/vnd.tcpdump.pcap") with pytest.raises(SDLParseError, match="unsupported required evidence media type"): - parse_sdl(_scenario_yaml().replace("application/json", "application/vnd.tcpdump.pcap")) + parse_sdl(payload) def test_dsl_124_evidence_requirements_are_not_objective_targets() -> None: diff --git a/implementations/python/tests/test_issue_1401_media_type_coherence.py b/implementations/python/tests/test_issue_1401_media_type_coherence.py index f155f1f89..e8b3fafd9 100644 --- a/implementations/python/tests/test_issue_1401_media_type_coherence.py +++ b/implementations/python/tests/test_issue_1401_media_type_coherence.py @@ -23,8 +23,9 @@ def test_sdl_rejects_unprovable_required_media_type(media_type: str) -> None: scenario = _capture_scenario() payload = scenario.evidence_requirements["attacker-action-log"].model_dump(mode="json") payload["media_types"] = ["application/json", media_type] + requirement_model = type(scenario.evidence_requirements["attacker-action-log"]) with pytest.raises(ValidationError, match="unsupported.*media type"): - type(scenario.evidence_requirements["attacker-action-log"]).model_validate(payload) + requirement_model.model_validate(payload) @pytest.mark.parametrize("media_type", ["text/plain", "application/x-ndjson", "application/vnd.tcpdump.pcap"]) @@ -74,13 +75,15 @@ def test_unknown_sdl_output_contract_is_rejected_at_authoring() -> None: scenario = _capture_scenario() payload = scenario.evidence_requirements["attacker-action-log"].model_dump(mode="json") payload["output_contract"] = "unknown-output-contract-v1" + requirement_model = type(scenario.evidence_requirements["attacker-action-log"]) with pytest.raises(ValidationError, match="output_contract"): - type(scenario.evidence_requirements["attacker-action-log"]).model_validate(payload) + requirement_model.model_validate(payload) def test_sdl_object_contract_rejects_json_lines_at_authoring() -> None: scenario = _capture_scenario(output_contract="experiment-evidence-record-v1") payload = scenario.evidence_requirements["attacker-action-log"].model_dump(mode="json") payload["media_types"] = ["application/jsonl"] + requirement_model = type(scenario.evidence_requirements["attacker-action-log"]) with pytest.raises(ValidationError, match="media.*output_contract"): - type(scenario.evidence_requirements["attacker-action-log"]).model_validate(payload) + requirement_model.model_validate(payload)