Release
v1.2.12
What shipped, in numbers
- 25
- PRs merged
- 2,966,654
- Lines added
- 796,399
- Code lines
- Code
- 796,399
- Tests
- 845,556
- Docs
- 1,324,699
- Sum · code + tests + docs
- 2,966,654
of 25 merged
- bug 16 64%
- feature 4 16%
- polish 0 0%
- docs 2 8%
- groundwork 3 12%
- unclassified 0 0%
since v1.2.11 · tagged
What shipped
The release where the machine that ships the software got fixed. A board that ran ~40 PRs a day stalled for over a week, and the cause was never the code under review — it was three controls that had quietly stopped meaning anything: a round budget set below the measured average, a settings switch implemented in one layer and absent from the layer that decides, and completed reviews whose verdicts evaporated between the lanes and the ledger. Two of the three are closed here, along with the site rebuild that had been waiting behind them — and ACE itself, which had been unreachable for a release because its shortcut was bound to a chord terminals cannot transmit. The third — the round budget — is diagnosed but not yet shipped; the note below tells you what to set.
Bugs fixed
The review pipeline
-
⚠️ The review-round budget default is UNCHANGED in this release — raise it yourself.
DefaultRoundBudgetis still 3, while measured history across 85 PRs puts the mean at 3.9 (p75 = 5, p90 = 7). So roughly 40% of PRs exhaust their budget and stop, waiting on a human disposition — and because stalled PRs never drain while healthy ones do, a busy board converges to all-stalled within hours. Until the shipped default is raised, set it explicitly:[rules] review_round_budget = 8in~/.flowforge/config/settings.toml, orFLOWFORGE_REVIEW_ROUND_BUDGET=8. 8 fits 92% of PRs; the remainder genuinely deserve a human look. Tracked in #4917. -
Completed reviews stopped vanishing. A cohort could run all six lanes, post every lane verdict, exit clean — and bank nothing: no consolidated verdict, no ledger entry, while the round was still charged. Root cause was a cross-process lost update in the mergepipe and convergence stores: the write path now takes a real cross-process lock, and convergence records are segmented by repository so two projects cannot overwrite each other's ledger. The sibling defect — mergepipe still keying its records by bare PR number, so two repositories with overlapping PR ranges share a filename — is not fixed in this release —
mergepipe.FileStore.statePathstill keys records by bare PR number at this release head, so two repositories with overlapping PR ranges still share a filename. Tracked in #4903 and #4911 (#4879). -
golden_accepts_minornow reaches the layer that DECIDES. The setting was fully implemented in Go and absent from the reviewer's own rule, so turning it on changed nothing — a PR at zero criticals and zero majors could not earn a verdict it had already met. One rendered rule, three consumers, and a bidirectional drift guard so the two copies cannot diverge again (#4918, completing #4758's single-reviewer lane). -
A reviewer verdict now binds to reviewed CONTENT, not to the commit that carried it. A base-merge changing zero reviewed bytes used to destroy a GOLDEN and burn a round. Content identity is a patch-id, proven by a negative control (#4870).
Trust surfaces that were reporting more than they knew
closedstops meaningmerged. A ticket closed by a passing mention rendered as shipped, on three surfaces, from a projection that proved no merge at all. One ownership predicate now serves all three, with a standing detector — and the PR template that taught contributors the wrong convention is corrected at the point the trailer is written (#4869).- The dispatch guard admits its own porosity. It fired and then permitted: four appended words flipped a deny into a permit. The lexical filter stays as a cheap first pass and is no longer trusted alone — an outcome detector now catches what the text cannot, and the enforcement registry records the honest coverage instead of the claim (#4898).
- A relayed message can no longer read as a human keystroke. Every relay arrives inside a provenance frame naming it agent-originated and stripped of ratification authority, carrying a per-relay random boundary a caller cannot forge, and lands a durable audit record with the calling session and target ticket — where the tool had advertised audit logging and written nothing (#4891).
- The cockpit
Kkey refuses a worker parked warm in review. One keypress could destroy a live lane with an open, unmerged PR; it now obeys the same probe the stop verb already did (#4892).
Gates that were not running, or running on the wrong thing
-
You can reach ACE again — it is
Ctrl+Onow. The attach shortcut was moved off plainAin v1.2.11 for a good reason (it fired while you typed the word "Ace"), but the replacement,Ctrl+Shift+A, is a chord terminals cannot send.Ctrl+Shift+<letter>only exists once an enhanced key encoding is negotiated end to end — outer terminal × its config × tmux extended-keys × the application. On a plain wire the terminal transmits the same byte (0x01) forCtrl+AandCtrl+Shift+A; the Shift is never sent. So the affordance shipped unreachable in v1.2.11, and the handler was never the problem. Measured at the wire rather than inferred from the keymap:0x01 legacy -> ctrl+a <- the defect ESC[97;6u kitty CSI-u -> ctrl+shift+a ESC[27;6;97~ xterm modifyOther -> ctrl+shift+aCtrl+O(0x0F) decodes identically on legacy, kitty and modifyOtherKeys wires, on everyTERM, and through real tmux — zero negotiation, zero configuration. It is non-printable, so typing "Ace…" still cannot fire it. Ships with a structural guard so the whole class — binding an affordance to a chord the wire cannot carry — fails a test instead of a release (#4838). -
Five workflows never fired on the release line. Their triggers named earlier version lines literally, so the test suite, the TDD gate, integration, security and smoke-install were all silently absent — a lane PR carried a single check. Triggers are now patterned, with a guard that probes for lanes which do not exist yet, so the next line cannot inherit the same silence (#4906).
-
The ratification wall stops reading a
#comment as a markdown heading — a note could gate its own PR, undiagnosably (#4867). -
adr newworks on a default install. Two separate Supabase paths had drifted; there is now one seam, the allocator uses it, and three distinct failure cases stop collapsing into a single misleading message about the network (#4839).
Documentation, pricing and the tree
- 28 dead external URLs in the
/docs/corpus, each with a per-URL remedy and a CI gate so the rot cannot silently return (#4885). - One price canon —
tiers.jsonis the record, the site derives from it, and a test fails on the appearance of a second source of truth (#4721). - The repo root is clean, the drawer-staging bundles that made
git statusunreadable stop recurring, and a doctor probe guards the class (#4876).
New features
The site rebuild
- Tabbed Product Tour — absorbs How-it-works and See-it-run into one surface, retiring
SeeItRun.astroand reclaiming ~2,648px of page (#4737). - The War Room band — the management surface gets its own section, claim-ceilinged against what the product actually does (#4738), with the capture regenerated on a real build and carried by an asset manifest (#4732).
- For Everybody — two personas become three; the softhouse is now addressed directly (#4741).
- FAQ and the Disclosure primitive — with the after-payment item deliberately not rendering (#4743).
- Credibility strip, behind a
renderIfhonesty gate so it cannot display a claim the data does not support (#4735). - Hero pipeline second render mode — two crops, a manifest, and a freshness gate (#4731).
Billing
- The plan you click is the plan you are billed. The frontend guards that forced every checkout down one path are removed (#4722).
- The confirmation page stops asserting the wrong plan.
/sign-up/successreads no session and hard-coded "Solo" in three slots — so the moment Team went self-serve, every Team buyer would be told their Solo subscription was active, on the last screen they read after the Team amount cleared. This is the other half of the money path from the fix above (#4748).
Accessibility
- The case-study LOC table is reachable by keyboard. The scrollable region had no focusable handle, so a keyboard-only visitor could not reach its right-hand half at 375px — axe
scrollable-region-focusable, WCAG 2.1.1, serious. It now carries a focusable region role, a label, and a visible focus indicator (#4746).