Patch process.emitWarning in the shared vitest setup to drop the
"SQLite is an experimental feature" notice; align the test mock for
getQrPayload with the canonical RemoteQrPayload signature.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Raise checkForChanges slow-poll warn threshold from 100ms to 750ms so
warnings only fire when cycles approach the 1s poll interval, and route
skill-resolver info diagnostics through log() instead of warn().
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Documents the race called out in code review: when recovery samples a
stale run id and a fresh run is spawned for the same agent before
endHeartbeatRun() lands, only the sampled id is terminated — never the
freshly-spawned run.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the dashboard crashes mid-heartbeat, the agentRuns row is left in
status='active' forever. HeartbeatTriggerScheduler.onTimerTick treats
any active run as "still running" and skips every subsequent tick, so
agents go silent indefinitely (observed: 6+ hours). The existing
in-memory missed-heartbeat watchdog can't help — its trackedAgents map
is wiped on process restart.
SelfHealingManager.recoverStaleHeartbeatRuns now reconciles these on
startup and during periodic maintenance: terminates active runs whose
processPid does not match the current process, has no recorded pid, or
has been active for more than 6 hours.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The MissionLoop calls this.missionStore.listMissions() during startup
recovery, but the mock TaskStore's getMissionStore() return value didn't
include this method. When the runtime startup sequence raced ahead, it
would hit "listMissions is not a function" — making the test flaky.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The merge completes FN-3498 across three steps: adds ownership-aware done-task reconciliation to the merger, prevents branch-missing head SHA pollution during merge operations, and restores workspace typecheck compatibility. Core changes touch the merger (103 lines) and self-healing module (67 lines
Fusion-Task-Id: FN-3498
Merged four commits implementing comment-driven retriage: triage rules now respond to specific comment patterns (Step 1) and surface needs-replan feedback inputs in the UI (Step 2), with documentation for the new behavior and a bug fix restoring workspace typecheck defaults. Changes span the core ta
Fusion-Task-Id: FN-3502
Merges FN-3470 in two steps: first, runtime plugins now prefer source path aliases over build artifacts, with hardening tests for vitest alias resolution and plugin view registry updates; second, a new `ensure-test-artifacts.mjs` bootstrap script guarantees required test files exist before test runs
Fusion-Task-Id: FN-3470
This merge introduces an eval automation domain store with persistence schema and a plugin dashboard view registry (FN-3512/FN-3513), adds scheduled eval batch architecture documentation (FN-3388), and includes substantial test coverage for Research routes and hooks (FN-3368 steps 1-3). The branch a
Fusion-Task-Id: FN-3368
The options parameter in __setCreateFnAgent's inline arrow already
uses any to match the module-level let (which has its own suppress
comment). Add the missing eslint-disable-next-line so CI passes.
Unrelated to the spinner fix — pre-existing on main.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-existing lint error on main — the `any` cast in __setCreateFnAgent
mirrors the eslint-disable already on the adjacent variable declarations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Simulates a database where project_insight_runs exists without lifecycle
and cancelledAt columns (the state that caused the original bug), then
verifies that re-opening the database adds the columns and creating a run
succeeds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This merge adds three major features: a new **eval domain store** (`eval-store.ts`, `eval-types.ts`) for AI evaluation data with persistence schema and a `PluginDashboardViewHost` for extensibility; a **plugin dashboard view registry** with navigation integration that lets plugins register custom vi
Fusion-Task-Id: FN-3512
This merge adds three major features: an eval domain (`eval-store.ts`, `eval-types.ts`) with persistence schema for evaluation data; a plugin dashboard view registry with navigation integration for third-party dashboard extensions; and GitHub source metadata traceability that locks and enforces issu
Fusion-Task-Id: FN-3513
Merged FN-3157 to add a plugin dashboard views system, including a plugin view registry with lazy loading, navigation integration for Header and MobileNavBar, a usePluginDashboardViews hook with cache and refetch support, and tests covering the no-loader path. Also added documentation in `docs/PLUGI
Fusion-Task-Id: FN-3157
Introduced a new evaluation persistence layer in `@fusion/core` with domain contracts, SQLite-backed storage APIs, and retention/window-rollup support, wired through the core store and documented in the architecture and storage docs.
Fusion-Task-Id: FN-3387
The @keyframes spin and .animate-spin rules were incorrectly placed
inside the first :root {} block, which is invalid CSS — @keyframes
cannot be nested inside selector blocks. Browsers silently ignore
them in that position, so the spinners would still get stuck on pages
without component CSS loaded.
Moves the rules to the stylesheet top level between the two :root
blocks. Also fixes the mobile-css regression test that parses the
first :root block with a non-greedy regex.
Addresses review feedback from Greptile (P1) and CodeRabbit on PR #40.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The `.animate-spin` CSS utility class and `@keyframes spin` were only
defined in TaskCard.css but used by 25+ components (~60 instances).
On pages without a TaskCard rendered, the class didn't exist in the
stylesheet, causing all spinners to appear frozen.
Moves both the keyframes and utility class to the global styles.css
so they're available from the first paint regardless of which
components are loaded.
ClosesRunfusion/Fusion#39
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merges three major changesets: ephemeral agent cleanup for FN-3481 (runtime and spawned agent teardown), a fix for planning-mode refine continuation flow (FN-3209) plus a new local startup script, and chat SSE broadcast isolation with QuickChat backend unification. Key components affected include th
Fusion-Task-Id: FN-3481
Merges fixes for the planning refine continuation flow (FN-3209) alongside a new local startup script for development environments. The changes include updates to `PlanningModeModal.tsx`, new and updated tests for the planning system, route handler improvements in `chat.ts` and `planning.ts`, and do
Fusion-Task-Id: FN-3209
Databases already at schema v59+ when the lifecycle column was added never
re-ran the v59 migration, causing "no column named lifecycle" errors on
insight generation. Adds an unconditional compatibility check following the
existing ensureRoutinesSchemaCompatibility pattern.
Fixes#42
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend
- chat.ts now routes both regular chat and QuickChat through
createResolvedAgentSession instead of branching to createFnAgent for
the no-runtime-hint case. This removes the divergent path where
pi-ai's cleanupSessionResources(sessionId) could tear down resources
the next generation depends on.
- sendMessage's finally only disposes the agent if it still owns the
activeGenerations slot. A newer generation that has pre-empted us
cleans up its own agent in its own finally — disposing here would
yank the underlying CLI process out from under it.
- __setCreateFnAgent test helper now mirrors its mock into the
createResolvedAgentSession slot so existing test setups still work
after the unification.
Frontend
- Extract createChatStreamHandlers (RAF coalescing, accumulators,
tool-call dedup, fallback handling) — useChat and useQuickChat were
duplicating ~85 LOC each. Both now compose the shared factory.
- Move shared chat types into chatTypes.ts. The hooks re-export them
for backward compatibility with existing consumers.
- Removed per-message Markdown/plain-text eye toggles. A single
thread-level toggle in the chat header now flips every assistant
bubble (including the streaming one) between rendered Markdown and
plain text.
- Model-only chats hide the per-message agent identity row entirely;
the model name is already in the thread header.
Tests
- Updated ChatView tests to reflect the new render-toggle contract
(single header toggle drives all bubbles) and the model-only avatar
suppression.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
req.on("close") was firing for healthy SSE connections in this
Node/Express setup, which cancelled the in-flight agent the client was
still listening to and made even msg #1 fail after a fresh reload.
Keep the beginGeneration (no dispose) change from the same commit —
that one's correct.
Closing the QuickChat browser tab mid-response left the backend agent
running with no listener. The `activeGenerations` slot persisted and the
next message's freshly-opened CLI SessionManager raced against the
lingering agent on the same session file, so the model produced no
output for the new prompt.
- POST /chat/sessions/:id/messages now calls cancelGeneration on
req.on("close") if the response hasn't ended yet, so disconnects stop
the agent promptly.
- beginGeneration only aborts the prior controller; it no longer
disposes the prior agent. Disposing pre-emptively could yank the CLI
process out from under the new generation's session opened on the
same file.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two related bugs left the Planning Mode modal stuck at partial height on
mobile. useModalResizePersist replayed desktop-saved pixel dimensions
that overrode the mobile 100dvh rule, and React reconciled removed CSS
custom properties to empty string rather than calling removeProperty(),
which on iOS Safari defeated the var() fallback after keyboard dismiss.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After stopping a streaming chat reply, the next message would appear
sent but show no Stop button or "Connecting…" indicator. The cancel
broadcast from the prior generation was leaking into the new SSE
subscription and immediately marking it as errored.
Each `chatManager.sendMessage` now allocates a per-generation id;
`ChatStreamManager` only delivers tagged broadcasts to subscribers
from the matching generation. `sendMessage`'s cleanup also stops
deleting a newer generation's `activeGenerations` slot when an older
one finally unwinds.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Auto-archive previously wiped .fusion/tasks/{id}/ for stale done tasks
even while downstream agents (triage/todo/in-progress/in-review) still
needed to read those sibling specs from disk. Now the sweep skips any
done task that has an active dependent. The executor prompt also
instructs the agent to fall back to fn_task_show when sibling spec
files are missing on disk (e.g., manually archived deps).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merges the documentation update for FN-3287, adding 2 lines to the dashboard README covering PR link visibility behavior. This completes Step 5 of the task.
Fusion-Task-Id: FN-3287
The merge adds expanded regression assertions for the org chart feature, covering agent CSS classes and mobile agents view components. The tests verify styling and layout behavior across both desktop and mobile contexts.
Fusion-Task-Id: FN-3472
This merge adds done-payload snapshot handling across the chat system (FN-3430), normalizing how final assistant messages are preserved and consumed in the dashboard hooks, plus it normalizes dashboard mailbox and user identity for inter-agent messaging (FN-3484) and introduces plugin workflow step
Fusion-Task-Id: FN-3430
This merge normalizes dashboard user identity and mailbox messaging (FN-3484, 4 steps), adds workflow step execution for plugins (FN-3490), and updates the restart integration store mock for plugin templates (FN-3096). Core changes touch the message store and store modules with identity normalizatio
Fusion-Task-Id: FN-3484
This merge adds WorkflowStepManager UI enhancements, extends the plugin-runner with new execution capabilities, expands executor tests with improved restart and mock handling, and adds agent routes for the dashboard. The changes span core plugin loading, dashboard components, and engine execution lo
Fusion-Task-Id: FN-3490
Updates the restart integration test mock to account for plugin template behavior, keeping the test in sync with recent plugin template changes.
Fusion-Task-Id: FN-3096
This merge introduces a new mesh replication protocol module in `@fusion/core` (with protocol documentation and tests) and updates multiple documentation files, while also normalizing button utility classes in the AgentsView component.
Fusion-Task-Id: FN-3500
The merge normalizes button utility classes in AgentsView, swapping 12 lines of CSS class references for their standardized counterparts for consistency and maintainability.
Fusion-Task-Id: FN-3448
Merged the FN-3497 task planning mode CLI reference documentation into the published CLI guide, updating `docs/cli-reference.md` with 10 lines of new content.
Fusion-Task-Id: FN-3497