Commit Graph

733 Commits

Author SHA1 Message Date
Fusion
6a5e240e9a feat(FN-2920): merge fusion/fn-2920
- Add cloudflared binary detection to the remote-access routes, surfaced in the Settings modal with install/uninstall UX states
- Update `SettingsModal.tsx` with new cloudflared status UI and install prompt flows; add co-located CSS in `SettingsModal.css`
- Add `SettingsModal.test.tsx` covering the new cloudflared states and API interactions
- Extend `remote-access-routes.test.ts` with detection and install/uninstall coverage
- Document the new cloudflared detection UX in `docs/remote-access.md` and `docs/settings-reference.md`
- Minor `server.test.ts` fixture update to align with the new server contract

Commits merged:
- docs(FN-2920): complete Step 7 — document cloudflared detection UX
- test(FN-2920): complete Step 6 — update server contract expectations
- feat(FN-2920): complete Step 5 — add cloudflared detection and install coverage

Files changed:
docs/remote-access.md                              |   2 +
 docs/settings-reference.md                         |   2 +
 packages/dashboard/app/api/legacy.ts               |   7 ++
 .../dashboard/app/components/SettingsModal.css     |  42 ++++++++
 .../dashboard/app/components/SettingsModal.tsx     | 112 ++++++++++++++++-----
 .../components/__tests__/SettingsModal.test.tsx    |  66 ++++++++++++
 .../src/__tests__/remote-access-routes.test.ts     | 107 +++++++++++++++++++-
 packages/dashboard/src/__tests__/server.test.ts    |   4 +-
 .../src/routes/register-settings-memory-routes.ts  |  59 ++++++++++-
 9 files changed, 372 insertions(+), 29 deletions(-)

Fusion-Task-Id: FN-2920
2026-04-29 13:57:41 -07:00
gsxdsm
9d9f351749 fix(remote): query tailscaled directly when no funnel URL was captured
When the tunnel was started before parseReadiness flipped to URL-required
(or by an external invocation), the manager's status URL stays null and
buildRemoteLoginUrlForTokenType used to fall back to a constructed
http://<configured-hostname>:<port> URL — which the user saw encoded
into the QR as e.g. "fusionstudio:4040".

Add a tailscale status --json fallback that recovers the public tailnet
DNS name and reconstructs the funnel URL (https://<machine>.<tailnet>.ts.net/).
If both sources fail, surface REMOTE_URL_NOT_READY rather than emitting a
non-public URL into the auth/QR payload.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:51:36 -07:00
Fusion
17a072c924 feat(FN-2920): improve remote tunnel setup and heartbeat scheduling
- Add cloudflared install/detection support in remote settings API, UI, and route tests
- Surface Cloudflare tunnel prerequisites in Settings modal with remote access docs updates
- Harden heartbeat runtime scheduling by avoiding stale timeout state and simplifying runtime timeout handling
- Expand CLI/core/dashboard/engine coverage for task lifecycle, agent health, and runtime heartbeat behavior
- Add changesets for heartbeat scheduling fixes and PR approval setting updates

Fusion-Task-Id: FN-2920
2026-04-29 13:49:35 -07:00
gsxdsm
ce37c61a79 fix(remote): derive tailscale target port from server-side request
Override the stored tailscale targetPort in the start handler using the
actual port the start request landed on (req.socket.localPort), instead
of trusting a value the browser supplied. window.location.port can be
wrong behind a reverse proxy, ssh forward, or split deployment, and
silently funneling the wrong process is worse than the prior
"port-not-configured" error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:39:08 -07:00
gsxdsm
256e54dfef feat(remote): real QR codes, live tailscale URL, TUI status & shortcut
* Replace placeholder /remote/qr SVG (URL drawn as text) with real QR
  rendered via the qrcode package; add format=terminal returning ASCII
  QR for the TUI.
* Resolve the public tailscale funnel URL from captured CLI output
  instead of constructing http://<hostname>:<port> from a configured
  hostname label — that label was never used by `tailscale funnel` and
  produced a non-public URL in the auth/QR link.
* Drop hostname requirement from engine + UI; only target port matters.
* Tighten tailscale parseReadiness to require a URL on the matched line
  so the tunnel manager doesn't lock in `running` before the URL line.
* TUI: poll remote status, show ● tunnel indicator + URL in MainHeader,
  bind Ctrl+Q to a global QR overlay (terminal ASCII), and switch the
  in-Settings K shortcut to render the same ASCII QR.
* Auto-poll remote status in the dashboard while in `starting`/`stopping`
  so the UI flips to running without reopening the modal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:20:03 -07:00
Fusion
fd7278044c feat(FN-2931): merge fusion/fn-2931
- **New node routing policy engine** (`packages/engine/src/node-routing-policy.ts`, `scheduler.ts`): introduces configurable routing rules for assigning tasks to specific nodes, with a new test suite covering policy matching, node priority, and capacity constraints
- **Agent run route decoupling** (`register-agent-runtime-routes.ts`): routes now respond before heartbeat side effects complete, improving latency and reducing 503s under load; tests updated to handle async state transitions
- **Scheduler node routing** (`scheduler-node-routing.test.ts`): 131-line test expansion covering task-to-node assignment with routing policies
- **Dashboard UI polish** (AgentsView, QuickChatFAB, SettingsModal): CSS refinements and component adjustments from FN-2903
- **Reviewer and triage refinements** (`reviewer.ts`, `triage.ts`): logic improvements for async execution paths
- **Remote access adapter** (`provider-adapters.ts`): extended from FN-2950
- **Settings memory routes** (`register-settings-memory-routes.ts`): from FN-2925
- **Docs** (`architecture.md`, `settings-reference.md`): updated for new routing policy and settings features

Commits merged:
- test(FN-2931): complete Step 2 — update async state route assertions
- feat(FN-2931): complete Step 1 — respond before heartbeat side effects
- feat(FN-2925): merge fusion/fn-2925
- feat(FN-2903): merge fusion/fn-2903
- feat(FN-2950): merge fusion/fn-2950

Files changed:
docs/architecture.md                               |  19 +--
 docs/settings-reference.md                         |   2 +-
 packages/dashboard/app/components/AgentsView.css   |  20 +++-
 packages/dashboard/app/components/AgentsView.tsx   |  11 +-
 packages/dashboard/app/components/QuickChatFAB.css |  32 ++++-
 .../dashboard/app/components/SettingsModal.css     |  21 ++++
 .../dashboard/app/components/SettingsModal.tsx     |  58 ++++++++-
 .../app/components/__tests__/AgentsView.test.tsx   |  37 ++++++
 .../app/components/__tests__/QuickChatFAB.test.tsx |  18 +--
 .../components/__tests__/SettingsModal.test.tsx    |   2 +-
 packages/dashboard/package.json                    |   2 +
 .../src/__tests__/routes-agent-runs.test.ts        |  13 +-
 .../src/routes/register-agent-runtime-routes.ts    |  49 ++++----
 .../src/routes/register-settings-memory-routes.ts  |   8 +-
 .../src/__tests__/node-routing-policy.test.ts      |  78 ++++++++++++
 packages/engine/src/__tests__/reviewer.test.ts     |  19 ++-
 .../src/__tests__/scheduler-node-routing.test.ts   | 131 ++++++++++++++++++++-
 packages/engine/src/__tests__/triage.test.ts       |  16 +--
 packages/engine/src/node-routing-policy.ts         |  45 +++++++
 .../engine/src/remote-access/provider-adapters.ts  |  14 ++-
 packages/engine/src/reviewer.ts                    |  33 ++++--
 packages/engine/src/scheduler.ts                   |  44 ++++++-
 packages/engine/src/triage.ts                      |  48 ++++----
 pnpm-lock.yaml                                     | 113 ++++++++++++++++++
 24 files changed, 721 insertions(+), 112 deletions(-)

Fusion-Task-Id: FN-2931
2026-04-29 12:56:56 -07:00
Fusion
a45a2268a6 feat(FN-2925): merge fusion/fn-2925
- Mobile header row polish: finalize QuickChatFAB CSS for mobile viewport handling, apply visual viewport height to quick chat panel, remove duplicate keyboard overlap subtraction
- Add `node-routing-policy.ts` with routing logic for mesh network nodes; expand scheduler node-routing tests with new policy coverage
- Improve reviewer decision logic and add reviewer test cases for changed behavior
- Refactor triage module (48 lines changed) with updated agent selection logic
- Update `AgentsView` component and styles; add `AgentsView.test.tsx` integration test
- Simplify `QuickChatFAB.test.tsx` test by removing CSS class permutation coverage
- Update architecture docs and settings reference to reflect new routing capabilities

Commits merged:
- fix(FN-2925): remove duplicate keyboard overlap subtraction
- feat(FN-2925): complete Step 5 — finalize mobile header row polish
- fix(FN-2925): apply visual viewport height to mobile quick chat panel
- feat(FN-2903): merge fusion/fn-2903
- feat(FN-2950): merge fusion/fn-2950

Files changed:
docs/architecture.md                               |  19 +--
 docs/settings-reference.md                         |   2 +-
 packages/dashboard/app/components/AgentsView.css   |  20 +++-
 packages/dashboard/app/components/AgentsView.tsx   |  11 +-
 packages/dashboard/app/components/QuickChatFAB.css |  32 ++++-
 .../dashboard/app/components/SettingsModal.tsx     |   4 +-
 .../app/components/__tests__/AgentsView.test.tsx   |  37 ++++++
 .../app/components/__tests__/QuickChatFAB.test.tsx |  18 +--
 .../src/__tests__/node-routing-policy.test.ts      |  78 ++++++++++++
 packages/engine/src/__tests__/reviewer.test.ts     |  19 ++-
 .../src/__tests__/scheduler-node-routing.test.ts   | 131 ++++++++++++++++++++-
 packages/engine/src/__tests__/triage.test.ts       |  16 +--
 packages/engine/src/node-routing-policy.ts         |  45 +++++++
 packages/engine/src/reviewer.ts                    |  33 ++++--
 packages/engine/src/scheduler.ts                   |  44 ++++++-
 packages/engine/src/triage.ts                      |  48 ++++----
 16 files changed, 473 insertions(+), 84 deletions(-)

Fusion-Task-Id: FN-2925
2026-04-29 12:53:10 -07:00
gsxdsm
1beebc0c45 feat(core,dashboard): allow tasks to be respec'd from in-review
Add `triage` to VALID_TRANSITIONS["in-review"] so the dashboard's
`Request AI Revision` and `Rebuild Spec` actions work for in-review
tasks. moveTask now applies the same full reset on in-review → triage
as on in-review → todo (clears branch/baseBranch/baseCommitSha/summary/
recovery metadata and workflowStepResults) so the respec'd task starts
from scratch. The in-review task card's Move menu also gains Planning
as a destination.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 11:53:35 -07:00
Fusion
78b5a1b7ae feat(FN-2849): merge fusion/fn-2849-2
- **Node routing & diff visibility** (FN-2840, FN-2910): Strengthened node routing with improved task diff visibility; `resolve-diff-base.ts` now prefers `merge-base` over potentially stale `baseCommitSha`; added `unavailable-node-policy` and `node-override-guard` tests
- **Concurrency races fixed**: Executor and merger now synchronize worktree lifecycle more defensively; reviewer pause/unpause fixed against TOCTOU races in `concurrency.ts`
- **Richer merge commit messages**: `merger.ts` and `ai-summarize.ts` enhanced to generate AI-summarized merge messages via the summarizer pipeline
- **Memory dream improvements**: `memory-dreams.ts` reads assistant text from session state when processing dreams; added coverage for undefined output edge cases
- **QuickChatFAB UI**: New floating action button component with chat integration (226 lines TSX, 140 lines CSS); `useQuickChat.ts` refactored for better state management; tests added
- **Task changes display**: `ChangesDiffModal` and `TaskChangesTab` now surface only files actually modified by the task, not the full diff baseline
- **Self-healing hooks**: `self-healing.ts` extended with additional recovery logic for agent runtime
- **Documentation**: Added `docs/multi-project.md` (central registry, isolation modes), `docs/architecture.md` (node settings sync API), `docs/task-management.md` (archive/restore), `docs/cli-reference.md`; updated `docs/settings-reference.md`
- **Gitignore**: Allow committed `.changeset/` directories
- Merged in FN-2734 and FN-2957 as part of this branch

Commits merged:
- test(FN-2849): add node routing route coverage
- fix(engine): close executor/merger concurrency races and reviewer pause TOCTOU
- fix(dashboard): prefer merge-base over outdated baseCommitSha
- fix(tui): surface visible feedback when copying a log entry
- feat(FN-2840): strengthen node routing and task diff visibility
- feat(FN-2910): merge fusion/fn-2910
- fix(dashboard): show only files actually changed by the task
- test(memory): cover dream session-state extraction and undefined output
- fix(gitignore): allow committed changesets
- fix(memory): read assistant text from session state when processing dreams
- feat(merger): generate richer merge commit messages via AI summarizer
- feat(FN-2734): merge fusion/fn-2734
- feat(FN-2957): merge fusion/fn-2957

Files changed:
.gitignore                                         |   5 +
 docs/architecture.md                               |  46 ++++
 docs/cli-reference.md                              |  21 ++
 docs/dashboard-guide.md                            |  10 +-
 docs/multi-project.md                              |  47 ++++
 docs/settings-reference.md                         |  32 ++-
 docs/task-management.md                            |  64 ++++++
 packages/cli/src/commands/dashboard-tui/app.tsx    |  40 +++-
 .../cli/src/commands/dashboard-tui/controller.ts   |  18 ++
 packages/cli/src/commands/dashboard-tui/state.ts   |   5 +
 packages/core/src/__tests__/memory-dreams.test.ts  |  22 ++
 .../core/src/__tests__/node-override-guard.test.ts |  24 +++
 packages/core/src/__tests__/store.test.ts          |  27 +++
 .../core/src/__tests__/task-node-override.test.ts  |  25 +++
 .../src/__tests__/unavailable-node-policy.test.ts  |  42 ++++
 packages/core/src/ai-summarize.ts                  |  34 ++-
 packages/core/src/memory-dreams.ts                 |   7 +-
 packages/dashboard/app/api/legacy.ts               |   3 +-
 .../dashboard/app/components/ChangesDiffModal.css  |   2 +
 .../dashboard/app/components/ChangesDiffModal.tsx  |   5 +-
 packages/dashboard/app/components/QuickChatFAB.css | 140 +++++++++++-
 packages/dashboard/app/components/QuickChatFAB.tsx | 226 +++++++++++++++++++-
 .../dashboard/app/components/TaskChangesTab.css    |   5 +
 .../dashboard/app/components/TaskChangesTab.tsx    |   5 +-
 .../components/__tests__/ChangesDiffModal.test.tsx |  31 +++
 .../app/components/__tests__/QuickChatFAB.test.tsx | 133 +++++++++++-
 .../components/__tests__/TaskChangesTab.test.tsx   |  71 +++++++
 .../app/hooks/__tests__/useQuickChat.test.ts       |  12 +-
 packages/dashboard/app/hooks/useQuickChat.ts       | 149 +++++++------
 .../src/__tests__/routes-file-diffs.test.ts        | 165 ++++++++++++++
 packages/dashboard/src/__tests__/routes.test.ts    | 236 +++++++++++++++++++--
 .../src/routes/register-session-diff-routes.ts     |  54 ++---
 .../src/routes/register-settings-memory-routes.ts  |  23 +-
 packages/dashboard/src/routes/resolve-diff-base.ts |  72 ++++++-
 .../engine/src/__tests__/project-engine.test.ts    |   8 +-
 packages/engine/src/agent-runtime.ts               |  15 ++
 packages/engine/src/agent-session-helpers.ts       |  14 +-
 packages/engine/src/concurrency.ts                 |  37 +++-
 packages/engine/src/executor.ts                    | 183 +++++++++++-----
 packages/engine/src/merger.ts                      |  97 +++++++--
 packages/engine/src/pi.ts                          |  11 +
 packages/engine/src/project-engine.ts              |  47 +++-
 packages/engine/src/reviewer.ts                    |  95 +++++++--
 packages/engine/src/self-healing.ts                |   8 +
 packages/engine/src/triage.ts                      |  10 +-
 45 files changed, 2054 insertions(+), 272 deletions(-)

Fusion-Task-Id: FN-2849
2026-04-29 11:35:01 -07:00
gsxdsm
c6c89a0fdf fix(dashboard): prefer merge-base over outdated baseCommitSha
When a worktree was rebased onto newer main, baseCommitSha remained an
ancestor of HEAD but the range baseCommitSha..HEAD then swept in upstream
main commits as if they were task changes (FN-2840 showed 33 files for a
4-file task). The previous display-recovery only fired when baseCommitSha
was no longer an ancestor, missing this case.

When enableDisplayRecovery is on and baseBranch is missing, also compute
merge-base(HEAD, main) and prefer it when it's a descendant of
baseCommitSha (tighter fork point). When merge-base is not a descendant
(FN-2855: baseCommitSha is on a deleted feature branch), keep
baseCommitSha so we don't widen to unrelated upstream files.

Also stabilizes the card-vs-Changes-tab divergence: resolution no longer
depends on whether a rebase happened between polls.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 10:29:13 -07:00
gsxdsm
e94159c74d fix(dashboard): show only files actually changed by the task
Two fixes for the in-review/in-progress "files changed" count on task
cards and the Changes tab:

- Drop untracked files from /tasks/:id/diff and /tasks/:id/file-diffs.
  At review time these are almost always build artifacts/cache/logs not
  in .gitignore, not real task changes, and they inflated the count.
- Add display-only `enableDisplayRecovery` option to resolveDiffBase.
  When a worktree was rebased onto origin/main after baseCommitSha was
  recorded and baseBranch was not set, the prior code fell through to
  HEAD~1 — undercounting to just the last commit's files (e.g. FN-2957
  showed 2 in review, 6 after merge). Recovery now tries
  merge-base(HEAD, main) / origin/main before HEAD~1.

Routes opt into recovery; the merger's mirrored copy
(resolveTaskDiffBaseRef) is intentionally untouched so merge-time
scope warnings still evaluate the strict task base.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 10:13:39 -07:00
gsxdsm
5f4892e99f test(memory): cover dream session-state extraction and undefined output
Update dashboard mocks to push assistant text into session.state.messages
(matching real session.prompt() void return) and add a regression test for
array-shaped content. Add core unit tests for extractDreamProcessorResult
to lock in undefined/null safety.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 10:10:08 -07:00
gsxdsm
f4de01a153 fix(memory): read assistant text from session state when processing dreams
session.prompt() resolves to void; the reply lives in session.state.messages.
The dream route was awaiting its return value, so parsing crashed with
"Cannot read properties of undefined (reading 'match')" once the dream
completed. Extract the assistant text post-prompt and fail soft on
non-string input in extractDreamProcessorResult.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 09:59:52 -07:00
gsxdsm
3202e578c2 fix(FN-0000): harden sqlite startup validation 2026-04-29 07:58:58 -07:00
gsxdsm
858e24468f fix(FN-XXX): align tui startup update check 2026-04-29 07:54:45 -07:00
gsxdsm
bd14cf84e3 fix(FN-XXX): harden windows path handling 2026-04-29 07:35:23 -07:00
gsxdsm
dba6059080 fix(engine): tighten Layer 3 — pass safety constraint into AI prompt + harden Layer 2 restore
Self-review of the recovery cascade surfaced three issues; this commit
addresses all of them.

1. AI didn't actually receive the safety constraint under Layer 3.

The previous commit logged the safety preamble to the task log via
`store.logEntry`, but the merge agent doesn't read task log entries as
prompt context — so the AI was running blind. The "no silent
re-introduction of main's deletions" guarantee was therefore relying
*entirely* on the deterministic verification gate (test + build),
which is correct as a backstop but doesn't help the AI produce a
correct first attempt.

Fixed by threading `preMergeRebaseFallthrough` through
`MergeAttemptParams` → `executeMergeAttempt` → `runAiAgentForCommit` →
`MergePromptParams` → `buildMergePrompt`, where it now injects an
explicit "⚠️ Pre-merge rebase recovery exhausted" preamble at the top
of the user prompt with three concrete rules:
  - Prefer main's deletion when branch re-adds removed lines
  - Prefer main's version on ambiguous hunks
  - Call `fn_report_build_failure` rather than commit a regression
Also includes the original rebase failure message (truncated) so the
AI has diagnostic context.

The truncated-context retry path also forwards the preamble — it's the
safety constraint, not bulk context, so we keep it even when stripping
diff stat / commit log to fit the window.

2. Layer 2's branch-restore could fail with "uncommitted changes".

When a cherry-pick midway through Layer 2's replay fails, the worktree
is in a half-applied state with conflicts in the index. The previous
restore did `git checkout <branch>` (no -f) followed by
`git reset --hard <originalSha>`. The plain checkout would refuse with
"would overwrite local changes" if there were unmerged paths,
preventing the reset from running and leaving the branch at the
half-replayed tip.

Fixed by reordering: hard-reset to the captured original SHA first
(this clears index/working tree of any cherry-pick state), then
`git checkout -f <branch>` to ensure HEAD points at the named branch,
then a final hard-reset to the original SHA as belt-and-suspenders.
Worst case the worktree is at the original branch tip — never worse
than where Layer 2 started.

3. Pre-existing unrelated lint error blocking workspace lint.

`packages/dashboard/src/server.ts` had an unused `resolve` import from
`node:path` left behind by a recent refactor that extracted
`PACKAGE_VERSION` into its own file. The user explicitly asked to
clean it up so workspace lint passes. One-line drop.

Tests + checks:
- Engine: 2886 / 2886 pass (added safety preamble didn't break any
  existing prompt-content assertions)
- Core: 3120 / 3120 pass
- Workspace lint: clean
- Engine typecheck: clean

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 07:20:20 -07:00
Fusion
995165ea60 feat(FN-2944): merge fusion/fn-2944
- test(FN-2944): cover already checked out worktree conflict recovery
- fix(FN-2944): recognize git already checked out worktree conflict
- fix(engine): auto-recover from squash-merge orphan rebase failures

Fusion-Task-Id: FN-2944
2026-04-29 07:10:52 -07:00
Fusion
10d565e344 feat(FN-2929): merge fusion/fn-2929
- fix(FN-2929): complete Step 6 — add changeset and docs
- test(FN-2929): update loginProvider API test for origin payload
- test(FN-2929): complete Step 4 — cover oauth redirect rewrite and callback proxy
- fix(FN-2929): complete Step 3 — send browser origin in auth login request
- fix(FN-2929): complete Step 1-2 — rewrite OAuth redirect and add callback proxy
- feat(FN-2934): merge fusion/fn-2934

Fusion-Task-Id: FN-2929
2026-04-29 01:32:37 -07:00
Fusion
f04333672c feat(FN-2930): merge fusion/fn-2930
- test(FN-2930): complete Step 2 — add auth redirect rewrite coverage
- feat(FN-2930): complete Step 1 — rewrite OAuth redirect_uri host
- feat(FN-2928): merge fusion/fn-2928

Fusion-Task-Id: FN-2930
2026-04-29 00:45:58 -07:00
Fusion
531b13e6ad feat(FN-2895): merge fusion/fn-2895
- feat(FN-2895): complete Step 7 — documentation and delivery

Fusion-Task-Id: FN-2895
2026-04-28 21:50:27 -07:00
Fusion
7650f2d2d9 feat(FN-2909): merge fusion/fn-2909 2026-04-28 20:07:54 -07:00
gsxdsm
2029968d23 fix(FN-2662): honor project model overrides and stabilize tests 2026-04-28 18:21:17 -07:00
gsxdsm
9c19749e44 feat(FN-2879): merge fusion/fn-2879 2026-04-28 14:25:56 -07:00
Fusion
d8eb39dab7 feat(FN-2726): add bulk node override support in dashboard workflows
- Extend batch task update APIs and route handlers to accept nodeId overrides alongside model settings
- Update ListView bulk edit UX to load nodes and apply node overrides through batch updates
- Add node routing visibility improvements in task detail/settings UI and align related labels/styles
- Expand dashboard/API test coverage for node override batch updates and bulk edit behavior
2026-04-28 14:25:56 -07:00
Fusion
9a1c21f373 fix(FN-2867): simplify remote access settings activation flow
- Remove the separate "Activate Provider" action from SettingsModal and rely on save-only provider configuration
- Ensure saving remote settings enables the selected active provider and keeps provider flags consistent
- Seed remoteAccess defaults in remote settings routes when project settings are missing instead of returning conflicts
- Expand dashboard tests to cover first-use/default remote settings behavior and updated provider lifecycle expectations
2026-04-28 14:25:56 -07:00
Fusion
f3b098cc15 feat(FN-2724): add interactive task routing controls
- Replace the static routing panel with a dedicated Routing tab that shows effective node, source, and policy details
- Add per-task node override selection with optimistic save/rollback, clear override action, and in-progress lock messaging
- Tighten PATCH /tasks/:id nodeId validation (empty/non-string rejection) while preserving node override conflict enforcement
- Update dashboard route and modal tests, including new RoutingTab coverage and tab-order assertions
2026-04-28 14:25:56 -07:00
Fusion
b4ccfc00e8 feat(FN-2881): document planning notification service transition
- Add planning-module documentation explaining current ntfy helper flow and future NotificationService migration
- Detect NotificationService export availability during helper initialization and emit diagnostic info logging
- Add regression test coverage that verifies planning notifications still use ntfy helper functions when NotificationService is present
- Preserve planning awaiting-input notification behavior and click URL/event gating expectations
2026-04-28 14:25:56 -07:00
Fusion
ff58623c32 fix(FN-2861): harden planning session recovery and retry UX
- Add planning and subtask retry routes with session-lock checks and proper API error mapping
- Improve planning session execution with timeout/abort handling, stop-generation support, and resilient stream catch-up behavior
- Update Planning Mode modal to handle reconnects, retry-from-error flow, stop action, and cross-tab session state synchronization
- Expand dashboard tests for planning routes, planning session behavior, and PlanningModeModal retry/error coverage
2026-04-28 14:25:55 -07:00
gsxdsm
2f7ba29ead fix(dashboard,core): bound AI session prompt() with timeout + abort
Subtask, mission-interview, and milestone/slice-interview sessions could pin
their `generating` state forever when the underlying provider stream stalled
silently or a tool call hung. Wrap each `agent.session.prompt()` in a new
GenerationGuard helper (per-session AbortController + timer) so a stuck turn
becomes a bounded error users can retry. Adds matching `stop*Generation`
exports and threads abort through cleanup so dismissing a modal cancels the
in-flight call instead of leaking it.

Also closes the gh-cli tool hang vector: `runGhAsync` / `runGhJsonAsync` now
accept `{ signal, timeoutMs }` (default 30s). Github-touching extension tools
forward the AI tool's signal so an aborted agent kills the `gh` child instead
of orphaning it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 14:25:55 -07:00
gsxdsm
479f25d50f fix(FN-2855): scope task diff base to baseCommitSha when branch is null
When a dependency task merges and its branch is deleted, self-healing nulls
the dependent task's baseBranch. Both resolveDiffBase (dashboard) and
resolveTaskDiffBaseRef (merger) defaulted to "main" in that case, widening
the diff range to merge-base(HEAD, main) and surfacing unrelated history —
e.g. FN-2855 reported 108 changed files instead of 16. Skip the merge-base
step when baseBranch is unset and a baseCommitSha is recorded; fall back to
"main" only for legacy tasks lacking both hints.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 14:25:55 -07:00
Fusion
f19ecac8f5 feat(FN-2848): add manual memory dream API trigger
- Add POST /api/memory/dream route that runs project and agent dream processing with AI prompt execution
- Expose triggerMemoryDreams() in dashboard legacy API client for direct dream invocation
- Switch SettingsModal and useMemoryData Dream Now actions from automation lookup to the new endpoint
- Update dashboard route, hook, and settings modal tests to cover success and error handling
- Add a patch changeset for @runfusion/fusion documenting the new endpoint and client helper
2026-04-28 14:25:55 -07:00
Fusion
1d9d9f4e7f feat(FN-2843): auto-select quick chat default model
- Extend /models API responses to include optional defaultProvider/defaultModelId from global settings, including empty and error paths
- Update QuickChatFAB to prefer the configured default model on load and fall back to first-model selection only when no agents exist
- Move quick chat model tag/title-wrap inline styles into QuickChatFAB.css using dashboard design tokens
- Add QuickChatFAB tests covering default-model auto-selection with and without agents and legacy behavior when no default is configured
2026-04-28 14:25:55 -07:00
Fusion
789afc30b0 feat(FN-2721): enforce node override guard across task workflows
- Add a core node-override-guard module, export it from @fusion/core, and enforce conflicts in store updates
- Add API route and CLI extension safeguards so nodeId override updates are blocked when ownership would conflict
- Wire node override routing and validation through dashboard quick-create, list, modal, settings, and task form/detail surfaces
- Add focused unit and integration tests for core guard logic, workflow routes, and dashboard node override UX
2026-04-28 14:25:55 -07:00
Fusion
3174f0dc64 chore(release): v0.7.1
Version bump via changesets.
2026-04-28 14:25:55 -07:00
gsxdsm
2229815bad fix: harden cross-platform paths and child-process handling
Replace process.env.HOME fallbacks with os.homedir() in dashboard usage
probes and the hermes plugin profile resolver so unset HOME no longer
yields literal "~" paths. Skip POSIX process-group semantics on Windows
in engine/merger and dashboard-tui's pgrep-based vitest killer. Add
shell: true to npx spawns in CLI skills/extension so .cmd shims resolve
on Windows, and route test:build-exe through cross-env.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:27:27 -07:00
gsxdsm
02d68f945d fix(dashboard): restore NodeStatusIndicator tests and fix routes.ts typecheck
- packages/dashboard/src/routes.ts: hermes/openclaw runtime metadata declares
  `version` as `string | undefined`, but BUNDLED_PLUGIN_RUNTIMES requires
  `string`. Coalesce to "0.0.0" so the bundled fallback list type-checks.
- packages/dashboard/app/components/__tests__/NodeStatusIndicator.test.tsx:
  the file had been reduced to a stub ("placeholder") which the test runner
  parsed as an undefined identifier. Restore the original 155-line suite from
  fc23e522a; the underlying NodeStatusIndicator component is unchanged.

All 9639 dashboard tests pass; pnpm typecheck is clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:26:47 -07:00
gsxdsm
4d48be9a5c fix(dashboard): expose bundled hermes/openclaw/paperclip runtimes in /api/plugins/runtimes
Merge metadata for the three example runtime plugins bundled as workspace
dependencies of @fusion/dashboard with pluginLoader.getPluginRuntimes(), so
the NewAgentDialog "Plugin Runtime" dropdown populates without requiring
an explicit `fn plugin install`. Installed plugins override the bundled
fallback by runtimeId.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:24:21 -07:00
gsxdsm
a6697ee7ca feat(paperclip-runtime): route Paperclip calls through paperclipai CLI in Local CLI mode
The Paperclip runtime card's Local CLI tab previously only derived an apiUrl
from the local config and then made HTTP calls itself, so the Test action and
the company/agent pickers ignored the user's onboarded CLI auth context.

Add CLI-backed variants for every Paperclip call that has a `paperclipai`
counterpart, and route through them when transport=cli — both from the
settings card and from the runtime adapter's prompt path.

- New plugin functions spawning `paperclipai … --json`:
  * probePaperclipViaCli, listCompaniesViaCli, listCompanyAgentsViaCli
    (settings card test + pickers)
  * createIssueViaCli, getIssueViaCli, agentsMeViaCli (runtime hot path)
- New dashboard routes: /providers/paperclip/cli-status, /cli-companies,
  /cli-agents (read-only façades over the plugin's CLI helpers)
- PaperclipRuntimeCard: branches on transport=cli to use the cli-* fetchers
- PaperclipRuntimeAdapter: stores transport on the session and routes
  createIssue/getIssue + identity derivation through CLI variants in CLI mode;
  raises a clear error when agentId is unset in CLI mode (paperclipai has no
  /agents/me equivalent)
- getIssueComments / wakeAgent / getRunEvents stay on HTTP (no matching
  paperclipai subcommands) and continue to use the apiKey discovered from
  the local paperclipai config, so CLI mode still works end-to-end
- Tests: 9 new paperclip-client tests covering each CLI variant + 5 new
  adapter tests for the Local-CLI transport branch (64/64 plugin tests pass)
- Update routes.test for the existing BUNDLED_PLUGIN_RUNTIMES fallback so
  the bundled hermes/openclaw/paperclip entries are expected alongside
  installed plugins

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:06:20 -07:00
Fusion
d3e1c28cef fix(plugins): re-export probe symbols + declare plugin deps in dashboard
- Hermes / OpenClaw plugin index.ts now re-export `probeHermesBinary` /
  `probeOpenClawBinary` and their status types so the dashboard's
  `runtime-provider-probes.ts` façade can import them via the public
  package entry instead of deep paths.
- Dashboard `package.json` adds `@fusion-plugin-examples/hermes-runtime`,
  `…/openclaw-runtime`, `…/paperclip-runtime` as workspace deps so
  pnpm symlinks them into `packages/dashboard/node_modules/`. Without
  these, the new probe imports failed with "Cannot find module" during
  `pnpm typecheck`.

This clears 6 of the 9 outstanding typecheck errors. The remaining 3 are
in the in-flight Hermes plugin rewrite (runtime-adapter still imports
from a deleted `./pi-module.js`; the new `index.ts` calls a factory
with the wrong arg type) and should be resolved by the same change set
that landed the rewrite.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 22:17:54 -07:00
gsxdsm
1fe59be960 feat(dashboard,cli): update-check frequency, GitHub star button, more resizable modals
Update-check frequency (end-to-end)
- Add `updateCheckFrequency: "manual" | "on-startup" | "daily" | "weekly"`
  to GlobalSettings (default: "daily").
- Backend `performUpdateCheck` honors the frequency: TTL = day/week,
  `manual` returns cache or empty without hitting npm, `on-startup`
  refreshes once per process lifetime then serves cache. `/refresh`
  route forces network regardless.
- Settings → Updates surfaces a working `<select>` for the cadence,
  disabled when auto-checks are off entirely.
- Tests: 4 new cases covering ttlForFrequency mapping, weekly window,
  manual semantics, on-startup once-per-process behavior.

TUI update notice
- Read cached update result synchronously on TUI startup. When an
  update is available, render a yellow notice line on the splash and
  a colored ● next to the version in the status bar.

Settings modal header polish
- Add "Star on GitHub" pill (icon + Star + cached star count from the
  GitHub API, 1h localStorage TTL) and "Help" button (opens project
  Discussions). Both link to the Runfusion/Fusion repo.
- Star button auto-hides after the user clicks it (intent = star),
  tracked in localStorage `fusion:github-star-clicked`.
- Settings → General gets a "Show Star on GitHub button" checkbox so
  users can hide it preemptively. New global setting
  `showGitHubStarButton: boolean` (default true) gates rendering.

More resizable modals
- Task Detail modal: 85vh default, resize: both, persisted via
  useModalResizePersist (key `fusion:task-detail-modal-size`).
- Quick Chat FAB: full 8-direction resize (4 corners + 4 edges) via
  pointer-event handlers; persisted to
  `fusion:quick-chat-size-<projectId>`. Each handle has the right
  cursor + role="separator" for accessibility.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 17:55:15 -07:00
gsxdsm
9650019877 fix(dashboard): prevent foreign-branch diffs after worktree pool reuse
When the worktree-recycle pool reassigned a path to a new task, the old
task's diff endpoints kept reading the new task's branch state — surfacing
unrelated commits as the original task's "files changed" list.

- Clear task.worktree/branch in the merger after the worktree is released
  to the pool or removed, so the path no longer points anywhere.
- Validate the worktree's current branch matches task.branch in the three
  worktree-backed diff endpoints; on mismatch return empty rather than
  diffing against a foreign branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 11:04:42 -07:00
Fusion
b2f71a2136 feat(FN-2689): standardize cross-platform shell selection
- Add engine shell utility to resolve the correct shell per platform
- Update routine runner to execute commands through shared shell selection
- Update cron runner to use the same cross-platform shell behavior
- Apply shared shell handling in dashboard routes for command execution
- Add shell utility tests covering platform-specific selection behavior
2026-04-27 08:33:03 -07:00
Fusion
0a5dcf12bc fix(FN-2684): harden system-stats when project lookup fails
- Keep /api/system-stats process and host metrics available even if scoped project resolution throws
- Fall back task and agent aggregates to zero when scoped task or agent stores cannot be loaded
- Preserve vitest process reporting while guarding optional vitestLastAutoKillAt lookup behind scoped context success
- Add route tests for scoped project-not-found fallback behavior and include a patch changeset for @runfusion/fusion
2026-04-27 06:03:53 -07:00
Fusion
ec092825ac feat(FN-2681): add Vitest kill controls in system stats
- Add dashboard API endpoint and server route to terminate Vitest worker processes safely
- Extend legacy API client with killVitestProcess support for frontend invocation
- Add SystemStatsModal UI controls and styling for triggering Vitest kill actions, including mobile width stability fixes
- Expand route and modal tests to cover new controls and behavior
- Add changeset and architecture docs updates for the new Vitest kill capability
2026-04-27 05:50:40 -07:00
Fusion
5517a59432 feat(FN-2673): stream automation schedule events over SSE
- Wire AutomationStore into dashboard SSE setup for both default and project-scoped /api/events streams
- Emit schedule:created, schedule:updated, schedule:deleted, and schedule:run events to connected SSE clients
- Add SSE coverage for automation event subscription, relay payloads, cleanup on disconnect, and graceful behavior without automation store
- Add server events integration coverage for automationStore wiring and document automation schedule events in architecture docs
2026-04-27 03:21:59 -07:00
Fusion
92b8631aad fix(FN-2672): harden automation execution and scheduling flows
- Improve automation startup diagnostics and route handling for manual execution steps
- Add support for full manual automation step execution in dashboard and engine flows
- Expand due-schedule coverage in automation store and dashboard route tests
- Add cron runner regression tests for edge cases and document the automation execution fix via changeset
2026-04-27 03:07:58 -07:00
Fusion
7806724cf2 feat(FN-2664): add dashboard updates check endpoint and settings flow
- Add GET /api/updates/check endpoint in dashboard server with coverage for success, failure, and disabled update scenarios
- Extend legacy dashboard API client with check-for-updates request support
- Add Settings modal update-check UI and styling for trigger, loading, and result states
- Expand Settings modal tests and document the updates check endpoint in architecture docs
2026-04-27 02:19:44 -07:00
Fusion
d4a8a45904 feat(FN-2666): filter unauthenticated providers from usage results
- Update fetchAllProviderUsage() to exclude providers in no-auth status before caching and returning data
- Keep usage cache aligned with the filtered provider list so TTL reads match authenticated-only behavior
- Revise dashboard usage tests to assert empty/undefined provider results when credentials are missing
2026-04-27 01:54:25 -07:00
Fusion
acbd6580b3 feat(FN-2663): add cached update-check setting, APIs, and banner
- Add global updateCheckEnabled setting to core schema/types and wire dashboard command to cache update checks in the CLI
- Implement dashboard server update-check cache module plus REST routes for status and refresh behavior
- Add dashboard client hook, legacy API helpers, and UpdateAvailableBanner UI to show cached CLI update notices
- Cover update-check server routes, hook behavior, banner rendering, and route registration with focused tests
- Document update-check configuration and API behavior in architecture and settings reference docs
2026-04-27 01:40:07 -07:00