Files
fusion/packages/cli
gsxdsm eb874f3da3 convert(cli/commands/task.ts): triage guard 1 → 0 (+ a live main regression in the lifecycle E2E release path) (#2627)
**Batched push, gate open.** One conversion; the two E2E commits are
held back and the reason is below — it is the more important half of
this PR body.

## Conversion

| File | triage column comparisons before | after |
|---|---|---|
| `packages/cli/src/commands/task.ts` | **1** | **0** |

`pnpm test:gate` green, `pnpm lint` clean.

All four non-terminal columns rendered the **same** glyph, so the four
id comparisons were only ever asking "is this column terminal?". Naming
`triage` made it a lifecycle-vocabulary site for no behavioural reason —
the merged Planning column dropped that id, so the comparison silently
stopped matching while the output stayed correct **by accident** (the
fallthrough gave it the same glyph).

Behaviour-identical **only** because the loop iterates the legacy
`COLUMNS` constant (`types/board.ts:27` — exactly the six ids), so `col`
can never be a custom id. Stated because the forms **diverge** outside
that set: the old chain fell through to the terminal glyph for an
unrecognised id, the new form returns the non-terminal one. If this ever
iterates workflow-resolved columns that difference becomes live, and the
right answer is a trait lookup, not this.

**Deeper bug deliberately untouched, for U12:** because the loop
iterates the legacy enum, a card in a workflow-renamed column **is not
rendered at all**. That is R8's surface change, far bigger than this
glyph.

*(Note: this file is not on the 45-guard list, so it will not move your
count. Flagging so the numbers reconcile.)*

---

## ⚠️ Live regression on origin/main — the lifecycle E2E release path

While rebasing to push, the flagship lifecycle E2E went red. **I
verified it on `origin/main` alone, with none of my commits: 2 failed /
18 passed.**

```
scenario 1 — DEFAULT vocabulary  → AssertionError: expected [] to include 'FN-E2E-1'
                                   (r.sweep.released is EMPTY)
scenario 2 — RENAMED vocabulary  → audit trail differential broken:
                                   renamed produced [{end},{review}], default produced []
```

Both are pre-existing tests I have never touched. **The capacity release
sweep is releasing nothing.**

**Likely cause, from reading rather than bisecting** — so treat it as a
lead, not a verdict: `moves.ts:1059` now resolves a capacity pool id and
enforces `enforcePooledColumnCapacity` **inside the move transaction**
(#2488 "bind the in-transaction capacity gate", made user-visible by
#2499 "make the capacity gate actually bind for real projects"). The E2E
drives with `settings = { experimentalFeatures: { workflowGraphExecutor:
true } }` — **no `maxConcurrent`** — while the fixture's wip column
declares `{ trait: "wip", config: { limitSetting: "maxConcurrent",
countPending: true } }`. If the resolved limit is finite and the pooled
count meets it, the hold→wip move is rejected on capacity and the sweep
correctly reports nothing released.

If that is right, it is a **test-harness/production interaction, not a
product break** — but it means the program's primary end-to-end evidence
for the capacity boundary is currently inert on main, which matters for
completion criterion 3. It needs the capacity worker's eyes, since
#2488/#2499 are theirs and I would be guessing at the intended
pool/limit contract.

## Why my two E2E commits are held

They add scenario 3 (merged intake+hold board) and scenario 6 (REVISE →
rework), both of which **depend on the same release leg**. On current
main they fail for main's reason, taking the file from 2 failures to 4.
Pushing them would add red to the count you are tracking and obscure
whose regression it is.

Both are complete, mutation-attributed, and green against the commit I
wrote them on:

| Scenario | Proves | Mutation that fails it |
|---|---|---|
| 3 — merged intake+hold | capacity release works from a dual-role
column | `isHeldTask` treating intake/hold as exclusive → exactly its 2
tests |
| 6 — REVISE → rework | `InReview → InProgress` on renamed *and* merged
boards | disabling rework re-entry → exactly its 2 tests |

They go out in the next batch the moment the release path is green.

## Also not shipped, twice attempted, deleted both times

Safeguard 2 (`autoMerge:false` terminal-until-human) still has **no**
graph-level E2E. Attempt 1 passed and then survived mutating
`merge-gate` to ignore `task.autoMerge` — the card was parking on the
review column's `merge-blocker` trait, not the gate. Attempt 2 removed
that trait to isolate the gate, and then the *control* case parked too,
so the flag still was not the discriminator. A fixture that can isolate
it needs a merge path mirroring the builtin (`merge-gate → merge node →
end`) rather than a direct edge to `end` — a real redesign, not a
speculative edit. The enforcement that actually holds today is
`allowInReviewMergeProcessing` in `project-engine` (unit-mutation
verified, NEW=9; gated via #2526).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 22:04:59 -07:00
..
2026-06-10 18:06:51 -07:00
2026-07-26 18:11:47 -07:00

Fusion

@runfusion/fusion

From rough idea to production code — automatically.

Multi-node agent orchestrator — tasks, agents, missions, git, files, and worktrees, with any model, local or cloud.

runfusion.ai → · GitHub · Docs


Fusion reel: from rough idea to production code

Install

Zero install, straight from npm:

npx runfusion.ai

Boots the dashboard. Subcommands forward through (npx runfusion.ai task list, etc). Long form: npx @runfusion/fusion dashboard.

One-line installer (macOS & Linux — auto-picks Homebrew, falls back to npm):

curl -fsSL https://runfusion.ai/install.sh | sh

Homebrew (macOS & Linux):

brew install runfusion/fusion/fusion

Fully-qualified install auto-taps and, on Homebrew 6.0+, trusts only this formula. If short-name install fails with “untrusted tap”, run brew trust --formula runfusion/fusion/fusion then brew install fusion.

npm global:

npm install -g @runfusion/fusion
fn dashboard              # or: fusion dashboard

Launch the dashboard

From a shell:

fn dashboard                 # or: fusion dashboard / npx @runfusion/fusion dashboard
fn dashboard --paused        # start with automation paused
fn dashboard --dev           # development-mode dashboard + AI engine
fn dashboard --no-engine     # web UI only, no AI engine

The dashboard gives you:

  • A live kanban board — tasks move through columns automatically as AI works on them
  • Task detail view — generated spec, step-by-step progress, reviewer verdicts, full execution log
  • Dependency-aware scheduling — declare task dependencies or let the engine infer them
  • Auto-merge — on by default; reviewed work squash-merges without you lifting a finger
  • Parallel execution — independent tasks run simultaneously in isolated git worktrees
  • Self-sustaining board — agents may spawn follow-up tasks; the board feeds itself

Your entire dev environment. On a single pane of glass.

Describe a task in plain language. A triage agent reads your project, understands context, and writes a full PROMPT.md spec — steps, file scope, acceptance criteria. Then Fusion plans, reviews, executes, and reviews again, in an isolated git worktree, with a human approval gate wherever you want one.

One board. Controlled from anywhere. Laptop, Mac mini, Linux server, cloud VM, phone — all connected.

Fusion mesh: laptop, Mac mini, Linux server, cloud VM, phone — all synced

Run an agent company

Import a team. Run it autonomously for weeks. 440+ agents across 16 companies, wired for missions, mailboxes, and inter-agent delegation.

npx companies.sh add paperclipai/companies/gstack
Fusion agent company: import a team, run it autonomously for weeks

How it works

You create a task with a rough description. A pipeline of specialized agents takes over.

Specification. A triage agent reads your codebase — file structure, existing patterns, related code — and turns your rough idea into a detailed spec. It breaks the work into discrete steps, identifies which files are in scope, writes acceptance criteria, and assigns a complexity rating that determines how aggressively the work gets reviewed.

Scheduling. Tasks declare dependencies on each other. The scheduler builds a dependency graph and starts work only when upstream tasks are done. Independent tasks run in parallel — each in its own isolated git worktree, so there are no conflicts during execution.

Execution & review. An executor agent works through the spec step by step in the worktree. At each step boundary, a separate reviewer agent, with read-only access, independently evaluates the work. The reviewer can approve (continue), request revisions (fix specific issues), or force a rethink (change the approach entirely). Review depth scales with the task's complexity rating: trivial tasks get light checks, complex tasks get thorough multi-pass review.

Merge. When execution finishes and the reviewer signs off, the task moves to In Review:

  • Direct merge (default) — automatically squash-merges the completed task branch into your current branch with a clean commit.
  • Pull request — automatically creates or links a GitHub PR, waits for reviews/checks, then merges once policy conditions are satisfied.

autoMerge controls whether Fusion performs completion automatically. If disabled, tasks stay in In Review until you finish the merge yourself. For PR-first mode, authenticate GitHub with gh auth login.

Tasks flow through: Triage → Todo → In Progress → In Review → Done.

This execution model is heavily based on Taskplane.


What makes it different

🧠 AI specification Rough idea in, detailed PROMPT.md out — steps, file scope, acceptance criteria.
🔁 Workflow gates Plan → Review → Execute → Review on every step. Block or pass automatically.
🌳 Worktree isolation Each task runs in its own branch and worktree. Parallel tasks. Zero conflicts.
⚡ Smart merge Passing every gate? Fusion squash-merges and moves on.
🛰️ Multi-node mesh Laptop, server, cloud, phone — all synced. Desktop, mobile, web.
🧩 Any model Anthropic, OpenAI, Ollama, and more.
🏢 Agent companies Import pre-built teams — 440+ agents across 16 companies.
📬 Inter-agent messaging Built-in mailbox between agents. Delegate, clarify, coordinate.
🗺️ Missions Hierarchical planning with autopilot and validation contracts.
🔓 Open source. MIT. No vendor lock-in. Run it on your own hardware.

Working from chat

Manage tasks without leaving the conversation:

"Every ten minutes, analyze the server code for logic the client hasn't implemented yet and create tasks. Tasks may spawn additional tasks, so just add enough to keep the board saturated."

"Create a Fusion task to fix the login redirect bug"

"Add a task for dark mode support, it depends on FN-003"

"What's the status of FN-042"

"Attach screenshot.png to FN-007"

"Pause FN-012 — I want to add more context first"

The Fusion extension exposes tools to create tasks, check progress, attach files, and pause or resume automation.


Standalone CLI

See STANDALONE.md for additional installation and usage options.

Optional provider: Factory AI via Droid CLI

@runfusion/fusion now ships a vendored @fusion/droid-cli extension in the published CLI bundle.

To use it:

  1. Install the droid binary and ensure it is on your PATH
  2. Authenticate with Droid CLI (droid auth login)
  3. In Fusion dashboard, go to Settings → Authentication and enable Factory AI — via Droid CLI
  4. Restart Fusion when prompted so the extension is loaded into the runtime

Once enabled, droid-cli models appear in Fusion model selection.

Maintainer note: workspace plugins in published CLI bundles

When CLI or dashboard runtime code imports workspace plugin packages (for example @fusion-plugin-examples/roadmap), those imports must stay statically analyzable and covered by packages/cli/tsup.config.ts noExternal rules so plugin runtime code is inlined into dist/bin.js.

Do not introduce dynamic or variable module specifiers for workspace plugin runtime paths in the published execution path. If a workspace plugin is needed for bundled auto-install, stage a bundled plugin entry (dist/plugins/<id>/bundled.js) rather than copying raw TypeScript source into dist/.

Full documentation

Architecture details, development setup, and contributor info live in the project README.

License

MIT — see LICENSE.