Skip to content

v3.19.0

For most of its life the project called itself an orchestrator for CLI coding agents. That was the demo, not the product. What it actually ships — an audit chain, signed lineage, byte-identical run receipts, compliance packs — never asked whether the agent was writing code, reading logs or assembling evidence. Bernstein is the open-source governance layer for AI agents. Nothing in the code had to change for that sentence. Only the sentence did.

Records someone else can verify

Trust records reach TRACE 0.2 conformance (#4760). Delegation parent hashes and aggregate member digests are computed over the RFC 8785 canonical form of the parsed record, not over whatever bytes we happened to emit (#4799). On ASCII documents the two agreed exactly, which is why it took a unicode model ID to find. A conformance lane replays the vectors against a fixture run in CI (#3618), and an attestation from outside our own chain is now classified fail-closed (#4806).

Reviews resolve which conventions apply to a change before any reviewer runs, recording the matched globs and any unscoped paths under a resolution hash bound into the review receipt (#3752). The orchestrator anchors a content-addressed code-graph digest in the audit chain before it spawns, so a parallel schedule can be checked against the tree it was planned on (#3610).

Receipts for the runs nobody watched

A completed fan-out produces one signed object binding its spine heads, instead of N hashes bound to nothing (#3760, #3761). A run-graph receipt is checked by re-deriving it. Audit verification reads only the tiles that changed, so verifying a long chain stopped being a reason not to (#3831). Volunteer work grew a DSSE-signed consent receipt (#3866) and donor budgets that survive a restart (#3867).

The shipped front-page demo receipt now carries a non-empty lineage spine, written by the run itself rather than rebuilt afterwards (#3570).

Adapters that admit what they cannot do

An adapter declares its authentication basis in its contract (#3875). max_tokens is part of the enforced sampling surface: an adapter that cannot honour it refuses the spawn instead of dropping it quietly (#3586). Onboarding records a successful smoke invocation as a replayable golden transcript and checks three held-out invocations against the same CLI; a failed run stays an explicit failure rather than being skipped (#3764). New this release: a HolmesGPT adapter that binds an investigation's data sources to its conclusion (#3123), and a deterministic gitleaks scanner adapter (#4838).

New commands

  • bernstein gc cas — mark-and-sweep for the content-addressed store. Referenced digests are collected from the durable roots (write-ahead log, snapshots, audit seals, lineage records, backlog), so a reachable blob survives regardless of age. --days, --dry-run, --workdir; every run writes a prune receipt (#4674).
  • bernstein volunteer hub — a standalone app exposing enroll, claim, heartbeat, submit and release over the volunteer lease store (#4037).
  • bernstein pool and bernstein limits pool are separate on purpose and neither shadows the other: pool governs named sandbox environments, limits pool governs lease-backed admission slots (#3138).

The suite stopped lying

A test_*.py module that collects zero items now fails CI (#4834), and so does a touched module that loses cases it used to collect (#4873). Both gates exist because we shipped green shards that ran nothing, twice. Shards are balanced by committed timings rather than by filename (#4840), and 134 pyright excludes that matched nothing on disk are gone (#4864). A task that falls behind the rest of its cohort is now reported as one, under StallReason.COHORT_LAGGARD (#3605).

Upgrading

Trust records written before this release whose fields contain non-ASCII characters carry parent and member digests an RFC 8785 verifier disagrees with. Re-emit them, or pin the reader to the version that wrote them.

CheckRunClient no longer accepts installation_id. It stored the value and never used it — authentication is delegated to the gh CLI — and a parameter that looks load-bearing but is not had already misled one caller. Drop the argument; nothing else changes (#4845).

The root .env.example that docker-compose.yaml has always told you to copy is now actually tracked. .gitignore matched it via .env.* and dropped it silently on git add (#4723).

The wheel no longer ships the GUI source map. Packaged GUI assets go from 5.0 MB to 1.1 MB.

Contributors

  • Sarvagya Sharma — the zero-collection guard (#4858) and its sibling that fails a touched module which loses cases (#4885), duration-balanced shards (#4853), versioned key schemes in stored gateway fixtures (#4869), opt-in task-tier classification at dispatch (#4875), a pinned pubkey compared as committed bytes (#4841), and 134 pyright excludes that matched nothing (#4865).
  • Vaibhav Srivastava — a cordon that survives a re-registration because it is operator intent (#4863), REST re-registration keyed on name and URL (#4819), plan templates resolved through the package (#4880), the 4.1 MB source map out of the wheel (#4881), the dead second run loop deleted (#4883), WIP commits described by what they changed (#4773), and a cost-cache test no longer at the mercy of filesystem mtime granularity (#4754).
  • Chirag Honnyal — JCS canonicalisation for trust-record digests (#4814), the agent-card keystore's Windows mode-bit check (#4770), and uv run subprocess isolation in tests (#4851).
  • Abishek N — sorted manifest entries with duplicate paths rejected (#4713), extractors for the nearest AGENTS.md and flaky tests (#4714), and dead trigger_sources modules removed (#4716).
  • mikemikimike — tests mapped from green co-change history (#4733), the co-change neighbours extractor (#4737), and hardened timeout-extension timing (#4719).
  • Tanish Bhandari — repeated worker action loops detected (#4843) and replay worker failures surfaced (#4708).
  • Prateek Gupta — a tracked .env.example with a guard test (#4730) and the SOC 2 export subprocess environment repaired (#4813).
  • Saketh Bandi — the deterministic gitleaks scanner adapter (#4838).
  • ADITYA V J — the loop detector wired to file-overlap wait checks (#4706).
  • Aravind S — the tool-call gate called from the dispatch point (#4844).
  • 0xddneto — foreign attestations classified fail-closed (#4806).
  • pttydou — persistent donor budgets (#4738).
  • GOLDMEMARY — the max_tokens capability gate enforced (#4892).
  • victorwon2001 — a probe-drafted profile that records its transcript (#4884).
  • Rehan30g — the unused installation id dropped from CheckRunClient (#4845).
  • Columbus Labs — the pymdown-extensions pin (#4769).