Move ActiveAgentsPanel between AgentMetricsBar and the main agent
collection so live work is visible without scrolling past the whole
agent directory. Add a "Next heartbeat in Xs" line to each card
footer (or "Heartbeat overdue" when negative), driven by
runtimeConfig.heartbeatIntervalMs with the dashboard default fallback.
Give cards a pointer cursor + hover/focus styling so the existing
click-to-select behavior is discoverable.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Agents in `active` state without a current taskId had no SSE to attach
to, but the card still rendered "Connecting..." — implying a network
state that never resolves. Branch on taskId first: idle agents show
"Idle — no task assigned"; running-without-task shows "Starting...".
Also fix a related SSE multiplexer race: subscribers joining a channel
that had already opened never got an onOpen callback (EventSource only
fires `open` once), so they sat at isConnected=false forever whenever
another component was already streaming the same URL. Fire onOpen on a
microtask for late-joiners.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The in-review timer chip was driven by per-step instrumented duration,
which is frozen during a merge (the merge phase isn't tracked as a
workflow step). A stuck merge could read "3m" indefinitely. While
status is "merging"/"merging-pr", show live elapsed since updatedAt
(set by the merger at status flip) with a "Merging Nm" tooltip.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
* Drop the Target port field from Settings — the dashboard already knows
what port it's serving on, so use window.location.port (falling back
to 80/443 by protocol). A user-overridable port adds no value and a
stale stored value silently misroutes the funnel.
* Restructure the running-tunnel scan block to show three rows: the
raw tailnet URL, the remote access code (rt= token, separate), and
the QR image. Previously the auth URL was rendered as one long string
that read as "the bare hostname" when truncated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Preserve and emphasize active agent card highlights across hover and modal states, with dedicated CSS updates and regression tests
- Expand dashboard and TUI activity surfaces for grouped tool-call and live agent status/log visibility, including Quick Chat and chat view refinements
- Add route and runtime updates for agent/settings flows plus self-healing coverage for merge recovery behavior
- Include accompanying changesets and test stabilizations for mission activity assertions and active highlight hooks
Fusion-Task-Id: FN-2932
- Inline grouped tool-call rendering in chat surfaces and update summary logic for clearer aggregation
- Refine chat, quick FAB, settings, and agents UI styles/behavior with matching test coverage updates
- Extend dashboard TUI state/controller flow with status and shortcut improvements
- Update engine and dashboard route handling related to agent runs, settings memory sync, and remote access adapters
Fusion-Task-Id: FN-2926
* 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>
Empty hostname triggered provider_not_configured even though the field
was labeled "(optional)". Drop the misleading label and default to the
browser's current hostname so the start action succeeds out of the box.
Also drop the legacy MediaQueryList.addListener fallback to clear the
deprecation warning.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
Two pre-existing local modifications that had been sitting in the
working tree across this session, neither produced by the recovery /
fallback work in adjacent commits. Committing them so the tree is clean.
- packages/dashboard/app/components/SettingsModal.css
Removes one trailing blank line at end-of-file. No semantic change.
- packages/dashboard/app/components/__tests__/ListView.test.tsx
Drops one test case ("shows NodeHealthDot for selected bulk node
override", 15 lines) from the "ListView - Bulk Selection" describe
block. The test asserted that selecting a bulk node override
rendered a `.status-dot--online` indicator in the DOM. Sibling tests
(option labels, batchUpdateTaskModels invocation) are preserved.
Likely debris from the FN-2729 NodeHealthDot work that didn't survive
one of the in-flight squash merges; the underlying behavior is still
exercised by the kept tests.
Verified: pnpm --filter @fusion/dashboard test ListView passes
(125/125), so the removed assertion isn't load-bearing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires the AI commit-body generator (introduced in 60217ce19) to the
existing dedicated title-summarization model lane, and updates the
settings UI so users understand the model is now used for two
short-summary jobs instead of just one. Also de-duplicates the
project-scope settings UI which was exposing the same model setting in
two places.
Engine (merger.ts):
- aiGenerateCommitBody now prefers settings.titleSummarizerProvider /
titleSummarizerModelId over the merger's default model. The
summarization lane is the right tier for this work — small, fast,
cheap. Falls back to the default merger model when the summarization
lane is unset.
Dashboard (SettingsModal.tsx):
- MODEL_LANES summarization lane label updated:
"Title Summarization Model" → "Title and Git Commit Message
Summarization Model". Helper text updated to mention the dual purpose
(auto-generated task titles + fallback merge commit message bodies).
This change flows through automatically to BOTH the global model
lanes view and any project-scope rendering of MODEL_LANES.
- Removed the duplicate summarization picker from the project-scope
Model Lanes section: previously it appeared once under Model Lanes
AND once under "AI Summarization". Now lives only in the dedicated
picker so users have a single source of truth in project scope.
- The dedicated picker section heading + description rewritten:
"AI Summarization" → "AI Title and Git Commit Message Summarization",
with a paragraph explaining both jobs the model performs.
- Inner dropdown label updated for consistency.
Tests + checks: engine 2887/2887 pass, dashboard typecheck clean,
workspace lint clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Resolve merge conflicts in InlineCreateCard and QuickEntryBox using the existing node picker UX
- Replace ad-hoc node status rendering with NodeHealthDot in task creation surfaces
- Keep advanced quick-create controls and portal-based dropdown behavior intact
- Preserve related dashboard styling and tests included in the staged squash
Fusion-Task-Id: FN-2729
- Default Cloudflare remote access to Quick Tunnel mode in settings documentation
- Replace the Quick Tunnel checkbox with an Advanced (Named Tunnel) details disclosure in SettingsModal
- Auto-sync quick tunnel state from the details open/close state while preserving named tunnel field editing
- Update SettingsModal tests to cover the new advanced-toggle behavior and persisted quick tunnel payload
Fusion-Task-Id: FN-2916
- Add attachment-first chat compose flow with paperclip picker, drag-and-drop, and paste support in ChatView input
- Render pending attachment preview chips with per-file remove actions and drag-over visual affordance
- Display sent message attachments with image/file presentation and accessible focus/interaction styling
- Update ChatView tests and icon mocks to cover attachment-only sends, file selection, and preview behavior
Fusion-Task-Id: FN-2911
- fix(FN-2914): remove divider line between close and shortcuts buttons in terminal
- feat(FN-2902): merge fusion/fn-2902
- chore(release): v0.8.3
- Update changeset
- fix(tui): swap 3/4 panel hotkeys so they match the help text
- fix(tui): always show auth token and report accurate macOS memory usage
- chore(release): v0.8.2
- feat(FN-2895): merge fusion/fn-2895
Fusion-Task-Id: FN-2914
Lead with Project Name, then Project Directory. Move setup-mode toggle
(existing vs clone) and the repository URL field into Advanced Settings
so the default path is one question — pick a folder, name it, register —
without the welcome blurb and mode picker getting in the way.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Remove btn-icon styling from ChatView render toggle controls and apply dedicated borderless toggle styling
- Update ChatView and QuickChatFAB behavior so quick chat streaming state is preserved when resuming sessions
- Add regression tests for QuickChatFAB and useQuickChat to cover resume and streaming-state handling
Fusion-Task-Id: FN-2906
- Keep active streaming responses alive when resuming an existing quick chat session instead of resetting stream state
- Update useQuickChat session-resume logic to only restart waiting indicators when appropriate
- Adjust QuickChatFAB waiting indicator behavior so it reflects real in-flight assistant activity
- Add focused hook and component tests covering same-session resume and waiting-indicator regressions
Fusion-Task-Id: FN-2904