diff --git a/contracts/fixtures/control-plane/backend-operation-capabilities-v1/valid/mixed-bridge.json b/contracts/fixtures/control-plane/backend-operation-capabilities-v1/valid/mixed-bridge.json new file mode 100644 index 000000000..c6c2b507e --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-capabilities-v1/valid/mixed-bridge.json @@ -0,0 +1,13 @@ +{ + "schema_version": "backend-operation-capabilities/v1", + "backend_id": "route:portable", + "revision": "sha256:7777777777777777777777777777777777777777777777777777777777777777", + "supported_operation_kinds": [ + "participant-crossing" + ], + "guarantees": [ + "effect-observation", + "cessation-evidence", + "partial-effects" + ] +} diff --git a/contracts/fixtures/control-plane/backend-operation-capabilities-v1/valid/mixed-transfer.json b/contracts/fixtures/control-plane/backend-operation-capabilities-v1/valid/mixed-transfer.json new file mode 100644 index 000000000..4f0dbba3c --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-capabilities-v1/valid/mixed-transfer.json @@ -0,0 +1,12 @@ +{ + "schema_version": "backend-operation-capabilities/v1", + "backend_id": "transfer:native-ownership", + "revision": "sha256:8888888888888888888888888888888888888888888888888888888888888888", + "supported_operation_kinds": [ + "composition-phase" + ], + "guarantees": [ + "effect-observation", + "cessation-evidence" + ] +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge-partial.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge-partial.json new file mode 100644 index 000000000..02e53356b --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge-partial.json @@ -0,0 +1,46 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation:mixed-edge-partial", + "invocation_id": "invocation:mixed-edge-partial", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "mixed-backend-execution-binding-v1", + "artifact_id": "binding:edge.sim-to-emu", + "digest": "sha256:6e600b603b2c5f83183836920caea4ba2b01b69b9caa94c0dbeac0c5c21a658e" + }, + "requirement_refs": [], + "required_guarantees": [ + "effect-observation", + "cessation-evidence" + ], + "budget": { + "origin_id": "budget:mixed-edge-partial", + "started_at": "2026-10-09T00:00:00Z", + "limit_ms": 30000, + "remaining_ms": 30000 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge-refused.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge-refused.json new file mode 100644 index 000000000..3945ca695 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge-refused.json @@ -0,0 +1,46 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation:mixed-edge-refused", + "invocation_id": "invocation:mixed-edge-refused", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "mixed-backend-execution-binding-v1", + "artifact_id": "binding:edge.sim-to-emu", + "digest": "sha256:6e600b603b2c5f83183836920caea4ba2b01b69b9caa94c0dbeac0c5c21a658e" + }, + "requirement_refs": [], + "required_guarantees": [ + "effect-observation", + "cessation-evidence" + ], + "budget": { + "origin_id": "budget:mixed-edge-refused", + "started_at": "2026-10-09T00:00:00Z", + "limit_ms": 30000, + "remaining_ms": 30000 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge-time-refused.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge-time-refused.json new file mode 100644 index 000000000..286ae247f --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge-time-refused.json @@ -0,0 +1,46 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation:mixed-edge-time-refused", + "invocation_id": "invocation:mixed-edge-time-refused", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "mixed-backend-execution-binding-v1", + "artifact_id": "binding:edge.sim-to-emu", + "digest": "sha256:6e600b603b2c5f83183836920caea4ba2b01b69b9caa94c0dbeac0c5c21a658e" + }, + "requirement_refs": [], + "required_guarantees": [ + "effect-observation", + "cessation-evidence" + ], + "budget": { + "origin_id": "budget:mixed-edge-time-refused", + "started_at": "2026-10-09T00:00:00Z", + "limit_ms": 30000, + "remaining_ms": 30000 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge.json new file mode 100644 index 000000000..25736525c --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-edge.json @@ -0,0 +1,46 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "mixed-backend-execution-binding-v1", + "artifact_id": "binding:edge.sim-to-emu", + "digest": "sha256:6e600b603b2c5f83183836920caea4ba2b01b69b9caa94c0dbeac0c5c21a658e" + }, + "requirement_refs": [], + "required_guarantees": [ + "effect-observation", + "cessation-evidence" + ], + "budget": { + "origin_id": "budget:mixed-edge", + "started_at": "2026-10-09T00:00:00Z", + "limit_ms": 30000, + "remaining_ms": 30000 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-handoff-stale.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-handoff-stale.json new file mode 100644 index 000000000..5d50ec427 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-handoff-stale.json @@ -0,0 +1,46 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation:mixed-handoff-stale", + "invocation_id": "invocation:mixed-handoff-stale", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "mixed-backend-execution-binding-v1", + "artifact_id": "binding:transition.sim-to-emu", + "digest": "sha256:9850e3cca45fb94fd7889d1f247991639daf2d50a49b2f38a897ac3b063f38e9" + }, + "requirement_refs": [], + "required_guarantees": [ + "effect-observation", + "cessation-evidence" + ], + "budget": { + "origin_id": "budget:mixed-handoff-stale", + "started_at": "2026-10-09T00:00:00Z", + "limit_ms": 30000, + "remaining_ms": 30000 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-handoff.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-handoff.json new file mode 100644 index 000000000..00bcf9fc5 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/mixed-handoff.json @@ -0,0 +1,46 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation:mixed-handoff", + "invocation_id": "invocation:mixed-handoff", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "mixed-backend-execution-binding-v1", + "artifact_id": "binding:transition.sim-to-emu", + "digest": "sha256:9850e3cca45fb94fd7889d1f247991639daf2d50a49b2f38a897ac3b063f38e9" + }, + "requirement_refs": [], + "required_guarantees": [ + "effect-observation", + "cessation-evidence" + ], + "budget": { + "origin_id": "budget:mixed-handoff", + "started_at": "2026-10-09T00:00:00Z", + "limit_ms": 30000, + "remaining_ms": 30000 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-01.json new file mode 100644 index 000000000..095812d48 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-01.json @@ -0,0 +1,38 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 1, + "message": { + "kind": "admission", + "disposition": "willing", + "capability_digest": "sha256:b0b3ae8edfe9d4504cf3484a89f37a8ab1674e0240474e23232882728eb06351", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-02.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-02.json new file mode 100644 index 000000000..6cfee2589 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-02.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 2, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-03.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-03.json new file mode 100644 index 000000000..d9368c77f --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-03.json @@ -0,0 +1,63 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 3, + "message": { + "kind": "outcome", + "proposed_state": "succeeded", + "effects": { + "effect": "complete", + "cessation_established": true, + "evidence_refs": [ + { + "contract_id": "mixed-backend-stage-report-v1", + "artifact_id": "stage:mixed-edge:execution", + "digest": "sha256:e6c202d828c96370bdf0ae8440950feabd8b980261dda8625f7b20c9047dea18" + }, + { + "contract_id": "mixed-backend-stage-report-v1", + "artifact_id": "stage:mixed-edge:delivery", + "digest": "sha256:0bc7ed7268f4cae3dde119d5e12e1e5ebc01e0138719eb66cfd97f09945b16a2" + } + ], + "residual_scope": [], + "residual_state": null, + "external_fence": null + }, + "satisfaction": "satisfied", + "release_gates_satisfied": true, + "cancellation_established": false, + "result": { + "contract_id": "runtime-snapshot-v1", + "artifact_id": "snapshot:mixed-edge", + "digest": "sha256:9999999999999999999999999999999999999999999999999999999999999999" + } + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-partial-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-partial-01.json new file mode 100644 index 000000000..4c6744bfe --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-partial-01.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-edge-partial", + "invocation_id": "invocation:mixed-edge-partial", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:0bafdc8cb663d1478e5bd8e66da22a18a26c1f040f47ea95a12fba477948967a", + "sequence": 1, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-partial-02.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-partial-02.json new file mode 100644 index 000000000..8da14bb90 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-partial-02.json @@ -0,0 +1,60 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-edge-partial", + "invocation_id": "invocation:mixed-edge-partial", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:0bafdc8cb663d1478e5bd8e66da22a18a26c1f040f47ea95a12fba477948967a", + "sequence": 2, + "message": { + "kind": "outcome", + "proposed_state": "indeterminate", + "effects": { + "effect": "partial", + "cessation_established": false, + "evidence_refs": [ + { + "contract_id": "mixed-backend-stage-report-v1", + "artifact_id": "stage:mixed-edge-partial:execution", + "digest": "sha256:4af95cdec4b07a269322b891b4992f7ab8265d2640268f1c26a1a112f38d057d" + } + ], + "residual_scope": [ + "crossings.alice.status" + ], + "residual_state": { + "contract_id": "runtime-snapshot-v1", + "artifact_id": "snapshot:mixed-edge-partial", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "external_fence": null + }, + "satisfaction": "unknown", + "release_gates_satisfied": false, + "cancellation_established": false, + "result": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-refused-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-refused-01.json new file mode 100644 index 000000000..5a4b8b8b4 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-refused-01.json @@ -0,0 +1,38 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-edge-refused", + "invocation_id": "invocation:mixed-edge-refused", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:351f4d6eeb299292b4f4aa0f5fa6de4ef695123e00fdce299a9ff9a7abe3ee12", + "sequence": 1, + "message": { + "kind": "admission", + "disposition": "refused", + "capability_digest": "sha256:b0b3ae8edfe9d4504cf3484a89f37a8ab1674e0240474e23232882728eb06351", + "reason": "context-refused" + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-time-refused-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-time-refused-01.json new file mode 100644 index 000000000..a8927f367 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-time-refused-01.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-edge-time-refused", + "invocation_id": "invocation:mixed-edge-time-refused", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:4c682409ce65cf3b1581458b9f18e43a84cadebc4b82753f9c986a70ff10a476", + "sequence": 1, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-time-refused-02.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-time-refused-02.json new file mode 100644 index 000000000..6e37eee7c --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-edge-time-refused-02.json @@ -0,0 +1,54 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-edge-time-refused", + "invocation_id": "invocation:mixed-edge-time-refused", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:4c682409ce65cf3b1581458b9f18e43a84cadebc4b82753f9c986a70ff10a476", + "sequence": 2, + "message": { + "kind": "outcome", + "proposed_state": "failed", + "effects": { + "effect": "absent", + "cessation_established": true, + "evidence_refs": [ + { + "contract_id": "mixed-backend-stage-report-v1", + "artifact_id": "stage:mixed-edge-time-refused:time-grant", + "digest": "sha256:dc2192edba5d414230956ff0882db05354c43e97e2b8f517ee5bd8e29ef22c01" + } + ], + "residual_scope": [], + "residual_state": null, + "external_fence": null + }, + "satisfaction": "unsatisfied", + "release_gates_satisfied": false, + "cancellation_established": false, + "result": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-01.json new file mode 100644 index 000000000..42dd01c36 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-01.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-handoff", + "invocation_id": "invocation:mixed-handoff", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:e688489a9b66f704822e227e9a0c25b8a4b6f6e4f072011f02ea3574e309fb3b", + "sequence": 1, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-02.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-02.json new file mode 100644 index 000000000..1e5295ac7 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-02.json @@ -0,0 +1,63 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-handoff", + "invocation_id": "invocation:mixed-handoff", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:e688489a9b66f704822e227e9a0c25b8a4b6f6e4f072011f02ea3574e309fb3b", + "sequence": 2, + "message": { + "kind": "outcome", + "proposed_state": "succeeded", + "effects": { + "effect": "complete", + "cessation_established": true, + "evidence_refs": [ + { + "contract_id": "mixed-backend-stage-report-v1", + "artifact_id": "stage:mixed-handoff:handoff", + "digest": "sha256:bf3127319ef9703bbacc2fbec20e4fadfd83a92494663228e496ebfb7685cbf1" + }, + { + "contract_id": "mixed-backend-stage-report-v1", + "artifact_id": "stage:mixed-handoff:owner", + "digest": "sha256:08f3aafed02a41b2d45bd14d800737f849a5d800ba673fcb7e6f3e888594bc30" + } + ], + "residual_scope": [], + "residual_state": null, + "external_fence": null + }, + "satisfaction": "satisfied", + "release_gates_satisfied": true, + "cancellation_established": false, + "result": { + "contract_id": "runtime-snapshot-v1", + "artifact_id": "snapshot:mixed-handoff", + "digest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + } + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-stale-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-stale-01.json new file mode 100644 index 000000000..727db48e5 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-stale-01.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-handoff-stale", + "invocation_id": "invocation:mixed-handoff-stale", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:07730d4dac0ef09031fce515a014fd45252ee137a1c82c0718e17d667e1fca32", + "sequence": 1, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-stale-02.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-stale-02.json new file mode 100644 index 000000000..b606a9697 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/mixed-handoff-stale-02.json @@ -0,0 +1,59 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation:mixed-handoff-stale", + "invocation_id": "invocation:mixed-handoff-stale", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:07730d4dac0ef09031fce515a014fd45252ee137a1c82c0718e17d667e1fca32", + "sequence": 2, + "message": { + "kind": "outcome", + "proposed_state": "failed", + "effects": { + "effect": "absent", + "cessation_established": true, + "evidence_refs": [ + { + "contract_id": "mixed-backend-stage-report-v1", + "artifact_id": "stage:mixed-handoff-stale:handoff", + "digest": "sha256:54ac308365de25f0b161f316fa56e224b1de0bfa1c833c125a5ab549b98da24f" + }, + { + "contract_id": "mixed-backend-stage-report-v1", + "artifact_id": "stage:mixed-handoff-stale:owner", + "digest": "sha256:3c072b5e427cb39957c868f7da6efb1d0971820b3bf39a85c2c1cbd2b5fed858" + } + ], + "residual_scope": [], + "residual_state": null, + "external_fence": null + }, + "satisfaction": "unsatisfied", + "release_gates_satisfied": false, + "cancellation_established": false, + "result": null + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/context-invalid/foreign-bridge.json b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/context-invalid/foreign-bridge.json new file mode 100644 index 000000000..4ba017d4f --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/context-invalid/foreign-bridge.json @@ -0,0 +1,58 @@ +{ + "schema_version": "mixed-backend-execution-binding/v1", + "binding_id": "binding:edge.sim-to-emu", + "profile_id": "profile:mixed", + "profile_revision": "mixed-cross-backend-participant-control-v1@rev1", + "profile_digest": "sha256:24758820769f964644a9331c1600aa8830ad85c3dc0b271d7760cb430520d821", + "subject": { + "kind": "edge", + "edge_id": "edge.sim-to-emu", + "operation_kind": "participant-crossing", + "owner_component_id": "emu", + "owner_allocation_id": "allocation.action", + "participant_address": "participant.behavior.red-agent", + "audience_scope_ref": "audience:red-operator", + "source_action_address": "participant.action-contract.contain-host", + "destination_action_address": "participant.action-contract.contain-host", + "subject_transformation": "compiled-identity", + "bridge": { + "service_ref": "route:unadmitted", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "time": { + "time_model_ref": "time-model:composition", + "time_model_digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "source_clock_address": "time.clocks.sim", + "destination_clock_address": "time.clocks.emu", + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "partial_order", + "required_comparison": "ordered", + "coordinator": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "temporal_coupling": "bounded-asynchronous" + }, + "mapping_loss": { + "kind": "semantics_approximated", + "basis_ref": "mapping:basis", + "affected_ref": "observation:status", + "limitation_ref": "limitation:mapping" + }, + "delivery_reader": { + "service_ref": "reader:destination-receipt", + "version": "1", + "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + "observation_reader": { + "service_ref": "reader:participant-audience", + "version": "1", + "digest": "sha256:4444444444444444444444444444444444444444444444444444444444444444" + }, + "required_evidence_refs": [ + "evidence:edge-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/bridge-as-reader.json b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/bridge-as-reader.json new file mode 100644 index 000000000..65b9119ce --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/bridge-as-reader.json @@ -0,0 +1,58 @@ +{ + "schema_version": "mixed-backend-execution-binding/v1", + "binding_id": "binding:edge.sim-to-emu", + "profile_id": "profile:mixed", + "profile_revision": "mixed-cross-backend-participant-control-v1@rev1", + "profile_digest": "sha256:24758820769f964644a9331c1600aa8830ad85c3dc0b271d7760cb430520d821", + "subject": { + "kind": "edge", + "edge_id": "edge.sim-to-emu", + "operation_kind": "participant-crossing", + "owner_component_id": "emu", + "owner_allocation_id": "allocation.action", + "participant_address": "participant.behavior.red-agent", + "audience_scope_ref": "audience:red-operator", + "source_action_address": "participant.action-contract.contain-host", + "destination_action_address": "participant.action-contract.contain-host", + "subject_transformation": "compiled-identity", + "bridge": { + "service_ref": "route:portable", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "time": { + "time_model_ref": "time-model:composition", + "time_model_digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "source_clock_address": "time.clocks.sim", + "destination_clock_address": "time.clocks.emu", + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "partial_order", + "required_comparison": "ordered", + "coordinator": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "temporal_coupling": "bounded-asynchronous" + }, + "mapping_loss": { + "kind": "semantics_approximated", + "basis_ref": "mapping:basis", + "affected_ref": "observation:status", + "limitation_ref": "limitation:mapping" + }, + "delivery_reader": { + "service_ref": "route:portable", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "observation_reader": { + "service_ref": "route:portable", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "required_evidence_refs": [ + "evidence:edge-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/changed-subject.json b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/changed-subject.json new file mode 100644 index 000000000..085788a23 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/changed-subject.json @@ -0,0 +1,58 @@ +{ + "schema_version": "mixed-backend-execution-binding/v1", + "binding_id": "binding:edge.sim-to-emu", + "profile_id": "profile:mixed", + "profile_revision": "mixed-cross-backend-participant-control-v1@rev1", + "profile_digest": "sha256:24758820769f964644a9331c1600aa8830ad85c3dc0b271d7760cb430520d821", + "subject": { + "kind": "edge", + "edge_id": "edge.sim-to-emu", + "operation_kind": "participant-crossing", + "owner_component_id": "emu", + "owner_allocation_id": "allocation.action", + "participant_address": "participant.behavior.red-agent", + "audience_scope_ref": "audience:red-operator", + "source_action_address": "participant.action-contract.contain-host", + "destination_action_address": "participant.action-contract.isolate-host", + "subject_transformation": "compiled-identity", + "bridge": { + "service_ref": "route:portable", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "time": { + "time_model_ref": "time-model:composition", + "time_model_digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "source_clock_address": "time.clocks.sim", + "destination_clock_address": "time.clocks.emu", + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "partial_order", + "required_comparison": "ordered", + "coordinator": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "temporal_coupling": "bounded-asynchronous" + }, + "mapping_loss": { + "kind": "semantics_approximated", + "basis_ref": "mapping:basis", + "affected_ref": "observation:status", + "limitation_ref": "limitation:mapping" + }, + "delivery_reader": { + "service_ref": "reader:destination-receipt", + "version": "1", + "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + "observation_reader": { + "service_ref": "reader:participant-audience", + "version": "1", + "digest": "sha256:4444444444444444444444444444444444444444444444444444444444444444" + }, + "required_evidence_refs": [ + "evidence:edge-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/open-metadata.json b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/open-metadata.json new file mode 100644 index 000000000..0fd5b9e5d --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/open-metadata.json @@ -0,0 +1,61 @@ +{ + "schema_version": "mixed-backend-execution-binding/v1", + "binding_id": "binding:edge.sim-to-emu", + "profile_id": "profile:mixed", + "profile_revision": "mixed-cross-backend-participant-control-v1@rev1", + "profile_digest": "sha256:24758820769f964644a9331c1600aa8830ad85c3dc0b271d7760cb430520d821", + "subject": { + "kind": "edge", + "edge_id": "edge.sim-to-emu", + "operation_kind": "participant-crossing", + "owner_component_id": "emu", + "owner_allocation_id": "allocation.action", + "participant_address": "participant.behavior.red-agent", + "audience_scope_ref": "audience:red-operator", + "source_action_address": "participant.action-contract.contain-host", + "destination_action_address": "participant.action-contract.contain-host", + "subject_transformation": "compiled-identity", + "bridge": { + "service_ref": "route:portable", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "time": { + "time_model_ref": "time-model:composition", + "time_model_digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "source_clock_address": "time.clocks.sim", + "destination_clock_address": "time.clocks.emu", + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "partial_order", + "required_comparison": "ordered", + "coordinator": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "temporal_coupling": "bounded-asynchronous" + }, + "mapping_loss": { + "kind": "semantics_approximated", + "basis_ref": "mapping:basis", + "affected_ref": "observation:status", + "limitation_ref": "limitation:mapping" + }, + "delivery_reader": { + "service_ref": "reader:destination-receipt", + "version": "1", + "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + "observation_reader": { + "service_ref": "reader:participant-audience", + "version": "1", + "digest": "sha256:4444444444444444444444444444444444444444444444444444444444444444" + }, + "required_evidence_refs": [ + "evidence:edge-realization" + ] + }, + "metadata": { + "backend": "emu" + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/transfer-as-owner-reader.json b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/transfer-as-owner-reader.json new file mode 100644 index 000000000..8f3445933 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/transfer-as-owner-reader.json @@ -0,0 +1,43 @@ +{ + "schema_version": "mixed-backend-execution-binding/v1", + "binding_id": "binding:transition.sim-to-emu", + "profile_id": "profile:mixed", + "profile_revision": "mixed-cross-backend-participant-control-v1@rev1", + "profile_digest": "sha256:83d1c9715656e4f1cbaf93083934fc941cccdae51718c36c75f6a77813f3371b", + "subject": { + "kind": "handoff", + "transition_id": "transition.sim-to-emu", + "operation_kind": "composition-phase", + "source_component_id": "sim", + "destination_component_id": "emu", + "source_owner_ref": "native-ownership:sim", + "destination_owner_ref": "native-ownership:emu", + "transfer": { + "service_ref": "transfer:native-ownership", + "version": "1", + "digest": "sha256:5555555555555555555555555555555555555555555555555555555555555555" + }, + "time": { + "time_model_ref": "time-model:composition", + "time_model_digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "source_clock_address": "time.clocks.sim", + "destination_clock_address": "time.clocks.emu", + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "control_plane_order", + "required_comparison": "ordered", + "coordinator": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + } + }, + "owner_reader": { + "service_ref": "transfer:native-ownership", + "version": "1", + "digest": "sha256:5555555555555555555555555555555555555555555555555555555555555555" + }, + "required_evidence_refs": [ + "evidence:phase-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/ungoverned-order.json b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/ungoverned-order.json new file mode 100644 index 000000000..a9e414dbf --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/invalid/ungoverned-order.json @@ -0,0 +1,58 @@ +{ + "schema_version": "mixed-backend-execution-binding/v1", + "binding_id": "binding:edge.sim-to-emu", + "profile_id": "profile:mixed", + "profile_revision": "mixed-cross-backend-participant-control-v1@rev1", + "profile_digest": "sha256:24758820769f964644a9331c1600aa8830ad85c3dc0b271d7760cb430520d821", + "subject": { + "kind": "edge", + "edge_id": "edge.sim-to-emu", + "operation_kind": "participant-crossing", + "owner_component_id": "emu", + "owner_allocation_id": "allocation.action", + "participant_address": "participant.behavior.red-agent", + "audience_scope_ref": "audience:red-operator", + "source_action_address": "participant.action-contract.contain-host", + "destination_action_address": "participant.action-contract.contain-host", + "subject_transformation": "compiled-identity", + "bridge": { + "service_ref": "route:portable", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "time": { + "time_model_ref": "time-model:composition", + "time_model_digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "source_clock_address": "time.clocks.sim", + "destination_clock_address": "time.clocks.emu", + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "wall_clock_only", + "required_comparison": "ordered", + "coordinator": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "temporal_coupling": "bounded-asynchronous" + }, + "mapping_loss": { + "kind": "semantics_approximated", + "basis_ref": "mapping:basis", + "affected_ref": "observation:status", + "limitation_ref": "limitation:mapping" + }, + "delivery_reader": { + "service_ref": "reader:destination-receipt", + "version": "1", + "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + "observation_reader": { + "service_ref": "reader:participant-audience", + "version": "1", + "digest": "sha256:4444444444444444444444444444444444444444444444444444444444444444" + }, + "required_evidence_refs": [ + "evidence:edge-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/valid/mixed-edge.json b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/valid/mixed-edge.json new file mode 100644 index 000000000..c837e40b9 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/valid/mixed-edge.json @@ -0,0 +1,58 @@ +{ + "schema_version": "mixed-backend-execution-binding/v1", + "binding_id": "binding:edge.sim-to-emu", + "profile_id": "profile:mixed", + "profile_revision": "mixed-cross-backend-participant-control-v1@rev1", + "profile_digest": "sha256:24758820769f964644a9331c1600aa8830ad85c3dc0b271d7760cb430520d821", + "subject": { + "kind": "edge", + "edge_id": "edge.sim-to-emu", + "operation_kind": "participant-crossing", + "owner_component_id": "emu", + "owner_allocation_id": "allocation.action", + "participant_address": "participant.behavior.red-agent", + "audience_scope_ref": "audience:red-operator", + "source_action_address": "participant.action-contract.contain-host", + "destination_action_address": "participant.action-contract.contain-host", + "subject_transformation": "compiled-identity", + "bridge": { + "service_ref": "route:portable", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "time": { + "time_model_ref": "time-model:composition", + "time_model_digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "source_clock_address": "time.clocks.sim", + "destination_clock_address": "time.clocks.emu", + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "partial_order", + "required_comparison": "ordered", + "coordinator": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "temporal_coupling": "bounded-asynchronous" + }, + "mapping_loss": { + "kind": "semantics_approximated", + "basis_ref": "mapping:basis", + "affected_ref": "observation:status", + "limitation_ref": "limitation:mapping" + }, + "delivery_reader": { + "service_ref": "reader:destination-receipt", + "version": "1", + "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + "observation_reader": { + "service_ref": "reader:participant-audience", + "version": "1", + "digest": "sha256:4444444444444444444444444444444444444444444444444444444444444444" + }, + "required_evidence_refs": [ + "evidence:edge-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/valid/mixed-handoff.json b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/valid/mixed-handoff.json new file mode 100644 index 000000000..22a3cf96b --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-execution-binding-v1/valid/mixed-handoff.json @@ -0,0 +1,43 @@ +{ + "schema_version": "mixed-backend-execution-binding/v1", + "binding_id": "binding:transition.sim-to-emu", + "profile_id": "profile:mixed", + "profile_revision": "mixed-cross-backend-participant-control-v1@rev1", + "profile_digest": "sha256:83d1c9715656e4f1cbaf93083934fc941cccdae51718c36c75f6a77813f3371b", + "subject": { + "kind": "handoff", + "transition_id": "transition.sim-to-emu", + "operation_kind": "composition-phase", + "source_component_id": "sim", + "destination_component_id": "emu", + "source_owner_ref": "native-ownership:sim", + "destination_owner_ref": "native-ownership:emu", + "transfer": { + "service_ref": "transfer:native-ownership", + "version": "1", + "digest": "sha256:5555555555555555555555555555555555555555555555555555555555555555" + }, + "time": { + "time_model_ref": "time-model:composition", + "time_model_digest": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "source_clock_address": "time.clocks.sim", + "destination_clock_address": "time.clocks.emu", + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "control_plane_order", + "required_comparison": "ordered", + "coordinator": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + } + }, + "owner_reader": { + "service_ref": "reader:native-owner", + "version": "1", + "digest": "sha256:6666666666666666666666666666666666666666666666666666666666666666" + }, + "required_evidence_refs": [ + "evidence:phase-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/context-invalid/foreign-invocation.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/context-invalid/foreign-invocation.json new file mode 100644 index 000000000..8a5ab79e7 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/context-invalid/foreign-invocation.json @@ -0,0 +1,45 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:another", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 3, + "stage": { + "stage": "delivery", + "producer": { + "service_ref": "reader:destination-receipt", + "version": "1", + "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + "destination_component_id": "emu", + "receipt_ref": "receipt:mixed-edge", + "evidence_refs": [ + "evidence:destination-receipt" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/invalid/failed-without-cessation.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/invalid/failed-without-cessation.json new file mode 100644 index 000000000..2854d0e95 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/invalid/failed-without-cessation.json @@ -0,0 +1,50 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 2, + "stage": { + "stage": "execution", + "producer": { + "service_ref": "route:portable", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "source_action_address": "participant.action-contract.contain-host", + "destination_action_address": "participant.action-contract.contain-host", + "status": "failed", + "evidence_refs": [ + "evidence:backend-readback" + ], + "mapping_loss_refs": [ + "limitation:mapping" + ], + "cessation_evidence_refs": [] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/invalid/observation-without-evidence.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/invalid/observation-without-evidence.json new file mode 100644 index 000000000..154efc5e3 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/invalid/observation-without-evidence.json @@ -0,0 +1,44 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 4, + "stage": { + "stage": "observation", + "producer": { + "service_ref": "reader:participant-audience", + "version": "1", + "digest": "sha256:4444444444444444444444444444444444444444444444444444444444444444" + }, + "participant_address": "participant.behavior.red-agent", + "audience_scope_ref": "audience:red-operator", + "observation_ref": "observation:mixed-edge", + "evidence_refs": [] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/invalid/untagged-stage.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/invalid/untagged-stage.json new file mode 100644 index 000000000..833ed27b9 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/invalid/untagged-stage.json @@ -0,0 +1,44 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 3, + "stage": { + "producer": { + "service_ref": "reader:destination-receipt", + "version": "1", + "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + "destination_component_id": "emu", + "receipt_ref": "receipt:mixed-edge", + "evidence_refs": [ + "evidence:destination-receipt" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-01.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-01.json new file mode 100644 index 000000000..7cb310af9 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-01.json @@ -0,0 +1,61 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 1, + "stage": { + "stage": "time-grant", + "producer": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "partial_order", + "order_ref": "order:bridge:mixed-edge", + "comparison": "ordered", + "source_coordinate": { + "segment": 0, + "tick": 4, + "microstep": 0 + }, + "destination_coordinate": { + "segment": 0, + "tick": 4, + "microstep": 1 + }, + "mapping_evidence_refs": [ + "evidence:mapping-call" + ], + "timing_evidence_refs": [ + "evidence:time-grant", + "evidence:edge-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-02.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-02.json new file mode 100644 index 000000000..bd2bf72bc --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-02.json @@ -0,0 +1,50 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 2, + "stage": { + "stage": "execution", + "producer": { + "service_ref": "route:portable", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "source_action_address": "participant.action-contract.contain-host", + "destination_action_address": "participant.action-contract.contain-host", + "status": "succeeded", + "evidence_refs": [ + "evidence:backend-readback" + ], + "mapping_loss_refs": [ + "limitation:mapping" + ], + "cessation_evidence_refs": [] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-03.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-03.json new file mode 100644 index 000000000..0ba05a327 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-03.json @@ -0,0 +1,45 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 3, + "stage": { + "stage": "delivery", + "producer": { + "service_ref": "reader:destination-receipt", + "version": "1", + "digest": "sha256:3333333333333333333333333333333333333333333333333333333333333333" + }, + "destination_component_id": "emu", + "receipt_ref": "receipt:mixed-edge", + "evidence_refs": [ + "evidence:destination-receipt" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-04.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-04.json new file mode 100644 index 000000000..847c3b8db --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-04.json @@ -0,0 +1,46 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge", + "invocation_id": "invocation:mixed-edge", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:28a8db987813e00f25f47eed676dd744831bcb92bb5d262f7bd97e05bd0ad1bd", + "sequence": 4, + "stage": { + "stage": "observation", + "producer": { + "service_ref": "reader:participant-audience", + "version": "1", + "digest": "sha256:4444444444444444444444444444444444444444444444444444444444444444" + }, + "participant_address": "participant.behavior.red-agent", + "audience_scope_ref": "audience:red-operator", + "observation_ref": "observation:mixed-edge", + "evidence_refs": [ + "evidence:participant-readback" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-partial-01.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-partial-01.json new file mode 100644 index 000000000..2bbb51ce9 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-partial-01.json @@ -0,0 +1,61 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge-partial", + "invocation_id": "invocation:mixed-edge-partial", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:0bafdc8cb663d1478e5bd8e66da22a18a26c1f040f47ea95a12fba477948967a", + "sequence": 1, + "stage": { + "stage": "time-grant", + "producer": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "partial_order", + "order_ref": "order:bridge:mixed-edge-partial", + "comparison": "ordered", + "source_coordinate": { + "segment": 0, + "tick": 4, + "microstep": 0 + }, + "destination_coordinate": { + "segment": 0, + "tick": 4, + "microstep": 1 + }, + "mapping_evidence_refs": [ + "evidence:mapping-call" + ], + "timing_evidence_refs": [ + "evidence:time-grant", + "evidence:edge-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-partial-02.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-partial-02.json new file mode 100644 index 000000000..26e69e802 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-partial-02.json @@ -0,0 +1,50 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge-partial", + "invocation_id": "invocation:mixed-edge-partial", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:0bafdc8cb663d1478e5bd8e66da22a18a26c1f040f47ea95a12fba477948967a", + "sequence": 2, + "stage": { + "stage": "execution", + "producer": { + "service_ref": "route:portable", + "version": "1", + "digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111" + }, + "source_action_address": "participant.action-contract.contain-host", + "destination_action_address": "participant.action-contract.contain-host", + "status": "partial", + "evidence_refs": [ + "evidence:backend-partial-readback" + ], + "mapping_loss_refs": [ + "limitation:mapping" + ], + "cessation_evidence_refs": [] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-time-refused-01.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-time-refused-01.json new file mode 100644 index 000000000..abc91518e --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-edge-time-refused-01.json @@ -0,0 +1,61 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-edge-time-refused", + "invocation_id": "invocation:mixed-edge-time-refused", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "route:portable", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "participant-crossing", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:4c682409ce65cf3b1581458b9f18e43a84cadebc4b82753f9c986a70ff10a476", + "sequence": 1, + "stage": { + "stage": "time-grant", + "producer": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "partial_order", + "order_ref": "order:bridge:mixed-edge-time-refused", + "comparison": "incomparable", + "source_coordinate": { + "segment": 0, + "tick": 4, + "microstep": 0 + }, + "destination_coordinate": { + "segment": 1, + "tick": 2, + "microstep": 0 + }, + "mapping_evidence_refs": [ + "evidence:mapping-call" + ], + "timing_evidence_refs": [ + "evidence:time-grant", + "evidence:edge-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-01.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-01.json new file mode 100644 index 000000000..afa9baaa0 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-01.json @@ -0,0 +1,61 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-handoff", + "invocation_id": "invocation:mixed-handoff", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:e688489a9b66f704822e227e9a0c25b8a4b6f6e4f072011f02ea3574e309fb3b", + "sequence": 1, + "stage": { + "stage": "time-grant", + "producer": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "control_plane_order", + "order_ref": "order:handoff:mixed-handoff", + "comparison": "ordered", + "source_coordinate": { + "segment": 0, + "tick": 4, + "microstep": 0 + }, + "destination_coordinate": { + "segment": 0, + "tick": 4, + "microstep": 1 + }, + "mapping_evidence_refs": [ + "evidence:mapping-call" + ], + "timing_evidence_refs": [ + "evidence:time-grant", + "evidence:phase-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-02.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-02.json new file mode 100644 index 000000000..3eb36f273 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-02.json @@ -0,0 +1,48 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-handoff", + "invocation_id": "invocation:mixed-handoff", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:e688489a9b66f704822e227e9a0c25b8a4b6f6e4f072011f02ea3574e309fb3b", + "sequence": 2, + "stage": { + "stage": "handoff", + "producer": { + "service_ref": "transfer:native-ownership", + "version": "1", + "digest": "sha256:5555555555555555555555555555555555555555555555555555555555555555" + }, + "status": "committed", + "predecessor_history_head": "composition:activation:initial", + "phase_revision": 0, + "order_ref": "order:handoff:mixed-handoff", + "evidence_refs": [ + "evidence:native-transfer", + "evidence:phase-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-03.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-03.json new file mode 100644 index 000000000..0a87b0bac --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-03.json @@ -0,0 +1,46 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-handoff", + "invocation_id": "invocation:mixed-handoff", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:e688489a9b66f704822e227e9a0c25b8a4b6f6e4f072011f02ea3574e309fb3b", + "sequence": 3, + "stage": { + "stage": "owner-readback", + "producer": { + "service_ref": "reader:native-owner", + "version": "1", + "digest": "sha256:6666666666666666666666666666666666666666666666666666666666666666" + }, + "owner_component_id": "emu", + "owner_ref": "native-ownership:emu", + "phase_revision": 1, + "evidence_refs": [ + "evidence:owner-readback:emu" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-stale-01.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-stale-01.json new file mode 100644 index 000000000..2794df57e --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-stale-01.json @@ -0,0 +1,61 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-handoff-stale", + "invocation_id": "invocation:mixed-handoff-stale", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:07730d4dac0ef09031fce515a014fd45252ee137a1c82c0718e17d667e1fca32", + "sequence": 1, + "stage": { + "stage": "time-grant", + "producer": { + "service_ref": "coordinator:reference-time", + "version": "1", + "digest": "sha256:2222222222222222222222222222222222222222222222222222222222222222" + }, + "mapping_ref": "time.mappings.sim-to-emu", + "ordering_basis": "control_plane_order", + "order_ref": "order:handoff:mixed-handoff-stale", + "comparison": "ordered", + "source_coordinate": { + "segment": 0, + "tick": 4, + "microstep": 0 + }, + "destination_coordinate": { + "segment": 0, + "tick": 4, + "microstep": 1 + }, + "mapping_evidence_refs": [ + "evidence:mapping-call" + ], + "timing_evidence_refs": [ + "evidence:time-grant", + "evidence:phase-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-stale-02.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-stale-02.json new file mode 100644 index 000000000..aa82e2b00 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-stale-02.json @@ -0,0 +1,48 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-handoff-stale", + "invocation_id": "invocation:mixed-handoff-stale", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:07730d4dac0ef09031fce515a014fd45252ee137a1c82c0718e17d667e1fca32", + "sequence": 2, + "stage": { + "stage": "handoff", + "producer": { + "service_ref": "transfer:native-ownership", + "version": "1", + "digest": "sha256:5555555555555555555555555555555555555555555555555555555555555555" + }, + "status": "stale", + "predecessor_history_head": "composition:activation:initial", + "phase_revision": 0, + "order_ref": "order:handoff:mixed-handoff-stale", + "evidence_refs": [ + "evidence:native-transfer", + "evidence:phase-realization" + ] + } +} diff --git a/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-stale-03.json b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-stale-03.json new file mode 100644 index 000000000..587439617 --- /dev/null +++ b/contracts/fixtures/control-plane/mixed-backend-stage-report-v1/valid/mixed-handoff-stale-03.json @@ -0,0 +1,46 @@ +{ + "schema_version": "mixed-backend-stage-report/v1", + "binding": { + "operation_id": "operation:mixed-handoff-stale", + "invocation_id": "invocation:mixed-handoff-stale", + "attempt_id": "attempt:1", + "worker_id": "worker:effects-1", + "deployment_id": "deployment:reference", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "transfer:native-ownership", + "baseline_revision": "revision:7", + "context": { + "actor_id": "operator:mixed", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target:mixed", + "run_scope": "run:mixed", + "operation_kind": "composition-phase", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:07730d4dac0ef09031fce515a014fd45252ee137a1c82c0718e17d667e1fca32", + "sequence": 3, + "stage": { + "stage": "owner-readback", + "producer": { + "service_ref": "reader:native-owner", + "version": "1", + "digest": "sha256:6666666666666666666666666666666666666666666666666666666666666666" + }, + "owner_component_id": "sim", + "owner_ref": "native-ownership:sim", + "phase_revision": 0, + "evidence_refs": [ + "evidence:owner-readback:sim" + ] + } +} diff --git a/contracts/schema-publication/entries/backend-manifest-v2.json b/contracts/schema-publication/entries/backend-manifest-v2.json index 2fa764d44..3d370036a 100644 --- a/contracts/schema-publication/entries/backend-manifest-v2.json +++ b/contracts/schema-publication/entries/backend-manifest-v2.json @@ -1,9 +1,9 @@ { - "content_hash": "be543802e6518ee04254963a97bba5b33c9cf06715cff0a4cd107ffb6ab0316b", + "content_hash": "5835e2604fb7c583e4fc84e4a78c31f52e7ee79baef69910c5bc6d120a578028", "contract_id": "backend-manifest-v2", "last_change": { - "content_hash": "be543802e6518ee04254963a97bba5b33c9cf06715cff0a4cd107ffb6ab0316b", - "summary": "Carry optional complete execution/recovery requirements and resolved evidence through SDL/native plans; declare installed support and fail closed on incompatible requests (#1361)." + "content_hash": "5835e2604fb7c583e4fc84e4a78c31f52e7ee79baef69910c5bc6d120a578028", + "summary": "Allow declarations of the mixed-backend execution binding and stage report contracts (#1371)." }, "schema_path": "contracts/schemas/backend-manifest/backend-manifest-v2.json", "stability": "draft" diff --git a/contracts/schema-publication/entries/backend-profile-v1.json b/contracts/schema-publication/entries/backend-profile-v1.json index a5acaf849..80438ae56 100644 --- a/contracts/schema-publication/entries/backend-profile-v1.json +++ b/contracts/schema-publication/entries/backend-profile-v1.json @@ -1,9 +1,9 @@ { - "content_hash": "b51c39ee482a49608a96ce3bdc66f587a2cdff9daf5b8c872a079dd920d88f56", + "content_hash": "d9c7a0ac6f2086f6972f16fcc7ae187207adffb4cd299f63503e2a7295c2b518", "contract_id": "backend-profile-v1", "last_change": { - "summary": "Allow exact declarations of participant-control v2 selection and evaluation contracts (#1365).", - "content_hash": "b51c39ee482a49608a96ce3bdc66f587a2cdff9daf5b8c872a079dd920d88f56" + "summary": "Allow declarations of the mixed-backend execution binding and stage report contracts (#1371).", + "content_hash": "d9c7a0ac6f2086f6972f16fcc7ae187207adffb4cd299f63503e2a7295c2b518" }, "schema_path": "contracts/schemas/profiles/backend-profile-v1.json", "stability": "draft" diff --git a/contracts/schema-publication/entries/mixed-backend-execution-binding-v1.json b/contracts/schema-publication/entries/mixed-backend-execution-binding-v1.json new file mode 100644 index 000000000..33409e83c --- /dev/null +++ b/contracts/schema-publication/entries/mixed-backend-execution-binding-v1.json @@ -0,0 +1,10 @@ +{ + "contract_id": "mixed-backend-execution-binding-v1", + "schema_path": "contracts/schemas/control-plane/mixed-backend-execution-binding-v1.json", + "stability": "draft", + "content_hash": "2efa65cb99c509f9be6c732c4339de37917982f6125101f0cdb4b5d29c7ef5e0", + "last_change": { + "summary": "Publish versioned mixed-backend execution bindings and correlated stage reports joined to the shared backend operation protocol (#1371).", + "content_hash": "2efa65cb99c509f9be6c732c4339de37917982f6125101f0cdb4b5d29c7ef5e0" + } +} diff --git a/contracts/schema-publication/entries/mixed-backend-stage-report-v1.json b/contracts/schema-publication/entries/mixed-backend-stage-report-v1.json new file mode 100644 index 000000000..dce7e32ec --- /dev/null +++ b/contracts/schema-publication/entries/mixed-backend-stage-report-v1.json @@ -0,0 +1,10 @@ +{ + "contract_id": "mixed-backend-stage-report-v1", + "schema_path": "contracts/schemas/control-plane/mixed-backend-stage-report-v1.json", + "stability": "draft", + "content_hash": "0cbff620168495429c60bcda111914eb02c80cc38e41ec25e750585378dcb628", + "last_change": { + "summary": "Publish versioned mixed-backend execution bindings and correlated stage reports joined to the shared backend operation protocol (#1371).", + "content_hash": "0cbff620168495429c60bcda111914eb02c80cc38e41ec25e750585378dcb628" + } +} diff --git a/contracts/schemas/backend-manifest/backend-manifest-v2.json b/contracts/schemas/backend-manifest/backend-manifest-v2.json index b71552539..6946ed314 100644 --- a/contracts/schemas/backend-manifest/backend-manifest-v2.json +++ b/contracts/schemas/backend-manifest/backend-manifest-v2.json @@ -3681,6 +3681,8 @@ "backend-operation-capabilities-v1", "backend-operation-control-v1", "backend-operation-response-v1", + "mixed-backend-execution-binding-v1", + "mixed-backend-stage-report-v1", "backend-materialization-attestation-v1", "backend-augmentation-scope-v1", "plan-realization-profiles-v1", diff --git a/contracts/schemas/control-plane/mixed-backend-execution-binding-v1.json b/contracts/schemas/control-plane/mixed-backend-execution-binding-v1.json new file mode 100644 index 000000000..2ef20c3ba --- /dev/null +++ b/contracts/schemas/control-plane/mixed-backend-execution-binding-v1.json @@ -0,0 +1,585 @@ +{ + "$defs": { + "MixedBackendEdgeBindingModel": { + "additionalProperties": false, + "description": "Bridge, coordinator and readers for one admitted directed edge.\n\nThe destination provider executes the mapped action under one RAES\nparticipant-crossing operation; owning the effect confers no controller,\ndisclosure or terminal-commit authority. Native translation stays inside\nthe pinned bridge, so the compiled action subject is preserved. Each role\nis a distinct service, so the bridge never grants its own order or reads\nback its own delivery or observation.", + "properties": { + "audience_scope_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Audience Scope Ref", + "type": "string" + }, + "bridge": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "delivery_reader": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "destination_action_address": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Destination Action Address", + "type": "string" + }, + "edge_id": { + "maxLength": 256, + "minLength": 1, + "title": "Edge Id", + "type": "string" + }, + "kind": { + "const": "edge", + "title": "Kind", + "type": "string" + }, + "mapping_loss": { + "$ref": "#/$defs/MixedCompositionMappingLossModel" + }, + "observation_reader": { + "anyOf": [ + { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + { + "type": "null" + } + ], + "default": null + }, + "operation_kind": { + "const": "participant-crossing", + "default": "participant-crossing", + "title": "Operation Kind", + "type": "string" + }, + "owner_allocation_id": { + "maxLength": 256, + "minLength": 1, + "title": "Owner Allocation Id", + "type": "string" + }, + "owner_component_id": { + "maxLength": 256, + "minLength": 1, + "title": "Owner Component Id", + "type": "string" + }, + "participant_address": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Participant Address", + "type": "string" + }, + "required_evidence_refs": { + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "minItems": 1, + "title": "Required Evidence Refs", + "type": "array" + }, + "source_action_address": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Source Action Address", + "type": "string" + }, + "subject_transformation": { + "const": "compiled-identity", + "default": "compiled-identity", + "title": "Subject Transformation", + "type": "string" + }, + "time": { + "$ref": "#/$defs/MixedBackendEdgeTimeRequirementModel" + } + }, + "required": [ + "kind", + "edge_id", + "owner_component_id", + "owner_allocation_id", + "participant_address", + "audience_scope_ref", + "source_action_address", + "destination_action_address", + "bridge", + "time", + "mapping_loss", + "delivery_reader", + "required_evidence_refs" + ], + "title": "MixedBackendEdgeBindingModel", + "type": "object" + }, + "MixedBackendEdgeTimeRequirementModel": { + "additionalProperties": false, + "description": "Edge time requirement that also carries the admitted edge's temporal coupling.", + "properties": { + "coordinator": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "destination_clock_address": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Destination Clock Address", + "type": "string" + }, + "mapping_ref": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Mapping Ref", + "type": "string" + }, + "ordering_basis": { + "enum": [ + "total_order", + "partial_order", + "simultaneous", + "serialized_backend_order", + "simulation_tick", + "control_plane_order", + "logical_clock", + "vector_clock" + ], + "title": "Ordering Basis", + "type": "string" + }, + "required_comparison": { + "const": "ordered", + "default": "ordered", + "title": "Required Comparison", + "type": "string" + }, + "source_clock_address": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Source Clock Address", + "type": "string" + }, + "temporal_coupling": { + "enum": [ + "tight", + "bounded-asynchronous", + "asynchronous" + ], + "title": "Temporal Coupling", + "type": "string" + }, + "time_model_digest": { + "minLength": 1, + "pattern": "^(?:sha256:[A-Fa-f0-9]{64}|sha384:[A-Fa-f0-9]{96}|sha512:[A-Fa-f0-9]{128}|blake3:[A-Fa-f0-9]{64})$", + "title": "Time Model Digest", + "type": "string" + }, + "time_model_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Time Model Ref", + "type": "string" + } + }, + "required": [ + "time_model_ref", + "time_model_digest", + "source_clock_address", + "destination_clock_address", + "mapping_ref", + "ordering_basis", + "coordinator", + "temporal_coupling" + ], + "title": "MixedBackendEdgeTimeRequirementModel", + "type": "object" + }, + "MixedBackendHandoffBindingModel": { + "additionalProperties": false, + "description": "Native responsibility transfer for one admitted component-changing transition.\n\nThe transfer service, coordinator and owner reader are distinct services,\nso a transfer never grants its own order or reads back its own owner.", + "properties": { + "destination_component_id": { + "maxLength": 256, + "minLength": 1, + "title": "Destination Component Id", + "type": "string" + }, + "destination_owner_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Destination Owner Ref", + "type": "string" + }, + "kind": { + "const": "handoff", + "title": "Kind", + "type": "string" + }, + "operation_kind": { + "const": "composition-phase", + "default": "composition-phase", + "title": "Operation Kind", + "type": "string" + }, + "owner_reader": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "required_evidence_refs": { + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "minItems": 1, + "title": "Required Evidence Refs", + "type": "array" + }, + "source_component_id": { + "maxLength": 256, + "minLength": 1, + "title": "Source Component Id", + "type": "string" + }, + "source_owner_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Source Owner Ref", + "type": "string" + }, + "time": { + "$ref": "#/$defs/MixedBackendTimeRequirementModel" + }, + "transfer": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "transition_id": { + "maxLength": 256, + "minLength": 1, + "title": "Transition Id", + "type": "string" + } + }, + "required": [ + "kind", + "transition_id", + "source_component_id", + "destination_component_id", + "source_owner_ref", + "destination_owner_ref", + "transfer", + "time", + "owner_reader", + "required_evidence_refs" + ], + "title": "MixedBackendHandoffBindingModel", + "type": "object" + }, + "MixedBackendServiceModel": { + "additionalProperties": false, + "description": "Pinned installed implementation identity; never a module, path, URL or command.", + "properties": { + "digest": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Digest", + "type": "string" + }, + "service_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Service Ref", + "type": "string" + }, + "version": { + "maxLength": 256, + "minLength": 1, + "title": "Version", + "type": "string" + } + }, + "required": [ + "service_ref", + "version", + "digest" + ], + "title": "MixedBackendServiceModel", + "type": "object" + }, + "MixedBackendTimeRequirementModel": { + "additionalProperties": false, + "description": "Named clocks, mapping and governed order a coordinator must grant before invocation.", + "properties": { + "coordinator": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "destination_clock_address": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Destination Clock Address", + "type": "string" + }, + "mapping_ref": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Mapping Ref", + "type": "string" + }, + "ordering_basis": { + "enum": [ + "total_order", + "partial_order", + "simultaneous", + "serialized_backend_order", + "simulation_tick", + "control_plane_order", + "logical_clock", + "vector_clock" + ], + "title": "Ordering Basis", + "type": "string" + }, + "required_comparison": { + "const": "ordered", + "default": "ordered", + "title": "Required Comparison", + "type": "string" + }, + "source_clock_address": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Source Clock Address", + "type": "string" + }, + "time_model_digest": { + "minLength": 1, + "pattern": "^(?:sha256:[A-Fa-f0-9]{64}|sha384:[A-Fa-f0-9]{96}|sha512:[A-Fa-f0-9]{128}|blake3:[A-Fa-f0-9]{64})$", + "title": "Time Model Digest", + "type": "string" + }, + "time_model_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Time Model Ref", + "type": "string" + } + }, + "required": [ + "time_model_ref", + "time_model_digest", + "source_clock_address", + "destination_clock_address", + "mapping_ref", + "ordering_basis", + "coordinator" + ], + "title": "MixedBackendTimeRequirementModel", + "type": "object" + }, + "MixedCompositionMappingLossModel": { + "additionalProperties": false, + "description": "Prospective mapping-loss obligation using the incumbent loss vocabulary.", + "properties": { + "affected_ref": { + "minLength": 1, + "title": "Affected Ref", + "type": "string" + }, + "basis_ref": { + "minLength": 1, + "title": "Basis Ref", + "type": "string" + }, + "kind": { + "enum": [ + "none", + "private_apparatus_detail", + "source_fields_omitted", + "semantics_approximated", + "redacted_by_policy", + "temporal_detail_collapsed", + "unknown", + "unsupported" + ], + "title": "Kind", + "type": "string" + }, + "limitation_ref": { + "minLength": 1, + "title": "Limitation Ref", + "type": "string" + } + }, + "required": [ + "kind", + "basis_ref", + "affected_ref", + "limitation_ref" + ], + "title": "MixedCompositionMappingLossModel", + "type": "object" + } + }, + "$id": "https://openrae.github.io/rae/schemas/mixed-backend-execution-binding-v1.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "description": "One installed executable binding, joined to its sealed profile by identity and digest.", + "properties": { + "binding_id": { + "maxLength": 256, + "minLength": 1, + "title": "Binding Id", + "type": "string" + }, + "profile_digest": { + "minLength": 1, + "pattern": "^(?:sha256:[A-Fa-f0-9]{64}|sha384:[A-Fa-f0-9]{96}|sha512:[A-Fa-f0-9]{128}|blake3:[A-Fa-f0-9]{64})$", + "title": "Profile Digest", + "type": "string" + }, + "profile_id": { + "maxLength": 256, + "minLength": 1, + "title": "Profile Id", + "type": "string" + }, + "profile_revision": { + "const": "mixed-cross-backend-participant-control-v1@rev1", + "default": "mixed-cross-backend-participant-control-v1@rev1", + "title": "Profile Revision", + "type": "string" + }, + "schema_version": { + "const": "mixed-backend-execution-binding/v1", + "default": "mixed-backend-execution-binding/v1", + "title": "Schema Version", + "type": "string" + }, + "subject": { + "discriminator": { + "mapping": { + "edge": "#/$defs/MixedBackendEdgeBindingModel", + "handoff": "#/$defs/MixedBackendHandoffBindingModel" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/$defs/MixedBackendEdgeBindingModel" + }, + { + "$ref": "#/$defs/MixedBackendHandoffBindingModel" + } + ], + "title": "Subject" + } + }, + "required": [ + "binding_id", + "profile_id", + "profile_digest", + "subject" + ], + "title": "MixedBackendExecutionBindingModel", + "type": "object", + "x-raes-invariants": [ + { + "description": "Validate closed bounded fields, unique collections, a preserved compiled subject, distinct handoff components and a distinct pinned service for each role, so no two roles share a service reference or digest; structural validity does not prove backend truth, installation or runtime authority.", + "id": "mixed-backend-local-consistency", + "inputs": [ + { + "contract_id": "mixed-backend-execution-binding-v1", + "instance_path": "#" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.MixedBackendExecutionBindingModel.model_validate" + }, + { + "description": "Require exactly one matching binding per active edge and one-to-one component-changing transition of the admitted sealed profile, with governed order, preserved compiled subjects, declared loss and the edge's admitted temporal coupling.", + "id": "mixed-backend-binding-profile-join", + "inputs": [ + { + "contract_id": "mixed-participant-composition-profile-v1", + "instance_path": "#" + }, + { + "contract_id": "mixed-backend-execution-binding-v1", + "instance_path": "#" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.validate_mixed_backend_bindings" + }, + { + "description": "Before invocation require the shared request to commit to this binding, its operation kind and its installed bridge or transfer service, then installed support and current exact-context willingness.", + "id": "mixed-backend-contextual-admission", + "inputs": [ + { + "contract_id": "mixed-backend-execution-binding-v1", + "instance_path": "#" + }, + { + "contract_id": "backend-operation-request-v1", + "instance_path": "#" + }, + { + "contract_id": "backend-operation-capabilities-v1", + "instance_path": "#" + }, + { + "contract_id": "backend-operation-response-v1", + "instance_path": "#" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.require_mixed_backend_admission" + } + ], + "x-raes-semantic-profile": { + "contract_id": "mixed-backend-execution-binding-v1", + "entry_schema_contract_id": "raes-semantic-invariants-v1", + "entry_schema_pointer": "#/$defs/RaesSemanticInvariantEntryModel", + "id": "raes-semantic-invariants-v1", + "keyword": "x-raes-invariants", + "required": true, + "uri": "https://openrae.github.io/rae/schemas/semantic-invariants/v1" + } +} diff --git a/contracts/schemas/control-plane/mixed-backend-stage-report-v1.json b/contracts/schemas/control-plane/mixed-backend-stage-report-v1.json new file mode 100644 index 000000000..f53a9c485 --- /dev/null +++ b/contracts/schemas/control-plane/mixed-backend-stage-report-v1.json @@ -0,0 +1,825 @@ +{ + "$defs": { + "BackendOperationBindingModel": { + "additionalProperties": false, + "description": "Original context and invocation identity, including state-publication fences.", + "properties": { + "attempt_id": { + "maxLength": 256, + "minLength": 1, + "title": "Attempt Id", + "type": "string" + }, + "backend_id": { + "maxLength": 256, + "minLength": 1, + "title": "Backend Id", + "type": "string" + }, + "baseline_revision": { + "maxLength": 256, + "minLength": 1, + "title": "Baseline Revision", + "type": "string" + }, + "context": { + "$ref": "#/$defs/OperationAdmissionContext" + }, + "deployment_id": { + "maxLength": 256, + "minLength": 1, + "title": "Deployment Id", + "type": "string" + }, + "effect_scope": { + "$ref": "#/$defs/OperationEffectScopeModel" + }, + "execution_generation": { + "maximum": 9007199254740991, + "minimum": 0, + "title": "Execution Generation", + "type": "integer" + }, + "invocation_id": { + "maxLength": 256, + "minLength": 1, + "title": "Invocation Id", + "type": "string" + }, + "operation_id": { + "maxLength": 256, + "minLength": 1, + "title": "Operation Id", + "type": "string" + }, + "owner_generation": { + "maximum": 9007199254740991, + "minimum": 0, + "title": "Owner Generation", + "type": "integer" + }, + "worker_id": { + "maxLength": 256, + "minLength": 1, + "title": "Worker Id", + "type": "string" + } + }, + "required": [ + "operation_id", + "invocation_id", + "attempt_id", + "worker_id", + "deployment_id", + "owner_generation", + "execution_generation", + "backend_id", + "baseline_revision", + "context" + ], + "title": "BackendOperationBindingModel", + "type": "object" + }, + "MixedBackendDeliveryStageModel": { + "additionalProperties": false, + "description": "Destination receipt read back by the pinned delivery reader, not the bridge.", + "properties": { + "destination_component_id": { + "maxLength": 256, + "minLength": 1, + "title": "Destination Component Id", + "type": "string" + }, + "evidence_refs": { + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "minItems": 1, + "title": "Evidence Refs", + "type": "array" + }, + "producer": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "receipt_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Receipt Ref", + "type": "string" + }, + "stage": { + "const": "delivery", + "title": "Stage", + "type": "string" + } + }, + "required": [ + "stage", + "producer", + "destination_component_id", + "receipt_ref", + "evidence_refs" + ], + "title": "MixedBackendDeliveryStageModel", + "type": "object" + }, + "MixedBackendExecutionStageModel": { + "additionalProperties": false, + "description": "Bridge execution readback; it establishes no delivery or participant observation.", + "properties": { + "cessation_evidence_refs": { + "default": [], + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "title": "Cessation Evidence Refs", + "type": "array" + }, + "destination_action_address": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Destination Action Address", + "type": "string" + }, + "evidence_refs": { + "default": [], + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "title": "Evidence Refs", + "type": "array" + }, + "mapping_loss_refs": { + "default": [], + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "title": "Mapping Loss Refs", + "type": "array" + }, + "producer": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "source_action_address": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Source Action Address", + "type": "string" + }, + "stage": { + "const": "execution", + "title": "Stage", + "type": "string" + }, + "status": { + "enum": [ + "succeeded", + "failed", + "partial", + "unknown" + ], + "title": "Status", + "type": "string" + } + }, + "required": [ + "stage", + "producer", + "source_action_address", + "destination_action_address", + "status" + ], + "title": "MixedBackendExecutionStageModel", + "type": "object" + }, + "MixedBackendHandoffStageModel": { + "additionalProperties": false, + "description": "Native transfer disposition at the exact predecessor history head and phase revision.", + "properties": { + "evidence_refs": { + "default": [], + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "title": "Evidence Refs", + "type": "array" + }, + "order_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Order Ref", + "type": "string" + }, + "phase_revision": { + "maximum": 9007199254740991, + "minimum": 0, + "title": "Phase Revision", + "type": "integer" + }, + "predecessor_history_head": { + "maxLength": 256, + "minLength": 1, + "title": "Predecessor History Head", + "type": "string" + }, + "producer": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "stage": { + "const": "handoff", + "title": "Stage", + "type": "string" + }, + "status": { + "enum": [ + "committed", + "failed", + "pending", + "stale", + "unknown" + ], + "title": "Status", + "type": "string" + } + }, + "required": [ + "stage", + "producer", + "status", + "predecessor_history_head", + "phase_revision", + "order_ref" + ], + "title": "MixedBackendHandoffStageModel", + "type": "object" + }, + "MixedBackendObservationStageModel": { + "additionalProperties": false, + "description": "Participant and audience readback after delivery; delivery alone is not observation.", + "properties": { + "audience_scope_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Audience Scope Ref", + "type": "string" + }, + "evidence_refs": { + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "minItems": 1, + "title": "Evidence Refs", + "type": "array" + }, + "observation_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Observation Ref", + "type": "string" + }, + "participant_address": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Participant Address", + "type": "string" + }, + "producer": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "stage": { + "const": "observation", + "title": "Stage", + "type": "string" + } + }, + "required": [ + "stage", + "producer", + "participant_address", + "audience_scope_ref", + "observation_ref", + "evidence_refs" + ], + "title": "MixedBackendObservationStageModel", + "type": "object" + }, + "MixedBackendOwnerReadbackStageModel": { + "additionalProperties": false, + "description": "Native responsibility owner read back by the pinned owner reader after a transfer attempt.", + "properties": { + "evidence_refs": { + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "minItems": 1, + "title": "Evidence Refs", + "type": "array" + }, + "owner_component_id": { + "maxLength": 256, + "minLength": 1, + "title": "Owner Component Id", + "type": "string" + }, + "owner_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Owner Ref", + "type": "string" + }, + "phase_revision": { + "maximum": 9007199254740991, + "minimum": 0, + "title": "Phase Revision", + "type": "integer" + }, + "producer": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "stage": { + "const": "owner-readback", + "title": "Stage", + "type": "string" + } + }, + "required": [ + "stage", + "producer", + "owner_component_id", + "owner_ref", + "phase_revision", + "evidence_refs" + ], + "title": "MixedBackendOwnerReadbackStageModel", + "type": "object" + }, + "MixedBackendServiceModel": { + "additionalProperties": false, + "description": "Pinned installed implementation identity; never a module, path, URL or command.", + "properties": { + "digest": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Digest", + "type": "string" + }, + "service_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Service Ref", + "type": "string" + }, + "version": { + "maxLength": 256, + "minLength": 1, + "title": "Version", + "type": "string" + } + }, + "required": [ + "service_ref", + "version", + "digest" + ], + "title": "MixedBackendServiceModel", + "type": "object" + }, + "MixedBackendTimeGrantStageModel": { + "additionalProperties": false, + "description": "Coordinator grant at the committed clock coordinates; incomparable grants permit no invocation.", + "properties": { + "comparison": { + "enum": [ + "ordered", + "incomparable" + ], + "title": "Comparison", + "type": "string" + }, + "destination_coordinate": { + "$ref": "#/$defs/TimeCoordinateModel" + }, + "mapping_evidence_refs": { + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "minItems": 1, + "title": "Mapping Evidence Refs", + "type": "array" + }, + "mapping_ref": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "title": "Mapping Ref", + "type": "string" + }, + "order_ref": { + "maxLength": 256, + "minLength": 1, + "title": "Order Ref", + "type": "string" + }, + "ordering_basis": { + "enum": [ + "total_order", + "partial_order", + "simultaneous", + "serialized_backend_order", + "simulation_tick", + "control_plane_order", + "logical_clock", + "vector_clock" + ], + "title": "Ordering Basis", + "type": "string" + }, + "producer": { + "$ref": "#/$defs/MixedBackendServiceModel" + }, + "source_coordinate": { + "$ref": "#/$defs/TimeCoordinateModel" + }, + "stage": { + "const": "time-grant", + "title": "Stage", + "type": "string" + }, + "timing_evidence_refs": { + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "minItems": 1, + "title": "Timing Evidence Refs", + "type": "array" + } + }, + "required": [ + "stage", + "producer", + "mapping_ref", + "ordering_basis", + "order_ref", + "comparison", + "source_coordinate", + "destination_coordinate", + "mapping_evidence_refs", + "timing_evidence_refs" + ], + "title": "MixedBackendTimeGrantStageModel", + "type": "object" + }, + "OperationAdmissionContext": { + "additionalProperties": false, + "description": "Immutable, value-free authority and request context fixed at admission.", + "properties": { + "actor_id": { + "maxLength": 256, + "minLength": 1, + "title": "Actor Id", + "type": "string" + }, + "authorization_scope": { + "items": { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + "maxItems": 64, + "minItems": 1, + "title": "Authorization Scope", + "type": "array" + }, + "operation_kind": { + "$ref": "#/$defs/OperationKind" + }, + "parent_operation_id": { + "anyOf": [ + { + "maxLength": 256, + "minLength": 1, + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Parent Operation Id" + }, + "request_commitment": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Request Commitment", + "type": "string" + }, + "run_scope": { + "maxLength": 256, + "minLength": 1, + "title": "Run Scope", + "type": "string" + }, + "target_scope": { + "maxLength": 256, + "minLength": 1, + "title": "Target Scope", + "type": "string" + } + }, + "required": [ + "actor_id", + "authorization_scope", + "target_scope", + "run_scope", + "operation_kind", + "request_commitment" + ], + "title": "OperationAdmissionContext", + "type": "object" + }, + "OperationArtifactReferenceModel": { + "additionalProperties": false, + "description": "Content-bound reference resolved through the owning admitted artifact authority.", + "properties": { + "artifact_id": { + "maxLength": 256, + "minLength": 1, + "title": "Artifact Id", + "type": "string" + }, + "contract_id": { + "maxLength": 128, + "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*-v[0-9]+$", + "title": "Contract Id", + "type": "string" + }, + "digest": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Digest", + "type": "string" + } + }, + "required": [ + "contract_id", + "artifact_id", + "digest" + ], + "title": "OperationArtifactReferenceModel", + "type": "object" + }, + "OperationEffectScopeModel": { + "additionalProperties": false, + "description": "Target/run exclusion is the default; narrowing needs admitted independence.", + "properties": { + "addresses": { + "default": [], + "items": { + "maxLength": 2048, + "minLength": 3, + "not": { + "pattern": "[^a-z0-9_.-]" + }, + "pattern": "^(?:[a-z0-9][a-z0-9_-]{0,63}|__private)(?:\\.(?:[a-z0-9][a-z0-9_-]{0,63}|__private))+$", + "type": "string" + }, + "maxItems": 256, + "title": "Addresses", + "type": "array" + }, + "independence": { + "anyOf": [ + { + "$ref": "#/$defs/OperationArtifactReferenceModel" + }, + { + "type": "null" + } + ], + "default": null + }, + "kind": { + "default": "target-run", + "enum": [ + "target-run", + "resources" + ], + "title": "Kind", + "type": "string" + } + }, + "title": "OperationEffectScopeModel", + "type": "object" + }, + "OperationKind": { + "description": "Closed kinds of work admitted by the runtime control plane.", + "enum": [ + "provisioning", + "orchestration", + "evaluation", + "workflow-cancellation", + "workflow-timeout-reconciliation", + "participant-action", + "participant-control", + "participant-crossing", + "composition-phase", + "indeterminate-resolution" + ], + "title": "OperationKind", + "type": "string" + }, + "TimeCoordinateModel": { + "additionalProperties": false, + "description": "Exact superdense coordinate within one discontinuity segment.", + "properties": { + "microstep": { + "default": 0, + "minimum": 0, + "title": "Microstep", + "type": "integer" + }, + "segment": { + "default": 0, + "minimum": 0, + "title": "Segment", + "type": "integer" + }, + "tick": { + "title": "Tick", + "type": "integer" + } + }, + "required": [ + "tick" + ], + "title": "TimeCoordinateModel", + "type": "object" + } + }, + "$id": "https://openrae.github.io/rae/schemas/mixed-backend-stage-report-v1.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "description": "One stage fact bound to the exact shared operation invocation and request commitment.\n\nThe sequence is the stage's fixed position in its chain: time grant 1,\nexecution or handoff 2, delivery or owner readback 3, observation 4. Each\nproducer numbers its own report without seeing the others, and a reader\naccepts the reports in ascending sequence.", + "properties": { + "binding": { + "$ref": "#/$defs/BackendOperationBindingModel" + }, + "request_digest": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Request Digest", + "type": "string" + }, + "schema_version": { + "const": "mixed-backend-stage-report/v1", + "default": "mixed-backend-stage-report/v1", + "title": "Schema Version", + "type": "string" + }, + "sequence": { + "maximum": 9007199254740991, + "minimum": 1, + "title": "Sequence", + "type": "integer" + }, + "stage": { + "discriminator": { + "mapping": { + "delivery": "#/$defs/MixedBackendDeliveryStageModel", + "execution": "#/$defs/MixedBackendExecutionStageModel", + "handoff": "#/$defs/MixedBackendHandoffStageModel", + "observation": "#/$defs/MixedBackendObservationStageModel", + "owner-readback": "#/$defs/MixedBackendOwnerReadbackStageModel", + "time-grant": "#/$defs/MixedBackendTimeGrantStageModel" + }, + "propertyName": "stage" + }, + "oneOf": [ + { + "$ref": "#/$defs/MixedBackendTimeGrantStageModel" + }, + { + "$ref": "#/$defs/MixedBackendExecutionStageModel" + }, + { + "$ref": "#/$defs/MixedBackendDeliveryStageModel" + }, + { + "$ref": "#/$defs/MixedBackendObservationStageModel" + }, + { + "$ref": "#/$defs/MixedBackendHandoffStageModel" + }, + { + "$ref": "#/$defs/MixedBackendOwnerReadbackStageModel" + } + ], + "title": "Stage" + } + }, + "required": [ + "binding", + "request_digest", + "sequence", + "stage" + ], + "title": "MixedBackendStageReportModel", + "type": "object", + "x-raes-invariants": [ + { + "description": "Validate closed bounded fields, unique collections and honest stage evidence; structural validity does not prove backend truth, installation or runtime authority.", + "id": "mixed-backend-local-consistency", + "inputs": [ + { + "contract_id": "mixed-backend-stage-report-v1", + "instance_path": "#" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.MixedBackendStageReportModel.model_validate" + }, + { + "description": "Require exact invocation binding and commitment, a trusted time model resolved under the binding's time-model reference and digest, each report's sequence equal to its stage's fixed chain position (time grant 1, execution or handoff 2, delivery or owner readback 3, observation 4) with reports accepted in ascending sequence, prerequisite stage order, the pinned producer for each stage, grant coordinates equal to the committed time readback, a committed composition state that still activates the edge or holds the handoff's source component without its destination, a handoff fenced on that state's head and phase revision, an ordered grant and accepted start before invocation stages, success or failure outcomes equal to the state the stages and trusted readbacks establish, and shared evidence that cites only supplied stage reports.", + "id": "mixed-backend-stage-transcript", + "inputs": [ + { + "contract_id": "mixed-backend-execution-binding-v1", + "instance_path": "#" + }, + { + "contract_id": "backend-operation-request-v1", + "instance_path": "#" + }, + { + "contract_id": "backend-operation-response-v1", + "instance_path": "#" + }, + { + "contract_id": "mixed-backend-stage-report-v1", + "instance_path": "#" + }, + { + "contract_id": "time-model-v1", + "instance_path": "#" + }, + { + "contract_id": "time-runtime-state-v1", + "instance_path": "#" + }, + { + "contract_id": "runtime-snapshot-v1", + "instance_path": "#/mixed_composition_states" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.validate_mixed_backend_stage_reports" + } + ], + "x-raes-semantic-profile": { + "contract_id": "mixed-backend-stage-report-v1", + "entry_schema_contract_id": "raes-semantic-invariants-v1", + "entry_schema_pointer": "#/$defs/RaesSemanticInvariantEntryModel", + "id": "raes-semantic-invariants-v1", + "keyword": "x-raes-invariants", + "required": true, + "uri": "https://openrae.github.io/rae/schemas/semantic-invariants/v1" + } +} diff --git a/contracts/schemas/profiles/backend-profile-v1.json b/contracts/schemas/profiles/backend-profile-v1.json index 393dde9fd..f810e98ef 100644 --- a/contracts/schemas/profiles/backend-profile-v1.json +++ b/contracts/schemas/profiles/backend-profile-v1.json @@ -16,6 +16,8 @@ "backend-operation-capabilities-v1", "backend-operation-control-v1", "backend-operation-response-v1", + "mixed-backend-execution-binding-v1", + "mixed-backend-stage-report-v1", "backend-materialization-attestation-v1", "backend-augmentation-scope-v1", "plan-realization-profiles-v1", diff --git a/docs/explain/reference/mixed-participant-composition.md b/docs/explain/reference/mixed-participant-composition.md index 735d685cb..187f9006d 100644 --- a/docs/explain/reference/mixed-participant-composition.md +++ b/docs/explain/reference/mixed-participant-composition.md @@ -161,6 +161,34 @@ they are not conformance evidence for a deployed apparatus. Linked inter-trial identity remains covered by the admitted-trial tests and never becomes a within-run fallback. +## Published execution and readback contracts + +Issue #1371 publishes a portable form of the trusted executable inputs above. +A [`mixed-backend-execution-binding-v1`](../../../contracts/schemas/control-plane/mixed-backend-execution-binding-v1.json) +record pins one edge bridge or native transfer service, its time coordinator +and its readers to one admitted edge or component-changing transition. Each +role is a distinct service. An edge binding preserves the compiled action +address and names the destination provider's action allocation as the effect +owner. A +[`mixed-backend-stage-report-v1`](../../../contracts/schemas/control-plane/mixed-backend-stage-report-v1.json) +record carries one time-grant, execution, delivery, observation, handoff or +owner-readback fact. Each report belongs to one invocation of the shared +[backend operation protocol](backend-operation-supervision.md). + +Pure validators join bindings to the sealed profile, requests to shared +contextual admission, and stage reports to the response transcript and to the +caller's committed time and composition readbacks. Each stage must name the +service pinned for its role. A proposed success or known failure must equal +the state that the published stage and settlement model establishes; that +model governs the carriers, not the coordinator above. Optional +`raes_backend_protocols` interfaces describe bridges, time coordinators and +stage readers; method presence and contract declarations are not effective +support. The coordinator above does not read these carriers. It still executes +its in-process bindings, and no runtime adoption is claimed. The +[migration note](../../migration/mixed-backend-execution.md) records producer +and reader obligations, the stage and settlement model, compatibility, +examples and limits. + ## Four worked realizations | Case | Allocation and transition | Expected meaning and evidence boundary | diff --git a/docs/migration/README.md b/docs/migration/README.md index e7795af52..3a32669ac 100644 --- a/docs/migration/README.md +++ b/docs/migration/README.md @@ -29,6 +29,10 @@ The fail-closed adoption of coherent backend capture offers and content-backed evidence satisfaction is documented in [Required Capture Admission Migration](required-capture-admission.md). +Producer and reader obligations for the published mixed-backend execution +binding and stage-report contracts are documented in +[Mixed-Backend Execution Contracts Migration](mixed-backend-execution.md). + The reorganization moved existing material into the current long-term buckets: - root `schemas/` -> `contracts/schemas/` diff --git a/docs/migration/mixed-backend-execution.md b/docs/migration/mixed-backend-execution.md new file mode 100644 index 000000000..199a8c224 --- /dev/null +++ b/docs/migration/mixed-backend-execution.md @@ -0,0 +1,277 @@ +# Mixed-backend execution contracts migration + +Issue #1371 publishes portable contracts for the executable mixed-backend +obligations that +[ADR-102](../decisions/adrs/adr-102-mixed-cross-backend-participant-control.md) +section 13 adopted for issue #1355. The +[issue #1355 preflight](../decisions/issue-1355-executable-mixed-mapping-time-preflight.md) +is architecture guidance for that amendment, not a normative decision. The +two contracts are: + +- [`mixed-backend-execution-binding-v1`](../../contracts/schemas/control-plane/mixed-backend-execution-binding-v1.json) + is the plain-data form of one installed bridge, time coordinator and set of + readers for one admitted `sem-234/rev1` edge or native handoff. +- [`mixed-backend-stage-report-v1`](../../contracts/schemas/control-plane/mixed-backend-stage-report-v1.json) + carries one correlated stage fact for one invocation of the shared + [backend operation protocol](../../specs/formal/runtime-contracts/backend-operation-supervision.md). + +This note defines producer and reader obligations. It is not a migrator. +Publication changes no runtime behavior: the reference coordinator described in +[mixed participant composition](../explain/reference/mixed-participant-composition.md) +still executes its in-process `MixedEdgeExecutionBinding` and +`MixedHandoffBinding`. No runtime, store or HTTP path reads or writes the new +carriers, and no executable or runtime adoption is claimed. + +## Execution bindings + +A binding names its sealed profile by `profile_id`, `profile_revision` and +`profile_digest`. Its `subject` is either an `edge` or a `handoff`: + +- An edge binding fixes the operation kind to `participant-crossing`. It names + the destination provider as `owner_component_id` and its action allocation as + `owner_allocation_id`. It also carries the participant and audience of the + edge's crossing subject, the source and destination action addresses, and the + pinned bridge. The only subject transformation is `compiled-identity`, so both + action addresses must be equal. Native translation stays inside the pinned + bridge. Owning the effect confers no controller, disclosure or terminal-commit + authority. +- A handoff binding fixes the operation kind to `composition-phase`. It names + the leaving and joining components, their native ownership references, the + pinned transfer service and the native owner reader. + +Both kinds carry a time requirement: the time model reference and digest, the +source and destination clocks, the clock mapping, a governed ordering basis and +the pinned coordinator. The required comparison is always `ordered`. +`wall_clock_only`, `unknown` and `unsupported` bases cannot be expressed. An +edge's time requirement also carries the admitted edge's `temporal_coupling`: +`tight`, `bounded-asynchronous` or `asynchronous`. A transition declares no +coupling, so a handoff carries none. An edge binding also carries the declared +mapping loss, a delivery reader, an optional observation reader and the edge's +evidence references. + +Services are pinned by `service_ref`, `version` and `digest`. A service +reference is an identity, never a module, path, URL, command or credential. +Each role has its own service: within one binding, no two of the bridge or +transfer service, the coordinator and the readers share a `service_ref` or a +`digest`. A binding that pins one service to two roles is invalid. Decoding a +binding installs nothing, selects no provider and grants no authority. + +## Stage reports + +Each report repeats the exact `binding` of one shared operation invocation +and the canonical digest of its request. Its `stage` is one of the kinds +below. Its `sequence` is fixed by that stage: the stage's position in its +chain, as the table shows. Each producer therefore numbers its own report +without seeing the other reports. This differs from the shared protocol's +response sequence, which one backend assigns in order. Every stage names its +`producer`, which must equal the service that the binding pins for that +stage: + +| Stage | Sequence | Producer | Fact it reports | +| --- | --- | --- | --- | +| `time-grant` | 1 | `time.coordinator` | Grant at the committed coordinates of both bound clocks: mapping, ordering basis, order reference, comparison, both coordinates and the mapping and timing evidence. | +| `execution` | 2 | `bridge` | Bridge execution with status `succeeded`, `failed`, `partial` or `unknown`. Known effects need readback evidence. A known failure needs cessation evidence. | +| `delivery` | 3 | `delivery_reader` | Destination receipt read back by the delivery reader, not by the bridge. | +| `observation` | 4 | `observation_reader` | Participant and audience readback after delivery. A binding without an observation reader admits no observation stage. | +| `handoff` | 2 | `transfer` | Native transfer disposition at the committed composition history head and phase revision. | +| `owner-readback` | 3 | `owner_reader` | Native responsibility owner read back after the transfer attempt. | + +Execution, delivery and observation are separate facts. One success value +cannot create another stage, and partial or unknown execution keeps its own +status. The reports are evidence proposals. A reader must validate them as +described below, and only RAES may commit operation state, composition history +and terminal outcomes. + +## Digests + +The binding reference digest and each stage-report citation digest are SHA-256 +over RFC 8785 canonical JSON of the complete validated model, including +materialized defaults and null values, with array order preserved. A digest is +written as `sha256:` followed by 64 lowercase hexadecimal digits. The reference +encoders are `mixed_backend_binding_reference()` and +`canonical_json_digest(report.model_dump(mode="json"))`. The request digest +follows the backend operation protocol's own rule. + +## Producer obligations + +- An edge bridge or native transfer service implements both the shared + `BackendOperationProvider` protocol and `MixedBackendBridge`. A coordinator + implements `MixedTimeCoordinator`, and a reader implements `MixedStageReader`. + These protocols live in `raes_backend_protocols.mixed_backend`. + `require_mixed_backend_service()` checks the declaration and installed call + shapes without invoking code. +- A service declares both contract IDs in `supported_contract_versions`. A + bridge also declares the four backend operation contracts. The declaration is + opt-in and is not effective support; it adds no API-407 feature term or + support level. +- A shared request commits to one binding. Its `command` is the reference + returned by `mixed_backend_binding_reference()`. Its `backend_id` names the + pinned bridge or transfer service, and its operation kind matches the binding. +- Each stage report names the producing service exactly as the binding pins + it. Because every role has its own service, a bridge never reports a time + grant, delivery or observation. A transfer service never reports a time + grant or its own owner readback. +- A coordinator grants over the committed time readback that it receives, and + both coordinates in its grant equal that readback. It reports `ordered` only + when the mapped source coordinate does not pass the destination coordinate + within one segment. Otherwise it reports `incomparable`. +- A transfer service names the committed composition history head and phase + revision that it acted on. +- A service reports each stage at most once per invocation, under the + stage's fixed `sequence` from the table above. A retransmitted report + carries identical content. A transcript that holds a stage must also hold + its prerequisite stage. Readers accept reports in ascending `sequence`, so + the order in which reports arrive does not matter. Execution and native + transfer reports need an `ordered` grant and an accepted acknowledgement, + so no invocation stage follows a refusal or an `incomparable` grant. +- A proposed shared outcome may claim success or known failure only when the + stage and settlement model below establishes it. Shared evidence may cite + only stage reports that the invocation supplied. + +## Reader obligations + +Readers resolve the sealed profile, resolution context, time-model declaration, +shared transcript and their own time and composition readbacks through their +owning authorities. They then call these pure validators from +`raes_contracts.contracts`: + +1. `validate_mixed_backend_bindings()` requires exactly one matching binding + for each edge active in an admitted phase. It requires one binding for each + transition that replaces exactly one component with another. It refuses + missing, foreign, duplicate or contradictory bindings, including an edge + binding whose temporal coupling differs from the admitted edge. It also + refuses an edge with an ungoverned order and a transition that changes + components in any other way. Alternative profiles admit no binding. +2. `require_mixed_backend_admission()` joins the request to the binding, then + applies the shared capability and exact-context willingness checks before + any invocation. +3. `validate_mixed_backend_stage_reports()` checks one invocation's reports + against the binding, the request and its response transcript. Its + `context` argument is a `MixedBackendStageContext` that holds these trusted + inputs: + - `time_model`: the declaration resolved from the binding's time + requirement. + - `time_model_ref` and `time_model_digest`: the reference and digest that + the caller resolved `time_model` under. They must equal the binding's + time requirement. + - `time_state`: the committed time readback that the coordinator received. + It must validate against `time_model` and cover both bound clocks. + - `post_time_state`: RAES's own time readback after the invocation, or + `None` when none was taken. When present, it must validate against + `time_model`. + - `composition_state`: the committed composition state of the invocation's + run and binding's profile. Its `run_id` is the unprefixed run identity; + the request's `run_scope` must equal `run:`. A handoff requires it. + When present, it must still activate a + bound edge. For a handoff, its active components must include the source + component and exclude the destination component. + +## Stage and settlement model + +The stage validator enforces this abstract model for one invocation. The rules +apply to the published carriers only. They do not describe the in-process +coordinator, which does not read the carriers. + +**State.** The record holds the accepted stage reports, at most one of each +kind. It also records whether the response transcript holds an accepted +acknowledgement and whether time is confirmed. Time is confirmed when +`post_time_state` is present and neither bound clock coordinate in it is lower +than in `time_state`. Coordinates compare by segment, then tick, then +microstep. + +**Preconditions.** Before any report is accepted, the trusted inputs must +match the binding. `time_model_ref` and `time_model_digest` equal its time +requirement, and `time_state` covers both bound clocks. A `composition_state` +belongs to the request's run and its profile, and it activates the bound edge or precedes the bound +handoff as described above. + +**Transitions.** Reports are accepted in ascending `sequence`, which is chain +order, whatever order they are supplied in. A report is accepted only when its +`sequence` is its stage's position from the stage report table, its +prerequisite was accepted before it and its joins hold: + +| Stage | Prerequisite | Joins | +| --- | --- | --- | +| `time-grant` | None | Both coordinates equal `time_state`. Mapping and ordering basis equal the binding. The grant cites the admitted evidence. An `ordered` grant has the mapped order within one segment. | +| `execution` | `ordered` grant and accepted acknowledgement | Action addresses and declared loss equal the binding. | +| `delivery` | Execution that did not fail | The destination component is the destination provider. | +| `observation` | Delivery | Participant and audience equal the binding. | +| `handoff` | `ordered` grant and accepted acknowledgement | The order reference equals the grant. History head and phase revision equal `composition_state`. The report cites the admitted evidence. | +| `owner-readback` | Handoff | None beyond the producer. A readback naming neither owner stays a valid, contradictory fact. | + +Every report must also name the pinned producer for its stage and repeat the +invocation binding and request digest. A repeated sequence number must carry +identical content, and a transcript holds at most 64 reports. + +**Settlement.** The accepted stages establish exactly one state: + +| Kind | Established state | Condition | +| --- | --- | --- | +| Edge | `SUCCEEDED` | `succeeded` execution, delivery and confirmed time. | +| Edge | `FAILED` | `failed` execution, or an `incomparable` grant with no execution stage. | +| Handoff | `SUCCEEDED` | `committed` transfer, an owner readback naming the destination owner at the committed revision plus one, and confirmed time. | +| Handoff | `FAILED` | `failed` or `stale` transfer, an owner readback naming the source owner at the committed revision, and confirmed time. An `incomparable` grant with no handoff stage also establishes `FAILED`. | +| Either | `INDETERMINATE` | Every other combination. | + +**Observation rules.** A proposed `SUCCEEDED` or `FAILED` outcome must equal the +established state. A `CANCELLED` or `INDETERMINATE` proposal is checked only by +the shared protocol's own rules. Only an explicit `incomparable` grant shows +that no invocation could start. An `ordered` grant without an invocation stage, +or no grant at all, establishes no failure, because an unreported invocation +may have started. + +**Invariants.** No invocation stage follows a refusal or an `incomparable` +grant. No stage is accepted from a service other than its pinned producer, and +no service holds two roles in one binding. A success never rests on a +backend's own time or composition claims. It needs the committed and +post-invocation time readbacks, and a handoff also needs the committed +composition state. A violated join refuses the whole transcript instead of +settling it. + +## Compatibility + +Both contracts are new IDs with draft stability under ADR-061. The +`supported_contract_versions` enums of `backend-manifest-v2` and +`backend-profile-v1` gain the two IDs. Existing manifests and profiles remain +valid. The stub and reference backends do not declare the new IDs. + +The meaning of a published `sem-234/rev1` profile is unchanged. Historical +reference-only records stay reference-only: no reader may reinterpret their +`success`, mapping references or timestamps as delivery, observation or +governed timing evidence. The in-process runtime bindings and the published +carriers are not converted into one another. The binding has no field for +callables, module paths, URLs, commands, credentials or open metadata. + +## Examples + +The corpus under `contracts/fixtures/control-plane/` carries six transcripts. +Each one has a request, its responses and its stage reports: + +| Example | Meaning | +| --- | --- | +| `mixed-edge` | Ordered grant, succeeded execution, destination delivery and participant observation; the shared outcome succeeds. | +| `mixed-edge-partial` | Partial execution after an ordered grant; the shared outcome is `INDETERMINATE`. | +| `mixed-edge-refused` | Contextual refusal at admission; no invocation stage can follow. | +| `mixed-edge-time-refused` | The destination clock has entered a later segment, so the grant is `incomparable`. The bridge accepts the start but reports no execution stage, and it proposes a known failure with no effect. | +| `mixed-handoff` | Committed native transfer with a destination owner readback at the next phase revision. | +| `mixed-handoff-stale` | Stale transfer whose readback retains the source owner; the shared outcome is a known failure with no effect. | + +Each new contract also has `invalid/` and `context-invalid/` examples. The +binding's `bridge-as-reader` and `transfer-as-owner-reader` examples are +invalid because they pin one service to two roles. Run the focused checks from +the repository root with +`uv run --project implementations/python --frozen --all-extras python -m pytest implementations/python/tests/test_issue_1371_mixed_backend_contracts.py -q`. + +## Limits + +The validators perform no I/O, dispatch or state mutation. Passing them proves +neither backend truth nor installation, conformance or runtime authority. They +compare the producer that each report names with the binding. The caller must +authenticate that a report came from that service. The binding model refuses +one service reference or digest in two roles, but whether two distinct +services are operationally independent is a deployment property that no +validator can prove. + +These contracts add no generic federation framework, HLA, FMI or HELICS +support, common clock or physical-OT timing guarantee. They also add no +exactly-once effects, multi-controller authority or backend equivalence. diff --git a/docs/public/api/contracts.rst b/docs/public/api/contracts.rst index 7f255bb2f..10e254fde 100644 --- a/docs/public/api/contracts.rst +++ b/docs/public/api/contracts.rst @@ -60,6 +60,28 @@ constraints. The provenance record preserves the participant implementation, selected manifest, selected configuration reference, participant contract versions, and decision-surface exposure policy used in a run. +Mixed-backend execution and readback +------------------------------------ + +Optional bindings and stage reports for one admitted mixed edge or native +handoff, exchanged through the backend operation protocol below. They grant no +authority, and the shared runtime does not read them. + +.. automodule:: raes_contracts.contracts.mixed_backend_binding + :members: + +.. automodule:: raes_contracts.contracts.mixed_backend_stages + :members: + +.. automodule:: raes_contracts.contracts.mixed_backend_validation + :members: + +.. automodule:: raes_contracts.contracts.mixed_backend_transcript + :members: + +.. automodule:: raes_backend_protocols.mixed_backend + :members: + Backend operation supervision ----------------------------- diff --git a/docs/public/backends.md b/docs/public/backends.md index e0ed7a422..eb6442ab1 100644 --- a/docs/public/backends.md +++ b/docs/public/backends.md @@ -28,3 +28,9 @@ cancellation and effect reports for backend authors. Read the [protocol and migration guide](https://github.com/OpenRAE/rae/blob/main/docs/explain/reference/backend-operation-supervision.md). These contracts keep unknown effects explicit. Publishing them does not certify that a backend can interrupt work or recover after a failure. + +Mixed-backend bridges, time services and readers can describe one admitted edge +or handoff with the execution binding and stage report contracts. Read the +[mixed-backend migration note](https://github.com/OpenRAE/rae/blob/main/docs/migration/mixed-backend-execution.md). +These reports keep execution, delivery and observation apart. Declaring the +contracts does not prove support, and the runtime does not read them. diff --git a/docs/research/formal-semantic-validation/analysis-v73.json b/docs/research/formal-semantic-validation/analysis-v73.json new file mode 100644 index 000000000..38e3071ad --- /dev/null +++ b/docs/research/formal-semantic-validation/analysis-v73.json @@ -0,0 +1,164 @@ +{ + "analysis_id": "issue-1371-sync-analysis-v73", + "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-v73.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-1371-sync-execution-v73", + "generated_at": "2026-10-11T19:24:50.695662+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.", + "Issue #1361 execution and recovery requirements are verified by dedicated policy, composition, and admission tests; this retained corpus establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 maintainability repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 resource type-hint repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The combined issue #1361 execution-policy and hatchling update preserves retained outcomes and bounded claims; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1418 runtime-fact export manifest split changes no contract, schema or behavior and adds no new formal-semantic claim.", + "This synchronization adds no mixed-backend runtime execution claim; the issue #1371 tests cover the composition run-scope join." + ], + "plain_language_outcome": "The retained formal controls reproduce their prior outcomes after merging the runtime-fact export manifest split with the mixed-backend contracts and composition run-scope repair. Bounded claim limits are unchanged.", + "protocol_revision": "2.0.0" +} diff --git a/docs/research/formal-semantic-validation/bundles/retest-v73.json b/docs/research/formal-semantic-validation/bundles/retest-v73.json new file mode 100644 index 000000000..c01b50eb6 --- /dev/null +++ b/docs/research/formal-semantic-validation/bundles/retest-v73.json @@ -0,0 +1,122 @@ +{ + "analysis_path": "docs/research/formal-semantic-validation/analysis-v73.json", + "analysis_sha256": "cfa0d5ddf268bd30ef5e3ad8cfcfbc5a36132b258fa0cb513380d366932d219e", + "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": "73.0.0", + "snapshot_path": "docs/research/formal-semantic-validation/execution-snapshot-v73.json", + "snapshot_sha256": "df5838ef00fe352cf4ec0932d3bea4eacfe9d6e0e76db75906e98e5ab67db02b" +} diff --git a/docs/research/formal-semantic-validation/execution-snapshot-v73.json b/docs/research/formal-semantic-validation/execution-snapshot-v73.json new file mode 100644 index 000000000..33643802f --- /dev/null +++ b/docs/research/formal-semantic-validation/execution-snapshot-v73.json @@ -0,0 +1,652 @@ +{ + "baseline": { + "execution_id": "issue-1418-execution-v72", + "release_path": "docs/research/formal-semantic-validation/bundles/retest-v72.json", + "release_revision": "72.0.0", + "release_sha256": "6a4b9d510e4d1c98f45cf0275cee2563bbdbaa432914694d86e4a4fdf96a06ed" + }, + "captured_at": "2026-10-11T19:24:50.695662+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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "limitations": [ + "The witness ends at compiled output." + ], + "replayable": true, + "result_digest": "d7c098c5d063b8d1b0747e8df5daa90061456065cdda0bbedfa10918442f5daa", + "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-1371-sync-execution-v73", + "limitations": [ + "Distinct digests are a non-vacuity control, not semantic non-equivalence proof." + ], + "replayable": true, + "result_digest": "a2fcebba3341592b133af813e8bb8e5f47270418bc58bfd471a89bfbc8ba46da", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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-1371-sync-execution-v73", + "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": "dabaf7c76e8b297a271a37dcd31d5947e9641413", + "source_state": { + "base_revision": "dabaf7c76e8b297a271a37dcd31d5947e9641413", + "checkout_state": "modified", + "implementation_digest": "25d03497c992a1079103325e50a36de2b16868efb4a7ddc33db82530c643679d", + "profile": "python-reference-source/v2" + }, + "versions": { + "python": "3.13.13", + "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 a8fc612cd..0090f4267 100644 --- a/docs/research/formal-semantic-validation/index.md +++ b/docs/research/formal-semantic-validation/index.md @@ -606,3 +606,15 @@ runtime-fact export manifest split in [`execution-snapshot-v72.json`](execution-snapshot-v72.json) and [`analysis-v72.json`](analysis-v72.json). Outcomes and claim limits remain unchanged. + +The issue #1371 captures that reused published release identities are preserved +in the [initial publication archive](../mixed-backend-pre-sync-evidence/README.md) +and [run-scope repair archive](../mixed-backend-run-scope-pre-sync-evidence/README.md), +with exact bytes and digests. The incoming published release history remains canonical. + +Release 73.0.0 replays the retained controls after merging the issue #1418 +runtime-fact export manifest split with the issue #1371 mixed-backend contracts +and composition run-scope repair in +[`execution-snapshot-v73.json`](execution-snapshot-v73.json) and +[`analysis-v73.json`](analysis-v73.json). Outcomes and bounded claim +limits remain unchanged; this retained corpus makes no new mixed-runtime execution claim. diff --git a/docs/research/mixed-backend-pre-sync-evidence/README.md b/docs/research/mixed-backend-pre-sync-evidence/README.md new file mode 100644 index 000000000..58c89e08a --- /dev/null +++ b/docs/research/mixed-backend-pre-sync-evidence/README.md @@ -0,0 +1,16 @@ +# Issue 1371 pre-synchronization captures + +These are byte-for-byte copies of the captures published on issue 1371 before +merging `dev` at `353ccffeaf07fe084485fba86f1029450d7608ad`. Formal release 70 and +specification release 69 collided with releases already published on `dev`. +The incoming published releases retain their canonical paths and version +selection rules. + +The [records](records.json) pin each archived file to its original path, digest +and immutable source revision. Paths embedded in these archival documents refer +to that source revision. These are historical records outside the active indexes. +No observation or prior capture byte has been discarded or relabeled. + +The subsequent formal release 72 and specification release 71 captures from +the composition run-scope repair are also [preserved with exact digests](../mixed-backend-run-scope-pre-sync-evidence/README.md) +after their identities collided with the issue #1418 integration releases. diff --git a/docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/analysis-v70.json b/docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/analysis-v70.json new file mode 100644 index 000000000..48084d917 --- /dev/null +++ b/docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/analysis-v70.json @@ -0,0 +1,163 @@ +{ + "analysis_id": "issue-1371-analysis-v70", + "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-v70.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-1371-execution-v70", + "generated_at": "2026-10-10T12:46:40.722206+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.", + "Issue #1361 execution and recovery requirements are verified by dedicated policy, composition, and admission tests; this retained corpus establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 maintainability repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 resource type-hint repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The combined issue #1361 execution-policy and hatchling update preserves retained outcomes and bounded claims; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "Issue #1371 publishes mixed-backend execution binding and stage-report contracts whose pure validators are covered by their dedicated contract suite; this retained corpus makes no new execution, interoperability or runtime adoption claim." + ], + "plain_language_outcome": "The retained formal cases reproduce their prior outcomes after issue #1371 published the mixed-backend execution binding and stage-report contracts with their pure validators. The bounded claims and unsupported classes are unchanged.", + "protocol_revision": "2.0.0" +} diff --git a/docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/bundles/retest-v70.json b/docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/bundles/retest-v70.json new file mode 100644 index 000000000..28284a004 --- /dev/null +++ b/docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/bundles/retest-v70.json @@ -0,0 +1,122 @@ +{ + "analysis_path": "docs/research/formal-semantic-validation/analysis-v70.json", + "analysis_sha256": "7fed1f53201e99d8d190deb20a150377632e848ba00fc7b87c77beef90d06b9a", + "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": "70.0.0", + "snapshot_path": "docs/research/formal-semantic-validation/execution-snapshot-v70.json", + "snapshot_sha256": "eae136a94f1c88908733475bcd9f8e2a0dc03a7d8dbc8aaec7c83df86957c401" +} diff --git a/docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/execution-snapshot-v70.json b/docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/execution-snapshot-v70.json new file mode 100644 index 000000000..2ea4a1cca --- /dev/null +++ b/docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/execution-snapshot-v70.json @@ -0,0 +1,652 @@ +{ + "baseline": { + "execution_id": "issue-1361-merged-execution-v69", + "release_path": "docs/research/formal-semantic-validation/bundles/retest-v69.json", + "release_revision": "69.0.0", + "release_sha256": "c9db66ba3abc167274b7c555d3a8ccc189155bc9e70647c144c81f0c18d99e6f" + }, + "captured_at": "2026-10-10T12:46:40.722206+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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "limitations": [ + "The witness ends at compiled output." + ], + "replayable": true, + "result_digest": "647a3e7436e9f5ec0529c206cb0f3eef46c4fcda8886227b55626372950ef177", + "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-1371-execution-v70", + "limitations": [ + "Distinct digests are a non-vacuity control, not semantic non-equivalence proof." + ], + "replayable": true, + "result_digest": "59f1443f868b170ad0552706f4e76436bee678a0acd842e7e72473f2a5ef5635", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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-1371-execution-v70", + "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": "1c42b7300d511434c81f1344fc600a11773d72c0", + "source_state": { + "base_revision": "1c42b7300d511434c81f1344fc600a11773d72c0", + "checkout_state": "modified", + "implementation_digest": "4eaf260fe51d511a4b43243ae1a927ce51e0dab34d99ca4a987bfad20d82b9f8", + "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/mixed-backend-pre-sync-evidence/records.json b/docs/research/mixed-backend-pre-sync-evidence/records.json new file mode 100644 index 000000000..5d97a1bac --- /dev/null +++ b/docs/research/mixed-backend-pre-sync-evidence/records.json @@ -0,0 +1,35 @@ +{ + "records": [ + { + "archive_path": "docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/execution-snapshot-v70.json", + "original_path": "docs/research/formal-semantic-validation/execution-snapshot-v70.json", + "sha256": "eae136a94f1c88908733475bcd9f8e2a0dc03a7d8dbc8aaec7c83df86957c401" + }, + { + "archive_path": "docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/analysis-v70.json", + "original_path": "docs/research/formal-semantic-validation/analysis-v70.json", + "sha256": "7fed1f53201e99d8d190deb20a150377632e848ba00fc7b87c77beef90d06b9a" + }, + { + "archive_path": "docs/research/mixed-backend-pre-sync-evidence/formal-semantic-validation/bundles/retest-v70.json", + "original_path": "docs/research/formal-semantic-validation/bundles/retest-v70.json", + "sha256": "fe50dc5abe2f480ff30c1e22c3948ceef71b82f68b09aed5d4279bb86a8f051c" + }, + { + "archive_path": "docs/research/mixed-backend-pre-sync-evidence/specification-coverage/execution-snapshot-v69.json", + "original_path": "docs/research/specification-coverage/execution-snapshot-v69.json", + "sha256": "08fb1b2220171bde3ed17efa44de02425db48dd509220bdfe5cf446d360d8b7c" + }, + { + "archive_path": "docs/research/mixed-backend-pre-sync-evidence/specification-coverage/analysis-v69.json", + "original_path": "docs/research/specification-coverage/analysis-v69.json", + "sha256": "124572da126674932525434fd28feaff1d3732acddd6f52d1a21b2cebffe8ecd" + }, + { + "archive_path": "docs/research/mixed-backend-pre-sync-evidence/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-v69.json", + "original_path": "docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-v69.json", + "sha256": "54c15ae112674aabcb5af72bb34cb5144c93d21e46e35d3156092ba01caf875e" + } + ], + "source_revision": "34fe98d9016737c1f3f89b43fc6d99fc7973b40e" +} diff --git a/docs/research/mixed-backend-pre-sync-evidence/specification-coverage/analysis-v69.json b/docs/research/mixed-backend-pre-sync-evidence/specification-coverage/analysis-v69.json new file mode 100644 index 000000000..5a1425422 --- /dev/null +++ b/docs/research/mixed-backend-pre-sync-evidence/specification-coverage/analysis-v69.json @@ -0,0 +1,112 @@ +{ + "analysis_id": "raes-standardized-specification-coverage-issue-1371-v69", + "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-v69.json", + "docs/research/specification-coverage/analysis-v69.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-10-10T12:46:40.722206+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.", + "Issue #1361 execution and recovery requirements are verified by dedicated policy, composition, and admission tests; this retained corpus establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 maintainability repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 resource type-hint repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The combined issue #1361 execution-policy and hatchling update preserves retained outcomes and bounded claims; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "Issue #1371 publishes mixed-backend execution binding and stage-report contracts whose pure validators are covered by their dedicated contract suite; this retained corpus makes no new execution, interoperability or runtime adoption claim." + ], + "load_bearing_results": { + "failed": 0, + "missing": 0, + "passed": 10, + "total": 10 + }, + "plain_language_outcome": "The retained specification-coverage matrix reproduces its prior classifications after issue #1371 published the mixed-backend execution binding and stage-report contracts with their pure validators; 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-1371-v69", + "snapshot_sha256": "204b38d880cf41208c01a3d4c47e31b6b2dc3415e78e6f24b5cf43a27107d3a8" +} diff --git a/docs/research/mixed-backend-pre-sync-evidence/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-v69.json b/docs/research/mixed-backend-pre-sync-evidence/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-v69.json new file mode 100644 index 000000000..27dd141ea --- /dev/null +++ b/docs/research/mixed-backend-pre-sync-evidence/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-v69.json @@ -0,0 +1,10 @@ +{ + "analysis_path": "docs/research/specification-coverage/analysis-v69.json", + "analysis_sha256": "124572da126674932525434fd28feaff1d3732acddd6f52d1a21b2cebffe8ecd", + "bundle_id": "raes-standardized-specification-coverage", + "protocol_path": "docs/research/specification-coverage/protocol-v1.json", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "revision": "69.0.0", + "snapshot_path": "docs/research/specification-coverage/execution-snapshot-v69.json", + "snapshot_sha256": "08fb1b2220171bde3ed17efa44de02425db48dd509220bdfe5cf446d360d8b7c" +} diff --git a/docs/research/mixed-backend-pre-sync-evidence/specification-coverage/execution-snapshot-v69.json b/docs/research/mixed-backend-pre-sync-evidence/specification-coverage/execution-snapshot-v69.json new file mode 100644 index 000000000..cab480bfd --- /dev/null +++ b/docs/research/mixed-backend-pre-sync-evidence/specification-coverage/execution-snapshot-v69.json @@ -0,0 +1,704 @@ +{ + "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-10-10T12:46:40.722206+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": "680d9d082ffc92a7334d4dbd27c281768038ba79129bab7c682997d35febf1fc", + "path": "implementations/python/packages/raes_contracts", + "surface_id": "contract-models" + }, + { + "content_sha256": "d6d298174122a1eb1b6602088163fc0304c6f55cf10c63abca2476a3030c42ae", + "path": "implementations/python/packages/raes_processor", + "surface_id": "processor-pipeline" + }, + { + "content_sha256": "dad5f52580ffdc1a9110be65fa96ee6c8179e9541c748675873440643df5a03b", + "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.", + "Issue #1361 execution and recovery requirements are verified by dedicated policy, composition, and admission tests; this retained corpus establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 maintainability repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 resource type-hint repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The combined issue #1361 execution-policy and hatchling update preserves retained outcomes and bounded claims; it establishes no live recovery, continuation, or trial-allocation guarantee." + ], + "protocol_revision": "1.0.0", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "raes_revision": "1c42b7300d511434c81f1344fc600a11773d72c0", + "snapshot_id": "raes-standardized-specification-coverage-issue-1371-v69", + "snapshot_revision": "69.0.0", + "source_state": { + "base_revision": "1c42b7300d511434c81f1344fc600a11773d72c0", + "checkout_state": "modified", + "implementation_digest": "4eaf260fe51d511a4b43243ae1a927ce51e0dab34d99ca4a987bfad20d82b9f8", + "profile": "python-reference-source/v2" + } +} diff --git a/docs/research/mixed-backend-run-scope-pre-sync-evidence/README.md b/docs/research/mixed-backend-run-scope-pre-sync-evidence/README.md new file mode 100644 index 000000000..c3ebe94aa --- /dev/null +++ b/docs/research/mixed-backend-run-scope-pre-sync-evidence/README.md @@ -0,0 +1,15 @@ +# Issue 1371 run-scope repair pre-synchronization captures + +These are byte-for-byte copies of the captures published with the issue #1371 +composition run-scope repair before merging `dev` at +`5d78a429ba9030f288db4527623f3b50bb2f53fd`. Formal release 72 and specification +release 71 collided with the issue #1418 releases already published on `dev`. +The incoming published releases retain their canonical paths. + +The [records](records.json) pin every archived file to its original path, digest +and immutable source revision. Embedded paths refer to that source revision. +These historical records are outside the active indexes; no capture byte or +observation has been discarded or relabeled. + +Formal release 73 and specification release 72 replay the synchronized source. +Retained outcomes, classifications and bounded claim limits remain unchanged. diff --git a/docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/analysis-v72.json b/docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/analysis-v72.json new file mode 100644 index 000000000..5a2bd51ce --- /dev/null +++ b/docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/analysis-v72.json @@ -0,0 +1,163 @@ +{ + "analysis_id": "issue-1371-run-scope-analysis-v72", + "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-v72.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-1371-run-scope-execution-v72", + "generated_at": "2026-10-11T18:05:47.960607+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.", + "Issue #1361 execution and recovery requirements are verified by dedicated policy, composition, and admission tests; this retained corpus establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 maintainability repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 resource type-hint repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The combined issue #1361 execution-policy and hatchling update preserves retained outcomes and bounded claims; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "Mixed-backend composition run-scope joins are covered by the issue #1371 regression tests, not a new formal claim in this retained corpus." + ], + "plain_language_outcome": "The retained formal controls reproduce their prior outcomes after integration and the mixed-backend composition run-scope repair. Bounded claim limits are unchanged.", + "protocol_revision": "2.0.0" +} diff --git a/docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/bundles/retest-v72.json b/docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/bundles/retest-v72.json new file mode 100644 index 000000000..c5c28434c --- /dev/null +++ b/docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/bundles/retest-v72.json @@ -0,0 +1,122 @@ +{ + "analysis_path": "docs/research/formal-semantic-validation/analysis-v72.json", + "analysis_sha256": "556c6ddace7bbb599f4f86254866a7eab3364be354f8ed54fc84bf2a06b398e8", + "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": "72.0.0", + "snapshot_path": "docs/research/formal-semantic-validation/execution-snapshot-v72.json", + "snapshot_sha256": "0c181d9c3ad0d3a59c4835ec3a0db62393979656421aa011ee739ca2772b2943" +} diff --git a/docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/execution-snapshot-v72.json b/docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/execution-snapshot-v72.json new file mode 100644 index 000000000..a6a9943a0 --- /dev/null +++ b/docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/execution-snapshot-v72.json @@ -0,0 +1,652 @@ +{ + "baseline": { + "execution_id": "issue-1481-sonar-execution-v71", + "release_path": "docs/research/formal-semantic-validation/bundles/retest-v71.json", + "release_revision": "71.0.0", + "release_sha256": "d0ea85a0d575a4387ee38cb18328e5f1dd4ecdcc017c157844a69a9d78efe592" + }, + "captured_at": "2026-10-11T18:05:47.960607+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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "limitations": [ + "The witness ends at compiled output." + ], + "replayable": true, + "result_digest": "d7c098c5d063b8d1b0747e8df5daa90061456065cdda0bbedfa10918442f5daa", + "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-1371-run-scope-execution-v72", + "limitations": [ + "Distinct digests are a non-vacuity control, not semantic non-equivalence proof." + ], + "replayable": true, + "result_digest": "a2fcebba3341592b133af813e8bb8e5f47270418bc58bfd471a89bfbc8ba46da", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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-1371-run-scope-execution-v72", + "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": "c57353d2472de5b55da3982cbc536008c2982b1e", + "source_state": { + "base_revision": "c57353d2472de5b55da3982cbc536008c2982b1e", + "checkout_state": "modified", + "implementation_digest": "6aa8b3ec88ea34713752f80fe20c4e27426883ab092a4cbcf35f9b95556350c7", + "profile": "python-reference-source/v2" + }, + "versions": { + "python": "3.13.13", + "raes": "5.0.0", + "z3_engine": "4.16.0", + "z3_solver": "4.16.0.0" + } +} diff --git a/docs/research/mixed-backend-run-scope-pre-sync-evidence/records.json b/docs/research/mixed-backend-run-scope-pre-sync-evidence/records.json new file mode 100644 index 000000000..c356f8ac1 --- /dev/null +++ b/docs/research/mixed-backend-run-scope-pre-sync-evidence/records.json @@ -0,0 +1,35 @@ +{ + "records": [ + { + "archive_path": "docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/execution-snapshot-v72.json", + "original_path": "docs/research/formal-semantic-validation/execution-snapshot-v72.json", + "sha256": "0c181d9c3ad0d3a59c4835ec3a0db62393979656421aa011ee739ca2772b2943" + }, + { + "archive_path": "docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/analysis-v72.json", + "original_path": "docs/research/formal-semantic-validation/analysis-v72.json", + "sha256": "556c6ddace7bbb599f4f86254866a7eab3364be354f8ed54fc84bf2a06b398e8" + }, + { + "archive_path": "docs/research/mixed-backend-run-scope-pre-sync-evidence/formal-semantic-validation/bundles/retest-v72.json", + "original_path": "docs/research/formal-semantic-validation/bundles/retest-v72.json", + "sha256": "86ea03a801eedada16acbac06184966809d638454b624a75f655817fe1fb68f4" + }, + { + "archive_path": "docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/execution-snapshot-v71.json", + "original_path": "docs/research/specification-coverage/execution-snapshot-v71.json", + "sha256": "c58c6e3e3c32fe2cabe1da50d7d6af618486218513703ea6567f82d277567265" + }, + { + "archive_path": "docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/analysis-v71.json", + "original_path": "docs/research/specification-coverage/analysis-v71.json", + "sha256": "d37da3491b72c8c57d0d72b202be5d3064e0d92ff37a805383a407dd9668d468" + }, + { + "archive_path": "docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-run-scope-v71.json", + "original_path": "docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-run-scope-v71.json", + "sha256": "c8e660f966e9dcb00990fd1ffca070003fcd30e0465f1ca6c71f90ec6ae2e71a" + } + ], + "source_revision": "d1fd761664dda76d49bb4c181d6b04cac7f8733a" +} diff --git a/docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/analysis-v71.json b/docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/analysis-v71.json new file mode 100644 index 000000000..e02c94dea --- /dev/null +++ b/docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/analysis-v71.json @@ -0,0 +1,112 @@ +{ + "analysis_id": "raes-standardized-specification-coverage-issue-1371-run-scope-analysis-v71", + "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-v71.json", + "docs/research/specification-coverage/analysis-v68.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-10-11T18:05:47.960607+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.", + "Issue #1361 execution and recovery requirements are verified by dedicated policy, composition, and admission tests; this retained corpus establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 maintainability repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 resource type-hint repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The combined issue #1361 execution-policy and hatchling update preserves retained outcomes and bounded claims; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "Mixed-backend composition run-scope joins are covered by the issue #1371 regression tests, not a new coverage claim in this retained matrix." + ], + "load_bearing_results": { + "failed": 0, + "missing": 0, + "passed": 10, + "total": 10 + }, + "plain_language_outcome": "The retained specification matrix preserves its prior classifications after integration and the mixed-backend composition run-scope repair. Bounded 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-1371-run-scope-v71", + "snapshot_sha256": "c51e281382cad8fe9ab3bb100208cf7e688711eacee5905da028e9611d218563" +} diff --git a/docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-run-scope-v71.json b/docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-run-scope-v71.json new file mode 100644 index 000000000..e3f458ac2 --- /dev/null +++ b/docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-run-scope-v71.json @@ -0,0 +1,10 @@ +{ + "analysis_path": "docs/research/specification-coverage/analysis-v71.json", + "analysis_sha256": "d37da3491b72c8c57d0d72b202be5d3064e0d92ff37a805383a407dd9668d468", + "bundle_id": "raes-standardized-specification-coverage", + "protocol_path": "docs/research/specification-coverage/protocol-v1.json", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "revision": "71.0.0", + "snapshot_path": "docs/research/specification-coverage/execution-snapshot-v71.json", + "snapshot_sha256": "c58c6e3e3c32fe2cabe1da50d7d6af618486218513703ea6567f82d277567265" +} diff --git a/docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/execution-snapshot-v71.json b/docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/execution-snapshot-v71.json new file mode 100644 index 000000000..433a42bdc --- /dev/null +++ b/docs/research/mixed-backend-run-scope-pre-sync-evidence/specification-coverage/execution-snapshot-v71.json @@ -0,0 +1,705 @@ +{ + "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-10-11T18:05:47.960607+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": "b64126d231558f22107bcc5e0e0fee87da692f50daa730b88388448e4647f1aa", + "path": "implementations/python/packages/raes_contracts", + "surface_id": "contract-models" + }, + { + "content_sha256": "e947f59695e907f5af899a6bc4bde60e629620aa7c4a69a41e074ba335758c7a", + "path": "implementations/python/packages/raes_processor", + "surface_id": "processor-pipeline" + }, + { + "content_sha256": "51688dbe152fb4bbeacd7f8443a3f1fbc7a09b1b898adb134be0e5b4edec28ab", + "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.", + "Issue #1361 execution and recovery requirements are verified by dedicated policy, composition, and admission tests; this retained corpus establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 maintainability repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 resource type-hint repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The combined issue #1361 execution-policy and hatchling update preserves retained outcomes and bounded claims; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "Mixed-backend composition run-scope joins are covered by the issue #1371 regression tests, not a new coverage claim in this retained matrix." + ], + "protocol_revision": "1.0.0", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "raes_revision": "c57353d2472de5b55da3982cbc536008c2982b1e", + "snapshot_id": "raes-standardized-specification-coverage-issue-1371-run-scope-v71", + "snapshot_revision": "71.0.0", + "source_state": { + "base_revision": "c57353d2472de5b55da3982cbc536008c2982b1e", + "checkout_state": "modified", + "implementation_digest": "6aa8b3ec88ea34713752f80fe20c4e27426883ab092a4cbcf35f9b95556350c7", + "profile": "python-reference-source/v2" + } +} diff --git a/docs/research/specification-coverage/analysis-v72.json b/docs/research/specification-coverage/analysis-v72.json new file mode 100644 index 000000000..91f07ded8 --- /dev/null +++ b/docs/research/specification-coverage/analysis-v72.json @@ -0,0 +1,113 @@ +{ + "analysis_id": "raes-standardized-specification-coverage-issue-1371-sync-analysis-v72", + "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-v72.json", + "docs/research/specification-coverage/analysis-v68.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-10-11T19:24:50.695662+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.", + "Issue #1361 execution and recovery requirements are verified by dedicated policy, composition, and admission tests; this retained corpus establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 maintainability repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 resource type-hint repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The combined issue #1361 execution-policy and hatchling update preserves retained outcomes and bounded claims; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1418 runtime-fact export manifest split changes no contract, schema or behavior; this retained matrix makes no new admission or coverage claim.", + "This synchronization adds no mixed-backend runtime execution claim; the issue #1371 tests cover the composition run-scope join." + ], + "load_bearing_results": { + "failed": 0, + "missing": 0, + "passed": 10, + "total": 10 + }, + "plain_language_outcome": "The retained specification matrix preserves its prior classifications after merging the runtime-fact export manifest split with the mixed-backend contracts and composition run-scope repair. Bounded 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-1371-sync-v72", + "snapshot_sha256": "e3e92557e7de81a436de657f224f2e865414d20ceb1639f04296f778dbaa962a" +} diff --git a/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-sync-v72.json b/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-sync-v72.json new file mode 100644 index 000000000..5aeeffbac --- /dev/null +++ b/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1371-sync-v72.json @@ -0,0 +1,10 @@ +{ + "analysis_path": "docs/research/specification-coverage/analysis-v72.json", + "analysis_sha256": "f53bcbed1935d0f94cabcab922a4eade389cf77ef214ddaca728429d8dc232c2", + "bundle_id": "raes-standardized-specification-coverage", + "protocol_path": "docs/research/specification-coverage/protocol-v1.json", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "revision": "72.0.0", + "snapshot_path": "docs/research/specification-coverage/execution-snapshot-v72.json", + "snapshot_sha256": "a3ffe14026c6b01ff0ea53118e99d45c5f5f0d01a0b6ecf09fd43cb76d58e952" +} diff --git a/docs/research/specification-coverage/execution-snapshot-v72.json b/docs/research/specification-coverage/execution-snapshot-v72.json new file mode 100644 index 000000000..8d07f8579 --- /dev/null +++ b/docs/research/specification-coverage/execution-snapshot-v72.json @@ -0,0 +1,705 @@ +{ + "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-10-11T19:24:50.695662+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": "701bd6ec60fe127e60bbd0dda48e01634206650d8aab67b2619b1bbc142d90ee", + "path": "implementations/python/packages/raes_contracts", + "surface_id": "contract-models" + }, + { + "content_sha256": "e947f59695e907f5af899a6bc4bde60e629620aa7c4a69a41e074ba335758c7a", + "path": "implementations/python/packages/raes_processor", + "surface_id": "processor-pipeline" + }, + { + "content_sha256": "51688dbe152fb4bbeacd7f8443a3f1fbc7a09b1b898adb134be0e5b4edec28ab", + "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.", + "Issue #1361 execution and recovery requirements are verified by dedicated policy, composition, and admission tests; this retained corpus establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 maintainability repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The issue #1361 resource type-hint repair preserves policy semantics and retained corpus outcomes; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "The combined issue #1361 execution-policy and hatchling update preserves retained outcomes and bounded claims; it establishes no live recovery, continuation, or trial-allocation guarantee.", + "This synchronization adds no mixed-backend runtime execution claim; the issue #1371 tests cover the composition run-scope join." + ], + "protocol_revision": "1.0.0", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "raes_revision": "dabaf7c76e8b297a271a37dcd31d5947e9641413", + "snapshot_id": "raes-standardized-specification-coverage-issue-1371-sync-v72", + "snapshot_revision": "72.0.0", + "source_state": { + "base_revision": "dabaf7c76e8b297a271a37dcd31d5947e9641413", + "checkout_state": "modified", + "implementation_digest": "25d03497c992a1079103325e50a36de2b16868efb4a7ddc33db82530c643679d", + "profile": "python-reference-source/v2" + } +} diff --git a/docs/research/specification-coverage/index.md b/docs/research/specification-coverage/index.md index 55b1959de..5f97267f0 100644 --- a/docs/research/specification-coverage/index.md +++ b/docs/research/specification-coverage/index.md @@ -546,3 +546,15 @@ export manifest split in [`execution-snapshot-v71.json`](execution-snapshot-v71.json) and [`analysis-v71.json`](analysis-v71.json). Classifications and claim limits remain unchanged. + +The issue #1371 captures that reused published release identities are preserved +in the [initial publication archive](../mixed-backend-pre-sync-evidence/README.md) +and [run-scope repair archive](../mixed-backend-run-scope-pre-sync-evidence/README.md), +with exact bytes and digests. The incoming published release history remains canonical. + +Release 72.0.0 replays the retained controls after merging the issue #1418 +runtime-fact export manifest split with the issue #1371 mixed-backend contracts +and composition run-scope repair in +[`execution-snapshot-v72.json`](execution-snapshot-v72.json) and +[`analysis-v72.json`](analysis-v72.json). Outcomes and bounded claim +limits remain unchanged; this retained corpus makes no new mixed-runtime execution claim. diff --git a/implementations/python/packages/raes_backend_protocols/__init__.py b/implementations/python/packages/raes_backend_protocols/__init__.py index 4323b8cba..592dcc7f9 100644 --- a/implementations/python/packages/raes_backend_protocols/__init__.py +++ b/implementations/python/packages/raes_backend_protocols/__init__.py @@ -1,7 +1,19 @@ """Backend-facing protocol and capability declarations.""" from .domain_topology import DomainTopologyBinding as DomainTopologyBinding +from .mixed_backend import MixedBackendBridge as MixedBackendBridge +from .mixed_backend import MixedStageReader as MixedStageReader +from .mixed_backend import MixedTimeCoordinator as MixedTimeCoordinator +from .mixed_backend import require_mixed_backend_service as require_mixed_backend_service from .operation_supervision import BackendOperationProvider as BackendOperationProvider from .operation_supervision import require_operation_provider as require_operation_provider -__all__ = ["DomainTopologyBinding", "BackendOperationProvider", "require_operation_provider"] +__all__ = [ + "DomainTopologyBinding", + "BackendOperationProvider", + "MixedBackendBridge", + "MixedStageReader", + "MixedTimeCoordinator", + "require_mixed_backend_service", + "require_operation_provider", +] diff --git a/implementations/python/packages/raes_backend_protocols/mixed_backend.py b/implementations/python/packages/raes_backend_protocols/mixed_backend.py new file mode 100644 index 000000000..48dc66fad --- /dev/null +++ b/implementations/python/packages/raes_backend_protocols/mixed_backend.py @@ -0,0 +1,121 @@ +"""Optional mixed-backend bridge, time-coordinator and stage-reader protocols. + +RAE retains admission, authored order, terminal publication and recovery. +These protocols let an installed service report correlated stage evidence for +one admitted edge or native handoff through the shared backend operation +protocol. Method presence never establishes capability, conformance or +authority, and declaring the contracts is not effective support. +""" + +from __future__ import annotations + +from collections.abc import Iterable +from inspect import signature +from typing import Literal, Protocol + +from raes_contracts.contracts import ( + BackendOperationControlModel, + BackendOperationRequestModel, + MixedBackendExecutionBindingModel, + MixedBackendStageReportModel, +) +from raes_contracts.contracts.time_model import TimeRuntimeStateModel +from raes_contracts.manifest_authority import validate_backend_supported_contract_versions +from raes_contracts.versions import MIXED_BACKEND_CONTRACT_IDS + +from .operation_supervision import BackendOperationProvider, require_operation_provider + +MixedBackendServiceRole = Literal["bridge", "coordinator", "reader"] + + +class MixedBackendBridge(BackendOperationProvider, Protocol): + """Installed edge bridge or native transfer service for exactly one admitted binding. + + The shared operation methods admit, start, observe, cancel and reconcile one + invocation whose request commits to :meth:`execution_binding`. Starting + invokes the destination provider at most once, and a duplicate identity + starts nothing. Stage reports are evidence proposals: a reader must validate + them, and only RAE may commit the operation, composition history and + terminal state. + """ + + def execution_binding(self) -> MixedBackendExecutionBindingModel: + """Return the installed binding declaration; it supplies no contextual willingness.""" + ... + + def stage_reports(self, control: BackendOperationControlModel) -> tuple[MixedBackendStageReportModel, ...]: + """Return bounded execution or handoff stage reports for an independently authorized read. + + Each report's sequence is 2, the chain position of execution and handoff. + """ + ... + + +class MixedTimeCoordinator(Protocol): + """Grant a governed order over the bound clocks before an invocation starts.""" + + def grant( + self, + request: BackendOperationRequestModel, + time_state: TimeRuntimeStateModel, + ) -> MixedBackendStageReportModel: + """Return one time-grant report at the coordinates of ``time_state``; it advances no clock. + + Its sequence is 1, the time grant's chain position. + """ + ... + + +class MixedStageReader(Protocol): + """Read back destination delivery, participant observation or native owner state.""" + + def read_stage(self, control: BackendOperationControlModel) -> MixedBackendStageReportModel: + """Return one stage report that names this reader as its producer; the read has no effects. + + Its sequence is its stage's chain position: 3 for delivery or owner readback, 4 for observation. + """ + ... + + +_ROLE_METHODS = { + "bridge": (("execution_binding", 0), ("stage_reports", 1)), + "coordinator": (("grant", 2),), + "reader": (("read_stage", 1),), +} + + +def require_mixed_backend_service( + service: object, + role: MixedBackendServiceRole, + declared_contracts: Iterable[str], +) -> None: + """Validate the opt-in declaration and installed call shapes without invoking code. + + A bridge must also install the shared operation protocol. Behavioral + conformance, the trusted profile join and contextual admission remain + separate checks. + """ + + declared = tuple(declared_contracts) + validate_backend_supported_contract_versions(declared) + if not set(MIXED_BACKEND_CONTRACT_IDS) <= set(declared): + raise ValueError("mixed backend contracts are not declared") + if role == "bridge": + require_operation_provider(service, declared) + for name, arity in _ROLE_METHODS[role]: + method = getattr(service, name, None) + if not callable(method): + raise ValueError("mixed backend service protocol is not installed") + try: + signature(method).bind(*(object(),) * arity) + except (TypeError, ValueError): + raise ValueError("installed mixed backend method has incompatible call shape") from None + + +__all__ = [ + "MixedBackendBridge", + "MixedBackendServiceRole", + "MixedStageReader", + "MixedTimeCoordinator", + "require_mixed_backend_service", +] diff --git a/implementations/python/packages/raes_backend_stubs/manifest.py b/implementations/python/packages/raes_backend_stubs/manifest.py index e5265ef5f..8f68c0de7 100644 --- a/implementations/python/packages/raes_backend_stubs/manifest.py +++ b/implementations/python/packages/raes_backend_stubs/manifest.py @@ -47,7 +47,7 @@ from raes_contracts.corpus import REALIZATION_ENVELOPES, corpus_family_root from raes_contracts.manifest_authority import BACKEND_SUPPORTED_CONTRACT_IDS from raes_contracts.realization_envelope import BackendRealizationEnvelopeModel -from raes_contracts.versions import BACKEND_OPERATION_CONTRACT_IDS +from raes_contracts.versions import BACKEND_OPERATION_CONTRACT_IDS, MIXED_BACKEND_CONTRACT_IDS from raes_contracts.vocabulary import ( ParticipantFeatureSupportLevel, RealizationSupportMode, @@ -56,6 +56,7 @@ REFERENCE_BACKEND_SUPPORTED_CONTRACT_VERSIONS = frozenset(BACKEND_SUPPORTED_CONTRACT_IDS) - { *BACKEND_OPERATION_CONTRACT_IDS, + *MIXED_BACKEND_CONTRACT_IDS, "backend-materialization-attestation-v1", "backend-augmentation-scope-v1", "backend-realization-preparation-v1", diff --git a/implementations/python/packages/raes_contracts/contracts/__init__.py b/implementations/python/packages/raes_contracts/contracts/__init__.py index faf1d61a3..ea29a40f9 100644 --- a/implementations/python/packages/raes_contracts/contracts/__init__.py +++ b/implementations/python/packages/raes_contracts/contracts/__init__.py @@ -33,6 +33,7 @@ from ._candidate_synthesis_facade import * from ._evidence_requirement_exports import * from ._exports import PUBLIC_EXPORTS as __all__ +from ._mixed_backend_exports import * from ._participant_control_exports import * from ._version_exports import * from .admitted_trial_plan import AdmittedApparatusBindingModel as AdmittedApparatusBindingModel diff --git a/implementations/python/packages/raes_contracts/contracts/_mixed_backend_exports.py b/implementations/python/packages/raes_contracts/contracts/_mixed_backend_exports.py new file mode 100644 index 000000000..6b8e13328 --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/_mixed_backend_exports.py @@ -0,0 +1,58 @@ +"""Mixed-backend execution and readback contract exports for the contracts facade.""" + +from ..versions import ( + MIXED_BACKEND_CONTRACT_IDS, + MIXED_BACKEND_EXECUTION_BINDING_SCHEMA_VERSION, + MIXED_BACKEND_STAGE_REPORT_SCHEMA_VERSION, +) +from .mixed_backend_binding import ( + MixedBackendEdgeBindingModel, + MixedBackendEdgeTimeRequirementModel, + MixedBackendExecutionBindingModel, + MixedBackendHandoffBindingModel, + MixedBackendServiceModel, + MixedBackendTimeRequirementModel, + mixed_backend_binding_reference, +) +from .mixed_backend_stages import ( + MixedBackendDeliveryStageModel, + MixedBackendExecutionStageModel, + MixedBackendHandoffStageModel, + MixedBackendObservationStageModel, + MixedBackendOwnerReadbackStageModel, + MixedBackendStageReportModel, + MixedBackendTimeGrantStageModel, +) +from .mixed_backend_transcript import MixedBackendStageContext, validate_mixed_backend_stage_reports +from .mixed_backend_validation import ( + require_mixed_backend_admission, + require_mixed_backend_request, + validate_mixed_backend_bindings, +) + +__all__ = [ + "MIXED_BACKEND_CONTRACT_IDS", + "MIXED_BACKEND_EXECUTION_BINDING_SCHEMA_VERSION", + "MIXED_BACKEND_STAGE_REPORT_SCHEMA_VERSION", + "MixedBackendDeliveryStageModel", + "MixedBackendEdgeBindingModel", + "MixedBackendEdgeTimeRequirementModel", + "MixedBackendExecutionBindingModel", + "MixedBackendExecutionStageModel", + "MixedBackendHandoffBindingModel", + "MixedBackendHandoffStageModel", + "MixedBackendObservationStageModel", + "MixedBackendOwnerReadbackStageModel", + "MixedBackendServiceModel", + "MixedBackendStageContext", + "MixedBackendStageReportModel", + "MixedBackendTimeGrantStageModel", + "MixedBackendTimeRequirementModel", + "mixed_backend_binding_reference", + "require_mixed_backend_admission", + "require_mixed_backend_request", + "validate_mixed_backend_bindings", + "validate_mixed_backend_stage_reports", +] + +MIXED_BACKEND_EXPORTS = __all__ diff --git a/implementations/python/packages/raes_contracts/contracts/_mixed_composition_exports.py b/implementations/python/packages/raes_contracts/contracts/_mixed_composition_exports.py index 0a329606d..ee0f8b3bb 100644 --- a/implementations/python/packages/raes_contracts/contracts/_mixed_composition_exports.py +++ b/implementations/python/packages/raes_contracts/contracts/_mixed_composition_exports.py @@ -1,5 +1,7 @@ """Public mixed-composition contract exports.""" +from ._mixed_backend_exports import MIXED_BACKEND_EXPORTS + MIXED_COMPOSITION_EXPORTS = [ "AdmittedMixedCompositionBindingModel", "AdmittedTrialSourceReferenceModel", @@ -9,6 +11,7 @@ "MixedParticipantCompositionProfileModel", "parse_mixed_composition_profile", "seal_mixed_composition_profile", + *MIXED_BACKEND_EXPORTS, ] __all__ = ["MIXED_COMPOSITION_EXPORTS"] diff --git a/implementations/python/packages/raes_contracts/contracts/bundle_runtime.py b/implementations/python/packages/raes_contracts/contracts/bundle_runtime.py index c0cb8a142..e539e4ba6 100644 --- a/implementations/python/packages/raes_contracts/contracts/bundle_runtime.py +++ b/implementations/python/packages/raes_contracts/contracts/bundle_runtime.py @@ -8,6 +8,7 @@ from .backend_operation_schema import backend_operation_schema_bundle from .execution_state import EvaluationHistoryEventModel from .experiment_bindings import ParticipantConfigurationResultModel +from .mixed_backend_schema import mixed_backend_schema_bundle from .operation_carriers import OperationReceiptModel, OperationStatusModel from .participant_context import ParticipantContextViewModel from .participant_control import ParticipantControlOccurrenceModel @@ -96,6 +97,7 @@ def _runtime_schema_bundle() -> dict[str, dict[str, Any]]: return { **backend_operation_schema_bundle(), **_participant_control_schema_bundle(), + **mixed_backend_schema_bundle(), "evaluation-history-event-stream-v1": _event_stream_schema( "EvaluationHistoryEventStream", EvaluationHistoryEventModel.model_json_schema(), diff --git a/implementations/python/packages/raes_contracts/contracts/mixed_backend_binding.py b/implementations/python/packages/raes_contracts/contracts/mixed_backend_binding.py new file mode 100644 index 000000000..236cec137 --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/mixed_backend_binding.py @@ -0,0 +1,196 @@ +"""Published executable bindings for admitted mixed-composition edges and handoffs. + +One binding is the plain-data form of the installed bridge, time coordinator +and readback services for exactly one admitted ``sem-234/rev1`` directed edge +or component-changing phase transition. It names pinned identities and the +obligations they must honour, and each role has its own service. Decoding a +binding installs nothing, selects no provider and grants no execution +authority; trusted joins against the sealed profile live in +:mod:`raes_contracts.contracts.mixed_backend_validation`. +""" + +from __future__ import annotations + +from typing import Annotated, Literal, Self + +from pydantic import Field, model_validator + +from ..addressing import CompiledAddress +from ..canonical import canonical_json_digest +from ..operation_lifecycle import OperationKind +from ..versions import MIXED_BACKEND_EXECUTION_BINDING_SCHEMA_VERSION +from .backend_operation import ( + OperationArtifactReferenceModel, + OperationContractModel, + OperationDigest, + OperationIdentifier, +) +from .base import PrefixedDigestString +from .mixed_composition import MIXED_COMPOSITION_PROFILE_REVISION, MixedCompositionMappingLossModel + +MIXED_BACKEND_EXECUTION_BINDING_CONTRACT_ID = "mixed-backend-execution-binding-v1" + +# Ordering bases that can support a governed comparison; wall-clock-only, +# unknown and unsupported bases cannot be promoted to an executable order. +GovernedOrderingBasis = Literal[ + "total_order", + "partial_order", + "simultaneous", + "serialized_backend_order", + "simulation_tick", + "control_plane_order", + "logical_clock", + "vector_clock", +] +_EvidenceRefs = Annotated[tuple[OperationIdentifier, ...], Field(min_length=1, max_length=64)] + + +class MixedBackendServiceModel(OperationContractModel): + """Pinned installed implementation identity; never a module, path, URL or command.""" + + service_ref: OperationIdentifier + version: OperationIdentifier + digest: OperationDigest + + +def _require_distinct_services(*services: MixedBackendServiceModel | None) -> None: + # A service pinned to two roles could report two stages itself, such as a + # bridge reading back its own delivery, so no two roles share a reference + # or a digest. + pinned = [service for service in services if service is not None] + references = {service.service_ref for service in pinned} + digests = {service.digest for service in pinned} + if len(references) != len(pinned) or len(digests) != len(pinned): + raise ValueError("a mixed binding must pin a distinct service for each role") + + +class MixedBackendTimeRequirementModel(OperationContractModel): + """Named clocks, mapping and governed order a coordinator must grant before invocation.""" + + time_model_ref: OperationIdentifier + time_model_digest: PrefixedDigestString + source_clock_address: CompiledAddress + destination_clock_address: CompiledAddress + mapping_ref: CompiledAddress + ordering_basis: GovernedOrderingBasis + required_comparison: Literal["ordered"] = "ordered" + coordinator: MixedBackendServiceModel + + +class MixedBackendEdgeTimeRequirementModel(MixedBackendTimeRequirementModel): + """Edge time requirement that also carries the admitted edge's temporal coupling.""" + + temporal_coupling: Literal["tight", "bounded-asynchronous", "asynchronous"] + + +class MixedBackendEdgeBindingModel(OperationContractModel): + """Bridge, coordinator and readers for one admitted directed edge. + + The destination provider executes the mapped action under one RAES + participant-crossing operation; owning the effect confers no controller, + disclosure or terminal-commit authority. Native translation stays inside + the pinned bridge, so the compiled action subject is preserved. Each role + is a distinct service, so the bridge never grants its own order or reads + back its own delivery or observation. + """ + + kind: Literal["edge"] + edge_id: OperationIdentifier + operation_kind: Literal[OperationKind.PARTICIPANT_CROSSING] = OperationKind.PARTICIPANT_CROSSING + owner_component_id: OperationIdentifier + owner_allocation_id: OperationIdentifier + participant_address: CompiledAddress + audience_scope_ref: OperationIdentifier + source_action_address: CompiledAddress + destination_action_address: CompiledAddress + subject_transformation: Literal["compiled-identity"] = "compiled-identity" + bridge: MixedBackendServiceModel + time: MixedBackendEdgeTimeRequirementModel + mapping_loss: MixedCompositionMappingLossModel + delivery_reader: MixedBackendServiceModel + observation_reader: MixedBackendServiceModel | None = None + required_evidence_refs: _EvidenceRefs + + @model_validator(mode="after") + def _compiled_subject_preserved(self) -> Self: + if self.source_action_address != self.destination_action_address: + raise ValueError("compiled-identity mapping must preserve the authorized action address") + return self + + @model_validator(mode="after") + def _distinct_services(self) -> Self: + _require_distinct_services(self.bridge, self.time.coordinator, self.delivery_reader, self.observation_reader) + return self + + +class MixedBackendHandoffBindingModel(OperationContractModel): + """Native responsibility transfer for one admitted component-changing transition. + + The transfer service, coordinator and owner reader are distinct services, + so a transfer never grants its own order or reads back its own owner. + """ + + kind: Literal["handoff"] + transition_id: OperationIdentifier + operation_kind: Literal[OperationKind.COMPOSITION_PHASE] = OperationKind.COMPOSITION_PHASE + source_component_id: OperationIdentifier + destination_component_id: OperationIdentifier + source_owner_ref: OperationIdentifier + destination_owner_ref: OperationIdentifier + transfer: MixedBackendServiceModel + time: MixedBackendTimeRequirementModel + owner_reader: MixedBackendServiceModel + required_evidence_refs: _EvidenceRefs + + @model_validator(mode="after") + def _distinct_owners(self) -> Self: + if self.source_component_id == self.destination_component_id: + raise ValueError("native handoff requires distinct source and destination components") + return self + + @model_validator(mode="after") + def _distinct_services(self) -> Self: + _require_distinct_services(self.transfer, self.time.coordinator, self.owner_reader) + return self + + +MixedBackendSubjectBinding = Annotated[ + MixedBackendEdgeBindingModel | MixedBackendHandoffBindingModel, + Field(discriminator="kind"), +] + + +class MixedBackendExecutionBindingModel(OperationContractModel): + """One installed executable binding, joined to its sealed profile by identity and digest.""" + + schema_version: Literal[MIXED_BACKEND_EXECUTION_BINDING_SCHEMA_VERSION] = ( + MIXED_BACKEND_EXECUTION_BINDING_SCHEMA_VERSION + ) + binding_id: OperationIdentifier + profile_id: OperationIdentifier + profile_revision: Literal[MIXED_COMPOSITION_PROFILE_REVISION] = MIXED_COMPOSITION_PROFILE_REVISION + profile_digest: PrefixedDigestString + subject: MixedBackendSubjectBinding + + +def mixed_backend_binding_reference(binding: MixedBackendExecutionBindingModel) -> OperationArtifactReferenceModel: + """Return the content-bound command reference a shared operation request must carry.""" + + return OperationArtifactReferenceModel( + contract_id=MIXED_BACKEND_EXECUTION_BINDING_CONTRACT_ID, + artifact_id=binding.binding_id, + digest=canonical_json_digest(binding.model_dump(mode="json")), + ) + + +__all__ = [ + "GovernedOrderingBasis", + "MIXED_BACKEND_EXECUTION_BINDING_CONTRACT_ID", + "MixedBackendEdgeBindingModel", + "MixedBackendEdgeTimeRequirementModel", + "MixedBackendExecutionBindingModel", + "MixedBackendHandoffBindingModel", + "MixedBackendServiceModel", + "MixedBackendTimeRequirementModel", + "mixed_backend_binding_reference", +] diff --git a/implementations/python/packages/raes_contracts/contracts/mixed_backend_schema.py b/implementations/python/packages/raes_contracts/contracts/mixed_backend_schema.py new file mode 100644 index 000000000..5a0a7a841 --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/mixed_backend_schema.py @@ -0,0 +1,86 @@ +"""Published mixed-backend schemas and their mandatory semantic validation bindings.""" + +from __future__ import annotations + +from typing import Any + +from .mixed_backend_binding import MixedBackendExecutionBindingModel +from .mixed_backend_stages import MixedBackendStageReportModel +from .schema_invariants import _add_raes_invariant + +_BINDING = "mixed-backend-execution-binding-v1" +_STAGE_REPORT = "mixed-backend-stage-report-v1" +_MODELS = {_BINDING: MixedBackendExecutionBindingModel, _STAGE_REPORT: MixedBackendStageReportModel} +_STRUCTURAL_LIMIT = "structural validity does not prove backend truth, installation or runtime authority." +_LOCAL_CONSISTENCY = { + _BINDING: "Validate closed bounded fields, unique collections, a preserved compiled subject, distinct handoff " + "components and a distinct pinned service for each role, so no two roles share a service reference or digest; " + + _STRUCTURAL_LIMIT, + _STAGE_REPORT: "Validate closed bounded fields, unique collections and honest stage evidence; " + _STRUCTURAL_LIMIT, +} + + +def _inputs(*contract_ids: str) -> list[dict[str, str]]: + return [{"contract_id": contract_id, "instance_path": "#"} for contract_id in contract_ids] + + +def mixed_backend_schema_bundle() -> dict[str, dict[str, Any]]: + schemas = {} + for contract_id, model in _MODELS.items(): + schema = model.model_json_schema() + _add_raes_invariant( + schema, + "mixed-backend-local-consistency", + _LOCAL_CONSISTENCY[contract_id], + validator=f"raes_contracts.contracts.{model.__name__}.model_validate", + inputs=_inputs(contract_id), + ) + schemas[contract_id] = schema + _add_raes_invariant( + schemas[_BINDING], + "mixed-backend-binding-profile-join", + "Require exactly one matching binding per active edge and one-to-one component-changing transition of the " + "admitted sealed profile, with governed order, preserved compiled subjects, declared loss and the edge's " + "admitted temporal coupling.", + validator="raes_contracts.contracts.validate_mixed_backend_bindings", + inputs=_inputs("mixed-participant-composition-profile-v1", _BINDING), + ) + _add_raes_invariant( + schemas[_BINDING], + "mixed-backend-contextual-admission", + "Before invocation require the shared request to commit to this binding, its operation kind and its " + "installed bridge or transfer service, then installed support and current exact-context willingness.", + validator="raes_contracts.contracts.require_mixed_backend_admission", + inputs=_inputs( + _BINDING, + "backend-operation-request-v1", + "backend-operation-capabilities-v1", + "backend-operation-response-v1", + ), + ) + _add_raes_invariant( + schemas[_STAGE_REPORT], + "mixed-backend-stage-transcript", + "Require exact invocation binding and commitment, a trusted time model resolved under the binding's " + "time-model reference and digest, each report's sequence equal to its stage's fixed chain position (time " + "grant 1, execution or handoff 2, delivery or owner readback 3, observation 4) with reports accepted in " + "ascending sequence, prerequisite stage order, the pinned producer for each stage, grant " + "coordinates equal to the committed time readback, a committed composition state that still activates " + "the edge or holds the handoff's source component without its destination, a handoff fenced on that " + "state's head and phase revision, an ordered grant and accepted start before invocation stages, success " + "or failure outcomes equal to the state the stages and trusted readbacks establish, and shared evidence " + "that cites only supplied stage reports.", + validator="raes_contracts.contracts.validate_mixed_backend_stage_reports", + inputs=[ + *_inputs( + _BINDING, + "backend-operation-request-v1", + "backend-operation-response-v1", + _STAGE_REPORT, + "time-model-v1", + "time-runtime-state-v1", + ), + {"contract_id": "runtime-snapshot-v1", "instance_path": "#/mixed_composition_states"}, + ], + ) + return schemas diff --git a/implementations/python/packages/raes_contracts/contracts/mixed_backend_stages.py b/implementations/python/packages/raes_contracts/contracts/mixed_backend_stages.py new file mode 100644 index 000000000..f4d4d9962 --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/mixed_backend_stages.py @@ -0,0 +1,154 @@ +"""Correlated stage reports for one mixed-backend invocation, never terminal commits. + +Each report proposes one fact for one shared backend operation invocation: a +time grant, bridge execution, destination delivery, participant observation, +native handoff or owner readback. Every stage names the pinned service that +produced it. Execution, delivery and observation are separate stages, so one +success flag cannot imply another; partial and unknown execution keep their own +status. A reader must validate reports against the installed binding, the +shared operation transcript and its own trusted readbacks; only RAES may commit +operation state, composition history and terminal outcomes. +""" + +from __future__ import annotations + +from typing import Annotated, Literal, Self + +from pydantic import Field, model_validator + +from ..addressing import CompiledAddress +from ..versions import MIXED_BACKEND_STAGE_REPORT_SCHEMA_VERSION +from .backend_operation import ( + BackendOperationBindingModel, + OperationContractModel, + OperationCounter, + OperationDigest, + OperationIdentifier, + OperationPositive, +) +from .mixed_backend_binding import GovernedOrderingBasis, MixedBackendServiceModel +from .time_model import TimeCoordinateModel + +MIXED_BACKEND_STAGE_REPORT_CONTRACT_ID = "mixed-backend-stage-report-v1" + +_Refs = Annotated[tuple[OperationIdentifier, ...], Field(default=(), max_length=64)] +_RequiredRefs = Annotated[tuple[OperationIdentifier, ...], Field(min_length=1, max_length=64)] + + +class MixedBackendTimeGrantStageModel(OperationContractModel): + """Coordinator grant at the committed clock coordinates; incomparable grants permit no invocation.""" + + stage: Literal["time-grant"] + producer: MixedBackendServiceModel + mapping_ref: CompiledAddress + ordering_basis: GovernedOrderingBasis + order_ref: OperationIdentifier + comparison: Literal["ordered", "incomparable"] + source_coordinate: TimeCoordinateModel + destination_coordinate: TimeCoordinateModel + mapping_evidence_refs: _RequiredRefs + timing_evidence_refs: _RequiredRefs + + +class MixedBackendExecutionStageModel(OperationContractModel): + """Bridge execution readback; it establishes no delivery or participant observation.""" + + stage: Literal["execution"] + producer: MixedBackendServiceModel + source_action_address: CompiledAddress + destination_action_address: CompiledAddress + status: Literal["succeeded", "failed", "partial", "unknown"] + evidence_refs: _Refs + mapping_loss_refs: _Refs + cessation_evidence_refs: _Refs + + @model_validator(mode="after") + def _honest_status(self) -> Self: + if self.status in {"succeeded", "partial"} and not self.evidence_refs: + raise ValueError("known execution effects require readback evidence") + if self.status == "failed" and not self.cessation_evidence_refs: + raise ValueError("known execution failure requires cessation evidence") + return self + + +class MixedBackendDeliveryStageModel(OperationContractModel): + """Destination receipt read back by the pinned delivery reader, not the bridge.""" + + stage: Literal["delivery"] + producer: MixedBackendServiceModel + destination_component_id: OperationIdentifier + receipt_ref: OperationIdentifier + evidence_refs: _RequiredRefs + + +class MixedBackendObservationStageModel(OperationContractModel): + """Participant and audience readback after delivery; delivery alone is not observation.""" + + stage: Literal["observation"] + producer: MixedBackendServiceModel + participant_address: CompiledAddress + audience_scope_ref: OperationIdentifier + observation_ref: OperationIdentifier + evidence_refs: _RequiredRefs + + +class MixedBackendHandoffStageModel(OperationContractModel): + """Native transfer disposition at the exact predecessor history head and phase revision.""" + + stage: Literal["handoff"] + producer: MixedBackendServiceModel + status: Literal["committed", "failed", "pending", "stale", "unknown"] + predecessor_history_head: OperationIdentifier + phase_revision: OperationCounter + order_ref: OperationIdentifier + evidence_refs: _Refs + + +class MixedBackendOwnerReadbackStageModel(OperationContractModel): + """Native responsibility owner read back by the pinned owner reader after a transfer attempt.""" + + stage: Literal["owner-readback"] + producer: MixedBackendServiceModel + owner_component_id: OperationIdentifier + owner_ref: OperationIdentifier + phase_revision: OperationCounter + evidence_refs: _RequiredRefs + + +MixedBackendStage = Annotated[ + MixedBackendTimeGrantStageModel + | MixedBackendExecutionStageModel + | MixedBackendDeliveryStageModel + | MixedBackendObservationStageModel + | MixedBackendHandoffStageModel + | MixedBackendOwnerReadbackStageModel, + Field(discriminator="stage"), +] + + +class MixedBackendStageReportModel(OperationContractModel): + """One stage fact bound to the exact shared operation invocation and request commitment. + + The sequence is the stage's fixed position in its chain: time grant 1, + execution or handoff 2, delivery or owner readback 3, observation 4. Each + producer numbers its own report without seeing the others, and a reader + accepts the reports in ascending sequence. + """ + + schema_version: Literal[MIXED_BACKEND_STAGE_REPORT_SCHEMA_VERSION] = MIXED_BACKEND_STAGE_REPORT_SCHEMA_VERSION + binding: BackendOperationBindingModel + request_digest: OperationDigest + sequence: OperationPositive + stage: MixedBackendStage + + +__all__ = [ + "MIXED_BACKEND_STAGE_REPORT_CONTRACT_ID", + "MixedBackendDeliveryStageModel", + "MixedBackendExecutionStageModel", + "MixedBackendHandoffStageModel", + "MixedBackendObservationStageModel", + "MixedBackendOwnerReadbackStageModel", + "MixedBackendStageReportModel", + "MixedBackendTimeGrantStageModel", +] diff --git a/implementations/python/packages/raes_contracts/contracts/mixed_backend_transcript.py b/implementations/python/packages/raes_contracts/contracts/mixed_backend_transcript.py new file mode 100644 index 000000000..13d67ec83 --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/mixed_backend_transcript.py @@ -0,0 +1,458 @@ +"""Cross-message checks for the stage reports of one mixed-backend invocation. + +The validator joins stage reports to their installed binding, the shared +backend operation request and response transcript, and trusted inputs resolved +by the caller: the time-model declaration with the reference and digest it was +resolved under, the committed time readback the coordinator received, RAES's +own time readback after the invocation and, for a native handoff, the committed +composition state. It performs no I/O, dispatch or state mutation, and passing +it proves neither backend truth nor runtime adoption. +""" + +from __future__ import annotations + +from collections.abc import Sequence +from dataclasses import dataclass +from fractions import Fraction + +from ..canonical import canonical_json_digest +from ..operation_lifecycle import OperationState +from .backend_operation import ( + BackendOperationControlModel, + BackendOperationRequestModel, + OperationArtifactReferenceModel, +) +from .backend_operation_response import ( + BackendOperationAcknowledgementModel, + BackendOperationMessage, + BackendOperationOutcomeModel, + BackendOperationProgressModel, + BackendOperationReconciliationModel, + BackendOperationResponseModel, +) +from .backend_operation_validation import backend_operation_request_digest, validate_backend_operation_history +from .mixed_backend_binding import ( + MixedBackendEdgeBindingModel, + MixedBackendExecutionBindingModel, + MixedBackendHandoffBindingModel, + MixedBackendServiceModel, + MixedBackendTimeRequirementModel, +) +from .mixed_backend_stages import ( + MIXED_BACKEND_STAGE_REPORT_CONTRACT_ID, + MixedBackendDeliveryStageModel, + MixedBackendExecutionStageModel, + MixedBackendHandoffStageModel, + MixedBackendObservationStageModel, + MixedBackendStage, + MixedBackendStageReportModel, + MixedBackendTimeGrantStageModel, +) +from .mixed_backend_validation import require_mixed_backend_request +from .mixed_runtime import MixedCompositionRuntimeStateModel +from .time_model import ( + TimeCoordinateModel, + TimeModelDeclarationModel, + TimeRuntimeStateModel, + validate_time_runtime_state, +) + +_MAX_STAGE_REPORTS = 64 +_UNSUPPORTED_ORDER = "time grant does not establish the required order within one segment" +_SubjectBinding = MixedBackendEdgeBindingModel | MixedBackendHandoffBindingModel +# Each stage may only follow its prerequisite; the stage after the time grant +# is the invocation itself and needs an ordered grant and accepted start. +_PREREQUISITES = { + "edge": {"time-grant": None, "execution": "time-grant", "delivery": "execution", "observation": "delivery"}, + "handoff": {"time-grant": None, "handoff": "time-grant", "owner-readback": "handoff"}, +} +# A report's sequence is its stage's fixed position in that chain, so producers +# that see neither each other's reports nor a shared counter can number them. +_STAGE_SEQUENCE = {"time-grant": 1, "execution": 2, "handoff": 2, "delivery": 3, "owner-readback": 3, "observation": 4} + + +@dataclass(frozen=True) +class _Transcript: + """Facts the shared operation transcript establishes; never persisted authority.""" + + accepted: bool + outcome: BackendOperationOutcomeModel | None + + +@dataclass(frozen=True) +class MixedBackendStageContext: + """Trusted, caller-resolved inputs for one invocation's stage reports; none comes from a backend. + + ``time_model`` is the declaration that the caller resolved under + ``time_model_ref`` and ``time_model_digest``, which must equal the binding's + time requirement. ``time_state`` is the committed time readback that the + coordinator received. ``post_time_state`` is RAES's own time readback after + the invocation, or ``None`` when none was taken. ``composition_state`` is + the committed composition state of the invocation's run and binding's profile: it must activate + a bound edge, or hold a handoff's source component but not its destination. + A native handoff requires it. + """ + + time_model: TimeModelDeclarationModel + time_model_ref: str + time_model_digest: str + time_state: TimeRuntimeStateModel + post_time_state: TimeRuntimeStateModel | None = None + composition_state: MixedCompositionRuntimeStateModel | None = None + + +@dataclass(frozen=True) +class _Trusted: + """Facts derived from the trusted context that the reports must match.""" + + time_model: TimeModelDeclarationModel + coordinates: tuple[TimeCoordinateModel, TimeCoordinateModel] + time_confirmed: bool + fence: tuple[str, int] | None + + +def validate_mixed_backend_stage_reports( + binding: MixedBackendExecutionBindingModel, + request: BackendOperationRequestModel, + responses: Sequence[BackendOperationResponseModel], + reports: Sequence[MixedBackendStageReportModel], + *, + context: MixedBackendStageContext, + controls: Sequence[BackendOperationControlModel] = (), +) -> None: + """Validate one invocation's stage reports against its binding, transcript and trusted context. + + The trusted time model must be resolved under the binding's time-model + reference and digest, and a committed composition state must still + activate the bound edge or precede the bound handoff. The grant's + coordinates must equal the committed time readback, and a native handoff + must name the committed composition history head and phase revision. Each + report's ``sequence`` must be its stage's fixed chain position (time grant + 1, execution or handoff 2, delivery or owner readback 3, observation 4), + and reports are accepted in ascending ``sequence`` whatever order they are + supplied in. Each stage must follow its prerequisite and name the service + pinned for its role, and the invocation stage needs an ordered grant and an + accepted acknowledgement. A proposed success or known failure must equal + the state that the stages and the trusted readbacks establish. + """ + + require_mixed_backend_request(binding, request) + validate_backend_operation_history(request, responses, controls=controls) + trusted = _trusted_inputs(binding, request, context) + messages = [response.message for response in responses] + accepted = any( + isinstance(message, BackendOperationAcknowledgementModel) and message.disposition == "accepted" + for message in messages + ) + outcomes = [message for message in messages if isinstance(message, BackendOperationOutcomeModel)] + transcript = _Transcript(accepted=accepted, outcome=outcomes[-1] if outcomes else None) + subject = binding.subject + seen: dict[str, MixedBackendStage] = {} + for stage in _ordered_stages(request, reports): + _require_prerequisite(subject, stage, seen, transcript) + _require_producer(subject, stage) + _require_stage_identity(subject, stage, seen, trusted) + seen[stage.stage] = stage + _require_honest_outcome(subject, seen, transcript, trusted) + _require_cited_reports(messages, reports) + + +def _trusted_inputs( + binding: MixedBackendExecutionBindingModel, + request: BackendOperationRequestModel, + context: MixedBackendStageContext, +) -> _Trusted: + required, time_model = binding.subject.time, context.time_model + if (context.time_model_ref, context.time_model_digest) != (required.time_model_ref, required.time_model_digest): + raise ValueError("trusted time model differs from the binding's time model reference or digest") + validate_time_runtime_state(time_model, context.time_state) + before = _bound_coordinates(required, context.time_state) + confirmed = _time_confirmed(required, time_model, before, context.post_time_state) + return _Trusted(time_model, before, confirmed, _composition_fence(binding, request, context.composition_state)) + + +def _bound_coordinates( + required: MixedBackendTimeRequirementModel, + state: TimeRuntimeStateModel, +) -> tuple[TimeCoordinateModel, TimeCoordinateModel]: + source = state.clocks.get(required.source_clock_address) + destination = state.clocks.get(required.destination_clock_address) + if source is None or destination is None: + raise ValueError("time readback does not cover the bound clocks") + return source.coordinate, destination.coordinate + + +def _time_confirmed( + required: MixedBackendTimeRequirementModel, + time_model: TimeModelDeclarationModel, + before: tuple[TimeCoordinateModel, TimeCoordinateModel], + post_time_state: TimeRuntimeStateModel | None, +) -> bool: + # RAES's own post-invocation readback confirms time only when it matches the + # declaration and neither bound clock moved backwards. + if post_time_state is None: + return False + validate_time_runtime_state(time_model, post_time_state) + after = _bound_coordinates(required, post_time_state) + return all(_position(late) >= _position(early) for early, late in zip(before, after, strict=True)) + + +def _position(coordinate: TimeCoordinateModel) -> tuple[int, int, int]: + return coordinate.segment, coordinate.tick, coordinate.microstep + + +def _composition_fence( + binding: MixedBackendExecutionBindingModel, + request: BackendOperationRequestModel, + state: MixedCompositionRuntimeStateModel | None, +) -> tuple[str, int] | None: + if state is None: + if binding.subject.kind == "handoff": + raise ValueError("native handoff validation requires the committed composition state") + return None + if request.binding.context.run_scope != f"run:{state.run_id}": + raise ValueError("committed composition state belongs to another run") + if (state.profile_id, state.profile_digest) != (binding.profile_id, binding.profile_digest): + raise ValueError("committed composition state belongs to another profile") + _require_open_obligation(binding.subject, state) + return state.history_head, state.phase_revision + + +def _require_open_obligation(subject: _SubjectBinding, state: MixedCompositionRuntimeStateModel) -> None: + # The committed state must still be the one the obligation acts on: the + # edge is active, or the handoff's source is active and its destination not. + if isinstance(subject, MixedBackendEdgeBindingModel): + if subject.edge_id not in state.active_edge_ids: + raise ValueError("committed composition state does not activate the bound edge") + return + active = set(state.active_component_ids) + if subject.source_component_id not in active or subject.destination_component_id in active: + raise ValueError("committed composition state does not precede the native handoff") + + +def _ordered_stages( + request: BackendOperationRequestModel, + reports: Sequence[MixedBackendStageReportModel], +) -> list[MixedBackendStage]: + if len(reports) > _MAX_STAGE_REPORTS: + raise ValueError("mixed stage report transcript exceeds its bound") + digest = backend_operation_request_digest(request) + by_sequence: dict[int, MixedBackendStageReportModel] = {} + for report in reports: + if report.binding != request.binding or report.request_digest != digest: + raise ValueError("mixed stage report belongs to another invocation") + if report.sequence != _STAGE_SEQUENCE[report.stage.stage]: + raise ValueError("stage report sequence differs from its stage's chain position") + # One number per stage kind, so a second report of a stage is either a + # retransmission or a contradiction. + if by_sequence.setdefault(report.sequence, report) != report: + raise ValueError("duplicate stage report sequence changed its content") + return [by_sequence[sequence].stage for sequence in sorted(by_sequence)] + + +def _require_prerequisite( + subject: _SubjectBinding, + stage: MixedBackendStage, + seen: dict[str, MixedBackendStage], + transcript: _Transcript, +) -> None: + prerequisites = _PREREQUISITES[subject.kind] + if stage.stage not in prerequisites: + raise ValueError("stage does not belong to this mixed binding obligation") + prerequisite = prerequisites[stage.stage] + if prerequisite is not None and prerequisite not in seen: + raise ValueError("mixed stage report precedes its prerequisite stage") + if prerequisite == "time-grant" and (not transcript.accepted or seen[prerequisite].comparison != "ordered"): + raise ValueError("invocation requires an ordered time grant and an accepted acknowledgement") + if stage.stage == "delivery" and seen["execution"].status == "failed": + raise ValueError("known execution failure cannot be followed by delivery") + + +def _require_producer(subject: _SubjectBinding, stage: MixedBackendStage) -> None: + if stage.producer != _pinned_producer(subject, stage.stage): + raise ValueError("stage report names a producer other than the service pinned for its stage") + + +def _pinned_producer(subject: _SubjectBinding, stage_kind: str) -> MixedBackendServiceModel | None: + if stage_kind == "time-grant": + return subject.time.coordinator + if isinstance(subject, MixedBackendEdgeBindingModel): + services = { + "execution": subject.bridge, + "delivery": subject.delivery_reader, + "observation": subject.observation_reader, + } + else: + services = {"handoff": subject.transfer, "owner-readback": subject.owner_reader} + return services[stage_kind] + + +def _require_stage_identity( + subject: _SubjectBinding, + stage: MixedBackendStage, + seen: dict[str, MixedBackendStage], + trusted: _Trusted, +) -> None: + # An owner readback naming neither admitted owner is a valid contradictory + # fact; the outcome rules keep such a transfer indeterminate. + if isinstance(stage, MixedBackendTimeGrantStageModel): + _require_time_grant(subject, stage, trusted) + elif isinstance(stage, MixedBackendExecutionStageModel): + _require_execution(subject, stage) + elif isinstance(stage, MixedBackendDeliveryStageModel): + _require_delivery(subject, stage) + elif isinstance(stage, MixedBackendObservationStageModel): + _require_observation(subject, stage) + elif isinstance(stage, MixedBackendHandoffStageModel): + _require_handoff(subject, stage, seen["time-grant"], trusted) + + +def _require_time_grant(subject: _SubjectBinding, grant: MixedBackendTimeGrantStageModel, trusted: _Trusted) -> None: + required = subject.time + if (grant.mapping_ref, grant.ordering_basis) != (required.mapping_ref, required.ordering_basis): + raise ValueError("time grant differs from the bound mapping or ordering basis") + if (grant.source_coordinate, grant.destination_coordinate) != trusted.coordinates: + raise ValueError("time grant coordinates differ from the committed time readback") + if not set(subject.required_evidence_refs) <= {*grant.mapping_evidence_refs, *grant.timing_evidence_refs}: + raise ValueError("time grant does not cite the admitted evidence obligations") + if grant.comparison == "ordered": + _require_mapped_order(required, grant, trusted.time_model) + + +def _require_mapped_order( + required: MixedBackendTimeRequirementModel, + grant: MixedBackendTimeGrantStageModel, + time_model: TimeModelDeclarationModel, +) -> None: + mapping = time_model.mappings.get(required.mapping_ref) + source, destination = grant.source_coordinate, grant.destination_coordinate + if mapping is None or source.segment != destination.segment: + raise ValueError(_UNSUPPORTED_ORDER) + mapped = Fraction(source.tick * mapping.scale.numerator, mapping.scale.denominator) + mapping.offset_ticks + if (mapped, source.microstep) > (destination.tick, destination.microstep): + raise ValueError(_UNSUPPORTED_ORDER) + + +def _require_execution(subject: MixedBackendEdgeBindingModel, execution: MixedBackendExecutionStageModel) -> None: + observed = ( + execution.source_action_address, + execution.destination_action_address, + frozenset(execution.mapping_loss_refs), + ) + expected = ( + subject.source_action_address, + subject.destination_action_address, + frozenset({subject.mapping_loss.limitation_ref}), + ) + if observed != expected: + raise ValueError("execution report differs from the installed subjects or declared loss") + + +def _require_delivery(subject: MixedBackendEdgeBindingModel, delivery: MixedBackendDeliveryStageModel) -> None: + if delivery.destination_component_id != subject.owner_component_id: + raise ValueError("delivery receipt differs from the destination provider") + + +def _require_observation( + subject: MixedBackendEdgeBindingModel, + observation: MixedBackendObservationStageModel, +) -> None: + observed = (observation.participant_address, observation.audience_scope_ref) + if observed != (subject.participant_address, subject.audience_scope_ref): + raise ValueError("participant observation differs from the bound participant or audience") + + +def _require_handoff( + subject: MixedBackendHandoffBindingModel, + handoff: MixedBackendHandoffStageModel, + grant: MixedBackendTimeGrantStageModel, + trusted: _Trusted, +) -> None: + if handoff.order_ref != grant.order_ref: + raise ValueError("native handoff differs from its granted order") + if (handoff.predecessor_history_head, handoff.phase_revision) != trusted.fence: + raise ValueError("native handoff differs from the committed composition history head or phase revision") + if not set(subject.required_evidence_refs) <= set(handoff.evidence_refs): + raise ValueError("native handoff does not cite the admitted evidence obligations") + + +def _require_honest_outcome( + subject: _SubjectBinding, + seen: dict[str, MixedBackendStage], + transcript: _Transcript, + trusted: _Trusted, +) -> None: + outcome = transcript.outcome + if outcome is None or outcome.proposed_state not in {OperationState.SUCCEEDED, OperationState.FAILED}: + return + established = _edge_state(seen, trusted) if subject.kind == "edge" else _handoff_state(subject, seen, trusted) + if outcome.proposed_state != established: + raise ValueError("shared outcome claims more than the mixed stages establish") + + +def _require_cited_reports( + messages: Sequence[BackendOperationMessage], + reports: Sequence[MixedBackendStageReportModel], +) -> None: + cited = { + reference.digest + for message in messages + for reference in _evidence_references(message) + if reference.contract_id == MIXED_BACKEND_STAGE_REPORT_CONTRACT_ID + } + supplied = {canonical_json_digest(report.model_dump(mode="json")) for report in reports} + if not cited <= supplied: + raise ValueError("shared operation evidence cites a stage report that this invocation did not supply") + + +def _evidence_references(message: BackendOperationMessage) -> tuple[OperationArtifactReferenceModel, ...]: + if isinstance(message, BackendOperationProgressModel): + return message.evidence_refs + if isinstance(message, (BackendOperationOutcomeModel, BackendOperationReconciliationModel)): + return message.effects.evidence_refs + return () + + +def _refused_grant_state(seen: dict[str, MixedBackendStage]) -> OperationState: + # Only an explicit incomparable grant proves that no invocation could start. + grant = seen.get("time-grant") + refused = grant is not None and grant.comparison == "incomparable" + return OperationState.FAILED if refused else OperationState.INDETERMINATE + + +def _edge_state(seen: dict[str, MixedBackendStage], trusted: _Trusted) -> OperationState: + execution = seen.get("execution") + if execution is None: + return _refused_grant_state(seen) + if execution.status == "failed": + return OperationState.FAILED + delivered = execution.status == "succeeded" and "delivery" in seen + return OperationState.SUCCEEDED if delivered and trusted.time_confirmed else OperationState.INDETERMINATE + + +def _handoff_state( + subject: MixedBackendHandoffBindingModel, + seen: dict[str, MixedBackendStage], + trusted: _Trusted, +) -> OperationState: + # Only a committed transfer read back at the destination owner and next phase + # revision succeeds; only a failed or stale one that kept the source owner + # fails. Both need confirmed post-transfer time. + handoff, readback = seen.get("handoff"), seen.get("owner-readback") + if handoff is None: + return _refused_grant_state(seen) + state = OperationState.INDETERMINATE + if readback is not None and trusted.time_confirmed: + # ``_require_handoff`` fenced this revision on the committed composition state. + revision = handoff.phase_revision + owner = (readback.owner_component_id, readback.owner_ref, readback.phase_revision) + destination = (subject.destination_component_id, subject.destination_owner_ref, revision + 1) + source = (subject.source_component_id, subject.source_owner_ref, revision) + if handoff.status == "committed" and owner == destination: + state = OperationState.SUCCEEDED + elif handoff.status in {"failed", "stale"} and owner == source: + state = OperationState.FAILED + return state + + +__all__ = ["MixedBackendStageContext", "validate_mixed_backend_stage_reports"] diff --git a/implementations/python/packages/raes_contracts/contracts/mixed_backend_validation.py b/implementations/python/packages/raes_contracts/contracts/mixed_backend_validation.py new file mode 100644 index 000000000..a9fd85872 --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/mixed_backend_validation.py @@ -0,0 +1,238 @@ +"""Trusted joins for mixed-backend bindings and their shared operation requests. + +These pure validators compare the published carriers with trusted inputs +resolved by the caller: the sealed composition profile and its resolution +context, and the shared backend operation request, capabilities and admission +response. They perform no I/O, dispatch or state mutation. Passing them proves +neither backend truth nor runtime adoption. +""" + +from __future__ import annotations + +from collections.abc import Sequence + +from .backend_operation import BackendOperationCapabilitiesModel, BackendOperationRequestModel +from .backend_operation_response import BackendOperationResponseModel +from .backend_operation_validation import require_backend_operation_admission +from .mixed_backend_binding import ( + MixedBackendEdgeBindingModel, + MixedBackendEdgeTimeRequirementModel, + MixedBackendExecutionBindingModel, + MixedBackendHandoffBindingModel, + MixedBackendTimeRequirementModel, + mixed_backend_binding_reference, +) +from .mixed_composition import ( + MixedCompositionEdgeModel, + MixedCompositionTransitionModel, + MixedParticipantCompositionProfileModel, +) +from .mixed_composition_resolution import MixedCompositionResolutionContext, validate_mixed_composition_context + +_MAX_BINDINGS = 2048 +_UNGOVERNED_ORDERING = frozenset({"wall_clock_only", "unknown", "unsupported"}) + + +def validate_mixed_backend_bindings( + profile: MixedParticipantCompositionProfileModel, + context: MixedCompositionResolutionContext, + bindings: Sequence[MixedBackendExecutionBindingModel], +) -> None: + """Require exactly one matching installed binding for each executable obligation. + + Every edge active in an admitted phase needs a bridge binding, and every + transition that changes the active components needs a one-to-one native + handoff binding. Alternative profiles have no such obligation and admit no + binding. Missing, foreign, duplicate or contradictory bindings and + unsupported coordination refuse the whole set. + """ + + validate_mixed_composition_context(profile, context) + edges, handoffs = _index_bindings(profile, bindings) + for edge_id in sorted({edge_id for phase in profile.phases.values() for edge_id in phase.active_edge_ids}): + _validate_edge_binding(profile, profile.edges[edge_id], edges.pop(edge_id, None)) + for transition_id in sorted(profile.transitions): + transition = profile.transitions[transition_id] + _validate_handoff_binding(profile, context, transition, handoffs.pop(transition_id, None)) + if edges or handoffs: + raise ValueError("mixed backend bindings must name admitted edges or component-changing transitions") + + +def _index_bindings( + profile: MixedParticipantCompositionProfileModel, + bindings: Sequence[MixedBackendExecutionBindingModel], +) -> tuple[dict[str, MixedBackendEdgeBindingModel], dict[str, MixedBackendHandoffBindingModel]]: + if len(bindings) > _MAX_BINDINGS: + raise ValueError("mixed backend binding set exceeds its bound") + if len({binding.binding_id for binding in bindings}) != len(bindings): + raise ValueError("mixed backend binding identities must be unique") + identity = (profile.profile_id, profile.profile_revision, profile.profile_digest) + edges: dict[str, MixedBackendEdgeBindingModel] = {} + handoffs: dict[str, MixedBackendHandoffBindingModel] = {} + for binding in bindings: + if (binding.profile_id, binding.profile_revision, binding.profile_digest) != identity: + raise ValueError("mixed backend binding names another composition profile") + subject = binding.subject + index, key = (edges, subject.edge_id) if subject.kind == "edge" else (handoffs, subject.transition_id) + if key in index: + raise ValueError("mixed backend binding set binds one obligation twice") + index[key] = subject + return edges, handoffs + + +def _validate_edge_binding( + profile: MixedParticipantCompositionProfileModel, + edge: MixedCompositionEdgeModel, + installed: MixedBackendEdgeBindingModel | None, +) -> None: + if edge.time_binding.ordering_basis in _UNGOVERNED_ORDERING: + raise ValueError("mixed edge requires an ungoverned order that no binding can execute") + if installed is None: + raise ValueError("active mixed edge requires an executable binding") + if not _owns_destination_action(profile, edge, installed): + raise ValueError("mixed edge binding must own the destination provider's action allocation") + observed = ( + installed.owner_component_id, + installed.participant_address, + installed.audience_scope_ref, + installed.bridge.service_ref, + installed.mapping_loss, + frozenset(installed.required_evidence_refs), + _time_coordinates(installed.time), + ) + binding = edge.time_binding + admitted = ( + edge.target_component_id, + edge.crossing_subject.participant_address, + edge.audience_scope_ref, + edge.routing_ref, + edge.mapping_loss, + frozenset(item.evidence_ref for item in edge.evidence_bindings), + ( + binding.time_model_ref, + binding.time_model_digest, + binding.source_clock_address, + binding.target_clock_address, + binding.mapping_address, + binding.ordering_basis, + binding.temporal_coupling, + ), + ) + if observed != admitted: + raise ValueError("mixed edge binding differs from the admitted edge") + + +def _owns_destination_action( + profile: MixedParticipantCompositionProfileModel, + edge: MixedCompositionEdgeModel, + installed: MixedBackendEdgeBindingModel, +) -> bool: + # The owner is the destination provider's action allocation for the bound + # address, active in at least one phase where the edge is active. + allocation = profile.allocations.get(installed.owner_allocation_id) + return ( + allocation is not None + and allocation.target_kind == "action-family" + and allocation.provider_component_id == edge.target_component_id + and allocation.target_address == installed.destination_action_address + and not set(allocation.phase_ids).isdisjoint(edge.phase_ids) + ) + + +def _validate_handoff_binding( + profile: MixedParticipantCompositionProfileModel, + context: MixedCompositionResolutionContext, + transition: MixedCompositionTransitionModel, + installed: MixedBackendHandoffBindingModel | None, +) -> None: + source = set(profile.phases[transition.source_phase_id].active_component_ids) + target = set(profile.phases[transition.target_phase_id].active_component_ids) + if source == target: + if installed is not None: + raise ValueError("a transition that keeps its components needs no native handoff binding") + return + leaving, joining = sorted(source - target), sorted(target - source) + if len(leaving) != 1 or len(joining) != 1: + raise ValueError("staged transition changes components outside one-to-one native handoff") + if installed is None: + raise ValueError("component-changing transition requires an executable handoff binding") + observed = ( + installed.source_component_id, + installed.destination_component_id, + installed.source_owner_ref, + installed.destination_owner_ref, + frozenset(installed.required_evidence_refs), + ) + admitted = ( + leaving[0], + joining[0], + profile.components[leaving[0]].native_ownership_ref, + profile.components[joining[0]].native_ownership_ref, + frozenset(item.evidence_ref for item in transition.evidence_bindings), + ) + if observed != admitted: + raise ValueError("mixed handoff binding differs from the admitted transition ownership") + _require_resolved_time(context, installed.time) + + +def _time_coordinates(time: MixedBackendEdgeTimeRequirementModel) -> tuple[str, ...]: + return ( + time.time_model_ref, + time.time_model_digest, + time.source_clock_address, + time.destination_clock_address, + time.mapping_ref, + time.ordering_basis, + time.temporal_coupling, + ) + + +def _require_resolved_time(context: MixedCompositionResolutionContext, time: MixedBackendTimeRequirementModel) -> None: + declaration = context.time_models.get(time.time_model_ref) + if declaration is None or context.time_model_digests.get(time.time_model_ref) != time.time_model_digest: + raise ValueError("mixed handoff time model is unresolved or stale") + mapping = declaration.mappings.get(time.mapping_ref) + source = declaration.clocks.get(time.source_clock_address) + destination = declaration.clocks.get(time.destination_clock_address) + endpoints = (source.time_domain_address, destination.time_domain_address) if source and destination else () + if mapping is None or endpoints != (mapping.source_domain_address, mapping.target_domain_address): + raise ValueError("mixed handoff clocks and mapping are unresolved") + + +def require_mixed_backend_request( + binding: MixedBackendExecutionBindingModel, + request: BackendOperationRequestModel, +) -> None: + """Require a shared request to commit to this exact binding, operation kind and installed service. + + The request's backend is the edge bridge or native transfer service the + binding pins, so shared capabilities and admission answer for that service. + """ + + if request.command != mixed_backend_binding_reference(binding): + raise ValueError("backend operation request does not commit to the installed mixed binding") + if request.binding.context.operation_kind != binding.subject.operation_kind: + raise ValueError("backend operation kind differs from the mixed binding obligation") + subject = binding.subject + service = subject.bridge if subject.kind == "edge" else subject.transfer + if request.binding.backend_id != service.service_ref: + raise ValueError("backend operation request is not addressed to the installed mixed service") + + +def require_mixed_backend_admission( + binding: MixedBackendExecutionBindingModel, + request: BackendOperationRequestModel, + capabilities: BackendOperationCapabilitiesModel, + response: BackendOperationResponseModel, +) -> None: + """Join shared contextual admission to one installed binding; grants no invocation authority.""" + + require_mixed_backend_request(binding, request) + require_backend_operation_admission(request, capabilities, response) + + +__all__ = [ + "require_mixed_backend_admission", + "require_mixed_backend_request", + "validate_mixed_backend_bindings", +] diff --git a/implementations/python/packages/raes_contracts/manifest_authority.py b/implementations/python/packages/raes_contracts/manifest_authority.py index 680b83db3..4b4fb65cd 100644 --- a/implementations/python/packages/raes_contracts/manifest_authority.py +++ b/implementations/python/packages/raes_contracts/manifest_authority.py @@ -4,7 +4,7 @@ from collections.abc import Iterable -from .versions import BACKEND_OPERATION_CONTRACT_IDS +from .versions import BACKEND_OPERATION_CONTRACT_IDS, MIXED_BACKEND_CONTRACT_IDS PROCESSOR_SUPPORTED_SDL_VERSION_IDS = ("sdl-authoring-input-v1",) @@ -40,6 +40,7 @@ # separate authority surfaces and do not belong in this declaration field. BACKEND_SUPPORTED_CONTRACT_IDS = ( *BACKEND_OPERATION_CONTRACT_IDS, + *MIXED_BACKEND_CONTRACT_IDS, "backend-materialization-attestation-v1", "backend-augmentation-scope-v1", "plan-realization-profiles-v1", diff --git a/implementations/python/packages/raes_contracts/versions.py b/implementations/python/packages/raes_contracts/versions.py index 6619fbf3b..30e2a3ddc 100644 --- a/implementations/python/packages/raes_contracts/versions.py +++ b/implementations/python/packages/raes_contracts/versions.py @@ -46,6 +46,9 @@ "backend-operation-control-v1", "backend-operation-response-v1", ) +MIXED_BACKEND_EXECUTION_BINDING_SCHEMA_VERSION = "mixed-backend-execution-binding/v1" +MIXED_BACKEND_STAGE_REPORT_SCHEMA_VERSION = "mixed-backend-stage-report/v1" +MIXED_BACKEND_CONTRACT_IDS = ("mixed-backend-execution-binding-v1", "mixed-backend-stage-report-v1") EVALUATION_STATE_SCHEMA_VERSION = "evaluation-result-state/v1" PROPOSITION_TRUTH_RESULT_SCHEMA_VERSION = "proposition-truth-result/v1" SDL_LINEAGE_LEDGER_SCHEMA_VERSION = "sdl-lineage-ledger/v1" diff --git a/implementations/python/packages/raes_reference_backend/manifest.py b/implementations/python/packages/raes_reference_backend/manifest.py index 9273dba5c..4b2d3ef21 100644 --- a/implementations/python/packages/raes_reference_backend/manifest.py +++ b/implementations/python/packages/raes_reference_backend/manifest.py @@ -43,7 +43,7 @@ ) from raes_contracts.manifest_authority import BACKEND_SUPPORTED_CONTRACT_IDS from raes_contracts.realization_envelope import BackendRealizationEnvelopeModel -from raes_contracts.versions import BACKEND_OPERATION_CONTRACT_IDS +from raes_contracts.versions import BACKEND_OPERATION_CONTRACT_IDS, MIXED_BACKEND_CONTRACT_IDS from raes_contracts.vocabulary import ( ParticipantFeatureSupportLevel, RealizationSupportMode, @@ -57,6 +57,7 @@ contract_id for contract_id in BACKEND_SUPPORTED_CONTRACT_IDS if contract_id not in BACKEND_OPERATION_CONTRACT_IDS + if contract_id not in MIXED_BACKEND_CONTRACT_IDS if contract_id not in {"backend-materialization-attestation-v1", "backend-augmentation-scope-v1"} if contract_id not in {"experiment-binding-descriptors-v1", "backend-realization-preparation-v1", "plan-realization-profiles-v1"} diff --git a/implementations/python/tests/test_backend_manifest.py b/implementations/python/tests/test_backend_manifest.py index 780b746a4..df85d06e8 100644 --- a/implementations/python/tests/test_backend_manifest.py +++ b/implementations/python/tests/test_backend_manifest.py @@ -55,6 +55,8 @@ "backend-operation-capabilities-v1", "backend-operation-control-v1", "backend-operation-response-v1", + "mixed-backend-execution-binding-v1", + "mixed-backend-stage-report-v1", "experiment-binding-descriptors-v1", "realization-envelope-v1", "backend-realization-preparation-v1", diff --git a/implementations/python/tests/test_formal_semantic_validation.py b/implementations/python/tests/test_formal_semantic_validation.py index b35015af1..e66fe69a1 100644 --- a/implementations/python/tests/test_formal_semantic_validation.py +++ b/implementations/python/tests/test_formal_semantic_validation.py @@ -151,6 +151,7 @@ def test_atomic_release_index_validates_every_historical_bundle() -> None: "70.0.0", "71.0.0", "72.0.0", + "73.0.0", ] assert all(validate_release_bundle(REPO_ROOT, release) == [] for release in releases) @@ -159,10 +160,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"] == "72.0.0" + assert release.manifest["revision"] == "73.0.0" assert protocol["revision"] == "2.0.0" assert corpus["revision"] == "4.0.0" - assert snapshot["baseline"]["release_revision"] == "71.0.0" + assert snapshot["baseline"]["release_revision"] == "72.0.0" assert snapshot["deviations"] == [] assert validate_retest_bundle(REPO_ROOT, release, protocol, corpus, snapshot, analysis) == [] diff --git a/implementations/python/tests/test_issue_1371_mixed_backend_contracts.py b/implementations/python/tests/test_issue_1371_mixed_backend_contracts.py new file mode 100644 index 000000000..9a3b017d6 --- /dev/null +++ b/implementations/python/tests/test_issue_1371_mixed_backend_contracts.py @@ -0,0 +1,1000 @@ +"""Published mixed-backend execution bindings, shared-operation admission and stage readback (#1371).""" + +from __future__ import annotations + +import json +from pathlib import Path + +import pytest +from jsonschema import Draft202012Validator +from pydantic import ValidationError +from raes_backend_protocols import require_mixed_backend_service +from raes_contracts import contracts +from raes_contracts.canonical import canonical_json_digest +from raes_contracts.contracts import seal_mixed_composition_profile +from raes_contracts.contracts.time_model import TimeModelDeclarationModel, TimeRuntimeStateModel +from raes_contracts.versions import BACKEND_OPERATION_CONTRACT_IDS, MIXED_BACKEND_CONTRACT_IDS +from test_issue_1014_mixed_composition_contracts import _context, _staged_profile, _time_model +from test_issue_1016_mixed_runtime_coordination import _runtime_mixed_profile, _runtime_profile + +ROOT = Path(__file__).resolve().parents[3] +FIXTURES = ROOT / "contracts/fixtures/control-plane" +BINDING = "mixed-backend-execution-binding-v1" +STAGES = "mixed-backend-stage-report-v1" +SCENARIOS = { + "mixed-edge": "mixed-edge", + "mixed-edge-partial": "mixed-edge", + "mixed-edge-refused": "mixed-edge", + "mixed-edge-time-refused": "mixed-edge", + "mixed-handoff": "mixed-handoff", + "mixed-handoff-stale": "mixed-handoff", +} +# Committed source and destination clock coordinates; after a reset the +# destination clock of the time-refused example sits in a later segment. +COMMITTED_CLOCKS = {"mixed-edge-time-refused": ((0, 4, 0), (1, 2, 0))} + + +def _fixture(family: str, kind: str, name: str) -> dict: + return json.loads((FIXTURES / family / kind / f"{name}.json").read_text(encoding="utf-8")) + + +def _subject_payload(name: str, **subject: object) -> dict: + payload = _fixture(BINDING, "valid", name) + payload["subject"].update(subject) + return payload + + +def _binding(name: str = "mixed-edge", **subject: object) -> contracts.MixedBackendExecutionBindingModel: + return contracts.MixedBackendExecutionBindingModel.model_validate(_subject_payload(name, **subject)) + + +def _scenario(name: str) -> tuple[contracts.BackendOperationRequestModel, list, list]: + request = contracts.BackendOperationRequestModel.model_validate( + _fixture("backend-operation-request-v1", "valid", name) + ) + responses = [ + contracts.BackendOperationResponseModel.model_validate_json(path.read_text(encoding="utf-8")) + for path in sorted((FIXTURES / "backend-operation-response-v1/valid").glob(f"{name}-0*.json")) + ] + reports = [ + contracts.MixedBackendStageReportModel.model_validate_json(path.read_text(encoding="utf-8")) + for path in sorted((FIXTURES / STAGES / "valid").glob(f"{name}-0*.json")) + ] + return request, responses, reports + + +def _coordinate(segment: int, tick: int, microstep: int) -> dict: + return {"segment": segment, "tick": tick, "microstep": microstep} + + +def _time_state( + source: tuple[int, int, int] = (0, 4, 0), + destination: tuple[int, int, int] = (0, 4, 1), + *, + declaration: TimeModelDeclarationModel | None = None, +) -> TimeRuntimeStateModel: + """Typed time readback with the bound simulation and emulation clocks at the given coordinates.""" + + declaration = declaration or _time_model() + positions = {"time.clocks.sim": source, "time.clocks.emu": destination} + clocks = {} + for address, clock in declaration.clocks.items(): + coordinate = _coordinate(*positions.get(address, (0, 0, 0))) + clocks[address] = { + "clock_address": address, + "time_domain_address": clock.time_domain_address, + "authority_kind": clock.authority_kind, + "authority_ref": clock.authority_ref, + "state": "running", + "coordinate": coordinate, + "sequence": 0, + "history": [ + { + "sequence": 0, + "kind": "initialize", + "previous": None, + "resulting": coordinate, + "resulting_state": "running", + } + ], + } + return TimeRuntimeStateModel.model_validate( + {"declaration_digest": declaration.canonical_digest(), "clocks": clocks} + ) + + +def _declaration(**emulation_clock: object) -> TimeModelDeclarationModel: + fields = _time_model().model_dump(mode="python") + clock = fields["clocks"].pop("time.clocks.emu") | emulation_clock + fields["clocks"][clock["address"]] = clock + return TimeModelDeclarationModel.model_validate(fields) + + +def _composition_state(profile=None, **changes: object) -> contracts.MixedCompositionRuntimeStateModel: + """Committed composition state; by default the staged profile's source phase before its handoff.""" + + profile = profile or _staged_profile() + return contracts.MixedCompositionRuntimeStateModel.model_validate( + { + "run_id": "mixed", + "plan_id": "plan:mixed", + "plan_entry_id": "entry:mixed", + "profile_id": profile.profile_id, + "profile_digest": profile.profile_digest, + "phase_id": "phase.sim", + "phase_revision": 0, + "active_component_ids": ["sim"], + "active_allocation_ids": ["allocation.participant", "allocation.action"], + "history_head": "composition:activation:initial", + } + | changes + ) + + +def _edge_composition_state(*active_edge_ids: str) -> contracts.MixedCompositionRuntimeStateModel: + """Committed state of the edge profile's only phase, with the given edges active.""" + + return _composition_state( + _runtime_mixed_profile(), + phase_id="phase.main", + active_component_ids=["sim", "emu"], + active_edge_ids=list(active_edge_ids), + ) + + +def _trusted(scenario: str) -> dict: + """Caller-resolved inputs: time model and its identity, time readbacks and the composition state.""" + + readback = _time_state(*COMMITTED_CLOCKS.get(scenario, ())) + time = _fixture(BINDING, "valid", SCENARIOS[scenario])["subject"]["time"] + trusted = { + "time_model": _time_model(), + "time_model_ref": time["time_model_ref"], + "time_model_digest": time["time_model_digest"], + "time_state": readback, + "post_time_state": readback, + } + if SCENARIOS[scenario] == "mixed-handoff": + trusted["composition_state"] = _composition_state() + return trusted + + +def _stage_context(scenario: str, **overrides: object) -> contracts.MixedBackendStageContext: + return contracts.MixedBackendStageContext(**(_trusted(scenario) | overrides)) + + +def _validate(scenario: str, *, binding=None, responses=None, reports=None, **trusted: object) -> None: + request, default_responses, default_reports = _scenario(scenario) + contracts.validate_mixed_backend_stage_reports( + binding or _binding(SCENARIOS[scenario]), + request, + default_responses if responses is None else responses, + default_reports if reports is None else reports, + context=_stage_context(scenario, **trusted), + ) + + +def _restage(report, **stage: object) -> contracts.MixedBackendStageReportModel: + payload = report.model_dump(mode="json") + payload["stage"].update(stage) + return contracts.MixedBackendStageReportModel.model_validate(payload) + + +def _remessage(response, **message: object) -> contracts.BackendOperationResponseModel: + payload = response.model_dump(mode="json") + payload["message"].update(message) + return contracts.BackendOperationResponseModel.model_validate(payload) + + +def _failed_outcome(response, *cited) -> contracts.BackendOperationResponseModel: + """Rewrite a transcript's outcome as a known failure with no effect that cites the given reports.""" + + references = [ + { + "contract_id": STAGES, + "artifact_id": f"stage:{report.stage.stage}", + "digest": canonical_json_digest(report.model_dump(mode="json")), + } + for report in cited + ] + effects = response.message.effects.model_dump(mode="json") | { + "effect": "absent", + "cessation_established": True, + "evidence_refs": references, + "residual_scope": [], + "residual_state": None, + } + return _remessage( + response, + proposed_state="failed", + satisfaction="unsatisfied", + release_gates_satisfied=False, + result=None, + effects=effects, + ) + + +def _reseal(profile, change) -> object: + fields = profile.model_dump(mode="python", exclude={"profile_digest"}) + change(fields) + return seal_mixed_composition_profile(**fields) + + +@pytest.mark.parametrize("scenario", sorted(SCENARIOS)) +def test_example_transcripts_validate_for_each_supported_arrangement(scenario: str) -> None: + _validate(scenario) + + +def test_execution_delivery_and_observation_remain_distinct_evidenced_stages() -> None: + _, _, reports = _scenario("mixed-edge") + stages = {report.stage.stage: report.stage for report in reports} + + assert list(stages) == ["time-grant", "execution", "delivery", "observation"] + assert {stages[name].evidence_refs for name in ("execution", "delivery", "observation")} == { + ("evidence:backend-readback",), + ("evidence:destination-receipt",), + ("evidence:participant-readback",), + } + _, _, partial = _scenario("mixed-edge-partial") + assert [report.stage.stage for report in partial] == ["time-grant", "execution"] + assert partial[1].stage.status == "partial" + + +@pytest.mark.parametrize( + ("profile_factory", "name"), [(_runtime_mixed_profile, "mixed-edge"), (_staged_profile, "mixed-handoff")] +) +def test_bindings_join_the_admitted_sealed_profile(profile_factory, name: str) -> None: + profile = profile_factory() + contracts.validate_mixed_backend_bindings(profile, _context(profile), [_binding(name)]) + + +def _grow_membership(fields: dict) -> None: + fields["phases"]["phase.emu"]["active_component_ids"] = ["sim", "emu"] + fields["phases"]["phase.emu"]["active_allocation_ids"] += ["allocation.participant", "allocation.action"] + for allocation_id in ("allocation.participant", "allocation.action"): + fields["allocations"][allocation_id]["phase_ids"] = ["phase.sim", "phase.emu"] + + +def _keep_membership(fields: dict) -> None: + fields["phases"]["phase.sim2"] = {**fields["phases"]["phase.sim"], "phase_id": "phase.sim2"} + for allocation_id in ("allocation.participant", "allocation.action"): + fields["allocations"][allocation_id]["phase_ids"] = ["phase.sim", "phase.sim2"] + fields["phase_order"] = ["phase.sim", "phase.sim2", "phase.emu"] + template = fields["transitions"].pop("transition.sim-to-emu") + fields["transitions"] = { + "transition.sim-to-sim2": { + **template, + "transition_id": "transition.sim-to-sim2", + "target_phase_id": "phase.sim2", + }, + "transition.sim2-to-emu": { + **template, + "transition_id": "transition.sim2-to-emu", + "source_phase_id": "phase.sim2", + }, + } + + +def _wall_clock_edge(fields: dict) -> None: + fields["edges"]["edge.sim-to-emu"]["time_binding"]["ordering_basis"] = "wall_clock_only" + + +def _defer_owner_allocation(fields: dict) -> None: + # The destination action allocation becomes active only in a later phase + # where the edge is inactive, so a binding naming it can never execute. + main = fields["phases"]["phase.main"] + main["active_allocation_ids"].remove("allocation.action") + fields["phases"]["phase.later"] = { + **main, + "phase_id": "phase.later", + "active_allocation_ids": ["allocation.action"], + "active_edge_ids": [], + } + fields["allocations"]["allocation.action"]["phase_ids"] = ["phase.later"] + fields["phase_order"] = ["phase.main", "phase.later"] + template = _staged_profile().transitions["transition.sim-to-emu"].model_dump(mode="python") + fields["transitions"] = { + "transition.main-to-later": { + **template, + "transition_id": "transition.main-to-later", + "source_phase_id": "phase.main", + "target_phase_id": "phase.later", + } + } + + +@pytest.mark.parametrize( + ("profile", "bindings", "rebind", "message"), + [ + (_runtime_mixed_profile, [], True, "active mixed edge requires an executable binding"), + (_staged_profile, [], True, "requires an executable handoff binding"), + (_staged_profile, [_binding()], False, "another composition profile"), + (_runtime_mixed_profile, [_binding(), _binding()], True, "identities must be unique"), + (lambda: _reseal(_runtime_mixed_profile(), _wall_clock_edge), [], True, "ungoverned order"), + (lambda: _reseal(_staged_profile(), _grow_membership), [], True, "outside one-to-one native handoff"), + ( + lambda: _reseal(_runtime_mixed_profile(), _defer_owner_allocation), + [_binding()], + True, + "own the destination provider's action allocation", + ), + ( + lambda: _reseal(_staged_profile(), _keep_membership), + [_binding("mixed-handoff", transition_id="transition.sim-to-sim2")], + True, + "needs no native handoff binding", + ), + ], +) +def test_binding_sets_refuse_missing_foreign_or_unsupported_obligations( + profile, bindings, rebind: bool, message: str +) -> None: + # ``rebind`` points the bindings at the selected profile so that only the + # case's own defect remains; the foreign-profile case keeps its identity. + selected = profile() + identity = {"profile_id": selected.profile_id, "profile_digest": selected.profile_digest} + rebound = [binding.model_copy(update=identity) if rebind else binding for binding in bindings] + context = _context(selected) + with pytest.raises(ValueError, match=message): + contracts.validate_mixed_backend_bindings(selected, context, rebound) + + +def test_alternative_profiles_admit_no_executable_binding() -> None: + alternative = _runtime_profile() + contracts.validate_mixed_backend_bindings(alternative, _context(alternative), []) + foreign = _binding().model_copy( + update={"profile_id": alternative.profile_id, "profile_digest": alternative.profile_digest} + ) + context = _context(alternative) + with pytest.raises(ValueError, match="must name admitted edges"): + contracts.validate_mixed_backend_bindings(alternative, context, [foreign]) + + +def test_one_obligation_cannot_be_bound_twice() -> None: + profile = _runtime_mixed_profile() + bindings = [_binding(), _binding().model_copy(update={"binding_id": "binding:edge.duplicate"})] + context = _context(profile) + with pytest.raises(ValueError, match="binds one obligation twice"): + contracts.validate_mixed_backend_bindings(profile, context, bindings) + + +def test_component_keeping_transitions_need_no_binding() -> None: + profile = _reseal(_staged_profile(), _keep_membership) + handoff = _binding("mixed-handoff", transition_id="transition.sim2-to-emu").model_copy( + update={"profile_id": profile.profile_id, "profile_digest": profile.profile_digest} + ) + contracts.validate_mixed_backend_bindings(profile, _context(profile), [handoff]) + + +def test_binding_sets_and_stage_transcripts_are_bounded() -> None: + # One past the published bounds of 2048 bindings and 64 stage reports. + profile = _runtime_mixed_profile() + context, oversized = _context(profile), [_binding()] * 2049 + with pytest.raises(ValueError, match="binding set exceeds its bound"): + contracts.validate_mixed_backend_bindings(profile, context, oversized) + _, responses, reports = _scenario("mixed-edge") + with pytest.raises(ValueError, match="transcript exceeds its bound"): + _validate("mixed-edge", responses=responses, reports=[reports[0]] * 65) + + +EDGE_TIME = _fixture(BINDING, "valid", "mixed-edge")["subject"]["time"] + + +@pytest.mark.parametrize( + "subject", + [ + {"owner_component_id": "sim"}, + {"owner_allocation_id": "allocation.participant"}, + {"bridge": {"service_ref": "route:unadmitted", "version": "1", "digest": "sha256:" + "1" * 64}}, + {"audience_scope_ref": "audience:other"}, + {"participant_address": "participant.behavior.blue-agent"}, + {"required_evidence_refs": ["evidence:unrelated"]}, + {"mapping_loss": {**_fixture(BINDING, "valid", "mixed-edge")["subject"]["mapping_loss"], "kind": "none"}}, + {"time": {**EDGE_TIME, "ordering_basis": "total_order"}}, + {"time": {**EDGE_TIME, "time_model_digest": "sha256:" + "e" * 64}}, + {"time": {**EDGE_TIME, "destination_clock_address": "time.clocks.sim"}}, + {"time": {**EDGE_TIME, "temporal_coupling": "tight"}}, + ], +) +def test_edge_binding_must_match_the_admitted_edge_and_destination_owner(subject: dict) -> None: + profile = _runtime_mixed_profile() + context, bindings = _context(profile), [_binding(**subject)] + with pytest.raises(ValueError, match="mixed edge binding"): + contracts.validate_mixed_backend_bindings(profile, context, bindings) + + +HANDOFF_TIME = _fixture(BINDING, "valid", "mixed-handoff")["subject"]["time"] + + +@pytest.mark.parametrize( + ("subject", "message"), + [ + ({"source_component_id": "emu", "destination_component_id": "sim"}, "transition ownership"), + ({"destination_owner_ref": "native-ownership:other"}, "transition ownership"), + ({"required_evidence_refs": ["evidence:unrelated"]}, "transition ownership"), + ({"time": {**HANDOFF_TIME, "time_model_digest": "sha256:" + "e" * 64}}, "unresolved or stale"), + ({"time": {**HANDOFF_TIME, "mapping_ref": "time.mappings.unknown"}}, "clocks and mapping"), + ( + { + "time": { + **HANDOFF_TIME, + "source_clock_address": "time.clocks.emu", + "destination_clock_address": "time.clocks.sim", + } + }, + "clocks and mapping", + ), + ], +) +def test_handoff_binding_must_match_one_to_one_ownership_and_resolved_time(subject: dict, message: str) -> None: + profile = _staged_profile() + context, bindings = _context(profile), [_binding("mixed-handoff", **subject)] + with pytest.raises(ValueError, match=message): + contracts.validate_mixed_backend_bindings(profile, context, bindings) + + +EDGE_SUBJECT = _fixture(BINDING, "valid", "mixed-edge")["subject"] +BRIDGE_SERVICE, DELIVERY_SERVICE = EDGE_SUBJECT["bridge"], EDGE_SUBJECT["delivery_reader"] +TRANSFER_SERVICE = _fixture(BINDING, "valid", "mixed-handoff")["subject"]["transfer"] + + +@pytest.mark.parametrize( + "payload", + [ + pytest.param(_fixture(BINDING, "invalid", "bridge-as-reader"), id="invalid-bridge-as-reader"), + pytest.param(_fixture(BINDING, "invalid", "transfer-as-owner-reader"), id="invalid-transfer-as-owner-reader"), + pytest.param(_subject_payload("mixed-edge", delivery_reader=BRIDGE_SERVICE), id="bridge-reads-delivery"), + pytest.param(_subject_payload("mixed-edge", observation_reader=BRIDGE_SERVICE), id="bridge-reads-observation"), + pytest.param(_subject_payload("mixed-edge", observation_reader=DELIVERY_SERVICE), id="one-reader-two-stages"), + pytest.param( + _subject_payload("mixed-edge", time={**EDGE_TIME, "coordinator": BRIDGE_SERVICE}), + id="bridge-grants-order", + ), + pytest.param( + _subject_payload("mixed-edge", delivery_reader={**BRIDGE_SERVICE, "service_ref": "reader:renamed"}), + id="shared-digest", + ), + pytest.param( + _subject_payload( + "mixed-edge", delivery_reader={**DELIVERY_SERVICE, "service_ref": BRIDGE_SERVICE["service_ref"]} + ), + id="shared-reference", + ), + pytest.param( + _subject_payload("mixed-handoff", time={**HANDOFF_TIME, "coordinator": TRANSFER_SERVICE}), + id="transfer-grants-order", + ), + pytest.param( + _subject_payload("mixed-handoff", owner_reader=HANDOFF_TIME["coordinator"]), + id="coordinator-reads-owner", + ), + ], +) +def test_binding_pins_a_distinct_service_for_each_role(payload: dict) -> None: + # Sharing a reference or a digest would let one service report two stages, + # such as a bridge reading back its own delivery or granting its own order. + with pytest.raises(ValidationError, match="distinct service for each role"): + contracts.MixedBackendExecutionBindingModel.model_validate(payload) + + +def _capabilities(name: str) -> contracts.BackendOperationCapabilitiesModel: + return contracts.BackendOperationCapabilitiesModel.model_validate( + _fixture("backend-operation-capabilities-v1", "valid", name) + ) + + +def test_contextual_admission_uses_the_shared_operation_protocol() -> None: + request, responses, _ = _scenario("mixed-edge") + binding, capabilities = _binding(), _capabilities("mixed-bridge") + contracts.require_mixed_backend_admission(binding, request, capabilities, responses[0]) + refused, refusal, _ = _scenario("mixed-edge-refused") + with pytest.raises(ValueError, match="context refused"): + contracts.require_mixed_backend_admission(binding, refused, capabilities, refusal[0]) + + +def _edge_request( + operation_kind: str = "participant-crossing", backend_id: str = "route:portable" +) -> contracts.BackendOperationRequestModel: + payload = _fixture("backend-operation-request-v1", "valid", "mixed-edge") + payload["binding"]["context"]["operation_kind"] = operation_kind + payload["binding"]["backend_id"] = backend_id + return contracts.BackendOperationRequestModel.model_validate(payload) + + +@pytest.mark.parametrize( + ("binding", "changes", "message"), + [ + (lambda: _binding("mixed-handoff"), {}, "does not commit"), + (lambda: _binding(audience_scope_ref="audience:other"), {}, "does not commit"), + (_binding, {"operation_kind": "composition-phase"}, "operation kind differs"), + (_binding, {"backend_id": "transfer:native-ownership"}, "installed mixed service"), + ], +) +def test_request_must_commit_to_the_exact_binding_kind_and_installed_service(binding, changes, message) -> None: + selected, request = binding(), _edge_request(**changes) + with pytest.raises(ValueError, match=message): + contracts.require_mixed_backend_request(selected, request) + + +CHAIN_POSITION = "sequence differs from its stage's chain position" +OWNER_READBACK = { + "stage": "owner-readback", + "producer": _fixture(BINDING, "valid", "mixed-handoff")["subject"]["owner_reader"], + "owner_component_id": "emu", + "owner_ref": "native-ownership:emu", + "phase_revision": 1, + "evidence_refs": ["evidence:owner-readback:emu"], +} + + +def _report(base, sequence: int, stage: dict) -> contracts.MixedBackendStageReportModel: + payload = base.model_dump(mode="json") | {"sequence": sequence, "stage": stage} + return contracts.MixedBackendStageReportModel.model_validate(payload) + + +def _edge_case(mutate) -> tuple[list, list]: + _, responses, reports = _scenario("mixed-edge") + return mutate(list(responses), list(reports)) + + +def _grant_case(**grant): + return lambda responses, reports: (responses, [_restage(reports[0], **grant), *reports[1:]]) + + +def _progress_cites_unsupplied_report(responses: list, reports: list) -> tuple[list, list]: + unsupplied = _restage(reports[2], receipt_ref="receipt:other") + reference = { + "contract_id": STAGES, + "artifact_id": "stage:mixed-edge:unsupplied", + "digest": canonical_json_digest(unsupplied.model_dump(mode="json")), + } + payload = responses[1].model_dump(mode="json") | { + "sequence": 3, + "message": {"kind": "progress", "phase": "executing", "evidence_refs": [reference]}, + } + return [*responses[:2], contracts.BackendOperationResponseModel.model_validate(payload)], reports + + +def _rebridged(responses: list, reports: list) -> tuple[list, list]: + producer = reports[1].stage.producer.model_dump(mode="json") | {"version": "2"} + return responses, [reports[0], _restage(reports[1], producer=producer), *reports[2:]] + + +@pytest.mark.parametrize( + ("mutate", "message"), + [ + (lambda r, s: (r, s[1:]), "precedes its prerequisite"), + (lambda r, s: (r, [s[0], s[2], s[3]]), "precedes its prerequisite"), + (lambda r, s: (r, [s[0], s[1], s[3]]), "precedes its prerequisite"), + (lambda r, s: (r[:1], s[:2]), "accepted acknowledgement"), + (lambda r, s: (r, [_restage(s[0], comparison="incomparable"), *s[1:]]), "ordered time grant"), + ( + _grant_case(source_coordinate=_coordinate(0, 0, 0), destination_coordinate=_coordinate(0, 999999, 0)), + "committed time readback", + ), + (_grant_case(timing_evidence_refs=["evidence:time-grant"]), "admitted evidence"), + (_grant_case(ordering_basis="total_order"), "bound mapping or ordering basis"), + ( + lambda r, s: (r, [s[0], _restage(s[1], mapping_loss_refs=[]), *s[2:]]), + "installed subjects or declared loss", + ), + (_rebridged, "names a producer other than"), + (lambda r, s: (r, [*s[:2], _restage(s[2], destination_component_id="sim"), s[3]]), "destination provider"), + (lambda r, s: (r, [*s[:3], _restage(s[3], audience_scope_ref="audience:other")]), "participant or audience"), + (lambda r, s: (r, [*s[:2], _report(s[1], 3, OWNER_READBACK)]), "belong to this mixed binding"), + (lambda r, s: (r, [*s, s[3].model_copy(update={"sequence": 9})]), CHAIN_POSITION), + (lambda r, s: (r, [*s, _restage(s[3], observation_ref="observation:rewritten")]), "changed its content"), + (lambda r, s: (r, s[:2]), "claims more than the mixed stages establish"), + (lambda r, s: (r, [s[0], s[1], _restage(s[2], receipt_ref="receipt:other"), s[3]]), "cites a stage report"), + (_progress_cites_unsupplied_report, "cites a stage report"), + ], +) +def test_edge_transcript_rejects_out_of_order_foreign_or_overclaimed_stages(mutate, message: str) -> None: + responses, reports = _edge_case(mutate) + with pytest.raises(ValueError, match=message): + _validate("mixed-edge", responses=responses, reports=reports) + + +def _renumbered(scenario: str, sequences: tuple) -> tuple[list, list]: + """A scenario's reports under other sequence numbers, re-cited so the numbering is the only defect.""" + + _, responses, reports = _scenario(scenario) + renumbered = [report.model_copy(update={"sequence": n}) for report, n in zip(reports, sequences, strict=True)] + digests = { + canonical_json_digest(old.model_dump(mode="json")): canonical_json_digest(new.model_dump(mode="json")) + for old, new in zip(reports, renumbered, strict=True) + } + recited = [] + for response in responses: + payload = response.model_dump(mode="json") + message = payload["message"] + for reference in [*message.get("evidence_refs", ()), *(message.get("effects") or {}).get("evidence_refs", ())]: + reference["digest"] = digests.get(reference["digest"], reference["digest"]) + recited.append(contracts.BackendOperationResponseModel.model_validate(payload)) + return recited, renumbered + + +@pytest.mark.parametrize( + ("scenario", "sequences"), + [ + ("mixed-edge", (1, 1, 1, 1)), # each producer numbers its own report from 1 + ("mixed-edge-partial", (1, 1)), + ("mixed-handoff", (1, 1, 1)), + ("mixed-edge", (5, 3, 6, 7)), # the coordinator picks 5 and the bridge 3 + ("mixed-handoff", (5, 3, 6)), + ("mixed-edge", (10, 20, 30, 40)), # ascending, but not the chain positions + ], +) +def test_independent_producers_number_each_stage_by_its_chain_position(scenario: str, sequences: tuple) -> None: + # A producer sees neither the other producers' reports nor a shared counter, + # so only the stage's fixed chain position can give every report its number. + responses, reports = _renumbered(scenario, sequences) + with pytest.raises(ValueError, match=CHAIN_POSITION): + _validate(scenario, responses=responses, reports=reports) + + +@pytest.mark.parametrize("scenario", ["mixed-edge", "mixed-edge-partial", "mixed-handoff", "mixed-handoff-stale"]) +def test_chain_numbered_reports_are_accepted_in_any_supplied_order(scenario: str) -> None: + _, _, reports = _scenario(scenario) + _validate(scenario, reports=reports[::-1]) + + +@pytest.mark.parametrize( + ("source", "destination"), + [((0, 4, 0), (0, 3, 0)), ((0, 4, 0), (1, 9, 0)), ((0, 4, 2), (0, 4, 1))], +) +def test_ordered_grant_must_establish_the_mapped_order_at_the_committed_readback(source, destination) -> None: + # The grant repeats the committed coordinates exactly, but they do not + # support the claimed order: a later mapped tick, another segment, or a + # later source microstep at an equal mapped tick. + _, _, reports = _scenario("mixed-edge") + grant = _restage( + reports[0], source_coordinate=_coordinate(*source), destination_coordinate=_coordinate(*destination) + ) + committed = _time_state(source, destination) + with pytest.raises(ValueError, match="required order"): + _validate("mixed-edge", reports=[grant, *reports[1:]], time_state=committed) + + +@pytest.mark.parametrize( + ("scenario", "index", "impostor"), + [ + ("mixed-edge", 0, 1), # the bridge cannot grant its own time order + ("mixed-edge", 1, 2), # a reader cannot report bridge execution + ("mixed-edge", 2, 1), # the bridge cannot report destination delivery + ("mixed-edge", 3, 1), # nor participant observation + ("mixed-handoff", 1, 2), # the owner reader cannot report the transfer + ("mixed-handoff", 2, 1), # the transfer service cannot read back its own result + ], +) +def test_each_stage_must_name_the_service_pinned_for_its_role(scenario: str, index: int, impostor: int) -> None: + _, responses, reports = _scenario(scenario) + reports[index] = _restage(reports[index], producer=reports[impostor].stage.producer.model_dump(mode="json")) + with pytest.raises(ValueError, match="names a producer other than"): + _validate(scenario, responses=responses, reports=reports) + + +def _rebind(binding: contracts.MixedBackendExecutionBindingModel, name: str = "mixed-edge") -> tuple: + """Recommit a scenario's request and correlated messages to another installed binding.""" + + request, responses, reports = _scenario(name) + request = request.model_copy(update={"command": contracts.mixed_backend_binding_reference(binding)}) + digest = contracts.backend_operation_request_digest(request) + rebound = [message.model_copy(update={"request_digest": digest}) for message in (*responses, *reports)] + return request, rebound[: len(responses)], rebound[len(responses) :] + + +def test_an_observation_report_needs_a_pinned_observation_reader() -> None: + binding = _binding(observation_reader=None) + request, responses, reports = _rebind(binding) + context = _stage_context("mixed-edge") + with pytest.raises(ValueError, match="names a producer other than"): + contracts.validate_mixed_backend_stage_reports(binding, request, responses, reports, context=context) + + +def _foreign_time_state() -> dict: + return {"time_state": _time_state(declaration=_declaration(description="another emulation clock"))} + + +def _uncovered_clocks() -> dict: + declaration = _declaration(address="time.clocks.other") + return {"time_model": declaration, "time_state": _time_state(declaration=declaration), "post_time_state": None} + + +def _foreign_post_time_state() -> dict: + return {"post_time_state": _time_state(declaration=_declaration(description="another emulation clock"))} + + +def _composition_after_handoff() -> dict: + # The transition already happened at the same head and revision. + return {"composition_state": _composition_state(phase_id="phase.emu", active_component_ids=["emu"])} + + +@pytest.mark.parametrize( + ("scenario", "trusted", "message"), + [ + ("mixed-edge", _foreign_time_state, "declaration_digest does not match"), + ("mixed-edge", _uncovered_clocks, "does not cover the bound clocks"), + ("mixed-edge", _foreign_post_time_state, "declaration_digest does not match"), + ("mixed-edge", lambda: {"time_model_digest": "sha256:" + "e" * 64}, "time model reference or digest"), + ("mixed-handoff", lambda: {"time_model_ref": "time-model:other"}, "time model reference or digest"), + ("mixed-handoff", lambda: {"composition_state": None}, "requires the committed composition state"), + ( + "mixed-handoff", + lambda: {"composition_state": _composition_state(profile_id="profile:other")}, + "belongs to another profile", + ), + ("mixed-handoff", _composition_after_handoff, "does not precede the native handoff"), + ( + "mixed-handoff", + lambda: {"composition_state": _composition_state(active_component_ids=["sim", "emu"])}, + "does not precede the native handoff", + ), + ( + "mixed-handoff", + lambda: {"composition_state": _composition_state(active_component_ids=["other"])}, + "does not precede the native handoff", + ), + ("mixed-edge", lambda: {"composition_state": _edge_composition_state()}, "does not activate the bound edge"), + ], +) +def test_trusted_inputs_must_match_the_binding_time_model_clocks_and_composition(scenario, trusted, message) -> None: + overrides = trusted() + with pytest.raises(ValueError, match=message): + _validate(scenario, **overrides) + + +def test_an_edge_validates_against_a_composition_state_that_activates_it() -> None: + _validate("mixed-edge", composition_state=_edge_composition_state("edge.sim-to-emu")) + + +@pytest.mark.parametrize("scenario", ["mixed-edge", "mixed-handoff"]) +def test_composition_readback_must_belong_to_the_invocation_run(scenario: str) -> None: + state = _edge_composition_state("edge.sim-to-emu") if scenario == "mixed-edge" else _composition_state() + _validate(scenario, composition_state=state) + foreign = state.model_copy(update={"run_id": "other"}) + with pytest.raises(ValueError, match="committed composition state belongs to another run"): + _validate(scenario, composition_state=foreign) + + +@pytest.mark.parametrize( + ("handoff", "readback"), + [ + ({"predecessor_history_head": "composition:foreign:head"}, {}), + ({"phase_revision": 41}, {}), + ({"predecessor_history_head": "composition:foreign:head", "phase_revision": 41}, {"phase_revision": 42}), + ], +) +def test_native_handoff_is_fenced_on_the_committed_composition_head_and_revision(handoff, readback) -> None: + _, responses, reports = _scenario("mixed-handoff") + reports[1:] = [_restage(reports[1], **handoff), _restage(reports[2], **readback)] + with pytest.raises(ValueError, match="committed composition history head or phase revision"): + _validate("mixed-handoff", responses=responses, reports=reports) + + +FAILED_EXECUTION = {"status": "failed", "cessation_evidence_refs": ["evidence:provider-cessation"]} + + +@pytest.mark.parametrize("execution", [{"status": "unknown", "evidence_refs": []}, FAILED_EXECUTION]) +def test_unknown_or_failed_execution_cannot_support_a_success_outcome(execution: dict) -> None: + _, responses, reports = _scenario("mixed-edge") + weakened = [reports[0], _restage(reports[1], **execution)] + with pytest.raises(ValueError, match="claims more"): + _validate("mixed-edge", responses=responses, reports=weakened) + + +def test_partial_execution_cannot_settle_as_a_known_failure() -> None: + _, responses, reports = _scenario("mixed-edge-partial") + effects = responses[-1].message.effects.model_dump(mode="json") | {"cessation_established": True} + failed = _remessage(responses[-1], proposed_state="failed", satisfaction="unsatisfied", effects=effects) + with pytest.raises(ValueError, match="claims more"): + _validate("mixed-edge-partial", responses=[responses[0], failed], reports=reports) + + +def test_known_failed_execution_cannot_be_followed_by_delivery() -> None: + _, responses, reports = _scenario("mixed-edge") + delivered_after_failure = [reports[0], _restage(reports[1], **FAILED_EXECUTION), reports[2]] + with pytest.raises(ValueError, match="cannot be followed by delivery"): + _validate("mixed-edge", responses=responses[:2], reports=delivered_after_failure) + + +def test_known_failed_execution_settles_without_post_effect_time() -> None: + _, responses, reports = _scenario("mixed-edge") + failed = _restage(reports[1], **FAILED_EXECUTION) + transcript = [*responses[:-1], _failed_outcome(responses[-1], failed)] + _validate("mixed-edge", responses=transcript, reports=[reports[0], failed], post_time_state=None) + + +@pytest.mark.parametrize("scenario", ["mixed-edge", "mixed-handoff"]) +def test_incomparable_grant_without_invocation_settles_as_known_failure(scenario: str) -> None: + _, responses, reports = _scenario(scenario) + grant = _restage(reports[0], comparison="incomparable") + transcript = [*responses[:-1], _failed_outcome(responses[-1], grant)] + _validate(scenario, responses=transcript, reports=[grant], post_time_state=None) + + +@pytest.mark.parametrize("scenario", ["mixed-edge", "mixed-handoff"]) +def test_an_ordered_grant_without_invocation_establishes_no_failure(scenario: str) -> None: + # The invocation may have started without reporting, so nothing is known. + _, responses, reports = _scenario(scenario) + transcript = [*responses[:-1], _failed_outcome(responses[-1], reports[0])] + with pytest.raises(ValueError, match="claims more"): + _validate(scenario, responses=transcript, reports=reports[:1]) + + +POST_READBACKS = { + "missing": lambda: None, + "source-regressed": lambda: _time_state(source=(0, 3, 0)), + "destination-regressed": lambda: _time_state(destination=(0, 1, 0)), +} + + +@pytest.mark.parametrize("scenario", ["mixed-edge", "mixed-handoff", "mixed-handoff-stale"]) +@pytest.mark.parametrize("post", sorted(POST_READBACKS)) +def test_settlement_needs_a_confirmed_post_invocation_time_readback(scenario: str, post: str) -> None: + readback = POST_READBACKS[post]() + with pytest.raises(ValueError, match="claims more"): + _validate(scenario, post_time_state=readback) + + +def test_contextual_refusal_permits_a_grant_record_but_no_invocation_stage() -> None: + refused, _, _ = _scenario("mixed-edge-refused") + _, _, reports = _scenario("mixed-edge") + correlation = { + "binding": refused.binding.model_dump(mode="json"), + "request_digest": contracts.backend_operation_request_digest(refused), + } + rebound = [ + contracts.MixedBackendStageReportModel.model_validate(report.model_dump(mode="json") | correlation) + for report in reports[:2] + ] + _validate("mixed-edge-refused", reports=rebound[:1]) + with pytest.raises(ValueError, match="accepted acknowledgement"): + _validate("mixed-edge-refused", reports=rebound) + + +@pytest.mark.parametrize( + ("scenario", "index", "stage", "message"), + [ + ( + "mixed-handoff", + 2, + {"owner_component_id": "sim", "owner_ref": "native-ownership:sim", "phase_revision": 0}, + "claims more", + ), + ( + "mixed-handoff-stale", + 2, + {"owner_component_id": "emu", "owner_ref": "native-ownership:emu", "phase_revision": 1}, + "claims more", + ), + ("mixed-handoff", 1, {"status": "pending"}, "claims more"), + ("mixed-handoff", 1, {"order_ref": "order:other"}, "granted order"), + ("mixed-handoff", 1, {"evidence_refs": ["evidence:native-transfer"]}, "admitted evidence"), + ], +) +def test_handoff_settles_only_on_a_correlated_matching_owner_readback(scenario, index, stage, message) -> None: + _, responses, reports = _scenario(scenario) + reports[index] = _restage(reports[index], **stage) + with pytest.raises(ValueError, match=message): + _validate(scenario, responses=responses, reports=reports) + + +def test_committed_transfer_without_owner_readback_cannot_settle() -> None: + _, responses, reports = _scenario("mixed-handoff") + with pytest.raises(ValueError, match="claims more"): + _validate("mixed-handoff", responses=responses, reports=reports[:2]) + + +@pytest.mark.parametrize("contract_id", MIXED_BACKEND_CONTRACT_IDS) +def test_published_schema_matches_the_bundle_and_classifies_the_example_corpus(contract_id: str) -> None: + schema = json.loads((ROOT / f"contracts/schemas/control-plane/{contract_id}.json").read_text(encoding="utf-8")) + assert schema == contracts.schema_bundle()[contract_id] + model = ( + contracts.MixedBackendExecutionBindingModel + if contract_id == BINDING + else contracts.MixedBackendStageReportModel + ) + for kind in ("valid", "context-invalid"): + for path in sorted((FIXTURES / contract_id / kind).glob("*.json")): + payload = json.loads(path.read_text(encoding="utf-8")) + Draft202012Validator(schema).validate(payload) + model.model_validate(payload) + invalid = sorted((FIXTURES / contract_id / "invalid").glob("*.json")) + assert invalid + for path in invalid: + payload = json.loads(path.read_text(encoding="utf-8")) + with pytest.raises(ValidationError): + model.model_validate(payload) + + +@pytest.mark.parametrize( + ("family", "name", "change", "message"), + [ + (BINDING, "mixed-handoff", {"destination_component_id": "sim"}, "distinct source and destination"), + (STAGES, "mixed-edge-02", {"status": "succeeded", "evidence_refs": []}, "require readback evidence"), + (STAGES, "mixed-edge-02", {"status": "partial", "evidence_refs": []}, "require readback evidence"), + ], +) +def test_closed_models_refuse_contradictory_local_facts(family: str, name: str, change: dict, message: str) -> None: + payload = _fixture(family, "valid", name) + payload["subject" if family == BINDING else "stage"].update(change) + model = contracts.MixedBackendExecutionBindingModel if family == BINDING else contracts.MixedBackendStageReportModel + with pytest.raises(ValidationError, match=message): + model.model_validate(payload) + + +def test_context_invalid_examples_fail_their_trusted_joins() -> None: + profile = _runtime_mixed_profile() + bridge = contracts.MixedBackendExecutionBindingModel.model_validate( + _fixture(BINDING, "context-invalid", "foreign-bridge") + ) + context = _context(profile) + with pytest.raises(ValueError, match="differs from the admitted edge"): + contracts.validate_mixed_backend_bindings(profile, context, [bridge]) + _, responses, reports = _scenario("mixed-edge") + foreign = contracts.MixedBackendStageReportModel.model_validate( + _fixture(STAGES, "context-invalid", "foreign-invocation") + ) + with pytest.raises(ValueError, match="another invocation"): + _validate("mixed-edge", responses=responses, reports=[*reports, foreign]) + + +def _accepts(*names: str) -> dict: + return {name: (lambda request: request) for name in names} + + +BRIDGE = dict( + operation_capabilities=lambda: None, + execution_binding=lambda: None, + **_accepts("check_operation", "start_operation", "observe_operation", "cancel_operation", "reconcile_operation"), + stage_reports=lambda control: control, +) +SERVICES = { + "bridge": BRIDGE, + "coordinator": {"grant": lambda request, time_state: (request, time_state)}, + "reader": {"read_stage": lambda control: control}, +} +DECLARED = (*BACKEND_OPERATION_CONTRACT_IDS, *MIXED_BACKEND_CONTRACT_IDS) + + +@pytest.mark.parametrize("role", sorted(SERVICES)) +def test_service_declarations_and_call_shapes_are_checked_without_invocation(role: str) -> None: + from types import SimpleNamespace + + installed, empty = SimpleNamespace(**SERVICES[role]), SimpleNamespace() + narrowed = SimpleNamespace(**{name: (lambda: None) for name in SERVICES[role]}) + require_mixed_backend_service(installed, role, DECLARED) + with pytest.raises(ValueError, match="not declared"): + require_mixed_backend_service(installed, role, BACKEND_OPERATION_CONTRACT_IDS) + with pytest.raises(ValueError, match="not installed"): + require_mixed_backend_service(empty, role, DECLARED) + with pytest.raises(ValueError, match="call shape"): + require_mixed_backend_service(narrowed, role, DECLARED) + + +@pytest.mark.parametrize( + ("method", "replacement", "message"), + [ + ("execution_binding", None, "mixed backend service protocol is not installed"), + ("stage_reports", None, "mixed backend service protocol is not installed"), + ("execution_binding", lambda required: required, "installed mixed backend method has incompatible call shape"), + ("stage_reports", lambda: None, "installed mixed backend method has incompatible call shape"), + ], +) +def test_a_bridge_needs_its_mixed_methods_beyond_the_shared_operation_protocol(method, replacement, message) -> None: + # Every shared operation method stays installed, so only the bridge's own + # binding and stage-report methods can be refused. + from types import SimpleNamespace + + bridge = SimpleNamespace(**(BRIDGE | {method: replacement})) + with pytest.raises(ValueError, match=message): + require_mixed_backend_service(bridge, "bridge", DECLARED) + + +def test_stub_and_reference_backends_do_not_advertise_mixed_backend_contracts() -> None: + from raes_backend_stubs.manifest import create_stub_manifest + from raes_reference_backend.manifest import REFERENCE_BACKEND_SUPPORTED_CONTRACT_VERSIONS + + assert set(MIXED_BACKEND_CONTRACT_IDS).isdisjoint(create_stub_manifest().supported_contract_versions) + assert set(MIXED_BACKEND_CONTRACT_IDS).isdisjoint(REFERENCE_BACKEND_SUPPORTED_CONTRACT_VERSIONS) diff --git a/implementations/python/tests/test_issue_989_versioned_evidence.py b/implementations/python/tests/test_issue_989_versioned_evidence.py index 31f182771..11ffe7b84 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("70.0.0"), _stub_release("71.0.0")], - "must be the explicit 72.0.0 retest", + [_stub_release("71.0.0"), _stub_release("72.0.0")], + "must be the explicit 73.0.0 retest", id="stale-current", ), pytest.param( - [_stub_release("71.0.0"), _stub_release("73.0.0")], - "must be the explicit 72.0.0 retest", + [_stub_release("72.0.0"), _stub_release("74.0.0")], + "must be the explicit 73.0.0 retest", id="unsupported-future", ), pytest.param( - [_stub_release("72.0.0", protocol_revision="1.0.0")], - "must be the explicit 72.0.0 retest", + [_stub_release("73.0.0", protocol_revision="1.0.0")], + "must be the explicit 73.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("72.0.0") - monkeypatch.setattr(_loading, "load_release_bundles", lambda _root: [_stub_release("71.0.0"), current]) + current = _stub_release("73.0.0") + monkeypatch.setattr(_loading, "load_release_bundles", lambda _root: [_stub_release("72.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"] == "72.0.0" + assert release.manifest["revision"] == "73.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"] == "71.0.0" + assert manifest["revision"] == "72.0.0" snapshot = deepcopy(snapshot) artifact = next(a for a in snapshot["artifacts"] if a["artifact_id"] == artifact_id) artifact["sha256"] = old_digest @@ -576,6 +576,7 @@ def test_no_capture_can_be_silently_dropped(monkeypatch, family, removed): "70.0.0", "71.0.0", "72.0.0", + "73.0.0", ] if family == "formal" else [ @@ -651,6 +652,7 @@ def test_no_capture_can_be_silently_dropped(monkeypatch, family, removed): "69.0.0", "70.0.0", "71.0.0", + "72.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 9993be42a..38423268d 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"] == "71.0.0" + assert manifest["revision"] == "72.0.0" def test_historical_failures_name_the_revision_specific_documents() -> None: diff --git a/specs/formal/runtime-contracts/participant-backend-contracts.md b/specs/formal/runtime-contracts/participant-backend-contracts.md index 039713150..4e83a6f59 100644 --- a/specs/formal/runtime-contracts/participant-backend-contracts.md +++ b/specs/formal/runtime-contracts/participant-backend-contracts.md @@ -180,6 +180,67 @@ physical-OT timing guarantee. Installed bindings are trusted runtime inputs against the sealed `sem-234/rev1` profile; this rule adds no manifest field, support vocabulary term, or published carrier revision. +### Published mixed-backend execution contracts (issue #1371) + +`mixed-backend-execution-binding-v1` is the closed plain-data form of one +installed binding for one admitted edge or component-changing transition. +`mixed-backend-stage-report-v1` carries one time-grant, execution, delivery, +observation, handoff, or owner-readback fact for one invocation of the +[backend operation protocol](backend-operation-supervision.md). Rules: + +- A backend may list both contract IDs in `supported_contract_versions`. The + listing is an opt-in declaration, not effective support. It adds no feature + term or support level, and it does not replace the joins above. +- Exactly one binding exists for each edge active in an admitted phase and for + each transition that replaces exactly one component with another. Missing, + foreign, duplicate, or contradictory bindings refuse the whole set, as do an + ungoverned edge order and any other component change. +- An edge binding uses operation kind `participant-crossing`. Its effect owner + is the destination provider's action allocation for the bound address, + active in at least one phase of the edge. Its `compiled-identity` + transformation preserves the authorized action address. Its bridge + reference equals the edge's routing reference, and its time coordinates, + temporal coupling, mapping loss, participant, audience, and evidence + references equal the admitted edge. +- A handoff binding uses operation kind `composition-phase`. It names the + leaving and joining components and their native ownership references, and + its clocks and mapping resolve in the trusted time model. +- Each role in one binding has its own service. No two of the bridge or + transfer service, the coordinator, and the readers share a service reference + or a digest, so a binding that pins one service to two roles is invalid. +- A shared request commits to one binding through its content-bound `command`, + is addressed to the pinned bridge or transfer service, and uses the + binding's operation kind. The binding reference digest and each stage-report + citation digest are SHA-256 over RFC 8785 canonical JSON of the complete + validated model, including materialized defaults and null values. +- Stage reports repeat the invocation binding and request digest and report + each stage at most once. A report's `sequence` is its stage's fixed chain + position: time grant 1, execution or handoff 2, delivery or owner readback + 3, and observation 4. Reports are accepted in ascending `sequence`, and a + stage needs its prerequisite stage. Each stage names its producer, which + equals the binding's coordinator, bridge, delivery reader, observation + reader, transfer service, or owner reader for that stage. Execution or + native transfer needs an `ordered` grant and an accepted acknowledgement. +- The caller resolves the trusted time model under the binding's time-model + reference and digest. A committed composition state belongs to the + invocation's run and binding's profile: the request's `run_scope` equals + `run:`. It still activates the bound edge, or holds the + handoff's source component but not its destination component. +- Time-grant coordinates equal the caller's committed time readback for both + bound clocks. A handoff names the committed composition history head and + phase revision, and its owner readback is judged against that revision. +- A proposed success or known failure must equal the state that the stages + and the caller's readbacks establish, and shared evidence cites only + supplied reports. Success needs a post-invocation time readback in which + neither bound clock moved backwards; so does a handoff failure. An + `incomparable` grant with no invocation stage establishes a known failure. + The [migration note](../../../docs/migration/mixed-backend-execution.md) + states the complete stage and settlement model. + +The validators are pure functions over trusted inputs resolved by the caller. +Passing them does not prove backend truth, installation, conformance, or +runtime adoption, and these rules do not describe the in-process coordinator. + ### Adversarial-control apparatus and backend support (issue #1004) The following governed `participant-runtime-behavior-features` terms let a diff --git a/tools/check_specification_coverage.py b/tools/check_specification_coverage.py index 7bf2b9865..4882beabb 100644 --- a/tools/check_specification_coverage.py +++ b/tools/check_specification_coverage.py @@ -176,12 +176,13 @@ def _load_bundle_index(repo_root: Path) -> list[tuple[str, dict[str, object]]]: "69.0.0", "70.0.0", "71.0.0", + "72.0.0", } if ( - dict(records)[current_path].get("revision") != "71.0.0" + dict(records)[current_path].get("revision") != "72.0.0" or {record.get("revision") for _, record in records} != supported_revisions ): - raise ValueError("coverage evidence requires the explicit current 71.0.0 release and supported history") + raise ValueError("coverage evidence requires the explicit current 72.0.0 release and supported history") return records diff --git a/tools/formal_semantic_validation/_loading.py b/tools/formal_semantic_validation/_loading.py index 242714714..1fb2f3bab 100644 --- a/tools/formal_semantic_validation/_loading.py +++ b/tools/formal_semantic_validation/_loading.py @@ -82,6 +82,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") != "72.0.0" or release.protocol.get("revision") != "2.0.0": - raise ValueError("the current formal evidence release must be the explicit 72.0.0 retest") + if release.manifest.get("revision") != "73.0.0" or release.protocol.get("revision") != "2.0.0": + raise ValueError("the current formal evidence release must be the explicit 73.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 b17c4b61e..d311e6bbe 100644 --- a/tools/formal_semantic_validation/_release_revisions.py +++ b/tools/formal_semantic_validation/_release_revisions.py @@ -73,9 +73,10 @@ "69.0.0", "70.0.0", "71.0.0", + "72.0.0", } -_SUPPORTED_RETEST_REVISIONS = _HISTORICAL_RETEST_REVISIONS | {"72.0.0"} +_SUPPORTED_RETEST_REVISIONS = _HISTORICAL_RETEST_REVISIONS | {"73.0.0"} _SOURCE_BOUND_RETEST_REVISIONS = _SUPPORTED_RETEST_REVISIONS - {"3.0.0"} _RETEST_BASELINE_REVISIONS = { @@ -150,4 +151,5 @@ "70.0.0": "69.0.0", "71.0.0": "70.0.0", "72.0.0": "71.0.0", + "73.0.0": "72.0.0", } diff --git a/tools/formal_semantic_validation/_releases.py b/tools/formal_semantic_validation/_releases.py index 579df51a6..1064491d7 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") == "72.0.0", + replay_current=manifest.get("revision") == "73.0.0", ) ) else: @@ -290,6 +290,7 @@ def _expected_corpus_revision(release_revision: object) -> str: "70.0.0", "71.0.0", "72.0.0", + "73.0.0", }: expected_corpus_revision = "4.0.0" return expected_corpus_revision diff --git a/tools/formal_semantic_validation/_retest.py b/tools/formal_semantic_validation/_retest.py index 0c62a1502..35954a715 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, 73)) +_SOURCE_STATE_REVISIONS = frozenset(f"{revision}.0.0" for revision in range(4, 74)) @dataclasses.dataclass(frozen=True)