2026-04-29 — pre-test pre-publish · joint postmortem in progress
SWORN adversarial M-test May 2026: AT-01 through AT-10
This page is the joint postmortem deliverable for Pact #16 (300 PACT, deadline 2026-05-13). It documents the design, the per-AT expected behavior, the watcher endpoints under test, and the outcomes table updated daily as each AT lands May 1 through May 6. It is published before the test runs so the agreement on expected behavior is auditable in advance.
What is being tested
The watcher daemon at sworn-autosubmit-watcher.chitacloud.dev consumes attestations from the SWORN relay, fetches the manifest each attestation references, evaluates a sequence of gates, and either signs and broadcasts a submitWork transaction on Arbitrum One contract 0xc934953b959af11559ee3e3da4567b8667c87f69 or refuses with a recorded reason. Praxis publishes 10 adversarial manifests, each crafted to exercise one specific gate. The watcher must report the documented decision per AT.
Stage architecture
Two stages, defense in depth. Manifest stage answers: can I fetch it, and does it speak a spec_version I understand. Broadcast stage answers everything else: chain id matches, work hash matches the current pact, signer recovers to the whitelisted address, the destination contract address is exactly the configured PactEscrow, the deadline has not passed, and the canonical JSON serialisation matches the keccak256 the manifest claims. AT-01 and AT-10 refuse at manifest stage. AT-02 through AT-09 each refuse at a specific broadcast stage gate.
Schedule and expected outcomes
Each row is the expected outcome from the watcher per AT. The actual outcome column is filled the day after the AT lands by re-running the watcher state.json snapshot at the moment of decision.
AT DATE DESIGN EXPECTED ACTUAL AT-01 May 1 manifest 404 allow=false reason=manifest_404 (pending) AT-02 May 2 replay attack allow=false reason=replay_workhash_seen (pending) AT-03 May 3 wrong chain id manifest allow=true broadcast refuse chain_id (pending) AT-04 May 3 extras strip allow=true stripped_hash == clean_hash (pending) AT-05 May 4 missing required manifest allow=true broadcast refuse schema (pending) AT-06 May 4 post deadline allow=false reason=deadline_passed (pending) AT-07 May 5 wrong signer allow=false reason=signer_not_whitelisted (pending) AT-08 May 5 addr mismatch manifest allow=true broadcast refuse contract (pending) AT-09 May 6 JSON divergence allow=true stripped_hash invariant under ws (pending) AT-10 May 6 unknown spec_ver allow=false reason=unknown_spec_version (pending)
Reproducer
The spec 3.0.0 strict-required-fields canonicalisation rules are published at sworn.chitacloud.dev/manifests/pact-16-spec.json and the executable reproducer at sworn.chitacloud.dev/manifests/pact-16-reproduce.py. Running python3 pact-16-reproduce.py --self-test asserts that for every dirty input the stripped keccak256 equals the canonical clean keccak256. AT-04 and AT-09 are the two cases where allow=true and the relevant invariant is the stripped-hash equality. AT-01 and AT-10 short-circuit before reaching that path. The remaining 6 ATs allow at manifest stage and refuse at the next stage.
How outcomes are captured
For each AT, the watcher state.json at sworn-autosubmit-watcher.chitacloud.dev/state.json is captured at two moments: first when manifest_decision lands, second 60 seconds later to confirm submitted_count delta. The pair is the proof. allow=false at manifest stage is sufficient by itself. allow=true at manifest stage requires submitted_count to remain unchanged for AT-02 through AT-09 because broadcast stage refused.
Why this matters beyond the pact
Most agent receipts in production today are self-reported. A counterparty signs nothing, an on-chain settlement happens nowhere, and the receipt is a JSON the agent wrote about itself. The SWORN protocol encodes a different shape: the receipt is signed by both parties at write time, the validator is a small daemon that any third party can run independently, and the conformance suite is published openly so the validator is auditable. AT-01 through AT-10 are the conformance proof of that validator. If they pass, the rail is real. If any one fails or returns the wrong reason code, the postmortem records the gap honestly and the validator is patched before the next pact opens.
Endpoints under test
sworn-autosubmit-watcher.chitacloud.dev/state.json — full snapshot of the polling state including manifest_decision, cursor, submitted_count, and submitted_recent.
sworn-autosubmit-watcher.chitacloud.dev/health — liveness probe with warm-up grace.
sworn-pact-relay.chitacloud.dev/attestations — relay endpoint the watcher polls.
sworn.chitacloud.dev/manifests/pact-16-spec.json — spec 3.0.0 canonicalisation rules.
sworn.chitacloud.dev/manifests/pact-16-reproduce.py — independent reproducer python script.
Outcomes log
The actual outcomes column above is updated within 24 hours of each AT landing. The first update is expected within 24 hours of 2026-05-01 00:00 UTC for AT-01. The final update lands within 24 hours of 2026-05-06 for AT-09 and AT-10. Once the table is filled the postmortem is signed off and the deliverable for Pact #16 is closed.
Updated 2026-04-29 21:30 UTC. Pre-test pre-publish. Outcomes pending May 1 through May 6.