From abf944ab966e93d1caaf0f93963991669f67b758 Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Fri, 25 Sep 2026 04:19:37 +0200 Subject: [PATCH 1/7] feat: publish backend operation and supervision contracts --- contracts/README.md | 6 + .../valid/provider.json | 14 + .../valid/cancel-race-01.json | 43 ++ .../valid/partial-cancel-01.json | 43 ++ .../valid/uncertain-01.json | 43 ++ .../valid/accepted.json | 51 ++ .../valid/cancel-race.json | 51 ++ .../valid/duplicate.json | 51 ++ .../valid/partial-cancel.json | 51 ++ .../valid/refused.json | 51 ++ .../valid/uncertain.json | 51 ++ .../valid/accepted-01.json | 38 + .../valid/accepted-02.json | 37 + .../valid/accepted-03.json | 37 + .../valid/accepted-04.json | 64 ++ .../valid/cancel-race-01.json | 37 + .../valid/cancel-race-02.json | 38 + .../valid/cancel-race-03.json | 64 ++ .../valid/duplicate-01.json | 37 + .../valid/duplicate-02.json | 37 + .../valid/partial-cancel-01.json | 37 + .../valid/partial-cancel-02.json | 38 + .../valid/partial-cancel-03.json | 64 ++ .../valid/refused-01.json | 38 + .../valid/uncertain-01.json | 37 + .../valid/uncertain-02.json | 54 ++ .../valid/uncertain-03.json | 57 ++ .../backend/operation-supervision.json | 11 + .../entries/backend-manifest-v2.json | 6 +- .../backend-operation-capabilities-v1.json | 10 + .../entries/backend-operation-control-v1.json | 10 + .../entries/backend-operation-request-v1.json | 10 + .../backend-operation-response-v1.json | 10 + .../entries/backend-profile-v1.json | 6 +- .../backend-manifest/backend-manifest-v2.json | 4 + .../backend-operation-capabilities-v1.json | 119 +++ .../backend-operation-control-v1.json | 370 ++++++++++ .../backend-operation-request-v1.json | 357 +++++++++ .../backend-operation-response-v1.json | 686 ++++++++++++++++++ .../schemas/profiles/backend-profile-v1.json | 4 + ...0-backend-operation-contracts-preflight.md | 261 +++++++ .../backend-operation-supervision.md | 101 +++ docs/explain/sdl/runtime-architecture.md | 10 + docs/public/api/contracts.rst | 18 + docs/public/backends.md | 6 + docs/requirements/API-402/requirement.md | 24 +- .../raes_backend_protocols/__init__.py | 4 +- .../operation_supervision.py | 93 +++ .../raes_backend_protocols/protocols.py | 2 + .../raes_contracts/contracts/__init__.py | 2 +- .../contracts/_backend_operation_exports.py | 72 ++ .../raes_contracts/contracts/_exports.py | 5 +- .../contracts/_version_exports.py | 6 + .../contracts/backend_operation.py | 130 ++++ .../contracts/backend_operation_response.py | 151 ++++ .../contracts/backend_operation_schema.py | 54 ++ .../contracts/backend_operation_validation.py | 136 ++++ .../contracts/bundle_runtime.py | 2 + .../raes_contracts/manifest_authority.py | 3 + .../packages/raes_contracts/versions.py | 10 + .../test_issue_1360_backend_operations.py | 377 ++++++++++ .../test_issue_1360_operation_rejections.py | 207 ++++++ .../backend-operation-supervision.md | 234 ++++++ tools/policy/requirement_order.yaml | 1 + 64 files changed, 4669 insertions(+), 12 deletions(-) create mode 100644 contracts/fixtures/control-plane/backend-operation-capabilities-v1/valid/provider.json create mode 100644 contracts/fixtures/control-plane/backend-operation-control-v1/valid/cancel-race-01.json create mode 100644 contracts/fixtures/control-plane/backend-operation-control-v1/valid/partial-cancel-01.json create mode 100644 contracts/fixtures/control-plane/backend-operation-control-v1/valid/uncertain-01.json create mode 100644 contracts/fixtures/control-plane/backend-operation-request-v1/valid/accepted.json create mode 100644 contracts/fixtures/control-plane/backend-operation-request-v1/valid/cancel-race.json create mode 100644 contracts/fixtures/control-plane/backend-operation-request-v1/valid/duplicate.json create mode 100644 contracts/fixtures/control-plane/backend-operation-request-v1/valid/partial-cancel.json create mode 100644 contracts/fixtures/control-plane/backend-operation-request-v1/valid/refused.json create mode 100644 contracts/fixtures/control-plane/backend-operation-request-v1/valid/uncertain.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-01.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-02.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-03.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-04.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-01.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-02.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-03.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/duplicate-01.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/duplicate-02.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-01.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-02.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-03.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/refused-01.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-01.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-02.json create mode 100644 contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-03.json create mode 100644 contracts/profiles/backend/operation-supervision.json create mode 100644 contracts/schema-publication/entries/backend-operation-capabilities-v1.json create mode 100644 contracts/schema-publication/entries/backend-operation-control-v1.json create mode 100644 contracts/schema-publication/entries/backend-operation-request-v1.json create mode 100644 contracts/schema-publication/entries/backend-operation-response-v1.json create mode 100644 contracts/schemas/control-plane/backend-operation-capabilities-v1.json create mode 100644 contracts/schemas/control-plane/backend-operation-control-v1.json create mode 100644 contracts/schemas/control-plane/backend-operation-request-v1.json create mode 100644 contracts/schemas/control-plane/backend-operation-response-v1.json create mode 100644 docs/decisions/issue-1360-backend-operation-contracts-preflight.md create mode 100644 docs/explain/reference/backend-operation-supervision.md create mode 100644 implementations/python/packages/raes_backend_protocols/operation_supervision.py create mode 100644 implementations/python/packages/raes_contracts/contracts/_backend_operation_exports.py create mode 100644 implementations/python/packages/raes_contracts/contracts/backend_operation.py create mode 100644 implementations/python/packages/raes_contracts/contracts/backend_operation_response.py create mode 100644 implementations/python/packages/raes_contracts/contracts/backend_operation_schema.py create mode 100644 implementations/python/packages/raes_contracts/contracts/backend_operation_validation.py create mode 100644 implementations/python/tests/test_issue_1360_backend_operations.py create mode 100644 implementations/python/tests/test_issue_1360_operation_rejections.py create mode 100644 specs/formal/runtime-contracts/backend-operation-supervision.md diff --git a/contracts/README.md b/contracts/README.md index 4d860acb7..6711ae999 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -1,5 +1,11 @@ # Contracts +The optional [backend operation and supervision family](../specs/formal/runtime-contracts/backend-operation-supervision.md) +publishes bounded requests, capability/willingness checks, correlated progress, +cancellation dispositions and effect evidence. The +[backend integration and migration guide](../docs/explain/reference/backend-operation-supervision.md) +explains the `operation-supervision` profile and its evidence limits. + `contracts/` contains the machine-readable contract side of the repository. The goal of this bucket is organizational clarity: diff --git a/contracts/fixtures/control-plane/backend-operation-capabilities-v1/valid/provider.json b/contracts/fixtures/control-plane/backend-operation-capabilities-v1/valid/provider.json new file mode 100644 index 000000000..a1bee44a2 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-capabilities-v1/valid/provider.json @@ -0,0 +1,14 @@ +{ + "schema_version": "backend-operation-capabilities/v1", + "backend_id": "backend-1", + "revision": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", + "supported_operation_kinds": [ + "provisioning" + ], + "guarantees": [ + "cessation-evidence", + "cancellation", + "effect-observation", + "partial-effects" + ] +} diff --git a/contracts/fixtures/control-plane/backend-operation-control-v1/valid/cancel-race-01.json b/contracts/fixtures/control-plane/backend-operation-control-v1/valid/cancel-race-01.json new file mode 100644 index 000000000..899edb596 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-control-v1/valid/cancel-race-01.json @@ -0,0 +1,43 @@ +{ + "schema_version": "backend-operation-control/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "control_id": "control-1", + "actor_id": "supervisor-1", + "authorization_scope": [ + "role:operator" + ], + "action": "cancel", + "budget": { + "origin_id": "budget-1", + "started_at": "2026-09-24T00:00:00Z", + "limit_ms": 1000, + "remaining_ms": 900 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-control-v1/valid/partial-cancel-01.json b/contracts/fixtures/control-plane/backend-operation-control-v1/valid/partial-cancel-01.json new file mode 100644 index 000000000..899edb596 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-control-v1/valid/partial-cancel-01.json @@ -0,0 +1,43 @@ +{ + "schema_version": "backend-operation-control/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "control_id": "control-1", + "actor_id": "supervisor-1", + "authorization_scope": [ + "role:operator" + ], + "action": "cancel", + "budget": { + "origin_id": "budget-1", + "started_at": "2026-09-24T00:00:00Z", + "limit_ms": 1000, + "remaining_ms": 900 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-control-v1/valid/uncertain-01.json b/contracts/fixtures/control-plane/backend-operation-control-v1/valid/uncertain-01.json new file mode 100644 index 000000000..675f88c98 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-control-v1/valid/uncertain-01.json @@ -0,0 +1,43 @@ +{ + "schema_version": "backend-operation-control/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "control_id": "control-1", + "actor_id": "supervisor-1", + "authorization_scope": [ + "role:operator" + ], + "action": "reconcile", + "budget": { + "origin_id": "budget-1", + "started_at": "2026-09-24T00:00:00Z", + "limit_ms": 1000, + "remaining_ms": 900 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/accepted.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/accepted.json new file mode 100644 index 000000000..9bcc92a6a --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/accepted.json @@ -0,0 +1,51 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "provisioning-plan-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "requirement_refs": [ + { + "contract_id": "artifact-requirement-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "required_guarantees": [ + "cessation-evidence" + ], + "budget": { + "origin_id": "budget-1", + "started_at": "2026-09-24T00:00:00Z", + "limit_ms": 1000, + "remaining_ms": 900 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/cancel-race.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/cancel-race.json new file mode 100644 index 000000000..9bcc92a6a --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/cancel-race.json @@ -0,0 +1,51 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "provisioning-plan-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "requirement_refs": [ + { + "contract_id": "artifact-requirement-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "required_guarantees": [ + "cessation-evidence" + ], + "budget": { + "origin_id": "budget-1", + "started_at": "2026-09-24T00:00:00Z", + "limit_ms": 1000, + "remaining_ms": 900 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/duplicate.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/duplicate.json new file mode 100644 index 000000000..9bcc92a6a --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/duplicate.json @@ -0,0 +1,51 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "provisioning-plan-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "requirement_refs": [ + { + "contract_id": "artifact-requirement-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "required_guarantees": [ + "cessation-evidence" + ], + "budget": { + "origin_id": "budget-1", + "started_at": "2026-09-24T00:00:00Z", + "limit_ms": 1000, + "remaining_ms": 900 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/partial-cancel.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/partial-cancel.json new file mode 100644 index 000000000..9bcc92a6a --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/partial-cancel.json @@ -0,0 +1,51 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "provisioning-plan-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "requirement_refs": [ + { + "contract_id": "artifact-requirement-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "required_guarantees": [ + "cessation-evidence" + ], + "budget": { + "origin_id": "budget-1", + "started_at": "2026-09-24T00:00:00Z", + "limit_ms": 1000, + "remaining_ms": 900 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/refused.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/refused.json new file mode 100644 index 000000000..9bcc92a6a --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/refused.json @@ -0,0 +1,51 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "provisioning-plan-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "requirement_refs": [ + { + "contract_id": "artifact-requirement-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "required_guarantees": [ + "cessation-evidence" + ], + "budget": { + "origin_id": "budget-1", + "started_at": "2026-09-24T00:00:00Z", + "limit_ms": 1000, + "remaining_ms": 900 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-request-v1/valid/uncertain.json b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/uncertain.json new file mode 100644 index 000000000..9bcc92a6a --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-request-v1/valid/uncertain.json @@ -0,0 +1,51 @@ +{ + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "command": { + "contract_id": "provisioning-plan-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "requirement_refs": [ + { + "contract_id": "artifact-requirement-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "required_guarantees": [ + "cessation-evidence" + ], + "budget": { + "origin_id": "budget-1", + "started_at": "2026-09-24T00:00:00Z", + "limit_ms": 1000, + "remaining_ms": 900 + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-01.json new file mode 100644 index 000000000..2979108f1 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-01.json @@ -0,0 +1,38 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 1, + "message": { + "kind": "admission", + "disposition": "willing", + "capability_digest": "sha256:066b3fa652e3c59d655a6c8f443164e8b5f5e79c08cbb911d18a363f0a912b9e", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-02.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-02.json new file mode 100644 index 000000000..ffa53a295 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-02.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 2, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-03.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-03.json new file mode 100644 index 000000000..6ba31be42 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-03.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 3, + "message": { + "kind": "progress", + "phase": "executing", + "evidence_refs": [] + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-04.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-04.json new file mode 100644 index 000000000..64dffaa3f --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/accepted-04.json @@ -0,0 +1,64 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 4, + "message": { + "kind": "outcome", + "proposed_state": "succeeded", + "effects": { + "effect": "complete", + "cessation_established": true, + "evidence_refs": [ + { + "contract_id": "backend-materialization-attestation-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "residual_scope": [ + "node.vm1" + ], + "residual_state": { + "contract_id": "runtime-snapshot-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "external_fence": null + }, + "satisfaction": "satisfied", + "release_gates_satisfied": true, + "cancellation_established": false, + "result": { + "contract_id": "runtime-snapshot-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-01.json new file mode 100644 index 000000000..752a59c89 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-01.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 1, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-02.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-02.json new file mode 100644 index 000000000..5f67a60a8 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-02.json @@ -0,0 +1,38 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 2, + "message": { + "kind": "control", + "control_id": "control-1", + "control_digest": "sha256:70871456333553d676f2b31b3d92f439018ed08039957cdcab00e3b5cb835bab", + "disposition": "accepted" + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-03.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-03.json new file mode 100644 index 000000000..b880a74f2 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/cancel-race-03.json @@ -0,0 +1,64 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 3, + "message": { + "kind": "outcome", + "proposed_state": "succeeded", + "effects": { + "effect": "complete", + "cessation_established": true, + "evidence_refs": [ + { + "contract_id": "backend-materialization-attestation-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "residual_scope": [ + "node.vm1" + ], + "residual_state": { + "contract_id": "runtime-snapshot-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "external_fence": null + }, + "satisfaction": "satisfied", + "release_gates_satisfied": true, + "cancellation_established": false, + "result": { + "contract_id": "runtime-snapshot-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/duplicate-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/duplicate-01.json new file mode 100644 index 000000000..752a59c89 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/duplicate-01.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 1, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/duplicate-02.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/duplicate-02.json new file mode 100644 index 000000000..752a59c89 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/duplicate-02.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 1, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-01.json new file mode 100644 index 000000000..752a59c89 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-01.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 1, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-02.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-02.json new file mode 100644 index 000000000..5f67a60a8 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-02.json @@ -0,0 +1,38 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 2, + "message": { + "kind": "control", + "control_id": "control-1", + "control_digest": "sha256:70871456333553d676f2b31b3d92f439018ed08039957cdcab00e3b5cb835bab", + "disposition": "accepted" + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-03.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-03.json new file mode 100644 index 000000000..c184f2885 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/partial-cancel-03.json @@ -0,0 +1,64 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 3, + "message": { + "kind": "outcome", + "proposed_state": "cancelled", + "effects": { + "effect": "partial", + "cessation_established": true, + "evidence_refs": [ + { + "contract_id": "backend-materialization-attestation-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "residual_scope": [ + "node.vm1" + ], + "residual_state": { + "contract_id": "runtime-snapshot-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "external_fence": null + }, + "satisfaction": "unsatisfied", + "release_gates_satisfied": false, + "cancellation_established": true, + "result": { + "contract_id": "runtime-snapshot-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/refused-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/refused-01.json new file mode 100644 index 000000000..7632a1e65 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/refused-01.json @@ -0,0 +1,38 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 1, + "message": { + "kind": "admission", + "disposition": "refused", + "capability_digest": "sha256:066b3fa652e3c59d655a6c8f443164e8b5f5e79c08cbb911d18a363f0a912b9e", + "reason": "context-refused" + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-01.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-01.json new file mode 100644 index 000000000..752a59c89 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-01.json @@ -0,0 +1,37 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 1, + "message": { + "kind": "acknowledgement", + "disposition": "accepted", + "reason": null + } +} diff --git a/contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-02.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-02.json new file mode 100644 index 000000000..77e62785a --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-02.json @@ -0,0 +1,54 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 2, + "message": { + "kind": "outcome", + "proposed_state": "indeterminate", + "effects": { + "effect": "unknown", + "cessation_established": false, + "evidence_refs": [ + { + "contract_id": "backend-materialization-attestation-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "residual_scope": [], + "residual_state": null, + "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/uncertain-03.json b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-03.json new file mode 100644 index 000000000..f973c3d14 --- /dev/null +++ b/contracts/fixtures/control-plane/backend-operation-response-v1/valid/uncertain-03.json @@ -0,0 +1,57 @@ +{ + "schema_version": "backend-operation-response/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": [ + "role:operator" + ], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parent_operation_id": null + }, + "effect_scope": { + "kind": "target-run", + "addresses": [], + "independence": null + } + }, + "request_digest": "sha256:3182586fa3572b311637fe36d00e2bfb0ba5e1ba680dcd05aed5784bd8c79d5b", + "sequence": 3, + "message": { + "kind": "reconciliation", + "control_id": "control-1", + "control_digest": "sha256:79afda832a8d41a79982049673e384c0087d90e9ba90e7b3ee0f00ce1c4db2eb", + "effects": { + "effect": "complete", + "cessation_established": true, + "evidence_refs": [ + { + "contract_id": "backend-materialization-attestation-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + } + ], + "residual_scope": [ + "node.vm1" + ], + "residual_state": { + "contract_id": "runtime-snapshot-v1", + "artifact_id": "artifact-1", + "digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "external_fence": null + } + } +} diff --git a/contracts/profiles/backend/operation-supervision.json b/contracts/profiles/backend/operation-supervision.json new file mode 100644 index 000000000..d5d36cacb --- /dev/null +++ b/contracts/profiles/backend/operation-supervision.json @@ -0,0 +1,11 @@ +{ + "schema_version": "backend-profile/v1", + "profile": "operation-supervision", + "required_contracts": [ + "backend-manifest-v2", + "backend-operation-request-v1", + "backend-operation-capabilities-v1", + "backend-operation-control-v1", + "backend-operation-response-v1" + ] +} diff --git a/contracts/schema-publication/entries/backend-manifest-v2.json b/contracts/schema-publication/entries/backend-manifest-v2.json index 680790ea9..0a6374b15 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": "fdd31f40e084699706b2ff0786f93318ed0ec418a230309744d5ca33d0929e85", + "content_hash": "67408de0a854ab63582c29bc4b1dfaa2efea2e61dff598a648ff03b2ad74755d", "contract_id": "backend-manifest-v2", "last_change": { - "summary": "Add opt-in bounded shared-time guarantees and typed numeric authoring; keep backend execution capabilities conditional (#216).", - "content_hash": "fdd31f40e084699706b2ff0786f93318ed0ec418a230309744d5ca33d0929e85" + "summary": "Publish optional backend operation and supervision contracts with contextual admission and bounded evidence (#1360).", + "content_hash": "67408de0a854ab63582c29bc4b1dfaa2efea2e61dff598a648ff03b2ad74755d" }, "schema_path": "contracts/schemas/backend-manifest/backend-manifest-v2.json", "stability": "draft" diff --git a/contracts/schema-publication/entries/backend-operation-capabilities-v1.json b/contracts/schema-publication/entries/backend-operation-capabilities-v1.json new file mode 100644 index 000000000..cccfec2de --- /dev/null +++ b/contracts/schema-publication/entries/backend-operation-capabilities-v1.json @@ -0,0 +1,10 @@ +{ + "contract_id": "backend-operation-capabilities-v1", + "schema_path": "contracts/schemas/control-plane/backend-operation-capabilities-v1.json", + "stability": "draft", + "content_hash": "b6bf52b1ce654ccf0bbeb86355b543dffb245fbba7923fd659116cbae40e84b9", + "last_change": { + "summary": "Publish optional backend operation and supervision contracts with contextual admission and bounded evidence (#1360).", + "content_hash": "b6bf52b1ce654ccf0bbeb86355b543dffb245fbba7923fd659116cbae40e84b9" + } +} diff --git a/contracts/schema-publication/entries/backend-operation-control-v1.json b/contracts/schema-publication/entries/backend-operation-control-v1.json new file mode 100644 index 000000000..bedd32555 --- /dev/null +++ b/contracts/schema-publication/entries/backend-operation-control-v1.json @@ -0,0 +1,10 @@ +{ + "contract_id": "backend-operation-control-v1", + "schema_path": "contracts/schemas/control-plane/backend-operation-control-v1.json", + "stability": "draft", + "content_hash": "d8afe33a427d6e4d306508c0f12ea748c7170435fa4734c5a4fcf82db2df5ee9", + "last_change": { + "summary": "Publish optional backend operation and supervision contracts with contextual admission and bounded evidence (#1360).", + "content_hash": "d8afe33a427d6e4d306508c0f12ea748c7170435fa4734c5a4fcf82db2df5ee9" + } +} diff --git a/contracts/schema-publication/entries/backend-operation-request-v1.json b/contracts/schema-publication/entries/backend-operation-request-v1.json new file mode 100644 index 000000000..60a92d32b --- /dev/null +++ b/contracts/schema-publication/entries/backend-operation-request-v1.json @@ -0,0 +1,10 @@ +{ + "contract_id": "backend-operation-request-v1", + "schema_path": "contracts/schemas/control-plane/backend-operation-request-v1.json", + "stability": "draft", + "content_hash": "91cc6370f4f2d62ddc33da1a64df1982794929557401920dd0682a2a6860c98b", + "last_change": { + "summary": "Publish optional backend operation and supervision contracts with contextual admission and bounded evidence (#1360).", + "content_hash": "91cc6370f4f2d62ddc33da1a64df1982794929557401920dd0682a2a6860c98b" + } +} diff --git a/contracts/schema-publication/entries/backend-operation-response-v1.json b/contracts/schema-publication/entries/backend-operation-response-v1.json new file mode 100644 index 000000000..fac95f9fd --- /dev/null +++ b/contracts/schema-publication/entries/backend-operation-response-v1.json @@ -0,0 +1,10 @@ +{ + "contract_id": "backend-operation-response-v1", + "schema_path": "contracts/schemas/control-plane/backend-operation-response-v1.json", + "stability": "draft", + "content_hash": "2b2f7de32d9bda155b0b8c062e783721e4580fcda3a35d9e244cc951aa5bf349", + "last_change": { + "summary": "Publish optional backend operation and supervision contracts with contextual admission and bounded evidence (#1360).", + "content_hash": "2b2f7de32d9bda155b0b8c062e783721e4580fcda3a35d9e244cc951aa5bf349" + } +} diff --git a/contracts/schema-publication/entries/backend-profile-v1.json b/contracts/schema-publication/entries/backend-profile-v1.json index c6851036c..3cd54f8bd 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": "163db0d1f1c1cf7e8e3d41b393a3c2a68d887a00964dacffc0c2dfc90306d36b", + "content_hash": "4fd12684309b617fe4308c90efb2a4631af1fe5590cf91d5b62a0ea0adabd5a4", "contract_id": "backend-profile-v1", "last_change": { - "summary": "Publish closed modular participant-control contracts and governed declaration support for issue #1072.", - "content_hash": "163db0d1f1c1cf7e8e3d41b393a3c2a68d887a00964dacffc0c2dfc90306d36b" + "summary": "Publish optional backend operation and supervision contracts with contextual admission and bounded evidence (#1360).", + "content_hash": "4fd12684309b617fe4308c90efb2a4631af1fe5590cf91d5b62a0ea0adabd5a4" }, "schema_path": "contracts/schemas/profiles/backend-profile-v1.json", "stability": "draft" diff --git a/contracts/schemas/backend-manifest/backend-manifest-v2.json b/contracts/schemas/backend-manifest/backend-manifest-v2.json index eafe15dfd..169937c78 100644 --- a/contracts/schemas/backend-manifest/backend-manifest-v2.json +++ b/contracts/schemas/backend-manifest/backend-manifest-v2.json @@ -3592,6 +3592,10 @@ "supported_contract_versions": { "items": { "enum": [ + "backend-operation-request-v1", + "backend-operation-capabilities-v1", + "backend-operation-control-v1", + "backend-operation-response-v1", "backend-materialization-attestation-v1", "backend-augmentation-scope-v1", "plan-realization-profiles-v1", diff --git a/contracts/schemas/control-plane/backend-operation-capabilities-v1.json b/contracts/schemas/control-plane/backend-operation-capabilities-v1.json new file mode 100644 index 000000000..4907ad27d --- /dev/null +++ b/contracts/schemas/control-plane/backend-operation-capabilities-v1.json @@ -0,0 +1,119 @@ +{ + "$defs": { + "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" + } + }, + "$id": "https://openrae.github.io/rae/schemas/backend-operation-capabilities-v1.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "description": "Installed provider declaration; neither willingness nor a conformance proof.", + "properties": { + "backend_id": { + "maxLength": 256, + "minLength": 1, + "title": "Backend Id", + "type": "string" + }, + "guarantees": { + "default": [], + "items": { + "enum": [ + "cancellation", + "effect-observation", + "cessation-evidence", + "partial-effects", + "external-fencing" + ], + "type": "string" + }, + "maxItems": 5, + "title": "Guarantees", + "type": "array" + }, + "revision": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Revision", + "type": "string" + }, + "schema_version": { + "const": "backend-operation-capabilities/v1", + "default": "backend-operation-capabilities/v1", + "title": "Schema Version", + "type": "string" + }, + "supported_operation_kinds": { + "items": { + "$ref": "#/$defs/OperationKind" + }, + "maxItems": 32, + "minItems": 1, + "title": "Supported Operation Kinds", + "type": "array" + } + }, + "required": [ + "backend_id", + "revision", + "supported_operation_kinds" + ], + "title": "BackendOperationCapabilitiesModel", + "type": "object", + "x-raes-invariants": [ + { + "description": "Validate unique collections, calendar instants, budget bounds, scope and honest effect/outcome claims; structural validity does not prove backend truth or runtime authority.", + "id": "backend-operation-local-consistency", + "inputs": [ + { + "contract_id": "backend-operation-capabilities-v1", + "instance_path": "#" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.BackendOperationCapabilitiesModel.model_validate" + }, + { + "description": "Before invocation require installed support, matching declaration and current exact-context willingness.", + "id": "backend-operation-contextual-admission", + "inputs": [ + { + "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_backend_operation_admission" + } + ], + "x-raes-semantic-profile": { + "contract_id": "backend-operation-capabilities-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/backend-operation-control-v1.json b/contracts/schemas/control-plane/backend-operation-control-v1.json new file mode 100644 index 000000000..8b070983b --- /dev/null +++ b/contracts/schemas/control-plane/backend-operation-control-v1.json @@ -0,0 +1,370 @@ +{ + "$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" + }, + "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" + }, + "OperationBudgetModel": { + "additionalProperties": false, + "description": "Remaining apparatus budget; the origin is retained across duplicate delivery.", + "properties": { + "limit_ms": { + "maximum": 9007199254740991, + "minimum": 1, + "title": "Limit Ms", + "type": "integer" + }, + "origin_id": { + "maxLength": 256, + "minLength": 1, + "title": "Origin Id", + "type": "string" + }, + "remaining_ms": { + "maximum": 9007199254740991, + "minimum": 1, + "title": "Remaining Ms", + "type": "integer" + }, + "started_at": { + "format": "date-time", + "maxLength": 64, + "minLength": 1, + "pattern": "^\\d{4}-\\d{2}-\\d{2}[Tt](?:[01]\\d|2[0-3]):[0-5]\\d:(?:[0-5]\\d|60)(?:\\.\\d+)?(?:[Zz]|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$", + "title": "Started At", + "type": "string" + } + }, + "required": [ + "origin_id", + "started_at", + "limit_ms", + "remaining_ms" + ], + "title": "OperationBudgetModel", + "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" + } + }, + "$id": "https://openrae.github.io/rae/schemas/backend-operation-control-v1.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "description": "Independently authorized, idempotent control/observation of the original invocation.", + "properties": { + "action": { + "enum": [ + "cancel", + "observe", + "reconcile" + ], + "title": "Action", + "type": "string" + }, + "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" + }, + "binding": { + "$ref": "#/$defs/BackendOperationBindingModel" + }, + "budget": { + "$ref": "#/$defs/OperationBudgetModel" + }, + "control_id": { + "maxLength": 256, + "minLength": 1, + "title": "Control Id", + "type": "string" + }, + "request_digest": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Request Digest", + "type": "string" + }, + "schema_version": { + "const": "backend-operation-control/v1", + "default": "backend-operation-control/v1", + "title": "Schema Version", + "type": "string" + } + }, + "required": [ + "binding", + "request_digest", + "control_id", + "actor_id", + "authorization_scope", + "action", + "budget" + ], + "title": "BackendOperationControlModel", + "type": "object", + "x-raes-invariants": [ + { + "description": "Validate unique collections, calendar instants, budget bounds, scope and honest effect/outcome claims; structural validity does not prove backend truth or runtime authority.", + "id": "backend-operation-local-consistency", + "inputs": [ + { + "contract_id": "backend-operation-control-v1", + "instance_path": "#" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.BackendOperationControlModel.model_validate" + } + ], + "x-raes-semantic-profile": { + "contract_id": "backend-operation-control-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/backend-operation-request-v1.json b/contracts/schemas/control-plane/backend-operation-request-v1.json new file mode 100644 index 000000000..dfc390bda --- /dev/null +++ b/contracts/schemas/control-plane/backend-operation-request-v1.json @@ -0,0 +1,357 @@ +{ + "$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" + }, + "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" + }, + "OperationBudgetModel": { + "additionalProperties": false, + "description": "Remaining apparatus budget; the origin is retained across duplicate delivery.", + "properties": { + "limit_ms": { + "maximum": 9007199254740991, + "minimum": 1, + "title": "Limit Ms", + "type": "integer" + }, + "origin_id": { + "maxLength": 256, + "minLength": 1, + "title": "Origin Id", + "type": "string" + }, + "remaining_ms": { + "maximum": 9007199254740991, + "minimum": 1, + "title": "Remaining Ms", + "type": "integer" + }, + "started_at": { + "format": "date-time", + "maxLength": 64, + "minLength": 1, + "pattern": "^\\d{4}-\\d{2}-\\d{2}[Tt](?:[01]\\d|2[0-3]):[0-5]\\d:(?:[0-5]\\d|60)(?:\\.\\d+)?(?:[Zz]|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$", + "title": "Started At", + "type": "string" + } + }, + "required": [ + "origin_id", + "started_at", + "limit_ms", + "remaining_ms" + ], + "title": "OperationBudgetModel", + "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" + } + }, + "$id": "https://openrae.github.io/rae/schemas/backend-operation-request-v1.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "description": "Exact admitted command and requirements checked again immediately before dispatch.", + "properties": { + "binding": { + "$ref": "#/$defs/BackendOperationBindingModel" + }, + "budget": { + "$ref": "#/$defs/OperationBudgetModel" + }, + "command": { + "$ref": "#/$defs/OperationArtifactReferenceModel" + }, + "required_guarantees": { + "default": [], + "items": { + "enum": [ + "cancellation", + "effect-observation", + "cessation-evidence", + "partial-effects", + "external-fencing" + ], + "type": "string" + }, + "maxItems": 5, + "title": "Required Guarantees", + "type": "array" + }, + "requirement_refs": { + "default": [], + "items": { + "$ref": "#/$defs/OperationArtifactReferenceModel" + }, + "maxItems": 64, + "title": "Requirement Refs", + "type": "array" + }, + "schema_version": { + "const": "backend-operation-request/v1", + "default": "backend-operation-request/v1", + "title": "Schema Version", + "type": "string" + } + }, + "required": [ + "binding", + "command", + "budget" + ], + "title": "BackendOperationRequestModel", + "type": "object", + "x-raes-invariants": [ + { + "description": "Validate unique collections, calendar instants, budget bounds, scope and honest effect/outcome claims; structural validity does not prove backend truth or runtime authority.", + "id": "backend-operation-local-consistency", + "inputs": [ + { + "contract_id": "backend-operation-request-v1", + "instance_path": "#" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.BackendOperationRequestModel.model_validate" + } + ], + "x-raes-semantic-profile": { + "contract_id": "backend-operation-request-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/backend-operation-response-v1.json b/contracts/schemas/control-plane/backend-operation-response-v1.json new file mode 100644 index 000000000..ece816978 --- /dev/null +++ b/contracts/schemas/control-plane/backend-operation-response-v1.json @@ -0,0 +1,686 @@ +{ + "$defs": { + "BackendOperationAcknowledgementModel": { + "additionalProperties": false, + "properties": { + "disposition": { + "enum": [ + "accepted", + "refused" + ], + "title": "Disposition", + "type": "string" + }, + "kind": { + "const": "acknowledgement", + "default": "acknowledgement", + "title": "Kind", + "type": "string" + }, + "reason": { + "anyOf": [ + { + "enum": [ + "unsupported-contract", + "unsupported-kind", + "unsupported-guarantee", + "context-refused", + "budget-exhausted", + "stale-binding", + "conflicting-effects", + "unavailable" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + } + }, + "required": [ + "disposition" + ], + "title": "BackendOperationAcknowledgementModel", + "type": "object" + }, + "BackendOperationAdmissionModel": { + "additionalProperties": false, + "properties": { + "capability_digest": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Capability Digest", + "type": "string" + }, + "disposition": { + "enum": [ + "willing", + "refused" + ], + "title": "Disposition", + "type": "string" + }, + "kind": { + "const": "admission", + "default": "admission", + "title": "Kind", + "type": "string" + }, + "reason": { + "anyOf": [ + { + "enum": [ + "unsupported-contract", + "unsupported-kind", + "unsupported-guarantee", + "context-refused", + "budget-exhausted", + "stale-binding", + "conflicting-effects", + "unavailable" + ], + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Reason" + } + }, + "required": [ + "disposition", + "capability_digest" + ], + "title": "BackendOperationAdmissionModel", + "type": "object" + }, + "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" + }, + "BackendOperationControlDispositionModel": { + "additionalProperties": false, + "properties": { + "control_digest": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Control Digest", + "type": "string" + }, + "control_id": { + "maxLength": 256, + "minLength": 1, + "title": "Control Id", + "type": "string" + }, + "disposition": { + "enum": [ + "recorded", + "accepted", + "refused", + "unsupported", + "already-terminal" + ], + "title": "Disposition", + "type": "string" + }, + "kind": { + "const": "control", + "default": "control", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "control_id", + "control_digest", + "disposition" + ], + "title": "BackendOperationControlDispositionModel", + "type": "object" + }, + "BackendOperationEffectsModel": { + "additionalProperties": false, + "description": "Effect knowledge and cessation are independent, scoped backend assertions.", + "properties": { + "cessation_established": { + "title": "Cessation Established", + "type": "boolean" + }, + "effect": { + "enum": [ + "absent", + "complete", + "partial", + "unknown" + ], + "title": "Effect", + "type": "string" + }, + "evidence_refs": { + "default": [], + "items": { + "$ref": "#/$defs/OperationArtifactReferenceModel" + }, + "maxItems": 32, + "title": "Evidence Refs", + "type": "array" + }, + "external_fence": { + "anyOf": [ + { + "$ref": "#/$defs/OperationArtifactReferenceModel" + }, + { + "type": "null" + } + ], + "default": null + }, + "residual_scope": { + "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": "Residual Scope", + "type": "array" + }, + "residual_state": { + "anyOf": [ + { + "$ref": "#/$defs/OperationArtifactReferenceModel" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "effect", + "cessation_established" + ], + "title": "BackendOperationEffectsModel", + "type": "object" + }, + "BackendOperationOutcomeModel": { + "additionalProperties": false, + "description": "Proposed outcome requiring RAE's native validation and atomic publication.", + "properties": { + "cancellation_established": { + "title": "Cancellation Established", + "type": "boolean" + }, + "effects": { + "$ref": "#/$defs/BackendOperationEffectsModel" + }, + "kind": { + "const": "outcome", + "default": "outcome", + "title": "Kind", + "type": "string" + }, + "proposed_state": { + "enum": [ + "succeeded", + "failed", + "cancelled", + "indeterminate" + ], + "title": "Proposed State", + "type": "string" + }, + "release_gates_satisfied": { + "title": "Release Gates Satisfied", + "type": "boolean" + }, + "result": { + "anyOf": [ + { + "$ref": "#/$defs/OperationArtifactReferenceModel" + }, + { + "type": "null" + } + ], + "default": null + }, + "satisfaction": { + "enum": [ + "satisfied", + "unsatisfied", + "unknown" + ], + "title": "Satisfaction", + "type": "string" + } + }, + "required": [ + "proposed_state", + "effects", + "satisfaction", + "release_gates_satisfied", + "cancellation_established" + ], + "title": "BackendOperationOutcomeModel", + "type": "object" + }, + "BackendOperationProgressModel": { + "additionalProperties": false, + "properties": { + "evidence_refs": { + "default": [], + "items": { + "$ref": "#/$defs/OperationArtifactReferenceModel" + }, + "maxItems": 32, + "title": "Evidence Refs", + "type": "array" + }, + "kind": { + "const": "progress", + "default": "progress", + "title": "Kind", + "type": "string" + }, + "phase": { + "enum": [ + "queued", + "executing", + "settling" + ], + "title": "Phase", + "type": "string" + } + }, + "required": [ + "phase" + ], + "title": "BackendOperationProgressModel", + "type": "object" + }, + "BackendOperationReconciliationModel": { + "additionalProperties": false, + "description": "Observation for separately authorized resolution, with no replay instruction.", + "properties": { + "control_digest": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Control Digest", + "type": "string" + }, + "control_id": { + "maxLength": 256, + "minLength": 1, + "title": "Control Id", + "type": "string" + }, + "effects": { + "$ref": "#/$defs/BackendOperationEffectsModel" + }, + "kind": { + "const": "reconciliation", + "default": "reconciliation", + "title": "Kind", + "type": "string" + } + }, + "required": [ + "control_id", + "control_digest", + "effects" + ], + "title": "BackendOperationReconciliationModel", + "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" + } + }, + "$id": "https://openrae.github.io/rae/schemas/backend-operation-response-v1.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "binding": { + "$ref": "#/$defs/BackendOperationBindingModel" + }, + "message": { + "discriminator": { + "mapping": { + "acknowledgement": "#/$defs/BackendOperationAcknowledgementModel", + "admission": "#/$defs/BackendOperationAdmissionModel", + "control": "#/$defs/BackendOperationControlDispositionModel", + "outcome": "#/$defs/BackendOperationOutcomeModel", + "progress": "#/$defs/BackendOperationProgressModel", + "reconciliation": "#/$defs/BackendOperationReconciliationModel" + }, + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/$defs/BackendOperationAdmissionModel" + }, + { + "$ref": "#/$defs/BackendOperationAcknowledgementModel" + }, + { + "$ref": "#/$defs/BackendOperationProgressModel" + }, + { + "$ref": "#/$defs/BackendOperationControlDispositionModel" + }, + { + "$ref": "#/$defs/BackendOperationOutcomeModel" + }, + { + "$ref": "#/$defs/BackendOperationReconciliationModel" + } + ], + "title": "Message" + }, + "request_digest": { + "pattern": "^sha256:[a-f0-9]{64}$", + "title": "Request Digest", + "type": "string" + }, + "schema_version": { + "const": "backend-operation-response/v1", + "default": "backend-operation-response/v1", + "title": "Schema Version", + "type": "string" + }, + "sequence": { + "maximum": 9007199254740991, + "minimum": 1, + "title": "Sequence", + "type": "integer" + } + }, + "required": [ + "binding", + "request_digest", + "sequence", + "message" + ], + "title": "BackendOperationResponseModel", + "type": "object", + "x-raes-invariants": [ + { + "description": "Validate unique collections, calendar instants, budget bounds, scope and honest effect/outcome claims; structural validity does not prove backend truth or runtime authority.", + "id": "backend-operation-local-consistency", + "inputs": [ + { + "contract_id": "backend-operation-response-v1", + "instance_path": "#" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.BackendOperationResponseModel.model_validate" + }, + { + "description": "Require exact request binding and commitment, scoped residuals and independently bound controls when present.", + "id": "backend-operation-response-binding", + "inputs": [ + { + "contract_id": "backend-operation-request-v1", + "instance_path": "#" + }, + { + "contract_id": "backend-operation-response-v1", + "instance_path": "#" + } + ], + "level": "error", + "validator": "raes_contracts.contracts.validate_backend_operation_response" + } + ], + "x-raes-semantic-profile": { + "contract_id": "backend-operation-response-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 86d740ec7..bdacdd712 100644 --- a/contracts/schemas/profiles/backend-profile-v1.json +++ b/contracts/schemas/profiles/backend-profile-v1.json @@ -12,6 +12,10 @@ "required_contracts": { "items": { "enum": [ + "backend-operation-request-v1", + "backend-operation-capabilities-v1", + "backend-operation-control-v1", + "backend-operation-response-v1", "backend-materialization-attestation-v1", "backend-augmentation-scope-v1", "plan-realization-profiles-v1", diff --git a/docs/decisions/issue-1360-backend-operation-contracts-preflight.md b/docs/decisions/issue-1360-backend-operation-contracts-preflight.md new file mode 100644 index 000000000..3924f76b1 --- /dev/null +++ b/docs/decisions/issue-1360-backend-operation-contracts-preflight.md @@ -0,0 +1,261 @@ +# Issue #1360 — Backend operation and supervision contracts preflight + +Date: 2026-09-24. Scope: API-402 and supplied issue #1360; prerequisite #1348. +This is architecture guidance, not an implementation plan or a new contract. + +The accepted [#1348 decision](issue-1348-operation-lifecycle.md) and +[supervision semantics S1–S6](../../specs/formal/runtime-control-plane/supervision.md) +already settle lifecycle meaning. Retain those authorities and ADR-104; no new +ADR is needed. The [earlier preflight](issue-1348-operation-lifecycle-preflight.md) +maps runtime integration risks. This note closes the publication-specific gaps. +Python paths below are relative to `implementations/python/packages/`. + +## API-402 boundary: compose the existing live contracts + +API-402's existing implementation and ACTIVE status do not establish delivery +of #1360's additional supervision carriers. Preserve these semantic owners: + +| Surface | Canonical incumbent and boundary | +| --- | --- | +| Submission | `contracts/realization_plans.py` in `raes_contracts` owns `ProvisioningPlanModel`, `OrchestrationPlanModel` and `EvaluationPlanModel`; `_operation_routes.py` accepts these today. Reuse admitted plan identity and payloads inside any new backend request. An instantiation request is not an execution request, and authenticated submission does not replace planner authorization. | +| Live operation | `operation_lifecycle.py`, receipt/status models and their `control-plane/operation-{receipt,status}-v1.json` schemas own operation identity and state. Backend acknowledgement/progress are evidence for this authority, not replacement status models. | +| Results and history | Existing `workflow-result-envelope-v1`, `evaluation-result-envelope-v1`, and their separate `*-history-event-stream-v1` schemas remain authoritative. `contracts/execution_state.py`, `workflow_result_contracts.py` and `evaluation_result_contracts.py` preserve compiled result/execution-contract validation, workflow causality, evaluator chronology and final-state/history agreement. Supervision history must not become workflow step history or evaluator evidence. | +| Live snapshot | `contracts/realization_plans.py:RuntimeSnapshotEnvelopeModel`, `runtime_state.py` and `snapshots/runtime-snapshot-v1.json` retain the portable state projection. A snapshot is neither a continuation checkpoint nor proof of external cessation. | +| Archival provenance | ADR-065's `experiment-run-v1` remains the archival join point for results, evidence and provenance references. Do not add another run-record root, use an archive as a mutable operation journal, or require an experiment wrapper for ordinary live execution. Operational persistence does not turn a live carrier into archival provenance. | + +Schema paths above are under `contracts/schemas/`. Keep the formal +[workflow](../../specs/formal/runtime-contracts/workflow-results.md) and +[evaluator](../../specs/formal/runtime-contracts/evaluator-results.md) contracts, +`contracts/README.md` and `docs/explain/sdl/runtime-architecture.md` aligned when +publication changes their public boundary. Some overview implementation mappings +still name the older processor ownership; use the current `raes_runtime` owners +above rather than introducing validation in the processor to match stale paths. + +## Existing contracts and the gaps to publish + +`raes_contracts/operation_lifecycle.py` owns operation kinds, immutable admission +context, legal state transitions and canonical terminal diagnostics. +`contracts/operation_carriers.py` in that package owns closed receipt/status wire +models; `runtime_state.py` owns their in-process counterparts. Reuse these +identities and meanings rather than introducing a competing backend lifecycle. +Domain (provisioning/orchestration/evaluation) is not operation kind. + +The current carriers do **not** supply the whole #1360 protocol: + +- `OperationAdmissionContext` lacks an explicit binding to selected supervision + requirements, backend execution generation and control-request identity. +- `raes_backend_protocols/protocols.py` exposes synchronous `ApplyResult` methods. + A returned failure with the predecessor snapshot does not establish absent + effects. Wrapping that result cannot manufacture cessation or interruption. +- `recovery_observation.py` provides unversioned Python dataclasses and only + absent/applied/indeterminate classifications. Applied requires a snapshot; + other classifications forbid one. There is no known-partial or cessation + carrier. Its operation/request checks do not supply every new correlation. +- Manifest `RecoveryObservationCapabilities` selects operation kinds only; + method presence and that declaration do not establish contextual willingness, + cancellation support, continuation, or satisfaction of requested guarantees. +- Receipt and status share `OPERATION_SCHEMA_VERSION = runtime-operation/v1`. + Store codecs and HTTP projections explicitly reconstruct their fields; an + added Python field alone can disappear at those boundaries. + +Publish only the missing portable facts, with one semantic owner for each. +Requests, acknowledgements, progress, refusal, cancellation dispositions, +outcomes and reconciliation must have closed, versioned shapes and documented +cross-message invariants. JSON Schema covers structural constraints; shared +contract validators cover context, identity and evidence joins. Publish those +semantic obligations through the existing `schema_invariants.py` annotation +conventions where applicable, not independent validators in every transport. +Annotations identify obligations; a generic JSON Schema validator does not +execute them. Publish language-neutral rules and cross-message vectors, with +Python validators as reference bindings rather than the only definition. + +The wire boundary is JSON data, not serialized Python objects, callbacks, +exceptions, futures, native handles or injected services. Reuse +`raes_contracts/canonical.py` for RFC 8785 commitments and +`control_plane_operation_context.py` for their authorized, value-free projection; +do not hash `repr()`, ad hoc JSON or resolved credentials. Specify omission/null, +defaults, ordering and numeric bounds consistently across schema and Python, +including finite numbers and interoperable integer limits for committed data. +`ContractModel` forbids extra fields but does not make every field strict or +bounded. Python coercion and `jsonable_fallback()` comparison markers must not +turn invalid wire inputs into accepted protocol facts. + +## Meaning and ownership guardrails + +**Separate the facts.** Capability, current willingness, acceptance, dispatch, +progress, cancellation acceptance, cessation, effect knowledge and runtime +terminal publication are different facts. Preserve the six existing operation +states; do not add `PARTIAL`, `TIMED_OUT`, `REFUSED` or `CANCELLING` states. +Backend completion is evidence submitted to the runtime, not authority to +commit a runtime terminal state. Progress cannot establish success, renew a +deadline, discharge quarantine or substitute for experiment evidence. Specify +ordering and duplicate/stale-message handling within an execution generation; +timestamps alone cannot order concurrent control and completion events. + +**Bind the whole exchange.** Preserve original actor, authorization scope, +target/run, operation kind, request commitment and parent linkage. Correlate +backend invocation, execution generation, conflicting-effect scope, baseline +snapshot revision, exact admitted requirements/context and every response. +A supervisory request has its own actor and scoped idempotency identity; +it never replaces the original actor. Reject mismatched responses even when +each object independently validates. Operation, control request, backend job, +execution attempt and trial/run identities are not interchangeable. +Keep backend-native locators behind a bounded, non-authorizing correlation +boundary; identifiers are neither credentials nor executable commands. + +**Name what fencing proves.** Runtime generation/revision checks reject stale +state publication. A remote fencing or cessation claim must identify its scope +and supporting backend guarantee/evidence; a lease, CAS token, timeout, PID, +cancelled future or killed local process supplies no such proof. Default effect +exclusion is target/run-wide unless the admitted contract establishes narrower +independence. Refusal and progress must also remain correlated to that scope. + +**Represent uncertainty without upgrading evidence.** Keep effect knowledge +(absent, complete, known partial, unknown), cessation and satisfaction of all +admitted result/release gates independent. Known partial effects require +validated residual state/scope; unknown remainder or unproved cessation requires +indeterminacy and retained exclusion. An exception, unsafe snapshot, or +`success=false` is not evidence of no effect. Preserve ASR-532 predecessor +isolation. Reconciliation is bounded observation/classification, never replay. +An immutable indeterminate parent may gain separately authorized linked +resolution evidence, not a rewritten terminal outcome. Administrative snapshot +acceptance is not cessation, clean-state evidence or permission to retry. + +**Contextual support is an optional protocol seam.** Bind support and willingness +to operation kind, exact selected requirements, backend contract version and +effective execution context. Preserve the existing manifest/installed-component +agreement; reject an unsupported required guarantee before effects, and recheck +after waiting. Missing support must not become best effort. The extensibility +parameter belongs here, not in backend-name branches or a global +`supports_cancel` Boolean. New cooperative interruption, observation or future +physical-OT capabilities should be selectable without changing P0 defaults or +requiring every backend to implement them. Publish invocation, concurrency, +side-effect and failure semantics so backend authors can implement the protocol +without owning scenario scheduling, retries, terminal commits or a second runtime. + +Reuse authored workflow/time/trial authorities: `WorkflowExecutionContract`, +`ExecutionRetryPolicyModel`, `TrialExecutionAuthorityModel`, +`AdmittedExecutionControlModel`, cleanup plan/receipt models and +`require_cleanup_plan_capability()`. Transport duplicates do not create attempts; +recovery does not allocate trials. Continuation requires established authority +and a compatible boundary; do not invent a general checkpoint format here. +Operational stage budgets remain positive, finite apparatus bounds with explicit +origins; duplicate messages do not renew them. Reuse `control_plane_timeouts.py` +and the shared time validators. Portable UTC timestamps and authored semantic +clock/domain/segment identity are not restartable monotonic deadlines. + +## Cross-cutting layers the design must pass + +| Layer and canonical incumbents | Required treatment | +| --- | --- | +| Source and admitted plans: `raes` models/validators, `raes_processor/compiler`, workflow/time/trial contracts | Reference or carry admitted requirements without reinterpreting authored source. Reuse existing policy defaults and cross-object validators; do not hide execution policy in metadata or transport settings. Ordinary P0 work needs no trial or participant wrapper. | +| Configuration and capability shape: `ControlPlaneOptions`, `control_plane_configuration.py`, `RuntimeTarget`/`RuntimeTargetComponents` in `registry.py`, `registry_target_validation.py`, `raes_backend_protocols/{capabilities,manifest,backend_manifest,capability_admission}.py` | Extend closed models, manifest conversion and signature/presence checks together wherever integration is touched. A protocol declaration must not advertise an installed implementation. Registry probing checks call shape without invoking effects. Retain operation-kind restrictions, including the distinction between observation and administrative resolution. | +| Profile/version admission: `raes_contracts/{manifest_authority,backend_profiles,versions}.py`, `contracts/profiles/backend/`, `raes_runtime/control_plane_profiles.py` | Register contract IDs in the correct producer/consumer allowlists. Backend profiles enumerate required contracts; P0–P3 describe runtime/store/deployment guarantees. They are different axes. Preserve P1/P2 optional observation with indeterminate fallback; it cannot satisfy a request explicitly requiring provable recovery. P3 stays unavailable. Profile loading keeps grammar and payload-identity checks before path use. | +| Authentication/disclosure: `ControlPlaneSecurityConfig.strict_defaults()`, `control_plane_api/_auth.py`, `ControlPlaneIdentity`, `control_plane_plan_authorization.py`, `operation_admission_context()` | Derive actors from trusted identity, not request assertions. Reauthorize status, cancellation and reconciliation for the exact target/run/subject; preserve operator-only administrative resolution. A receipt, backend handle or fencing value grants no access. Retain hard failure for invalid bearer credentials and explicit proxy trust. Direct calls retain the trusted embedder boundary. | +| Request/value admission: `RequestSizeLimitMiddleware`, `_ControlPlaneCallExecutor`, `ContractModel`, `raes_contracts/runtime_value_limits.py`, `backend_input_contracts.py`, `backend_call_contracts.py` | Bound identifiers, collections, nesting, diagnostics and progress/evidence volume before copying, hashing or publication. Closed models alone do not imply strict booleans/numbers or finite budgets. Use existing strict primitives and calendar validation. Bound supervisory traffic independently of effect traffic; no unbounded iterator or acknowledged-but-discarded control request. | +| Secrets/environment: `SecretReferenceId`, `runtime_fact_dispatch.py`, `runtime_fact_binding_policy.py`, `raes/runtime_environment.py`, planner `stateful_admission.py` | Carry authorized references rather than resolved credentials in durable/public context. Preserve visibility/freshness and closed generated-environment projections. `value_from` excludes literal values and `operator_secret`; redacted/operator-secret values cannot contain raw material. Rebinding inputs reapplies the existing gates. `control_plane_operation_context.py` and `control_plane_admission.py` keep credential-sensitive retry proof ephemeral; a public commitment after restart is insufficient. | +| Backend result admission: `backend_calls.py`, `_validated_backend_result()`, `backend_result_diagnostics.py`, `result_contracts.py`, [result-admission spec](../../specs/formal/runtime-contracts/backend-result-admission.md) | Use isolated predecessors, native domain/workflow/participant/time validation, realization authority, changed-address accounting and credential egress checks for partial, recovery and late results too. Typed backend evidence remains untrusted. Known effects do not bypass final disclosure/release gates. | +| Persistence: `RuntimeMutationAuthority`, `RuntimeDurabilityMixin`, `ControlPlaneStoreCommitAdapter`, `control_plane_store_records.py`, `control_plane_store_record_migration.py`, `control_plane_store_paths.py` | Retain one writer, atomic claims and snapshot/terminal/audit commit, revision CAS, immutable terminal history and strict codecs. Unknown store acknowledgement requires authoritative readback/poisoning, distinct from unknown external effects. Preserve private paths, lease-before-inspection and close-before-lease-release. No new supervision store, callback-owned commit, or database transaction spanning backend execution. | +| Errors/observability: `Diagnostic`/`DiagnosticModel`, `portable_diagnostic_payload()`, canonical terminal diagnostics, `control_plane_api/_responses.py`, `_operation_routes.py`, `AuditEvent`, `control_plane_health.py` | Refusal and uncertainty are typed protocol facts with stable safe diagnostics, not a parallel exception hierarchy. Preserve redacted 422/500 and conflict envelopes. Reject input echoes, raw exception text, native output, credentials and sensitive locators in errors/audit/progress. Reuse bounded actor-bound audit and module loggers; keep health, operational progress, participant observations and archival evidence distinct. | +| Host/process and delivery: existing backend drivers, embedder deployment, `raes_contracts/corpus.py`, Python package configuration | Publishing this protocol needs no shell, port, process manager or new credential loader. Examples must not place tokens in argv, accept request-supplied executable paths, or dump/inherit broad environments. TLS/proxy and process lifecycle remain deployment duties. Load schemas/profiles through the packaged corpus seam, not checkout-relative path heuristics. | + +These are obligations for the eventual implementation, not claims that current +runtime code already provides bounded supervision. In particular, current +external-call locking/drain and exception-to-failed-result behavior remain the +gaps documented by #1348; publishing models does not fix them. +For claim-bearing observability carriers, reuse ADR-066 and +`raes/observability_plane_semantics.py` when publishing `x-raes-plane`: +the classifier rejects unregistered contract IDs. Do not infer the plane from +an `evidence` field name or copy an archival annotation onto operational progress. + +## Publication, compatibility and traceability + +Follow ADR-009/061 and +[the evolution policy](../../specs/evolution/versioning-deprecation-and-migration.md). +Normative schemas live in `contracts/schemas/`; `schema_bundle()` and +`contracts/bundle_runtime.py` must generate identical artifacts. Keep +`tools/generate_contract_schemas.py` routing, public contract exports +(`contracts/__init__.py`/`_exports.py`), `versions.py`, manifests, profiles, +fixtures and public backend/API documentation consistent. Reuse +`corpus.py` and the existing wheel/sdist corpus inclusion in +`implementations/python/pyproject.toml`; backend owners must receive the +contract without a source checkout or a runtime implementation dependency. + +The publication manifest is now a **v2 directory index**. Update each affected +`contracts/schema-publication/entries/.json` with its content hash +and `last_change`; use independent `tombstones/` records for removals. Do not +restore the older monolithic ledger described by some historical notes. + +Choose lineage/discriminators under the existing stability policy and document +producer/consumer direction, semantic as well as structural compatibility, and +source/target migration rules. Optional fields and enum additions can break old +closed readers. Audit receipt/status DTOs, in-process conversions, store codecs, +HTTP response models and downstream CLI/MCP consumers for loss of meaning. +Do not change the shared operation version constant as an isolated edit. +Any legacy adapter must disclose missing guarantees: old applied/absent reports +cannot be promoted to cessation, partial-effect or safe-resume evidence. +Missing historical evidence stays unknown; migrations never replay work, invent +fences, silently discard fields or rewrite terminal history. New protocol +publication need not force a legacy-store rewrite if its carriers remain +separate; document that boundary explicitly. + +API-402 is this delivery's requirement; #1360 supplies its acceptance scope. +Use `RAES_REQUIREMENT_UID=API-402` when the branch lacks a UID. Preserve the +supplied CONSTRAINS/TESTS/DOCUMENTS relationships and use existing +DOCUMENTS/IMPLEMENTS/TESTS conventions for new evidence. Adjacent owners +API-403/404, RUN-304, ASR-532 and #1348's change/retain table remain consistency +obligations, not substitutes for API-402. Distinguish contract publication from +runtime enforcement; do not mark the prerequisite's runtime gaps complete. + +Preflight verification found a governance blocker: the repository-authority +check reports `requirement-policy-missing` because API-402 is not mapped in +`tools/policy/requirement_order.yaml`. Reconcile that mapping with the canonical +requirement authority before delivery; do not guess dependency ordering, use +API-404 to bypass the gate, or report requirement governance as passed. This +guidance does not change requirement policy or traceability records. + +Delivery resolution: API-402's existing ACTIVE live control-plane contract now +maps to the existing `runtime-control-plane` phase beside API-404. A regression +exercises the real policy consumer, and requirement governance passes with +`RAES_REQUIREMENT_UID=API-402`. No dependency phase or prerequisite was removed. + +## Examples and assurance boundary + +Contract examples must demonstrate relationships, not just individually valid +JSON objects. Keep them in the existing fixture/conformance system: + +| Required example | Meaning that must remain visible | +| --- | --- | +| Accepted work | Exact requirement/context binding, acknowledgement before execution, correlated progress and backend evidence; runtime success only after all gates. | +| Contextual refusal | Supported capability but unwilling context; pre-claim denial is audit only, accepted-before-dispatch refusal becomes cancellation with refusal diagnostic. Refusal after possible effects requires effect classification. | +| Cancellation races | Request recorded/accepted differs from cessation. Completion can win; cancellation can retain validated partial effects; late evidence cannot overwrite either terminal result. | +| Duplicate requests | Same scoped identity returns the same work/disposition without another invocation, interrupt or renewed budget. Changed commitments, actors, runs and generations cannot alias the claim. | +| Uncertain completion | Partial effect followed by exception, malformed evidence, absent-at-one-instant without cessation, and lost store acknowledgement retain their distinct uncertainties. Reconciliation supplies evidence without replay. | + +Reuse lifecycle tests (`test_issue_1182_operation_lifecycle_contract.py`), +#1348's bounded supervision model, #1179 recovery, #1184 claims, #1187 durable +carrier/security tests, #1189 profile declarations, `test_backend_profiles.py`, +`test_runtime_contracts.py` and `test_contracts_facade_exports.py`. Include +negative cross-message identity/evidence cases and schema/Python parity; +`test_issue_1348_operation_supervision.py` is an abstract witness, not proof +that an installed backend can stop work. Use existing schema coverage and +fixture validation rather than tests that merely search for model names. +Each new publication needs actual routed corpus/conformance coverage or another +accepted coverage association under `tools/check_schema_coverage.py`; merely +adding a fixture directory does not demonstrate that a runner exercises it. + +Repository conventions remain `.ground-control.yaml`, `.gc/plan-rules.md`, +`noxfile.py` and the existing policy, generated-schema, publication, coverage, +requirement-governance and ADR-pin tools. Run targeted checks for changed +artifacts locally; full/integration/fuzz suites belong to CI. This preflight +changes only guidance and requires no generated artifact or runtime test change. + +Non-goals: implementing execution/supervision, new HTTP endpoints or transports, +a second scenario/workflow engine, generic durable-job/checkpoint services, +implicit retry/resume/rollback, universal cleanup, P3/multiple owners, or physical +containment/certification. Avoid free-form policy/evidence dictionaries, +duplicate lifecycle enums or cleanup schemas, parallel exception/audit systems, +and capability claims inferred from schema availability. Keep implementation +changes for #1360 confined to publishing usable contracts, their necessary +validation/compatibility boundaries and evidence, rather than solving the +prerequisite's entire runtime backlog. diff --git a/docs/explain/reference/backend-operation-supervision.md b/docs/explain/reference/backend-operation-supervision.md new file mode 100644 index 000000000..3d3d01c06 --- /dev/null +++ b/docs/explain/reference/backend-operation-supervision.md @@ -0,0 +1,101 @@ +# Implement the backend operation protocol + +The optional `operation-supervision` profile publishes messages for one +admitted backend invocation. It lets a backend report acceptance, progress, +refusal, effects and cancellation evidence while RAE retains scenario execution +and terminal publication. It does not enable supervision in today's +`RuntimeTarget` or change the runtime P0–P3 profile matrix. + +The [normative contract](../../../specs/formal/runtime-contracts/backend-operation-supervision.md) +defines field meaning, guarantees, identity, budgets and validation. Import +models and validation helpers from `raes_contracts.contracts`, and +`BackendOperationProvider`/`require_operation_provider` from +`raes_backend_protocols.operation_supervision`. This interface has no dependency +on `raes_runtime`. Schemas, profile and examples ship in the existing packaged +contract corpus; use `raes_contracts.corpus` to locate them in an installed wheel. + +## Provider responsibilities + +1. Declare all four `backend-operation-*-v1` contracts in the existing backend + manifest. Implement the six protocol methods and return the current + capability declaration. Use `require_operation_provider` to check the + declaration and call shapes without making an effect call. +2. Implement `check_operation` against the exact resolved native requirements, + command and execution context. Return explicit refusal if any required + guarantee is unsupported or currently unavailable. Match the request and + capability digests; do not claim that a supported protocol proves readiness. +3. Accept `start_operation` only through the trusted RAE invocation path after + it confirms the one-use claim and current authority. Deduplicate the exact + binding/commitment, retain conflicting-effect reservations and return the + same work for duplicate delivery. A changed commitment under an existing + invocation is a conflict, never another start. +4. Return bounded evidence records. Keep a sequence within the invocation; + retries retain its content. Resolve and validate artifacts through their + owning contracts. Partial results include the native residual snapshot and + changed-address scope. Native output, secrets, exception text and process + arguments must not enter these carriers. +5. Serve observation, cancellation and reconciliation independently of effect + worker saturation. Respect the remaining apparatus budget; an accepted + cancellation is only an undertaking. Report cessation only with evidence + that accounts for outstanding workers, effects and residual state. +6. Preserve unknown outcomes and retained exclusion. RAE validates native + results and commits terminal operation/snapshot/audit state. A backend must + not schedule workflow retries, allocate new trials, rewrite an immutable + terminal parent, or treat reconciliation as execution replay. + +Each method returns one `BackendOperationResponseModel`, whose `message.kind` +identifies the payload. `check_operation` returns `admission`; `start_operation` +returns `acknowledgement`; `cancel_operation` returns `control`. +`observe_operation` returns a retained progress/outcome record, a correlated +reconciliation observation, or a control refusal. `reconcile_operation` returns +`reconciliation` or a control refusal. All exceptions/lost replies leave the +caller uncertain; callers never infer no effects from a failed call. + +The shape checker does not authenticate callers, grant claims, exercise the +backend or certify liveness. Independent integrations must implement those +normative duties before claiming support. The existing runtime remains on its +incumbent synchronous protocol until a separate integration delivery wires and +verifies the new path. + +## Migration and compatibility + +| Existing surface | Migration rule | +| --- | --- | +| `operation-receipt-v1`, `operation-status-v1` | Preserve their shared `runtime-operation/v1` discriminator, six states and existing readers. New backend records are separate evidence for the runtime authority. Do not inject unknown fields into old closed readers. | +| `ApplyResult` | Preserve native result admission. A false success flag or predecessor snapshot cannot be converted to effect absence, known failure or cessation. Without independently validated new evidence, the new outcome is indeterminate. | +| `RecoveryObservationResult` | Its absent/applied/indeterminate vocabulary has no general cessation or partial-effect witness. Conversion cannot invent one. Keep legacy reports on the old observer, or obtain fresh evidence before constructing a new report. | +| P1/P2 stored operation records | No store migration in this publication. Existing strict codecs keep their existing shape. A later integration must explicitly version/persist the new facts and test lossless readback before it claims supervision across restart. | +| Backend manifests/profiles | New draft schemas expand the backend contract-ID allowlist. Old manifests and profiles remain valid under the new reader; old closed readers can reject new IDs. Negotiate support before sending new messages. Never strip IDs or fields to disguise incompatibility. | +| P0–P3 runtime profiles | Unchanged guarantees. This backend profile is a separate axis; schema availability cannot activate distributed operation, interruption, recovery, or P3. | + +Migration must preserve complete bindings, request/requirement commitments, +control actors, sequence and remaining budget origins. If historical records +lack any required fact, there is **no lossless automatic conversion**. Refuse +the stronger protocol or retain unknown evidence through the existing recovery +path. Do not fabricate generations, claim IDs, cessation, clean state, +continuation points or retry authority. Changing operation IDs, restoring a +database or restarting a timer is not a migration strategy. + +The four new contracts are draft v1 publications under ADR-009/061. Incompatible +future changes follow the existing evolution policy; the reference bundle must +match each normative schema and each publication entry records its content hash +and contract-facing change. This publication changes no existing store/HTTP +projection and does not silently upgrade any backend declaration. + +## Examples and evidence limits + +The packaged `fixtures/control-plane/` corpus groups exchanges by filename: + +| Prefix | What the exchange demonstrates | +| --- | --- | +| `accepted` | Willing admission, accepted invocation, progress and a success proposal awaiting RAE validation. | +| `refused` | A capable backend declines the exact context. No invocation follows. | +| `cancel-race` | Cancellation is accepted, then completion proposes success. RAE decides the atomic settlement order. | +| `partial-cancel` | Cancellation is established with known residual effects; no rollback is asserted. | +| `duplicate` | Identical sequence and acknowledgement may be read twice without a second invocation. | +| `uncertain` | Unknown effects remain indeterminate; later reconciliation evidence cannot rewrite that parent. | + +`test_issue_1360_backend_operations.py` validates these messages and their +relationships. Fixture evidence references are synthetic. A real implementation +must resolve and validate actual evidence and pass runtime/backend conformance +before these examples can support stronger claims. diff --git a/docs/explain/sdl/runtime-architecture.md b/docs/explain/sdl/runtime-architecture.md index bd169ecff..753373df2 100644 --- a/docs/explain/sdl/runtime-architecture.md +++ b/docs/explain/sdl/runtime-architecture.md @@ -675,3 +675,13 @@ The current runtime scope includes: Real Docker/cloud/simulation backends are outside this repository's current implementation surface. Such backends would have to consume and satisfy these contracts. + +## Optional backend operation contracts + +The [operation-supervision family](../../../specs/formal/runtime-contracts/backend-operation-supervision.md) +publishes the portable backend boundary for the accepted supervision design. +It separates capability, willingness, acknowledgement, progress, control +dispositions and scoped effect evidence. RAE retains native result validation +and atomic terminal publication. The [migration guide](../reference/backend-operation-supervision.md) +explains the additive profile and the limits of legacy conversions. These +contracts do not enable a new RuntimeTarget provider or change P0–P3 guarantees. diff --git a/docs/public/api/contracts.rst b/docs/public/api/contracts.rst index 93595c34b..7f255bb2f 100644 --- a/docs/public/api/contracts.rst +++ b/docs/public/api/contracts.rst @@ -59,3 +59,21 @@ compatibility, decision-surface modes, tool-affordance expectations, and 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. + +Backend operation supervision +----------------------------- + +The optional backend protocol reports evidence for one admitted invocation. +The shared runtime retains authorization, scenario execution and terminal state. + +.. automodule:: raes_contracts.contracts.backend_operation + :members: + +.. automodule:: raes_contracts.contracts.backend_operation_response + :members: + +.. automodule:: raes_contracts.contracts.backend_operation_validation + :members: + +.. automodule:: raes_backend_protocols.operation_supervision + :members: diff --git a/docs/public/backends.md b/docs/public/backends.md index bb07a9290..e0ed7a422 100644 --- a/docs/public/backends.md +++ b/docs/public/backends.md @@ -22,3 +22,9 @@ and the [conformance API](api/contracts.rst). Backends can also report what they built as SDL. The runtime saves this record with the run. See [SDL run records](https://github.com/OpenRAE/rae/blob/main/docs/explain/reference/materialization-attestations.md) for the contract and setup. + +The optional operation-supervision profile defines requests, progress, +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. diff --git a/docs/requirements/API-402/requirement.md b/docs/requirements/API-402/requirement.md index 3b7de7bd8..4444be226 100644 --- a/docs/requirements/API-402/requirement.md +++ b/docs/requirements/API-402/requirement.md @@ -6,7 +6,7 @@ type: FUNCTIONAL priority: MUST wave: 1 created_at: 2026-04-03T05:40:04.988670Z -updated_at: 2026-04-05T03:06:54.035699Z +updated_at: 2026-09-24T00:00:00.000000Z --- # API-402 — Plain-Data Execution, Result, And History Contracts @@ -34,3 +34,25 @@ Current state: implemented. Portable live-execution contracts are required so in - CONSTRAINS → SPEC `contracts/schemas/control-plane/workflow-history-event-stream-v1.json` (Workflow History Event Stream Schema) - CONSTRAINS → SPEC `contracts/schemas/control-plane/evaluation-history-event-stream-v1.json` (Evaluation History Event Stream Schema) - CONSTRAINS → SPEC `contracts/schemas/snapshots/runtime-snapshot-v1.json` (Runtime Snapshot Schema) + +- IMPLEMENTS → GITHUB_ISSUE `1360` (Optional backend operation and supervision contract publication) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_backend_protocols/__init__.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_backend_protocols/operation_supervision.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_backend_protocols/protocols.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/__init__.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/_exports.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/_version_exports.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/backend_operation.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/backend_operation_response.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/backend_operation_schema.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/backend_operation_validation.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/bundle_runtime.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/manifest_authority.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/versions.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- TESTS → TEST `implementations/python/tests/test_issue_1360_backend_operations.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- TESTS → TEST `implementations/python/tests/test_issue_1360_operation_rejections.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) +- IMPLEMENTS → SPEC `specs/formal/runtime-contracts/backend-operation-supervision.md` (Normative carrier and cross-message semantics) +- DOCUMENTS → DOCUMENTATION `docs/explain/reference/backend-operation-supervision.md` (Provider duties, migration and evidence limits) +- DOCUMENTS → DOCUMENTATION `docs/decisions/issue-1360-backend-operation-contracts-preflight.md` (Contract publication guardrails) +- IMPLEMENTS → CONFIG `tools/policy/requirement_order.yaml` (Existing live-contract requirement admitted through control-plane governance) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/_backend_operation_exports.py` (Public operation contract facade exports) diff --git a/implementations/python/packages/raes_backend_protocols/__init__.py b/implementations/python/packages/raes_backend_protocols/__init__.py index 4bf684e56..4323b8cba 100644 --- a/implementations/python/packages/raes_backend_protocols/__init__.py +++ b/implementations/python/packages/raes_backend_protocols/__init__.py @@ -1,5 +1,7 @@ """Backend-facing protocol and capability declarations.""" from .domain_topology import DomainTopologyBinding as DomainTopologyBinding +from .operation_supervision import BackendOperationProvider as BackendOperationProvider +from .operation_supervision import require_operation_provider as require_operation_provider -__all__ = ["DomainTopologyBinding"] +__all__ = ["DomainTopologyBinding", "BackendOperationProvider", "require_operation_provider"] diff --git a/implementations/python/packages/raes_backend_protocols/operation_supervision.py b/implementations/python/packages/raes_backend_protocols/operation_supervision.py new file mode 100644 index 000000000..68791693e --- /dev/null +++ b/implementations/python/packages/raes_backend_protocols/operation_supervision.py @@ -0,0 +1,93 @@ +"""Optional one-invocation backend protocol; RAE retains scenario and state authority.""" + +from __future__ import annotations + +from collections.abc import Iterable +from inspect import signature +from typing import Protocol, cast + +from raes_contracts.contracts import ( + BackendOperationCapabilitiesModel, + BackendOperationControlModel, + BackendOperationRequestModel, + BackendOperationResponseModel, +) +from raes_contracts.manifest_authority import validate_backend_supported_contract_versions +from raes_contracts.versions import BACKEND_OPERATION_CONTRACT_IDS + + +class BackendOperationProvider(Protocol): + """Bounded calls on separately provisioned effect/control capacity. + + All responses echo the exact invocation binding and request commitment. + Callers authenticate and authorize separately, resolve the command and + requirements through their owning authorities, and consume the current + one-use invocation claim before start. No method schedules scenario work, + allocates a trial/retry, publishes a snapshot or commits a terminal state. + A caller timeout cannot establish that any remote effects have stopped. + """ + + def operation_capabilities(self) -> BackendOperationCapabilitiesModel: + """Return the installed declaration; it supplies no contextual willingness.""" + ... + + def check_operation(self, request: BackendOperationRequestModel) -> BackendOperationResponseModel: + """Return admission/refusal without effects; recheck immediately before dispatch.""" + ... + + def start_operation(self, request: BackendOperationRequestModel) -> BackendOperationResponseModel: + """Return acknowledgement; duplicate identity never starts another effect. + + A refusal establishes that this invocation did not start. Once effects + are possible, report uncertainty/outcome evidence through observation. + """ + ... + + def observe_operation(self, request: BackendOperationControlModel) -> BackendOperationResponseModel: + """Return one progress, outcome, reconciliation or control-disposition record. + + Reads are bounded and independently authorized. An observation with + effects of its own requires separate effect admission, not this method. + """ + ... + + def cancel_operation(self, request: BackendOperationControlModel) -> BackendOperationResponseModel: + """Return control disposition; acceptance is not cessation or rollback.""" + ... + + def reconcile_operation(self, request: BackendOperationControlModel) -> BackendOperationResponseModel: + """Return read-only reconciliation evidence or an explicit control refusal.""" + ... + + +def require_operation_provider(provider: object, declared_contracts: Iterable[str]) -> BackendOperationProvider: + """Validate opt-in declaration and installed call shapes without invoking code. + + This public protocol boundary cannot import the runtime's private registry + checker. It provides the same signature binding for independent embedders; + behavioral conformance and contextual admission remain separate checks. + """ + + declared = tuple(declared_contracts) + validate_backend_supported_contract_versions(declared) + if not set(BACKEND_OPERATION_CONTRACT_IDS) <= set(declared): + raise ValueError("backend operation contracts are not declared") + for name in ( + "operation_capabilities", + "check_operation", + "start_operation", + "observe_operation", + "cancel_operation", + "reconcile_operation", + ): + method = getattr(provider, name, None) + if not callable(method): + raise ValueError("backend operation protocol is not installed") + try: + signature(method).bind(*(() if name == "operation_capabilities" else (object(),))) + except (TypeError, ValueError): + raise ValueError("installed backend operation method has incompatible call shape") from None + return cast(BackendOperationProvider, provider) + + +__all__ = ["BackendOperationProvider", "require_operation_provider"] diff --git a/implementations/python/packages/raes_backend_protocols/protocols.py b/implementations/python/packages/raes_backend_protocols/protocols.py index 7ee51c18e..2ff54ac94 100644 --- a/implementations/python/packages/raes_backend_protocols/protocols.py +++ b/implementations/python/packages/raes_backend_protocols/protocols.py @@ -26,6 +26,8 @@ from raes_contracts.realization_preparation import RealizationPreparation from raes_contracts.runtime_state import ApplyResult, RuntimeSnapshot +from .operation_supervision import BackendOperationProvider as BackendOperationProvider + if TYPE_CHECKING: from raes_contracts.contracts.time_model import TimeModelDeclarationModel, TimeRuntimeStateModel diff --git a/implementations/python/packages/raes_contracts/contracts/__init__.py b/implementations/python/packages/raes_contracts/contracts/__init__.py index 932d4c540..f8cc3222d 100644 --- a/implementations/python/packages/raes_contracts/contracts/__init__.py +++ b/implementations/python/packages/raes_contracts/contracts/__init__.py @@ -22,6 +22,7 @@ WorkflowFeature, WorkflowStatePredicateFeature, ) +from ._backend_operation_exports import * from ._candidate_synthesis_facade import * from ._evidence_requirement_exports import * from ._exports import PUBLIC_EXPORTS as __all__ @@ -223,7 +224,6 @@ ) from .mixed_runtime import MixedCompositionRuntimeEventModel, MixedCompositionRuntimeStateModel from .observation_capture import ObservationCaptureOfferModel -from .operation_carriers import OperationReceiptModel, OperationStatusModel from .participant_context import ParticipantContextViewModel from .participant_decision_surface import ( ParticipantDecisionSurfaceActionEntryModel, diff --git a/implementations/python/packages/raes_contracts/contracts/_backend_operation_exports.py b/implementations/python/packages/raes_contracts/contracts/_backend_operation_exports.py new file mode 100644 index 000000000..21f73b900 --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/_backend_operation_exports.py @@ -0,0 +1,72 @@ +"""Operation-contract facade exports, including the retained receipt/status boundary.""" + +from ..versions import ( + BACKEND_OPERATION_CAPABILITIES_SCHEMA_VERSION, + BACKEND_OPERATION_CONTRACT_IDS, + BACKEND_OPERATION_CONTROL_SCHEMA_VERSION, + BACKEND_OPERATION_REQUEST_SCHEMA_VERSION, + BACKEND_OPERATION_RESPONSE_SCHEMA_VERSION, + OPERATION_SCHEMA_VERSION, +) +from .backend_operation import ( + BackendOperationBindingModel, + BackendOperationCapabilitiesModel, + BackendOperationControlModel, + BackendOperationRequestModel, + OperationArtifactReferenceModel, + OperationBudgetModel, + OperationEffectScopeModel, +) +from .backend_operation_response import ( + BackendOperationAcknowledgementModel, + BackendOperationAdmissionModel, + BackendOperationControlDispositionModel, + BackendOperationEffectsModel, + BackendOperationOutcomeModel, + BackendOperationProgressModel, + BackendOperationReconciliationModel, + BackendOperationResponseModel, +) +from .backend_operation_validation import ( + backend_operation_control_digest, + backend_operation_request_digest, + canonical_backend_operation_capabilities_digest, + require_backend_operation_admission, + validate_backend_operation_history, + validate_backend_operation_response, +) +from .operation_carriers import OperationReceiptModel, OperationStatusModel + +__all__ = [ + "BackendOperationBindingModel", + "BackendOperationCapabilitiesModel", + "BackendOperationControlModel", + "BackendOperationRequestModel", + "OperationArtifactReferenceModel", + "OperationBudgetModel", + "OperationEffectScopeModel", + "BackendOperationAcknowledgementModel", + "BackendOperationAdmissionModel", + "BackendOperationControlDispositionModel", + "BackendOperationEffectsModel", + "BackendOperationOutcomeModel", + "BackendOperationProgressModel", + "BackendOperationReconciliationModel", + "BackendOperationResponseModel", + "backend_operation_control_digest", + "backend_operation_request_digest", + "canonical_backend_operation_capabilities_digest", + "require_backend_operation_admission", + "validate_backend_operation_history", + "validate_backend_operation_response", + "BACKEND_OPERATION_REQUEST_SCHEMA_VERSION", + "BACKEND_OPERATION_CAPABILITIES_SCHEMA_VERSION", + "BACKEND_OPERATION_CONTROL_SCHEMA_VERSION", + "BACKEND_OPERATION_RESPONSE_SCHEMA_VERSION", + "BACKEND_OPERATION_CONTRACT_IDS", + "OPERATION_SCHEMA_VERSION", + "OperationReceiptModel", + "OperationStatusModel", +] + +BACKEND_OPERATION_EXPORTS = __all__ diff --git a/implementations/python/packages/raes_contracts/contracts/_exports.py b/implementations/python/packages/raes_contracts/contracts/_exports.py index bc7ab2069..2499c8b14 100644 --- a/implementations/python/packages/raes_contracts/contracts/_exports.py +++ b/implementations/python/packages/raes_contracts/contracts/_exports.py @@ -1,10 +1,12 @@ """Canonical public export manifest for the contracts facade.""" +from ._backend_operation_exports import BACKEND_OPERATION_EXPORTS from ._candidate_synthesis_exports import CANDIDATE_SYNTHESIS_EXPORTS from ._mixed_composition_exports import MIXED_COMPOSITION_EXPORTS from ._participant_control_exports import PARTICIPANT_CONTROL_EXPORTS PUBLIC_EXPORTS = [ + *BACKEND_OPERATION_EXPORTS, *PARTICIPANT_CONTROL_EXPORTS, *MIXED_COMPOSITION_EXPORTS, "MaterializationArchiveRecord", @@ -234,9 +236,6 @@ "EvaluatorCapabilitiesModel", "EventClassificationModel", "InstantiationRequestModel", - "OPERATION_SCHEMA_VERSION", - "OperationReceiptModel", - "OperationStatusModel", "ObservedOperatingSystemIdentityModel", "ObservationCaptureOfferModel", "ObservationCapabilitiesModel", diff --git a/implementations/python/packages/raes_contracts/contracts/_version_exports.py b/implementations/python/packages/raes_contracts/contracts/_version_exports.py index 9f018af6e..d34a1253b 100644 --- a/implementations/python/packages/raes_contracts/contracts/_version_exports.py +++ b/implementations/python/packages/raes_contracts/contracts/_version_exports.py @@ -49,3 +49,9 @@ UCO_ALIGNMENT_SCHEMA_VERSION = _versions.UCO_ALIGNMENT_SCHEMA_VERSION WORKFLOW_CANCELLATION_REQUEST_SCHEMA_VERSION = _versions.WORKFLOW_CANCELLATION_REQUEST_SCHEMA_VERSION WORKFLOW_STATE_SCHEMA_VERSION = _versions.WORKFLOW_STATE_SCHEMA_VERSION + +BACKEND_OPERATION_REQUEST_SCHEMA_VERSION = _versions.BACKEND_OPERATION_REQUEST_SCHEMA_VERSION +BACKEND_OPERATION_CAPABILITIES_SCHEMA_VERSION = _versions.BACKEND_OPERATION_CAPABILITIES_SCHEMA_VERSION +BACKEND_OPERATION_CONTROL_SCHEMA_VERSION = _versions.BACKEND_OPERATION_CONTROL_SCHEMA_VERSION +BACKEND_OPERATION_RESPONSE_SCHEMA_VERSION = _versions.BACKEND_OPERATION_RESPONSE_SCHEMA_VERSION +BACKEND_OPERATION_CONTRACT_IDS = _versions.BACKEND_OPERATION_CONTRACT_IDS diff --git a/implementations/python/packages/raes_contracts/contracts/backend_operation.py b/implementations/python/packages/raes_contracts/contracts/backend_operation.py new file mode 100644 index 000000000..32f843851 --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/backend_operation.py @@ -0,0 +1,130 @@ +"""Bounded portable requests for one backend invocation, never execution authority.""" + +from __future__ import annotations + +from typing import Annotated, Literal + +from pydantic import ConfigDict, Field, model_validator + +from ..addressing import CompiledAddress +from ..operation_lifecycle import OperationAdmissionContext, OperationKind +from ..versions import ( + BACKEND_OPERATION_CAPABILITIES_SCHEMA_VERSION, + BACKEND_OPERATION_CONTROL_SCHEMA_VERSION, + BACKEND_OPERATION_REQUEST_SCHEMA_VERSION, +) +from .base import ContractModel, Rfc3339DateTimeString, _parse_rfc3339_datetime + +OperationIdentifier = Annotated[str, Field(min_length=1, max_length=256)] +OperationDigest = Annotated[str, Field(pattern=r"^sha256:[a-f0-9]{64}$")] +OperationCounter = Annotated[int, Field(strict=True, ge=0, le=9007199254740991)] +OperationPositive = Annotated[int, Field(strict=True, ge=1, le=9007199254740991)] +OperationGuarantee = Literal[ + "cancellation", "effect-observation", "cessation-evidence", "partial-effects", "external-fencing" +] + + +class OperationContractModel(ContractModel): + """Immutable bounded values; decoding a value supplies no authorization.""" + + model_config = ConfigDict(extra="forbid", frozen=True) + + @model_validator(mode="after") + def _unique_collections(self): + for name in type(self).model_fields: + values = getattr(self, name) + if isinstance(values, tuple) and len(values) != len(set(values)): + raise ValueError("operation collections must contain unique values") + return self + + +class OperationArtifactReferenceModel(OperationContractModel): + """Content-bound reference resolved through the owning admitted artifact authority.""" + + contract_id: Annotated[str, Field(max_length=128, pattern=r"^[a-z0-9]+(?:-[a-z0-9]+)*-v[0-9]+$")] + artifact_id: OperationIdentifier + digest: OperationDigest + + +class OperationBudgetModel(OperationContractModel): + """Remaining apparatus budget; the origin is retained across duplicate delivery.""" + + origin_id: OperationIdentifier + started_at: Annotated[Rfc3339DateTimeString, Field(max_length=64)] + limit_ms: OperationPositive + remaining_ms: OperationPositive + + @model_validator(mode="after") + def _budget_bounds(self): + _parse_rfc3339_datetime("started_at", self.started_at) + if self.remaining_ms > self.limit_ms: + raise ValueError("remaining budget cannot exceed its original limit") + return self + + +class OperationEffectScopeModel(OperationContractModel): + """Target/run exclusion is the default; narrowing needs admitted independence.""" + + kind: Literal["target-run", "resources"] = "target-run" + addresses: tuple[CompiledAddress, ...] = Field(default=(), max_length=256) + independence: OperationArtifactReferenceModel | None = None + + @model_validator(mode="after") + def _scope_boundary(self): + if self.kind == "target-run" and (self.addresses or self.independence is not None): + raise ValueError("target/run scope cannot carry a narrowed resource boundary") + if self.kind == "resources" and (not self.addresses or self.independence is None): + raise ValueError("resource scope requires addresses and admitted independence evidence") + return self + + +class BackendOperationBindingModel(OperationContractModel): + """Original context and invocation identity, including state-publication fences.""" + + operation_id: OperationIdentifier + invocation_id: OperationIdentifier + attempt_id: OperationIdentifier + worker_id: OperationIdentifier + deployment_id: OperationIdentifier + owner_generation: OperationCounter + execution_generation: OperationCounter + backend_id: OperationIdentifier + baseline_revision: OperationIdentifier + context: OperationAdmissionContext + effect_scope: OperationEffectScopeModel = Field(default_factory=OperationEffectScopeModel) + + +class BackendOperationRequestModel(OperationContractModel): + """Exact admitted command and requirements checked again immediately before dispatch.""" + + schema_version: Literal[BACKEND_OPERATION_REQUEST_SCHEMA_VERSION] = BACKEND_OPERATION_REQUEST_SCHEMA_VERSION + binding: BackendOperationBindingModel + command: OperationArtifactReferenceModel + requirement_refs: tuple[OperationArtifactReferenceModel, ...] = Field(default=(), max_length=64) + required_guarantees: tuple[OperationGuarantee, ...] = Field(default=(), max_length=5) + budget: OperationBudgetModel + + +class BackendOperationCapabilitiesModel(OperationContractModel): + """Installed provider declaration; neither willingness nor a conformance proof.""" + + schema_version: Literal[BACKEND_OPERATION_CAPABILITIES_SCHEMA_VERSION] = ( + BACKEND_OPERATION_CAPABILITIES_SCHEMA_VERSION + ) + backend_id: OperationIdentifier + revision: OperationDigest + supported_operation_kinds: tuple[OperationKind, ...] = Field(min_length=1, max_length=32) + guarantees: tuple[OperationGuarantee, ...] = Field(default=(), max_length=5) + + +class BackendOperationControlModel(OperationContractModel): + """Independently authorized, idempotent control/observation of the original invocation.""" + + schema_version: Literal[BACKEND_OPERATION_CONTROL_SCHEMA_VERSION] = BACKEND_OPERATION_CONTROL_SCHEMA_VERSION + binding: BackendOperationBindingModel + request_digest: OperationDigest + control_id: OperationIdentifier + actor_id: OperationIdentifier + authorization_scope: tuple[OperationIdentifier, ...] = Field(min_length=1, max_length=64) + action: Literal["cancel", "observe", "reconcile"] + budget: OperationBudgetModel diff --git a/implementations/python/packages/raes_contracts/contracts/backend_operation_response.py b/implementations/python/packages/raes_contracts/contracts/backend_operation_response.py new file mode 100644 index 000000000..76f862180 --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/backend_operation_response.py @@ -0,0 +1,151 @@ +"""Backend reports are correlated evidence proposals, never runtime terminal commits.""" + +from __future__ import annotations + +from typing import Annotated, Literal + +from pydantic import Field, StrictBool, model_validator + +from ..addressing import CompiledAddress +from ..operation_lifecycle import OperationState +from ..versions import BACKEND_OPERATION_RESPONSE_SCHEMA_VERSION +from .backend_operation import ( + BackendOperationBindingModel, + OperationArtifactReferenceModel, + OperationContractModel, + OperationDigest, + OperationIdentifier, + OperationPositive, +) + +OperationRefusalReason = Literal[ + "unsupported-contract", + "unsupported-kind", + "unsupported-guarantee", + "context-refused", + "budget-exhausted", + "stale-binding", + "conflicting-effects", + "unavailable", +] + + +class BackendOperationAdmissionModel(OperationContractModel): + kind: Literal["admission"] = "admission" + disposition: Literal["willing", "refused"] + capability_digest: OperationDigest + reason: OperationRefusalReason | None = None + + @model_validator(mode="after") + def _refusal_reason(self): + if (self.disposition == "refused") != (self.reason is not None): + raise ValueError("only a refused admission requires a refusal reason") + return self + + +class BackendOperationAcknowledgementModel(OperationContractModel): + kind: Literal["acknowledgement"] = "acknowledgement" + disposition: Literal["accepted", "refused"] + reason: OperationRefusalReason | None = None + + @model_validator(mode="after") + def _refusal_reason(self): + if (self.disposition == "refused") != (self.reason is not None): + raise ValueError("only a refused acknowledgement requires a refusal reason") + return self + + +class BackendOperationProgressModel(OperationContractModel): + kind: Literal["progress"] = "progress" + phase: Literal["queued", "executing", "settling"] + evidence_refs: tuple[OperationArtifactReferenceModel, ...] = Field(default=(), max_length=32) + + +class BackendOperationControlDispositionModel(OperationContractModel): + kind: Literal["control"] = "control" + control_id: OperationIdentifier + control_digest: OperationDigest + disposition: Literal["recorded", "accepted", "refused", "unsupported", "already-terminal"] + + +class BackendOperationEffectsModel(OperationContractModel): + """Effect knowledge and cessation are independent, scoped backend assertions.""" + + effect: Literal["absent", "complete", "partial", "unknown"] + cessation_established: StrictBool + evidence_refs: tuple[OperationArtifactReferenceModel, ...] = Field(default=(), max_length=32) + residual_scope: tuple[CompiledAddress, ...] = Field(default=(), max_length=256) + residual_state: OperationArtifactReferenceModel | None = None + external_fence: OperationArtifactReferenceModel | None = None + + @model_validator(mode="after") + def _evidence_boundary(self): + if (self.effect != "unknown" or self.cessation_established or self.external_fence) and not self.evidence_refs: + raise ValueError("known effects, cessation and external fencing require evidence") + if bool(self.residual_scope) != (self.residual_state is not None): + raise ValueError("residual scope and state must be reported together") + if self.effect == "partial" and self.residual_state is None: + raise ValueError("known partial effects require residual state and scope") + if self.effect == "absent" and self.residual_state is not None: + raise ValueError("absent effects cannot carry residual changes") + if self.residual_state and self.residual_state.contract_id != "runtime-snapshot-v1": + raise ValueError("residual state must reference the native runtime snapshot contract") + return self + + +class BackendOperationOutcomeModel(OperationContractModel): + """Proposed outcome requiring RAE's native validation and atomic publication.""" + + kind: Literal["outcome"] = "outcome" + proposed_state: Literal[ + OperationState.SUCCEEDED, OperationState.FAILED, OperationState.CANCELLED, OperationState.INDETERMINATE + ] + effects: BackendOperationEffectsModel + satisfaction: Literal["satisfied", "unsatisfied", "unknown"] + release_gates_satisfied: StrictBool + cancellation_established: StrictBool + result: OperationArtifactReferenceModel | None = None + + @model_validator(mode="after") + def _honest_outcome(self): + known = self.effects.effect != "unknown" and self.effects.cessation_established + if self.proposed_state != OperationState.INDETERMINATE and not known: + raise ValueError("unknown effects or unproved cessation require indeterminate outcome") + if self.proposed_state == OperationState.SUCCEEDED: + if self.satisfaction != "satisfied" or not self.release_gates_satisfied or self.result is None: + raise ValueError("success requires complete satisfaction, result and release gates") + if self.effects.effect == "partial": + raise ValueError("partial effects cannot establish success") + if self.proposed_state == OperationState.FAILED and self.satisfaction != "unsatisfied": + raise ValueError("known failure requires established non-satisfaction") + if self.cancellation_established != (self.proposed_state == OperationState.CANCELLED): + raise ValueError("only an established cancellation may propose cancelled") + return self + + +class BackendOperationReconciliationModel(OperationContractModel): + """Observation for separately authorized resolution, with no replay instruction.""" + + kind: Literal["reconciliation"] = "reconciliation" + control_id: OperationIdentifier + control_digest: OperationDigest + effects: BackendOperationEffectsModel + + +BackendOperationMessage = Annotated[ + BackendOperationAdmissionModel + | BackendOperationAcknowledgementModel + | BackendOperationProgressModel + | BackendOperationControlDispositionModel + | BackendOperationOutcomeModel + | BackendOperationReconciliationModel, + Field(discriminator="kind"), +] + + +class BackendOperationResponseModel(OperationContractModel): + schema_version: Literal[BACKEND_OPERATION_RESPONSE_SCHEMA_VERSION] = BACKEND_OPERATION_RESPONSE_SCHEMA_VERSION + binding: BackendOperationBindingModel + request_digest: OperationDigest + sequence: OperationPositive + message: BackendOperationMessage diff --git a/implementations/python/packages/raes_contracts/contracts/backend_operation_schema.py b/implementations/python/packages/raes_contracts/contracts/backend_operation_schema.py new file mode 100644 index 000000000..009f34ca8 --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/backend_operation_schema.py @@ -0,0 +1,54 @@ +"""Published operation schemas and their mandatory semantic validation bindings.""" + +from __future__ import annotations + +from .backend_operation import ( + BackendOperationCapabilitiesModel, + BackendOperationControlModel, + BackendOperationRequestModel, +) +from .backend_operation_response import BackendOperationResponseModel +from .schema_invariants import _add_raes_invariant + + +def backend_operation_schema_bundle(): + models = { + "backend-operation-request-v1": BackendOperationRequestModel, + "backend-operation-capabilities-v1": BackendOperationCapabilitiesModel, + "backend-operation-control-v1": BackendOperationControlModel, + "backend-operation-response-v1": BackendOperationResponseModel, + } + schemas = {} + for contract_id, model in models.items(): + schema = model.model_json_schema() + _add_raes_invariant( + schema, + "backend-operation-local-consistency", + "Validate unique collections, calendar instants, budget bounds, scope and honest effect/outcome claims; " + "structural validity does not prove backend truth or runtime authority.", + validator=f"raes_contracts.contracts.{model.__name__}.model_validate", + inputs=[{"contract_id": contract_id, "instance_path": "#"}], + ) + schemas[contract_id] = schema + _add_raes_invariant( + schemas["backend-operation-response-v1"], + "backend-operation-response-binding", + "Require exact request binding and commitment, scoped residuals and independently bound controls when present.", + validator="raes_contracts.contracts.validate_backend_operation_response", + inputs=[ + {"contract_id": "backend-operation-request-v1", "instance_path": "#"}, + {"contract_id": "backend-operation-response-v1", "instance_path": "#"}, + ], + ) + _add_raes_invariant( + schemas["backend-operation-capabilities-v1"], + "backend-operation-contextual-admission", + "Before invocation require installed support, matching declaration and current exact-context willingness.", + validator="raes_contracts.contracts.require_backend_operation_admission", + inputs=[ + {"contract_id": "backend-operation-request-v1", "instance_path": "#"}, + {"contract_id": "backend-operation-capabilities-v1", "instance_path": "#"}, + {"contract_id": "backend-operation-response-v1", "instance_path": "#"}, + ], + ) + return schemas diff --git a/implementations/python/packages/raes_contracts/contracts/backend_operation_validation.py b/implementations/python/packages/raes_contracts/contracts/backend_operation_validation.py new file mode 100644 index 000000000..723fccf9c --- /dev/null +++ b/implementations/python/packages/raes_contracts/contracts/backend_operation_validation.py @@ -0,0 +1,136 @@ +"""Pure cross-message checks shared by transports and contract conformance readers.""" + +from __future__ import annotations + +from collections.abc import Sequence + +from ..canonical import canonical_json_digest +from .backend_operation import ( + BackendOperationCapabilitiesModel, + BackendOperationControlModel, + BackendOperationRequestModel, +) +from .backend_operation_response import ( + BackendOperationAcknowledgementModel, + BackendOperationAdmissionModel, + BackendOperationControlDispositionModel, + BackendOperationOutcomeModel, + BackendOperationReconciliationModel, + BackendOperationResponseModel, +) + + +def backend_operation_request_digest(request: BackendOperationRequestModel) -> str: + return canonical_json_digest(request.model_dump(mode="json")) + + +def backend_operation_control_digest(control: BackendOperationControlModel) -> str: + return canonical_json_digest(control.model_dump(mode="json")) + + +def canonical_backend_operation_capabilities_digest(capabilities: BackendOperationCapabilitiesModel) -> str: + return canonical_json_digest(capabilities.model_dump(mode="json")) + + +def validate_backend_operation_response( + request: BackendOperationRequestModel, + response: BackendOperationResponseModel, + *, + control: BackendOperationControlModel | None = None, +) -> None: + """Reject foreign or stale evidence; this does not authenticate its producer.""" + + if response.binding != request.binding: + raise ValueError("backend operation binding mismatch") + if response.request_digest != backend_operation_request_digest(request): + raise ValueError("backend operation request commitment mismatch") + message = response.message + if isinstance(message, (BackendOperationControlDispositionModel, BackendOperationReconciliationModel)): + _validate_control(request, response, control) + if isinstance(message, (BackendOperationOutcomeModel, BackendOperationReconciliationModel)): + scope = request.binding.effect_scope + if scope.kind == "resources" and not set(message.effects.residual_scope) <= set(scope.addresses): + raise ValueError("residual effects exceed the admitted resource scope") + + +def _validate_control(request, response, control): + message = response.message + if control is None or control.binding != request.binding: + raise ValueError("control binding missing or mismatched") + if control.request_digest != response.request_digest: + raise ValueError("control request commitment mismatch") + if message.control_id != control.control_id or message.control_digest != backend_operation_control_digest(control): + raise ValueError("control identity or commitment mismatch") + if isinstance(message, BackendOperationReconciliationModel) and control.action not in {"observe", "reconcile"}: + raise ValueError("control action cannot supply reconciliation evidence") + + +def require_backend_operation_admission( + request: BackendOperationRequestModel, + capabilities: BackendOperationCapabilitiesModel, + response: BackendOperationResponseModel, +) -> None: + """Check declarations and exact-context willingness, never grant invocation authority.""" + + validate_backend_operation_response(request, response) + message = response.message + if not isinstance(message, BackendOperationAdmissionModel): + raise ValueError("backend admission response required") + if capabilities.backend_id != request.binding.backend_id: + raise ValueError("backend capability identity mismatch") + if request.binding.context.operation_kind not in capabilities.supported_operation_kinds: + raise ValueError("backend operation kind is unsupported") + if not set(request.required_guarantees) <= set(capabilities.guarantees): + raise ValueError("required backend operation guarantee is unsupported") + if message.capability_digest != canonical_backend_operation_capabilities_digest(capabilities): + raise ValueError("backend capability commitment mismatch") + if message.disposition != "willing": + raise ValueError("backend context refused") + + +def validate_backend_operation_history( + request: BackendOperationRequestModel, + responses: Sequence[BackendOperationResponseModel], + *, + controls: Sequence[BackendOperationControlModel] = (), +) -> None: + """Validate a bounded invocation transcript; no scheduling, effects or state mutation.""" + + if len(responses) > 1024 or len(controls) > 256: + raise ValueError("backend operation transcript exceeds its bound") + by_control = {} + for control in controls: + if control.control_id in by_control and by_control[control.control_id] != control: + raise ValueError("duplicate control identity changed its commitment") + by_control[control.control_id] = control + seen = {} + previous = 0 + terminal = False + acknowledged = False + for response in responses: + message = response.message + control = by_control.get(message.control_id) if hasattr(message, "control_id") else None + validate_backend_operation_response(request, response, control=control) + if response.sequence in seen: + if seen[response.sequence] != response: + raise ValueError("duplicate response sequence changed its content") + continue + if response.sequence <= previous: + raise ValueError("response sequence is stale or unordered") + if terminal and message.kind not in {"control", "reconciliation"}: + raise ValueError("terminal evidence cannot be rewritten") + if isinstance(message, BackendOperationAdmissionModel): + if acknowledged: + raise ValueError("admission must precede invocation acknowledgement") + terminal = message.disposition == "refused" + if isinstance(message, BackendOperationAcknowledgementModel): + if acknowledged: + raise ValueError("invocation cannot be acknowledged twice") + acknowledged = message.disposition == "accepted" + terminal = not acknowledged + if message.kind in {"progress", "outcome"} and not acknowledged: + raise ValueError("execution evidence requires acknowledgement") + if isinstance(message, BackendOperationOutcomeModel): + terminal = True + seen[response.sequence] = response + previous = response.sequence diff --git a/implementations/python/packages/raes_contracts/contracts/bundle_runtime.py b/implementations/python/packages/raes_contracts/contracts/bundle_runtime.py index a9768a775..5fe80e9d9 100644 --- a/implementations/python/packages/raes_contracts/contracts/bundle_runtime.py +++ b/implementations/python/packages/raes_contracts/contracts/bundle_runtime.py @@ -5,6 +5,7 @@ from typing import Any from .associated_artifacts import AssociatedArtifactManifestModel +from .backend_operation_schema import backend_operation_schema_bundle from .execution_state import EvaluationHistoryEventModel from .experiment_bindings import ParticipantConfigurationResultModel from .operation_carriers import OperationReceiptModel, OperationStatusModel @@ -83,6 +84,7 @@ def _participant_control_schema_bundle() -> dict[str, dict[str, Any]]: def _runtime_schema_bundle() -> dict[str, dict[str, Any]]: return { + **backend_operation_schema_bundle(), **_participant_control_schema_bundle(), "evaluation-history-event-stream-v1": _event_stream_schema( "EvaluationHistoryEventStream", diff --git a/implementations/python/packages/raes_contracts/manifest_authority.py b/implementations/python/packages/raes_contracts/manifest_authority.py index 4c8f068b4..32c53a528 100644 --- a/implementations/python/packages/raes_contracts/manifest_authority.py +++ b/implementations/python/packages/raes_contracts/manifest_authority.py @@ -4,6 +4,8 @@ from collections.abc import Iterable +from .versions import BACKEND_OPERATION_CONTRACT_IDS + PROCESSOR_SUPPORTED_SDL_VERSION_IDS = ("sdl-authoring-input-v1",) # These are the published processor-facing and live-control-plane contracts a @@ -37,6 +39,7 @@ # profiles, processor manifests, and authoring-side request artifacts are # separate authority surfaces and do not belong in this declaration field. BACKEND_SUPPORTED_CONTRACT_IDS = ( + *BACKEND_OPERATION_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 ac08d6a20..6619fbf3b 100644 --- a/implementations/python/packages/raes_contracts/versions.py +++ b/implementations/python/packages/raes_contracts/versions.py @@ -36,6 +36,16 @@ WORKFLOW_CANCELLATION_REQUEST_SCHEMA_VERSION = "workflow-cancellation-request/v1" RUNTIME_SNAPSHOT_SCHEMA_VERSION = "runtime-snapshot/v1" OPERATION_SCHEMA_VERSION = "runtime-operation/v1" +BACKEND_OPERATION_REQUEST_SCHEMA_VERSION = "backend-operation-request/v1" +BACKEND_OPERATION_CAPABILITIES_SCHEMA_VERSION = "backend-operation-capabilities/v1" +BACKEND_OPERATION_CONTROL_SCHEMA_VERSION = "backend-operation-control/v1" +BACKEND_OPERATION_RESPONSE_SCHEMA_VERSION = "backend-operation-response/v1" +BACKEND_OPERATION_CONTRACT_IDS = ( + "backend-operation-request-v1", + "backend-operation-capabilities-v1", + "backend-operation-control-v1", + "backend-operation-response-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/tests/test_issue_1360_backend_operations.py b/implementations/python/tests/test_issue_1360_backend_operations.py new file mode 100644 index 000000000..679e1e958 --- /dev/null +++ b/implementations/python/tests/test_issue_1360_backend_operations.py @@ -0,0 +1,377 @@ +"""Portable operation evidence, contextual admission and supervision boundaries.""" + +from __future__ import annotations + +import json +from pathlib import Path + +import pytest +from jsonschema import Draft202012Validator +from jsonschema import ValidationError as SchemaValidationError +from pydantic import ValidationError +from raes_contracts import contracts +from tools.policy.requirement_governance import evaluate_requirement_governance + +ROOT = Path(__file__).resolve().parents[3] + + +def request_payload(): + return { + "schema_version": "backend-operation-request/v1", + "binding": { + "operation_id": "operation-1", + "invocation_id": "invocation-1", + "attempt_id": "attempt-1", + "worker_id": "worker-1", + "deployment_id": "deployment-1", + "owner_generation": 1, + "execution_generation": 1, + "backend_id": "backend-1", + "baseline_revision": "revision-1", + "context": { + "actor_id": "author-1", + "authorization_scope": ["role:operator"], + "target_scope": "target-1", + "run_scope": "run-1", + "operation_kind": "provisioning", + "request_commitment": "sha256:" + "a" * 64, + }, + "effect_scope": {"kind": "target-run"}, + }, + "command": artifact("provisioning-plan-v1"), + "requirement_refs": [artifact("artifact-requirement-v1")], + "required_guarantees": ["cessation-evidence"], + "budget": budget(), + } + + +def artifact(contract_id="runtime-snapshot-v1"): + return {"contract_id": contract_id, "artifact_id": "artifact-1", "digest": "sha256:" + "b" * 64} + + +def budget(): + return {"origin_id": "budget-1", "started_at": "2026-09-24T00:00:00Z", "limit_ms": 1000, "remaining_ms": 900} + + +def request(): + return contracts.BackendOperationRequestModel.model_validate(request_payload()) + + +def capabilities(): + return contracts.BackendOperationCapabilitiesModel( + backend_id="backend-1", + revision="sha256:" + "c" * 64, + supported_operation_kinds=["provisioning"], + guarantees=["cessation-evidence", "cancellation", "effect-observation", "partial-effects"], + ) + + +def response(message, sequence=1, operation=None): + operation = operation or request() + return contracts.BackendOperationResponseModel( + binding=operation.binding, + request_digest=contracts.backend_operation_request_digest(operation), + sequence=sequence, + message=message, + ) + + +def admission(disposition="willing"): + return response( + { + "kind": "admission", + "disposition": disposition, + "capability_digest": contracts.canonical_backend_operation_capabilities_digest(capabilities()), + "reason": None if disposition == "willing" else "context-refused", + } + ) + + +def evidence(effect="complete", cessation=True): + result = { + "effect": effect, + "cessation_established": cessation, + "evidence_refs": [artifact("backend-materialization-attestation-v1")], + "residual_scope": [], + "residual_state": None, + } + if effect in {"complete", "partial"}: + result.update(residual_scope=["node.vm1"], residual_state=artifact()) + return result + + +def outcome(state="succeeded", **updates): + message = { + "kind": "outcome", + "proposed_state": state, + "effects": evidence(), + "satisfaction": "satisfied", + "release_gates_satisfied": True, + "cancellation_established": False, + "result": artifact("runtime-snapshot-v1"), + } + message.update(updates) + return message + + +def control(action="cancel"): + op = request() + return contracts.BackendOperationControlModel( + binding=op.binding, + request_digest=contracts.backend_operation_request_digest(op), + control_id="control-1", + actor_id="supervisor-1", + authorization_scope=["role:operator"], + action=action, + budget=budget(), + ) + + +def test_api_402_is_admitted_by_real_requirement_policy(): + class Client: + def get_requirement(self, project, uid): + return {"id": uid, "uid": uid, "status": "ACTIVE"} + + def get_traceability(self, requirement_id): + return [] + + assert ( + evaluate_requirement_governance(ROOT, ["contracts/README.md"], client=Client(), requirement_uid="API-402") == [] + ) + + +def test_contextual_willingness_and_capability_are_both_required(): + contracts.require_backend_operation_admission(request(), capabilities(), admission()) + with pytest.raises(ValueError, match="refused"): + contracts.require_backend_operation_admission(request(), capabilities(), admission("refused")) + unsupported = capabilities().model_dump() + unsupported["guarantees"] = [] + unsupported = contracts.BackendOperationCapabilitiesModel.model_validate(unsupported) + with pytest.raises(ValueError): + contracts.require_backend_operation_admission(request(), unsupported, admission()) + + +@pytest.mark.parametrize( + "field,value", + [ + ("operation_id", "other"), + ("invocation_id", "other"), + ("attempt_id", "other"), + ("worker_id", "other"), + ("deployment_id", "other"), + ("owner_generation", 2), + ("execution_generation", 2), + ("backend_id", "other"), + ("baseline_revision", "other"), + ], +) +def test_individually_valid_foreign_response_is_rejected(field, value): + raw = response({"kind": "acknowledgement", "disposition": "accepted", "reason": None}).model_dump() + raw["binding"][field] = value + foreign = contracts.BackendOperationResponseModel.model_validate(raw) + with pytest.raises(ValueError, match="binding"): + contracts.validate_backend_operation_response(request(), foreign) + + +@pytest.mark.parametrize("field", ["actor_id", "target_scope", "run_scope", "request_commitment"]) +def test_original_admission_context_cannot_be_rebound(field): + raw = admission().model_dump() + raw["binding"]["context"][field] = "sha256:" + "d" * 64 if field == "request_commitment" else "other" + foreign = contracts.BackendOperationResponseModel.model_validate(raw) + with pytest.raises(ValueError, match="binding"): + contracts.validate_backend_operation_response(request(), foreign) + + +def test_request_commitment_includes_guarantees_budget_and_artifact(): + original = request() + for field, value in [ + ("required_guarantees", []), + ("budget", {**budget(), "remaining_ms": 800}), + ("command", artifact("orchestration-plan-v1")), + ]: + raw = request_payload() + raw[field] = value + changed = contracts.BackendOperationRequestModel.model_validate(raw) + assert contracts.backend_operation_request_digest(changed) != contracts.backend_operation_request_digest( + original + ) + with pytest.raises(ValueError, match="commitment"): + contracts.validate_backend_operation_response(changed, admission()) + + +@pytest.mark.parametrize("effect,ceased", [("unknown", False), ("unknown", True), ("absent", False)]) +@pytest.mark.parametrize("state", ["succeeded", "failed", "cancelled"]) +def test_unknown_effects_or_unproved_cessation_cannot_claim_known_terminal_outcome(effect, ceased, state): + with pytest.raises(ValidationError): + response(outcome(state, effects=evidence(effect, ceased), cancellation_established=state == "cancelled")) + + +def test_known_partial_cancellation_preserves_residual_state(): + result = response( + outcome( + "cancelled", + effects=evidence("partial"), + satisfaction="unsatisfied", + release_gates_satisfied=False, + cancellation_established=True, + ) + ) + assert result.message.effects.residual_state.contract_id == "runtime-snapshot-v1" + raw = result.model_dump() + raw["message"]["effects"]["residual_state"] = None + with pytest.raises(ValidationError): + contracts.BackendOperationResponseModel.model_validate(raw) + + +def test_cancel_acceptance_can_be_followed_by_success_without_claiming_cancellation(): + ctl = control() + acknowledgement = response({"kind": "acknowledgement", "disposition": "accepted", "reason": None}) + accepted = response( + { + "kind": "control", + "control_id": ctl.control_id, + "control_digest": contracts.backend_operation_control_digest(ctl), + "disposition": "accepted", + }, + 2, + ) + completed = response(outcome(), 3) + contracts.validate_backend_operation_history(request(), [acknowledgement, accepted, completed], controls=[ctl]) + assert completed.message.proposed_state.value == "succeeded" + + +def test_duplicate_records_are_idempotent_but_changed_sequence_content_is_rejected(): + ack = response({"kind": "acknowledgement", "disposition": "accepted", "reason": None}) + contracts.validate_backend_operation_history(request(), [ack, ack]) + conflict = response({"kind": "acknowledgement", "disposition": "refused", "reason": "context-refused"}) + with pytest.raises(ValueError, match="sequence"): + contracts.validate_backend_operation_history(request(), [ack, conflict]) + + +def test_uncertain_completion_and_reconciliation_do_not_rewrite_parent_outcome(): + uncertain = response( + outcome( + "indeterminate", + effects=evidence("unknown", False), + satisfaction="unknown", + release_gates_satisfied=False, + result=None, + ), + 2, + ) + ack = response({"kind": "acknowledgement", "disposition": "accepted", "reason": None}) + ctl = control("reconcile") + observed = response( + { + "kind": "reconciliation", + "control_id": ctl.control_id, + "control_digest": contracts.backend_operation_control_digest(ctl), + "effects": evidence(), + }, + 3, + ) + contracts.validate_backend_operation_history(request(), [ack, uncertain, observed], controls=[ctl]) + with pytest.raises(ValueError, match="terminal"): + contracts.validate_backend_operation_history(request(), [ack, uncertain, response(outcome(), 3)]) + + +@pytest.mark.parametrize( + "field,value", + [("limit_ms", True), ("limit_ms", "1000"), ("limit_ms", 0), ("remaining_ms", 1001), ("remaining_ms", float("inf"))], +) +def test_budgets_reject_coercion_expiry_and_renewal(field, value): + raw = request_payload() + raw["budget"][field] = value + with pytest.raises(ValidationError): + contracts.BackendOperationRequestModel.model_validate(raw) + + +def test_closed_versioned_carriers_reject_unknown_fields_and_versions(): + for mutation in [{"schema_version": "backend-operation-request/v2"}, {"metadata": {"retry": True}}]: + with pytest.raises(ValidationError): + contracts.BackendOperationRequestModel.model_validate({**request_payload(), **mutation}) + + +def test_supervisor_identity_and_control_commitment_are_independent(): + ctl = control() + assert ctl.actor_id != ctl.binding.context.actor_id + raw = ctl.model_dump() + raw["actor_id"] = "different-supervisor" + other = contracts.BackendOperationControlModel.model_validate(raw) + report = response( + { + "kind": "control", + "control_id": ctl.control_id, + "control_digest": contracts.backend_operation_control_digest(ctl), + "disposition": "accepted", + } + ) + with pytest.raises(ValueError, match="control"): + contracts.validate_backend_operation_response(request(), report, control=other) + + +def test_published_family_and_profile_are_consumable_without_runtime(): + from raes_backend_protocols.operation_supervision import BackendOperationProvider, require_operation_provider + from raes_contracts.backend_profiles import load_backend_profile + + family = { + "backend-operation-request-v1": request(), + "backend-operation-capabilities-v1": capabilities(), + "backend-operation-control-v1": control(), + "backend-operation-response-v1": admission(), + } + profile = load_backend_profile("operation-supervision") + assert set(family) <= set(profile.required_contracts) + bundle = contracts.schema_bundle() + for name, value in family.items(): + schema = json.loads((ROOT / f"contracts/schemas/control-plane/{name}.json").read_text()) + assert schema == bundle[name] + Draft202012Validator(schema).validate(value.model_dump(mode="json")) + with pytest.raises(SchemaValidationError): + Draft202012Validator(schema).validate({**value.model_dump(mode="json"), "metadata": {}}) + assert schema["x-raes-semantic-profile"]["required"] is True + with pytest.raises(ValueError, match="installed"): + require_operation_provider(object(), profile.required_contracts) + assert BackendOperationProvider is not None + + +@pytest.mark.parametrize( + "changes", + [ + {"effects": evidence("partial")}, + {"result": None}, + {"release_gates_satisfied": False}, + {"satisfaction": "unknown"}, + {"cancellation_established": True}, + ], +) +def test_success_requires_full_validated_claim_not_just_observed_effects(changes): + with pytest.raises(ValidationError): + response(outcome(**changes)) + + +def test_example_corpus_exercises_every_message_and_required_scenario(): + from raes_contracts.corpus import FIXTURES, corpus_family_root + + root = corpus_family_root(FIXTURES) / "control-plane" + request_root = root / "backend-operation-request-v1/valid" + response_root = root / "backend-operation-response-v1/valid" + kinds = set() + for scenario in ["accepted", "refused", "cancel-race", "partial-cancel", "duplicate", "uncertain"]: + op = contracts.BackendOperationRequestModel.model_validate_json((request_root / f"{scenario}.json").read_text()) + reports = [ + contracts.BackendOperationResponseModel.model_validate_json(p.read_text()) + for p in sorted(response_root.glob(f"{scenario}-*.json")) + ] + controls = [ + contracts.BackendOperationControlModel.model_validate_json(p.read_text()) + for p in sorted((root / "backend-operation-control-v1/valid").glob(f"{scenario}-*.json")) + ] + assert reports + for report in reports: + kinds.add(report.message.kind) + Draft202012Validator(contracts.schema_bundle()["backend-operation-response-v1"]).validate( + report.model_dump(mode="json") + ) + contracts.validate_backend_operation_history(op, reports, controls=controls) + assert kinds == {"admission", "acknowledgement", "progress", "control", "outcome", "reconciliation"} diff --git a/implementations/python/tests/test_issue_1360_operation_rejections.py b/implementations/python/tests/test_issue_1360_operation_rejections.py new file mode 100644 index 000000000..f2812d95a --- /dev/null +++ b/implementations/python/tests/test_issue_1360_operation_rejections.py @@ -0,0 +1,207 @@ +"""Adversarial portable supervision inputs and installed-provider admission.""" + +import pytest +from pydantic import ValidationError +from raes_backend_protocols.operation_supervision import require_operation_provider +from raes_contracts import contracts +from raes_contracts.versions import BACKEND_OPERATION_CONTRACT_IDS +from test_issue_1360_backend_operations import ( + admission, + artifact, + capabilities, + control, + evidence, + outcome, + request, + request_payload, + response, +) + + +def test_refused_admission_cannot_be_followed_by_dispatch(): + refused = admission("refused") + ack = response({"kind": "acknowledgement", "disposition": "accepted"}, 2) + with pytest.raises(ValueError, match="terminal"): + contracts.validate_backend_operation_history(request(), [refused, ack]) + + +@pytest.mark.parametrize("disposition", ["willing", "refused"]) +def test_admission_cannot_reclassify_an_accepted_invocation(disposition): + ack = response({"kind": "acknowledgement", "disposition": "accepted"}) + late_admission = response(admission(disposition).message, 2) + with pytest.raises(ValueError, match="admission must precede"): + contracts.validate_backend_operation_history(request(), [ack, late_admission]) + + +@pytest.mark.parametrize( + "timestamp", ["2026-02-30T00:00:00Z", "2026-09-24T00:00:00", "2026-09-24T00:00:00." + "1" * 80 + "Z"] +) +def test_budget_origin_is_a_bounded_real_calendar_instant(timestamp): + raw = request_payload() + raw["budget"]["started_at"] = timestamp + with pytest.raises(ValidationError): + contracts.BackendOperationRequestModel.model_validate(raw) + + +@pytest.mark.parametrize( + "changes", + [ + {"effect": "partial", "residual_scope": [], "residual_state": None}, + {"effect": "absent"}, + {"evidence_refs": []}, + {"residual_state": artifact("workflow-result-envelope-v1")}, + {"cessation_established": "false"}, + {"residual_scope": ["node.vm1", "node.vm1"]}, + ], +) +def test_effect_claims_reject_missing_contradictory_or_coerced_evidence(changes): + with pytest.raises(ValidationError): + contracts.BackendOperationEffectsModel.model_validate({**evidence(), **changes}) + + +@pytest.mark.parametrize( + "scope", + [ + {"kind": "resources", "addresses": ["node.vm1"]}, + {"kind": "resources", "independence": artifact()}, + {"kind": "target-run", "addresses": ["node.vm1"]}, + ], +) +def test_narrow_scope_requires_an_admitted_independence_witness(scope): + raw = request_payload() + raw["binding"]["effect_scope"] = scope + with pytest.raises(ValidationError): + contracts.BackendOperationRequestModel.model_validate(raw) + + +def test_residual_scope_cannot_escape_admitted_resource_boundary(): + raw = request_payload() + raw["binding"]["effect_scope"] = { + "kind": "resources", + "addresses": ["node.vm2"], + "independence": artifact(), + } + op = contracts.BackendOperationRequestModel.model_validate(raw) + result = response(outcome(), operation=op) + with pytest.raises(ValueError, match="scope"): + contracts.validate_backend_operation_response(op, result) + + +@pytest.mark.parametrize( + "field,value", + [("backend_id", "other"), ("supported_operation_kinds", ["evaluation"]), ("revision", "sha256:" + "d" * 64)], +) +def test_wrong_capability_identity_kind_and_revision_prevent_admission(field, value): + raw = capabilities().model_dump() + raw[field] = value + foreign = contracts.BackendOperationCapabilitiesModel.model_validate(raw) + with pytest.raises(ValueError): + contracts.require_backend_operation_admission(request(), foreign, admission()) + + +def test_non_admission_message_cannot_supply_willingness(): + with pytest.raises(ValueError, match="admission"): + contracts.require_backend_operation_admission(request(), capabilities(), response(outcome())) + + +@pytest.mark.parametrize( + "kind,disposition,reason", + [ + ("admission", "willing", "context-refused"), + ("admission", "refused", None), + ("acknowledgement", "accepted", "context-refused"), + ("acknowledgement", "refused", None), + ], +) +def test_refusal_reasons_are_required_only_on_refusal(kind, disposition, reason): + raw = {"kind": kind, "disposition": disposition, "reason": reason} + if kind == "admission": + raw["capability_digest"] = "sha256:" + "c" * 64 + with pytest.raises(ValidationError): + response(raw) + + +def test_failure_requires_known_non_satisfaction(): + with pytest.raises(ValidationError, match="non-satisfaction"): + response(outcome("failed")) + failed = response(outcome("failed", satisfaction="unsatisfied", release_gates_satisfied=False)) + contracts.validate_backend_operation_response(request(), failed) + + +def test_control_requires_original_binding_commitment_and_matching_action(): + ctl = control() + report = response( + { + "kind": "reconciliation", + "control_id": ctl.control_id, + "control_digest": contracts.backend_operation_control_digest(ctl), + "effects": evidence(), + } + ) + with pytest.raises(ValueError, match="action"): + contracts.validate_backend_operation_response(request(), report, control=ctl) + with pytest.raises(ValueError, match="control"): + contracts.validate_backend_operation_response(request(), report) + raw = ctl.model_dump() + raw["request_digest"] = "sha256:" + "f" * 64 + other = contracts.BackendOperationControlModel.model_validate(raw) + with pytest.raises(ValueError, match="commitment"): + contracts.validate_backend_operation_response(request(), report, control=other) + + +def test_transcript_rejects_changed_control_and_unordered_or_unacknowledged_records(): + ctl = control() + raw = ctl.model_dump() + raw["budget"]["remaining_ms"] = 800 + changed = contracts.BackendOperationControlModel.model_validate(raw) + with pytest.raises(ValueError, match="control"): + contracts.validate_backend_operation_history(request(), [], controls=[ctl, changed]) + with pytest.raises(ValueError, match="acknowledgement"): + contracts.validate_backend_operation_history(request(), [response(outcome())]) + ack = response({"kind": "acknowledgement", "disposition": "accepted"}, 2) + with pytest.raises(ValueError, match="unordered"): + contracts.validate_backend_operation_history(request(), [ack, admission()]) + with pytest.raises(ValueError, match="twice"): + contracts.validate_backend_operation_history(request(), [ack, response(ack.message, 3)]) + + +@pytest.mark.parametrize("field", ["responses", "controls"]) +def test_transcript_size_is_bounded_before_traversal(field): + with pytest.raises(ValueError, match="bound"): + contracts.validate_backend_operation_history( + request(), + [admission()] * (1025 if field == "responses" else 0), + controls=[control()] * (257 if field == "controls" else 0), + ) + + +def test_protocol_installation_checks_do_not_invoke_provider(): + class Provider: + def operation_capabilities(self): + raise AssertionError("shape checking must not invoke the provider") + + def check_operation(self, request): + raise AssertionError("shape checking must not invoke the provider") + + start_operation = check_operation + observe_operation = check_operation + cancel_operation = check_operation + reconcile_operation = check_operation + + provider = Provider() + assert require_operation_provider(provider, BACKEND_OPERATION_CONTRACT_IDS) is provider + with pytest.raises(ValueError, match="declared"): + require_operation_provider(provider, ["backend-manifest-v2"]) + provider.cancel_operation = lambda: None + with pytest.raises(ValueError, match="call shape"): + require_operation_provider(provider, BACKEND_OPERATION_CONTRACT_IDS) + + +def test_request_is_frozen_and_duplicate_requirements_are_rejected(): + op = request() + with pytest.raises(ValidationError): + op.binding.worker_id = "replacement" + raw = request_payload() + raw["required_guarantees"] *= 2 + with pytest.raises(ValidationError, match="unique"): + contracts.BackendOperationRequestModel.model_validate(raw) diff --git a/specs/formal/runtime-contracts/backend-operation-supervision.md b/specs/formal/runtime-contracts/backend-operation-supervision.md new file mode 100644 index 000000000..228d4e771 --- /dev/null +++ b/specs/formal/runtime-contracts/backend-operation-supervision.md @@ -0,0 +1,234 @@ +# Backend operation and supervision contracts + +Status: published draft contracts, issue #1360, API-402. Classification: FM3. +The [supervision semantics](../runtime-control-plane/supervision.md) and +[ADR-113](../../../docs/decisions/adrs/adr-113-reusable-execution-machinery.md) +own the execution design. This publication supplies portable messages and +validation obligations. It does not implement the runtime dispatch, claim, +supervision, store, or physical fencing mechanisms described by that design. + +## 1. Authority and contract family + +RAE admits authored work and drives one backend invocation through the public +`raes_backend_protocols.operation_supervision.BackendOperationProvider` protocol. +The backend performs concrete work and supplies evidence. RAE retains scenario +ordering, authorization, workflow/time/trial policy, retries, trusted snapshots, +result admission, terminal publication and operational audit. A backend needs +no second scenario interpreter. Schema validity proves none of these duties. + +The additive `operation-supervision` backend profile requires the existing +backend manifest plus four schemas under `contracts/schemas/control-plane/`: + +| Contract | Direction and purpose | +| --- | --- | +| `backend-operation-request-v1` | RAE to backend: exact admitted command, requirements, context and apparatus budget. | +| `backend-operation-capabilities-v1` | Backend to RAE: installed versioned declaration for operation kinds and guarantees. | +| `backend-operation-control-v1` | Authorized supervisor to backend via RAE: cancel, observe or reconcile the original invocation. | +| `backend-operation-response-v1` | Backend to RAE: discriminated admission, acknowledgement, progress, control disposition, outcome or reconciliation evidence. | + +Wire `schema_version` values use `/v1`; publication IDs use `-v1`. All objects +are closed. Unknown versions, fields, enum values or required guarantees fail +closed. Profile membership is contract support, not backend conformance or a +P0–P3 runtime guarantee. Existing backends do not opt in automatically. + +## 2. Binding, command and authorization + +Every request and response preserves the original `OperationAdmissionContext`: +actor, authorization scope, target/run, operation kind, request commitment and +parent operation. A binding additionally identifies backend, deployment, +operation, invocation, authored attempt, authorized worker, owner generation, +execution generation, baseline snapshot revision and conflicting-effect scope. +These identifiers have distinct meanings and must not be substituted for one +another. An engine delivery attempt is not an authored attempt or invocation. +An ordinary operation needs no experiment, participant or trial wrapper. + +`command` is a digest-bound reference to the admitted native command/plan. +`requirement_refs` identify exact admitted requirement artifacts, including any +selected workflow, time, trial, effect or release constraints. The command's +owning contract retains its resolved policy and provenance. These references +are not a free-form policy language: the runtime must resolve and validate +their native types, expected kind and immutable contents before dispatch. +Unresolved, unsupported or incompatible references prevent invocation. No +raw credentials, executable paths, native job locators or arbitrary metadata +are carried here. References and digests grant neither access nor permission. + +The request digest is SHA-256 over RFC 8785 canonical JSON of the complete +validated request, including materialized defaults and null values. Preserve +array order. `backend_operation_request_digest()` is the reference encoder; +the original admission commitment remains a distinct value. Every response +echoes both the binding and this digest. Capability and control digests follow +the same rule. A changed requirement, budget, scope or command is a different +request, not a transport retry of an existing invocation. + +Before `start_operation`, the current authenticated RAE authority must validate +the command, current scope authorization, budget, capability and willingness, +then consume the one-use invocation claim specified by ADR-113. The first +confirmed consumer may invoke. A lost claim acknowledgement grants no usable +permission. No database transaction spans the backend call. Duplicate delivery +observes the same invocation and cannot cause another effect or authored +attempt. Credential-sensitive retries retain their incumbent ephemeral proof +requirements; a durable public digest cannot replace that proof after restart. + +Owner generation, execution generation and baseline revision fence **state +publication**. They cannot prove cessation or fence a remote effect. A backend +external fence requires separate scoped evidence under its admitted guarantee. +Replacing an owner or worker retains outstanding reservations and quarantine. + +Effect exclusion defaults to the entire target/run. A `resources` scope requires +bounded canonical addresses and a digest-bound independence artifact that the +runtime validates. Residual addresses must stay within this admitted scope. +Unrepresented or out-of-scope effects invalidate the report and require +indeterminacy, not silent truncation. An external fence reference is evidence +to validate against this exact scope, not a self-authenticating token. + +## 3. Capability, willingness and bounded calls + +`operation_capabilities()` returns an installed provider declaration with a +backend identity, revision, operation kinds and selectable guarantees: + +| Guarantee | Required meaning when selected | +| --- | --- | +| `cancellation` | Accept the scoped cancellation protocol and explicitly report its disposition. It does not promise successful cessation. | +| `effect-observation` | Provide bounded, correlated effect observations during execution/reconciliation, including honest uncertainty. | +| `cessation-evidence` | Establish scoped cessation evidence required by the admitted operation, or refuse that operation before effects. | +| `partial-effects` | Represent known partial effects with a native residual snapshot and complete residual scope. | +| `external-fencing` | Establish the admitted backend fence for the exact external effect scope; local CAS is insufficient. | + +The exact required strength, durations, scope and native evidence are in the +admitted command/requirement artifacts. A guarantee name alone never proves +their satisfaction. General continuation/checkpoint support is absent from v1; +a request requiring an unsupported continuation guarantee must be refused. + +`require_operation_provider()` checks declared contract IDs and installed call +shapes without invoking the provider. `check_operation(request)` returns an +`admission` response bound to the complete request and the canonical capability +digest. `require_backend_operation_admission()` requires matching backend/kind, +all requested guarantees, the exact capability digest and current willingness. +This pure validator does not authorize effects. The runtime must recheck after +queueing and immediately before consuming the invocation claim. A previous +willing answer is not an irrevocable promise. No missing guarantee becomes +best effort, a shorter duration, a replacement backend or an implicit retry. + +Each request/control carries a positive finite integral apparatus budget in +milliseconds, its immutable origin ID, a valid RFC 3339 origin instant and the +remaining allowance. Integers are strict and bounded to the interoperable JSON +integer range. The remaining allowance cannot exceed the original limit. +It is a ceiling, not a restartable timer: the runtime tracks elapsed apparatus +monotonic time and every nested call consumes the enclosing remaining budget. +Duplicates never renew it. Restart requires clock-continuity/elapsed evidence; +otherwise the remaining time is unknown and invocation is refused. UTC origin +evidence does not make a portable monotonic deadline. Authored semantic clock, +domain and segment semantics remain in their native contracts. + +RAE must independently bound admission, execution, observation/interruption, +store readback/commit and drain. This backend carrier transmits the remaining +budget for the particular backend stage; it does not implement those timers. +Effect and control calls require independent bounded capacity. If that cannot +be provided, the composition cannot advertise the stronger supervision claim. +No unbounded callback iterator is part of this protocol: each method returns +one bounded response. Transport loss, method exceptions, malformed results and +timeout are uncertainty; native exception text must not become public records. + +## 4. Response meanings and ordering + +| Message | Meaning | +| --- | --- | +| `admission` | Current willingness or contextual refusal, referencing the exact capability declaration. | +| `acknowledgement` | This invocation was accepted, or refused before it could produce effects. Acceptance is not success. | +| `progress` | Bounded operational phase/evidence; it neither extends a budget nor proves a result. | +| `control` | A supervisory request was recorded, accepted, refused, unsupported, or arrived after terminal evidence. None of these establishes cessation. | +| `outcome` | Proposed existing terminal state with independent effect knowledge, cessation, satisfaction, release and cancellation claims. RAE must validate before publishing. | +| `reconciliation` | Bounded observation for a correlated observe/reconcile request; it does not invoke, replay or rewrite a terminal parent. | + +Backend sequence numbers are positive and ordered within one exact invocation +binding. They order reports, not the runtime's atomic commits. The identical +sequence/content may be retransmitted; different content at the same sequence +or a previously unseen lower sequence is invalid. Gaps are permitted, since +progress may be coalesced before publication; acknowledged controls must remain +retrievable and cannot be silently discarded. Retain deduplication for as long +as the admitted effect/recovery window requires. Sequence exhaustion must close +admission; wrapping a counter cannot create a new invocation. + +`validate_backend_operation_history()` checks bounded transcripts of at most +1024 response records and 256 controls. Progress/outcome requires an accepted +acknowledgement. Refused acknowledgement closes that invocation. A proposed +terminal report is immutable within the transcript; later control/reconciliation +records may add evidence, but cannot replace it. Transcript validation is a +conformance check, not a scheduler, persistence implementation or proof that +a backend deduplicates its physical effects. + +Each control request binds its own actor, authorization scope, unique control +ID and canonical digest to the original operation. Runtime authorization must +independently authenticate that supervisor and check the precise subject/scope; +fields asserted by a caller are not identity proof. Responses to control and +reconciliation echo its ID and digest. Same control ID with changed content is +invalid. A repeated cancellation cannot multiply interrupts or restart budgets. +Status retrieval may return previously recorded progress/outcomes unchanged; +the runtime still authorizes each disclosure. + +## 5. Effects, settlement and uncertainty + +Effect knowledge is `absent`, `complete`, `partial` or `unknown`, independently +of `cessation_established`. Known effect/cessation/fence claims require scoped +content-bound evidence references. Known partial effects require both a native +`runtime-snapshot-v1` residual state reference and its complete changed-address +scope. Unknown remainder may preserve a known residual prefix, but must stay +`unknown`. Absence cannot include residual changes. Complete effects may be a +validated no-op. Evidence references must be resolved, authenticated, bounded, +scope-checked and validated; presence of a reference does not establish truth. + +| Proposed state | Required claims, in addition to native runtime validation | +| --- | --- | +| `succeeded` | Known nonpartial effects, cessation, all admitted requirements satisfied, result reference and final release gates satisfied. | +| `failed` | Known effects, cessation and established non-satisfaction. Known partial effects remain represented. | +| `cancelled` | Known effects, cessation and established cancellation contract. Known partial residuals remain represented; rollback is not implied. | +| `indeterminate` | Required for unknown effects or unproved cessation, and available for other unsettled contract/commit facts. Preserve trusted state and exclusion. | + +The proposed state uses the existing `OperationState` vocabulary. There is no +new PARTIAL, REFUSED, CANCELLING or TIMED_OUT state. The backend proposal cannot +override native result validation, trusted-predecessor isolation, requirement +satisfaction or final release validation. RAE alone commits the permitted +snapshot, terminal record and actor-bound audit atomically with revision CAS. +An effect can be known complete while a release gate still prevents success. +Generic failure or a predecessor snapshot cannot prove no external effect. + +If cancellation is accepted and valid completion wins the runtime commit, +success remains possible. Cancellation requires evidence, not the accepted +request. A late completion after cancellation/indeterminacy may supply linked +resolution evidence, but cannot rewrite the parent. Pre-dispatch contextual +refusal after runtime claim becomes the existing cancellation/refusal path; +before claim it remains denial audit. A refusal after possible effects is not +an absent-effect acknowledgement: report classified/unknown effects instead. + +Backend effect uncertainty and store commit uncertainty remain separate. For a +lost store acknowledgement, read back the complete atomic cut, poison readiness +while unknown, and do not publish a second terminal record. A backend outcome +cannot resolve store uncertainty. Reconciliation observes without replay; +administrative acceptance, compensation, cleanup and new trial allocation keep +their separate owning contracts. Unknown cessation retains quarantine even +after a terminal indeterminate record or owner loss. + +## 6. Validation and examples + +Consumers must run structural JSON Schema validation **and** the semantic +invariants declared with `x-raes-semantic-profile`/`x-raes-invariants`. +Annotations document the mandatory rules; a generic JSON Schema validator does +not execute Python validators or validate backend truth. The Python facade +exports the four models, nested message models, digest helpers, admission, +response and transcript validators. Cross-message checks require the trusted +request and, for a control result, its independently admitted control request. + +The routed fixtures under `contracts/fixtures/control-plane/backend-operation-*` +are executable contract examples. Matching filename prefixes form exchanges: +`accepted`, `refused`, `cancel-race`, `partial-cancel`, `duplicate`, `uncertain`. +They demonstrate every message kind and preserve uncertain parents when new +reconciliation evidence arrives. The `provider` capability fixture is a +synthetic declaration, not a claim about an installed backend. Artifact digests +are synthetic identity witnesses; these examples prove carrier and relationship +validation, not actual artifact contents, physical effects or liveness. + +`test_issue_1360_backend_operations.py` executes the corpus, rejects foreign +bindings and changed commitments, exercises cancellation races/duplicates and +checks honest outcome boundaries. The existing #1348 abstract model and lifecycle +tests retain their narrower claims. No fixture establishes runtime interruption, +distributed coordination, recovery truth, physical containment or P3 support. diff --git a/tools/policy/requirement_order.yaml b/tools/policy/requirement_order.yaml index 80f7d3917..434f1f15f 100644 --- a/tools/policy/requirement_order.yaml +++ b/tools/policy/requirement_order.yaml @@ -15,6 +15,7 @@ phases: - ^DSL- - id: runtime-control-plane requirements: + - API-402 - API-404 - id: api400-core requirements: From 8a158cb1b1d3a5695409fcdfdf14d1a0607d597b Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Fri, 25 Sep 2026 04:27:45 +0200 Subject: [PATCH 2/7] fix: preserve backend opt-in and refresh execution evidence --- docs/requirements/API-402/requirement.md | 3 +- .../analysis-v45.json | 154 ++++ .../bundles/retest-v45.json | 122 +++ .../execution-snapshot-v45.json | 652 ++++++++++++++++ .../formal-semantic-validation/index.md | 13 +- .../specification-coverage/analysis-v45.json | 101 +++ ...specification-coverage-issue-1360-v45.json | 10 + .../execution-snapshot-v45.json | 700 ++++++++++++++++++ docs/research/specification-coverage/index.md | 11 +- .../packages/raes_backend_stubs/manifest.py | 2 + .../python/tests/test_backend_manifest.py | 4 + .../tests/test_formal_semantic_validation.py | 5 +- .../test_issue_1360_backend_operations.py | 7 + .../test_issue_989_versioned_evidence.py | 6 +- .../tests/test_specification_coverage.py | 2 +- tools/check_specification_coverage.py | 5 +- tools/formal_semantic_validation/_baseline.py | 3 +- tools/formal_semantic_validation/_loading.py | 5 +- .../_release_revisions.py | 3 +- tools/formal_semantic_validation/_releases.py | 7 +- tools/formal_semantic_validation/_retest.py | 2 +- 21 files changed, 1798 insertions(+), 19 deletions(-) create mode 100644 docs/research/formal-semantic-validation/analysis-v45.json create mode 100644 docs/research/formal-semantic-validation/bundles/retest-v45.json create mode 100644 docs/research/formal-semantic-validation/execution-snapshot-v45.json create mode 100644 docs/research/specification-coverage/analysis-v45.json create mode 100644 docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v45.json create mode 100644 docs/research/specification-coverage/execution-snapshot-v45.json diff --git a/docs/requirements/API-402/requirement.md b/docs/requirements/API-402/requirement.md index 4444be226..596efb9ec 100644 --- a/docs/requirements/API-402/requirement.md +++ b/docs/requirements/API-402/requirement.md @@ -6,7 +6,7 @@ type: FUNCTIONAL priority: MUST wave: 1 created_at: 2026-04-03T05:40:04.988670Z -updated_at: 2026-09-24T00:00:00.000000Z +updated_at: 2026-09-25T00:00:00.000000Z --- # API-402 — Plain-Data Execution, Result, And History Contracts @@ -56,3 +56,4 @@ Current state: implemented. Portable live-execution contracts are required so in - DOCUMENTS → DOCUMENTATION `docs/decisions/issue-1360-backend-operation-contracts-preflight.md` (Contract publication guardrails) - IMPLEMENTS → CONFIG `tools/policy/requirement_order.yaml` (Existing live-contract requirement admitted through control-plane governance) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/_backend_operation_exports.py` (Public operation contract facade exports) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_backend_stubs/manifest.py` (Keep operation supervision opt-in; legacy stub does not advertise an unimplemented provider) diff --git a/docs/research/formal-semantic-validation/analysis-v45.json b/docs/research/formal-semantic-validation/analysis-v45.json new file mode 100644 index 000000000..854ae7c19 --- /dev/null +++ b/docs/research/formal-semantic-validation/analysis-v45.json @@ -0,0 +1,154 @@ +{ + "analysis_id": "issue-1360-analysis-v45", + "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-v45.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-1360-execution-v45", + "generated_at": "2026-09-25", + "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." + ], + "plain_language_outcome": "The retained controls replay against the backend operation contract publication. The original claim limits and unsupported classes remain unchanged; this offline corpus does not establish live backend supervision or recovery.", + "protocol_revision": "2.0.0" +} diff --git a/docs/research/formal-semantic-validation/bundles/retest-v45.json b/docs/research/formal-semantic-validation/bundles/retest-v45.json new file mode 100644 index 000000000..3dac64c2b --- /dev/null +++ b/docs/research/formal-semantic-validation/bundles/retest-v45.json @@ -0,0 +1,122 @@ +{ + "analysis_path": "docs/research/formal-semantic-validation/analysis-v45.json", + "analysis_sha256": "57b63be83b10ea89af9421f6a35eb22065631e9ef513bceb6de4fae963e593ee", + "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": "46.0.0", + "snapshot_path": "docs/research/formal-semantic-validation/execution-snapshot-v45.json", + "snapshot_sha256": "edef1beb5d11a4d4443b5a3852df1278641d5158dd1ffd3cb78231d9c06a14c3" +} diff --git a/docs/research/formal-semantic-validation/execution-snapshot-v45.json b/docs/research/formal-semantic-validation/execution-snapshot-v45.json new file mode 100644 index 000000000..e1d639e40 --- /dev/null +++ b/docs/research/formal-semantic-validation/execution-snapshot-v45.json @@ -0,0 +1,652 @@ +{ + "baseline": { + "execution_id": "issue-218-execution-v44", + "release_path": "docs/research/formal-semantic-validation/bundles/retest-v44.json", + "release_revision": "45.0.0", + "release_sha256": "64e562329eef767b3d75b5a0457aa0a36dd36da2d8eacec6880aa4dfdf1b9c3b" + }, + "captured_at": "2026-09-25T02:26:58.817893+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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "limitations": [ + "The witness ends at compiled output." + ], + "replayable": true, + "result_digest": "11264a648a949917c0e84a2a1e5d116139a35e6cb941844735a422df95141d6c", + "source_digest": null + }, + { + "actual_outcome": "distinguishable", + "analysis_profile": null, + "case_id": "compile-non-vacuity-control", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/determinism-a.sdl.yaml", + "docs/research/formal-semantic-validation/corpus/determinism-b.sdl.yaml" + ], + "execution_id": "issue-1360-execution-v45", + "limitations": [ + "Distinct digests are a non-vacuity control, not semantic non-equivalence proof." + ], + "replayable": true, + "result_digest": "72c1ee8c7bbc1f970216fa232b3d4ae917bcb003bd823439bbac8a5db94214e2", + "source_digest": null + }, + { + "actual_outcome": "unsupported", + "analysis_profile": null, + "case_id": "necessity-witness-request", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/decisions/issue-168-formal-semantic-validation-reachability-preflight.md" + ], + "execution_id": "issue-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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-1360-execution-v45", + "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": "99f7667388056bd8b98bb553f270a6f954882f4b", + "source_state": { + "base_revision": "99f7667388056bd8b98bb553f270a6f954882f4b", + "checkout_state": "modified", + "implementation_digest": "2ad3010ff26ef5d14e206cc2b51573a17e684cd7fef661e062b0a9690da080fa", + "profile": "python-reference-source/v2" + }, + "versions": { + "python": "3.14.4", + "raes": "5.0.0", + "z3_engine": "4.16.0", + "z3_solver": "4.16.0.0" + } +} diff --git a/docs/research/formal-semantic-validation/index.md b/docs/research/formal-semantic-validation/index.md index a2fbe8266..0a30aa5ed 100644 --- a/docs/research/formal-semantic-validation/index.md +++ b/docs/research/formal-semantic-validation/index.md @@ -336,7 +336,7 @@ outcomes and claim limits, recording the positive successor's changed result digest; the dangling-reference diagnostic remains identical. It establishes no autonomy threshold, authority grant, or realized attribution. -Current validation requires explicit release 45.0.0, rejects unsupported future +Current validation requires explicit release 46.0.0, rejects unsupported future or duplicate revisions, and never accepts an old/new output-digest pair as a substitute for replay. Historical releases (including the issue-826 supplement) undergo pin, shape, control, and internal-join checks without executing current @@ -440,10 +440,19 @@ refactoring in [`execution-snapshot-v43.json`](execution-snapshot-v43.json) and [`analysis-v43.json`](analysis-v43.json). Fresh replay retains the same bounded outcomes and claim limits; it does not add a new semantic claim. -Current release 45.0.0 records the merged participant identity and local +Release 45.0.0 records the merged participant identity and local outcome implementation in [`execution-snapshot-v44.json`](execution-snapshot-v44.json) and [`analysis-v44.json`](analysis-v44.json). The two pre-merge issue #218 captures retain their observations and source identities in v42 and v43; only their release numbers, paths, and corresponding digest joins were reconciled with the independently published issue #1338 capture. The combined capture uses the issue #1338 baseline and preserves the same bounded claim limits. + +## Backend operation contract source replay + +Release 46.0.0 binds issue #1360 to fresh source evidence in +[`execution-snapshot-v45.json`](execution-snapshot-v45.json) and +[`analysis-v45.json`](analysis-v45.json). The retained offline cases preserve +their classifications and claim limits. Backend supervision contracts have +dedicated contract tests; this capture makes no live backend recovery claim. +Earlier published captures retain their exact bytes. diff --git a/docs/research/specification-coverage/analysis-v45.json b/docs/research/specification-coverage/analysis-v45.json new file mode 100644 index 000000000..060936e1b --- /dev/null +++ b/docs/research/specification-coverage/analysis-v45.json @@ -0,0 +1,101 @@ +{ + "analysis_id": "issue-1360-specification-coverage-v45", + "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-v45.json", + "docs/research/specification-coverage/analysis-v45.json" + ], + "falsification_protocol": "docs/research/specification-coverage/protocol-v1.json", + "objective_fail_criteria": "A load-bearing concept is missing or lossy, an applicable stage fails, or backend vocabulary is required in core SDL while the result claims success.", + "objective_pass_criteria": "Every load-bearing concept passes at every owning stage, backend-specific mechanics stay outside core SDL, and no requested concept is silently lost.", + "statement": "RAES provides a standardized configurable portable specification surface for the preregistered representative cyber-agent evaluation environment requirements without backend vocabulary in core SDL.", + "threats_to_validity": [ + "The representative corpus contains four source strata and sixteen atomic concepts rather than every cyber-range requirement.", + "The reference processor and repository fixtures are not independent backend implementations.", + "No live range, simulator federation, or participant execution was part of this offline specification-coverage test." + ] + }, + "classification_counts": { + "deliberately-backend-specific": 1, + "directly-expressible": 10, + "missing": 3, + "profile-or-manifest-constraint": 2 + }, + "evidence_status": "partial", + "execution_status": "complete", + "generated_at": "2026-09-25", + "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." + ], + "load_bearing_results": { + "failed": 0, + "missing": 0, + "passed": 10, + "total": 10 + }, + "plain_language_outcome": "The retained specification matrix replays explicit participant affiliations, objective ownership, and assignment using abstract action contracts. Classification counts and untested concepts are unchanged; no execution authority or live backend behavior is inferred.", + "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": "issue-1360-specification-coverage-v45", + "snapshot_sha256": "60ec6e1314a7f06c83bba7005b591577a11df7bfb06c3d9d9b7ed4ae88216e39" +} diff --git a/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v45.json b/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v45.json new file mode 100644 index 000000000..d9e28bf6f --- /dev/null +++ b/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v45.json @@ -0,0 +1,10 @@ +{ + "analysis_path": "docs/research/specification-coverage/analysis-v45.json", + "analysis_sha256": "4673596f03401f352aae6d86fce95181e2c5a9c301985dd91638c84befa24b56", + "bundle_id": "raes-standardized-specification-coverage", + "protocol_path": "docs/research/specification-coverage/protocol-v1.json", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "revision": "45.0.0", + "snapshot_path": "docs/research/specification-coverage/execution-snapshot-v45.json", + "snapshot_sha256": "c7695251b09acf1ab3e0536d228c65030119527126aa1f7b6b3a171807a01f9a" +} diff --git a/docs/research/specification-coverage/execution-snapshot-v45.json b/docs/research/specification-coverage/execution-snapshot-v45.json new file mode 100644 index 000000000..fb2992d2a --- /dev/null +++ b/docs/research/specification-coverage/execution-snapshot-v45.json @@ -0,0 +1,700 @@ +{ + "artifacts": [ + { + "artifact_id": "enterprise-participant-sdl", + "kind": "sdl", + "path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "sha256": "f7a8897beec243e188ee081975006fad32725f469f267db6e75a1e1cf5727032", + "validator": "raes parse, semantic, instantiation/admission, and compiler pipeline" + }, + { + "artifact_id": "port-range-sdl", + "kind": "sdl", + "path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "sha256": "0d5497ec946b863e6985284ec487dde7d7f6bf710a985be51401ac0e5e79dc4f", + "validator": "raes parse, semantic, instantiation/admission, and compiler pipeline" + }, + { + "artifact_id": "experiment-task-contract", + "kind": "experiment-task", + "path": "contracts/fixtures/experiment-core/experiment-task-v1/valid/reference.json", + "sha256": "f3edf713ac6af26bad609136851c6dd434bfb87ce919a2d8c4414c1035deeafc", + "validator": "raes_contracts.contracts.ExperimentTaskModel" + }, + { + "artifact_id": "apparatus-context-contract", + "kind": "experiment-apparatus-context", + "path": "contracts/fixtures/experiment-core/experiment-apparatus-context-v1/valid/reference.json", + "sha256": "e6fa559c5e961f0aab448d0f70dead24aa74fa8ba5f20e1b72f88e11473c9299", + "validator": "raes_contracts.contracts.ExperimentApparatusContextModel" + }, + { + "artifact_id": "backend-profile", + "kind": "backend-profile", + "path": "contracts/profiles/backend/orchestration-capable.json", + "sha256": "f70b8505a5c0055416db86c533e2e5bf08b11e5a514f076223b6d6c36215a092", + "validator": "raes_contracts.backend_profiles.BackendProfileModel" + }, + { + "artifact_id": "known-limitations", + "kind": "documentation", + "path": "docs/explain/sdl/limitations.md", + "sha256": "489eeab3ce682627682311581eb98af9abb9ff42a437145af266eefb71dc7fc4", + "validator": "documentation evidence only" + } + ], + "baseline": { + "release_revision": "1.1.0", + "release_sha256": "4020a1d56c7fe2831cec59ea64a12bbda9d38ccd94f93b916dd90f1a28f17fcb" + }, + "captured_at": "2026-09-25T02:26:58.817893+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": "7531f0ffb125a928a8cd9c8b57443aa175c3dc7ea921f0b51eab6377f2443459", + "path": "implementations/python/packages/raes_contracts", + "surface_id": "contract-models" + }, + { + "content_sha256": "4999b8adf294f364a758bc9cf78816d5da9eae1c263ae678eabe4d0e2c82dec6", + "path": "implementations/python/packages/raes_processor", + "surface_id": "processor-pipeline" + }, + { + "content_sha256": "9ecd780448b054693503bab246120a1a2bb49a43016d0b9c27c5284ba609833f", + "path": "implementations/python/packages/raes", + "surface_id": "sdl-pipeline" + } + ], + "limitations": [ + "The execution validates the pinned reference implementation and published contracts, not an independent backend.", + "Repository-owned examples are exact execution artifacts but are not themselves the literature-derived request corpus; the protocol's requests and concepts are.", + "No live range, participant, simulator federation, or provider provisioning engine was executed.", + "Missing concepts remain frozen in this snapshot and require separately scoped product work before a later rerun.", + "This capture replays the retained protocol after EXP-732 run, apparatus, measurement-channel, and augmentation-producer provenance validation; it adds no independent backend or universal provenance assurance claim.", + "Materialization attestation is covered by its dedicated regression suite, not a new claim in this preregistered matrix.", + "This capture refreshes the corrected runtime limitations prose for issue #959; the protocol, coverage classifications and implementation source are unchanged.", + "This capture replays open-by-default augmentation scope integrated with the EXP-731 evidence refinements after composition type refinement; it does not evaluate native backend scope enforcement or broaden the preregistered coverage claims.", + "This capture replays the retained protocol after merging ACT-612 participant relationships with open-by-default augmentation scope; it adds no claim of realized participant relationships or native backend scope enforcement.", + "This capture replays issue #1299 partial listener descriptions on the integrated source state; endpoint completeness and backend admission remain outside this protocol's claims.", + "This capture also binds authoring-adapter semantic conformance to the integrated source; adapter transport behavior remains outside this protocol's claims.", + "Reviewed OCI mirror and pre-seed admission is covered by its own regression suites and the development artifact policy gate, not a new claim in this preregistered matrix.", + "This capture binds issue #1297 service-manager identity, native-name, and explicitly selected systemd-state contract changes to the integrated source. It exercises no live service manager and adds no backend-execution claim.", + "This capture replays the retained specification-coverage protocol after API-404 startup reconciliation added an operational recovery-observation contract. It does not evaluate crash recovery, classify provider effects, or broaden EXP-715 experiment-observation claims.", + "This capture binds API-404 single-owner store admission and immutable target/run scope to the integrated source. The retained offline protocol does not exercise process leases, SQLite lifecycle ordering, or crash recovery.", + "This capture binds issue #1015 deterministic mixed and staged trial admission to the integrated source. The retained offline language corpus does not execute mixed runtimes, phase transitions, backend handoff, or scheduler-driven realization.", + "This replay binds issue #1186 offline control-plane maintenance, readiness, and bounded audit code to the integrated source. The retained language corpus does not execute store recovery, HTTP health behavior, or audit redaction.", + "Issue #1187 control-plane crash/profile conformance and HTTP security changes are covered by their dedicated regression suite, not promoted to new claims by this retained corpus.", + "Issue #1189 control-plane profile declarations are covered by their dedicated runtime suite, not promoted to new claims by the retained language corpus.", + "Issue #1016 mixed-runtime coordination is covered by its dedicated runtime suite. The retained language corpus does not execute mixed providers or establish backend-native realization, multi-controller coordination, IFC, or equivalence.", + "Issue #610's reconciliation demonstration harness is covered by its dedicated processor and CLI suite, not promoted to new claims by the retained language corpus.", + "Participant identity, organization ownership, and participant assignment are separated by issue #1338. This retained offline corpus does not establish participant autonomy, execution authority, live backend fidelity, or causal attribution." + ], + "protocol_revision": "1.0.0", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "raes_revision": "99f7667388056bd8b98bb553f270a6f954882f4b", + "snapshot_id": "issue-1360-specification-coverage-v45", + "snapshot_revision": "45.0.0", + "source_state": { + "base_revision": "99f7667388056bd8b98bb553f270a6f954882f4b", + "checkout_state": "modified", + "implementation_digest": "2ad3010ff26ef5d14e206cc2b51573a17e684cd7fef661e062b0a9690da080fa", + "profile": "python-reference-source/v2" + } +} diff --git a/docs/research/specification-coverage/index.md b/docs/research/specification-coverage/index.md index 04ee1b312..ccb5902a0 100644 --- a/docs/research/specification-coverage/index.md +++ b/docs/research/specification-coverage/index.md @@ -292,7 +292,7 @@ the port scenario. Historical captures and archived example bytes are retained. The matrix classifications and untested concepts are unchanged; no execution authority, successful action, or live backend fidelity is inferred. -Current validation requires release 44.0.0 and rejects duplicate or unsupported +Current validation requires release 45.0.0 and rejects duplicate or unsupported future revisions. It executes current artifacts, requires exact source and package hashes, and checks all passing stage pointers. `source_state` discloses the base Git commit, modified checkout state, and exact implementation digest; @@ -383,3 +383,12 @@ captures retain their observations and source identities in v42 and v43; only their release numbers, paths, and corresponding digest joins were reconciled with the independently published issue #1338 capture. The combined capture uses the issue #1338 baseline and preserves the same bounded claim limits. + +## Backend operation contract source replay + +Release 45.0.0 binds issue #1360 to fresh source evidence in +[`execution-snapshot-v45.json`](execution-snapshot-v45.json) and +[`analysis-v45.json`](analysis-v45.json). The retained offline cases preserve +their classifications and claim limits. Backend supervision contracts have +dedicated contract tests; this capture makes no live backend recovery claim. +Earlier published captures retain their exact bytes. diff --git a/implementations/python/packages/raes_backend_stubs/manifest.py b/implementations/python/packages/raes_backend_stubs/manifest.py index eba60c8fb..e5265ef5f 100644 --- a/implementations/python/packages/raes_backend_stubs/manifest.py +++ b/implementations/python/packages/raes_backend_stubs/manifest.py @@ -47,6 +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.vocabulary import ( ParticipantFeatureSupportLevel, RealizationSupportMode, @@ -54,6 +55,7 @@ ) REFERENCE_BACKEND_SUPPORTED_CONTRACT_VERSIONS = frozenset(BACKEND_SUPPORTED_CONTRACT_IDS) - { + *BACKEND_OPERATION_CONTRACT_IDS, "backend-materialization-attestation-v1", "backend-augmentation-scope-v1", "backend-realization-preparation-v1", diff --git a/implementations/python/tests/test_backend_manifest.py b/implementations/python/tests/test_backend_manifest.py index 915a7b418..780b746a4 100644 --- a/implementations/python/tests/test_backend_manifest.py +++ b/implementations/python/tests/test_backend_manifest.py @@ -51,6 +51,10 @@ for contract_id in BACKEND_SUPPORTED_CONTRACT_IDS if contract_id not in { + "backend-operation-request-v1", + "backend-operation-capabilities-v1", + "backend-operation-control-v1", + "backend-operation-response-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 a026dec57..864544cb6 100644 --- a/implementations/python/tests/test_formal_semantic_validation.py +++ b/implementations/python/tests/test_formal_semantic_validation.py @@ -124,6 +124,7 @@ def test_atomic_release_index_validates_every_historical_bundle() -> None: "43.0.0", "44.0.0", "45.0.0", + "46.0.0", ] assert all(validate_release_bundle(REPO_ROOT, release) == [] for release in releases) @@ -132,10 +133,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"] == "45.0.0" + assert release.manifest["revision"] == "46.0.0" assert protocol["revision"] == "2.0.0" assert corpus["revision"] == "4.0.0" - assert snapshot["baseline"]["release_revision"] == "42.0.0" + assert snapshot["baseline"]["release_revision"] == "45.0.0" assert snapshot["deviations"] == [] assert validate_retest_bundle(REPO_ROOT, release, protocol, corpus, snapshot, analysis) == [] diff --git a/implementations/python/tests/test_issue_1360_backend_operations.py b/implementations/python/tests/test_issue_1360_backend_operations.py index 679e1e958..562e23bb1 100644 --- a/implementations/python/tests/test_issue_1360_backend_operations.py +++ b/implementations/python/tests/test_issue_1360_backend_operations.py @@ -375,3 +375,10 @@ def test_example_corpus_exercises_every_message_and_required_scenario(): ) contracts.validate_backend_operation_history(op, reports, controls=controls) assert kinds == {"admission", "acknowledgement", "progress", "control", "outcome", "reconciliation"} + + +def test_existing_stub_does_not_advertise_operation_supervision(): + from raes_backend_stubs.manifest import create_stub_manifest + from raes_contracts.versions import BACKEND_OPERATION_CONTRACT_IDS + + assert set(BACKEND_OPERATION_CONTRACT_IDS).isdisjoint(create_stub_manifest().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 e74645b01..35199486c 100644 --- a/implementations/python/tests/test_issue_989_versioned_evidence.py +++ b/implementations/python/tests/test_issue_989_versioned_evidence.py @@ -230,7 +230,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"] == "45.0.0" + assert release.manifest["revision"] == "46.0.0" original = _retest.replay_case def changed_result(root, case): @@ -283,7 +283,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"] == "44.0.0" + assert manifest["revision"] == "45.0.0" snapshot = deepcopy(snapshot) artifact = next(a for a in snapshot["artifacts"] if a["artifact_id"] == artifact_id) artifact["sha256"] = old_digest @@ -497,6 +497,7 @@ def test_no_capture_can_be_silently_dropped(monkeypatch, family, removed): "43.0.0", "44.0.0", "45.0.0", + "46.0.0", ] if family == "formal" else [ @@ -545,6 +546,7 @@ def test_no_capture_can_be_silently_dropped(monkeypatch, family, removed): "42.0.0", "43.0.0", "44.0.0", + "45.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 3b774fbd5..8406035dd 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"] == "44.0.0" + assert manifest["revision"] == "45.0.0" def test_historical_failures_name_the_revision_specific_documents() -> None: diff --git a/tools/check_specification_coverage.py b/tools/check_specification_coverage.py index d584d2ed4..10ba95c52 100644 --- a/tools/check_specification_coverage.py +++ b/tools/check_specification_coverage.py @@ -102,7 +102,7 @@ def _load_bundle_index(repo_root: Path) -> list[tuple[str, dict[str, object]]]: max_bytes=_MAX_FILE_BYTES, ) current_path = current_release_path(records) - if dict(records)[current_path].get("revision") != "44.0.0" or {record.get("revision") for _, record in records} != { + if dict(records)[current_path].get("revision") != "45.0.0" or {record.get("revision") for _, record in records} != { "1.0.0", "1.1.0", "2.0.0", @@ -148,8 +148,9 @@ def _load_bundle_index(repo_root: Path) -> list[tuple[str, dict[str, object]]]: "42.0.0", "43.0.0", "44.0.0", + "45.0.0", }: - raise ValueError("coverage evidence requires the explicit current 44.0.0 release and supported history") + raise ValueError("coverage evidence requires the explicit current 45.0.0 release and supported history") return records diff --git a/tools/formal_semantic_validation/_baseline.py b/tools/formal_semantic_validation/_baseline.py index 22ecd31ed..35c22fa96 100644 --- a/tools/formal_semantic_validation/_baseline.py +++ b/tools/formal_semantic_validation/_baseline.py @@ -74,6 +74,7 @@ "42.0.0", "43.0.0", "44.0.0", + "45.0.0", } ) _V3_CORPUS_REVISIONS = frozenset( @@ -222,7 +223,7 @@ def _selected_baseline_manifest( if baseline_revision in _V2_REVISIONS else "docs/research/formal-semantic-validation/protocol-v1.json" ) - if baseline_revision == "42.0.0": + if baseline_revision in {"42.0.0", "45.0.0"}: expected_corpus_path = "docs/research/formal-semantic-validation/corpus/manifest-v4.json" elif baseline_revision in _V3_CORPUS_REVISIONS: expected_corpus_path = "docs/research/formal-semantic-validation/corpus/manifest-v3.json" diff --git a/tools/formal_semantic_validation/_loading.py b/tools/formal_semantic_validation/_loading.py index c05945aac..873dcff8e 100644 --- a/tools/formal_semantic_validation/_loading.py +++ b/tools/formal_semantic_validation/_loading.py @@ -75,6 +75,7 @@ def load_release_bundles(repo_root: Path = REPO_ROOT) -> list[EvidenceRelease]: "43.0.0", "44.0.0", "45.0.0", + "46.0.0", }: raise ValueError("formal evidence requires every supported historical and current release") releases: list[EvidenceRelease] = [] @@ -121,6 +122,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") != "45.0.0" or release.protocol.get("revision") != "2.0.0": - raise ValueError("the current formal evidence release must be the explicit 45.0.0 retest") + if release.manifest.get("revision") != "46.0.0" or release.protocol.get("revision") != "2.0.0": + raise ValueError("the current formal evidence release must be the explicit 46.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 2710eff1b..851561e53 100644 --- a/tools/formal_semantic_validation/_release_revisions.py +++ b/tools/formal_semantic_validation/_release_revisions.py @@ -44,8 +44,9 @@ "42.0.0", "43.0.0", "44.0.0", + "45.0.0", } ) -_SUPPORTED_RETEST_REVISIONS = _HISTORICAL_RETEST_REVISIONS | {"45.0.0"} +_SUPPORTED_RETEST_REVISIONS = _HISTORICAL_RETEST_REVISIONS | {"46.0.0"} _SOURCE_BOUND_RETEST_REVISIONS = _SUPPORTED_RETEST_REVISIONS - {"3.0.0"} diff --git a/tools/formal_semantic_validation/_releases.py b/tools/formal_semantic_validation/_releases.py index 4a45b2446..46fd67a0d 100644 --- a/tools/formal_semantic_validation/_releases.py +++ b/tools/formal_semantic_validation/_releases.py @@ -159,7 +159,7 @@ def validate_release_bundle(repo_root: Path, release: EvidenceRelease) -> list[P release.corpus, release.snapshot, release.analysis, - replay_current=manifest.get("revision") == "45.0.0", + replay_current=manifest.get("revision") == "46.0.0", ) ) else: @@ -244,7 +244,7 @@ def validate_retest_bundle( return [ _failure( "formal-validation-current-replay-required", - "only releases 3.0.0 through 44.0.0 can use integrated historical validation", + "only releases 3.0.0 through 45.0.0 can use integrated historical validation", snapshot_path, ) ] @@ -292,7 +292,7 @@ def validate_retest_bundle( } else "2.0.0" ) - if release_revision in {"42.0.0", "45.0.0"}: + if release_revision in {"42.0.0", "45.0.0", "46.0.0"}: expected_corpus_revision = "4.0.0" if protocol.get("revision") != "2.0.0" or corpus.get("revision") != expected_corpus_revision: failures.append( @@ -399,6 +399,7 @@ def _current_retest_source_failures( "43.0.0": "41.0.0", "44.0.0": "43.0.0", "45.0.0": "42.0.0", + "46.0.0": "45.0.0", }[release_revision] if not isinstance(baseline, Mapping) or baseline.get("release_revision") != expected_baseline: failures.append( diff --git a/tools/formal_semantic_validation/_retest.py b/tools/formal_semantic_validation/_retest.py index cc8d62700..b8d81d0b4 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, 46)) +_SOURCE_STATE_REVISIONS = frozenset(f"{revision}.0.0" for revision in range(4, 47)) @dataclasses.dataclass(frozen=True) From b827185b1efcfba324a57fd6fd84e801868b5177 Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Fri, 25 Sep 2026 04:35:25 +0200 Subject: [PATCH 3/7] fix: keep reference backend supervision opt-in --- docs/requirements/API-402/requirement.md | 1 + .../analysis-v46.json | 154 ++++ .../bundles/retest-v46.json | 122 +++ .../execution-snapshot-v46.json | 652 ++++++++++++++++ .../formal-semantic-validation/index.md | 7 +- .../specification-coverage/analysis-v46.json | 101 +++ ...specification-coverage-issue-1360-v46.json | 10 + .../execution-snapshot-v46.json | 700 ++++++++++++++++++ docs/research/specification-coverage/index.md | 7 +- .../raes_reference_backend/manifest.py | 2 + .../tests/test_formal_semantic_validation.py | 5 +- .../test_issue_989_versioned_evidence.py | 6 +- .../tests/test_specification_coverage.py | 2 +- tools/check_specification_coverage.py | 5 +- tools/formal_semantic_validation/_baseline.py | 3 +- tools/formal_semantic_validation/_loading.py | 5 +- .../_release_revisions.py | 3 +- tools/formal_semantic_validation/_releases.py | 7 +- tools/formal_semantic_validation/_retest.py | 2 +- 19 files changed, 1777 insertions(+), 17 deletions(-) create mode 100644 docs/research/formal-semantic-validation/analysis-v46.json create mode 100644 docs/research/formal-semantic-validation/bundles/retest-v46.json create mode 100644 docs/research/formal-semantic-validation/execution-snapshot-v46.json create mode 100644 docs/research/specification-coverage/analysis-v46.json create mode 100644 docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v46.json create mode 100644 docs/research/specification-coverage/execution-snapshot-v46.json diff --git a/docs/requirements/API-402/requirement.md b/docs/requirements/API-402/requirement.md index 596efb9ec..a2217b0ab 100644 --- a/docs/requirements/API-402/requirement.md +++ b/docs/requirements/API-402/requirement.md @@ -57,3 +57,4 @@ Current state: implemented. Portable live-execution contracts are required so in - IMPLEMENTS → CONFIG `tools/policy/requirement_order.yaml` (Existing live-contract requirement admitted through control-plane governance) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/_backend_operation_exports.py` (Public operation contract facade exports) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_backend_stubs/manifest.py` (Keep operation supervision opt-in; legacy stub does not advertise an unimplemented provider) +- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_reference_backend/manifest.py` (Keep operation supervision opt-in for reference emulation) diff --git a/docs/research/formal-semantic-validation/analysis-v46.json b/docs/research/formal-semantic-validation/analysis-v46.json new file mode 100644 index 000000000..07169292d --- /dev/null +++ b/docs/research/formal-semantic-validation/analysis-v46.json @@ -0,0 +1,154 @@ +{ + "analysis_id": "issue-1360-analysis-v46", + "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-v46.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-1360-execution-v46", + "generated_at": "2026-09-25", + "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." + ], + "plain_language_outcome": "The retained controls replay against the backend operation contract publication. The original claim limits and unsupported classes remain unchanged; this offline corpus does not establish live backend supervision or recovery.", + "protocol_revision": "2.0.0" +} diff --git a/docs/research/formal-semantic-validation/bundles/retest-v46.json b/docs/research/formal-semantic-validation/bundles/retest-v46.json new file mode 100644 index 000000000..2108e7036 --- /dev/null +++ b/docs/research/formal-semantic-validation/bundles/retest-v46.json @@ -0,0 +1,122 @@ +{ + "analysis_path": "docs/research/formal-semantic-validation/analysis-v46.json", + "analysis_sha256": "21bdf2ff3dd191238534e2f00af2c98856e6752f4c3ab583b523bd46a1fccada", + "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": "47.0.0", + "snapshot_path": "docs/research/formal-semantic-validation/execution-snapshot-v46.json", + "snapshot_sha256": "b3165ce644ff926045d6887ff9c3754406843b809fccf6869269f43f19538a23" +} diff --git a/docs/research/formal-semantic-validation/execution-snapshot-v46.json b/docs/research/formal-semantic-validation/execution-snapshot-v46.json new file mode 100644 index 000000000..869bc9519 --- /dev/null +++ b/docs/research/formal-semantic-validation/execution-snapshot-v46.json @@ -0,0 +1,652 @@ +{ + "baseline": { + "execution_id": "issue-1360-execution-v45", + "release_path": "docs/research/formal-semantic-validation/bundles/retest-v45.json", + "release_revision": "46.0.0", + "release_sha256": "d5cc880d58ad85468bb9b2a24c74bbb99b838a1a58476df9e9469d7b293aa871" + }, + "captured_at": "2026-09-25T02:34:46.514076+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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "limitations": [ + "The witness ends at compiled output." + ], + "replayable": true, + "result_digest": "11264a648a949917c0e84a2a1e5d116139a35e6cb941844735a422df95141d6c", + "source_digest": null + }, + { + "actual_outcome": "distinguishable", + "analysis_profile": null, + "case_id": "compile-non-vacuity-control", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/determinism-a.sdl.yaml", + "docs/research/formal-semantic-validation/corpus/determinism-b.sdl.yaml" + ], + "execution_id": "issue-1360-execution-v46", + "limitations": [ + "Distinct digests are a non-vacuity control, not semantic non-equivalence proof." + ], + "replayable": true, + "result_digest": "72c1ee8c7bbc1f970216fa232b3d4ae917bcb003bd823439bbac8a5db94214e2", + "source_digest": null + }, + { + "actual_outcome": "unsupported", + "analysis_profile": null, + "case_id": "necessity-witness-request", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/decisions/issue-168-formal-semantic-validation-reachability-preflight.md" + ], + "execution_id": "issue-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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-1360-execution-v46", + "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": "8a158cb1b1d3a5695409fcdfdf14d1a0607d597b", + "source_state": { + "base_revision": "8a158cb1b1d3a5695409fcdfdf14d1a0607d597b", + "checkout_state": "modified", + "implementation_digest": "1157e520ea06390072485a32ed4bd10c1e4a08ff56aaa80aa198b60343704072", + "profile": "python-reference-source/v2" + }, + "versions": { + "python": "3.14.4", + "raes": "5.0.0", + "z3_engine": "4.16.0", + "z3_solver": "4.16.0.0" + } +} diff --git a/docs/research/formal-semantic-validation/index.md b/docs/research/formal-semantic-validation/index.md index 0a30aa5ed..f30a95b2f 100644 --- a/docs/research/formal-semantic-validation/index.md +++ b/docs/research/formal-semantic-validation/index.md @@ -336,7 +336,7 @@ outcomes and claim limits, recording the positive successor's changed result digest; the dangling-reference diagnostic remains identical. It establishes no autonomy threshold, authority grant, or realized attribution. -Current validation requires explicit release 46.0.0, rejects unsupported future +Current validation requires explicit release 47.0.0, rejects unsupported future or duplicate revisions, and never accepts an old/new output-digest pair as a substitute for replay. Historical releases (including the issue-826 supplement) undergo pin, shape, control, and internal-join checks without executing current @@ -456,3 +456,8 @@ Release 46.0.0 binds issue #1360 to fresh source evidence in their classifications and claim limits. Backend supervision contracts have dedicated contract tests; this capture makes no live backend recovery claim. Earlier published captures retain their exact bytes. + +Release 47.0.0 binds the reference-backend opt-in correction to +[`execution-snapshot-v46.json`](execution-snapshot-v46.json) and +[`analysis-v46.json`](analysis-v46.json). The retained claims and +classifications are unchanged. diff --git a/docs/research/specification-coverage/analysis-v46.json b/docs/research/specification-coverage/analysis-v46.json new file mode 100644 index 000000000..e03452b97 --- /dev/null +++ b/docs/research/specification-coverage/analysis-v46.json @@ -0,0 +1,101 @@ +{ + "analysis_id": "issue-1360-specification-coverage-v46", + "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-v46.json", + "docs/research/specification-coverage/analysis-v46.json" + ], + "falsification_protocol": "docs/research/specification-coverage/protocol-v1.json", + "objective_fail_criteria": "A load-bearing concept is missing or lossy, an applicable stage fails, or backend vocabulary is required in core SDL while the result claims success.", + "objective_pass_criteria": "Every load-bearing concept passes at every owning stage, backend-specific mechanics stay outside core SDL, and no requested concept is silently lost.", + "statement": "RAES provides a standardized configurable portable specification surface for the preregistered representative cyber-agent evaluation environment requirements without backend vocabulary in core SDL.", + "threats_to_validity": [ + "The representative corpus contains four source strata and sixteen atomic concepts rather than every cyber-range requirement.", + "The reference processor and repository fixtures are not independent backend implementations.", + "No live range, simulator federation, or participant execution was part of this offline specification-coverage test." + ] + }, + "classification_counts": { + "deliberately-backend-specific": 1, + "directly-expressible": 10, + "missing": 3, + "profile-or-manifest-constraint": 2 + }, + "evidence_status": "partial", + "execution_status": "complete", + "generated_at": "2026-09-25", + "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." + ], + "load_bearing_results": { + "failed": 0, + "missing": 0, + "passed": 10, + "total": 10 + }, + "plain_language_outcome": "The retained specification matrix replays explicit participant affiliations, objective ownership, and assignment using abstract action contracts. Classification counts and untested concepts are unchanged; no execution authority or live backend behavior is inferred.", + "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": "issue-1360-specification-coverage-v46", + "snapshot_sha256": "11038ca384f91409b23dcb46a24e12f2655e2e5721f6477c6b029e798939b5f0" +} diff --git a/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v46.json b/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v46.json new file mode 100644 index 000000000..67bfff0bf --- /dev/null +++ b/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v46.json @@ -0,0 +1,10 @@ +{ + "analysis_path": "docs/research/specification-coverage/analysis-v46.json", + "analysis_sha256": "af63196c8a449134e2a19adcf6474987127096b7026de969975c99af08ec439a", + "bundle_id": "raes-standardized-specification-coverage", + "protocol_path": "docs/research/specification-coverage/protocol-v1.json", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "revision": "46.0.0", + "snapshot_path": "docs/research/specification-coverage/execution-snapshot-v46.json", + "snapshot_sha256": "f052919f8dbcb78e9242453c5e1830e8c55f1943f40aea176a3e3579617345b5" +} diff --git a/docs/research/specification-coverage/execution-snapshot-v46.json b/docs/research/specification-coverage/execution-snapshot-v46.json new file mode 100644 index 000000000..5d0576ac6 --- /dev/null +++ b/docs/research/specification-coverage/execution-snapshot-v46.json @@ -0,0 +1,700 @@ +{ + "artifacts": [ + { + "artifact_id": "enterprise-participant-sdl", + "kind": "sdl", + "path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "sha256": "f7a8897beec243e188ee081975006fad32725f469f267db6e75a1e1cf5727032", + "validator": "raes parse, semantic, instantiation/admission, and compiler pipeline" + }, + { + "artifact_id": "port-range-sdl", + "kind": "sdl", + "path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "sha256": "0d5497ec946b863e6985284ec487dde7d7f6bf710a985be51401ac0e5e79dc4f", + "validator": "raes parse, semantic, instantiation/admission, and compiler pipeline" + }, + { + "artifact_id": "experiment-task-contract", + "kind": "experiment-task", + "path": "contracts/fixtures/experiment-core/experiment-task-v1/valid/reference.json", + "sha256": "f3edf713ac6af26bad609136851c6dd434bfb87ce919a2d8c4414c1035deeafc", + "validator": "raes_contracts.contracts.ExperimentTaskModel" + }, + { + "artifact_id": "apparatus-context-contract", + "kind": "experiment-apparatus-context", + "path": "contracts/fixtures/experiment-core/experiment-apparatus-context-v1/valid/reference.json", + "sha256": "e6fa559c5e961f0aab448d0f70dead24aa74fa8ba5f20e1b72f88e11473c9299", + "validator": "raes_contracts.contracts.ExperimentApparatusContextModel" + }, + { + "artifact_id": "backend-profile", + "kind": "backend-profile", + "path": "contracts/profiles/backend/orchestration-capable.json", + "sha256": "f70b8505a5c0055416db86c533e2e5bf08b11e5a514f076223b6d6c36215a092", + "validator": "raes_contracts.backend_profiles.BackendProfileModel" + }, + { + "artifact_id": "known-limitations", + "kind": "documentation", + "path": "docs/explain/sdl/limitations.md", + "sha256": "489eeab3ce682627682311581eb98af9abb9ff42a437145af266eefb71dc7fc4", + "validator": "documentation evidence only" + } + ], + "baseline": { + "release_revision": "1.1.0", + "release_sha256": "4020a1d56c7fe2831cec59ea64a12bbda9d38ccd94f93b916dd90f1a28f17fcb" + }, + "captured_at": "2026-09-25T02:34:46.514076+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": "7531f0ffb125a928a8cd9c8b57443aa175c3dc7ea921f0b51eab6377f2443459", + "path": "implementations/python/packages/raes_contracts", + "surface_id": "contract-models" + }, + { + "content_sha256": "4999b8adf294f364a758bc9cf78816d5da9eae1c263ae678eabe4d0e2c82dec6", + "path": "implementations/python/packages/raes_processor", + "surface_id": "processor-pipeline" + }, + { + "content_sha256": "9ecd780448b054693503bab246120a1a2bb49a43016d0b9c27c5284ba609833f", + "path": "implementations/python/packages/raes", + "surface_id": "sdl-pipeline" + } + ], + "limitations": [ + "The execution validates the pinned reference implementation and published contracts, not an independent backend.", + "Repository-owned examples are exact execution artifacts but are not themselves the literature-derived request corpus; the protocol's requests and concepts are.", + "No live range, participant, simulator federation, or provider provisioning engine was executed.", + "Missing concepts remain frozen in this snapshot and require separately scoped product work before a later rerun.", + "This capture replays the retained protocol after EXP-732 run, apparatus, measurement-channel, and augmentation-producer provenance validation; it adds no independent backend or universal provenance assurance claim.", + "Materialization attestation is covered by its dedicated regression suite, not a new claim in this preregistered matrix.", + "This capture refreshes the corrected runtime limitations prose for issue #959; the protocol, coverage classifications and implementation source are unchanged.", + "This capture replays open-by-default augmentation scope integrated with the EXP-731 evidence refinements after composition type refinement; it does not evaluate native backend scope enforcement or broaden the preregistered coverage claims.", + "This capture replays the retained protocol after merging ACT-612 participant relationships with open-by-default augmentation scope; it adds no claim of realized participant relationships or native backend scope enforcement.", + "This capture replays issue #1299 partial listener descriptions on the integrated source state; endpoint completeness and backend admission remain outside this protocol's claims.", + "This capture also binds authoring-adapter semantic conformance to the integrated source; adapter transport behavior remains outside this protocol's claims.", + "Reviewed OCI mirror and pre-seed admission is covered by its own regression suites and the development artifact policy gate, not a new claim in this preregistered matrix.", + "This capture binds issue #1297 service-manager identity, native-name, and explicitly selected systemd-state contract changes to the integrated source. It exercises no live service manager and adds no backend-execution claim.", + "This capture replays the retained specification-coverage protocol after API-404 startup reconciliation added an operational recovery-observation contract. It does not evaluate crash recovery, classify provider effects, or broaden EXP-715 experiment-observation claims.", + "This capture binds API-404 single-owner store admission and immutable target/run scope to the integrated source. The retained offline protocol does not exercise process leases, SQLite lifecycle ordering, or crash recovery.", + "This capture binds issue #1015 deterministic mixed and staged trial admission to the integrated source. The retained offline language corpus does not execute mixed runtimes, phase transitions, backend handoff, or scheduler-driven realization.", + "This replay binds issue #1186 offline control-plane maintenance, readiness, and bounded audit code to the integrated source. The retained language corpus does not execute store recovery, HTTP health behavior, or audit redaction.", + "Issue #1187 control-plane crash/profile conformance and HTTP security changes are covered by their dedicated regression suite, not promoted to new claims by this retained corpus.", + "Issue #1189 control-plane profile declarations are covered by their dedicated runtime suite, not promoted to new claims by the retained language corpus.", + "Issue #1016 mixed-runtime coordination is covered by its dedicated runtime suite. The retained language corpus does not execute mixed providers or establish backend-native realization, multi-controller coordination, IFC, or equivalence.", + "Issue #610's reconciliation demonstration harness is covered by its dedicated processor and CLI suite, not promoted to new claims by the retained language corpus.", + "Participant identity, organization ownership, and participant assignment are separated by issue #1338. This retained offline corpus does not establish participant autonomy, execution authority, live backend fidelity, or causal attribution." + ], + "protocol_revision": "1.0.0", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "raes_revision": "8a158cb1b1d3a5695409fcdfdf14d1a0607d597b", + "snapshot_id": "issue-1360-specification-coverage-v46", + "snapshot_revision": "46.0.0", + "source_state": { + "base_revision": "8a158cb1b1d3a5695409fcdfdf14d1a0607d597b", + "checkout_state": "modified", + "implementation_digest": "1157e520ea06390072485a32ed4bd10c1e4a08ff56aaa80aa198b60343704072", + "profile": "python-reference-source/v2" + } +} diff --git a/docs/research/specification-coverage/index.md b/docs/research/specification-coverage/index.md index ccb5902a0..659910744 100644 --- a/docs/research/specification-coverage/index.md +++ b/docs/research/specification-coverage/index.md @@ -292,7 +292,7 @@ the port scenario. Historical captures and archived example bytes are retained. The matrix classifications and untested concepts are unchanged; no execution authority, successful action, or live backend fidelity is inferred. -Current validation requires release 45.0.0 and rejects duplicate or unsupported +Current validation requires release 46.0.0 and rejects duplicate or unsupported future revisions. It executes current artifacts, requires exact source and package hashes, and checks all passing stage pointers. `source_state` discloses the base Git commit, modified checkout state, and exact implementation digest; @@ -392,3 +392,8 @@ Release 45.0.0 binds issue #1360 to fresh source evidence in their classifications and claim limits. Backend supervision contracts have dedicated contract tests; this capture makes no live backend recovery claim. Earlier published captures retain their exact bytes. + +Release 46.0.0 binds the reference-backend opt-in correction to +[`execution-snapshot-v46.json`](execution-snapshot-v46.json) and +[`analysis-v46.json`](analysis-v46.json). The retained claims and +classifications are unchanged. diff --git a/implementations/python/packages/raes_reference_backend/manifest.py b/implementations/python/packages/raes_reference_backend/manifest.py index 3af46a43d..9273dba5c 100644 --- a/implementations/python/packages/raes_reference_backend/manifest.py +++ b/implementations/python/packages/raes_reference_backend/manifest.py @@ -43,6 +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.vocabulary import ( ParticipantFeatureSupportLevel, RealizationSupportMode, @@ -55,6 +56,7 @@ REFERENCE_BACKEND_SUPPORTED_CONTRACT_VERSIONS = frozenset( contract_id for contract_id in BACKEND_SUPPORTED_CONTRACT_IDS + if contract_id not in BACKEND_OPERATION_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_formal_semantic_validation.py b/implementations/python/tests/test_formal_semantic_validation.py index 864544cb6..74ae55d61 100644 --- a/implementations/python/tests/test_formal_semantic_validation.py +++ b/implementations/python/tests/test_formal_semantic_validation.py @@ -125,6 +125,7 @@ def test_atomic_release_index_validates_every_historical_bundle() -> None: "44.0.0", "45.0.0", "46.0.0", + "47.0.0", ] assert all(validate_release_bundle(REPO_ROOT, release) == [] for release in releases) @@ -133,10 +134,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"] == "46.0.0" + assert release.manifest["revision"] == "47.0.0" assert protocol["revision"] == "2.0.0" assert corpus["revision"] == "4.0.0" - assert snapshot["baseline"]["release_revision"] == "45.0.0" + assert snapshot["baseline"]["release_revision"] == "46.0.0" assert snapshot["deviations"] == [] assert validate_retest_bundle(REPO_ROOT, release, protocol, corpus, snapshot, analysis) == [] diff --git a/implementations/python/tests/test_issue_989_versioned_evidence.py b/implementations/python/tests/test_issue_989_versioned_evidence.py index 35199486c..eb3ee7ba1 100644 --- a/implementations/python/tests/test_issue_989_versioned_evidence.py +++ b/implementations/python/tests/test_issue_989_versioned_evidence.py @@ -230,7 +230,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"] == "46.0.0" + assert release.manifest["revision"] == "47.0.0" original = _retest.replay_case def changed_result(root, case): @@ -283,7 +283,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"] == "45.0.0" + assert manifest["revision"] == "46.0.0" snapshot = deepcopy(snapshot) artifact = next(a for a in snapshot["artifacts"] if a["artifact_id"] == artifact_id) artifact["sha256"] = old_digest @@ -498,6 +498,7 @@ def test_no_capture_can_be_silently_dropped(monkeypatch, family, removed): "44.0.0", "45.0.0", "46.0.0", + "47.0.0", ] if family == "formal" else [ @@ -547,6 +548,7 @@ def test_no_capture_can_be_silently_dropped(monkeypatch, family, removed): "43.0.0", "44.0.0", "45.0.0", + "46.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 8406035dd..453a1dd3a 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"] == "45.0.0" + assert manifest["revision"] == "46.0.0" def test_historical_failures_name_the_revision_specific_documents() -> None: diff --git a/tools/check_specification_coverage.py b/tools/check_specification_coverage.py index 10ba95c52..9d19cf2b7 100644 --- a/tools/check_specification_coverage.py +++ b/tools/check_specification_coverage.py @@ -102,7 +102,7 @@ def _load_bundle_index(repo_root: Path) -> list[tuple[str, dict[str, object]]]: max_bytes=_MAX_FILE_BYTES, ) current_path = current_release_path(records) - if dict(records)[current_path].get("revision") != "45.0.0" or {record.get("revision") for _, record in records} != { + if dict(records)[current_path].get("revision") != "46.0.0" or {record.get("revision") for _, record in records} != { "1.0.0", "1.1.0", "2.0.0", @@ -149,8 +149,9 @@ def _load_bundle_index(repo_root: Path) -> list[tuple[str, dict[str, object]]]: "43.0.0", "44.0.0", "45.0.0", + "46.0.0", }: - raise ValueError("coverage evidence requires the explicit current 45.0.0 release and supported history") + raise ValueError("coverage evidence requires the explicit current 46.0.0 release and supported history") return records diff --git a/tools/formal_semantic_validation/_baseline.py b/tools/formal_semantic_validation/_baseline.py index 35c22fa96..23dc1642e 100644 --- a/tools/formal_semantic_validation/_baseline.py +++ b/tools/formal_semantic_validation/_baseline.py @@ -75,6 +75,7 @@ "43.0.0", "44.0.0", "45.0.0", + "46.0.0", } ) _V3_CORPUS_REVISIONS = frozenset( @@ -223,7 +224,7 @@ def _selected_baseline_manifest( if baseline_revision in _V2_REVISIONS else "docs/research/formal-semantic-validation/protocol-v1.json" ) - if baseline_revision in {"42.0.0", "45.0.0"}: + if baseline_revision in {"42.0.0", "45.0.0", "46.0.0"}: expected_corpus_path = "docs/research/formal-semantic-validation/corpus/manifest-v4.json" elif baseline_revision in _V3_CORPUS_REVISIONS: expected_corpus_path = "docs/research/formal-semantic-validation/corpus/manifest-v3.json" diff --git a/tools/formal_semantic_validation/_loading.py b/tools/formal_semantic_validation/_loading.py index 873dcff8e..3ca6e1d34 100644 --- a/tools/formal_semantic_validation/_loading.py +++ b/tools/formal_semantic_validation/_loading.py @@ -76,6 +76,7 @@ def load_release_bundles(repo_root: Path = REPO_ROOT) -> list[EvidenceRelease]: "44.0.0", "45.0.0", "46.0.0", + "47.0.0", }: raise ValueError("formal evidence requires every supported historical and current release") releases: list[EvidenceRelease] = [] @@ -122,6 +123,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") != "46.0.0" or release.protocol.get("revision") != "2.0.0": - raise ValueError("the current formal evidence release must be the explicit 46.0.0 retest") + if release.manifest.get("revision") != "47.0.0" or release.protocol.get("revision") != "2.0.0": + raise ValueError("the current formal evidence release must be the explicit 47.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 851561e53..d533292de 100644 --- a/tools/formal_semantic_validation/_release_revisions.py +++ b/tools/formal_semantic_validation/_release_revisions.py @@ -45,8 +45,9 @@ "43.0.0", "44.0.0", "45.0.0", + "46.0.0", } ) -_SUPPORTED_RETEST_REVISIONS = _HISTORICAL_RETEST_REVISIONS | {"46.0.0"} +_SUPPORTED_RETEST_REVISIONS = _HISTORICAL_RETEST_REVISIONS | {"47.0.0"} _SOURCE_BOUND_RETEST_REVISIONS = _SUPPORTED_RETEST_REVISIONS - {"3.0.0"} diff --git a/tools/formal_semantic_validation/_releases.py b/tools/formal_semantic_validation/_releases.py index 46fd67a0d..6bafd9f68 100644 --- a/tools/formal_semantic_validation/_releases.py +++ b/tools/formal_semantic_validation/_releases.py @@ -159,7 +159,7 @@ def validate_release_bundle(repo_root: Path, release: EvidenceRelease) -> list[P release.corpus, release.snapshot, release.analysis, - replay_current=manifest.get("revision") == "46.0.0", + replay_current=manifest.get("revision") == "47.0.0", ) ) else: @@ -244,7 +244,7 @@ def validate_retest_bundle( return [ _failure( "formal-validation-current-replay-required", - "only releases 3.0.0 through 45.0.0 can use integrated historical validation", + "only releases 3.0.0 through 46.0.0 can use integrated historical validation", snapshot_path, ) ] @@ -292,7 +292,7 @@ def validate_retest_bundle( } else "2.0.0" ) - if release_revision in {"42.0.0", "45.0.0", "46.0.0"}: + if release_revision in {"42.0.0", "45.0.0", "46.0.0", "47.0.0"}: expected_corpus_revision = "4.0.0" if protocol.get("revision") != "2.0.0" or corpus.get("revision") != expected_corpus_revision: failures.append( @@ -400,6 +400,7 @@ def _current_retest_source_failures( "44.0.0": "43.0.0", "45.0.0": "42.0.0", "46.0.0": "45.0.0", + "47.0.0": "46.0.0", }[release_revision] if not isinstance(baseline, Mapping) or baseline.get("release_revision") != expected_baseline: failures.append( diff --git a/tools/formal_semantic_validation/_retest.py b/tools/formal_semantic_validation/_retest.py index b8d81d0b4..17c73d8a3 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, 47)) +_SOURCE_STATE_REVISIONS = frozenset(f"{revision}.0.0" for revision in range(4, 48)) @dataclasses.dataclass(frozen=True) From f7f1e41491419c3797620d2d8178f690e203da25 Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Fri, 25 Sep 2026 04:53:54 +0200 Subject: [PATCH 4/7] refactor: simplify backend operation contract validation --- docs/requirements/API-402/requirement.md | 1 - .../analysis-v47.json | 154 ++++ .../bundles/retest-v47.json | 122 +++ .../execution-snapshot-v47.json | 652 ++++++++++++++++ .../formal-semantic-validation/index.md | 7 +- .../specification-coverage/analysis-v47.json | 101 +++ ...specification-coverage-issue-1360-v47.json | 10 + .../execution-snapshot-v47.json | 700 ++++++++++++++++++ docs/research/specification-coverage/index.md | 7 +- .../raes_backend_protocols/protocols.py | 2 - .../contracts/backend_operation.py | 8 +- .../contracts/backend_operation_response.py | 26 +- .../contracts/backend_operation_schema.py | 4 +- .../contracts/backend_operation_validation.py | 75 +- .../tests/test_formal_semantic_validation.py | 5 +- .../test_issue_1360_backend_operations.py | 45 +- .../test_issue_1360_operation_rejections.py | 54 +- .../test_issue_989_versioned_evidence.py | 6 +- .../tests/test_specification_coverage.py | 2 +- tools/check_specification_coverage.py | 5 +- tools/formal_semantic_validation/_baseline.py | 3 +- tools/formal_semantic_validation/_loading.py | 5 +- .../_release_revisions.py | 3 +- tools/formal_semantic_validation/_releases.py | 7 +- tools/formal_semantic_validation/_retest.py | 2 +- 25 files changed, 1918 insertions(+), 88 deletions(-) create mode 100644 docs/research/formal-semantic-validation/analysis-v47.json create mode 100644 docs/research/formal-semantic-validation/bundles/retest-v47.json create mode 100644 docs/research/formal-semantic-validation/execution-snapshot-v47.json create mode 100644 docs/research/specification-coverage/analysis-v47.json create mode 100644 docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v47.json create mode 100644 docs/research/specification-coverage/execution-snapshot-v47.json diff --git a/docs/requirements/API-402/requirement.md b/docs/requirements/API-402/requirement.md index a2217b0ab..d443056e7 100644 --- a/docs/requirements/API-402/requirement.md +++ b/docs/requirements/API-402/requirement.md @@ -38,7 +38,6 @@ Current state: implemented. Portable live-execution contracts are required so in - IMPLEMENTS → GITHUB_ISSUE `1360` (Optional backend operation and supervision contract publication) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_backend_protocols/__init__.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_backend_protocols/operation_supervision.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) -- IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_backend_protocols/protocols.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/__init__.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/_exports.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) - IMPLEMENTS → CODE_FILE `implementations/python/packages/raes_contracts/contracts/_version_exports.py` (Portable operation carriers, contextual validation and publication boundary; no runtime supervision claim) diff --git a/docs/research/formal-semantic-validation/analysis-v47.json b/docs/research/formal-semantic-validation/analysis-v47.json new file mode 100644 index 000000000..e0ad95a3c --- /dev/null +++ b/docs/research/formal-semantic-validation/analysis-v47.json @@ -0,0 +1,154 @@ +{ + "analysis_id": "issue-1360-analysis-v47", + "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-v47.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-1360-execution-v47", + "generated_at": "2026-09-25", + "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." + ], + "plain_language_outcome": "The retained controls replay against the backend operation contract publication. The original claim limits and unsupported classes remain unchanged; this offline corpus does not establish live backend supervision or recovery.", + "protocol_revision": "2.0.0" +} diff --git a/docs/research/formal-semantic-validation/bundles/retest-v47.json b/docs/research/formal-semantic-validation/bundles/retest-v47.json new file mode 100644 index 000000000..f5656dcbc --- /dev/null +++ b/docs/research/formal-semantic-validation/bundles/retest-v47.json @@ -0,0 +1,122 @@ +{ + "analysis_path": "docs/research/formal-semantic-validation/analysis-v47.json", + "analysis_sha256": "528f9da30ae5fd70b9db60d1d2fed72d9ef5aca337146e3b06561f489a922561", + "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": "48.0.0", + "snapshot_path": "docs/research/formal-semantic-validation/execution-snapshot-v47.json", + "snapshot_sha256": "845446ea5dad1eb7c4c4b99ab35211d056a0f245bf6cb9f65395c40f73f3484e" +} diff --git a/docs/research/formal-semantic-validation/execution-snapshot-v47.json b/docs/research/formal-semantic-validation/execution-snapshot-v47.json new file mode 100644 index 000000000..8b801cfd7 --- /dev/null +++ b/docs/research/formal-semantic-validation/execution-snapshot-v47.json @@ -0,0 +1,652 @@ +{ + "baseline": { + "execution_id": "issue-1360-execution-v46", + "release_path": "docs/research/formal-semantic-validation/bundles/retest-v46.json", + "release_revision": "47.0.0", + "release_sha256": "c597bc18eb008841aec5c21f92edf965adfb81dddff5d50dd1f0fa73e292a7b2" + }, + "captured_at": "2026-09-25T02:52:47.736460+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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "limitations": [ + "The witness ends at compiled output." + ], + "replayable": true, + "result_digest": "11264a648a949917c0e84a2a1e5d116139a35e6cb941844735a422df95141d6c", + "source_digest": null + }, + { + "actual_outcome": "distinguishable", + "analysis_profile": null, + "case_id": "compile-non-vacuity-control", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/research/formal-semantic-validation/corpus/determinism-a.sdl.yaml", + "docs/research/formal-semantic-validation/corpus/determinism-b.sdl.yaml" + ], + "execution_id": "issue-1360-execution-v47", + "limitations": [ + "Distinct digests are a non-vacuity control, not semantic non-equivalence proof." + ], + "replayable": true, + "result_digest": "72c1ee8c7bbc1f970216fa232b3d4ae917bcb003bd823439bbac8a5db94214e2", + "source_digest": null + }, + { + "actual_outcome": "unsupported", + "analysis_profile": null, + "case_id": "necessity-witness-request", + "configuration_digest": null, + "configuration_id": "raes-python-reference-offline-v41", + "diagnostic_kind": null, + "evidence_artifact_path": null, + "evidence_artifact_sha256": null, + "evidence_digest": null, + "evidence_profile": null, + "evidence_refs": [ + "docs/decisions/issue-168-formal-semantic-validation-reachability-preflight.md" + ], + "execution_id": "issue-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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-1360-execution-v47", + "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": "b827185b1efcfba324a57fd6fd84e801868b5177", + "source_state": { + "base_revision": "b827185b1efcfba324a57fd6fd84e801868b5177", + "checkout_state": "modified", + "implementation_digest": "ff02d6c5409926c36e99322264e7e3b99b57cab2bad7e29af883dbbcb4667fc0", + "profile": "python-reference-source/v2" + }, + "versions": { + "python": "3.14.4", + "raes": "5.0.0", + "z3_engine": "4.16.0", + "z3_solver": "4.16.0.0" + } +} diff --git a/docs/research/formal-semantic-validation/index.md b/docs/research/formal-semantic-validation/index.md index f30a95b2f..68869d096 100644 --- a/docs/research/formal-semantic-validation/index.md +++ b/docs/research/formal-semantic-validation/index.md @@ -336,7 +336,7 @@ outcomes and claim limits, recording the positive successor's changed result digest; the dangling-reference diagnostic remains identical. It establishes no autonomy threshold, authority grant, or realized attribution. -Current validation requires explicit release 47.0.0, rejects unsupported future +Current validation requires explicit release 48.0.0, rejects unsupported future or duplicate revisions, and never accepts an old/new output-digest pair as a substitute for replay. Historical releases (including the issue-826 supplement) undergo pin, shape, control, and internal-join checks without executing current @@ -461,3 +461,8 @@ Release 47.0.0 binds the reference-backend opt-in correction to [`execution-snapshot-v46.json`](execution-snapshot-v46.json) and [`analysis-v46.json`](analysis-v46.json). The retained claims and classifications are unchanged. + +Release 48.0.0 binds the operation validator maintainability changes to +[`execution-snapshot-v47.json`](execution-snapshot-v47.json) and +[`analysis-v47.json`](analysis-v47.json). The retained claims and +classifications are unchanged. diff --git a/docs/research/specification-coverage/analysis-v47.json b/docs/research/specification-coverage/analysis-v47.json new file mode 100644 index 000000000..39b6e313c --- /dev/null +++ b/docs/research/specification-coverage/analysis-v47.json @@ -0,0 +1,101 @@ +{ + "analysis_id": "issue-1360-specification-coverage-v47", + "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-v47.json", + "docs/research/specification-coverage/analysis-v47.json" + ], + "falsification_protocol": "docs/research/specification-coverage/protocol-v1.json", + "objective_fail_criteria": "A load-bearing concept is missing or lossy, an applicable stage fails, or backend vocabulary is required in core SDL while the result claims success.", + "objective_pass_criteria": "Every load-bearing concept passes at every owning stage, backend-specific mechanics stay outside core SDL, and no requested concept is silently lost.", + "statement": "RAES provides a standardized configurable portable specification surface for the preregistered representative cyber-agent evaluation environment requirements without backend vocabulary in core SDL.", + "threats_to_validity": [ + "The representative corpus contains four source strata and sixteen atomic concepts rather than every cyber-range requirement.", + "The reference processor and repository fixtures are not independent backend implementations.", + "No live range, simulator federation, or participant execution was part of this offline specification-coverage test." + ] + }, + "classification_counts": { + "deliberately-backend-specific": 1, + "directly-expressible": 10, + "missing": 3, + "profile-or-manifest-constraint": 2 + }, + "evidence_status": "partial", + "execution_status": "complete", + "generated_at": "2026-09-25", + "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." + ], + "load_bearing_results": { + "failed": 0, + "missing": 0, + "passed": 10, + "total": 10 + }, + "plain_language_outcome": "The retained specification matrix replays explicit participant affiliations, objective ownership, and assignment using abstract action contracts. Classification counts and untested concepts are unchanged; no execution authority or live backend behavior is inferred.", + "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": "issue-1360-specification-coverage-v47", + "snapshot_sha256": "5364c1e1c198253f3914457ae792407ba3f8401a1bfaf8b8a340a77b4775d73d" +} diff --git a/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v47.json b/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v47.json new file mode 100644 index 000000000..d0d5f3bb8 --- /dev/null +++ b/docs/research/specification-coverage/bundles/raes-standardized-specification-coverage-issue-1360-v47.json @@ -0,0 +1,10 @@ +{ + "analysis_path": "docs/research/specification-coverage/analysis-v47.json", + "analysis_sha256": "b77b2f4b70cd0ea3a8680968042aa00b4af98927dbbb1fe29c91608796cb0321", + "bundle_id": "raes-standardized-specification-coverage", + "protocol_path": "docs/research/specification-coverage/protocol-v1.json", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "revision": "47.0.0", + "snapshot_path": "docs/research/specification-coverage/execution-snapshot-v47.json", + "snapshot_sha256": "7ba5682fe81d25569cdad10827cadf3161dc53dbc7db14ddd789fe99952fddd7" +} diff --git a/docs/research/specification-coverage/execution-snapshot-v47.json b/docs/research/specification-coverage/execution-snapshot-v47.json new file mode 100644 index 000000000..699408316 --- /dev/null +++ b/docs/research/specification-coverage/execution-snapshot-v47.json @@ -0,0 +1,700 @@ +{ + "artifacts": [ + { + "artifact_id": "enterprise-participant-sdl", + "kind": "sdl", + "path": "examples/scenarios/enterprise-participant-evidence-loop.sdl.yaml", + "sha256": "f7a8897beec243e188ee081975006fad32725f469f267db6e75a1e1cf5727032", + "validator": "raes parse, semantic, instantiation/admission, and compiler pipeline" + }, + { + "artifact_id": "port-range-sdl", + "kind": "sdl", + "path": "examples/scenarios/port-authority-surge-response.sdl.yaml", + "sha256": "0d5497ec946b863e6985284ec487dde7d7f6bf710a985be51401ac0e5e79dc4f", + "validator": "raes parse, semantic, instantiation/admission, and compiler pipeline" + }, + { + "artifact_id": "experiment-task-contract", + "kind": "experiment-task", + "path": "contracts/fixtures/experiment-core/experiment-task-v1/valid/reference.json", + "sha256": "f3edf713ac6af26bad609136851c6dd434bfb87ce919a2d8c4414c1035deeafc", + "validator": "raes_contracts.contracts.ExperimentTaskModel" + }, + { + "artifact_id": "apparatus-context-contract", + "kind": "experiment-apparatus-context", + "path": "contracts/fixtures/experiment-core/experiment-apparatus-context-v1/valid/reference.json", + "sha256": "e6fa559c5e961f0aab448d0f70dead24aa74fa8ba5f20e1b72f88e11473c9299", + "validator": "raes_contracts.contracts.ExperimentApparatusContextModel" + }, + { + "artifact_id": "backend-profile", + "kind": "backend-profile", + "path": "contracts/profiles/backend/orchestration-capable.json", + "sha256": "f70b8505a5c0055416db86c533e2e5bf08b11e5a514f076223b6d6c36215a092", + "validator": "raes_contracts.backend_profiles.BackendProfileModel" + }, + { + "artifact_id": "known-limitations", + "kind": "documentation", + "path": "docs/explain/sdl/limitations.md", + "sha256": "489eeab3ce682627682311581eb98af9abb9ff42a437145af266eefb71dc7fc4", + "validator": "documentation evidence only" + } + ], + "baseline": { + "release_revision": "1.1.0", + "release_sha256": "4020a1d56c7fe2831cec59ea64a12bbda9d38ccd94f93b916dd90f1a28f17fcb" + }, + "captured_at": "2026-09-25T02:52:47.736460+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": "9f7edff3ddc324cec333556ce8044c137f87c978a8c38f20f92971259625c43e", + "path": "implementations/python/packages/raes_contracts", + "surface_id": "contract-models" + }, + { + "content_sha256": "4999b8adf294f364a758bc9cf78816d5da9eae1c263ae678eabe4d0e2c82dec6", + "path": "implementations/python/packages/raes_processor", + "surface_id": "processor-pipeline" + }, + { + "content_sha256": "9ecd780448b054693503bab246120a1a2bb49a43016d0b9c27c5284ba609833f", + "path": "implementations/python/packages/raes", + "surface_id": "sdl-pipeline" + } + ], + "limitations": [ + "The execution validates the pinned reference implementation and published contracts, not an independent backend.", + "Repository-owned examples are exact execution artifacts but are not themselves the literature-derived request corpus; the protocol's requests and concepts are.", + "No live range, participant, simulator federation, or provider provisioning engine was executed.", + "Missing concepts remain frozen in this snapshot and require separately scoped product work before a later rerun.", + "This capture replays the retained protocol after EXP-732 run, apparatus, measurement-channel, and augmentation-producer provenance validation; it adds no independent backend or universal provenance assurance claim.", + "Materialization attestation is covered by its dedicated regression suite, not a new claim in this preregistered matrix.", + "This capture refreshes the corrected runtime limitations prose for issue #959; the protocol, coverage classifications and implementation source are unchanged.", + "This capture replays open-by-default augmentation scope integrated with the EXP-731 evidence refinements after composition type refinement; it does not evaluate native backend scope enforcement or broaden the preregistered coverage claims.", + "This capture replays the retained protocol after merging ACT-612 participant relationships with open-by-default augmentation scope; it adds no claim of realized participant relationships or native backend scope enforcement.", + "This capture replays issue #1299 partial listener descriptions on the integrated source state; endpoint completeness and backend admission remain outside this protocol's claims.", + "This capture also binds authoring-adapter semantic conformance to the integrated source; adapter transport behavior remains outside this protocol's claims.", + "Reviewed OCI mirror and pre-seed admission is covered by its own regression suites and the development artifact policy gate, not a new claim in this preregistered matrix.", + "This capture binds issue #1297 service-manager identity, native-name, and explicitly selected systemd-state contract changes to the integrated source. It exercises no live service manager and adds no backend-execution claim.", + "This capture replays the retained specification-coverage protocol after API-404 startup reconciliation added an operational recovery-observation contract. It does not evaluate crash recovery, classify provider effects, or broaden EXP-715 experiment-observation claims.", + "This capture binds API-404 single-owner store admission and immutable target/run scope to the integrated source. The retained offline protocol does not exercise process leases, SQLite lifecycle ordering, or crash recovery.", + "This capture binds issue #1015 deterministic mixed and staged trial admission to the integrated source. The retained offline language corpus does not execute mixed runtimes, phase transitions, backend handoff, or scheduler-driven realization.", + "This replay binds issue #1186 offline control-plane maintenance, readiness, and bounded audit code to the integrated source. The retained language corpus does not execute store recovery, HTTP health behavior, or audit redaction.", + "Issue #1187 control-plane crash/profile conformance and HTTP security changes are covered by their dedicated regression suite, not promoted to new claims by this retained corpus.", + "Issue #1189 control-plane profile declarations are covered by their dedicated runtime suite, not promoted to new claims by the retained language corpus.", + "Issue #1016 mixed-runtime coordination is covered by its dedicated runtime suite. The retained language corpus does not execute mixed providers or establish backend-native realization, multi-controller coordination, IFC, or equivalence.", + "Issue #610's reconciliation demonstration harness is covered by its dedicated processor and CLI suite, not promoted to new claims by the retained language corpus.", + "Participant identity, organization ownership, and participant assignment are separated by issue #1338. This retained offline corpus does not establish participant autonomy, execution authority, live backend fidelity, or causal attribution." + ], + "protocol_revision": "1.0.0", + "protocol_sha256": "e97a19e643e94c9e589dca823a63c6ce49d3329fe2a3cb888ab630838ed93125", + "raes_revision": "b827185b1efcfba324a57fd6fd84e801868b5177", + "snapshot_id": "issue-1360-specification-coverage-v47", + "snapshot_revision": "47.0.0", + "source_state": { + "base_revision": "b827185b1efcfba324a57fd6fd84e801868b5177", + "checkout_state": "modified", + "implementation_digest": "ff02d6c5409926c36e99322264e7e3b99b57cab2bad7e29af883dbbcb4667fc0", + "profile": "python-reference-source/v2" + } +} diff --git a/docs/research/specification-coverage/index.md b/docs/research/specification-coverage/index.md index 659910744..525ca3803 100644 --- a/docs/research/specification-coverage/index.md +++ b/docs/research/specification-coverage/index.md @@ -292,7 +292,7 @@ the port scenario. Historical captures and archived example bytes are retained. The matrix classifications and untested concepts are unchanged; no execution authority, successful action, or live backend fidelity is inferred. -Current validation requires release 46.0.0 and rejects duplicate or unsupported +Current validation requires release 47.0.0 and rejects duplicate or unsupported future revisions. It executes current artifacts, requires exact source and package hashes, and checks all passing stage pointers. `source_state` discloses the base Git commit, modified checkout state, and exact implementation digest; @@ -397,3 +397,8 @@ Release 46.0.0 binds the reference-backend opt-in correction to [`execution-snapshot-v46.json`](execution-snapshot-v46.json) and [`analysis-v46.json`](analysis-v46.json). The retained claims and classifications are unchanged. + +Release 47.0.0 binds the operation validator maintainability changes to +[`execution-snapshot-v47.json`](execution-snapshot-v47.json) and +[`analysis-v47.json`](analysis-v47.json). The retained claims and +classifications are unchanged. diff --git a/implementations/python/packages/raes_backend_protocols/protocols.py b/implementations/python/packages/raes_backend_protocols/protocols.py index 2ff54ac94..7ee51c18e 100644 --- a/implementations/python/packages/raes_backend_protocols/protocols.py +++ b/implementations/python/packages/raes_backend_protocols/protocols.py @@ -26,8 +26,6 @@ from raes_contracts.realization_preparation import RealizationPreparation from raes_contracts.runtime_state import ApplyResult, RuntimeSnapshot -from .operation_supervision import BackendOperationProvider as BackendOperationProvider - if TYPE_CHECKING: from raes_contracts.contracts.time_model import TimeModelDeclarationModel, TimeRuntimeStateModel diff --git a/implementations/python/packages/raes_contracts/contracts/backend_operation.py b/implementations/python/packages/raes_contracts/contracts/backend_operation.py index 32f843851..d3b52e1a2 100644 --- a/implementations/python/packages/raes_contracts/contracts/backend_operation.py +++ b/implementations/python/packages/raes_contracts/contracts/backend_operation.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Annotated, Literal +from typing import Annotated, Literal, Self from pydantic import ConfigDict, Field, model_validator @@ -30,7 +30,7 @@ class OperationContractModel(ContractModel): model_config = ConfigDict(extra="forbid", frozen=True) @model_validator(mode="after") - def _unique_collections(self): + def _unique_collections(self) -> Self: for name in type(self).model_fields: values = getattr(self, name) if isinstance(values, tuple) and len(values) != len(set(values)): @@ -55,7 +55,7 @@ class OperationBudgetModel(OperationContractModel): remaining_ms: OperationPositive @model_validator(mode="after") - def _budget_bounds(self): + def _budget_bounds(self) -> Self: _parse_rfc3339_datetime("started_at", self.started_at) if self.remaining_ms > self.limit_ms: raise ValueError("remaining budget cannot exceed its original limit") @@ -70,7 +70,7 @@ class OperationEffectScopeModel(OperationContractModel): independence: OperationArtifactReferenceModel | None = None @model_validator(mode="after") - def _scope_boundary(self): + def _scope_boundary(self) -> Self: if self.kind == "target-run" and (self.addresses or self.independence is not None): raise ValueError("target/run scope cannot carry a narrowed resource boundary") if self.kind == "resources" and (not self.addresses or self.independence is None): diff --git a/implementations/python/packages/raes_contracts/contracts/backend_operation_response.py b/implementations/python/packages/raes_contracts/contracts/backend_operation_response.py index 76f862180..6d21f5169 100644 --- a/implementations/python/packages/raes_contracts/contracts/backend_operation_response.py +++ b/implementations/python/packages/raes_contracts/contracts/backend_operation_response.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Annotated, Literal +from typing import Annotated, Literal, Self from pydantic import Field, StrictBool, model_validator @@ -37,7 +37,7 @@ class BackendOperationAdmissionModel(OperationContractModel): reason: OperationRefusalReason | None = None @model_validator(mode="after") - def _refusal_reason(self): + def _refusal_reason(self) -> Self: if (self.disposition == "refused") != (self.reason is not None): raise ValueError("only a refused admission requires a refusal reason") return self @@ -49,7 +49,7 @@ class BackendOperationAcknowledgementModel(OperationContractModel): reason: OperationRefusalReason | None = None @model_validator(mode="after") - def _refusal_reason(self): + def _refusal_reason(self) -> Self: if (self.disposition == "refused") != (self.reason is not None): raise ValueError("only a refused acknowledgement requires a refusal reason") return self @@ -79,9 +79,13 @@ class BackendOperationEffectsModel(OperationContractModel): external_fence: OperationArtifactReferenceModel | None = None @model_validator(mode="after") - def _evidence_boundary(self): + def _evidence_boundary(self) -> Self: if (self.effect != "unknown" or self.cessation_established or self.external_fence) and not self.evidence_refs: raise ValueError("known effects, cessation and external fencing require evidence") + self._validate_residual_state() + return self + + def _validate_residual_state(self) -> None: if bool(self.residual_scope) != (self.residual_state is not None): raise ValueError("residual scope and state must be reported together") if self.effect == "partial" and self.residual_state is None: @@ -90,7 +94,6 @@ def _evidence_boundary(self): raise ValueError("absent effects cannot carry residual changes") if self.residual_state and self.residual_state.contract_id != "runtime-snapshot-v1": raise ValueError("residual state must reference the native runtime snapshot contract") - return self class BackendOperationOutcomeModel(OperationContractModel): @@ -107,21 +110,24 @@ class BackendOperationOutcomeModel(OperationContractModel): result: OperationArtifactReferenceModel | None = None @model_validator(mode="after") - def _honest_outcome(self): + def _honest_outcome(self) -> Self: known = self.effects.effect != "unknown" and self.effects.cessation_established if self.proposed_state != OperationState.INDETERMINATE and not known: raise ValueError("unknown effects or unproved cessation require indeterminate outcome") if self.proposed_state == OperationState.SUCCEEDED: - if self.satisfaction != "satisfied" or not self.release_gates_satisfied or self.result is None: - raise ValueError("success requires complete satisfaction, result and release gates") - if self.effects.effect == "partial": - raise ValueError("partial effects cannot establish success") + self._validate_success() if self.proposed_state == OperationState.FAILED and self.satisfaction != "unsatisfied": raise ValueError("known failure requires established non-satisfaction") if self.cancellation_established != (self.proposed_state == OperationState.CANCELLED): raise ValueError("only an established cancellation may propose cancelled") return self + def _validate_success(self) -> None: + if self.satisfaction != "satisfied" or not self.release_gates_satisfied or self.result is None: + raise ValueError("success requires complete satisfaction, result and release gates") + if self.effects.effect == "partial": + raise ValueError("partial effects cannot establish success") + class BackendOperationReconciliationModel(OperationContractModel): """Observation for separately authorized resolution, with no replay instruction.""" diff --git a/implementations/python/packages/raes_contracts/contracts/backend_operation_schema.py b/implementations/python/packages/raes_contracts/contracts/backend_operation_schema.py index 009f34ca8..c539d26bf 100644 --- a/implementations/python/packages/raes_contracts/contracts/backend_operation_schema.py +++ b/implementations/python/packages/raes_contracts/contracts/backend_operation_schema.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing import Any + from .backend_operation import ( BackendOperationCapabilitiesModel, BackendOperationControlModel, @@ -11,7 +13,7 @@ from .schema_invariants import _add_raes_invariant -def backend_operation_schema_bundle(): +def backend_operation_schema_bundle() -> dict[str, dict[str, Any]]: models = { "backend-operation-request-v1": BackendOperationRequestModel, "backend-operation-capabilities-v1": BackendOperationCapabilitiesModel, diff --git a/implementations/python/packages/raes_contracts/contracts/backend_operation_validation.py b/implementations/python/packages/raes_contracts/contracts/backend_operation_validation.py index 723fccf9c..28f5c78a9 100644 --- a/implementations/python/packages/raes_contracts/contracts/backend_operation_validation.py +++ b/implementations/python/packages/raes_contracts/contracts/backend_operation_validation.py @@ -3,6 +3,7 @@ from __future__ import annotations from collections.abc import Sequence +from dataclasses import dataclass, field from ..canonical import canonical_json_digest from .backend_operation import ( @@ -14,6 +15,7 @@ BackendOperationAcknowledgementModel, BackendOperationAdmissionModel, BackendOperationControlDispositionModel, + BackendOperationMessage, BackendOperationOutcomeModel, BackendOperationReconciliationModel, BackendOperationResponseModel, @@ -53,7 +55,11 @@ def validate_backend_operation_response( raise ValueError("residual effects exceed the admitted resource scope") -def _validate_control(request, response, control): +def _validate_control( + request: BackendOperationRequestModel, + response: BackendOperationResponseModel, + control: BackendOperationControlModel | None, +) -> None: message = response.message if control is None or control.binding != request.binding: raise ValueError("control binding missing or mismatched") @@ -98,39 +104,60 @@ def validate_backend_operation_history( if len(responses) > 1024 or len(controls) > 256: raise ValueError("backend operation transcript exceeds its bound") - by_control = {} - for control in controls: - if control.control_id in by_control and by_control[control.control_id] != control: - raise ValueError("duplicate control identity changed its commitment") - by_control[control.control_id] = control - seen = {} - previous = 0 - terminal = False - acknowledged = False + by_control = _index_controls(controls) + history = _InvocationHistory() for response in responses: message = response.message control = by_control.get(message.control_id) if hasattr(message, "control_id") else None validate_backend_operation_response(request, response, control=control) - if response.sequence in seen: - if seen[response.sequence] != response: + history.accept(response) + + +def _index_controls(controls: Sequence[BackendOperationControlModel]) -> dict[str, BackendOperationControlModel]: + by_control: dict[str, BackendOperationControlModel] = {} + for control in controls: + if control.control_id in by_control and by_control[control.control_id] != control: + raise ValueError("duplicate control identity changed its commitment") + by_control[control.control_id] = control + return by_control + + +@dataclass +class _InvocationHistory: + """Transient transcript validation state; never persisted runtime authority.""" + + seen: dict[int, BackendOperationResponseModel] = field(default_factory=dict) + previous: int = 0 + terminal: bool = False + acknowledged: bool = False + + def accept(self, response: BackendOperationResponseModel) -> None: + if response.sequence in self.seen: + if self.seen[response.sequence] != response: raise ValueError("duplicate response sequence changed its content") - continue - if response.sequence <= previous: + return + if response.sequence <= self.previous: raise ValueError("response sequence is stale or unordered") - if terminal and message.kind not in {"control", "reconciliation"}: + self._advance(response.message) + self.seen[response.sequence] = response + self.previous = response.sequence + + def _advance(self, message: BackendOperationMessage) -> None: + if self.terminal and message.kind not in {"control", "reconciliation"}: raise ValueError("terminal evidence cannot be rewritten") if isinstance(message, BackendOperationAdmissionModel): - if acknowledged: + if self.acknowledged: raise ValueError("admission must precede invocation acknowledgement") - terminal = message.disposition == "refused" + self.terminal = message.disposition == "refused" if isinstance(message, BackendOperationAcknowledgementModel): - if acknowledged: + if self.acknowledged: raise ValueError("invocation cannot be acknowledged twice") - acknowledged = message.disposition == "accepted" - terminal = not acknowledged - if message.kind in {"progress", "outcome"} and not acknowledged: + self.acknowledged = message.disposition == "accepted" + self.terminal = not self.acknowledged + self._execution_evidence(message) + + def _execution_evidence(self, message: BackendOperationMessage) -> None: + if message.kind in {"progress", "outcome"} and not self.acknowledged: raise ValueError("execution evidence requires acknowledgement") if isinstance(message, BackendOperationOutcomeModel): - terminal = True - seen[response.sequence] = response - previous = response.sequence + self.terminal = True diff --git a/implementations/python/tests/test_formal_semantic_validation.py b/implementations/python/tests/test_formal_semantic_validation.py index 74ae55d61..cea64ee67 100644 --- a/implementations/python/tests/test_formal_semantic_validation.py +++ b/implementations/python/tests/test_formal_semantic_validation.py @@ -126,6 +126,7 @@ def test_atomic_release_index_validates_every_historical_bundle() -> None: "45.0.0", "46.0.0", "47.0.0", + "48.0.0", ] assert all(validate_release_bundle(REPO_ROOT, release) == [] for release in releases) @@ -134,10 +135,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"] == "47.0.0" + assert release.manifest["revision"] == "48.0.0" assert protocol["revision"] == "2.0.0" assert corpus["revision"] == "4.0.0" - assert snapshot["baseline"]["release_revision"] == "46.0.0" + assert snapshot["baseline"]["release_revision"] == "47.0.0" assert snapshot["deviations"] == [] assert validate_retest_bundle(REPO_ROOT, release, protocol, corpus, snapshot, analysis) == [] diff --git a/implementations/python/tests/test_issue_1360_backend_operations.py b/implementations/python/tests/test_issue_1360_backend_operations.py index 562e23bb1..ff8e31880 100644 --- a/implementations/python/tests/test_issue_1360_backend_operations.py +++ b/implementations/python/tests/test_issue_1360_backend_operations.py @@ -10,6 +10,7 @@ from jsonschema import ValidationError as SchemaValidationError from pydantic import ValidationError from raes_contracts import contracts + from tools.policy.requirement_governance import evaluate_requirement_governance ROOT = Path(__file__).resolve().parents[3] @@ -142,13 +143,18 @@ def get_traceability(self, requirement_id): def test_contextual_willingness_and_capability_are_both_required(): contracts.require_backend_operation_admission(request(), capabilities(), admission()) + operation_1 = request() + capability_report_2 = capabilities() + admission_report_3 = admission("refused") with pytest.raises(ValueError, match="refused"): - contracts.require_backend_operation_admission(request(), capabilities(), admission("refused")) + contracts.require_backend_operation_admission(operation_1, capability_report_2, admission_report_3) unsupported = capabilities().model_dump() unsupported["guarantees"] = [] unsupported = contracts.BackendOperationCapabilitiesModel.model_validate(unsupported) + operation_4 = request() + admission_report_5 = admission() with pytest.raises(ValueError): - contracts.require_backend_operation_admission(request(), unsupported, admission()) + contracts.require_backend_operation_admission(operation_4, unsupported, admission_report_5) @pytest.mark.parametrize( @@ -169,8 +175,9 @@ def test_individually_valid_foreign_response_is_rejected(field, value): raw = response({"kind": "acknowledgement", "disposition": "accepted", "reason": None}).model_dump() raw["binding"][field] = value foreign = contracts.BackendOperationResponseModel.model_validate(raw) + operation_6 = request() with pytest.raises(ValueError, match="binding"): - contracts.validate_backend_operation_response(request(), foreign) + contracts.validate_backend_operation_response(operation_6, foreign) @pytest.mark.parametrize("field", ["actor_id", "target_scope", "run_scope", "request_commitment"]) @@ -178,8 +185,9 @@ def test_original_admission_context_cannot_be_rebound(field): raw = admission().model_dump() raw["binding"]["context"][field] = "sha256:" + "d" * 64 if field == "request_commitment" else "other" foreign = contracts.BackendOperationResponseModel.model_validate(raw) + operation_7 = request() with pytest.raises(ValueError, match="binding"): - contracts.validate_backend_operation_response(request(), foreign) + contracts.validate_backend_operation_response(operation_7, foreign) def test_request_commitment_includes_guarantees_budget_and_artifact(): @@ -195,15 +203,17 @@ def test_request_commitment_includes_guarantees_budget_and_artifact(): assert contracts.backend_operation_request_digest(changed) != contracts.backend_operation_request_digest( original ) + admission_report_15 = admission() with pytest.raises(ValueError, match="commitment"): - contracts.validate_backend_operation_response(changed, admission()) + contracts.validate_backend_operation_response(changed, admission_report_15) @pytest.mark.parametrize("effect,ceased", [("unknown", False), ("unknown", True), ("absent", False)]) @pytest.mark.parametrize("state", ["succeeded", "failed", "cancelled"]) def test_unknown_effects_or_unproved_cessation_cannot_claim_known_terminal_outcome(effect, ceased, state): + outcome_payload_8 = outcome(state, effects=evidence(effect, ceased), cancellation_established=state == "cancelled") with pytest.raises(ValidationError): - response(outcome(state, effects=evidence(effect, ceased), cancellation_established=state == "cancelled")) + response(outcome_payload_8) def test_known_partial_cancellation_preserves_residual_state(): @@ -244,8 +254,9 @@ def test_duplicate_records_are_idempotent_but_changed_sequence_content_is_reject ack = response({"kind": "acknowledgement", "disposition": "accepted", "reason": None}) contracts.validate_backend_operation_history(request(), [ack, ack]) conflict = response({"kind": "acknowledgement", "disposition": "refused", "reason": "context-refused"}) + operation_9 = request() with pytest.raises(ValueError, match="sequence"): - contracts.validate_backend_operation_history(request(), [ack, conflict]) + contracts.validate_backend_operation_history(operation_9, [ack, conflict]) def test_uncertain_completion_and_reconciliation_do_not_rewrite_parent_outcome(): @@ -271,8 +282,10 @@ def test_uncertain_completion_and_reconciliation_do_not_rewrite_parent_outcome() 3, ) contracts.validate_backend_operation_history(request(), [ack, uncertain, observed], controls=[ctl]) + operation_10 = request() + reports_11 = [ack, uncertain, response(outcome(), 3)] with pytest.raises(ValueError, match="terminal"): - contracts.validate_backend_operation_history(request(), [ack, uncertain, response(outcome(), 3)]) + contracts.validate_backend_operation_history(operation_10, reports_11) @pytest.mark.parametrize( @@ -288,8 +301,9 @@ def test_budgets_reject_coercion_expiry_and_renewal(field, value): def test_closed_versioned_carriers_reject_unknown_fields_and_versions(): for mutation in [{"schema_version": "backend-operation-request/v2"}, {"metadata": {"retry": True}}]: + payload_16 = {**request_payload(), **mutation} with pytest.raises(ValidationError): - contracts.BackendOperationRequestModel.model_validate({**request_payload(), **mutation}) + contracts.BackendOperationRequestModel.model_validate(payload_16) def test_supervisor_identity_and_control_commitment_are_independent(): @@ -306,8 +320,9 @@ def test_supervisor_identity_and_control_commitment_are_independent(): "disposition": "accepted", } ) + operation_12 = request() with pytest.raises(ValueError, match="control"): - contracts.validate_backend_operation_response(request(), report, control=other) + contracts.validate_backend_operation_response(operation_12, report, control=other) def test_published_family_and_profile_are_consumable_without_runtime(): @@ -327,11 +342,14 @@ def test_published_family_and_profile_are_consumable_without_runtime(): schema = json.loads((ROOT / f"contracts/schemas/control-plane/{name}.json").read_text()) assert schema == bundle[name] Draft202012Validator(schema).validate(value.model_dump(mode="json")) + validator_17 = Draft202012Validator(schema) + payload_18 = {**value.model_dump(mode="json"), "metadata": {}} with pytest.raises(SchemaValidationError): - Draft202012Validator(schema).validate({**value.model_dump(mode="json"), "metadata": {}}) + validator_17.validate(payload_18) assert schema["x-raes-semantic-profile"]["required"] is True + provider_13 = object() with pytest.raises(ValueError, match="installed"): - require_operation_provider(object(), profile.required_contracts) + require_operation_provider(provider_13, profile.required_contracts) assert BackendOperationProvider is not None @@ -346,8 +364,9 @@ def test_published_family_and_profile_are_consumable_without_runtime(): ], ) def test_success_requires_full_validated_claim_not_just_observed_effects(changes): + outcome_payload_14 = outcome(**changes) with pytest.raises(ValidationError): - response(outcome(**changes)) + response(outcome_payload_14) def test_example_corpus_exercises_every_message_and_required_scenario(): diff --git a/implementations/python/tests/test_issue_1360_operation_rejections.py b/implementations/python/tests/test_issue_1360_operation_rejections.py index f2812d95a..a9173700a 100644 --- a/implementations/python/tests/test_issue_1360_operation_rejections.py +++ b/implementations/python/tests/test_issue_1360_operation_rejections.py @@ -21,16 +21,18 @@ def test_refused_admission_cannot_be_followed_by_dispatch(): refused = admission("refused") ack = response({"kind": "acknowledgement", "disposition": "accepted"}, 2) + operation_1 = request() with pytest.raises(ValueError, match="terminal"): - contracts.validate_backend_operation_history(request(), [refused, ack]) + contracts.validate_backend_operation_history(operation_1, [refused, ack]) @pytest.mark.parametrize("disposition", ["willing", "refused"]) def test_admission_cannot_reclassify_an_accepted_invocation(disposition): ack = response({"kind": "acknowledgement", "disposition": "accepted"}) late_admission = response(admission(disposition).message, 2) + operation_2 = request() with pytest.raises(ValueError, match="admission must precede"): - contracts.validate_backend_operation_history(request(), [ack, late_admission]) + contracts.validate_backend_operation_history(operation_2, [ack, late_admission]) @pytest.mark.parametrize( @@ -55,8 +57,9 @@ def test_budget_origin_is_a_bounded_real_calendar_instant(timestamp): ], ) def test_effect_claims_reject_missing_contradictory_or_coerced_evidence(changes): + payload_3 = {**evidence(), **changes} with pytest.raises(ValidationError): - contracts.BackendOperationEffectsModel.model_validate({**evidence(), **changes}) + contracts.BackendOperationEffectsModel.model_validate(payload_3) @pytest.mark.parametrize( @@ -95,13 +98,18 @@ def test_wrong_capability_identity_kind_and_revision_prevent_admission(field, va raw = capabilities().model_dump() raw[field] = value foreign = contracts.BackendOperationCapabilitiesModel.model_validate(raw) + operation_4 = request() + admission_report_5 = admission() with pytest.raises(ValueError): - contracts.require_backend_operation_admission(request(), foreign, admission()) + contracts.require_backend_operation_admission(operation_4, foreign, admission_report_5) def test_non_admission_message_cannot_supply_willingness(): + operation_6 = request() + capability_report_7 = capabilities() + response_report_8 = response(outcome()) with pytest.raises(ValueError, match="admission"): - contracts.require_backend_operation_admission(request(), capabilities(), response(outcome())) + contracts.require_backend_operation_admission(operation_6, capability_report_7, response_report_8) @pytest.mark.parametrize( @@ -122,8 +130,9 @@ def test_refusal_reasons_are_required_only_on_refusal(kind, disposition, reason) def test_failure_requires_known_non_satisfaction(): + outcome_payload_9 = outcome("failed") with pytest.raises(ValidationError, match="non-satisfaction"): - response(outcome("failed")) + response(outcome_payload_9) failed = response(outcome("failed", satisfaction="unsatisfied", release_gates_satisfied=False)) contracts.validate_backend_operation_response(request(), failed) @@ -138,15 +147,18 @@ def test_control_requires_original_binding_commitment_and_matching_action(): "effects": evidence(), } ) + operation_10 = request() with pytest.raises(ValueError, match="action"): - contracts.validate_backend_operation_response(request(), report, control=ctl) + contracts.validate_backend_operation_response(operation_10, report, control=ctl) + operation_11 = request() with pytest.raises(ValueError, match="control"): - contracts.validate_backend_operation_response(request(), report) + contracts.validate_backend_operation_response(operation_11, report) raw = ctl.model_dump() raw["request_digest"] = "sha256:" + "f" * 64 other = contracts.BackendOperationControlModel.model_validate(raw) + operation_12 = request() with pytest.raises(ValueError, match="commitment"): - contracts.validate_backend_operation_response(request(), report, control=other) + contracts.validate_backend_operation_response(operation_12, report, control=other) def test_transcript_rejects_changed_control_and_unordered_or_unacknowledged_records(): @@ -154,24 +166,34 @@ def test_transcript_rejects_changed_control_and_unordered_or_unacknowledged_reco raw = ctl.model_dump() raw["budget"]["remaining_ms"] = 800 changed = contracts.BackendOperationControlModel.model_validate(raw) + operation_13 = request() with pytest.raises(ValueError, match="control"): - contracts.validate_backend_operation_history(request(), [], controls=[ctl, changed]) + contracts.validate_backend_operation_history(operation_13, [], controls=[ctl, changed]) + operation_14 = request() + reports_15 = [response(outcome())] with pytest.raises(ValueError, match="acknowledgement"): - contracts.validate_backend_operation_history(request(), [response(outcome())]) + contracts.validate_backend_operation_history(operation_14, reports_15) ack = response({"kind": "acknowledgement", "disposition": "accepted"}, 2) + operation_16 = request() + reports_17 = [ack, admission()] with pytest.raises(ValueError, match="unordered"): - contracts.validate_backend_operation_history(request(), [ack, admission()]) + contracts.validate_backend_operation_history(operation_16, reports_17) + operation_18 = request() + reports_19 = [ack, response(ack.message, 3)] with pytest.raises(ValueError, match="twice"): - contracts.validate_backend_operation_history(request(), [ack, response(ack.message, 3)]) + contracts.validate_backend_operation_history(operation_18, reports_19) @pytest.mark.parametrize("field", ["responses", "controls"]) def test_transcript_size_is_bounded_before_traversal(field): + operation_20 = request() + reports_21 = [admission()] * (1025 if field == "responses" else 0) + reports_22 = [control()] * (257 if field == "controls" else 0) with pytest.raises(ValueError, match="bound"): contracts.validate_backend_operation_history( - request(), - [admission()] * (1025 if field == "responses" else 0), - controls=[control()] * (257 if field == "controls" else 0), + operation_20, + reports_21, + controls=reports_22, ) diff --git a/implementations/python/tests/test_issue_989_versioned_evidence.py b/implementations/python/tests/test_issue_989_versioned_evidence.py index eb3ee7ba1..0c16c1442 100644 --- a/implementations/python/tests/test_issue_989_versioned_evidence.py +++ b/implementations/python/tests/test_issue_989_versioned_evidence.py @@ -230,7 +230,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"] == "47.0.0" + assert release.manifest["revision"] == "48.0.0" original = _retest.replay_case def changed_result(root, case): @@ -283,7 +283,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"] == "46.0.0" + assert manifest["revision"] == "47.0.0" snapshot = deepcopy(snapshot) artifact = next(a for a in snapshot["artifacts"] if a["artifact_id"] == artifact_id) artifact["sha256"] = old_digest @@ -499,6 +499,7 @@ def test_no_capture_can_be_silently_dropped(monkeypatch, family, removed): "45.0.0", "46.0.0", "47.0.0", + "48.0.0", ] if family == "formal" else [ @@ -549,6 +550,7 @@ def test_no_capture_can_be_silently_dropped(monkeypatch, family, removed): "44.0.0", "45.0.0", "46.0.0", + "47.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 453a1dd3a..3c3f3bdf5 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"] == "46.0.0" + assert manifest["revision"] == "47.0.0" def test_historical_failures_name_the_revision_specific_documents() -> None: diff --git a/tools/check_specification_coverage.py b/tools/check_specification_coverage.py index 9d19cf2b7..1b71a6988 100644 --- a/tools/check_specification_coverage.py +++ b/tools/check_specification_coverage.py @@ -102,7 +102,7 @@ def _load_bundle_index(repo_root: Path) -> list[tuple[str, dict[str, object]]]: max_bytes=_MAX_FILE_BYTES, ) current_path = current_release_path(records) - if dict(records)[current_path].get("revision") != "46.0.0" or {record.get("revision") for _, record in records} != { + if dict(records)[current_path].get("revision") != "47.0.0" or {record.get("revision") for _, record in records} != { "1.0.0", "1.1.0", "2.0.0", @@ -150,8 +150,9 @@ def _load_bundle_index(repo_root: Path) -> list[tuple[str, dict[str, object]]]: "44.0.0", "45.0.0", "46.0.0", + "47.0.0", }: - raise ValueError("coverage evidence requires the explicit current 46.0.0 release and supported history") + raise ValueError("coverage evidence requires the explicit current 47.0.0 release and supported history") return records diff --git a/tools/formal_semantic_validation/_baseline.py b/tools/formal_semantic_validation/_baseline.py index 23dc1642e..2b9ad7986 100644 --- a/tools/formal_semantic_validation/_baseline.py +++ b/tools/formal_semantic_validation/_baseline.py @@ -76,6 +76,7 @@ "44.0.0", "45.0.0", "46.0.0", + "47.0.0", } ) _V3_CORPUS_REVISIONS = frozenset( @@ -224,7 +225,7 @@ def _selected_baseline_manifest( if baseline_revision in _V2_REVISIONS else "docs/research/formal-semantic-validation/protocol-v1.json" ) - if baseline_revision in {"42.0.0", "45.0.0", "46.0.0"}: + if baseline_revision in {"42.0.0", "45.0.0", "46.0.0", "47.0.0"}: expected_corpus_path = "docs/research/formal-semantic-validation/corpus/manifest-v4.json" elif baseline_revision in _V3_CORPUS_REVISIONS: expected_corpus_path = "docs/research/formal-semantic-validation/corpus/manifest-v3.json" diff --git a/tools/formal_semantic_validation/_loading.py b/tools/formal_semantic_validation/_loading.py index 3ca6e1d34..3d0f12001 100644 --- a/tools/formal_semantic_validation/_loading.py +++ b/tools/formal_semantic_validation/_loading.py @@ -77,6 +77,7 @@ def load_release_bundles(repo_root: Path = REPO_ROOT) -> list[EvidenceRelease]: "45.0.0", "46.0.0", "47.0.0", + "48.0.0", }: raise ValueError("formal evidence requires every supported historical and current release") releases: list[EvidenceRelease] = [] @@ -123,6 +124,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") != "47.0.0" or release.protocol.get("revision") != "2.0.0": - raise ValueError("the current formal evidence release must be the explicit 47.0.0 retest") + if release.manifest.get("revision") != "48.0.0" or release.protocol.get("revision") != "2.0.0": + raise ValueError("the current formal evidence release must be the explicit 48.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 d533292de..819789278 100644 --- a/tools/formal_semantic_validation/_release_revisions.py +++ b/tools/formal_semantic_validation/_release_revisions.py @@ -46,8 +46,9 @@ "44.0.0", "45.0.0", "46.0.0", + "47.0.0", } ) -_SUPPORTED_RETEST_REVISIONS = _HISTORICAL_RETEST_REVISIONS | {"47.0.0"} +_SUPPORTED_RETEST_REVISIONS = _HISTORICAL_RETEST_REVISIONS | {"48.0.0"} _SOURCE_BOUND_RETEST_REVISIONS = _SUPPORTED_RETEST_REVISIONS - {"3.0.0"} diff --git a/tools/formal_semantic_validation/_releases.py b/tools/formal_semantic_validation/_releases.py index 6bafd9f68..e8824e130 100644 --- a/tools/formal_semantic_validation/_releases.py +++ b/tools/formal_semantic_validation/_releases.py @@ -159,7 +159,7 @@ def validate_release_bundle(repo_root: Path, release: EvidenceRelease) -> list[P release.corpus, release.snapshot, release.analysis, - replay_current=manifest.get("revision") == "47.0.0", + replay_current=manifest.get("revision") == "48.0.0", ) ) else: @@ -244,7 +244,7 @@ def validate_retest_bundle( return [ _failure( "formal-validation-current-replay-required", - "only releases 3.0.0 through 46.0.0 can use integrated historical validation", + "only releases 3.0.0 through 47.0.0 can use integrated historical validation", snapshot_path, ) ] @@ -292,7 +292,7 @@ def validate_retest_bundle( } else "2.0.0" ) - if release_revision in {"42.0.0", "45.0.0", "46.0.0", "47.0.0"}: + if release_revision in {"42.0.0", "45.0.0", "46.0.0", "47.0.0", "48.0.0"}: expected_corpus_revision = "4.0.0" if protocol.get("revision") != "2.0.0" or corpus.get("revision") != expected_corpus_revision: failures.append( @@ -401,6 +401,7 @@ def _current_retest_source_failures( "45.0.0": "42.0.0", "46.0.0": "45.0.0", "47.0.0": "46.0.0", + "48.0.0": "47.0.0", }[release_revision] if not isinstance(baseline, Mapping) or baseline.get("release_revision") != expected_baseline: failures.append( diff --git a/tools/formal_semantic_validation/_retest.py b/tools/formal_semantic_validation/_retest.py index 17c73d8a3..066df45d3 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, 48)) +_SOURCE_STATE_REVISIONS = frozenset(f"{revision}.0.0" for revision in range(4, 49)) @dataclasses.dataclass(frozen=True) From 222b00001ad6830c76772e01168532105751fbb7 Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Fri, 25 Sep 2026 04:55:20 +0200 Subject: [PATCH 5/7] style: align operation test imports with project lint context --- .../python/tests/test_issue_1360_backend_operations.py | 1 - 1 file changed, 1 deletion(-) diff --git a/implementations/python/tests/test_issue_1360_backend_operations.py b/implementations/python/tests/test_issue_1360_backend_operations.py index ff8e31880..5d455eb2e 100644 --- a/implementations/python/tests/test_issue_1360_backend_operations.py +++ b/implementations/python/tests/test_issue_1360_backend_operations.py @@ -10,7 +10,6 @@ from jsonschema import ValidationError as SchemaValidationError from pydantic import ValidationError from raes_contracts import contracts - from tools.policy.requirement_governance import evaluate_requirement_governance ROOT = Path(__file__).resolve().parents[3] From bb75d733271a46a27c360943adb765a4310f52c4 Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Fri, 25 Sep 2026 07:35:00 +0200 Subject: [PATCH 6/7] Format formal evidence release list --- tools/formal_semantic_validation/_releases.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/formal_semantic_validation/_releases.py b/tools/formal_semantic_validation/_releases.py index 4359c7173..056444b73 100644 --- a/tools/formal_semantic_validation/_releases.py +++ b/tools/formal_semantic_validation/_releases.py @@ -292,7 +292,18 @@ def validate_retest_bundle( } else "2.0.0" ) - if release_revision in {"42.0.0", "45.0.0", "46.0.0", "47.0.0", "48.0.0", "49.0.0", "50.0.0", "51.0.0", "52.0.0", "53.0.0"}: + if release_revision in { + "42.0.0", + "45.0.0", + "46.0.0", + "47.0.0", + "48.0.0", + "49.0.0", + "50.0.0", + "51.0.0", + "52.0.0", + "53.0.0", + }: expected_corpus_revision = "4.0.0" if protocol.get("revision") != "2.0.0" or corpus.get("revision") != expected_corpus_revision: failures.append( From 8c42ce120743ea9401bffaa87180768df9c38360 Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Fri, 25 Sep 2026 07:52:55 +0200 Subject: [PATCH 7/7] Split formal evidence corpus revision selection --- tools/formal_semantic_validation/_releases.py | 73 ++++++++++--------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/tools/formal_semantic_validation/_releases.py b/tools/formal_semantic_validation/_releases.py index 056444b73..6512c6614 100644 --- a/tools/formal_semantic_validation/_releases.py +++ b/tools/formal_semantic_validation/_releases.py @@ -222,40 +222,7 @@ def validate_release_bundle(repo_root: Path, release: EvidenceRelease) -> list[P return failures -def validate_retest_bundle( - repo_root: Path, - release: EvidenceRelease, - protocol: dict[str, object], - corpus: dict[str, object], - snapshot: dict[str, object], - analysis: dict[str, object], - *, - replay_current: bool = True, -) -> list[PolicyFailure]: - """Validate the integrated issue-828 evidence release.""" - - failures: list[PolicyFailure] = [] - protocol_path = str(release.manifest.get("protocol_path")) - corpus_path = str(release.manifest.get("corpus_path")) - snapshot_path = str(release.manifest.get("snapshot_path")) - analysis_path = str(release.manifest.get("analysis_path")) - release_revision = release.manifest.get("revision") - if not replay_current and release_revision not in _HISTORICAL_RETEST_REVISIONS: - return [ - _failure( - "formal-validation-current-replay-required", - "only releases 3.0.0 through 52.0.0 can use integrated historical validation", - snapshot_path, - ) - ] - if release_revision not in _SUPPORTED_RETEST_REVISIONS: - failures.append( - _failure( - "formal-validation-retest-release", - "integrated retest requires an explicitly supported release revision", - release.manifest_path, - ) - ) +def _expected_corpus_revision(release_revision: object) -> str: expected_corpus_revision = ( "3.0.0" if release_revision @@ -305,6 +272,44 @@ def validate_retest_bundle( "53.0.0", }: expected_corpus_revision = "4.0.0" + return expected_corpus_revision + + +def validate_retest_bundle( + repo_root: Path, + release: EvidenceRelease, + protocol: dict[str, object], + corpus: dict[str, object], + snapshot: dict[str, object], + analysis: dict[str, object], + *, + replay_current: bool = True, +) -> list[PolicyFailure]: + """Validate the integrated issue-828 evidence release.""" + + failures: list[PolicyFailure] = [] + protocol_path = str(release.manifest.get("protocol_path")) + corpus_path = str(release.manifest.get("corpus_path")) + snapshot_path = str(release.manifest.get("snapshot_path")) + analysis_path = str(release.manifest.get("analysis_path")) + release_revision = release.manifest.get("revision") + if not replay_current and release_revision not in _HISTORICAL_RETEST_REVISIONS: + return [ + _failure( + "formal-validation-current-replay-required", + "only releases 3.0.0 through 52.0.0 can use integrated historical validation", + snapshot_path, + ) + ] + if release_revision not in _SUPPORTED_RETEST_REVISIONS: + failures.append( + _failure( + "formal-validation-retest-release", + "integrated retest requires an explicitly supported release revision", + release.manifest_path, + ) + ) + expected_corpus_revision = _expected_corpus_revision(release_revision) if protocol.get("revision") != "2.0.0" or corpus.get("revision") != expected_corpus_revision: failures.append( _failure(