Commit Graph

9988 Commits

Author SHA1 Message Date
gsxdsm
4a4e389254 FN-7032: add signed Android release artifacts
Add secret-gated signed Android release packaging while preserving the unsigned fallback.

- Build signed Android release APK and AAB artifacts when keystore secrets are configured.
- Verify signed APKs, generate checksums for APK/AAB outputs, and include AABs in release aggregation.
- Document Android signing secrets, sideload verification, fallback artifacts, and Play upload scope.
- Cover the release and rehearsal workflow wiring with CLI and desktop workflow tests.

Files changed:
 .github/workflows/release.yml                      | 94 ++++++++++++++++++----
 .github/workflows/test-release.yml                 | 94 ++++++++++++++++++----
 MOBILE.md                                          | 18 ++++-
 RELEASING.md                                       | 34 ++++++--
 packages/cli/src/__tests__/ci-workflow.test.ts     | 24 ++++++
 packages/desktop/README.md                         |  2 +-
 .../desktop/src/__tests__/release-workflow.test.ts | 24 +++++-
 7 files changed, 251 insertions(+), 39 deletions(-)

Fusion-Task-Id: FN-7032
Fusion-Task-Lineage: 0334c026-384e-4531-a2b2-f8a0b5bb7ff0
2026-06-25 20:20:33 -07:00
gsxdsm
c0958bfd4f FN-7029: split AI merge prompts and worktree helpers
Split the clean-room AI merger into smaller focused modules while preserving its public behavior.

- Extract prompt builders and review verdict parsing into merger-ai-prompts.
- Extract AI merge worktree lifecycle and cleanup helpers into merger-ai-worktree.
- Re-export the extracted APIs from merger-ai and cover prompt/verdict behavior with tests.
- Remove the merger-ai line-count baseline now that the file is under the guardrail.

Files changed:
 .../engine/src/__tests__/merger-ai-prompts.test.ts |  86 ++++
 packages/engine/src/merger-ai-prompts.ts           | 312 ++++++++++++
 packages/engine/src/merger-ai-worktree.ts          | 287 +++++++++++
 packages/engine/src/merger-ai.ts                   | 555 ++-------------------
 scripts/line-count-baseline.json                   |   1 -
 5 files changed, 723 insertions(+), 518 deletions(-)

Fusion-Task-Id: FN-7029

Fusion-Task-Lineage: 59adc31f-7386-4008-b74f-8fb9bbae078a
2026-06-25 20:12:20 -07:00
gsxdsm
0ae44992df FN-7030: route graph tasks to shared pop-out
Route dependency Graph task opens through the shared movable task pop-out.\n\n- Send dependency-graph plugin task opens and rendered graph task cards to popOutTaskDetail.\n- Preserve fixed modal behavior for non-graph plugin dashboard views.\n- Document the Graph behavior and add regression coverage for desktop, mobile, and pop-out deduping.\n- Add a patch changeset for the published CLI package.\n\nFiles changed:\n .changeset/fn-7030-graph-task-popout.md            |   7 +\n docs/dashboard-guide.md                            |   4 +-\n .../app/components/dashboard/MainContent.tsx       |  15 +-\n .../__tests__/MainContent.graph-popout.test.tsx    | 274 +++++++++++++++++++++\n 4 files changed, 296 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-7030

Fusion-Task-Lineage: 83008d81-218e-49ce-9aff-cb6b51d84dba
2026-06-25 20:03:53 -07:00
gsxdsm
45727f1459 FN-7019: fix Command Center range filtering
Command Center analytics now honor picker presets and open-ended date bounds.\n\n- Serialize All time with an explicit upper bound and preserve one-sided custom/preset query params.\n- Resolve server analytics ranges as open windows for from-only and to-only requests instead of defaulting them away.\n- Cover picker query serialization and range-consuming Command Center endpoints with regression tests.\n- Document the restored picker contract and add a patch changeset.\n\nFiles changed:\n .changeset/fn-7019-command-center-range.md         |  7 ++\n docs/dashboard-guide.md                            |  3 +-\n .../components/command-center/DateRangePicker.tsx  | 12 ++-\n .../command-center/areas/__tests__/areas.test.tsx  | 54 ++++++++++++-\n .../components/command-center/areas/areaShared.ts  |  8 +-\n .../register-command-center-routes.test.ts         | 92 +++++++++++++++++++++-\n .../src/routes/register-command-center-routes.ts   | 28 ++++---\n 7 files changed, 183 insertions(+), 21 deletions(-)

Fusion-Task-Id: FN-7019

Fusion-Task-Lineage: 327f8f45-8ad8-4103-8cc4-efcf2af6a73a
2026-06-25 19:57:49 -07:00
gsxdsm
e48f80b764 FN-7028: split AgentLogViewer tests by concern
Split the large AgentLogViewer suite into focused, line-count-friendly test files.

- Move header, layout, markdown, and rendering coverage into separate test modules.
- Add a shared AgentLogViewer test helper for reusable setup.
- Remove the oversized combined AgentLogViewer test and update the line-count baseline.

Files changed:
 .../__tests__/AgentLogViewer.header.test.tsx       |  490 +++++
 .../__tests__/AgentLogViewer.layout.test.tsx       |  367 ++++
 .../__tests__/AgentLogViewer.markdown.test.tsx     |  797 ++++++++
 .../__tests__/AgentLogViewer.rendering.test.tsx    |  410 ++++
 .../__tests__/AgentLogViewer.test-helpers.ts       |   16 +
 .../components/__tests__/AgentLogViewer.test.tsx   | 2010 --------------------
 scripts/line-count-baseline.json                   |    1 -
 7 files changed, 2080 insertions(+), 2011 deletions(-)

Fusion-Task-Id: FN-7028

Fusion-Task-Lineage: 5ef134c7-0969-4b9b-908c-9713daa9d0d2
2026-06-25 19:51:21 -07:00
gsxdsm
ea3cfeeac4 FN-7027: constrain skill list row text
Keep discovered skill rows within the left pane by truncating long text values.

- Wrap skill names in a truncatable text span while keeping chevrons fixed-size.
- Add ellipsis rules and compact font sizing for skill names, paths, and sources.
- Cover long, short, and empty metadata skill rows with a dashboard test.
- Add a patch changeset for the published CLI package.

Files changed:
 .changeset/fn-7027-skill-list-truncation.md        |  7 +++
 packages/dashboard/app/components/SkillsView.css   | 28 ++++++++++
 packages/dashboard/app/components/SkillsView.tsx   |  2 +-
 .../app/components/__tests__/SkillsView.test.tsx   | 64 ++++++++++++++++++++++
 4 files changed, 100 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7027

Fusion-Task-Lineage: ae50f1aa-e58b-4374-abae-38ca28e4073a
2026-06-25 19:35:47 -07:00
gsxdsm
8754e28868 FN-7026: cap scoped affected test watchdogs
Keep changed-only affected test lanes from outliving the workspace verification timeout.

- Add a scoped affected watchdog ceiling below the default executor timeout.
- Use the ceiling for scoped dashboard and engine affected Vitest lanes while leaving full fallback budget unchanged.
- Cover the timeout derivation and dashboard-only package selection in script tests.
- Document the changed-only watchdog behavior for future test infrastructure changes.

Files changed:
 docs/testing.md                         |  6 +++--
 scripts/__tests__/test-changed.test.mjs | 48 +++++++++++++++++++++++++++++++++
 scripts/test-changed.mjs                | 18 ++++++++++---
 3 files changed, 66 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-7026

Fusion-Task-Lineage: 774519e0-505b-4e40-8309-5d2250da1eba
2026-06-25 19:35:46 -07:00
gsxdsm
775a1f8e9a FN-7020: compact AI session input banner
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
2026-06-25 19:35:05 -07:00
gsxdsm
541f1f6533 FN-7017: expose optional workflow steps in task creation
Surface active workflow optional steps on task creation surfaces so users can opt into workflow-specific steps before creating tasks.

- Add optional-step dropdown state and creation payload handling to quick entry.
- Move New Task optional-step controls into the inline quick-button row.
- Cover default-on, workflow selection, duplicate-confirmed create, empty-step rendering, and mobile touch-target behavior with tests.
- Document create-time optional-step controls and add the published package changeset.

Files changed:
 .../fn-7017-optional-steps-quick-dropdown.md       |   7 +
 docs/dashboard-guide.md                            |   4 +-
 docs/workflow-steps.md                             |   2 +
 .../dashboard/app/components/QuickEntryBox.css     |   6 +-
 .../dashboard/app/components/QuickEntryBox.tsx     |  65 ++++++++-
 packages/dashboard/app/components/TaskForm.tsx     |  34 ++---
 .../app/components/__tests__/NewTaskModal.test.tsx |  21 ++-
 .../components/__tests__/QuickEntryBox.test.tsx    | 145 ++++++++++++++++++++-
 .../app/components/__tests__/TaskForm.test.tsx     |   1 +
 9 files changed, 258 insertions(+), 27 deletions(-)

Fusion-Task-Id: FN-7017

Fusion-Task-Lineage: 1b7d21e6-ff7f-4d27-b285-4fd865eafce6
2026-06-25 19:35:05 -07:00
gsxdsm
f5b588cab6 FN-7018: retry transient ntfy notification failures
Ntfy sends now retry bounded transient failures before giving up.

- Add per-attempt timeouts and bounded retries for ntfy network, timeout, 5xx, and 429 failures.\n- Preserve best-effort abort behavior while retrying only retryable publish failures.\n- Cover retry, timeout, abort, payload, and non-retryable failure behavior in notifier tests.\n- Add a patch changeset for the published Fusion package.\n\nFiles changed:\n .changeset/fn-7018-ntfy-retry.md               |   7 +\n packages/engine/src/__tests__/notifier.test.ts | 259 ++++++++++++++++++++++++-\n packages/engine/src/notifier.ts                | 173 +++++++++++++----\n 3 files changed, 399 insertions(+), 40 deletions(-)

Fusion-Task-Id: FN-7018

Fusion-Task-Lineage: 0d0b7313-532a-4583-8bb7-67fc4b2e98bf
2026-06-25 19:35:05 -07:00
gsxdsm
f9f767c46a FN-7007: speed up SettingsModal interaction tests
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
2026-06-25 19:35:05 -07:00
gsxdsm
dba65933e5 FN-7014: publish Android APK release artifacts
Adds Android APK generation to binary release and rehearsal workflows so GitHub releases ship mobile assets.

- Add Android build jobs that sync Capacitor, assemble the debug APK, and upload APK/checksum artifacts.
- Include Android artifacts in release and test-release collection dependencies and file matching.
- Document Android release outputs and extend workflow shape tests for the new asset path.

Files changed:
 .github/workflows/release.yml                      | 86 +++++++++++++++++++++-
 .github/workflows/test-release.yml                 | 85 ++++++++++++++++++++-
 MOBILE.md                                          |  2 +-
 RELEASING.md                                       | 10 ++-
 packages/cli/src/__tests__/ci-workflow.test.ts     |  6 +-
 packages/desktop/README.md                         |  1 +
 .../desktop/src/__tests__/release-workflow.test.ts | 24 +++++-
 7 files changed, 201 insertions(+), 13 deletions(-)

Fusion-Task-Id: FN-7014
Fusion-Task-Lineage: 8ed94f64-399b-433f-add4-0294fc5722d1
2026-06-25 19:35:05 -07:00
gsxdsm
90c0e9936e FN-7009: update dashboard tests for current labels
Refresh dashboard test expectations so they follow current project setup and theme metadata.

- Assert setup wizard registration payloads include workspace and task-prefix fields.
- Resolve default theme assertions through shared theme metadata instead of hardcoded labels.
- Update Command Center theme dropdown coverage to use the current default theme label.

Files changed:
 .../app/components/__tests__/SetupWizardModal.test.tsx   | 16 +++++++++-------
 .../app/components/__tests__/ThemeSelector.test.tsx      | 11 ++++++-----
 .../__tests__/CommandCenterControls.test.tsx             | 12 +++++++-----
 3 files changed, 22 insertions(+), 17 deletions(-)

Fusion-Task-Id: FN-7009
Fusion-Task-Lineage: 1255f1b5-b63d-4366-afe6-5d72ca15cb1a
2026-06-25 19:35:04 -07:00
gsxdsm
0b0e91cc18 fix: bound changed-affected test lane to avoid vitest --changed graph blowup (#1780)
## 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 -->
2026-06-25 19:34:02 -07:00
gsxdsm
62f5e35407 feat: add built-in Code Review pre-merge workflow step (#1779)
## 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 -->
2026-06-25 19:32:45 -07:00
gsxdsm
c5fbe08c00 fix: bound changed-affected test lane to avoid vitest --changed graph blowup
`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>
2026-06-25 19:28:15 -07:00
gsxdsm
4ea6084322 feat: make Code Review a default-on toggleable optional-group step
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>
2026-06-25 18:16:59 -07:00
gsxdsm
a50074d411 feat: make Code Review a standard always-on pre-merge step
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>
2026-06-25 17:57:08 -07:00
gsxdsm
7772ab3647 feat: add built-in Code Review pre-merge workflow step
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>
2026-06-25 17:34:50 -07:00
gsxdsm
977000ca99 FN-7012: restore mobile task tab scrolling
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
2026-06-25 17:26:16 -07:00
gsxdsm
65a2b3bc72 feat: add test-free verify:fast (typecheck + build + boot-smoke) (#1777)
## 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 -->
2026-06-25 17:24:25 -07:00
gsxdsm
eb763e8bc3 chore: test value audit (deletion-candidate evidence base) (#1776)
## 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 -->
2026-06-25 17:23:03 -07:00
gsxdsm
55b9c548ad test: quarantine 3 failing CI full-suite tests (#1775)
## 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 -->
2026-06-25 17:22:23 -07:00
gsxdsm
0346ea0f6b perf: snapshot migrated in-memory DB to skip per-test migrations (#1774)
## 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 -->
2026-06-25 17:22:08 -07:00
gsxdsm
88a2dbf59b test: split ChatView.test.tsx into 3 parallel files + fix FN-4327 isolation bug (#1773)
## 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 -->
2026-06-25 17:21:33 -07:00
gsxdsm
17ddc19010 docs(verification): discourage allowFullSuite in fn_run_verification (#1772)
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 -->
2026-06-25 17:21:01 -07:00
gsxdsm
f342761f1b feat: add test-free verify:fast (typecheck + build + boot-smoke)
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>
2026-06-25 17:06:08 -07:00
gsxdsm
4426a9ae75 chore: add test value audit (deletion-candidate evidence base)
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>
2026-06-25 17:04:30 -07:00
gsxdsm
5ce577842e test: quarantine 3 failing CI full-suite tests
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.
2026-06-25 17:02:29 -07:00
gsxdsm
6dc8eb7161 perf: snapshot migrated in-memory DB to skip per-test migrations
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>
2026-06-25 16:48:56 -07:00
gsxdsm
2306fe67f3 test: split giant ChatView.test.tsx into 3 parallel files + fix FN-4327 isolation bug
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>
2026-06-25 16:43:54 -07:00
gsxdsm
a0954c7f27 FN-6975: make mission planning modal movable and resilient
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
2026-06-25 16:31:10 -07:00
gsxdsm
a9193df997 docs(verification): instruct agents not to use allowFullSuite unless necessary
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>
2026-06-25 16:22:40 -07:00
gsxdsm
0f95f6d1c1 FN-7013: refresh line-count guard baseline
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
2026-06-25 16:17:46 -07:00
gsxdsm
744aa2cc05 feat(engine): scope verification to changed files + scope-aware timeout
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>
2026-06-25 16:11:45 -07:00
gsxdsm
3513d5f6f8 FN-7002: fix mobile New Task dialog affordances
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
2026-06-25 16:11:45 -07:00
gsxdsm
4349f6a72f fix(engine): make merge/step verification timeout scope-aware (#1771)
## 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 -->
2026-06-25 16:11:36 -07:00
gsxdsm
826045d50b fix(dashboard): repair CSS token/contrast regressions and ~19 stale tests (#1770)
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 -->
2026-06-25 16:11:01 -07:00
gsxdsm
5c9f8b0040 test(engine): update sandbox-wiring timeout assertion for scope-aware default
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>
2026-06-25 14:59:31 -07:00
gsxdsm
efa5d9b5f6 fix(engine): make merge/step verification timeout scope-aware
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>
2026-06-25 14:43:41 -07:00
gsxdsm
b293525751 fix(dashboard): repair CSS token/contrast regressions and stale tests
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>
2026-06-25 14:37:52 -07:00
gsxdsm
9c24440e21 chore: Tier-1 storage optimization (LFS doc images + gc) (#1768)
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 -->
2026-06-25 13:29:31 -07:00
gsxdsm
3320558a7a chore: route demo reel GIFs through Git LFS (#1767)
## 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 -->
2026-06-25 13:29:15 -07:00
gsxdsm
c202053725 fix(dashboard): make embedded Planning view scroll on mobile
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>
2026-06-25 13:27:37 -07:00
gsxdsm
ad246e8bd2 FN-7001: repair dashboard changed-test expectations
Repair dashboard changed-test expectations for graduated navigation and workflow behavior.

- Update App tests to use the left-sidebar default and keep graduated Todo/Goals destinations available when stale flags are false.
- Align route tests with workflow-column graduation and live promote branches.
- Adjust dashboard test fixtures for command-center pricing settings and current spinner/viewport listener contracts.

Files changed:
 .../app/components/__tests__/App.test.tsx          | 43 +++++++++++++++++++---
 .../__tests__/PlanningModeModal.initial.test.tsx   |  6 ++-
 .../__tests__/board-mobile-initial-render.test.tsx | 12 +++++-
 .../register-command-center-routes.auth.test.ts    | 10 +++++
 .../routes/__tests__/board-workflows-route.test.ts | 19 ++++++----
 .../src/routes/__tests__/promote-route.test.ts     | 13 ++-----
 6 files changed, 77 insertions(+), 26 deletions(-)

Fusion-Task-Id: FN-7001

Fusion-Task-Lineage: 23c0b18d-6895-4a94-a77a-17c7438f477a
2026-06-25 13:27:37 -07:00
gsxdsm
6c51bd1d44 FN-6989: make workflow editor float
Make workflow editing open in the shared floating window shell.

- Replace the workflow editor modal overlay with FloatingWindow drag, resize, and geometry persistence.
- Let graph and header workflow switcher callbacks forward the selected workflow id into the editor.
- Update workflow editor sizing styles and mobile full-screen behavior for the floating shell.
- Add regression coverage for floating-window behavior, resize ownership, and workflow id forwarding.

Files changed:
 .../app/components/GraphWorkflowSwitcherSlot.tsx   |   6 +-
 .../app/components/HeaderWorkflowSwitcherSlot.tsx  |   6 +-
 .../app/components/WorkflowNodeEditor.css          |  51 +++++++--
 .../app/components/WorkflowNodeEditor.tsx          |  33 +++---
 .../__tests__/GraphWorkflowSwitcherSlot.test.tsx   |  11 ++
 .../__tests__/HeaderWorkflowSwitcherSlot.test.tsx  |  10 ++
 .../__tests__/WorkflowNodeEditor.css.test.ts       |  21 ++--
 .../__tests__/WorkflowNodeEditor.test.tsx          | 126 +++++++++++++++++----
 8 files changed, 208 insertions(+), 56 deletions(-)

Fusion-Task-Id: FN-6989

Fusion-Task-Lineage: cf762608-37d5-43be-8cbe-20fd1ae56296
2026-06-25 13:27:28 -07:00
gsxdsm
bf4a4de347 chore: route doc/demo PNG screenshots through Git LFS
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>
2026-06-25 13:23:17 -07:00
gsxdsm
5fe76a6c44 docs: note Git LFS setup for demo reel GIFs
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:21:43 -07:00
gsxdsm
e3564c2333 chore: route demo/assets GIFs through Git LFS
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>
2026-06-25 13:21:43 -07:00
gsxdsm
893c1dfa27 test(dashboard): fix 30 pre-existing pnpm-test failures on main (#1765)
## 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 -->
2026-06-25 13:17:35 -07:00