Skip to content
All releases

Release

v1.2.25

What shipped, in numbers

43
PRs merged
85,548
Lines added
22,326
Code lines
Code
22,326
Tests
34,663
Docs
28,559
Sum · code + tests + docs
85,548

of 43 merged

  • bug 23 54%
  • feature 7 16%
  • polish 0 0%
  • docs 9 21%
  • groundwork 1 2%
  • unclassified 3 7%

since v1.2.24 · tagged

The letter

What shipped

Sign in, update and repair without a terminal. A new customer could sign in to FlowForge, open the cockpit, spawn a worker — and watch it stop on a Claude Code sign-in screen whose only fix was a command typed into a terminal the desktop app does not have. An update signed you out of your own seat because the machine's fingerprint rode a hostname macOS rewrites. The cockpit's sign-in screen could render with no Email and no Password field. And flowforge update returned the moment the versions matched, so the repair everyone reaches for never ran. Each of those is fixed here, along with the cockpit faults of the week: your own keystrokes painted on the ACE rail header, typing that got slower every hour, an idle cockpit burning CPU, and 522 dead processes nobody cleaned up. What needs one step from you, and what is not fixed yet, are each stated plainly below.

Sign in without a terminal

  • 🔴 Claude Code sign-in is checked before a worker is built, and named. A worker used to be given a worktree, a branch, a tmux session and a Fleet row, then idle through a 60-second deadline before the pane showed a Claude Code login screen. The spawn now asks first: a machine that is plainly signed out is refused before anything is built, with the one command that fixes it; a machine whose state cannot be read proceeds and says so. ACE's launch asks the same question at the one door every ACE launch crosses (#6391). flowforge doctor has a new claude-auth row that reads UNKNOWN on any doubt instead of guessing (#6390).
  • 🔴 flowforge claude login signs Claude Code in without a terminal. It opens your browser at Anthropic's sign-in page, takes the code if the browser shows one, and exits 0 only when the machine is confirmed signed in afterwards. If Claude Code ever changes the output it relies on, it falls back to the named terminal path within a bounded time and never hangs (#6392). flowforge claude status [--json] reports the state (#6393).
  • 🔴 The desktop app's setup gate has two rows, one click each. The overlay used to know about the FlowForge account and nothing else. It now shows both — FlowForge account and Claude Code — and a click on the Claude Code row runs the sign-in above, streaming its progress into the row. It is also reachable any time from ⋯ More ▸ Sign-ins… (#6393).
  • The desktop stops calling every failure a wrong password. A server that was not configured, a session file that could not be written, and even a sign-in that succeeded but could not be read back all read "That email and password didn't match". Only a real credential mismatch says that now; every other failure is shown in its own words, and a sign-in that landed is re-checked instead of refused. The app also re-checks when its window regains focus and every 5 seconds while the gate is up, so a sign-in finished elsewhere is picked up without a restart, and a cockpit that needs a sign-in raises the gate instead of printing advice into a pane with no prompt (#6395).
  • 🔴 An update no longer signs you out of your own seat. The seat's machine fingerprint was built on the hostname, which macOS rewrites on a network change, a VPN or a sleep/wake — so one Mac read as two, and the seat refused the machine it was sitting on ("FlowForge is already running on "). The fingerprint now uses the machine id (the hardware UUID on macOS, /etc/machine-id on Linux). And a daemon stopped by an update now releases the seat before it exits, instead of leaving it held for the four-minute timeout (#6394).
  • The cockpit's sign-in form draws. The in-cockpit re-login showed its heading and nothing else — no Email field, no Password field, no error — because the form was drawing into the cockpit's log file instead of the screen. It now draws where you are looking, and a form that fails to run says so instead of reading as if you cancelled (#6441).
  • Concurrent token refreshes are serialized. Eight FlowForge processes could each refresh the same stored session with no lock between them. Refreshes now take a cross-process lock, and every attempt is recorded in ~/.flowforge/auth/refresh-ledger.jsonl. This closes the window on reading the code; nobody has reproduced a lost session against the live server (#6401).

flowforge update repairs

  • 🔴 flowforge update finishes the install even when you are already current. It used to return at version parity, before re-laying the agents, hooks, commands, skills, the ~/.claude mirror and the MCP registration — so the only repair door was curl … install.sh | sh. The install steps now always run, in install.sh's order, from the newly installed binary (#6381, #6400).
  • 🔴 An update never writes over a live binary, and proves the new one runs. Writing new bytes into an existing macOS binary can get every later launch killed silently by the code-signature check. The update now removes the old file before writing, and fails if the written binary does not start and answer — a checksum match alone no longer counts as success (#6382).
  • flowforge update --repair and --force. --repair re-lays the installed assets without needing the release server, so it works offline or behind a proxy; --force re-downloads and reinstalls the promoted release even at parity. --yes, which did nothing, is hidden but still accepted (#6383).
  • The install tells the truth about its version. ~/.flowforge/VERSION read 1.0.0 on every install since v1.0.0, and so did the FLOWFORGE BEGIN v… marker in every mirrored CLAUDE.md. Both now carry the real version. Each install writes a stamp at ~/.flowforge/state/install.json, and a new flowforge doctor row, install-freshness, goes red when the installed assets and the running binary disagree, naming flowforge update --repair (#6383).

The cockpit stays solid

  • 🔴 FlowForge cleans up its own garbage. On the founder's Mac with zero workers running: 522 dead child processes under one cockpit, 84 dead tmux sockets, and six abandoned tmux servers up to nine days old — and the installer printed "report only, never killed". Every cockpit start and every install or update now removes them and prints what it removed and which live workers it kept, by name. A live cockpit or worker server is never touched, nor anything FlowForge did not create or could not check. flowforge hygiene (alias sweep) is the manual door, report-only by default. Every child process FlowForge starts is now waited on (#6378).
  • 🔴 Your keystrokes no longer appear on the ACE rail header. The rail's activity line walked the pane upward for "the latest action" and took your own wrapped message for one, then painted it into the status row. Activity is now read only from what happened after your last message (#6379).
  • Typing no longer gets slower the longer the cockpit stays open. Each new turn re-pushed the whole transcript; only a trailing window is pushed now, so the cost stays flat however long the session runs (#6379).
  • An idle cockpit stops burning CPU on nothing. An idle voice manager kept a 10-frames-a-second clock rebuilding the rail forever; it stops at rest. The worker process scan now streams the process table instead of copying it and runs at most every 5 seconds instead of every second, and a cockpit with no workers runs none (#6379, #6387).
  • F5 repaints everything. A cockpit whose screen looks wrong now always has a way out: F5 drops every render cache and redraws the whole frame, in any state (#6379).
  • A paste during an input-method composition no longer freezes the desktop terminal. A paste that arrived while an IME or dictation composition was open latched the terminal, and every keystroke after it was swallowed. The composition is now committed first, in order, and nothing is dropped (#6374).
  • ACE launches on a Claude Code without --permission-mode auto (customer-reported). FlowForge assumed every Claude Code accepts auto; one that did not exited on the spot, and the rail kept saying ● alive while what you typed ran as shell commands. FlowForge now asks the installed Claude Code which modes it accepts, the rail shows a launcher that died on its arguments as a failure with the error and the remedy, and flowforge doctor has a claude-permission-mode row (#6376).
  • A retired worker reads retired, not vanished. A worker ended on purpose after its PR merged used to read the same as a crash. The reaper also names any unpushed branch a worktree still holds before removing it, with the command to get it back, and an auto-merge now tells you which PR, which head and which gate it passed (#6399).

Reading the cockpit at a glance

  • Two named clocks on the header. TIME becomes FLOWFORGE SESSION, which survives an ACE restart, and CONTEXT, which zeroes on /clear and on a reset — so you can see how old the context you are about to trust really is (#6424).
  • The ctx gauge stops jumping backwards. A session near 95% full read ctx 45%, 9% and 39% inside one minute, because the gauge took the newest line of a feed that was replaying the session's past. It now takes the highest value the session has reached (#6423).
  • The ACE rail narrates a long turn. Instead of one "running a command…" until the turn ends, the rail shows the current step, a ledger of what landed (tickets filed, workers spawned, PRs merged), and a clock per step. A step that cannot be read says so instead of being labelled (#6427, #6437).

Plans and the Gantt

  • A sprint can depend on another sprint. flowforge sprint-dep records a finish-to-start edge between two sprints, dry-run by default and naming the date consequence without moving a date; flowforge sprint-dep-audit blocks on a broken edge or one the dates deny, and warns on a dependency written only in prose. The Gantt draws a whole initiative's sprints on one chart with those edges and the cross-sprint critical path (#6419).
  • The Gantt stops reporting good news beside late work. The pace and estimate readings used to say on track or 100% on-time in green beside open tickets past their planned end. They now withhold the verdict and show the overdue count instead (#5597).
  • SV(t) and SPI(t) are back on the Gantt strip. The earned-schedule reading shows a direction only where an open ticket's real effort cannot turn it around (#6143).
  • The logic path is proven not to move with the sprint. The delta between the logic path and the achievable path is now tested as the cost of the boundary, at every width (#5596).

Reviews that no longer strand a worker

  • 🔴 A review crew that dies with its session no longer leaves the worker waiting for hours. When the session that dispatched a review ended, the crew was killed without writing anything, and its round said "still running" for up to 3 hours 10 minutes — a dead end only a person could clear. The round now checks whether the crew is alive, records a dead one as ended with no verdict, and the existing heal re-dispatches the review on the next beat (#6442).
  • The post-GOLDEN push override takes a class, not a sentence. FF_GOLDEN_PUSH_OVERRIDE accepted any prose, so a worker could override the guard that had just refused it. It now accepts only base-sync: <why>, proven at source, or founder: <why>, recorded and counted separately (#6412).
  • A voided GOLDEN is dated by the push that broke it, not by the review that gave it, so a fresh void no longer drops out of the report window (#6420).

Colado

Colado is a jiu-jitsu term — a position is colado when it's justo, perfectly adjusted, no gaps, full pressure — and it's the name for the family of FlowForge gates that leave no space between the rule and the work. This release closes these gaps:

  • A worker can no longer be built on a machine that is plainly signed out of Claude Code — the spawn asks first (#6391).
  • An update can no longer count a binary that will not start as installed — the written binary must run (#6382).
  • A worker can no longer grant itself the override the guard just refused — the override names a class, and base-sync is proven (#6412).
  • A child process FlowForge starts can no longer be left unreaped — every start is waited on, and a test refuses the shape that leaked (#6378).
  • A dead review crew can no longer hold a round open — the round reads the crew's liveness (#6442).

Small things that change everything

Not every change earns a headline. These fit in a line each, and you feel them every day.

  • The ForgePlay picker scrolls, and the selection can never sit on a play you cannot see (#6433).
  • F5 repaints the whole cockpit, whatever state it is in (#6379).
  • A retired worker reads retired, so a finished job no longer looks like a lost one (#6399).
  • An auto-merge names its PR, head and gate on the rail (#6399).

Studies and plans

  • ADR-0139 — the cockpit is rock solid and FlowForge leaves the camp cleaner than it found it (#6388).
  • The crew that builds software, and the crew that launches it — two studies of the agent roster, awaiting ratification (#6425, #6426).
  • Concurrent waves — a study of running several waves at once on one host, awaiting ratification (#6434).
  • The FLEET READ delivery DAG — split into two plans and generated from its table (#6141, #6413).

Smaller, and under the hood

  • Two tests that would have turned the cut red are fixed. A code scanner read claude auth as a GitHub CLI assumption (#6447), and the inode-reuse test for the update fix could not prove its claim on Linux (#6448). No shipped behaviour changed.
  • A test that claimed to walk the update's child processes only filtered two paths; it now walks what each child reaches (#6400).

One setup step

  • Sign in to Claude Code once, if the cockpit asks. On a machine that is signed out, spawns and ACE are now refused with the fix instead of stalling: run flowforge claude login (or claude auth login), or click Sign in on the desktop's Claude Code row, then press r in the cockpit to re-check (#6391, #6392, #6393).
  • Expect one last four-minute wait for your seat on this upgrade. The daemon you are upgrading from predates the seat-release fix, so the seat it holds clears at its timeout, once. From the next upgrade on, the seat is freed on the way out (#6394).
  • If you set FF_GOLDEN_PUSH_OVERRIDE, give it a class. A plain sentence is now refused; use base-sync: <why> or founder: <why> (#6412).
  • Quit and relaunch every open cockpit after you update, so the new sign-in check, hygiene sweep and rail fixes are running.

Not yet

  • The idle-CPU target is not proven on a running cockpit. The fixes above remove the idle clock and cut the process-scan rate, and the per-frame cost is held by a test, but an "after" figure from a live cockpit on this release has not been measured, and the War Room render cache the work also planned was reverted (#6379, #6387).
  • A worker with no worktree and no Fleet row is not swept. Removing one would mean killing a session on a live cockpit on the strength of a signal that is known to be unreliable, so it is left for now (#6378).
  • flowforge claude login depends on Claude Code's current sign-in output. It was re-measured on Claude Code 2.1.274 and falls back to the terminal path if that output changes (#6392).
  • On Linux, the seat fingerprint identifies the installation, not the hardware — a cloned VM disk or container image carries the same id (#6394).

Agents

No roster change in this release: FlowForge installs the same 44 specialists v1.2.24 shipped (git diff --name-status -M v1.2.24 origin/release/1.2.25 -- v3/packages/core/agents is empty).

Update

  • flowforge update on an existing install, or curl -fsSL https://get.flowforgesoft.com/install.sh | sh for a fresh one. Both write the same release binary to /usr/local/bin and ~/.flowforge/bin together. flowforge update --repair re-lays the installed assets without the network. Then quit and relaunch every open cockpit.

v1.2.25 — 43 PRs, 86k lines, made with FlowForge