Search Brigade

Search Brigade pages and docs.

[ RELEASE ]

Brigade 0.21.0: receipts with a chain of custody

v0.21.0

Published July 8, 2026 · Escoffier Labs

This post bundles the 0.20.0 and 0.21.0 release cuts into one. The first wave gave receipts a chain of custody, the second wave built on top of it the same week, and the two read better as a single story than as two posts three days apart.

A receipt can now prove itself

Brigade’s pitch for receipts has always been “a verified exit code, not an opinion.” Until now that exit code lived in a plain JSON file that any process with filesystem access could rewrite. 0.21.0 closes that in three layers.

Runbooks get verified binary pins. A runbook can pin each step’s binary by sha256, runbook plan shows pin status without executing anything, and runbook run refuses on a mismatch unless you pass --allow-pin-mismatch, in which case the override is recorded loudly in the receipt. brigade runbook pin <runbook.json> writes pins from the binaries you have right now, so adopting a known-good state is one command.

Receipts get digests. Verify, runbook, and outcome artifacts carry a sha256 block binding the receipt payload and every referenced log file, and the outcome ledger is hash-chained so an edited or deleted middle record breaks visibly. brigade receipts verify walks all of it and reports OK, MISMATCH, MISSING, or legacy. Old artifacts report as legacy, never as failures.

And receipts can be signed. brigade receipts keygen writes a local 0600 key, after which receipts carry an HMAC-SHA256 signature over their digest. Hand-editing a signed receipt flips receipts verify to MISMATCH with a nonzero exit. Without a key, receipts are byte-identical to before.

Runs record what they did to the code graph

A verify run or brigade run now snapshots the target’s GraphTrail database before starting, re-syncs and diffs after, and attaches a compact code_graph_delta to the receipt: symbols changed, edges added and removed, with the full diff as a digest-covered graph-delta.json sidecar. The snapshots are WAL-safe SQLite backups, deleted after the diff with their sha256s kept in the receipt, so the inputs stay content-addressed without eating disk. The summary reports raw edge counts and line-insensitive ones side by side, because GraphTrail’s edge identity includes the call line and a pure line shift would otherwise read as churn.

The proof case during development: a verify run whose only command wrote one new Python file produced added_nodes=1, changed_symbols=['probe_fn'] in its receipt, and the sidecar verified clean.

Evidence flows out, then back in

brigade receipts export miseledger turns receipts into miseledger.adapter.v1 JSONL, with each item’s content hash reusing the receipt digest. MiseLedger’s identity model dedupes re-imports natively: the first export inserted 91 receipts, the second inserted 0. Receipts carry git provenance now (head, branch, dirty count, inside the digest), and the export emits the commit URL as a link. --new-only adds a cursor for cheap reruns, --import pipes the batch straight into MiseLedger, and a zero-item export skips the import subprocess entirely, which matters when one import invocation against a 13 GB archive costs about 2 minutes regardless of input size.

The return path is new in the second wave. brigade run can attach an evidence brief: recent verified results for the target repo pulled back out of MiseLedger, capped at 2000 bytes, always framed as untrusted evidence rather than instructions, and recorded in run.json like the other briefs. A run now starts knowing what previous runs on that repo verifiably changed. brigade work import context --from-miseledger '<query>' does the same fetch on demand.

The outcome ledger gets structure-aware

Captured outcomes copy the receipt’s graph delta into the hash-chained record, and outcome rank shows graph: N changing / M no-op per subject. Capture also takes --run-receipt now, because verify runs execute tests and rarely change code, while run receipts are where workers actually edit. The first run-receipt capture in the ledger recorded changed_symbols=19, edge_churn=23 for the run that built the feature.

Runs with a code-graph brief also get a context eval: did the brief name the files the run actually touched. hits, missed, and a brief_hit_rate, computed from artifacts the run already writes. No model in the loop, and no eval at all when nothing changed.

Also in 0.21.0

The workflow scanner mines run artifacts for command sequences operators keep repeating and proposes runbooks from them, pin stubs included. brigade run --detach gets live watch and steer/interrupt verbs. content-guard is vendored as brigade guard, so brigade scrub works without a separate checkout. Run receipts are written atomically, closing a read race that CI caught twice in one day. Friction imports stopped duplicating on re-import.

Every PR in this release was verified through the receipt pipeline it ships. The ledger also scored one -1 along the way, against a verify run invoked without the repo’s PYTHONPATH quirk. The ratchet does not care whose mistake it was.

Try Brigade

One reviewed source for the memory, tools, and MCP your AI coding agents share, merged into each tool's native config with a review gate and a receipt for every change. Local files, no daemon, no lock-in.

Quickstart · GitHub · All posts