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>
Two related leaks in the agent lifecycle plus a refactor:
- Governance-skip paths in executeHeartbeat (budget/global-pause/engine-paused)
were leaving agents permanently stuck in `running` because they ran startRun
first and then short-circuited with skipStateTransition: true. Removed the
flag from those four paths so they flow through running → active. Added
HeartbeatMonitor.reconcileOrphanedRunningAgents() on start to recover any
rows already trapped in this state.
- Ephemeral task-workers piled up across runtime restarts because taskAgentMap
was in-memory only and the startup sweep ignored ephemerals with no taskId.
Now: spawn dedup via findAgentByName before create, on-disk fallback in
finalize when the in-memory map is empty, and the sweep deletes any
ephemeral not bound to an in-progress task.
- Extracted the lifecycle into EphemeralWorkerManager
(packages/engine/src/ephemeral-worker-manager.ts). InProcessRuntime drops
~140 lines and delegates via onTaskStart/onTaskComplete/onTaskError/
attachStateChangeListener/reconcileOrphaned. ChildProcessRuntime and
RemoteNodeRuntime inherit the fix because they delegate execution to a
worker that runs InProcessRuntime.
Durable assigned agents now return to `active` after task completion (was
`terminated` in the old contract).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Clarify task memory scope behavior across core types, project memory logic, engine tool prompts, and related docs
- Add regression coverage for memory scope and runtime plugin alias handling in core/dashboard/engine tests
- Add agent avatar API routes and dashboard UI support for avatar display and storage documentation
- Add line-number gutter toggle support in FileEditor and Files modal with accompanying component tests
- Include changeset for @runfusion/fusion documenting memory scope guidance update
Fusion-Task-Id: FN-3485
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
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
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
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>
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
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 delivers agent self-improvement (FN-3321) — adding evaluation identity tools, wiring evaluation into the heartbeat loop, implementing a self-improvement service, and providing test coverage. It also expands the dashboard guide view with regression tests, adds org chart full-view mode with
Fusion-Task-Id: FN-3321
This merge normalizes agent-memory paths in the core memory backend and ensures the qmd gets refreshed after agent dream writes, fixing a bug where stale paths could persist after memory updates. The engine's agent-tools module was updated to integrate with this fix, and a changeset was included for
Fusion-Task-Id: FN-3197
The merge introduces the auto-claim setting feature, enabling agents to automatically claim tasks on assignment, with corresponding UI in AgentDetailView and documentation. It also adds the agent heartbeat execution system to the engine, refinements to workflow results styling and design tokens, aut
Fusion-Task-Id: FN-3479
Added auto-claim setting UI to the Agent detail view with corresponding documentation in agents.md and test coverage for the new component behavior. The changeset marks this as a minor feature for the published `@runfusion/fusion` package.
Fusion-Task-Id: FN-3250
pi-ai's openai-codex-responses provider surfaces ChatGPT-plan WebSocket
drops as bare "WebSocket error" / "WebSocket closed <code>". The
underlying ErrorEvent.error is dropped by extractWebSocketError (it only
inspects event.message), so the cause is gone by the time we see it.
The engine then propagated these as fatal failures instead of retrying
a transient network blip.
- Add WebSocket patterns to TRANSIENT_ERROR_PATTERNS so the executor's
existing transient retry path picks them up.
- Tag the model id onto the thrown error and emit a structured warn in
promptSessionAndCheck so future drops can be triaged by transport.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This merge lands four major features: the desktop app gains shell onboarding with remote mode support via a new `DesktopModeChooser` and `shell-settings` module (FN-3399); the dashboard gains full archived insights support with the `InsightsView` redesign and `useInsights` hook overhaul (FN-3315); C
Fusion-Task-Id: FN-3434
This merge enables heartbeat agents to use coding sessions with tool access (FN-3459). It adds heartbeat session prompt tests, updates the heartbeat executor to support tool mode, modifies dashboard node components and hooks, and includes a fix for a typecheck regression. A changeset is included for
Fusion-Task-Id: FN-3459
This merge lands five features spanning the Fusion stack: research settings key renaming (FN-3313, Steps 2–7) across types, defaults, CLI, and engine packages; static plugin slot-host rendering contract documentation (FN-3260); Docker node provisioning routes with a planning modal (FN-3116); plannin
Fusion-Task-Id: FN-3313
- store.ts close(): clear retry timer and buffer before nulling _db to
prevent re-opening a new connection after close (Greptile P1)
- merger-staging-allowlist.test.ts: use `git init -b main` so the
default branch is always named 'main' regardless of git config
- SettingsModal.test.tsx: fix expected text for compact DroidCli card
— shows "✓ Active" badge, not "✓ Connected — 1.2.3"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds comprehensive tests for cleanup reliability in the in-process runtime (131-line test suite) plus related coverage in the executor tests, with a small fix to the runtime implementation itself to address the reliability issue.
Fusion-Task-Id: FN-3352
The merger issues several `git reset --hard` / `git reset --merge` and
forced-checkout calls against `rootDir` during merge attempts. When
`rootDir` is the developer's primary checkout (common for solo / single-host
setups), those resets silently discard any unrelated unstaged or untracked
changes — we burned dev work this way during FN-3329 (dashboard-tui edits
wiped mid-flight by an unrelated merge run).
Snapshot dirty paths at entry to `aiMergeTask`, stash them under a
recognizable label including the taskId (`-u` to capture untracked), and
pop them in a finally block on every exit path. On pop conflict we leave
the stash intact and log a recovery hint rather than dropping it. Best-
effort: a stash failure logs and proceeds with the old behavior so the
merge itself is never blocked.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The merge lands FN-3323's self-healing system: a new "reports health" prompt section and `agent-heartbeat.ts` module that detect orphaned agents and recover their state (clearing stale error states and re-enabling heartbeat execution). The engine's `self-healing.ts` was expanded with wired recovery
Fusion-Task-Id: FN-3323
Adds a regression test sentinel in the engine's in-process runtime test suite to guard against runtime guard behavior regressions (FN-3324).
Fusion-Task-Id: FN-3324
The merge completes FN-3320 by implementing configuration tools for the agent system (`agent-tools.ts`), wiring them through the executor, and adding test coverage (`agent-tools-config.test.ts`). Documentation was updated in `AGENTS.md` and the engine tools reference, with minor updates to the agent
Fusion-Task-Id: FN-3320
Added 95 lines of test coverage for merge scheduler recovery paths in the merge error recovery test suite, completing Step 4 of FN-3317.
Fusion-Task-Id: FN-3317
Fixes CSS token consistency issues in TaskDetailModal and SettingsModal, and updates the corresponding mobile overflow test to match the refactored styles.
Fusion-Task-Id: FN-3308
Replaces blanket `git add -A` in `commitOrAmendMergeWithFixes` with an
explicit allowlist of (squash-staged ∪ fix-agent-modified) paths, so
unrelated dirty files in the project root no longer get swept into a
task's squash commit. The in-merge fix agent now snapshots the working
tree before/after its session to capture exactly which files it touched.
Hardens the git invocations the allowlist relies on:
- All `git add` and `git checkout --ours/--theirs` calls switched from
shell-interpolated `execAsync` to `execFile` array form, eliminating
path-injection surface and batching per-file spawns into one call.
- `snapshotDirtyFiles` adopts `git -z` NUL-delimited parsing so paths
with embedded spaces or specials are handled correctly.
- Long allowlist debug logs are truncated to 20 entries with an overflow
marker.
Refused-to-stage paths emit a warn naming each file so the user can
audit what was filtered.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Documents the research boundary contract in the architecture docs and research hardening preflight guide, updating architecture documentation and adding a new boundary definition file.
Fusion-Task-Id: FN-3292
This merge adds done-column sorting by most recent completion while preserving merge-active state on verification bounces, introduces a comprehensive droid runtime regression test suite covering engine delegation, auth routes, and model routing, hardens the CLI native bundle externalization, and fix
Fusion-Task-Id: FN-3074
This merge lands FN-3231 across two steps: it preserves a merge-active fix when verification bounces occur (step 1) and ensures the fix is retained during board routing transitions (step 2). Changes span the dashboard Board routing logic and the engine executor, with corresponding test coverage adde
Fusion-Task-Id: FN-3231
Moonshot/Kimi returns a non-standard finish_reason of "repeat" when its
server-side repetition detector trips. pi-ai surfaces this as a fatal
session state error, killing the agent heartbeat. Filter that case in
promptSessionAndCheck so the truncated turn is logged and the heartbeat
continues on the next tick.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cleans up lint and type errors in the engine by removing unused imports from executor and merger, and replacing `any` types with proper type annotations in verification-utils.
Fusion-Task-Id: FN-3345
Heartbeat read non-existent split modelProvider/modelId fields while the
dashboard saves runtimeConfig.model as combined "provider/modelId", so
sessions fell through to pi's default model and failed with
"No API key for provider: openai-codex". Add extractRuntimeModel helper
that prefers the combined string and use it from heartbeat.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A task whose previous run exhausted its merge budget (mergeRetries=MAX)
could land back in in-review with status=null, where the merger refused
it (canMergeTask false) and the ghost-review fallback bounced it back to
todo every taskStuckTimeoutMs (10 min) — beating the 30 min merge
cooldown reset. Each fresh execution now starts with mergeRetries=0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The merge adds an auto-reload setting (FN-3334) with UI controls in the settings modal, documentation, and a new version-check module, while also fixing a bug (FN-3338) where extension providers incorrectly resolved the project root when invoked from git worktrees — moving the project-root resolutio
Fusion-Task-Id: FN-3338
Merges FN-3335 (worktree project resolution) and FN-3333 (spurious version reloads). The engine's `createFnAgent` now resolves project root from the worktree's cwd rather than the parent process, with `resolveProjectRoot` added to skill-resolver for consistency. The dashboard's `versionCheck` was up
Fusion-Task-Id: FN-3335
The verification-fix agent prompt previously forbade modifying files
unrelated to the failure, which blocked the natural fix when
deterministic merge verification failed because of stale/missing
plugin `dist/` outputs in sibling workspace packages (e.g.
`Failed to resolve import "./cli-spawn.js"` from
`fusion-plugin-hermes-runtime/dist`).
- Add explicit guidance to detect stale-artifact failure signatures
and rebuild the affected package(s) before editing source.
- Allow the agent to fix pre-existing breakage on the base branch,
preferring the smallest change that makes verification green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>