Commit Graph

10002 Commits

Author SHA1 Message Date
gsxdsm
795963bcf6 fix: land stranded test-minimality follow-ups (core bounding, watchdog, gate-aware delegation) (#1785)
## Why this exists

PR #1780 was merged while its head was only the first commit
(`c5fbe08c0`, the original bounded-lane fix). Two follow-up commits were
pushed to the branch **after** that merge and never landed on `main`.
This PR lands them.

Confirmed absent from `main`: `existingChangedTestFilesInPackage`,
`GATE_COVERED_MEMORY_ENVELOPE_PACKAGES`, `CORE_SCOPED_AFFECTED_PACKAGE`,
the 13-min watchdog ceiling, and `workers=4` — all 0 occurrences on
origin/main.

## What's in here (the two stranded commits)

**1. Greptile P1/P2 review fixes (`8297762`)**
- **P2:** filter directly-changed test files to paths that still exist
on disk (`existingChangedTestFilesInPackage`) so deleted/renamed `.test`
paths never reach `vitest run` positionally; all-deletions diff falls
into the delegate path.
- **P1:** gate-coverage-aware delegation
(`GATE_COVERED_MEMORY_ENVELOPE_PACKAGES`) — engine delegation keeps its
accurate "curated subset ran above" note; dashboard/core delegation now
`console.warn`s that the gate doesn't cover them (CI full-suite is the
backstop) instead of a silent false-green.

**2. Core bounding + watchdog + workers (`2cff1864c`) — the actual
remedy for the remaining timeouts**
- **`@fusion/core` is now a bounded memory-envelope package.** It was
the remaining timeout path: core is the hub ~everything imports (~354
test files), so a core source edit made `vitest --changed` expand to
~the whole core suite and blow past the engine's 15-min kill → SIGKILL +
task restart. PR #1780 only covered engine/dashboard.
- **Watchdog `changed` ceiling 20min → 13min** so the script fails a
runaway lane itself (exit 124, no restart) *before* the engine's 15-min
kill restarts the whole task.
- **Scoped-affected workers 1 → 4** (operator decision) — the fan-out
guard now bounds the set, so the OOM scenario that justified `=1` is
prevented at the source. Heap stays 6144MB/worker.

## Verification
- `scripts/__tests__/test-changed.test.mjs` 117/117;
`run-vitest-watchdog.test.mjs` 15/15; eslint clean. (Re-confirmed on
this branch.)

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

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1785">
  <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**
* Increased parallel test execution for scoped runs in engine and
dashboard areas.
* Added dedicated scoped test handling for core with bounded resources.

* **Bug Fixes**
* Test selection now ignores deleted or renamed test files, preventing
failed runs on missing paths.
* Improved fallback handling when no directly changed tests remain in a
package.
* Adjusted watchdog timing for changed-test runs to better match
expected limits.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 23:00:37 -07:00
gsxdsm
1699c60033 fix: anchor rootDir at the git toplevel so subdir runs don't skip tests (#1785)
greptile: my earlier existence-check anchor was necessary but insufficient.
`rootDir` (= process.cwd() when FUSION_PROJECT_DIR is unset) drives ALL workspace
discovery (readWorkspacePatterns / listWorkspacePackageInfos /
packageHasVitestConfig). Launched from a package subdir, cwd-based discovery
found no packages, so decideExecutionPlan saw "no affected package", ran only the
gate, and exited successfully WITHOUT running the live changed package tests.

Fix the root cause: resolveRepoRoot() resolves the git toplevel as the fallback
(FUSION_PROJECT_DIR still the explicit override; cwd only when git can't report a
toplevel). This is correct from any cwd inside the repo, including a git worktree
(how the engine runs per-task verification). repoRootForExistence is now
redundant and removed; the existence check defaults back to rootDir.

Demonstrated: resolveRepoRoot() from packages/core (no FUSION_PROJECT_DIR) now
resolves the repo root and finds the workspace. +1 regression test. 121/121.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:56:10 -07:00
gsxdsm
e29954e50d Merge remote-tracking branch 'origin/main' into feature/tasks-take-too-long
# Conflicts:
#	scripts/__tests__/test-changed.test.mjs
2026-06-25 22:41:18 -07:00
gsxdsm
7b19f9796c test: remove real-time waits from the slowest test files (FN-5048) (#1784)
Removes real wall-clock waits and per-test rebuilds from the slowest
test files, replacing them with deterministic seams. **No assertions
weakened, no timeouts widened, no retries added** — this is anti-pattern
removal per FN-5048, verified by re-running each file.

## Changes

| File | What | Result |
|---|---|---|
| `dashboard/.../insights-routes.test.ts` | Boot server+store **once**
in `beforeAll` (was `createServer` + `TaskStore.init` per test ×24);
reset insight tables per test for isolation; drive sweeper via fake
timers | test-exec **~3.7s → ~0.8s** |
| `core/.../db.test.ts` | Fixed 150ms write-lock hold → manual stdin
signal-release (keeps the real OS-lock contention under test); fixed a
real EPIPE on redundant release | 152 pass, non-flaky / 8 runs; −300ms
dead wait |
| `core/.../mission-store.test.ts` | 4 real `setTimeout` sleeps (only
there to force distinct timestamps) → `vi.setSystemTime` controlled
clock | anti-pattern removed |
| `core/.../agent-store.test.ts` | 1 real ordering-sleep → injected
`renewedAt` clock; **assertions strengthened** to pin exact timestamp
values | anti-pattern removed |
| `engine/.../in-process-runtime.test.ts` | Fake the one real 25ms
sleep; drop its inflated 30s per-test timeout | anti-pattern removed |

## Honest accounting
- The **real wins** are `insights-routes` (per-test server boot
eliminated, ~75% execution-time cut) and `db` (dead lock-hold removed).
- The **timestamp-sleep removals** (mission-store, agent-store,
in-process-runtime) are small absolute wins — the headline per-file
durations (16–25s) were **full-suite shard contention, not in-file dead
time** (each runs in 3–10s isolated). But they eliminate the FN-5048
real-wait anti-pattern, so a hub edit no longer drags real sleeps into
every `--changed` selection.
- **`workflow-routes.test.ts` was evaluated for splitting and
deliberately NOT split.** A measured A/B showed the 4-way split
*regressed* wall-clock (6s → 11s): the file is import/transform-bound
(per-file esbuild + `@fusion/core`/express import ≈ 5s > the ~4.3s test
runtime), and per-test store migration was already amortized by
`installInMemoryDbSnapshot`. Splitting only multiplies the dominant
fixed cost. Left intact.

## Verification
- `core` 612/612, `dashboard` 24/24, `engine` 78/78 (file-scoped).
- `tsc --noEmit` clean on all 3 packages; eslint clean.

Follow-up (not in this PR): `scripts/test-timings.json` is stale (its
former #1 file no longer exists) — refresh via `pnpm test:velocity --
--measure --write-report` so the watchdog budgets and velocity report
reflect reality.

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

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1784">
  <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

* **Tests**
* Made several test suites more deterministic by replacing real-time
delays with controlled timers and fixed timestamps.
* Improved lock and task checkout tests to use manual release signals,
reducing timing-related flakiness.
* Streamlined route test setup/teardown for faster, more reliable runs.
* Added safer cleanup around timer-based tests to avoid intermittent
failures.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 22:35:53 -07:00
gsxdsm
c36f234da2 Address PR review feedback (#1785)
- P2 (greptile): anchor the changed-test existence check at the git repo root
  (repoRootForExistence via `git rev-parse --show-toplevel`) instead of rootDir,
  so a script run from a package subdir without FUSION_PROJECT_DIR no longer
  forms a doubled path and silently drops live tests into the delegate path.
  +1 regression test (default root resolves to repo root).
- coderabbit: fix stale "1-worker lane" wording in the delegation log (now
  "heavy memory-envelope lane") and the "single-worker envelope" test title,
  both stale after the 1->4 worker change.

test-changed 118/118, eslint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:30:57 -07:00
gsxdsm
50f5c36660 feat(core): per-stage column dwell instrumentation (#1781)
## Why

Diagnosing "tasks take too long" showed the dominant end-to-end
wall-clock is **waiting**, not work: tasks sit in `todo` (queue) and
`in-review` (merge wait) far longer than the agent actually runs. Today
only `cumulativeActiveMs` exists, which measures **in-progress time
only** — every other stage's dwell had to be reconstructed by hand from
agent logs.

## What

Adds `columnDwellMs?: Record<string, number>` to `Task` — a per-column
accumulator (column name → cumulative ms), recorded at the **same store
column-transition seam** as `cumulativeActiveMs` (`moveTaskInternal`).
On each move it adds `columnMovedAt(new) − columnMovedAt(prev)` to the
bucket for the column being left:

- clamped `>= 0` (clock skew safe);
- unparseable/missing prior timestamp and zero-dwell moves are skipped
(no spurious buckets);
- second visits **add** to the existing bucket (multi-visit churn is
captured);
- flag-independent — keys off the generic `columnMovedAt` delta, so it
runs for both the workflow-hook and legacy-inline move paths.

This makes per-stage dwell directly queryable, the same way
`productivity-analytics.ts` already consumes `cumulativeActiveMs`.

## Persistence

JSON-text task column, following the v129 `workspaceWorktrees` precedent
exactly: `SCHEMA_SQL` column + `SCHEMA_VERSION` 129→130 + a versioned
`addColumnIfMissing` migration. Additive and behavior-preserving —
pre-existing rows start NULL and accumulate from their next transition.
Survives archive/restore (added to the archive-entry mapping).

## Tests

`src/__tests__/store-execution-timing.test.ts` — new regression asserts
dwell across
`todo→in-progress→in-review→done→todo→in-progress→in-review` accumulates
the right per-column ms (second visits add) and survives a `getTask` DB
round-trip.

```
pnpm --filter @fusion/core exec vitest run src/__tests__/store-execution-timing.test.ts ... --reporter=dot
→ store-execution-timing 5/5, schema suites (goals/secrets) green, 17/17 total
```

Migration chain verified end-to-end (secrets-schema test climbs v11/v82
→ v130). No hardcoded literal version assertions in the suite; schema
tests assert against the `SCHEMA_VERSION` constant.

`@fusion/core` is private — no changeset.

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

<!-- stage-review-badge-begin -->

---

<a href="https://stagereview.app/Runfusion/Fusion/pull/1781">
  <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 per-column dwell timing to tasks, showing how long work spent in
each column across multiple visits.
  * Preserved this timing data when tasks are archived and restored.

* **Bug Fixes**
* Task timing now updates correctly during column moves, including
repeated returns to the same column.
* Existing data can be upgraded to the new timing format without
breaking stored tasks.

* **Tests**
* Added coverage for multi-step task movement and data reloading to
verify timing totals stay accurate.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-25 22:23:48 -07:00
gsxdsm
207d2b899a test: remove real-time waits from slow test files (FN-5048)
Replace real wall-clock waits and per-test rebuilds in the slowest test files
with deterministic seams. No assertions weakened, no timeouts widened, no
retries added — anti-pattern removal only.

- insights-routes.test.ts: boot the server + store ONCE in beforeAll (was a full
  createServer + TaskStore.init per test x24), reset insight tables per test for
  isolation, drive the sweeper via fake timers. Test-execution time ~3.7s -> ~0.8s.
- db.test.ts: convert the fixed 150ms write-lock hold to manual stdin signal-
  release; keeps the real OS-lock contention under test, removes 2x150ms dead
  wait. Fixed a real EPIPE on redundant release. 152 pass, non-flaky over 8 runs.
- mission-store.test.ts / agent-store.test.ts: replace real setTimeout sleeps
  used only to force distinct timestamps with a controlled clock (vi.setSystemTime
  / injected renewedAt). agent-store assertions strengthened to pin exact values.
- in-process-runtime.test.ts: fake the one real 25ms sleep, drop its inflated
  30s per-test timeout.

Honest note: the timestamp-sleep removals are small absolute wins (the headline
per-file durations were full-suite shard contention, not in-file dead time) but
eliminate the FN-5048 real-wait anti-pattern. workflow-routes.test.ts was
evaluated for splitting and deliberately NOT split — measured A/B showed the
split regressed wall-clock (the file is import/transform-bound, already amortized
by installInMemoryDbSnapshot), so splitting only multiplies fixed import cost.

Verified: core 612/612, dashboard 24/24, engine 78/78; typecheck + eslint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 22:08:41 -07:00
gsxdsm
2cff1864c9 fix: bound @fusion/core affected lane + tighten changed watchdog under engine kill
Three changes to make `pnpm test` reliably minimal and fail gracefully:

- @fusion/core is now a memory-envelope/wide-fan-out package (was unguarded).
  It's the hub nearly everything imports (~354 test files), so a core source
  edit made `vitest --changed` expand to ~the whole core suite and blow past the
  engine's 15-min verification kill -> SIGKILL + task restart. Adding it to
  SCOPED_AFFECTED_MEMORY_ENVELOPES applies the wide-fan-out guard (run only
  directly-changed core tests, else delegate) and the bounded env. core is NOT
  gate-covered, so delegation warns loudly rather than false-greens.

- Lower CLASS_BUDGET_BANDS.changed ceiling 20min -> 13min so the script watchdog
  fails a runaway local lane itself (exit 124, no restart) BEFORE the engine's
  15-min kill restarts the whole task. A tightening, not a timeout-widening.
  Guard test pins ceiling < 900_000ms.

- Raise scoped-affected worker fan-out 1 -> 4 (operator decision). Was 1 only
  for OOM safety (FN-6854/FN-6874); the fan-out guard now bounds the set so the
  hundreds-of-files OOM driver no longer reaches these workers. Heap stays
  6144MB/worker (~4x6GB on the lane) — revisit if a RAM-constrained CI runner
  OOMs. Trades FN-5048 worker-knob guidance for throughput, scoped to the
  bounded affected lanes only.

Tests: test-changed 117/117, watchdog 15/15, eslint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 21:42:22 -07:00
gsxdsm
b6b5583f01 FN-7039: apply execution-lane models to workflow steps
Route workflow and automation prompt steps through the execution-lane model hierarchy.

- Use executor session model resolution for task workflow prompt steps while preserving per-step overrides.
- Use execution settings model resolution for scheduled and manual AI-prompt automation runs.
- Document the model precedence and add regression coverage plus a patch changeset.

Files changed:
 .changeset/fn-7039-workflow-execution-model.md     |   7 +
 docs/settings-reference.md                         |   2 +
 .../core/src/__tests__/model-resolution.test.ts    |  12 ++
 packages/dashboard/src/routes.ts                   |   6 +-
 .../engine/src/__tests__/executor-test-helpers.ts  |  11 +-
 .../__tests__/executor-workflow-step-model.test.ts | 234 +++++++++++++++++++++
 packages/engine/src/cron-runner.ts                 |   7 +-
 packages/engine/src/executor.ts                    |  23 +-
 8 files changed, 285 insertions(+), 17 deletions(-)

Fusion-Task-Id: FN-7039

Fusion-Task-Lineage: f27c4be8-7793-4212-b9ee-679f50193406
2026-06-25 21:05:33 -07:00
gsxdsm
79c602d9d4 FN-7022: add MCP server configuration foundation
Add core MCP configuration primitives for secure server declarations and resolution.

- Add MCP server setting types, schema entries, validation, and project-over-global resolution.
- Add secret-reference materialization seams plus Claude Desktop import/export helpers.
- Cover MCP config behavior with core unit tests and document settings and secret handling.
- Add a changeset for the published CLI package.

Files changed:
 .changeset/fn-7022-mcp-core-foundation.md      |   7 +
 docs/secrets.md                                |   3 +-
 docs/settings-reference.md                     |  23 ++
 packages/core/src/__tests__/mcp-config.test.ts | 199 ++++++++++++++
 packages/core/src/index.ts                     |  30 +-
 packages/core/src/mcp-config.ts                | 366 +++++++++++++++++++++++++
 packages/core/src/settings-schema.ts           |  90 +++++-
 packages/core/src/settings-validation.ts       | 172 +++++++++++-
 packages/core/src/types.ts                     |  62 +++++
 9 files changed, 947 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-7022

Fusion-Task-Lineage: 7bafd0b8-e4a5-4bc2-9a2a-43bfb934845c
2026-06-25 21:01:15 -07:00
gsxdsm
b663eebcb3 FN-7035: split oversized test suites
Split oversized ChatView and notifier suites while updating the line-count baseline.

- Move ChatView core contract and interaction coverage into focused sibling test files.
- Move notifier runtime coverage into its own suite and share setup through a test harness.
- Document the line-count guard decision and ratchet baseline entries for existing growth.

Files changed:
 .../__tests__/ChatView.core-contracts.test.tsx     |  623 ++++++++
 .../__tests__/ChatView.core-interactions.test.tsx  | 1261 +++++++++++++++
 .../components/__tests__/ChatView.core.test.tsx    | 1652 +-------------------
 .../engine/src/__tests__/notifier.runtime.test.ts  |  810 ++++++++++
 .../engine/src/__tests__/notifier.test-harness.ts  |   71 +
 packages/engine/src/__tests__/notifier.test.ts     |  847 +---------
 scripts/check-file-line-count.mjs                  |    3 +
 scripts/line-count-baseline.json                   |   12 +-
 8 files changed, 2778 insertions(+), 2501 deletions(-)

Fusion-Task-Id: FN-7035
Fusion-Task-Lineage: 14cebb57-925b-41c7-9c8b-472f34b76fe2
2026-06-25 20:50:30 -07:00
gsxdsm
6415eed0c1 FN-7034: Align steps dropdown trigger styling
Align the optional steps dropdown trigger with shared task creation button styling.

- Reuse the dashboard btn btn-sm classes for the workflow optional steps trigger.
- Remove bespoke trigger button styling so shared button tokens control padding, border, radius, and states.
- Extend dropdown tests to cover shared classes across empty, selected, and disabled states.
- Add a patch changeset for the published Fusion package.

Files changed:
 .changeset/fn-7034-steps-dropdown-style.md         |  7 +++
 .../components/WorkflowOptionalStepsDropdown.css   | 14 ------
 .../components/WorkflowOptionalStepsDropdown.tsx   |  9 +++-
 .../WorkflowOptionalStepsDropdown.test.tsx         | 50 ++++++++++++++++++++--
 4 files changed, 61 insertions(+), 19 deletions(-)

Fusion-Task-Id: FN-7034

Fusion-Task-Lineage: 3ca2a726-2c67-44a0-9a88-467e4fc1ad6b
2026-06-25 20:28:38 -07:00
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
8297762eeb Address PR review feedback (#1780)
- P2: filter directly-changed test files to paths that still exist on disk
  (existingChangedTestFilesInPackage) so deleted/renamed .test paths from
  `git diff` never reach `vitest run` positionally; all-deletions diff falls
  into the delegate-to-gate path.
- P1: make heavy-package delegation gate-coverage-aware
  (GATE_COVERED_MEMORY_ENVELOPE_PACKAGES). Engine delegation keeps the accurate
  "curated engine-core subset ran above" note; dashboard delegation now warns
  that the gate runs no dashboard tests and names the CI full-suite backstop,
  so the coverage gap is loud instead of a silent false-green.
- +4 regression tests (115/115).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 20:17:56 -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
8a03e4fc23 feat(core): per-stage column dwell instrumentation
Adds `columnDwellMs?: Record<string, number>` to Task — a per-column
accumulator (column name -> cumulative ms) recorded at the same store
column-transition seam as `cumulativeActiveMs`. On every move it adds
`columnMovedAt(new) - columnMovedAt(prev)` to the bucket for the column
being left, clamped >= 0; unparseable/missing prior timestamps and 0-dwell
moves are skipped, and second visits add to the existing bucket.

Motivation: `cumulativeActiveMs` only measures in-progress time. Diagnosis
of slow tasks showed the dominant wall-clock is *waiting* (queue time in
todo, review wait in in-review), which previously had to be reconstructed
from agent logs. This makes per-stage dwell directly queryable, like
productivity-analytics already consumes cumulativeActiveMs.

Persisted as a JSON-text task column following the v129 workspaceWorktrees
precedent: SCHEMA_SQL column + SCHEMA_VERSION 129->130 + versioned
addColumnIfMissing migration. Additive and behavior-preserving; pre-existing
rows start NULL and accumulate from their next transition. Survives
archive/restore. @fusion/core is private — no changeset.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 19:39:02 -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