policy.decide is a pure function so the phase-0 scenario fixtures can be fed to it verbatim. Those seven decisions survived three-reviewer scrutiny, so they are the contract rather than a fresh set of rules, and the test asserts against expected_policy.decision directly. Order inside the policy matters. Transport doubt and staleness invalidate the evidence itself, so they are answered before anything is inferred from it; a blocked agent is waiting for a human and can never be completed; attribution including the execution anchor comes before quiescence, because idle is not evidence of finishing when a session is reused; and a report must be finalized, never merely paused, since a debounce is a candidate filter and not an authority. The shadow runner is never handed the engine, so it has no route to a write. That is the structural half of P2A-03. The measured half hashes every file under the registry directory around a full run and asserts it is unchanged, which is a stronger claim than checking a status field. Adds the five scenarios P2A-04 requires: a raced double dispatch, a reused attempt with no anchor, a mid-write report, an unknown status, and a pane restarted mid-flight. They pass phase 0's own fixture validator, which is what keeps them honest. The phase-0 test that pinned exactly seven scenarios now requires the seven to still exist rather than forbidding growth. Also pins the two phase 1 handoffs as dormant: nothing here spawns a daemon, so preexec_fn stays unreachable, and nothing calls a frozen shell helper. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UrDNJkHmm18uu7n7JwV5Qd
63 lines
1.8 KiB
JSON
63 lines
1.8 KiB
JSON
{
|
|
"schema_version": "1.0.0",
|
|
"scenario_id": "race_double_dispatch",
|
|
"backend": "backend_agnostic",
|
|
"provenance": "simulated",
|
|
"description": "Two dispatches raced; the observed signal carries the previous process generation. The stale attempt must not decide anything.",
|
|
"dispatch_context": {
|
|
"job_id": "test-job-race-01",
|
|
"attempt_id": 2,
|
|
"agent_session_uuid": "7d5700d0-bab1-4f65-9665-6b887396a9a6",
|
|
"pane_process_generation": "w2X:p1:1234:2026-09-06T00:00:00Z",
|
|
"dispatch_ack": true,
|
|
"execution_anchor_observed": true
|
|
},
|
|
"timeline": [
|
|
{
|
|
"collector_clock_id": "CLOCK_MONOTONIC",
|
|
"relative_ms": 0,
|
|
"source_kind": "event",
|
|
"source_provenance": "simulated",
|
|
"payload": {
|
|
"event": "started",
|
|
"job_id": "test-job-finalized-01"
|
|
}
|
|
},
|
|
{
|
|
"collector_clock_id": "CLOCK_MONOTONIC",
|
|
"relative_ms": 5000,
|
|
"source_kind": "filesystem",
|
|
"source_provenance": "simulated",
|
|
"payload": {
|
|
"report_manifest": {
|
|
"report_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
|
"attempt_id": 1,
|
|
"finalized": true
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"collector_clock_id": "CLOCK_MONOTONIC",
|
|
"relative_ms": 6000,
|
|
"source_kind": "herdr",
|
|
"source_provenance": "simulated",
|
|
"payload": {
|
|
"agent_status": "idle",
|
|
"interactive_ready": true,
|
|
"pane_process_generation": "w2X:p9:9999:2026-09-06T00:00:00Z"
|
|
}
|
|
}
|
|
],
|
|
"filesystem": {
|
|
"report_path": ".mam/jobs/test-job-finalized-01/report-final.md",
|
|
"exists": true,
|
|
"manifest_committed": true,
|
|
"hash_verified": true
|
|
},
|
|
"expected_policy": {
|
|
"decision": "reject_stale",
|
|
"reason": "signal belongs to a superseded process generation",
|
|
"policy_version": "2.0.0"
|
|
}
|
|
}
|