The /_perf/dashboard-load server route no longer exists, so every
reportDashboardPerf() call was a silently-swallowed 404. Remove the helper
in legacy.ts plus its five call sites in App.tsx / useProjects.ts (the
companion console.log lines stay), and drop the dashboard-perf.log entry
from the test-isolation runtime ignore list since nothing writes that file
anymore.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This merge lands eval score categorization and evaluator hardening in core/engine, mobile mission CTA improvements with documented behavior, reply-link threading documentation, and a test-isolation fix that tolerates runtime noise on shared HOME directories. Dashboard components affected include Mai
Fusion-Task-Id: FN-3601
Local `pnpm test:isolated` was failing because a concurrently-running
fusion app continually mutates `~/.fusion` (databases, agent sessions,
memory, automations, plugins, logs). Filter those runtime-owned paths
from the protected-dir signature, widen the baseline-stability sampling
window, and re-sample on suspected violations so transient app activity
doesn't masquerade as test pollution.
Tests still cannot legitimately write into these paths — they're skipped
because the *running app* is expected to.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This merge restores the canonical agent lifecycle with termination scoped at the run level (FN-3580, 4 steps), adds sender-side wake recipient override for messages, and introduces test isolation CI enforcement with a stuck-requeue race fix. UI changes remove terminated-agent indicators from AgentDe
Fusion-Task-Id: FN-3580
This merge lands five FN-3593 commits establishing a test isolation contract with a new `scripts/check-test-isolation.mjs` guard that scans for accidental `beforeEach`/`afterEach`/`beforeAll`/`afterAll` in setup helpers, plus per-package `setup-test-isolation.ts` bootstraps that canonicalize the pat
Fusion-Task-Id: FN-3593
Senders can now force the recipient agent to wake on receipt regardless
of the recipient's `messageResponseMode`. Surfaced as a "Wake recipient
immediately" checkbox in MessageComposer and as a `wake_recipient`
boolean param on the `fn_send_message` agent tool. Carried as
`metadata.wakeRecipient: true` on the message; the heartbeat hook
treats forced wakes as `message_received_urgent` in the wake delta so
agents can distinguish them from normal `messageResponseMode: immediate`
wakes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When SelfHealingManager.recoverCompletedTasks moved a task from
in-progress to in-review, the executor's stuck-kill cleanup running in
execute()'s finally block could fire 20s later, see a stale captured
task.column = "in-progress", and overwrite the recovery by tearing down
the worktree and moving the task back to todo with all step progress
reset. Both the outer-finally and step-session requeue blocks (and the
force-requeue setTimeout in markStuckAborted) now re-read the latest
column and skip cleanup entirely if the task has moved past
in-progress/todo.
Adds a new preserveProgressOnStuckRequeue setting (default: true,
toggle in Settings near the Stuck Task Timeout) so stuck-requeue passes
{ preserveProgress: true } to moveTask. Completed step statuses now
survive the bounce so the agent resumes from where it left off instead
of restarting every step from pending.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Update AgentErrorDetailsModal styles to improve mobile layout and avoid viewport overflow
- Add mobile regression tests for agent modal behavior in agent-modals-mobile coverage
- Extend core modal mobile test suite with AgentErrorDetailsModal safeguards
Fusion-Task-Id: FN-3587
The merge integrates five commits across the engine and dashboard: it fixes a quick chat icon-tag regression, ensures manual heartbeat runs respond immediately once a run record exists, splits the agents overview label into separate active vs running counts, prevents inbox messages from being auto-m
Fusion-Task-Id: FN-3586
The Overview dropdown previously rendered "X active · Y running" where
both X (stats.activeCount) and Y (activeAgents.length) counted agents
whose state was either "active" or "running" — so an agent that was
merely enabled but idle would still inflate the "running" tally. The
label now counts each state distinctly so "running" only reflects
agents that are mid-heartbeat. Adds AgentsOverviewBar.test.tsx to lock
in the new contract.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the dashboard user browses another agent's mailbox (e.g. the CEO's
inbox), opening a message no longer triggers POST /messages/:id/read.
The previous behavior silently consumed the agent's unread state, so the
agent's heartbeat never surfaced the message and fn_read_messages (which
defaults to unread_only=true) returned nothing. Auto-mark-read now only
fires on the dashboard user's own inbox tab. Adds regression tests in
MailboxView.test.tsx and MailboxModal.test.tsx.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This merge introduces a memory file markdown preview feature (FN-3584) with corresponding documentation, refines the AgentDetailView and AgentLogViewer components in the dashboard, and adds defensive collision handling for worktree operations during manual task moves (FN-3583).
Fusion-Task-Id: FN-3584
The merge lands five commits: a fix (FN-3583) that preserves non-tool message boundaries when tools are hidden in CLI bundles, plus hardened test coverage for that regression and bundle asset bootstrapping; worktree collision prevention on manual task moves via a new `worktree-names.ts` module and s
Fusion-Task-Id: FN-3583
This merge adds a canonical in-dialog AI interview flow for agent onboarding (FN-3553), replacing the old wizard with a multi-step dialog that guides users through creating and reviewing agent prompts before spawning, plus tokenized typography fixes. It also introduces native shell connection handof
Fusion-Task-Id: FN-3553
This merge adds a complete plugin management system (FN-3565) with CLI commands, a loader, runner, and dashboard routes, along with project-scoped auth storage (FN-3544), native shell connection support for mobile (FN-3400) spanning onboarding, connection manager, and remote desktop handoff, and ref
Fusion-Task-Id: FN-3400
Fixes FN-3567 by synchronizing the `allowParallelExecution` runtime toggle in the AgentDetailView component, adding one line to keep the setting in sync.
Fusion-Task-Id: FN-3567
This merge completes the agent terminated state alignment (FN-3535), adding "running → terminated" transition support with consistent styling and lifecycle controls across the heartbeat engine, agent store, and dashboard UI, plus plugin author documentation improvements (FN-3537) and plugin loader t
Fusion-Task-Id: FN-3535
Refactored plugin-loader tests and implementation to isolate plugin test contamination, improving test independence in `@fusion/core`.
Fusion-Task-Id: FN-3564
In a narrow resized sidebar the milestones / features / tasks counts ran
off the card edge because .mission-list__item-summary was a non-wrapping
flex row. Switch it to flex-wrap with split row/column gaps so the stats
reflow onto new lines instead of clipping.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Promote the sidebar "Plan New Mission" CTA to a btn-primary (matching the
chat sidebar's "New Chat") and drop the dashed icon buttons; full-width
progress bar and Activity row each get their own line in the card.
- Auto-select the first mission in the inline desktop view so users land
in detail rather than the empty placeholder. Skipped in mobile and the
standalone modal so existing flows and unit tests stay intact.
- Replace the bare "No missions yet" line with a richer empty state that
explains what missions are and offers an inline Plan New Mission CTA.
- Guard loadMissionDetail against malformed responses (missing milestones)
so racing fetch fallbacks don't crash the detail render.
- Update three MissionManager tests to match the new copy/structure.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Import button moved to the AgentsView header; its detail-view test
coverage no longer applies.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Recovers cleanups from stash@{2}/stash@{3} (FN-3530 merger autostashes)
that the merger never restored: 4 dead `[data-state="terminated"]`
selectors in AgentListModal.css, 3 CSS-class assertions in
agent-css-classes.test.ts targeting classes the runtime no longer emits,
and a `state: "terminated"` fixture in routes-agents.test.ts now flipped
to `paused` so the "invalid state transitions" test exercises a real
rejection (paused→paused is not in AGENT_VALID_TRANSITIONS).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Stack mission cards vertically inside the sidebar so the title gets
the full card width; action buttons drop to their own row below.
- Move the Activity timestamp out of the cramped stats row onto its
own line.
- Replace the icon-only Sparkles button in the sidebar header with a
full-width centered "Plan New Mission" button (icon + text). Mobile
footer button uses the same label.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Shorten Import button aria-label/title to "Import" to match visible text.
- Add agent-controls-actions class to the global controls wrapper.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Make the mission split sidebar drag-resizable (220–560px, persisted) so
long mission titles aren't trapped behind a fixed-width column.
- Move card tags (autopilot/health/status) to a row below the title and
drop the overflowing "Active: …" line.
- Collapse mission creation to a single AI-driven entry point: rename
Sparkles to "Create New Mission" and remove the manual "+" button.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The avatar already self-renders its colored badge; the wrapper's
var(--todo) tile produced a redundant outline around the icon.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous commit's working-tree state lost the AgentsView/AgentDetailView
edits during an auto-stash flow; re-applies the move so Import sits beside
"New Agent" in the global header and is gone from the detail page and
controls panel.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Creating a new terminal tab caused every pty data chunk (including
keystroke echo) to render twice in xterm. The connect-effect's
`contextChanged` dep flips true→false in the same render cycle as
the new connection: the effect re-runs, React calls cleanup which
closed the still-CONNECTING WS without nulling its handlers, then
connect() opens a fresh WS. The ghost socket's onmessage continued
firing on the shared `onDataCallbacksRef` Set, delivering each chunk
twice (and producing the "WebSocket is closed before the connection
is established" warning). Null onopen/onmessage/onclose/onerror in
both cleanup() and connect()'s pre-close branch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Permanent agents now run heartbeats regardless of bound-task block state.
The prior queued+blockedBy early-exit and its state-tracking machinery are
removed; HEARTBEAT_SYSTEM_PROMPT is rewritten to scope heartbeats to
ambient coordination (messaging, memory, finding work, delegation,
surfacing/chasing blockers, status). Task body work continues via the
executor path. Ephemeral agents are unchanged.
New allowParallelExecution flag (default true, permanent agents only) on
AgentHeartbeatConfig. When false, heartbeat and executor paths serialize
symmetrically: a heartbeat will not start while the agent's bound task
has an active executor session, and an executor session will not start
while the agent has an active heartbeat run. Either side re-dispatches
the other's deferred work on completion. UI toggle surfaces in the
agent's Heartbeat Settings tab.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a "Tools: On/Off" toggle next to the existing markdown toggle in
AgentLogViewer (used by both agent logs and task agent logs). When tool
output is off, tool/tool_result/tool_error entries are filtered before
grouping so only agent text and thinking render. Both toggles persist
globally across sessions via localStorage (fn-agent-log-markdown,
fn-agent-log-tool-output).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes no-op `agents.filter((a) => true)` calls (a leftover from the
terminated AgentState refactor) flagged by eslint and updates affected
tests and fixtures so `terminated` is no longer referenced. Also:
- Deletes the duplicate `state === "paused"` render branch in
AgentListModal list view that produced two "Resume" buttons.
- Updates the AgentDetailView help text to reflect the current
deletable states ("idle or paused").
- Aligns the bundled-plugin-install test with the new auto-load
behavior for already-installed enabled plugins.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the engine boots, if an agent has the new
runMissedHeartbeatOnStartup flag enabled and lastHeartbeatAt is older
than its interval, fire one catch-up heartbeat through the existing
executeHeartbeat path. Default is off, so existing agents are
unchanged. Toggle exposed in the agent's Heartbeat Settings tab.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Only running shows green and error shows red; idle/active/paused share
the neutral gray border and badge across the agent list, board, and
org-chart views.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops "terminated" from AGENT_STATES. The agent lifecycle now runs through
idle | active | running | paused | error. paused (carrying a pauseReason)
absorbs every former terminated use case — manual stop, heartbeat run
termination, spawned-child cleanup. Run status (agentRuns.status) is
unchanged: "terminated" stays a valid run-status value.
AGENT_VALID_TRANSITIONS allows direct any→idle transitions so resetAgent
no longer needs the intermediate hop.
Stack-wide:
- core/agent-store: lastError clearing + resetAgent simplified.
- engine/agent-heartbeat, executor, in-process-runtime: terminated state
writes → paused; halt-state listener fires on paused/error.
- dashboard: AgentsView/AgentListModal/AgentDetailView lose the Terminated
badge/option/state-block; agent pickers no longer filter terminated;
agentHealth drops the Terminated branch; routes/state cast widened to
the new AgentState union.
Tests across core and engine updated to assert paused for AgentState and
left "terminated" intact for run-status assertions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Run Now now optimistically stamps the agent's state to "running" before
the startAgentRun API call so the card reacts immediately. Rolls back on
error, mirroring the handleStateChange pattern.
- Whole .agent-card body is clickable (role=button, Enter/Space, focus ring)
and bails when the click landed on an action button, select, or the
role-icon so those keep their dedicated behaviors.
- Renamed the card's "View Details" button to "Details" and switched
.agent-card-actions to flex-wrap: nowrap so Run Now / Pause / Details
stay on one row regardless of card width.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add AgentErrorDetailsModal and wire agent list/detail views to open full error diagnostics while keeping inline errors compact
- Add line-number gutter toggle in FileEditor and Files modal with dashboard persistence coverage
- Align project memory scope guidance across core logic, CLI tool docs, and dashboard docs
- Add regression coverage for runtime plugin alias behavior and update related engine/heartbeat tests
- Include changesets for FN-3530 UI improvements and FN-3485 memory guidance updates
Fusion-Task-Id: FN-3530
This merge adds a line-number toggle to the Files modal with persisted preference, introduces an AgentAvatar component with server-side avatar storage routes, and adds documentation for both the toggle and avatar storage. It also includes a regression test for runtime plugin alias behavior and updat
Fusion-Task-Id: FN-3528
Six new tests covering the three bugs fixed in the previous commit:
- Retry limit: stops showing toasts after 3 consecutive failures,
resets counter on success
- Skip flag: startFreshSession sets/clears skipNextSessionInitRef,
creates new session even when existing one exists
- Ref stability: switchSession reads activeSession from ref so it
correctly detects "same session" and skips re-initialization
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three interacting bugs caused "Failed to initialize chat" toast spam and
prevented fresh session creation:
1. Race condition in handleCreateFreshSession — setting chatMode/
selectedAgentId before startFreshSession triggered the session-init
useEffect, which called switchSession and resumed the old session
instead of creating a new one. Fixed with skipNextSessionInitRef.
2. Infinite retry loop — shouldRetrySessionInit retried indefinitely
when initializeSession failed, producing unbounded toast spam.
Fixed with a 3-retry cap (initRetryCountRef).
3. Cascading re-renders — switchSession depended on activeSession in
its closure, getting a new identity on every state change and
re-triggering the consumer's useEffect. Fixed by reading
activeSession from a ref instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the local fn/fusion CLI is on the wrong version, the banner now
says "Update the Fusion CLI", shows installed vs expected versions,
and labels the action "Update with npm" instead of the generic install
copy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The test clicked 'Medium' and 'Continue' synchronously without waiting
for the scope question options to fully render. Use findByText/findByRole
to wait for elements to appear before interacting, and add a timeout to
the final waitFor for the second question.