Make the dashboard AI session needs-input banner less prominent while preserving visibility rules.
- Reduce the session notification banner spacing, text scale, max heights, and mobile density.
- Cover banner visibility on missions, planning, hidden, empty, and board-session states.
- Add a patch changeset for the published CLI package.
Files changed:
.changeset/fn-7020-session-banner-compact.md | 7 +
.../app/components/SessionNotificationBanner.css | 47 +++--
.../dashboard/__tests__/DashboardBanners.test.tsx | 227 +++++++++++++++++++++
3 files changed, 263 insertions(+), 18 deletions(-)
Fusion-Task-Id: FN-7020
Fusion-Task-Lineage: bd48da60-29ef-4871-ae27-8a1a48f744ea
Optimize the split SettingsModal test suite to avoid default user-event overhead while preserving interaction coverage.
- Add a shared no-delay SettingsModal test user with pointer-event tree checks disabled.
- Route split SettingsModal tests through the shared fast user and use fireEvent for simple form mutations.
- Shorten modal readiness checks to wait on settings loading instead of querying Save repeatedly.
Files changed:
.../__tests__/SettingsModal.general.test.tsx | 124 +++++++--------
.../__tests__/SettingsModal.models-auth.test.tsx | 136 ++++++++--------
.../SettingsModal.remote-notifications.test.tsx | 61 ++++----
.../SettingsModal.scheduling-merge.test.tsx | 174 ++++++++++-----------
.../__tests__/SettingsModal.test-harness.tsx | 32 ++--
.../__tests__/SettingsModal.testMode.test.tsx | 5 +-
.../__tests__/SettingsModal.worktrunk.test.tsx | 5 +-
.../__tests__/SettingsModalNodeRouting.test.tsx | 7 +-
8 files changed, 273 insertions(+), 271 deletions(-)
Fusion-Task-Id: FN-7007
Fusion-Task-Lineage: 42cf8ce2-3da7-4607-8790-5bf46c07b417
## Problem
Fusion runs `pnpm test` as per-task verification. We have hard evidence
from a real task's agent log (FN-7011) that it repeatedly hit the
engine's **15-minute** verification timeout
(`VERIFICATION_TIMEOUT_WORKSPACE_MS = 900_000`) and got SIGKILLed — **9
separate 15.0-minute timeouts in one task, ~2.8h wasted**, after which
the engine restarts the task and re-runs the same lane.
## Root cause
`pnpm test` → `scripts/test-changed.mjs` changed-affected lane runs
`vitest run --changed <base>` for the heavy packages (`@fusion/engine`,
`@fusion/dashboard`), pinned to `workers=1` by the OOM-safety envelope.
But `vitest --changed` does **unbounded transitive module-graph
expansion**: a single changed *hub* source file selects ~the whole
package suite. Measured empirically — one `self-healing.ts`-class change
selects **8,393 test entries** (79s just to *list* them). At 1 worker
that blows past the 15-min kill; the script's own watchdog ceiling for
this class is 20 min, so it never engages. Prior FN-6854/FN-6877 work
fixed *OOM* but not *wall-clock*.
## Fix
A bounded, **git-only** guard in `scripts/test-changed.mjs` (no vitest
probe, no graph build, no widened timeouts/retries/workers — all
forbidden by AGENTS.md):
- New `changedSourceFilesAffectingPackage(pkg, changedFiles, …)` returns
changed **non-test source** within the package's own dir, any transitive
workspace-dependency dir, or the shared
`packages/core/src/__test-utils__` tree.
- In the affected lane for a heavy memory-envelope package: if that list
is non-empty (wide-fan-out risk), run **only the directly-changed test
files** (bounded to the diff) instead of `--changed`; if no test files
changed, **delegate cross-cutting coverage to the merge gate** (already
run first in changed mode) and skip. Test-only diffs keep normal `vitest
--changed`.
- Delegated/partially-tested packages are excluded from the pass-cache
so a partial pass is never recorded as full.
Mirrors the codebase's existing "delegate cross-cutting coverage to the
gate" philosophy (the reverse-dependent blast cap), one level down.
`pnpm test:full` remains the explicit full sweep.
## Proof
- Predictor unit checks + regression suite: `node --test
scripts/__tests__/test-changed.test.mjs` → **111/111 pass** (~3s).
- Bounded path: the explicit-changed-file engine run completes in
**2.79s** vs 79s just to *list* the 8,393-entry fan-out.
- `eslint scripts/test-changed.mjs
scripts/__tests__/test-changed.test.mjs` → exit 0.
- `pnpm build` green; `pnpm verify:fast` green.
No changeset: internal test tooling, not the published
`@runfusion/fusion` package (per AGENTS.md).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1780">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
## What
Adds a configurable built-in **Code Review** diff-review step to the
Fusion coding workflows. It is a workflow prompt-gate step — built
entirely on the existing workflow-step machinery, **not** engine
verification code.
## How (mirrors browser-verification exactly)
- **New catalog template** `code-review` in `WORKFLOW_STEP_TEMPLATES`
(`packages/core/src/types.ts`): `name: "Code Review"`, `toolMode:
"readonly"`, `gateMode: "advisory"` (non-blocking default, same as
browser-verification), `phase: "pre-merge"`. The prompt drives a strong
diff-review focused on the value tests miss — correctness/logic bugs,
broken edge cases, intent-vs-implementation mismatch, regressions in
touched paths, error handling, and contract/signature changes. It reads
`git diff` against the base + changed files, cites `file:line`,
fast-bails APPROVE on trivial/out-of-scope diffs, and ends with exactly
the shared trailing verdict JSON
`{"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}`. No
verdict-parsing code added — the existing gate machinery parses it.
- **New optional-group module**
`packages/core/src/builtin-code-review-group.ts` mirroring
`builtin-browser-verification-group.ts`: resolves the `code-review`
template and builds a **default-OFF** `optional-group` node with stable
group id `code-review` and distinct inner node id `code-review-step`,
sourcing prompt/toolMode/gateMode from the catalog.
- **Wired** into `builtin-coding-workflow-ir.ts` and
`builtin-stepwise-coding-workflow-ir.ts` on the pre-merge path next to
browser-verification: `… → browser-verification → code-review → review`
(failure → end). Default OFF / opt-in via task `enabledWorkflowSteps`;
disabled → byte-inert pass-through.
## Default off / opt-in
The step is **default OFF** and advisory. It only runs when a task's
`enabledWorkflowSteps` includes `code-review`, and
`resolveDefaultOnOptionalGroupIds` never auto-seeds it. Operators can
promote it to a blocking gate.
## Tests
New `builtin-code-review-group.test.ts` (template fields, default-OFF
group node with stable/distinct ids, pre-merge wiring + parse round-trip
for both built-ins, opt-in toggle advertised but never seeded). Updated
the verdict-contract, optional-steps resolver, and
builtin-coding-workflow-ir edge tests. Relevant core workflow suite:
**141 passed**. `tsc --noEmit` clean, eslint clean (0 errors).
## Scope
Pure `packages/core/**` change (+ changeset). No engine files touched.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1779">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a new built-in **Code Review** step to the pre-merge workflow,
available in both coding and stepwise coding flows.
* The step is on by default for new tasks but can still be turned off
per task.
* It also appears in the editor palette as a selectable workflow step.
* **Bug Fixes**
* Fixed default workflow setup so default-on steps are preserved
correctly during task creation and restart.
* Updated workflow paths so Code Review is now included before the final
review stage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
`pnpm test`'s changed-affected lane ran `vitest run --changed <base>` for the
heavy packages (@fusion/engine, @fusion/dashboard). `vitest --changed` does
unbounded transitive module-graph expansion: one changed hub source file
selects ~8,393 test entries (79s just to list), which at the OOM-pinned
workers=1 exceeds the engine's 15-min VERIFICATION_TIMEOUT_WORKSPACE_MS. The
engine SIGKILLs and restarts the task, producing the observed loop of nine
15-min verification timeouts (~2.8h) on a single task.
Guard the lane with a git-only predictor: when a heavy package has changed
non-test source in its graph, run only the directly-changed test files;
when no test files changed, delegate cross-cutting coverage to the merge gate
(already run in changed mode). Test-only diffs keep normal --changed.
Mirrors the existing reverse-dependent blast cap one level down. No widened
timeouts, retries, or worker bumps. test:full remains the explicit full sweep.
Bounded engine run: 2.79s vs 79s. Regression suite 111/111.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Refinement: Code Review is now a DEFAULT-ON but toggleable `optional-group` in the
built-in coding and stepwise coding workflows (defaultOn:true), not a standard
always-on node. It is part of the existing pre-merge flow (execute →
[browser-verification optional] → code-review → review) and runs for every coding
task by default, yet an operator can toggle it off per task by removing `code-review`
from enabledWorkflowSteps; disabled → byte-inert pass-through. Advisory gateMode keeps
it non-blocking (operators can promote to a gate); toolMode readonly.
- Restore the optional-group builder (builtin-code-review-node.ts → -group.ts) with
config.defaultOn:true; stable group id `code-review`, inner id `code-review-step`.
- Wire the default-on optional-group into both built-in coding IRs.
- Fix store default-workflow seeding: interpreter-deferred built-ins (which carry
optional-group nodes) previously bailed to `undefined` in
materializeDefaultWorkflowSteps, dropping default-on group seeding under a
project-default workflow. Now they seed resolveDefaultOnOptionalGroupIds, mirroring
the explicit-workflow path, so defaultOn:true actually takes effect (the executor
enables a group strictly via enabledWorkflowSteps.includes(node.id)).
- Update tests + changeset; full @fusion/core suite green (356 files).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Design correction: Code Review is now a STANDARD, default-ON step in the
built-in coding and stepwise coding workflows — not a default-off optional-group
toggle. It is a regular advisory `prompt` node on the pre-merge success path
(execute → [browser-verification optional] → code-review → review), so it runs
for every coding task with no enabledWorkflowSteps gating. Advisory gateMode means
it does not change merge outcomes; operators can promote it to a blocking gate.
- Replace the optional-group module with a standard prompt-node builder
(builtin-code-review-group.ts → builtin-code-review-node.ts).
- Keep the `code-review` WORKFLOW_STEP_TEMPLATE in the catalog (editor palette).
- Edges unchanged: code-review → review on success, code-review → end on failure
(mirrors the existing review node, no dead-end).
- Update tests + changeset for the standard always-on (no-toggle) semantics.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a configurable "Code Review" diff-review step to the built-in coding and
stepwise coding workflows as a default-OFF optional-group prompt gate. It reuses
the existing workflow-step machinery and the shared trailing-verdict convention
(REVISE blocks, APPROVE/APPROVE_WITH_NOTES pass) — no engine verification code.
- New `code-review` WORKFLOW_STEP_TEMPLATE (toolMode readonly, gateMode advisory,
phase pre-merge) focused on the correctness value tests miss: logic bugs, edge
cases, intent-vs-implementation drift, regressions, error handling, contracts.
- New builtin-code-review-group.ts mirroring builtin-browser-verification-group.ts
(stable group id `code-review`, distinct inner node id `code-review-step`).
- Wired into builtin-coding-workflow-ir.ts and builtin-stepwise-coding-workflow-ir.ts
on the pre-merge path next to browser-verification, default OFF / opt-in.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restores mobile access to all task detail tabs by making the tab strip the horizontal scroller.
- Allow the task-detail content, body, modal tabs, tablet tabs, and embedded tabs to shrink within narrow containers.
- Preserve touch horizontal panning and momentum scrolling on tab strips without moving horizontal overflow to the detail body.
- Cover the Board modal, List embedded pane, and complete tab label set with responsive CSS regression tests.
- Add a patch changeset for the published Fusion package.
Files changed:
.../fn-7012-task-detail-mobile-tabs-scroll.md | 7 +++
.../dashboard/app/components/TaskDetailModal.css | 25 +++++++-
...etailModal.responsive-and-dependencies.test.tsx | 67 +++++++++++++++++++++-
3 files changed, 96 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-7012
Fusion-Task-Lineage: 06b06a81-b9ec-4058-879f-2f5e187a63a4
## What this adds
A **test-free verification command** — `pnpm verify:fast`
(`scripts/verify-fast.mjs`) — that gives deterministic, flake-free
signal without running the test suite. It is fully **additive**: `pnpm
test`, the merge gate (`test:gate`), and CI are untouched.
`docs/testing.md` observes the broad test gate "caught no recalled real
bugs while consuming ~70% of shipping time in flake triage."
`verify:fast` is the opt-in path for non-test verification, suitable as
a project `testCommand`/verification command.
## What verify:fast runs
1. **typecheck — scoped to the changed packages** (each package's
`typecheck` script, or `pnpm --filter <pkg> exec tsc --noEmit -p .` when
none exists).
2. **build — scoped to the changed packages** (`pnpm --filter <pkg>
build`, only for packages that declare a build script).
3. **boot smoke once** (`scripts/boot-smoke.mjs`: CLI `--help` + a real
`fn serve` answering `GET /api/health`), after builds so it runs against
fresh artifacts.
Change-detection **reuses `scripts/test-changed.mjs`** (`getBaseBranch`
/ `detectComparisonBase` / `changedFilesSince` /
`resolveAffectedPackages` / workspace resolution — newly `export`ed)
instead of reinventing git-diff, so it scopes to exactly the packages a
changed-only test run would. With no affected package (root/docs-only
diff) it runs the boot smoke only. Each step is bounded by the existing
`runWithWatchdog` (class `changed`) so a hung tsc/build/serve fails
fast; it streams progress and exits nonzero on the first failing step.
`@fusion/desktop` and `@fusion/mobile` are skipped, mirroring the root
`build`/`typecheck` exclusions.
## Measured wall-time
On this branch's diff (which resolves to the heaviest package,
`@fusion/dashboard`), end-to-end:
```
[verify:fast] plan: typecheck:@fusion/dashboard -> build:@fusion/dashboard -> boot-smoke
[verify:fast] OK typecheck @fusion/dashboard (~44s)
[verify:fast] OK build @fusion/dashboard (26.2s)
[verify:fast] OK boot smoke (CLI --help + real serve /api/health) (19.6s)
[verify:fast] PASS — 3 step(s) green in 90.3s (no tests run).
```
**~90s total**, deterministic and flake-free. By contrast a typical
**scoped test run for the same package** is far heavier and flake-prone:
`docs/testing.md` notes a dashboard task "otherwise re-ran all 822
dashboard test files (~5-8 min)", and `pnpm test` additionally runs the
merge-gate suite first. verify:fast trades that test-suite cost (and its
flake-triage tax) for a typecheck+build+boot signal in ~1.5 min.
## Doc additions
- `AGENTS.md` + `docs/testing.md` testing-commands lists now include
`pnpm verify:fast`, described as the recommended **test-free
verification** (typecheck + build + boot-smoke), suitable as a project
`testCommand`/verification command; the full suite stays available and
runs non-blocking.
## Tests / verification
- New `scripts/__tests__/verify-fast.test.mjs` (11 tests) pins the pure
planning / arg-construction logic — scoped typecheck/build selection,
build-script gating, desktop/mobile exclusion, boot-smoke-only fallback,
and reuse of `resolveAffectedPackages`. It never spawns real
tsc/build/vitest.
- `pnpm verify:fast` runs end-to-end and exits 0 (output above).
- Lint clean on all new/changed files; `agents-md-invariants`,
`check-test-inventory`, `verify-fast`, and `test-changed` script tests
all green (132 tests).
No changeset (scripts + docs + CI-tooling, behavior-additive;
`@runfusion/fusion` runtime unaffected).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1777">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
## What
A **test value audit**: a heuristic that scores every test file under
`packages/*/src/**/__tests__/**` and
`packages/dashboard/app/**/__tests__/**` by how much real regression
signal it has encoded over its git history, then ranks **slow AND
low-value** files first as deletion candidates. This is the **evidence
base** for a human/follow-up deletion decision — **the script deletes
nothing**.
Motivated by AGENTS.md "Do Not Add Slow Tests" (FN-5048) + the
quarantine deletion ratchet: we want data on which slow tests are also
low-signal so they can be cut without losing coverage.
## How it scores (HEURISTIC, not ground truth)
Single whole-history `git log --name-status` pass; per-commit
classification (renames followed backward):
- **Positive** — `fix(...)`/`fix:` with sibling source change (+3), fix
alone (+2), `## Symptom Verification` regression marker (+3, FN-5893),
test added-with-source (+2)/alone (+1), plain test+source co-change
(+1.5).
- **Negative** — subject/body churn keywords
`flake/flaky/deflake/quarantine/stabiliz/appease/timeout/retry` (−3),
test-only modify with no source (−1), quarantine-ledger membership
current+historical (−5).
`valueScore` = sum of weights. `deletionPriority = durationMs / (1 +
max(0, valueScore))` (+ small net-negative boost), joined with
`scripts/test-timings.json` so slow + low-value surfaces first.
Recommendation: `delete` (≤0) / `review` (≤3) / `keep` (>3). A
`safeDelete` flag marks files meeting the ratchet's churn/quarantine
bar.
## Deliverables
- `scripts/test-value-audit.mjs` — runner (git IO + report generation)
- `scripts/lib/test-value-audit-lib.mjs` — pure, unit-tested scoring
logic
- `scripts/__tests__/test-value-audit.test.mjs` — 15 synthetic-record
unit tests
- `docs/test-value-audit.json` + `docs/test-value-audit.md` — generated
artifacts (top 40 + methodology + honest caveats: heuristic limits,
git-follow/squash-merge blind spots, lying subjects, timing snapshot)
## Verification
- `node scripts/test-value-audit.mjs` runs end-to-end (~1s), 2051 files
analyzed, writes both artifacts.
- `node --test scripts/__tests__/test-value-audit.test.mjs` → 15/15
pass.
- `eslint` clean on all three new source files.
No changeset (scripts + docs only; `@runfusion/fusion` runtime
unaffected).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1776">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
## Summary
Quarantine 3 test files consistently failing on the non-blocking
full-suite CI on `main`. Per the AGENTS.md deletion-ratchet policy, each
is added to `scripts/lib/test-quarantine.json` with a matching exclude
in its package's vitest config. Tests will be deleted after 14 days
unless rescued with a root-cause fix.
## Quarantined Tests
| File | Shard | Failure | CI Run |
|------|-------|---------|--------|
|
`engine/src/__tests__/self-healing-fn-5488-fast-path-regressions.test.ts`
| 1/4 | `expected +0 to be 1` + `parseFileScopeFromPrompt is not a
function` | [run
28206337202](https://github.com/Runfusion/Fusion/actions/runs/28206337202)
|
| `engine/src/__tests__/in-review-merge-stall-deadlock-recovery.test.ts`
| 2/4 | `expected 'FN-5485' to be null` | [run
28206337202](https://github.com/Runfusion/Fusion/actions/runs/28206337202)
|
| `dashboard/app/components/__tests__/DevServerView.mobile.test.tsx` |
4/4 | `expected +0 to be 1` (mobile CSS structure) | [run
28206337202](https://github.com/Runfusion/Fusion/actions/runs/28206337202)
|
## Verification
- `pnpm test:gate` passes (313 core + 58 ci-shape tests)
- `pnpm lint` clean
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1775">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated the test quarantine list to exclude several flaky or failing
tests from routine dashboard and engine test runs.
* Added records for newly quarantined tests, including the date they
were marked and the CI issue they were linked to.
* Continued using the quarantine list across relevant test projects to
keep CI runs more stable.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
Hundreds of DB-backed tests build a fresh in-memory store in
`beforeEach` and call `db.init()`, which replays `SCHEMA_SQL` + **~129
migrations every single test** (~40ms each). Across thousands of tests
this is minutes of pure setup. The slowest core store suites are
dominated entirely by this.
## Approach (Option A: serialize/deserialize snapshot)
`node:sqlite` (and `bun:sqlite`) expose `serialize()`/`deserialize()`. I
migrate **one** in-memory DB per test file, serialize it to a byte
buffer, and register it via a test-only hook. Every subsequent in-memory
`Database` deserializes the snapshot at open time, so `init()` finds
`schemaVersion === SCHEMA_VERSION` plus the matching compat fingerprint
and short-circuits `migrate()` + all backfills.
Why this over the existing truncate-based
`createSharedTaskStoreTestHarness`: the snapshot keeps the **exact same
per-test isolation model** — each test still constructs its own
brand-new, fully-isolated DB — so suites that reassign their store/db
inside test bodies (both targets do) need no restructuring. Only the
migration cost is amortized. Disk-backed (production) DBs are never
touched; the hook is `null` in production, so behavior is unchanged.
### Harness API
```ts
beforeAll(() => installInMemoryDbSnapshot());
afterAll(() => clearInMemoryDbSnapshot());
// existing per-test `new <Store>({ inMemoryDb: true }); init()` stays as-is
```
- `packages/core/src/__tests__/store-test-helpers.ts` — core suites
- `packages/dashboard/src/__tests__/db-snapshot-helper.ts` — dashboard
suites (core `__tests__` is a private cross-package dir, so it mirrors
via the new public `setInMemoryTemplateSnapshot` export)
## Before / after
Raw `db.init()` microbenchmark: **43.4ms → 5.4ms (8x)**.
| Suite | Tests | Before | After | Note |
|---|---|---|---|---|
| `agent-store.test.ts` | 199 | 13.12s | **3.32s** | ~4x; init-dominated
|
| `mission-store.test.ts` | 261 | 17.62s | **5.69s** | ~3x; min of 3 |
| `workflow-routes.test.ts` | 53 | tests 4.38s | **tests 2.79s** | min
of 5; not init-dominated, so a smaller (~36%) but real win — most of its
time is express/route logic, not DB init |
All converted suites pass with **0 failures** and every original
assertion preserved. `db.test.ts` (which tests init/migration directly)
is intentionally left unconverted and still passes. Core + dashboard
typecheck clean; lint clean.
> Honest note: `workflow-routes` machine timings were noisy (same config
varied 5–13s under load); the `tests`-portion min-of-5 is the reliable
signal. The snapshot helps every in-memory suite, but the suite-level
win scales with how init-dominated the suite is.
## No changeset
Changes are test-infra only and behavior-preserving for the published
bundle — the snapshot hook is a no-op (`null`) in production. Per
AGENTS.md, no changeset for behavior-preserving/internal changes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1774">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Improved in-memory database handling for test runs by reusing a
prepared snapshot instead of rebuilding it repeatedly.
* Added snapshot support to the database layer and SQLite adapter to
speed up initialization in test environments.
* Updated core and dashboard test suites to use shared setup/teardown
for the cached database state.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What
Splits the giant
`packages/dashboard/app/components/__tests__/ChatView.test.tsx` (**231
tests, ~24s, one sequential worker**) into 3 parallelizable sibling
files sharing a harness — the same pattern already used for
`SettingsModal` — and fixes a latent test-isolation bug it exposed.
### Split (sum unchanged = 231)
| File | tests |
|------|------|
| `ChatView.core.test.tsx` | 140 |
| `ChatView.sessions-rooms.test.tsx` | 40 |
| `ChatView.mobile.test.tsx` | 51 |
`ChatView.test-harness.tsx` exports fixtures, helpers (`renderWithAct`,
`setupMockChat`, `setupMockRooms`, `mockViewportMode`,
`renderRoomCreation`, …), the `vi.mocked` handles, and
`installChatViewEnv()` (the former file-level `beforeEach`/`afterEach`).
The `vi.mock(...)` factories stay **inline & self-contained** in each
test file — delegating them to a harness export triggers a TDZ
`ReferenceError` because the harness imports `ChatView`/`../../api`.
### FN-4327 isolation bug (root cause + fix)
`Direct/Rooms scope toggle > "FN-4327: switching scope from Rooms to
Direct re-anchors direct thread"` failed standalone/split with `expected
500 to be 1200`.
**Root cause:** the Direct↔Rooms toggle swaps subtrees in ChatView's
render (`chatScope` ternary), so the `.chat-messages` container
**unmounts** on entering Rooms and a **fresh node mounts** on returning
to Direct. The re-anchor effect (`anchorToBottom` on scope change)
correctly targets that remounted node — whose jsdom `scrollHeight` is
`0`. The pre-split file mocked geometry on the *pre-toggle* node and
only passed via a timing race against the remount (confirmed:
`sameNode=false`, `afterScrollHeight=0`).
**Fix (no assertion weakening):** install scroll geometry at the
prototype level (restored in `finally`, per-node `scrollTop` backing) so
whichever `.chat-messages` node is live — including the remounted one —
reports `scrollHeight 1200`, making the re-anchor deterministic.
### vitest.config.ts
- Repoint `dashboard-app-quality-chat` (`qualityAppChatOnlyTests`) to
the 3 new files.
- Drop bare `"ChatView"` from `qualityAppComponentTests` and
`isolatedQualityAppComponentTests`.
- Spread `qualityAppChatOnlyTests` into `backfillAppExclude` (mirroring
the settings split) so the files aren't double-collected by the app
backfill lane.
## Verification
- 3 new files together: **231 passed / 0 failed**, stable across 2 runs.
- FN-4327 passes **standalone** (`-t "FN-4327"`) **and** in the full
split run.
- `vitest list --filesOnly` → each new file collected by exactly **one**
project (`dashboard-app-quality-chat`); harness not collected; no
backfill double-collection.
- ESLint on all 4 new files: exit 0.
- Combined Duration ~**17s** (vs original ~24s); in CI the 3 files
parallelize across workers within the chat project.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1773">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved chat experience reliability across mobile and desktop,
including session switching, room navigation, keyboard behavior,
scrolling, and sidebar interactions.
* Strengthened coverage for room creation, scope switching, and message
refresh behavior to help prevent regressions.
* **Chores**
* Reorganized automated checks to run chat-related scenarios more
consistently and avoid duplicate test collection.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Agents were free to pass `allowFullSuite: true` to
`fn_run_verification`, which runs a marathon command (`pnpm test`, `pnpm
test:full`, whole-package tests) far beyond what a change needs — the
main way verification balloons past its budget.
This strengthens the guidance in three places agents read:
- **`run-verification-tool.ts`** — the `allowFullSuite` param
description now leads with "DO NOT SET THIS unless absolutely necessary"
and points to a file-scoped command.
- **`AGENTS.md`** — new standing rule: scope verification to changed
files; reserve `allowFullSuite` for cross-cutting changes with no
targetable test set; the thin merge gate is the safety net.
- **`docs/testing.md`** — same emphasis inline.
No functional change. Pairs with the file-scoped-verification work
(verification now runs only the tests affected by the diff).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1772">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Clarified verification guidance to strongly prefer targeted,
file-scoped test runs for changed files.
* Added clearer rules for when full-suite verification may be used,
including when to note the reason.
* Updated the `allowFullSuite` guidance to emphasize it as a last-resort
option while keeping timeout behavior unchanged.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Adds scripts/verify-fast.mjs + root `pnpm verify:fast`, an opt-in, flake-free
verification path that runs typecheck + build scoped to the changed packages
(reusing test-changed.mjs git-diff / changed-package resolution) plus the
existing boot smoke once, with no test suite. Each step is bounded by the
shared runWithWatchdog (class "changed"); exits nonzero on the first failure.
No default changed: pnpm test, the merge gate, and CI are untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add scripts/test-value-audit.mjs + scripts/lib/test-value-audit-lib.mjs:
a heuristic that scores every test file under packages/*/src/**/__tests__/**
and packages/dashboard/app/**/__tests__/** from git history, classifying
commits as positive (fix+source co-change, Symptom Verification regressions,
added-with-source) vs negative (flake/quarantine/timeout churn, test-only
modifies, quarantine-ledger membership). Joins per-file durations from
scripts/test-timings.json so SLOW + LOW-VALUE files rank first as deletion
candidates. Emits docs/test-value-audit.json + docs/test-value-audit.md
(top 40 + methodology + caveats). Pure scoring logic is unit-tested with
synthetic commit records. The script never deletes tests — evidence only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Quarantine three test files consistently failing on the non-blocking
full-suite CI on main, per the AGENTS.md deletion-ratchet policy:
- engine self-healing-fn-5488-fast-path-regressions.test.ts (shard 1)
- engine in-review-merge-stall-deadlock-recovery.test.ts (shard 2)
- dashboard DevServerView.mobile.test.tsx (shard 4)
Each has a matching entry in scripts/lib/test-quarantine.json with
the failing CI run link and quarantinedAt date. Tests will be deleted
after 14 days unless rescued with a root-cause fix.
db.init() replays SCHEMA_SQL + ~129 migrations on every fresh in-memory
DB (~40ms each), which is minutes of pure setup across thousands of
DB-backed tests. Add a test-only migrated-schema snapshot: migrate ONE
in-memory DB per test file, serialize it, and deserialize a fresh copy
per test instead of re-migrating. Each test still gets a brand-new,
fully-isolated in-memory DB; only the migration cost is amortized.
- sqlite-adapter: expose serialize()/deserialize() (node:sqlite + bun)
- db.ts: setInMemoryTemplateSnapshot() hook (test-only, null in prod) +
serializeSnapshot(); constructor deserializes the snapshot for
in-memory DBs so init() short-circuits migrate()+compat at v129
- store-test-helpers: install/clearInMemoryDbSnapshot harness
- dashboard: db-snapshot-helper mirror (core __tests__ is cross-package)
- convert agent-store, mission-store, workflow-routes suites
Measured (raw db.init(): 43ms -> 5ms, 8x):
- agent-store 13.12s -> 3.32s
- mission-store 17.62s -> 5.69s (min of 3)
- workflow-routes tests 4.38s -> 2.79s (min of 5; not init-dominated)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Split packages/dashboard/app/components/__tests__/ChatView.test.tsx (231 tests,
~24s, one sequential worker) into 3 sibling files sharing ChatView.test-harness,
mirroring the SettingsModal split, so the dashboard chat project parallelizes them:
- ChatView.core.test.tsx (140 tests)
- ChatView.sessions-rooms.test.tsx (40 tests)
- ChatView.mobile.test.tsx (51 tests)
sum = 231 (unchanged)
vi.mock factories stay inline & self-contained per file (delegating them to a
harness export triggers a TDZ ReferenceError because the harness imports
ChatView/../../api). The harness exports fixtures, helpers, the vi.mocked handles,
and installChatViewEnv() (former file-level beforeEach/afterEach).
Fix latent isolation bug in the FN-4327 re-anchor test: the Direct<->Rooms toggle
swaps subtrees in ChatView's render, so `.chat-messages` REMOUNTS on the round
trip. The re-anchor effect correctly targets the freshly-mounted node, whose jsdom
scrollHeight is 0. The pre-split file mocked geometry on the pre-toggle node and
only passed via a timing race against the remount; standalone/split it fails
"expected 500 to be 1200". Install scroll geometry at the prototype level (restored
in finally) so the remounted node reports scrollHeight 1200, making the re-anchor
deterministically observable without weakening the assertion.
vitest.config.ts: repoint dashboard-app-quality-chat to the 3 new files, drop bare
"ChatView" from qualityAppComponentTests/isolatedQualityAppComponentTests, and spread
qualityAppChatOnlyTests into backfillAppExclude (mirroring the settings split) so the
files aren't double-collected by the app backfill lane.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make the AI mission planning workspace movable on desktop and safer when streams fail.
- Host the Plan Mission with AI modal in FloatingWindow with desktop drag/resize geometry and mobile full-screen preservation.
- Normalize terminal mission interview stream failures, close SSE/keepalive once, and suppress duplicate late terminal events.
- Cover modal geometry and stream-error behavior with dashboard tests and document the operator-facing behavior.
Files changed:
.changeset/fn-6975-mission-modal-stream.md | 7 ++
docs/dashboard-guide.md | 7 ++
.../api/__tests__/mission-interview-stream.test.ts | 98 ++++++++++++++++++
packages/dashboard/app/api/legacy.ts | 66 ++++++++++---
.../app/components/MissionInterviewModal.css | 51 ++++++++++
.../app/components/MissionInterviewModal.tsx | 37 ++++---
.../__tests__/MissionInterviewModal.test.tsx | 110 ++++++++++++++++++++-
7 files changed, 344 insertions(+), 32 deletions(-)
Fusion-Task-Id: FN-6975
Fusion-Task-Lineage: b2ffa558-8b7e-4a46-8882-f2c4f6189831
Strengthen the fn_run_verification allowFullSuite parameter description, add an
AGENTS.md standing rule, and update docs/testing.md so agents default to a
file-scoped verification command and reserve allowFullSuite for genuinely full
runs with no targetable test set. allowFullSuite is the main way verification
balloons past its budget; the thin merge gate is the cross-cutting safety net.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Refresh the opt-in line-count guard so current files match the recorded baseline.
- Document why the guard remains outside the default test gate.
- Re-ratchet current line-count violations after organic growth.
- Tighten or prune stale baseline entries and grandfather two long-existing over-cap files.
Files changed:
scripts/check-file-line-count.mjs | 3 +
scripts/line-count-baseline.json | 133 +++++++++++++++++++-------------------
2 files changed, 69 insertions(+), 67 deletions(-)
Fusion-Task-Id: FN-7013
Fusion-Task-Lineage: bd770058-5b42-4d63-a18d-bf46b7b957e0
Diff-proportional verification (deriveFileScopedPnpmTestCommand) + scope-aware
verification timeout, so merge/step checks finish in seconds. Propagated to this
worktree directly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep mobile New Task dialog controls reachable and tappable under keyboard-constrained viewports.
- Re-enable hit testing on the New Task sheet while preserving desktop overlay click-through behavior.
- Bound GitHub, dependency, and agent picker popups so mobile users can scroll them inside the sheet.
- Add regression coverage for mobile dialog affordances and document the mobile behavior.
- Add a patch changeset for the published Fusion package.
Files changed:
.changeset/fn-7002-mobile-new-task-affordances.md | 7 ++
docs/dashboard-guide.md | 2 +-
packages/dashboard/app/components/NewTaskModal.css | 18 +++++
.../app/components/__tests__/NewTaskModal.test.tsx | 87 +++++++++++++++++++++-
.../__tests__/core-modals-mobile.test.tsx | 32 ++++++++
5 files changed, 144 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-7002
Fusion-Task-Lineage: 31c2504e-56fd-4395-bbe3-e753aab04e23
## Problem
Fusion's verification gate (the merger, and the executor's per-step
auto-gate) runs the project's configured `testCommand`/`buildCommand`
bounded by a **flat 10-minute** default
(`VERIFICATION_COMMAND_TIMEOUT_MS = 600_000`) when no
`verificationCommandTimeoutMs` override is set. A **workspace-scoped**
command (a full suite that legitimately takes ~10+ min) hits that wall
and is killed as an **infra `timedOut`** — blocking the merge — even
though nothing is actually hung. Meanwhile a **package-scoped** command
got a too-generous bound. The `fn_run_verification` tool already derived
its default from scope (300s/900s); the merger/executor did not.
## Change
Make the shared `runVerificationCommand` (used by both the merger and
the executor auto-gate) **scope-aware**, mirroring the tool:
- **package-scoped** (`pnpm --filter`/`-F …`) → **300s**
- **workspace-scoped** (root command like `pnpm test`) → **900s**
An explicit project `verificationCommandTimeoutMs` still overrides, and
the 30-min hard cap (`VERIFICATION_COMMAND_HARD_CAP_MS`) still clamps.
New `classifyVerificationScope` / `defaultVerificationTimeoutMs` helpers
mirror `run-verification-tool`'s `DEFAULT_TIMEOUT_PACKAGE_SEC` (300) /
`DEFAULT_TIMEOUT_WORKSPACE_SEC` (900).
## Verification
- `verification-utils.test.ts` (new scope-classification + default
cases), `run-verification-command.test.ts`,
`merger-verification.test.ts` — **143 tests pass**.
- Lint clean. `patch` changeset added.
Note: a workspace command needing >900s should be **scoped** (FN-5048 /
the bounded-verification guidance), or set
`verificationCommandTimeoutMs` explicitly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1771">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Verification (merge/step gate) timeouts are now scope-aware:
package-scoped commands default to 300s and workspace-scoped commands
default to 900s.
* If a custom timeout is provided, it still overrides the default, while
the safety hard cap remains enforced.
* **Bug Fixes**
* Prevents verification jobs from using an overly generic fixed timeout,
reducing unnecessary early timeouts or excessive waits.
* **Tests**
* Expanded coverage to validate scope detection and the new default
timeout behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Follow-up to #1765 (which fixed the first 30). Fixes ~19 more
deterministic dashboard test failures that were pre-existing on `main`
in the non-blocking full-suite lane. Mix of **real product fixes** and
stale-test reconciliation — no appeasement (no widened timeouts, skips,
or weakened assertions). Rebased onto latest `main`.
## Real product fixes (guards caught genuine regressions)
- **Info-toast contrast (WCAG AA):** shadcn-custom light theme had
white-on-`#0284c7` (4.10 < 4.5); enrolled it in the light-mode dark-text
correction.
- **27 undefined CSS token references** (typos/foreign tokens) renamed
to canonical tokens; defined the genuinely-intended `--border-strong`
and `--right-dock-min/max-width`.
- **Raw `rgba()` box-shadow** tokenized to `color-mix`; dev-server
mobile header split into its own responsive rule.
## Stale tests reconciled with intentional product changes
- `workflowColumns` graduated to always-on (`buildBoardWorkflowsPayload`
unit test).
- Workflow optional-steps source re-pointed to v2 `optional-group`
nodes.
- Command-center pricing docs (filled one real gap: `openai-codex:*`
keying).
- SetupWizardModal `detectWorkspace` + `workspaceMode`/`taskPrefix`
payload.
- board-mobile listener-count assertion → unmount no-throw behavior.
- CommandCenterControls / ThemeSelector "Default" → "Fusion Legacy"
relabel.
- ProjectOverview / WorkflowNodeEditor header divider intentionally
removed.
## Verification
- foundation-ui lane fully green (56 files / 487 tests); all
originally-failing files pass.
- All CSS hygiene/token-validity guards green post-tokenization (no new
violations).
- `patch` changeset added (toast-contrast + tokenization ship in
`@runfusion/fusion`).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1770">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved dashboard styling consistency across several screens,
including better contrast for toast messages and more reliable theme
colors, shadows, and spacing.
* Fixed mobile and responsive layout behavior in dashboard views so
headers, dropdowns, and terminal controls render more cleanly.
* Updated labels and wording in theme-related UI to match the current
experience.
* Resolved a few stale dashboard tests to align with recent product
changes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
echo ok is workspace-scoped, so the default verification budget is now 900s
(VERIFICATION_TIMEOUT_WORKSPACE_MS) rather than the retired flat 600s. Assert via
defaultVerificationTimeoutMs so the expectation tracks the scope-aware default.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The merger and executor verification gate (shared runVerificationCommand) used
a flat 10-min default (VERIFICATION_COMMAND_TIMEOUT_MS) for any configured
test/build command, while the fn_run_verification tool already derived its
default from command scope. A workspace-scoped command (a full suite, ~10+ min)
hit the flat 10-min wall and was killed as an infra timeout; a package-scoped
command got a too-generous bound.
Derive the default from command scope to match the tool: package-scoped
(pnpm --filter/-F ...) → 300s, workspace-scoped (root command like pnpm test)
→ 900s. An explicit project verificationCommandTimeoutMs still overrides, and
the 30-min hard cap still clamps the result. Covers both the merger and the
executor per-step auto-gate, which share runVerificationCommand.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixes ~19 deterministic dashboard test failures pre-existing on origin/main
(non-blocking full-suite lane). Mix of real product fixes and stale-test
reconciliation; no appeasement (no widened timeouts, skips, or weakened
assertions).
Product CSS fixes (real regressions the guards caught):
- Info toast contrast: shadcn-custom light theme had white-on-#0284c7 (4.10,
below WCAG AA 4.5); enrolled it in the light-mode dark-text correction.
- 27 undefined CSS token references (typos/foreign tokens) renamed to canonical
defined tokens; defined the genuinely-intended --border-strong and
--right-dock-min/max-width.
- Raw rgba() box-shadow fallback tokenized to color-mix; dev-server mobile
header split into its own responsive rule.
Stale tests reconciled with intentional product changes:
- workflowColumns graduated to always-on (board-workflows unit test).
- workflow optional-steps source re-pointed to v2 optional-group nodes.
- command-center pricing docs (one doc gap filled: openai-codex:* keying).
- SetupWizardModal added detectWorkspace + workspaceMode/taskPrefix payload.
- board-mobile listener-count assertion → unmount no-throw behavior.
- CommandCenterControls / ThemeSelector: default theme relabeled "Fusion Legacy".
- ProjectOverview / WorkflowNodeEditor: header divider intentionally removed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-up to #1767. Safe, track-forward storage cleanup — **no history
rewrite, no force-push.**
## What
- Extend the Git LFS policy from GIFs to **documentation/marketing PNG
screenshots** (`docs/screenshots/**`, `demo/**`, top-level
`screenshots/**`) — 53 PNGs converted to LFS pointers.
- Ran `git gc --prune=now` locally: consolidated 7 packfiles → 1 and
pruned loose objects (**local `.git` 421M → 300M**; this is a
local-clone benefit, not a remote-history change).
## Deliberately excluded (stay as real blobs)
These are build/runtime assets — an LFS-less build env would otherwise
embed a 132-byte pointer stub and break them:
- `packages/dashboard/app/public/icons/*.png` — PWA manifest icons
(served)
- `packages/desktop/src/icons/*.png` — Electron app/tray icons
(packaged)
- `packages/dashboard/app/public/fonts/SymbolsNerdFontMono-Regular.ttf`
— `@font-face` source (served)
## Verified
- No runtime icon/font asset entered LFS (`git lfs ls-files` excludes
`icons/`, `fonts/`, `.ttf`).
- `docs-screenshot-links` test still passes — it checks path existence,
and LFS pointer files satisfy `existsSync`.
## Not in scope
The ~300MB of stale binary history (old GIF/PNG revisions) is only
reclaimable via a history rewrite (force-push + re-clone) — tracked
separately as Tier 2.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1768">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Workflow editing now opens in a floating window with improved drag,
sizing, and close behavior.
* Workflow switchers now pass the selected workflow into the editor, so
the chosen workflow opens directly.
* **Bug Fixes**
* Improved mobile and desktop layout behavior for the workflow editor,
including overlay sizing and scroll handling.
* Updated navigation and onboarding flows to match the latest sidebar
and empty-state behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What
Routes `demo/assets/*.gif` through **Git LFS** and converts the 20
existing reel GIFs to LFS pointers. Adds a Git LFS setup note to
`docs/contributing.md`.
## Why
The demo reel GIFs dominate repo size: the same captures get re-shot and
re-committed, and git keeps every old blob forever (~118 MB of GIF
history backing a ~421 MB `.git`). Routing them through LFS keeps the
binaries out of the packfile so future regenerations stop bloating
history.
## Scope / blast radius
- **Track-forward only** — existing history is left intact. No
`filter-repo` rewrite, no force-push, no re-clone required.
- This does **not** shrink the current `.git` (old blobs remain in
history); it stops the bleeding going forward.
- Contributors must have `git lfs install` configured, or the GIFs
arrive as pointer stubs — documented in `docs/contributing.md`.
## Notes
- GitHub free LFS tier is 1 GB storage + 1 GB/month bandwidth; live GIFs
are ~49 MB. Worth keeping an eye on LFS bandwidth for a trafficked
public repo.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1767">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Added Git LFS tracking for GIFs in the demo assets folder to help keep
the repository size manageable.
* **Documentation**
* Updated contributor setup instructions with Git LFS guidance,
including installation, pulling existing large files, and how new GIFs
are handled automatically.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
The global mobile fullscreen modal rule (`.modal-lg`, `.modal:not(.confirm-dialog)`)
forced the embedded Planning shell to 100dvh, overflowing its bounded `.planning-view`
pane. `overflow:hidden` then clipped the footer action buttons and blocked scrolling.
Qualify the mobile embedded override as `.planning-view.open .planning-modal--embedded`
so it outranks the global rule, and re-pin `max-height:100%` so the inner flex scroll
chain works. Adds a CSS regression test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extend the LFS track-forward policy from GIFs to documentation and marketing
PNG screenshots (docs/screenshots, demo, top-level screenshots). Scoped to
doc/demo dirs only; app-runtime/build images (PWA icons, Electron tray icons,
the served Nerd Font) stay as real blobs so LFS-less build envs never embed a
pointer stub. No history rewrite / force-push. Stacks on the GIF LFS change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Track demo/assets/*.gif via Git LFS and convert the 20 existing reel GIFs
to LFS pointers. Stops binary GIF regenerations from bloating .git going
forward; existing history is left intact (no rewrite/force-push).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## What & why
`pnpm test` on `main` failed **30 tests** across 5 dashboard files. All
ran in the **non-blocking full-suite lane** (not the merge gate), so
they went unnoticed despite being deterministic. Every one is a **stale
test trailing an intentional product change** — fixes are **test-only**,
with **no product code changed** and **no appeasement** (no widened
timeouts, no `.skip`, no weakened assertions).
## Root causes & fixes
| File | Failures | Root cause | Fix |
|---|---:|---|---|
| `App.test.tsx` | 26 | Sidebar-destination tests (view switching, chat
unread, GitHub import, board branch filters) never set `leftSidebarNav:
true`; the shared `defaultSettings` keeps it `false` to preserve legacy
header-nav tests, so the sidebar never rendered. The backend-unreachable
recovery test asserted a setup wizard that **intentionally no longer
auto-opens** on zero projects (`useViewState` FNXC:Onboarding
2026-06-22-05:06) with `modelOnboardingComplete: true`. | Opt each
sidebar describe/test into `leftSidebarNav: true`; assert recovery to
the dashboard shell instead of the retired auto-wizard. |
| `board-workflows-route.test.ts` | 1 | `workflowColumns` flag
**graduated to always-on** (`isWorkflowColumnsEnabled` returns `true`;
stale persisted `false` treated as enabled) — the flag-OFF empty-shape
branch is retired. | Assert the graduation invariant (persisted `false`
→ `flagEnabled: true`). |
| `promote-route.test.ts` | 1 | Same graduation: the flag-OFF → `400`
branch is dead, so the route proceeds and 500s on the incomplete mock. |
Assert persisted `false` proceeds to the engine (no legacy 400). |
| `register-command-center-routes.auth.test.ts` | 1 |
`/command-center/tokens` now reads `modelPricingOverrides` via
`getGlobalSettingsStore()`; `MockStore` lacked it → 500. | Add the
`getGlobalSettingsStore()` stub. |
| `PlanningModeModal.initial.test.tsx` | 1 | The shared `.spin` loader
keyframe was renamed `spin` → `fusion-spinner-spin` for
collision-proofing. | Update the CSS regex to the current keyframe. |
## Verification
- All 5 files together: **161 passed / 0 failed** (`App.test.tsx`
128/128).
- ESLint on all 5 files: exit 0.
- `git diff` touches **test files only** — confirmed no product/source
file changed, and no `timeout:`/`.skip`/removed-`expect` introduced.
## Notes
- No changeset (test-only).
- Diagnosis confirmed by instrumenting `App.tsx` (reverted): after
settings load, `leftSidebarNavEnabled` flipped to `false` because the
fixture set `leftSidebarNav: false`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1765">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Dashboard navigation now consistently follows the new default sidebar
layout.
* Restored dashboard recovery flow after a backend outage so the normal
shell returns cleanly when service resumes.
* Workflow-related actions and board views now behave as enabled even
when older saved settings say otherwise.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
These deterministic failures lived in the non-blocking full-suite lane
(App.test.tsx + three API-backfill route tests + one modal test), so the
merge gate never surfaced them. All are stale tests trailing intentional
product changes — fixes are test-only; no product code and no appeasement
(no widened timeouts, no skips, no weakened assertions).
App.test.tsx (26): sidebar-destination tests (view switching, chat unread,
GitHub import, board branch filters) never opted into leftSidebarNav:true,
so with the shared defaultSettings keeping it false (to preserve legacy
header-nav tests) the sidebar never rendered. Enable leftSidebarNav per
sidebar describe/test. The backend-unreachable recovery test asserted a
setup wizard that intentionally no longer auto-opens on zero projects
(useViewState FNXC:Onboarding 2026-06-22-05:06) with modelOnboardingComplete
true — assert recovery to the dashboard shell instead.
board-workflows-route + promote-route: the workflowColumns flag graduated to
always-on (isWorkflowColumnsEnabled returns true; stale persisted false is
treated as enabled), retiring the flag-OFF 400/empty-shape branches. Update
both "flag OFF" tests to assert the graduation invariant.
register-command-center-routes.auth: the /command-center/tokens handler now
reads modelPricingOverrides via getGlobalSettingsStore(); MockStore lacked it,
yielding a 500. Add the stub.
PlanningModeModal.initial: the shared .spin loader keyframe was renamed
spin -> fusion-spinner-spin for collision-proofing; update the CSS regex.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep Command Center token usage surfaces mounted and updated during live analytics polling.
- Preserve existing analytics data while background polls are in flight so token surfaces revalidate without disappearing.
- Add live refresh intervals for Overview and Tokens token-usage data.
- Cover in-place token stat, chart, and model-row updates with Command Center and area tests.
- Add a patch changeset for the published Fusion package.
Files changed:
.changeset/fn-6970-command-center-token-live.md | 7 ++
.../components/command-center/CommandCenter.tsx | 4 +
.../__tests__/CommandCenter.test.tsx | 81 +++++++++++++--
.../components/command-center/areas/AreaShell.tsx | 3 +
.../components/command-center/areas/TokensArea.tsx | 4 +
.../command-center/areas/__tests__/areas.test.tsx | 111 +++++++++++++++++++--
.../command-center/areas/useAnalyticsArea.ts | 12 ++-
7 files changed, 208 insertions(+), 14 deletions(-)
Fusion-Task-Id: FN-6970
Fusion-Task-Lineage: 670bb5ac-bc7d-47d8-abed-ef6748292cc6
Dashboard Back navigation now dismisses task detail surfaces before leaving the current context.
- Add full-panel task-detail history entries that restore board/list state or the previous nested detail.
- Route modal task-detail Back handling through the same close path as explicit dismissal so deep-link cleanup runs.
- Cover board-opened, nested, and modal popstate flows and document the Back behavior.
- Add a patch changeset for the published Fusion dashboard behavior.
Files changed:
.changeset/fn-6964-dashboard-back-navigation.md | 7 ++
docs/dashboard-guide.md | 3 +-
packages/dashboard/app/App.tsx | 50 ++++++++++--
packages/dashboard/app/components/AppModals.tsx | 31 ++++++--
.../app/components/__tests__/App.test.tsx | 90 ++++++++++++++++++++++
.../app/components/__tests__/AppModals.test.tsx | 5 +-
.../app/components/dashboard/MainContent.tsx | 6 +-
.../dashboard/app/components/dashboard/types.ts | 1 -
8 files changed, 173 insertions(+), 20 deletions(-)
Fusion-Task-Id: FN-6964
Fusion-Task-Lineage: 2308b603-a6ac-4978-9a6a-a6028b9bc38c