Release
v1.2.26
What shipped, in numbers
- 326
- PRs merged
- 643,616
- Lines added
- 223,470
- Code lines
- Code
- 223,470
- Tests
- 211,155
- Docs
- 208,991
- Sum · code + tests + docs
- 643,616
of 326 merged
- bug 122 38%
- feature 134 41%
- polish 1 0%
- docs 47 14%
- groundwork 20 6%
- unclassified 2 1%
since v1.2.25 · tagged
The letter
What shipped
More work in flight, and a cockpit that tells you only what needs you. 323 pull requests merged in ten days, and this section covers all of them. Waves stop being one at a time — you choose how many run side by side, queue the rest, give an entry a start time, and the queue keeps moving with no cockpit open. ACE reads one recap of the whole fleet, and the actors behind it now deliver a review's findings and nudge a quiet worker by themselves. The Fleet screen and the Workers queue are rebuilt on one shared reading of every worker, with a legend for every symbol. The War Room's board tells the truth again and reads only what you ask for. Eight new specialists join the roster (44 → 52), and the first opt-in pack ships. Windows is supported through WSL2, the sign-in gets you in, and two weeks of one customer's field report are fixed, finding by finding. What needs one step from you, and what is not done yet, are stated plainly at the end.
Waves: several at a time, and a queue for the rest
- 🔴 Run more than one wave at once. You set a width N, and the queue keeps N waves live; the next one starts the moment one lands. A doctor row names any ticket two runs both hold (#7244). Slots are shared fairly: starved runs are served first, each wave can carry its own maximum and weight, and a reserved floor is enforced at the gate that admits a worker. Two runs that would plan the same ticket are refused (#7137).
- The queue of waves. Queued sprints wait in a durable, per-repository queue with barriers, a park policy and a breaker (#7042). Manage it from the CLI (
flowforge waves queue show|add|rm|mv|barrier|width|start|hold,waves resume|skip|abandon) or thewaves_queueMCP tool. Every refusal happens when you compose the entry, never later (#7059). The queue reads the machine's own ledgers too: the shared GitHub budget, a usage pause and the start verb's refusal codes (#7084). - A queue is a schedule as well. An entry can carry a start day and time, and you can move one to the front or to the back (#7109). The Waves board edits the queue in place: width, start time, and "third to first" in one key (#7123). A paved plan can wait in the queue too. Its begin date is answered when you add it, and it fires through
plans firewhen its turn comes (#7071). - 🔴 The queue keeps moving with no cockpit open. The cockpit steps the queue on its 1 Hz beat (#7064). When no cockpit is driving, the FlowForge daemon steps every draining queue through the same verb and the same
create_workerdoor. A cockpit that opens takes the run back by its lease, so two drivers never fire one run. A queue whose next entry is scheduled for tomorrow reads nothing from GitHub until then (#7260). Every worker spawn brings the daemon up if it is not running, unless you setFLOWFORGE_DAEMON_AUTOSPAWN=0(#6952). - 🔴 A ticket starts when its own dependencies land. Inside a wave, a ticket used to wait for the whole previous layer to finish. Now it starts as soon as every ticket it depends on has merged and a slot is free. A plan with no recorded edges keeps the old barrier, byte for byte (#7335). From a customer's field report.
- The Waves board. It shows the live runs and the queued entries side by side, a driver and host line, a trouble banner, and five widths (#7102). It has a focus ring, drill-in, verbs that name their target, and a latch on destructive keys (#7121). One hue means one run everywhere it appears (#7118). Each run gets its own record: an id, its scope, a driver, a typed outcome (#6957), and storage of its own, so stop and pause act on one run only (#7125).
- Wave history. Every run that ended is kept with its sprint, start, end and outcome until you clear it (#6964).
- Arm a wave without the board.
flowforge waves start --sprint, thewaves_startMCP tool andSall go through one verb. It layers the sprint's own tickets and refuses with named reasons (#7012).loop autofire's sprint mode passes the same refusals before it takes a lease (#7124). - A wave is
≈1, neverW0. Waves count from 1 and read≈Non the widget, the Fleet chip, the board, the Waves screen and in ACE's words.Wis for workers only (#7063). - Smaller wave fixes. Every row shows its ticket's title, or
loading…, never a blank (#6894). Waves returns to the screen that opened it, andb/topen the same sprint's Kanban and Gantt (#6715). The fire modals and the waves strip count every worker on the machine, not just this project's (#7062). An epic is a container, not work: it is never put in a wave or spawned (#7107). The wave board anddepends-auditread the same full roster (#6510).
ACE that acts
- 🔴 One recap of the whole fleet. The recap is one snapshot of the fleet, where every reading is either known or explicitly UNKNOWN (#6979). The daemon serves it at
/v1/recap, andflowforge recapreads it (#7003). It appears as an escalation in ACE's rail, composed at the rail's width (#7010). Before ACE ends a turn, a Stop-hook gate makes sure it has read the latest recap (#7029, #7041, #7056). In production every reader that has a source is wired in (#7055), and the loop was closed and re-measured end to end (#7087). - 🔴 The actor table — five remedies, each with a stage it has earned. The actors run in the daemon's actor host: one per home and account (#6827), supervised so that a panic costs one pass and never the daemon (#7023). Each remedy has its own trust stage, and it is promoted only on its record (#6951):
- relay-verdict delivers a review's findings into the warm worker that owns the pull request. It acts today (#6968, #6953).
- nudge-worker sends one "continue" per quiet spell. It names any refusal or NOT-GOLDEN, and after a usage limit it waits for the reset. It acts today.
- order-rebase orders a rebase when a pull request turns conflicting (#6959, #7057). It runs in shadow: it records what it would have done and acts on nothing.
- dispatch-review starts a review that is owed (#6984). It also runs in shadow.
- reap-vanished reaps a worker whose window is gone while no cockpit runs (#7037). It records only, and it never kills anything.
- Each row on the stuck-work board says what actually happened, read from a record: ACTED, ESCALATED, WAIVED or FAIL (#7004).
- Escalations reach ACE first. There is one ledger with four classes. A fork goes only through a gate a plan designed. A merge gate is scoped to its pull request and head. Failures and questions go to ACE first, and only a founder-class decision pages you (#6913). ACE-first escalations ride ACE's wake (#7035) and reach a headless ACE too (#7049). Below the escalation bar, the stall actor still tells ACE (#7060). A condition no remedy will act on owes ACE one notice per head that names why and the next move (#7073). Automation failures no longer have a silent route (#6949), and a red lane names the failing check and tests (#6996).
- The wake. A durable outbox and a drainer on the stream lane wake ACE when something needs it. Its composer fallback is guarded and never one-shot (#7030). A send queued behind a live turn is held, not counted as delivered (#7036). The worker-done relay to ACE re-arms after a refusal (#7093).
- A worker that needs you says why. A worker's permission prompt becomes a deferred needs-you row (#6998).
claude agents --jsonis a second source for those rows (#6990). A/goalthat never armed escalates (#7005). A goal the harness gave up on reads GOAL LOST, never a quiet park (#7000), and the/goalline fits under Claude Code's paste-collapse limit, so it arms again (#7002). - Relays ride Claude Code's own inbox. A message to a worker is a framed message with a typed outcome, with paste kept as the fallback (#7006). It dials only the current user's sockets (#7009). A relay that lands in a worker's queue is delivered by FlowForge, not by you (#6531).
The Fleet screen and the Workers queue
- 🔴 One reading of every worker, shared by both screens. A typed projection of every work item (#6907) and of every wave (#7096) is built once and handed to both screens on the same tick. The Workers queue reads it (#7106), and ten per-field setters retire. The ticket's title, milestone, labels and kind are read in one batch (#7103), and the ticket key is read the way it was written (#7100).
- The Fleet screen. The roster is now the sessions: every live session is a lane, and a stale worker is a lane for the first time. If the daemon is down, a banner says so and no lane vanishes (#7305). The vitals strip fits one row and has a fault banner (#7310). Selecting a lane opens its detail and a peek without taking a table key (#7301). The detail modal shows each lane's conditions and fits a short terminal (#7296).
- The Workers queue. Every row tells you what the worker is doing. It shows how long it has been quiet, from the stall ledger or the pane (#7098), how many review rounds its pull request has had (#7104), and which wave it belongs to (#6898). Its title reads at 120 columns (#7111). Rows group under five groups, each with a header row (#7140, #7285), and both rows carry the same attention reading (#7132). The branch base is recorded when a worker spawns (#7101).
- Every symbol, explained. Decoder rows and legends cover every glyph, each one drawn with its colour and its label (#7145, #6909). Help has a Symbols block for the Workers and the Fleet, generated from the renderers' own tables (#7320). The keys, hints and help were reworked across both screens:
kwalks the focused queue, the bar and the footer name only live verbs, and?on the Fleet shows the Fleet's own keys (#7313). - The columns line up. Every glyph is drawn in its own cell, and a property test holds each column to one x position in the Fleet and help renders (#7322). Every screen was re-rendered from code in both themes for acceptance (#7318).
- One worker cap and one GitHub budget per machine. Every door that spawns a worker passes one host-wide slot gate (#6915). A Settings dial writes the cap, and the cockpit has a host line (#6973). A dead worker's slot is freed (#7034). Every FlowForge process on the machine shares one GitHub budget (#6902). The GraphQL part of it is measured, ledgered and reserved for the merge gates, and the status line and the autofire lane stop polling what has not changed (#7275).
The War Room
- 🔴 The board tells the truth, and
rcorrects it. Cards no longer vanish from a sprint board when another read lands. The lane board counts and draws one list, says when it is stale, andrre-reads it. A ticket with an open pull request sits in Review, not To-do, because a pull request now joins its ticket by branch. A merged-but-open ticket shows in Review with a badge, and START and DUE read in your own time (#7293). From a customer's field report. - The War Room reads what you ask for. Reload whenever you want. Read one sprint, one milestone, the standalone tickets, or everything updated since a date, each answered by the provider's own query (#7196). A read row under the title says what the board asked for.
Ropens the read picker,rreloads in every state, and your choice is remembered per project (#7284). - Schedules and containers that add up. Behind and ahead follow one rule: undated work inherits the sprint end, epics never count, the header equals the rows, and work that finished early finally shows as ahead (#6545). A sprint can be detached from its initiative (#6555). A closed initiative reopens when a live sprint is attached (#6551). However old the "Plans ready to fire" shelf is, it shows as one named row (#6696).
container-sweepnames every epic it considered, including one held open by an open child (#6869). - A clock you read is your own clock. The War Room, Release Letters and every cockpit clock render in your own time (#6549).
Merges and reviews you can trust
- A verdict binds the head and the base. A retarget earns a fresh review without a byte-changing commit (#6475). A retarget also re-arms review, the merge gate ignores CI runs from the old base, and
worker parkrefuses a pull request off the lane (#7302). - A merge never lands under a worker that is still working. It holds while the worker has uncommitted changes, unpushed commits or a turn in flight, tells the worker once per head, and retries on the next pass (#7011).
- Conflicts are ordered once. A merge refused as a conflict at a head is tried once, ordered once, and re-armed only by a push (#7295). One shared conflict-order round per pull request, head and base (#7091).
- One decision per round. A gate's refusal on the code is posted as one refusal notice, never banked as a verdict (#6687). The review-of-record says who judged a head, and a refused GOLDEN is not reported as a dead crew (#6597). An unreadable ledger is said on the merge row, never shown as "no ask" (#6969). A founder gate cleared after a NOT-GOLDEN can re-bind the head (#6963).
- Reviews start through one door. The review crews launch through one door, with measured turn and budget ceilings and SIGINT before any kill (#6992). A worker's durable park on any branch marks review as owed (#6911). Dispatch budgets split judged, died and refused, every lane honours a host-wide usage pause, and the merge verb spends nothing (#6965).
- Closing is exact. A default-branch pull request closes only the tickets it declares (#6480). Two projects stop sharing one verify record and lock per pull-request number (#6906). A founder's post-merge step is a durable record, shown as an absolute command (#6658).
A customer's field report, fixed finding by finding
One customer ran FlowForge on a real project for two weeks and reported what broke, with incident counts. Every finding below was worked on its own ticket.
- 🔴 A dead worker is found, its work is saved, and it is respawned. A worker killed by an out-of-memory error or a reboot, or a Claude session that died inside a live tmux, was never detected. The cockpit now finds it. It saves the uncommitted work to a
rescue/<ticket>-<time>branch, a patch and a tarball, then respawns the worker with a brief that names the rescue. A worker that keeps dying is held for a person (#7286). - 🔴 Workers start on the sprint's base. Worktrees ignored the sprint's declared umbrella branch. They are now cut from it, and
create_workercan name a base (#7281). - 🔴 A NOT-GOLDEN about the pull request body alone can be re-graded at the same head once the body changes. The worker no longer parks forever (#7279).
- 🔴
flowforge mergecloses the ticket its pull request owns. A failed close is queued and retried (#7287). - A fresh GOLDEN merges on the verdict. It used to wait out a GitHub-error back-off that belonged to a different call (#7328).
- A review is logged as spawned only once its round is open (#7336).
- Generated files carry no per-file line cap. A header marker,
linguist-generated, or a configured glob exempts them (#7331). - Every worker brief carries your project's standing rules from
.flowforge/worker-brief.md, for example a memory limit for your test runner (#7327). - A respawned worker is not a stopped worker. The relay re-reads tmux before it refuses, and a respawn from any door revives the worker's row (#7330).
- Your own Claude Code
statusLinestays yours. FlowForge claims the slot only when it is empty or already FlowForge's, and says so once (#7334). - A promotion or sync pull request always takes a merge commit, never a squash (#7329).
blueprint amendwrites one file per amendment, so sibling pull requests merge cleanly (#7332).- A worker whose turn died on an API error before its first pull request gets one retry nudge, then ACE is told (#7333).
- A message you send never paints outside ACE's rail. Carriage returns and tabs in a pasted message are normalised before the wrap, and every row is clamped to the rail (#7338).
- Re-emitting an amended plan creates only the new units, not duplicates of every ticket (#7337).
plans fireis safe to re-run after an interruption (#7256). - The War Room's board truth and per-ticket readiness in a wave came from the same report; both are above (#7293, #7335).
- From the first week of the same report: a merged pull request closes only the tickets it declares (#6480). The wave board and
depends-auditread one roster (#6510). A ticket your lane already touched dispatches, with the evidence in its brief (#6487).create_workerreportsspawnedonly after it sees the session (#6481).flowforge review cleared <pr>asks about that pull request's own head (#6478). The git and GitHub write guards judge each executed command on its own arguments, not the whole line (#6485). Aticket new --liverefusal names the missing line first (#6484). A rendered document never silently loses its body (#6482).
Sign in, and get in
- 🔴 The sign-in screen takes the whole screen. It used to draw under a wall of launch diagnostics. Now it owns the alternate screen, and every diagnostic is still in your scrollback (#6506).
- 🔴 The password field takes input. Validation gates the submit, never the move between fields (#6509).
- 🔴 The desktop sign-in always ends, with a value, an error or a timeout, never a spinner that turns forever (#6508).
- A sign-in click is not a takeover. Signing in on your own Mac no longer evicts you (#6535).
- Sign in to Claude Code without a terminal. A menu signs you in for the first time or switches accounts (#6548).
FlowForge Desktop, and Windows through WSL2
- 🔴 Windows, through WSL2. A WSL install prepares the Windows side by itself: the graphics check first, then the launchers, then a summary of what it skipped (#6524).
flowforge desktop shortcut --windowsputs Desktop and Start Menu launchers in place through WSLg, and removes them again (#6523). The app has a multi-size Windows icon (#6514), and there is an install guide (#6515). This is Windows through WSL2, not native Windows (#6520). - The desktop app says what is missing on a clean Linux or WSL host instead of aborting with a stack trace, and
flowforge doctorgains adesktop-glrow (#6507). The app's environment reaches the cockpit it opens, and a document that will not open says why (#6511). The packagers refuse to bundle aflowforgewith an empty or stale embed (#6976). - The preview becomes a reader. Find in the document with ⌘F, with every match painted and "3 of 12" (#7131). Zoom to one remembered reading size (#6895), and ⌘+ ⌘− ⌘0 and Esc work wherever focus sits (#6904). Return to where you were, and read "On this page" (#7128). The Documents drawer shows a title on every row and can be widened (#7127). A split always leaves the document room to read (#7114). Every chord is written down (#7139).
- Ratify on the page. The gate band ratifies the document on screen, at the revision you are reading, with an undo window (#7119). "Not yet" opens the document's own ACE with the composer prefilled, and the document stays in view (#7122, #7120).
flowforge doc statusanswers whether a ratification waits on these bytes (#7113), anddoc ratify --jsonis the machine surface (#7112). - The page fits the pane. The page fills the pane (#6897), the chrome is one band that folds (#6905), a document's own THEME button flips only that document (#6892), and the preview names each document's project (#6865).
Agents, routing and the rights lane
- One source for the roster.
agents/manifest.yamlis the only source of the agent roster. Every count, menu and routing skill is generated from it (#6617, #6620, #6826). A routing door and a detector grade every dispatch (#6621), and agents and skills get their own CI gate (#6619). The design chain can nest four agents deep (#6997). - The rights lane. An agent reaches a live database only through
flowforge db, under a grant you issue withflowforge grant, and every grant lands in an append-only ledger (#6630). Raw database clients are routed to that door by a real shell parser (#6628, #6697, #6694). Release, platform and marketing work get the same treatment (#6629, #6627, #6625), and every agent definition carries an## Authorisationblock (#6948). Every auto-mode denial lands in a ledger the cockpit reads (#6607). - Existing specialists, re-cut.
fft-devops-agentis re-founded as the platform operator (#6680).fft-content-strategistandfft-social-mediaare re-cut, and the paid-media pair operates every tracking rung (#6681).fft-medicalstops shipping five wrong healthcare-billing facts (#6954).
The first optional pack: recebimento-médico
flowforge agents install recebimento-medicoadds two Brazilian medical-revenue specialists:fft-faturista(glosa, recurso, prazos, pricing; citation-first) (#6967) andfft-tiss-xml(the TISS exchange format: XSD validation, versions, portals) (#6970). The pack ships inside every release binary (#6972). It installs only on request, survivesinstall --global, and the doctor counts it (#6978, #6981, #6982). Its PT-BR quotations are checked against their sources (#6975)./agentslists optional packs separately, so the core count never moves (#6962).
Fewer prompts, steadier service
- Customer workers run FlowForge's own gated plan and ticket verbs with no permission prompt (#7141).
- macOS stops asking whether FlowForge may access data from other apps. Claude Code's helpers now start in FlowForge's own folder, not in
/(#6893). - Licensing errors say what they are. A server error reads as a server error, not "check your connection" (#7078). The routine 29-a-day licensing grace no longer alarms you (#6528). The service behind it got its heaviest job bounded and its heartbeat made constant-time (#7086, #7099, #7094, #7291, #7290).
- Ctrl-O is the escape hatch again: Claude Code on ACE's own session, with one controller (#7259).
- A reap no longer kills a healthy cockpit (#6657). The update sweep stops only a provably abandoned cockpit server, and names it (#6464).
- Token costs are priced for the models in use (#6543).
Plans, releases and the record
- Plans are named for what they deliver. One naming rule is enforced at lint, fire and land, and there is a safe rename (#6896). ADR numbers go through one server-verified door (#6903).
flowforge backfill-dates --acrossderives several sprints as one schedule (#6483).- Releases finish. A cut that merged and then died resumes at the main-CI gate (#6473). The cut records its lane in every layer that carries it (#6477).
release-ci --checkhonours the lane policy (#7026). - The doctor speaks one vocabulary. Every row uses six verdict marks with a hint on each non-pass (#6679, #6960). A
cc-release-watchrow tracks Claude Code releases (#6986). - The header clocks are back. The session clock is in the right corner, and the context clock centres on the header (#6486).
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 merge can no longer land under a worker that is still editing its head (#7011).
- Two drivers can no longer fire one wave run: the lease decides, and the daemon checks it before every spawn (#7260).
- An epic can no longer be spawned as work (#7107).
- A merged pull request can no longer close a ticket it did not declare (#6480, #7287).
- A verdict can no longer be spent on a branch it never judged (#6475, #7302).
- A spawn can no longer report a worker that does not exist (#6481).
Studies and plans
Nothing below is built or shipped. Each one is listed only as what it is.
- Team Tier 1.0: the study, FlowForge-native parity with GitHub and Jira, the console scope and the emitted plans. No Team feature ships in this release (#7115, #7130, #7138, #7245).
- ADR-0141, the FlowForge session model, which the sign-in fixes are built against (#6505). The pipeline delivers, not only detects, the decision record behind the actor table (#6622).
- The preview study (#6744), the briefing module (#6695), ForgePlays on web screens (#6950), the FlowForge agent study (#6916), Idea to Investor and Brand Identity Creation (#6745), and the launch plan (#7283).
Agents — 44 → 52: the legal org, the release operator, the database pair, the marketing head, DevRel and product marketing
- Added
fft-legal-architect— the legal head: asks before it drafts, decides which law and which contracts a deal needs, grades every issue, reconciles Brazil↔US. - Added
fft-legal-br— Brazilian software law: contracts, licenses, terms and privacy under LGPD, Marco Civil, CDC and the Lei do Software; INPI trademarks and software registration. - Added
fft-legal-us— US software law: contracts, licenses, terms and privacy under CCPA/CPRA, COPPA, CAN-SPAM and FTC §5; USPTO, Copyright Office, DMCA, DTSA. - Added
fft-release-engineer— the release operator: runs a release from a ready lane to customers having it — notes, letter pack, the cut up to your consent, tag, staging, verification by name, rehearsal, install parity. The consent and the promote stay yours (#6682). - Renamed
fft-database→fft-database-architect— the data-model head, now design only: the store, the ERD, who may read and write each table, and the migration plan with its way back. It has no shell and never opens a connection (#6683). - Added
fft-dba— the only agent that may touch a live database, and only throughflowforge db: it rehearses every migration on a disposable copy, reads production read-only, applies a change only under your grant, and reports what it did (#6683). - Added
fft-marketing-architect— the marketing head: decides what your company says, to whom, in what order and through which lanes, and writes one launch brief every marketing lane plans against. It drafts; it never publishes or spends. Paid media keeps its own head for every campaign decision (#6688). - Added
fft-devrel— developer relations under the marketing head: which technical stories to tell on Hacker News, Reddit, Product Hunt and Discord, and with what proof; creator research with personal drafts for you to send. It never asks for votes, never hides who it works for and never posts as a real person. It drafts; a person posts (#6690). - Added
fft-product-marketer— product marketing: keeps the list of what your company may say, each claim with its evidence, re-checked on every release, and builds battlecards, the kit for a deal, case studies and each release's announcement from it. It never decides a price or names a competitor in anything a buyer reads. It drafts; it never publishes (#6691). - The legal org is #6458. The customer-success, paid-media and data-analytics teams were already on the roster before this release and are unchanged in count.
One setup step
- Quit and relaunch every open cockpit after you update, so the new Fleet, Workers queue, Waves board and sign-in are the ones running.
- On Linux or WSL, install the GLES runtime if the desktop app refuses to start. That is
libgles2on Debian/Ubuntu,libglvnd-gleson Fedora/RHEL andlibglvndon Arch.flowforge doctor'sdesktop-glrow names it before the app does (#6507). - Optional: put your project's standing rules for workers in
.flowforge/worker-brief.md(#7327), and install the medical-revenue pack withflowforge agents install recebimento-medicoif you need it (#6978).
Not yet
- Two of the five remedies only watch. order-rebase and dispatch-review run in shadow, and reap-vanished only records. They will act only once their records earn it, and until then a conflicting pull request or an owed review still needs ACE or you (#6959, #6984, #7037).
- A long single line pasted into ACE (#6504) was never reproduced. A related fault was found and fixed: a pasted message with line breaks painted over the Workers pane (#7338). If you still see a single-line overflow, a screenshot, and which app it was taken in, settles it.
- The GLES fix was not confirmed in a clean container. The probe ships as a script anyone with a container runtime can run in about a minute (#6507).
- One page-drain hole remains, pinned by a test. A full GitHub page whose every row is a pull request still ends the read (#6510).
- Team Tier is studies and plans only in this release (#7115).
Update
flowforge updateon an existing install, orcurl -fsSL https://get.flowforgesoft.com/install.sh | shfor a fresh one. Both write the same release binary to/usr/local/binand~/.flowforge/bintogether.flowforge update --repairre-lays the installed assets without the network. Then quit and relaunch every open cockpit.