Demote the refresh message from console.error to debugMcp so it no
longer appears as an error in normal output.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PluginStore expects a project-root path and appends `.fusion` itself, but the in-process runtime was handing it the already-resolved `.fusion` directory — producing a spurious `.fusion/.fusion/fusion.db` on every engine startup.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This merge lands seven features and fixes across the dashboard and engine. Notable changes: restructured TodoView rows with improved action row styling, added `/clear` command to Chat and QuickChat, persisted session banner dismissals with a hide-banner setting, made peer exchange shutdown determini
Fusion-Task-Id: FN-3040
RoutineStore's constructor appends ".fusion" to its rootDir argument,
but InProcessRuntime was passing taskStore.getFusionDir() (already the
.fusion path), producing <projectRoot>/.fusion/.fusion/fusion.db. Pass
the project root instead, matching AutomationStore's construction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each agent now gets its own .fusion/agents/<id>/HEARTBEAT.md procedure
file instead of sharing a single project-wide file. A one-shot
migration in AgentStore.init() re-points existing agents off the legacy
shared path and copies the legacy file's contents into each agent's
new per-agent location so operator edits are preserved.
The HeartbeatTriggerScheduler now phase-aligns the first tick to
lastHeartbeatAt + intervalMs so a process restart resumes each agent's
existing schedule rather than waiting up to a full interval before
firing again. Overdue ticks fire promptly within a small jitter window
to avoid a thundering herd at boot.
Also fixes three pre-existing QuickChatFAB test failures introduced by
739e899b5: auto-select default model now switches to model mode whether
or not agents are present, the model tag only renders in model mode,
and one test scopes its option lookup to role="option" to disambiguate
the in-header tag from the dropdown entry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stale-merge recovery now calls back into ProjectEngine's auto-merge queue
directly instead of waiting on the 15s polling sweep — wired via a new
InProcessRuntime.setMergeEnqueuer hook so SelfHealingManager can re-enqueue
without leaking engine internals.
createWorktree mirrors the merge-time rebase: when worktreeRebaseBeforeMerge
is enabled, the new task branch is rebased onto <remote>/<defaultBranch>
right after creation, so executors start from origin's tip with local main
replayed on top. Best-effort — fetch/rebase failures abort cleanly and
leave the merge-time rebase as the backstop.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add isGitRepository utility in worktree-pool using git rev-parse checks
- Fail fast in TaskExecutor with actionable non-git errors before worktree creation starts
- Classify not-a-git-repository worktree add failures as non-retryable in recovery flows
- Warn from in-process runtime startup when the working directory is not a Git repository
- Expand executor and worktree-pool tests to cover non-git, missing-dir, and conflict-classification paths
TUI quit ('q'/Ctrl+C) bypassed signal handlers via process.exit(0), and
neither shutdown path closed the HTTP server, so server.close()'s
stopAllDevServers() listener never ran. In-flight agent bash commands
(spawned detached for their own pgroup) were also never aborted, so
their subprocess trees — including vitest workers — survived as orphans.
Route the TUI quit through SIGINT so the registered shutdown handler
runs, await stopAllDevServers() in both shutdown paths, and abort
in-flight bash on every active agent session at the start of the
runtime drain so killProcessTree reaches every grandchild.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mostly mechanical cleanup left over from the earlier test-consolidation pass:
- Update import paths to ../../ for mocks now that test files moved deeper
- Simplify mock setup (drop usePluginUiSlots inline mock, etc.)
- Move engine ipc + runtimes tests into __tests__/ subdirs
- Move dashboard utils tests into __tests__/ subdir
- Refresh fusion-plugin-hermes-runtime/dist artifacts
build-exe.test.ts: spawn-import fix from a parallel branch (resolved during
worktree merge of the CSS extraction work).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Move all co-located *.test.* files into sibling __tests__/ directories so the
layout is consistent across packages (159 renames + content-rewrite moves).
Updates relative imports, vi.mock specifiers, and __dirname/import.meta.url
path resolutions where tests read fixtures from disk.
- Drop tracked tsc-emit alongside engine .ts sources (auth-storage/logger/
skill-resolver/context-limit-detector/pi.{js,d.ts,*.map}). These were
accidentally committed in a merge and the stale pi.js was masking a real
test-mock vs source mismatch (tests imported "../pi.js" and vite preferred
the stale build over pi.ts).
- Add packages/engine/.gitignore to block future src/*.{js,d.ts,map}.
- Refactor plugin pi-module seams (openclaw/paperclip/hermes) to ESM-import
createFnAgent / promptWithFallback / describeModel from @fusion/engine
instead of require()-ing packages/engine/src/pi.js. Adds @fusion/engine to
the two plugin package.jsons that were missing it; exports describeModel
from the engine public API.
- Fix engine test mocks now that they run against current pi.ts: add
ModelRegistry.create static to mocks in pi.test.ts and pi-create-fn-agent
.test.ts; switch three boundary-result toEqual assertions to toMatchObject
so the new content/isError fields don't trip exact-match comparison.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
findLandedTaskCommit only fell back to scanning all of HEAD on git-log
exceptions. When the bounded base..HEAD range is valid but empty — e.g.
the merger fast-forward-rebased the task branch and set baseCommitSha
to the new HEAD, or later commits moved HEAD past the merge — recovery
silently returned null and re-queued the merge even though the commit
had already landed. Add an empty-stdout fallback that re-scans HEAD,
with a regression test covering the FN-2221 scenario.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three orthogonal fixes bundled together so they re-land as a unit after
earlier worktree-based reverts kept wiping them individually.
1. `--no-auth` flag now actually disables auth. Previously a stale
FUSION_DAEMON_TOKEN in .env silently re-armed bearer-token auth despite
the CLI flag. Added a `noAuth` option to ServerOptions; auth-middleware's
isDaemonAuthActive/getDaemonToken short-circuit to false/undefined when
set; CLI plumbs opts.noAuth through both createServer call sites.
2. Workflow review failures no longer reset every completed step. Previously
a single CSS nit from a workflow reviewer could drag 5+ already-approved
steps back through plan review, code review, and re-execution because
determineRevisionResetStart fuzzy-matched feedback tokens against step
names. handleWorkflowRevisionRequest, handleWorkflowStepFailure, and
sendTaskBackForFix now call a new reopenLastStepForRevision helper that
flips only the last non-pending step back to pending (with currentStep
rewind via a newly-accepted updateTask field) — all earlier done steps
stay done, and the agent applies the feedback as an in-place patch per
the updated PROMPT.md instructions. determineRevisionResetStart stays
exported as @deprecated so existing unit tests still link.
3. Heartbeat scheduling is now state-driven. Previously a non-ephemeral
agent with a stale runtimeConfig.enabled=false on disk would never tick
and the Pause/Resume button couldn't arm the timer without also flipping
that hidden flag. HeartbeatTriggerScheduler's watchAgentLifecycle now
registers on transitions into active/running and clears on transitions
out; the tick and assignment-trigger guards key off state + ephemeral
classification. InProcessRuntime's created/updated listeners and startup
scan mirror the same semantics. runtimeConfig.enabled is only retained
for ephemeral (task-worker) opt-out.
Tests updated: agent-heartbeat.test.ts — one test renamed from "skips
registration when enabled is false" (obsolete behavior) to
"registers regardless of the legacy enabled flag"; 4 assignment-watching
tests now pass a realistic `state: "active"` on mock agents. 207 heartbeat
tests + 330 executor tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add termination-driven cleanup in InProcessRuntime so ephemeral agents are disposed when the runtime terminates
- Extend in-process runtime tests with comprehensive coverage for ephemeral cleanup behavior and lifecycle expectations
- Fix ephemeral termination cleanup assertions to align test checks with actual teardown semantics
- Update CLI tests to skip obsolete changeset validation and reduce flakiness in binary timeout handling
Atomic worktree creation: on `git worktree add` failure, remove the
partial directory so retries see a clean slate (executor.ts,
step-session-executor.ts). Add `reapOrphanWorktrees()` sweep on engine
startup to delete `.worktrees/*` dirs that have no `.git` file and are
not registered with git. Force readonly workflow steps to run pre-merge
so review personas reuse the coding worktree instead of allocating a
fresh post-merge one. Inject a Frontend UX Criteria checklist into
TRIAGE_SYSTEM_PROMPT when a task touches dashboard UI, so the first
coding pass can meet UX reviewer expectations.
Motivated by FN-2185 post-mortem: an incomplete `.worktrees/pale-raven`
dir blocked retries, and three Step 6 revision cycles over cosmetic UX
issues consumed ~13 hours.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add structured warning logs in silent catch paths for IPC worker shutdown, plugin unregistration cleanup, child runtime metrics polling, and merger build rollback reset
- Improve merger rollback warning context to make build-verification reset and retry failures easier to diagnose
- Add regression tests covering each new warning path to ensure errors are surfaced without changing existing control flow
- Add StepSessionExecutor test coverage for cherry-pick abort logging when conflict cleanup fails
- Convert seed-sample-nodes into a test-only helper and remove direct execution against the real central database
- Replace private-looking host examples with RFC 5737 test-net addresses in node connection docs and ConnectNodeModal expectations
- Add Vitest aliases for @fusion/core and @fusion/engine to stabilize cross-package test imports
- Load AgentReflectionService via local engine source path in in-process runtime to avoid alias resolution failures
Adds a SelfHealingManager scan that finds tasks parked in in-review with
a failed pre-merge workflow step and no active session, and sends them
back through the existing sendTaskBackForFix flow (PROMPT.md injection,
step reset, todo → in-progress). Bounded by a new maxPostReviewFixes
setting (default 1) and a per-task postReviewFixCount so a persistently-
failing verifier cannot ping-pong a task indefinitely.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add a reusable .btn-secondary style (including light-theme hover/focus states) for reflections tab actions
- Initialize ReflectionStore in reflection API routes before reading or writing reflections
- Create AgentStore and ReflectionStore during in-process runtime startup and wire AgentReflectionService into TaskExecutor
- Reuse the initialized AgentStore for HeartbeatMonitor and trigger scheduler setup with non-fatal guards
- Apply a default 30s heartbeat interval when scheduler config is missing or invalid
- Dynamically register and update heartbeat triggers from AgentStore create/update events
- Register all non-disabled agents at startup and guard listener cleanup when stopping runtime
- Treat non-periodic agents as healthy in dashboard health checks to avoid stale-time false alarms
- Expand engine and dashboard tests and add a patch changeset for @gsxdsm/fusion
- Wire MessageStore into the in-process executor runtime and project engine
- Forward MessageStore events through dashboard SSE infrastructure for mailbox updates
- Close mailbox pipeline gaps across API routes, server wiring, and mailbox UI components
- Add regression coverage for messaging routes, SSE forwarding, and agent tool behavior
- Document the MessageStore SSE wiring pattern in .fusion/memory.md
- Expose getAgentStore from runtime and engine packages
- Add includeSystem filter to getOrgTree API endpoint
- Wire AgentStore into SSE endpoint for event forwarding
- Forward agent events through the SSE pipeline
- Exclude ephemeral agents from org tree API and UI
- Filter ephemeral agents in useAgents hook
- Update AgentsView test to expect includeSystem filter
- Document agent SSE event forwarding architecture
- Auto-delete spawned child agents when their parent task terminates (reportsTo cleanup)
- Auto-delete task-worker agents when their owned task completes
- Add includeSystem filter to AgentStore.list() and REST API
- Hide system agents by default on the agents page (show only user-facing agents)
- Wire includeSystem toggle through the API layer and AgentsView component
- Add changeset for @gsxdsm/fusion patch release
- Add comprehensive tests for agent cleanup and includeSystem filtering
- Add scope field to automations and routines for granular control
- Update automation-store and routine-store with scope-aware query methods
- Extend database schema with scope column for automations and routines
- Update cron-runner and routine-scheduler to respect scope boundaries
- Add project context injection to in-process runtime for scoped execution
- Include changeset for minor version bump
- Add MailboxView as a full-page navigation view replacing the modal-based approach
- Migrate MessageStore from filesystem to SQLite backend for message persistence
- Implement conversation grouping for inbox display with unread badge state
- Remove modal plumbing (useModalManager, AppModals exports) and simplify App.tsx
- Add evictStaleProcessing() to TriageProcessor for self-healing hung triage sessions
- Add comprehensive MailboxView tests and Header mailbox tests
- Update README documentation with MailboxView features
- Add CSS styles for MailboxView component
- Fix MobileNavBar tests for mailbox tab visibility
- Replace filesystem-based message storage with SQLite backend
- Add MessageStore class using better-sqlite3 with WAL mode
- Update message.ts CLI command to use new MessageStore API
- Update dashboard routes and engine runtime for SQLite integration
- Update all related tests for new storage implementation
- Add SignalListener type definition to child-process-worker.test.ts
- Update mockImplementation callbacks to use unknown type instead of any
- Add proper TypeScript types to createAgentWithTaskDone opts parameter
- Use optional chaining for safer customTools access
- Use () => void | undefined type for resolvePrompt variables
- restart.integration.test.ts: add eslint-disable for Function/any types in mocks
- child-process-worker.test.ts: add eslint-disable for Function[] in baseline arrays
- Restore build to passing by avoiding overly strict type changes
- All tests pass
- child-process-worker.test.ts: replace Function[] with SignalListener type
- remote-node-runtime.test.ts: add yield statement to idleStream generator
- All 57 test files pass with 0 errors
- Remove unused imports across 25 files in engine package
- Remove unused variable declarations in ipc-worker.ts, child-process-runtime.ts, and mission-autopilot.ts
- Clean up unnecessary imports in agent-instructions.ts, agent-tools.ts, cron-runner.ts, executor.ts, and other modules
- Minor cleanup in notifier.ts, peer-exchange-service.ts, pi.ts, plugin-runner.ts, and other files
- Improves code quality and reduces potential confusion from unused code
- Pass recoverApprovedTriageTask and getSpecifyingTaskIds callbacks from
TriageProcessor to SelfHealingManager in InProcessRuntime. Without these,
approved triage tasks stuck in 'specifying' status were never recovered.
- Remove duplicate imports in ModelOnboardingModal.tsx that caused TypeScript
errors (duplicate identifiers: useEffect, useRef, ToastType, fetchAuthStatus).
- Add mock for model-onboarding-state in App.test.tsx.
- Add PUT /api/global-concurrency endpoint to update globalMaxConcurrent
via CentralCore (validated 1-50 range)
- Make InProcessRuntime semaphore react to live concurrency changes via
CentralCore "concurrency:changed" event — no restart needed
- Add Global Max Concurrent input to Settings modal Scheduling section
with fetch-on-mount and save-alongside-project-settings behavior
- Add updateGlobalConcurrency API client function
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>