v3.18.0¶
A release cut from watching unattended runs: what they merge, what they refuse, and how they account for themselves afterwards.
The run accounts for itself¶
Asking what came of a batch of runs meant reading .sdd/ by hand once the orchestrator had exited. bernstein runs report projects the work ledger into one row per finished run — pr-opened, gate-failed, no-changes, infra-error or wedged — each carrying the line of evidence it was classified from (#4465).
Pull requests are described from the change, not from the session. The title names the commit that changed the most under src/, skipping upkeep; the body is composed from the issue's problem statement, the touched files and the gates that ran, and carries a Provenance block the review-receipt machinery verifies against the diff (#4484).
Journal payload hashing excludes the wall-clock envelope by design, so ts and elapsed_s on stored rows are not covered by chain verification — and nothing said so. replay --verify and the receipt manifest now name the unauthenticated field set, machine-readably (#4209).
Plan approval binds to the rendering the reviewer saw: a plan carries the SHA-256 digest of its deterministic rendering, and approve or reject answers 409 when the stored plan no longer matches it (#3839).
Gates that refuse¶
Reap-and-merge landed an agent's branch without running the configured quality gates. They now run on the still-alive worktree before the merge commit; a blocking failure — or a gate runner that errors — leaves the branch unmerged and records the refusal (#4393).
A merge-gate failure gets one bounded repair attempt seeded with the exact failure output, then falls back to the existing handling; no second attempt either way. Off switch: gate_repair_enabled (#4463).
A run used to pin its overrides into the tracked bernstein.yaml, so an agent that committed with a staged tree proposed rewriting the repository's configuration for everyone. Overrides now resolve from an untracked overlay merged at load time, and a new required run_config gate refuses any diff touching a run-configuration path (#4485).
agent_test_mutation is in VALID_GATE_NAMES, so a seed naming it parses instead of failing; a structural test keeps every default gate spec listed (#4488).
Keys that stay apart¶
Installing an Agent Plugins directory containment-checked the manifest's skills field but followed whatever the entries under it pointed at: a skill directory, a bucket or a nested file symlinked out of the pack was copied into the install scope. Every walked path now has to resolve inside the pack; an escaping skill directory is skipped and reported, an escaping file refuses the skill's install (#4448).
Every HMAC-chained store signed with the same raw key. New audit entries carry scheme v2 — an HKDF-SHA256 per-store key and a domain-tagged preimage — resolved in one place, so the log verifier, the local record check and the startup guard reach the same verdict. v1 chains verify unchanged; an unknown scheme fails hard everywhere (#4212).
Also¶
A board carrying a dependency cycle drains instead of wedging (#4287). The legacy /dashboard route is gone; bernstein dashboard points at bernstein gui serve (#4395). The watchdog no longer restarts a run that already finished (#4445). The nightly dependency audit is green again on pip 26.2.1. A release-notes entry can ship as its own fragment file instead of a line in the shared page, so parallel PRs stop colliding in the merge queue (#4474).
Contributors¶
- Chirag Honnyal — the gate-name fix that lets a seed naming
agent_test_mutationparse (#4493), the cycle-forming dependency rejected before persistence rather than after (#4431), the legacy/dashboardroute removal (#4430), quality gates running in reap-and-merge before an agent branch lands (#4429), and the staleness-clock reset for the curated context files (#4477). - Louis20060723 — Agent Plugins directory layout in
skills install, including the containment walk that refuses a skill escaping its pack (#4448). - Aditya Pathak — the mypy configuration and its preview follow-up (#4434, #4432).
- Vaibhav Srivastava — the CI canary proposal branch now builds on the fetched default branch, not on whatever the runner had checked out (#4497).