Synthe

Anatomy of a handoff

One handoff, from draft to ledger. Scroll through the five moments that matter, with the exact packet beside each one.

Step 1 · Draft

The sender writes it down

Alice declares who she is, who this is for, what she plans to do, and what it may cost. No free-form prose: the plan is a list of named actions on named tools, inside a budget.

If a field is missing, the checker stops here with missing_field:purpose and never touches a key.

{
  "from": "alice",
  "to": "bob",
  "purpose": "Verify the M-1 verdict pack",
  "planned_actions": [
    {"name": "read_rules", "tool": "read_repo"}
  ],
  "authority": {
    "budget": {"tokens": 50000,
               "usd": 2.0, "minutes": 30}
  }
}
Step 2 · Pin

Evidence gets pinned

Every file the handoff depends on is hashed with SHA-256 and the hash is written into the packet. If the file changes later, the hash will not match.

Verbatim quotes are pinned word for word. A paraphrase fails with evidence_not_verbatim.

{
  "acceptance": {
    "evidence": [{
      "kind": "verbatim_quote",
      "ref": "rules/M-1.md#m1-u-12",
      "sha256": "3cfde1…9b72"
    }]
  },
  "inputs": {
    "artifact_refs": [{
      "path": "context/brief.md",
      "sha256": "0f1e2d…0011"
    }]
  }
}
Step 3 · Sign

The sender signs

Alice signs the canonical bytes of the handoff with her Ed25519 key. The signed bytes start with the domain tag synthe/handoff-signature/v1, so a signature can never be replayed as something else.

Any edit after this moment breaks the signature: signature_invalid.

{
  "handoff": { … },
  "signature": {
    "alg": "Ed25519",
    "signer": "alice",
    "kid": "2026-10-01",
    "sig": "n4U8…9qZz"
  }
}
Step 4 · Check

The receiver checks, in order

Bob's checker runs seven checks in a fixed order: structure, identity and signature, duplicates, freshness, authority, artifacts, evidence. A broken structure stops it at once. After that it reports every problem it finds, and the first reason names the earliest broken link.

Approvals are verified too: each one is signed over this handoff's idempotency key, sender and receiver, so it can't be reused on another handoff.

$ python3 src/handoff_check.py \
    signed.json --registry registry.json \
    --workspace . --ledger ledger.json

ACCEPT claim recorded
# or, for example:
REJECT blocked: approval_missing
Step 5 · Record

The ledger remembers

On ACCEPT, the idempotency key is recorded as a claim. The same handoff can never be claimed twice, even across restarts: a second claim is refused with idempotency_key_reserved while the work runs, and duplicate_idempotency_key once it's done.

When the work is real, the claim flips to COMPLETED. That is the whole trick: check once, record it, never twice.

{
  "cadros:verdict-pack:m1-os-pl:rev-7": {
    "state": "COMPLETED",
    "handoff_id": "h-0001",
    "trace_id": "trace-cadros-2026-09-30-001",
    "completed_at": "2026-10-01T…Z"
  }
}

That is the whole checker: a typed packet, pinned evidence, a signature, seven checks, and a ledger. With the commit broker there is one more moment: when Bob is ready to act, Synthe checks all of this again, performs the action itself, and signs a receipt. Race two agents to see it, or try each moment yourself: sign a packet, attack one, or break a log.