v12.5 — nothing runs on a timer, and now nothing says otherwise
Full release tree at commit fb40b85fa26202714898c62f8b4160653d3dc8f2 of the source repository, published by the product's own gh_commit reading each blob straight out of its own git store. MANIFEST.txt lists every file and its digest. 104 files. Fourteen paths move; the other 90 are byte identical to 12.4.
12.0 deleted the runners. What survived was the vocabulary — and in four places the vocabulary was making a promise the code could not keep.
The console told you your work was somewhere it was not
Every strain's status light in the Flow Hood rendered queued work as "3 on the bus". There is no bus. It now reads "3 queued", which is what that number has always actually been: work_items with status pending.
Two system prompts were false rather than stale
Every strain in every install was sent them.
- The operator digest printed
BUS: gemini-only. Sweeper tick PAUSED — stalled work parks, it does not escalate to Claude.There is no sweeper to pause, and paused invites an agent to ask for it to be resumed. - The per-strain digest printed
Your twin runs your items as you, on GCP billing.Nothing runs anyone's items.
Both now say DISPATCH, and both say plainly that nothing runs unattended. The law constant beside them said BUS LAW: there is no bus; a law that has to name the thing it denies keeps the thing alive in the reader's head, so it now reads DISPATCH LAW: nothing in this install runs unattended.
The cost page warned you about unattended spend from a component that does not exist
wiki/pages/model-config.md, under Cost: "Chat is per-turn and interactive. The work-item bus is not: it runs queued items without you watching. Turn it on knowing that."
That is the page a person reads before deciding what to switch on. It now says the true thing, which is also the reassuring one: chat is the only thing that spends, and there is no unattended spend to turn on.
A shipped API field named the deleted mechanism
/api/flow returned bus per agent and per feed row, derived from journal rows only the runners ever wrote — so on any install it is permanently "unknown". Renamed to model, which is what it holds. Verified safe before renaming, not after: a grep for \.bus\b|\bbus: across all 55 files of control-plane/ returns eight hits and every one is in index.ts. No consumer changes.
The one thing deliberately not removed
The cloudscheduler API. install.sh enables it and step 2/10 grants admin on it, while the rationale comment beside it named two runner deploy scripts that no longer exist — which reads as an instruction to drop the API. Dropping it breaks installs. The comment now says that in as many words, alongside the two facts that settle it: install.sh creates no scheduler job itself, and a gate executor driven by a scheduled tick needs the API to exist.
How this is enforced from here
The release build now cuts the tree and greps the emitted bytes — what a downloader actually gets — for the whole vocabulary, and refuses to build on a single hit. It proves the pattern can still match before it judges the tree (a four-line negative control), and its one allowance — an upstream MCP SDK option bag quoted verbatim in a comment — asserts it still matches, so a dead allowance fails the build rather than sitting there as a standing hole.
This is not decoration. A grep of the source reported index.ts clean while it carried twenty hits, because the pattern asked for "event bus" and not "the bus". Four of the ten the gate caught live in files that do not exist in the source repository at all — README's paragraphs are emitted from string literals in the generator. The emitted tree is the only honest subject.
Still in the tree, and this release does not pretend otherwise
The fifteen /api/webauthn/* routes and control-plane/src/locked.html. Removing them is a separate commit for a real reason: gen.py's REQUIRED list names locked.html and refuses the cut without it, and a second gate cross-checks every pcHtml() argument against the emitted tree, so the file, its loader and the manifest entry have to move together. The passkey requirement was already gone in 12.4; what remains is dead surface, not a live gate.
Checks
Cut deterministically — gen.py run twice into separate directories, diff -r reports zero. Route audit: 88 live routes, none unrecorded, none vanished, 17 known public, no new unguarded route. Blob audit clean over 35 files. check-apis, check-python-names and check-no-embedded-assets all green against the emitted tree, not the source.
Apache-2.0. Your project, your bill, your key.