v3.17.1¶
A patch release about one thing: a container run that starts from an issue number and is still alive an hour later.
Agents stopped dying¶
The heartbeat was refreshed by a shell loop pasted into the agent's own prompt. A model that ignored the block was killed for ignoring it. The worker writes it now, where the orchestrator reads it (#4330).
Four subsystems read that number. The recycler and the escalation ladder disagreed about the same agent, and the harsher one won (#4314). The stalled-manager detector went by wall-clock runtime alone, ignoring the liveness verdict from the same tick (#4338).
A dead agent's uncommitted work survives: the orphan path built a request body httpx could not encode, and the error killed the tick before the commit ran (#4345).
Runs recover on their own¶
A run with a high error rate blocked every new spawn wave, which is also how it stayed at a high error rate; the gate waits for three observations now (#4336). Agent process deaths counted as task failures (#4310). A failed planning task's retry raced a sibling that had already done the same decomposition (#4309).
The gate graded the wrong tree¶
Agents commit in their own worktree, and the merge back waits for the gate — so the gate graded a checkout missing the work under review. A task whose acceptance signal named a file it had just written could never pass. It had done this for as long as the gate has existed. The verdict is computed on the merged result now (#4367).
The task graph¶
An inferred file-overlap edge could contradict an explicit depends_on and fabricate a two-node cycle, after which topological_order returned nothing and every task read as blocked (#4366). A declared cycle no longer wedges the scheduler either (#4299).
PostgreSQL¶
Five bugs, all in the code that claims a task: two ignored the claiming role, one raised on a parameter the store did not accept, one queried a tenant column the schema never created, and create() raised ImportError (#4323, #4325, #4328, #4332, #4333).
Upgrade note: tasks written before this release carry no recorded tenant and land in the default scope; on a multi-tenant install the original scope is not recoverable.
Models and transport¶
Retry escalation replaced the model an operator pinned with a hard-coded Claude tier name (#4274). A model: in bernstein.yaml or --model now suppresses model escalation on retry; effort still escalates. An agent that exits without spending a token no longer spends the retry budget (#4275).
The MCP bridge pointed at a module with no __main__ guard: it imported, exited 0, and never answered the handshake. Every agent reported the bridge as disconnected and nobody read the init event (#4313, #4315).
Also¶
The manager prompt never showed how to set depends_on, so QA started before the module it tested existed (#4311). The PR a run opens no longer describes a run it cannot find (#4349). Adapters declare which channel carries system_addendum (#4256). On a TTY, bernstein run says it is waiting for the first agent (#4257).
Soundtrack: https://suno.com/s/sQ51WglS4Qzj9eIN