Commit Graph

179 Commits

Author SHA1 Message Date
Fusion
8e861a42a4 feat(FN-3117): add plugin dashboard views, chat session icons, and SQLite t
This release (v0.15.0) brings significant plugin system enhancements including a new dependency graph plugin with dashboard view, plugin skills in session selection, and extended plugin UI slot metadata. Database improvements add SQLite WAL tuning, integrity checks, and batch writes for agent logs.

Fusion-Task-Id: FN-3117
2026-05-02 00:04:29 -07:00
Fusion
ed477f8c71 feat(FN-3173): add SQLite WAL tuning, integrity checks, and agent log batch
This merge brings FN-3173's SQLite stability improvements: WAL tuning pragmas for better concurrency, periodic integrity checks with self-healing recovery, and batched agent log writes to reduce I/O overhead. It also includes a new cron-runner for scheduled maintenance tasks, TUI mouse wheel scrolli

Fusion-Task-Id: FN-3173
2026-05-01 23:26:14 -07:00
gsxdsm
dd291db725 fix(FN-XXXX): tokenize backup-command matcher
Two follow-ups to the in-process backup interception:

- Previously the matcher only allowed a bare `npx` prefix, so the
  canonical zero-install form `npx -y runfusion.ai backup --create`
  (and any `npx --yes` / `-p <pkg>` / `--package=<pkg>` variant) fell
  through to the legacy shell-out path. The matcher now consumes any
  number of npx flags before the binary token so all canonical
  invocations route through the in-process executor.
- Previously the matcher accepted arbitrary text after `--create` and
  the runner silently dropped it. Authors writing
  `fn backup --create && notify-send done` or
  `fn backup --create | tee log` reasonably expected the trailing
  side effect to fire. The matcher now refuses any command containing
  shell continuations / redirections / substitutions
  (`&&`, `||`, `|`, `;`, `>`, `<`, backticks, `$()`), and rejects
  trailing positional arguments. Such commands shell out as the user
  wrote them.

The matcher is now a small tokenizer rather than a regex collection,
so the contract is easier to read and the unit-test grid covers each
permitted prefix combination plus all the previously-unhandled shell
forms.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 22:58:18 -07:00
gsxdsm
31195374d4 fix(FN-XXXX): quiet pi-claude-cli MCP config refresh log
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>
2026-05-01 22:58:00 -07:00
gsxdsm
5a41ce42e9 fix(FN-XXXX): narrow backup matcher and isolate version probes
Two follow-up corrections to the in-process auto-backup interception:

- The matcher previously hijacked any `fn backup …` / `fusion backup …` /
  `runfusion.ai backup …` form. The in-process replacement only knows how
  to do `--create` + cleanup, so scheduling `--list`, `--cleanup`, or
  `--restore <file>` would have silently executed a create instead of the
  requested operation. The matcher is now anchored to `backup --create`
  (with optional trailing flags), with positive/negative unit tests.
- Step-based automations (`AutomationStep` with `type: "command"`) also
  shell out — the legacy-command interception alone left that path
  vulnerable. `executeCommandStep` now applies the same in-process backup
  detour, factored through a shared `runBackupActionInProcess` helper.

Independently, `runProbe` in fn-binary now spawns with `cwd: tmpdir()`.
The dashboard's `/system/fn-binary/status` route runs `<bin> --version`
on whatever fusion binary happens to be on PATH — older releases (e.g.
v0.13.0) initialise an engine and create a fresh `.fusion/<project>/
.fusion/` tree as a side effect. Pinning the probe's cwd to the OS temp
directory keeps any such artefacts off the developer's project.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 22:49:03 -07:00
Fusion
b3e2b614c8 feat(FN-3059): align provider metadata and documentation
Merged feat(FN-3059) which aligns provider metadata and documentation across the codebase, updating README and getting-started docs plus refinements to the CustomProviderForm and ProviderIcon dashboard components.

Fusion-Task-Id: FN-3059
2026-05-01 17:39:47 -07:00
Fusion
2e5c4f1ff3 feat(FN-3094): add cached plugin contribution accessors
- Add PluginRunner contribution cache plumbing to store and reuse plugin-provided contributions
- Expose new PluginLoader accessors for reading cached contributions during runtime workflows
- Add core plugin-loader tests covering contribution accessor behavior and edge cases
- Add engine plugin-runner tests validating contribution cache population and retrieval

Fusion-Task-Id: FN-3094
2026-05-01 17:26:01 -07:00
Fusion
cafe986f1b feat(FN-3140): add readonly custom tools and plugin SDK
This merge adds readonly custom tool preservation (FN-3140) with new plugin SDK types and documentation, fixes PluginManager responsive overflow (FN-3093), and integrates the fn-3065 branch with enhanced plugin authoring capabilities. The core plugin-types module was significantly expanded with 230+

Fusion-Task-Id: FN-3140
2026-05-01 16:54:42 -07:00
gsxdsm
c08a872169 feat(fusion): make auto-merge queue priority-aware
Triage and the todo→in-progress scheduler already sorted by priority
(urgent→low, then createdAt ASC, then id ASC); the auto-merge queue
was strictly FIFO, so a backlogged low-priority task could merge
ahead of an urgent one. drainMergeQueue now picks the highest-
priority eligible task each iteration, and the four in-review sweeps
(startup, periodic, global unpause, engine unpause) sort by priority
before enqueueing so the single-item fast path also picks priority-
first. Picker is hardened against concurrent queue mutation by stop()
and pause-handler removal: it re-locates the chosen entry by id and
re-checks shuttingDown after awaiting getTask.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 15:45:00 -07:00
Fusion
80b45d0bd5 feat(FN-3033): align agent asset directory naming and heartbeat path compat
The merge delivers three major features: a droid CLI path reconciliation extension that resolves workspace path mismatches for spawned agents, session-first quick chat with improved heartbeat prompts and a dramatically simplified QuickChatFAB component, and canonical agent asset directory naming wit

Fusion-Task-Id: FN-3033
2026-05-01 12:54:17 -07:00
Fusion
a6ae7b4e04 feat(FN-3060): add agent task auto-summarization and droid CLI path reconci
This merge adds droid CLI path reconciliation as a new pi extension, wires agent task auto-summarization for the agent tools layer, makes the UsageIndicator component resizable with improved styling, and updates related tests and documentation. The core changes include a new `reconcile-droid-cli-pat

Fusion-Task-Id: FN-3060
2026-05-01 12:43:36 -07:00
Fusion
fd36fbdf9d feat(FN-3036): fix heartbeat prompt composition for autonomous agents
This merge fixes heartbeat prompt composition for autonomous agents (FN-3036) so child agents spawned via `spawn_agent` receive properly formatted system prompts with heartbeat instructions, adds regression tests and documentation for the behavior, and removes duplicate constructor assignments in He

Fusion-Task-Id: FN-3036
2026-05-01 12:06:48 -07:00
gsxdsm
6032b900a4 fix(engine,droid-cli): stop subagents with parent task and harden droid-cli probes
engine: reviewer subagents previously kept running after the parent task
was moved out of in-progress, paused, or globally paused — they spawn
their own AgentSession outside `activeSessions`/`activeStepExecutors`,
so the existing kill paths never reached them. Track them in a per-task
`activeSubagentSessions` map (mirrored in TriageProcessor) and dispose
on the same triggers as the main session. ReviewOptions gains
`onSessionCreated` / `onSessionEnded` callbacks the executor and triage
processor wire to register/unregister.

droid-cli: probe timeouts (`validateCliPresence`, `validateCliAuth`,
`runDroidProbe`) raised from 5s to 45s — observed cold-start is ~20s,
so 5s reported the binary as missing even when present. Provider gains
a `FIRST_LINE_TIMEOUT_MS` (60s) cold-start guard so a hung droid binary
is reported with an actionable error instead of being indistinguishable
from a slow-thinking turn. Fix the await race in `streamViaCli`: when
SIGKILL destroys stdout mid-buffer, `rl` may never emit "close", so the
promise also resolves on `proc.close` and forces `rl.close()` — prevents
the engine's "executor did not unwind within 60s — hung subprocess".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 06:44:07 -07:00
gsxdsm
d6d591b532 feat(heartbeat): inline Identity Snapshot for runtime-agnostic delivery
Plugin runtimes (openclaw, hermes, paperclip) wrap external CLIs and may not
propagate JS customTools to the underlying agent, so fn_identity could be
unreachable on those runtimes. Embedding the agent's identity (role, soul,
instructions, memory previews) directly in every execution prompt guarantees
the agent always sees what loaded for the tick — fn_identity remains as an
optional richer read for runtimes that do support custom tools.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 06:27:23 -07:00
Fusion
2a766fe8d6 feat(FN-2979): add droid CLI probe module for node diagnostics
Added a new `droid-cli-probe` module to the dashboard package with test coverage, implementing a CLI probe capability for the droid system.

Fusion-Task-Id: FN-2979
2026-05-01 04:03:02 -07:00
Fusion
1747d6fc43 feat(FN-3050): preserve failed review tasks during recovery to prevent loop
The merge strengthens task recovery logic to prevent in-review tasks from entering merge-recovery loops and preserves failed review tasks during retry sweeps instead of incorrectly resetting them. It adds targeted test coverage for these edge cases in the self-healing and project engine modules.

Fusion-Task-Id: FN-3050
2026-05-01 02:07:43 -07:00
Fusion
8e09af95ea feat(FN-3044): add canonical mock helpers and migrate representative test s
This merge introduces canonical mock helper modules across the dashboard and engine packages, and migrates representative test suites to use them for consistency. The changes add four new mock helpers (`mockApi.ts`, `mockLucide.ts`, `mockCore.ts`, `mockCoreEngine.ts`) and harden the API mock proxy's

Fusion-Task-Id: FN-3044
2026-05-01 00:33:17 -07:00
Fusion
864f5bbb8c feat(FN-2996): add research agent tools with extension wiring, remote setti
This merge brings multiple substantial features: new research extension tools wired through the AI engine (with full test coverage and documentation), legacy routines agentId backward compatibility with migration paths, migration of experimental remote settings to the global scope, Nerd Font glyph a

Fusion-Task-Id: FN-2996
2026-04-30 20:39:42 -07:00
Fusion
ff2bb23b80 feat(FN-3029): add research settings, AgentDetailView markdown viewer, and
This merge brings several enhancements across the dashboard and engine. Research settings are now fully integrated into the settings modal and exported for alias builds, including a new schema and dedicated resolver. The AgentDetailView receives a heartbeat markdown viewer modal and expanded styling

Fusion-Task-Id: FN-3029
2026-04-30 19:29:07 -07:00
Fusion
dac2597beb feat(FN-3037): add focus-visible styling to AgentLogViewer log action butto
Adds `focus-visible` styling to action buttons in the AgentLogViewer component, improving keyboard accessibility for interactive button elements.

Fusion-Task-Id: FN-3037
2026-04-30 19:18:56 -07:00
Fusion
d3c6859819 feat(FN-2839): add research settings section to settings modal and dashboar
This merge introduces a research settings system including new resolver functions in `@fusion/core`, a dedicated ResearchView in the dashboard with a full SettingsModal integration, and corresponding TypeScript types and schemas. Comprehensive unit tests cover routing resolution, research settings,

Fusion-Task-Id: FN-2839
2026-04-30 19:11:38 -07:00
gsxdsm
21402a3c1a fix(test-harness): restore promisify(exec) + unblock CLI introspection probes
The vitest child-process guard wrapped exec/execFile without preserving the
`[util.promisify.custom]` symbol, so awaited `execAsync` resolved to a raw
stdout string instead of `{stdout, stderr}`. That single regression cascaded
through ~60 "failing" tests across cli, core, engine, and dashboard whose
production code was actually correct. Also relax the AI-CLI blocklist for
cheap introspection (--version/--help/which …), give SIGTERM'd subprocesses a
brief grace period before being flagged as "left running", fix a few real
test-side bugs uncovered along the way (executor mock step transitions, iOS
last-resort keyboard path, mission SSE replay tests racing with the real AI
agent), and convert dashboard route tests' dynamic `await import("../server.js")`
to static imports so first-test timings drop from 2–5s to <200ms.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 17:40:14 -07:00
gsxdsm
98c3c22344 fix(engine): preserve step progress + worktree across internal task bounces
Workflow-step REVISE retries, pause→todo handoffs, and the
context-overflow fresh-session requeue were all routing tasks back to
`todo` before returning to `in-progress`. The default reopen-to-todo
path reset every step to pending and rewrote PROMPT.md checkboxes, so
each retry restarted from step 0 even when earlier steps had already
been done — the symptom seen on FN-2978, where every workflow REVISE
or pause cycle wiped the task's progress.

- Add `preserveResumeState` to `TaskStore.moveTask`. When set, skip
  `resetAllStepsToPending` + `resetPromptCheckboxes` and keep
  `worktree` and `executionStartedAt` so the resumed run reattaches to
  the same checkout. `status`, `error`, and `blockedBy` still clear.
- Use it on the workflow-rerun bounce, the three pause-graceful
  handoffs, and the context-overflow requeue. The agent-terminated
  pause path still discards (it nukes worktree+branch by design).
- Context-overflow requeue clears `sessionFile` synchronously in the
  awaited `updateTask` immediately before `moveTask`, so the next
  dispatch cannot reopen the saturated session via a stale pointer.
- `fn_task_update` no longer silently regresses `done`/`skipped` steps
  to `in-progress`, no longer captures a stale rewind checkpoint when
  it does, and tells the agent honestly when a regression is ignored.
- Mobile chat keyboard: ChatView/QuickChatFAB gate layout on the new
  `keyboardOpen` flag so focused-input + viewport-shrink iOS cases
  still adjust when the computed overlap is zero.

Tests:
- New `preserveResumeState` coverage in store.test.ts; updated
  workflow-rerun + pause-graceful assertions in executor.test.ts.
- Restructured the previously-flaky "routes exhausted prompt-mode
  workflow hard failures" test to drive the bounce inline; passes in
  isolation and in the wider workflow/pause/context sweep (59/59).
- Added regression tests in ChatView.test.tsx and QuickChatFAB.test.tsx
  for the iOS last-resort `keyboardOpen=true, keyboardOverlap=0` case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 14:12:03 -07:00
gsxdsm
e7c86aa08f feat(engine): preserve branches on auto-requeue + add fn_run_verification
Three coordinated fixes for the FN-2978 incident class — auto-requeues
that orphaned committed work and watchdog kills on long verification runs.

**Auto-requeue branch reuse** (executor.ts, worktree-pool.ts)
- executor.ts:1782 now uses `task.branch || fusion/<id>` so persisted
  branches are honored on requeue. Previously the hardcoded fallback
  always tried to re-create the original branch, hit a conflict with
  the prior run's ref, and got suffix -2/-3. Other call sites already
  honor task.branch — this aligns the worktree-acquisition path.
- worktree-pool.ts:181 prepareForTask now probes existing branches with
  `git rev-parse --verify` and checks them out as-is. Falls through to
  suffixed creation only when the branch is genuinely in use by another
  live worktree. Previously force-reset with `checkout -B`, destroying
  prior commits.
- New private reconcileStepsFromGitHistory walks `git log
  baseCommitSha..HEAD` for `feat(FN-X): complete Step N` commits and
  marks matching steps[] as done so resumes don't redo committed work.

**Manual reset endpoint + UI** (dashboard)
- POST /api/tasks/:id/reset (requires `confirm: true`) — clears worktree,
  branch, all retry counters, resets steps[] to pending, moves to todo.
  Distinct from /retry which is the soft-resume path.
- Reset button alongside Retry in TaskDetailModal with confirm dialog,
  wired through useTasks → AppModals → API.

**fn_run_verification tool** (run-verification-tool.ts, executor.ts)
- New custom tool wrapping test/lint/build commands with a heartbeat
  callback (per-line + 60s synthetic), 200KB head+tail output cap, hard
  timeout with SIGTERM→SIGKILL escalation, and auto-bootstrap detection
  for missing node_modules. Prevents the inactivity watchdog from
  killing sessions during long compiles.
- Cross-platform via `shell: true` (Node picks /bin/sh on POSIX,
  cmd.exe on Windows). Prompt section in EXECUTOR_SYSTEM_PROMPT and
  EXECUTOR_PROMPT_TEXT instructs agents to prefer package-scoped
  verification first and reserve workspace-scoped runs for final
  integration.

**Tests** (64 passing)
- detect-pseudo-pause.test.ts (27 tests) — covers all 7 regex patterns,
  structural fallback, FN-2978 regression text.
- reconcile-step-regex.test.ts (25 tests) — pins the commit-message
  regex against a wide variant set.
- run-verification-command.test.ts (12 tests) — basic execution, output
  capture, heartbeat callbacks, timeout, error handling. POSIX-specific
  cases (multi-cmd `;`, `>&2`, `\$USER`) gated behind itPosix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 10:19:54 -07:00
Fusion
3fcf5f4d82 feat(FN-2976): detect and display external Tailscale funnel tunnels in remo
Merges external Tailscale funnel detection (FN-2976) — adds types, detection logic, status inclusion, kill flow, and a dedicated UI panel for funnel processes started outside Fusion — alongside custom AI providers API routes and a new settings UI section (FN-2965).

Fusion-Task-Id: FN-2976
2026-04-30 05:43:13 -07:00
gsxdsm
208345e872 feat(self-healing): add ghost-review fallback recovery
Add recoverGhostReviewTasks as a final-fallback scan in the maintenance
loop. Catches any in-review task that fell through every more-specific
recovery scan and has been idle past taskStuckTimeoutMs, kicks it back
to todo with transient status cleared. Worktree state is intentionally
ignored — the executor recreates as needed. Preserves human-handoff and
active-merge statuses; rate-limited naturally by updatedAt refresh.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 04:41:56 -07:00
Fusion
9ee92de604 feat(FN-2992): merge fusion/fn-2992
Commits merged:
- fix(FN-2992): align ResearchView styles with design tokens
- fix(FN-2992): align Research view with standalone layout conventions
- test(FN-2992): complete Step 6 — expand orchestration verification
- feat(FN-2992): complete Step 5 — wire research settings and engine exports
- test(FN-2992): cover provider error classification in step runner
- feat(FN-2992): complete Step 4 — implement research step runner
- test(FN-2992): add orchestrator lifecycle regression coverage
- feat(FN-2992): complete Step 3 — add research orchestrator lifecycle
- feat(FN-2992): complete Step 2 — align research store API events
- feat(FN-2992): complete Step 1 — define orchestration domain types
- feat(FN-2992): complete Step 1 — define orchestration domain types

Files changed:
packages/core/src/index.ts                         |  15 +
 packages/core/src/research-store.ts                |   8 +-
 packages/core/src/research-types.ts                | 109 +++++
 packages/core/src/settings-schema.ts               |  10 +
 packages/core/src/types.ts                         |  31 ++
 packages/dashboard/app/components/ResearchView.css |  87 +++-
 packages/dashboard/app/components/ResearchView.tsx | 144 +++---
 .../app/components/__tests__/ResearchView.test.tsx |   3 +-
 .../src/__tests__/research-orchestrator.test.ts    | 256 ++++++++++
 .../src/__tests__/research-step-runner.test.ts     | 102 ++++
 packages/engine/src/index.ts                       |  11 +
 packages/engine/src/project-engine.ts              |  17 +
 packages/engine/src/research-orchestrator.ts       | 517 +++++++++++++++++++++
 packages/engine/src/research-step-runner.ts        | 235 ++++++++++
 14 files changed, 1464 insertions(+), 81 deletions(-)

Fusion-Task-Id: FN-2992
2026-04-30 00:48:37 -07:00
Fusion
115ea77d12 feat(FN-3019): merge fusion/fn-3019
Commits merged:
- feat(FN-3019): complete Step 4 — document gridlock cooldown semantics
- fix(FN-3019): normalize legacy custom provider payloads for typecheck
- test(FN-3019): complete Step 2 — add gridlock cooldown regression coverage
- fix(FN-3019): repair notifier class structure after cooldown refactor
- feat(FN-3019): complete Step 1 — add gridlock notification cooldown

Files changed:
docs/architecture.md                               |  3 +-
 docs/settings-reference.md                         |  4 +-
 .../app/components/CustomProvidersSection.tsx      | 25 ++++++----
 .../engine/src/__tests__/gridlock-detector.test.ts |  5 +-
 packages/engine/src/__tests__/notifier.test.ts     | 47 ++++++++++++++++--
 packages/engine/src/gridlock-detector.ts           | 16 +++++--
 packages/engine/src/notifier.ts                    | 55 ++++++++++++----------
 packages/engine/src/project-engine.ts              |  1 +
 8 files changed, 109 insertions(+), 47 deletions(-)

Fusion-Task-Id: FN-3019
2026-04-30 00:20:51 -07:00
gsxdsm
55ba19d06e fix(engine): widen mutableTask.column type in executor test
The `as const` annotation narrowed column to "in-progress" only, breaking
tsc build when the moveTask mock assigned "todo".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:19:10 -07:00
gsxdsm
7f9adb71e1 fix(FN-3005): restore unrelated heartbeat files 2026-04-29 23:14:51 -07:00
gsxdsm
bb9b0f1d1a fix(FN-3005): preserve card timer across reruns 2026-04-29 23:13:38 -07:00
gsxdsm
d81fc9b2c7 fix(heartbeat): per-agent HEARTBEAT.md and phase-aligned scheduler
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
ad4db8243: 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>
2026-04-29 23:08:21 -07:00
Fusion
739514cf04 feat(FN-3018): merge fusion/fn-3018
- **feat(engine): sanitize cwd from createFnAgent startup log** — prevents worktree paths from leaking into engine diagnostic logs
- **test(engine): add regression test for cwd redaction** — verifies working directory is not present in logged output
- **test(engine): update routes-agent-skills test** — minimal addition to coverage
- **test(dashboard): stabilize TaskCard test** — fixes flakiness in full-suite gate

Commits merged:
- test(FN-3018): stabilize dashboard tests for full-suite gate
- test(FN-3018): complete Step 2 — add cwd redaction regression
- feat(FN-3018): complete Step 1 — sanitize createFnAgent startup log

Files changed:
.../app/components/__tests__/TaskCard.test.tsx     |  2 +-
 .../src/__tests__/routes-agent-skills.test.ts      |  1 +
 .../src/__tests__/pi-create-fn-agent.test.ts       | 28 ++++++++++++++++++++++
 packages/engine/src/pi.ts                          |  2 +-
 4 files changed, 31 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-3018
2026-04-29 22:09:05 -07:00
Fusion
5e58ab91cf feat(FN-3003): merge fusion/fn-3003
- Unify notification service ownership across the engine: `Notifier` now operates on `ProjectEngine` rather than its own `Core` reference, resolving stale-closure issues during engine lifecycle
- Add regression tests in `notifier.test.ts` covering merge dedupe wiring and ownership initialization
- Expand `project-engine.test.ts` to cover ownership state transitions and `ProjectEngine`-notifier integration
- Fix TypeScript regressions in `ModelOnboardingModal.tsx` and `SettingsModal.tsx` introduced by custom provider types
- Document the notification ownership model in `docs/architecture.md`

Commits merged:
- feat(FN-3003): complete Step 4 — document notification ownership model
- fix(FN-3003): resolve dashboard custom provider typecheck regressions
- test(FN-3003): complete Step 2 — add merge dedupe wiring regressions
- feat(FN-3003): complete Step 1 — unify notification service ownership

Files changed:
docs/architecture.md                               |  2 +
 .../app/components/ModelOnboardingModal.tsx        | 13 +++++-
 .../dashboard/app/components/SettingsModal.tsx     | 17 +++++--
 packages/engine/src/__tests__/notifier.test.ts     | 33 ++++++++++++++
 .../engine/src/__tests__/project-engine.test.ts    | 53 +++++++++++++++++++---
 packages/engine/src/notifier.ts                    |  3 +-
 packages/engine/src/project-engine.ts              | 12 +++--
 7 files changed, 116 insertions(+), 17 deletions(-)

Fusion-Task-Id: FN-3003
2026-04-29 21:48:13 -07:00
Fusion
64b5f677ff feat(FN-2962): merge fusion/fn-2962
- Add changeset for `@runfusion/fusion` minor release introducing custom provider registration support

Commits merged:
- feat(FN-2962): complete Step 8 — add changeset and documentation

Files changed:
.changeset/register-custom-providers.md | 5 +++++
 1 file changed, 5 insertions(+)

Fusion-Task-Id: FN-2962
2026-04-29 21:42:44 -07:00
Fusion
3c37f8d4bb feat(FN-2987): merge fusion/fn-2987
- **Archived task read-only enforcement** — `packages/core/src/store.ts` adds guards that prevent log entries and documents from being written to archived tasks; `packages/engine/src/agent-tools.ts` surfaces meaningful errors instead of silent failures when tools are called on archived tasks
- **Type safety for archived guards** — resolved typecheck issues around the archived-task write guards in core
- **Tests for archived behavior** — added regression coverage in `packages/core/src/__tests__/store.test.ts` and `packages/core/src/__tests__/task-documents.test.ts`; also added `packages/engine/src/__tests__/agent-tools.test.ts` to cover archived-task error paths
- **Documentation** — updated `docs/task-management.md` to document the archived read-only behavior
- **Also merged** `fusion/fn-2959-2` (CustomProviderForm component, SettingsModal routing, custom provider API routes, and associated tests)

Commits merged:
- feat(FN-2987): complete Step 6 — document archived read-only behavior
- fix(FN-2987): complete Step 5 — resolve typecheck for archived guards
- test(FN-2987): complete Step 4 — add archived-task regression coverage
- feat(FN-2987): complete Step 3 — handle archived log tool errors
- feat(FN-2987): complete Step 2 — enforce archived document write guard
- feat(FN-2987): complete Step 1 — harden archived logEntry checks
- feat(FN-2959): merge fusion/fn-2959-2

Files changed:
.changeset/custom-openai-anthropic-providers.md    |   5 +
 docs/task-management.md                            |   4 +
 packages/core/src/__tests__/store.test.ts          |  38 +++
 packages/core/src/__tests__/task-documents.test.ts |  32 +++
 packages/core/src/store.ts                         |  34 ++-
 packages/dashboard/app/api/legacy.ts               |  41 ++++
 .../app/components/CustomProviderForm.css          |  45 ++++
 .../app/components/CustomProviderForm.tsx          | 203 ++++++++++++++++
 .../app/components/ModelOnboardingModal.css        |  14 ++
 .../app/components/ModelOnboardingModal.tsx        |  62 ++++-
 .../dashboard/app/components/SettingsModal.css     |  38 +++
 .../dashboard/app/components/SettingsModal.tsx     |  91 +++++++-
 .../__tests__/CustomProviderForm.test.tsx          |  60 +++++
 .../__tests__/ModelOnboardingModal.test.tsx        |  23 ++
 .../components/__tests__/SettingsModal.test.tsx    |  13 ++
 .../__tests__/SettingsModalNodeRouting.test.tsx    |   4 +
 .../components/__tests__/settings-mobile.test.tsx  |   4 +
 packages/dashboard/src/auth-paths.ts               |   4 +
 packages/dashboard/src/routes.ts                   |   2 +
 .../__tests__/custom-provider-routes.test.ts       | 118 ++++++++++
 .../src/routes/register-custom-provider-routes.ts  | 254 +++++++++++++++++++++
 .../src/__tests__/agent-document-tools.test.ts     |  15 ++
 packages/engine/src/__tests__/agent-tools.test.ts  |  43 ++++
 packages/engine/src/agent-tools.ts                 |  28 ++-
 24 files changed, 1166 insertions(+), 9 deletions(-)

Fusion-Task-Id: FN-2987
2026-04-29 20:18:46 -07:00
Fusion
9e5ac3c676 feat(FN-2947): merge fusion/fn-2947
- Add AI-powered merge commit summarization with toggle in Settings (`packages/core/src/ai-summarize.ts`, `packages/dashboard/app/components/SettingsModal.tsx`, `packages/engine/src/merger.ts`)
- Introduce `generateMergeCommitSummary` utility in `@fusion/core` that calls the configured model with a diff prompt; results appear in the commit log for merge commits
- Add `aiMergeSummaryEnabled` project setting and `useAiMergeSummaryEnabled` hook in dashboard
- Update `@runfusion/fusion` CLI extension to surface the new setting
- Add `POST /api/tasks/:id/workflow/pre-merge` and `POST /api/tasks/:id/planning-subtask` routes (`packages/dashboard/src/routes/`)
- Rework InsightsView with two-pane layout for better readability (`packages/dashboard/app/components/InsightsView.tsx`, `packages/dashboard/app/components/InsightsView.css`)
- Fix `task plan` command to surface errors when planning fails (`packages/cli/src/commands/task.ts`)
- Add tests for `ai-summarize`, `agent-heartbeat`, `agent-tools`, and dashboard API routes; refresh onboarding and agents-view mobile tests
- Minor CSS polish: reduce AgentsView panel hover gap, improve CommitDiffTab layout, add ScriptsModal styles
- Changelog and version bumps for `@runfusion/fusion` v0.9.1, CLI alias, and all workspace packages

Commits merged:
- feat(FN-2947): complete Step 7 — add changeset and docs deliverables
- fix(FN-2947): clean unused aiSummary path
- test(FN-2947): complete Step 5 — cover AI merge summary flow
- feat(FN-2947): complete Step 4 — add merge summary settings toggle
- feat(FN-2947): complete Step 3 — wire AI merge summaries into merger
- feat(FN-2947): complete Step 2 — add merge summary setting
- feat(FN-2947): complete Step 1 — add merge commit summarizer
- feat(FN-2970): merge fusion/fn-2970
- feat(FN-2956): merge fusion/fn-2956
- feat(FN-2923): merge fusion/fn-2923
- feat(FN-2945): merge fusion/fn-2945
- chore(release): v0.9.1
- fix(FN-XXX): improve git manager diff layout
- fix(dashboard): rework Insights view with two-pane layout
- fix(FN-XXX): keep experimental views off by default

Files changed:
.changeset/active-agents-no-stuck-connecting.md    |  13 --
 .changeset/active-agents-panel-hoist-heartbeat.md  |  13 --
 .changeset/add-ai-merge-commit-summary.md          |   5 +
 .changeset/fix-agent-heartbeat-terminal-links.md   |   5 -
 .changeset/show-planning-tasks-immediately.md      |   5 -
 CHANGELOG.md                                       |  92 ++++++++++
 docs/settings-reference.md                         |   3 +
 package.json                                       |   2 +-
 packages/cli-alias/CHANGELOG.md                    |  15 ++
 packages/cli-alias/package.json                    |   2 +-
 packages/cli/CHANGELOG.md                          |  12 ++
 packages/cli/package.json                          |   2 +-
 packages/cli/src/__tests__/task-plan.test.ts       |   1 +
 packages/cli/src/commands/__tests__/task.test.ts   |  15 +-
 packages/cli/src/commands/task.ts                  |  15 +-
 packages/cli/src/extension.ts                      |   9 +
 packages/core/CHANGELOG.md                         |   7 +
 packages/core/package.json                         |   2 +-
 packages/core/src/__tests__/ai-summarize.test.ts   |  64 +++++++
 packages/core/src/ai-summarize.ts                  | 114 ++++++++++++
 packages/core/src/index.ts                         |   3 +
 packages/core/src/settings-schema.ts               |   1 +
 packages/core/src/types.ts                         |   4 +
 packages/dashboard/CHANGELOG.md                    |  14 ++
 packages/dashboard/app/App.tsx                     |  28 ++-
 .../app/__tests__/agent-css-classes.test.ts        |   3 +-
 packages/dashboard/app/__tests__/api.test.ts       |  13 ++
 packages/dashboard/app/api/legacy.ts               |   2 +
 packages/dashboard/app/components/AgentsView.css   |  22 +--
 .../dashboard/app/components/CommitDiffTab.tsx     |   2 +-
 .../dashboard/app/components/GitManagerModal.tsx   |  71 ++++----
 packages/dashboard/app/components/InsightsView.css | 200 ++++++++++++++++++---
 packages/dashboard/app/components/InsightsView.tsx | 111 ++++++++----
 .../app/components/ModelOnboardingModal.tsx        |   5 +-
 packages/dashboard/app/components/ScriptsModal.css |  89 +++++++++
 .../dashboard/app/components/SettingsModal.css     |  11 +-
 .../dashboard/app/components/SettingsModal.tsx     |  22 ++-
 .../dashboard/app/components/TaskDetailModal.css   |   5 +
 packages/dashboard/app/components/TodoView.tsx     |   2 +
 .../app/components/__tests__/App.test.tsx          |  33 ++++
 .../app/components/__tests__/InsightsView.test.tsx |  25 ++-
 .../__tests__/ModelOnboardingModal.test.tsx        |   4 +-
 .../app/components/__tests__/QuickChatFAB.test.tsx |  14 +-
 .../__tests__/SettingsModalNodeRouting.test.tsx    |  12 +-
 .../app/components/__tests__/TodoView.test.tsx     |   4 +-
 .../__tests__/agents-view-mobile.test.tsx          |   5 +-
 .../components/__tests__/onboarding-flow.test.tsx  |   2 +-
 .../app/hooks/__tests__/useAppSettings.test.ts     |   1 +
 .../app/hooks/__tests__/useTaskHandlers.test.ts    |   4 +-
 packages/dashboard/app/hooks/useAppSettings.ts     |  12 ++
 packages/dashboard/app/hooks/useTaskHandlers.ts    |   4 +-
 packages/dashboard/package.json                    |   2 +-
 packages/dashboard/src/__tests__/routes.test.ts    |  14 ++
 packages/dashboard/src/routes.ts                   |   4 +
 .../dashboard/src/routes/register-git-github.ts    |  12 ++
 .../src/routes/register-planning-subtask-routes.ts |   3 +
 .../src/routes/register-task-workflow-routes.ts    |   7 +
 packages/desktop/CHANGELOG.md                      |   7 +
 packages/desktop/package.json                      |   2 +-
 packages/engine/CHANGELOG.md                       |  11 ++
 packages/engine/package.json                       |   2 +-
 .../engine/src/__tests__/agent-heartbeat.test.ts   |  10 ++
 .../src/__tests__/agent-tools-delegation.test.ts   |   2 +
 packages/engine/src/__tests__/agent-tools.test.ts  |  37 ++++
 packages/engine/src/__tests__/cron-runner.test.ts  |   4 +
 packages/engine/src/__tests__/merger.test.ts       |  75 ++++++++
 .../src/__tests__/node-routing-policy.test.ts      |  25 ++-
 .../src/__tests__/pr-comment-handler.test.ts       |   8 +
 .../src/__tests__/scheduler-node-routing.test.ts   |  18 +-
 packages/engine/src/__tests__/triage.test.ts       |   2 +
 packages/engine/src/agent-heartbeat.ts             |  13 +-
 packages/engine/src/agent-tools.ts                 |  13 +-
 packages/engine/src/cron-runner.ts                 |   7 +-
 packages/engine/src/executor.ts                    |   2 +-
 packages/engine/src/merger.ts                      | 181 ++++++++-----------
 packages/engine/src/mission-execution-loop.ts      |   8 +
 packages/engine/src/pr-comment-handler.ts          |   5 +
 packages/engine/src/project-engine.ts              |   8 +
 packages/engine/src/routine-runner.ts              |   4 +
 packages/engine/src/scheduler.ts                   |   8 +-
 packages/engine/src/triage.ts                      |   4 +
 packages/mobile/CHANGELOG.md                       |   7 +
 packages/mobile/package.json                       |   2 +-
 packages/pi-claude-cli/CHANGELOG.md                |   7 +
 packages/pi-claude-cli/package.json                |   2 +-
 packages/plugin-sdk/CHANGELOG.md                   |  10 ++
 packages/plugin-sdk/package.json                   |   2 +-
 .../examples/fusion-plugin-auto-label/CHANGELOG.md |   8 +
 .../examples/fusion-plugin-auto-label/package.json |   2 +-
 .../examples/fusion-plugin-ci-status/CHANGELOG.md  |   8 +
 .../examples/fusion-plugin-ci-status/package.json  |   2 +-
 .../fusion-plugin-notification/CHANGELOG.md        |   8 +
 .../fusion-plugin-notification/package.json        |   2 +-
 .../fusion-plugin-settings-demo/CHANGELOG.md       |   8 +
 .../fusion-plugin-settings-demo/package.json       |   2 +-
 plugins/fusion-plugin-hermes-runtime/CHANGELOG.md  |   8 +
 plugins/fusion-plugin-hermes-runtime/package.json  |   2 +-
 .../fusion-plugin-openclaw-runtime/CHANGELOG.md    |   8 +
 .../fusion-plugin-openclaw-runtime/package.json    |   2 +-
 .../fusion-plugin-paperclip-runtime/CHANGELOG.md   |   8 +
 .../fusion-plugin-paperclip-runtime/package.json   |   2 +-
 101 files changed, 1388 insertions(+), 334 deletions(-)

Fusion-Task-Id: FN-2947
2026-04-29 17:38:25 -07:00
Fusion
2e2be655f8 feat(FN-2956): merge fusion/fn-2956
- **FN-2956: Node routing policy guard** — `scheduler.ts` and `agent-heartbeat.ts` now enforce unavailable-node dispatch prevention; adds policy-matrix unit tests (`node-routing-policy.test.ts`) and integration tests (`scheduler-node-routing.test.ts`)
- **Agent delegation tools** — `agent-tools.ts` gains delegation functionality; `agent-heartbeat.ts` updated with monitoring hooks; 37 new lines of test coverage in `agent-tools.test.ts`
- **Dashboard route registration** — New routes added for git/github registration (`register-git-github.ts`), planning subtasks, and task workflows; test coverage in `routes.test.ts`
- **CLI task planning** — `task.ts` and `extension.ts` updated to support task planning flow; task-plan test extended
- **Engine integrations** — `cron-runner.ts`, `pr-comment-handler.ts`, `triage.ts`, `mission-execution-loop.ts`, `project-engine.ts`, and `routine-runner.ts` all updated with expanded tests and feature hooks
- **Dashboard UI/hooks** — `useTaskHandlers.ts` and related tests updated; `ModelOnboardingModal.tsx` and `TodoView.tsx` refined; CSS adjustments in `AgentsView.css`
- Includes merged work from `fusion/fn-2923` and `fusion/fn-2945`

Commits merged:
- test(FN-2956): complete Step 4 — align scheduler routing policy integration tests
- test(FN-2956): complete Step 3 — expand policy matrix unit coverage
- feat(FN-2956): complete Step 2 — enforce unavailable-node policy dispatch guard
- feat(FN-2923): merge fusion/fn-2923
- feat(FN-2945): merge fusion/fn-2945

Files changed:
packages/cli/src/__tests__/task-plan.test.ts       |  1 +
 packages/cli/src/commands/__tests__/task.test.ts   | 15 +++++++--
 packages/cli/src/commands/task.ts                  | 15 ++++++++-
 packages/cli/src/extension.ts                      |  9 ++++++
 .../app/__tests__/agent-css-classes.test.ts        |  3 +-
 packages/dashboard/app/__tests__/api.test.ts       | 13 ++++++++
 packages/dashboard/app/api/legacy.ts               |  2 ++
 packages/dashboard/app/components/AgentsView.css   | 22 ++++++-------
 .../app/components/ModelOnboardingModal.tsx        |  5 ++-
 packages/dashboard/app/components/TodoView.tsx     |  2 ++
 .../__tests__/ModelOnboardingModal.test.tsx        |  4 +--
 .../app/components/__tests__/QuickChatFAB.test.tsx | 14 ++------
 .../app/components/__tests__/TodoView.test.tsx     |  4 +--
 .../__tests__/agents-view-mobile.test.tsx          |  5 ++-
 .../components/__tests__/onboarding-flow.test.tsx  |  2 +-
 .../app/hooks/__tests__/useTaskHandlers.test.ts    |  4 +--
 packages/dashboard/app/hooks/useTaskHandlers.ts    |  4 +--
 packages/dashboard/src/__tests__/routes.test.ts    | 14 ++++++++
 packages/dashboard/src/routes.ts                   |  4 +++
 .../dashboard/src/routes/register-git-github.ts    | 12 +++++++
 .../src/routes/register-planning-subtask-routes.ts |  3 ++
 .../src/routes/register-task-workflow-routes.ts    |  7 ++++
 .../engine/src/__tests__/agent-heartbeat.test.ts   | 10 ++++++
 .../src/__tests__/agent-tools-delegation.test.ts   |  2 ++
 packages/engine/src/__tests__/agent-tools.test.ts  | 37 ++++++++++++++++++++++
 packages/engine/src/__tests__/cron-runner.test.ts  |  4 +++
 .../src/__tests__/node-routing-policy.test.ts      | 25 +++++++++++++--
 .../src/__tests__/pr-comment-handler.test.ts       |  8 +++++
 .../src/__tests__/scheduler-node-routing.test.ts   | 18 +++++------
 packages/engine/src/__tests__/triage.test.ts       |  2 ++
 packages/engine/src/agent-heartbeat.ts             | 13 ++++++--
 packages/engine/src/agent-tools.ts                 | 13 ++++++--
 packages/engine/src/cron-runner.ts                 |  7 +++-
 packages/engine/src/executor.ts                    |  2 +-
 packages/engine/src/mission-execution-loop.ts      |  8 +++++
 packages/engine/src/pr-comment-handler.ts          |  5 +++
 packages/engine/src/project-engine.ts              |  8 +++++
 packages/engine/src/routine-runner.ts              |  4 +++
 packages/engine/src/scheduler.ts                   |  8 +++--
 packages/engine/src/triage.ts                      |  4 +++
 40 files changed, 280 insertions(+), 62 deletions(-)

Fusion-Task-Id: FN-2956
2026-04-29 17:30:39 -07:00
Fusion
a285c2988b feat(FN-2923): merge fusion/fn-2923
- Add task `source` provenance field tracking how tasks enter the system (e.g. `"manual"`, `"heartbeat"`, `"executor"`, `"triage"`, `"cron"`, `"routine"`)
- Wire `source` into shared create-task tools, executor agent, triage agent, cron runner, and routine runner
- Add `source` to heartbeat task creation in `agent-heartbeat.ts` and mission execution loop in `mission-execution-loop.ts`
- Wire `source` field into dashboard routes (`register-planning-subtask-routes.ts`, `register-task-workflow-routes.ts`) and GitHub integration (`register-git-github.ts`)
- Add `source` to the API layer and task store handlers in the dashboard
- Expose `source` in the `fn` CLI task command and `task-plan` extension tool
- Add integration tests for provenance across engine (agent-tools, agent-heartbeat, cron-runner, triage, pr-comment-handler) and dashboard routes
- Update existing tests to assert the correct source values
- Bulk-revert stale changeset files that were superseded by the v0.9.1 release commit

Commits merged:
- test(FN-2923): complete Step 14 — align tests with task source provenance
- test(FN-2923): complete Steps 12-13 — update and add provenance tests
- feat(FN-2923): complete Step 10 — wire CLI task provenance
- feat(FN-2923): complete Step 9 — wire dashboard UI and API source fields
- feat(FN-2923): complete Step 8 — wire dashboard route provenance
- feat(FN-2923): complete Step 7 — wire remaining engine provenance
- feat(FN-2923): complete Step 6 — add routine create-task provenance
- feat(FN-2923): complete Step 5 — add cron create-task provenance
- feat(FN-2923): complete Step 4 — add triage subtask source
- feat(FN-2923): complete Step 3 — add executor create-task source
- feat(FN-2923): complete Step 2 — add heartbeat task provenance
- feat(FN-2923): complete Step 1 — add provenance to shared create-task tools
- feat(FN-2945): merge fusion/fn-2945
- chore(release): v0.9.1

Files changed:
.changeset/active-agents-no-stuck-connecting.md    | 13 ---
 .changeset/active-agents-panel-hoist-heartbeat.md  | 13 ---
 .changeset/fix-agent-heartbeat-terminal-links.md   |  5 --
 .changeset/fix-experimental-defaults.md            |  5 --
 .changeset/improve-git-manager-diff-pane.md        |  5 --
 .changeset/insights-two-pane-layout.md             |  5 --
 .changeset/show-planning-tasks-immediately.md      |  5 --
 CHANGELOG.md                                       | 92 ++++++++++++++++++++++
 package.json                                       |  2 +-
 packages/cli-alias/CHANGELOG.md                    | 15 ++++
 packages/cli-alias/package.json                    |  2 +-
 packages/cli/CHANGELOG.md                          | 12 +++
 packages/cli/package.json                          |  2 +-
 packages/cli/src/__tests__/task-plan.test.ts       |  1 +
 packages/cli/src/commands/__tests__/task.test.ts   | 15 +++-
 packages/cli/src/commands/task.ts                  | 15 +++-
 packages/cli/src/extension.ts                      |  9 +++
 packages/core/CHANGELOG.md                         |  7 ++
 packages/core/package.json                         |  2 +-
 packages/dashboard/CHANGELOG.md                    | 14 ++++
 .../app/__tests__/agent-css-classes.test.ts        |  3 +-
 packages/dashboard/app/__tests__/api.test.ts       | 13 +++
 packages/dashboard/app/api/legacy.ts               |  2 +
 packages/dashboard/app/components/AgentsView.css   | 22 +++---
 .../app/components/ModelOnboardingModal.tsx        |  5 +-
 packages/dashboard/app/components/TodoView.tsx     |  2 +
 .../__tests__/ModelOnboardingModal.test.tsx        |  4 +-
 .../app/components/__tests__/QuickChatFAB.test.tsx | 14 +---
 .../app/components/__tests__/TodoView.test.tsx     |  4 +-
 .../__tests__/agents-view-mobile.test.tsx          |  5 +-
 .../components/__tests__/onboarding-flow.test.tsx  |  2 +-
 .../app/hooks/__tests__/useTaskHandlers.test.ts    |  4 +-
 packages/dashboard/app/hooks/useTaskHandlers.ts    |  4 +-
 packages/dashboard/package.json                    |  2 +-
 packages/dashboard/src/__tests__/routes.test.ts    | 14 ++++
 packages/dashboard/src/routes.ts                   |  4 +
 .../dashboard/src/routes/register-git-github.ts    | 12 +++
 .../src/routes/register-planning-subtask-routes.ts |  3 +
 .../src/routes/register-task-workflow-routes.ts    |  7 ++
 packages/desktop/CHANGELOG.md                      |  7 ++
 packages/desktop/package.json                      |  2 +-
 packages/engine/CHANGELOG.md                       | 11 +++
 packages/engine/package.json                       |  2 +-
 .../engine/src/__tests__/agent-heartbeat.test.ts   | 10 +++
 .../src/__tests__/agent-tools-delegation.test.ts   |  2 +
 packages/engine/src/__tests__/agent-tools.test.ts  | 37 +++++++++
 packages/engine/src/__tests__/cron-runner.test.ts  |  4 +
 .../src/__tests__/pr-comment-handler.test.ts       |  8 ++
 packages/engine/src/__tests__/triage.test.ts       |  2 +
 packages/engine/src/agent-heartbeat.ts             | 13 ++-
 packages/engine/src/agent-tools.ts                 | 13 ++-
 packages/engine/src/cron-runner.ts                 |  7 +-
 packages/engine/src/executor.ts                    |  2 +-
 packages/engine/src/mission-execution-loop.ts      |  8 ++
 packages/engine/src/pr-comment-handler.ts          |  5 ++
 packages/engine/src/project-engine.ts              |  8 ++
 packages/engine/src/routine-runner.ts              |  4 +
 packages/engine/src/triage.ts                      |  4 +
 packages/mobile/CHANGELOG.md                       |  7 ++
 packages/mobile/package.json                       |  2 +-
 packages/pi-claude-cli/CHANGELOG.md                |  7 ++
 packages/pi-claude-cli/package.json                |  2 +-
 packages/plugin-sdk/CHANGELOG.md                   | 10 +++
 packages/plugin-sdk/package.json                   |  2 +-
 .../examples/fusion-plugin-auto-label/CHANGELOG.md |  8 ++
 .../examples/fusion-plugin-auto-label/package.json |  2 +-
 .../examples/fusion-plugin-ci-status/CHANGELOG.md  |  8 ++
 .../examples/fusion-plugin-ci-status/package.json  |  2 +-
 .../fusion-plugin-notification/CHANGELOG.md        |  8 ++
 .../fusion-plugin-notification/package.json        |  2 +-
 .../fusion-plugin-settings-demo/CHANGELOG.md       |  8 ++
 .../fusion-plugin-settings-demo/package.json       |  2 +-
 plugins/fusion-plugin-hermes-runtime/CHANGELOG.md  |  8 ++
 plugins/fusion-plugin-hermes-runtime/package.json  |  2 +-
 .../fusion-plugin-openclaw-runtime/CHANGELOG.md    |  8 ++
 .../fusion-plugin-openclaw-runtime/package.json    |  2 +-
 .../fusion-plugin-paperclip-runtime/CHANGELOG.md   |  8 ++
 .../fusion-plugin-paperclip-runtime/package.json   |  2 +-
 78 files changed, 499 insertions(+), 115 deletions(-)

Fusion-Task-Id: FN-2923
2026-04-29 17:23:22 -07:00
Fusion
7e832bbf92 feat(FN-2943): merge fusion/fn-2943
- **Active Agents panel overhaul**: Hoisted above the main agent list with a new `ActiveAgentsPanel.css` stylesheet; shows next heartbeat ETA and prevents cards from getting stuck in "Connecting..." state
- **Node routing policy**: Scheduler now enforces unavailable-node scheduling rules and routes tasks to eligible nodes more reliably (`packages/engine/src/scheduler.ts`, `node-routing-policy.ts`)
- **Task card merge timer**: Keeps the card timer live while a task is actively merging rather than resetting on merge start
- **Settings modal scroll**: Scrolls to top when auth actions succeed, with regression tests added
- **Task steps reset**: Resets steps when reopening a task that returns to todo or triage (FN-2966)
- **Core store additions**: New `packages/core/src/store.ts` test coverage for task state mutations
- **Dashboard SSE bus**: New `sse-bus.ts` for event bus communication in the dashboard
- **Version bumps**: `v0.9.0` release across all packages; `cli-alias`, `dashboard`, `engine`, `plugin-sdk`, and plugin changelogs updated
- **Changeset cleanup**: Removed 20 stale changeset files consumed by the v0.9.0 release; added two new ones for Active Agents panel fixes

Commits merged:
- test(FN-2943): complete Step 3 — add auth scroll-to-top regressions
- feat(FN-2943): complete Step 2 — scroll on successful auth actions
- feat(FN-2943): complete Step 1 — add settings content scroll ref
- feat(FN-2951): enforce unavailable-node scheduling and improve active agents panel
- chore: add changeset for Active Agents panel hoist + heartbeat ETA
- feat(dashboard): hoist Active Agents panel above main list, show next heartbeat
- fix(dashboard): add top margin between agent list and Active Agents panel
- fix(dashboard): unstick Active Agents panel cards from "Connecting..."
- chore(release): v0.9.0
- chore: add changeset for live merge timer on task card
- fix(dashboard): keep card timer live while task is actively merging
- feat(FN-2966): reset task steps when reopening to todo or triage

Files changed:
.changeset/active-agents-live-status-and-logs.md   |  13 -
 .changeset/active-agents-no-stuck-connecting.md    |  13 +
 .changeset/active-agents-panel-hoist-heartbeat.md  |  13 +
 .changeset/dashboard-merge-base-diff.md            |  13 -
 .changeset/dashboard-task-changed-files-only.md    |  13 -
 .changeset/engine-concurrency-races.md             |  13 -
 .changeset/fix-agent-heartbeat-scheduling.md       |   5 -
 .changeset/memory-dream-session-state.md           |  13 -
 .changeset/merger-ai-summarized-commits.md         |  13 -
 .changeset/multi-node-routing.md                   |  21 -
 .changeset/pluggable-notification-providers.md     |   4 -
 .changeset/pr-mode-push-branch-and-cleanup.md      |  16 -
 .../recover-mergeable-respects-merge-settings.md   |  13 -
 .changeset/remote-tailscale-qr-tui.md              |   7 -
 .changeset/require-pr-approval-setting.md          |  17 -
 .changeset/respec-from-in-review.md                |  13 -
 .changeset/restore-task-card-fallbacks.md          |  13 -
 .changeset/tui-log-copy-feedback.md                |  13 -
 .changeset/tui-wide-stats-stack.md                 |  13 -
 CHANGELOG.md                                       | 449 +++++++++++++++++++++
 package.json                                       |   2 +-
 packages/cli-alias/CHANGELOG.md                    |  60 +++
 packages/cli-alias/package.json                    |   2 +-
 packages/cli/CHANGELOG.md                          |  44 ++
 packages/cli/package.json                          |   2 +-
 packages/core/CHANGELOG.md                         |  41 ++
 packages/core/package.json                         |   2 +-
 packages/core/src/__tests__/store.test.ts          | 127 ++++++
 packages/core/src/store.ts                         |  35 +-
 packages/dashboard/CHANGELOG.md                    |  63 +++
 .../dashboard/app/components/ActiveAgentsPanel.css |  29 ++
 .../dashboard/app/components/ActiveAgentsPanel.tsx |  35 +-
 packages/dashboard/app/components/AgentsView.tsx   |   5 +-
 .../dashboard/app/components/SettingsModal.tsx     |  13 +-
 packages/dashboard/app/components/TaskCard.tsx     |  30 +-
 .../__tests__/ActiveAgentsPanel.test.tsx           |  42 ++
 .../app/components/__tests__/AgentsView.test.tsx   |  11 +-
 .../components/__tests__/SettingsModal.test.tsx    |  68 ++++
 .../app/components/__tests__/TaskCard.test.tsx     |  36 ++
 packages/dashboard/app/sse-bus.ts                  |  13 +
 packages/dashboard/package.json                    |   2 +-
 packages/desktop/CHANGELOG.md                      |  41 ++
 packages/desktop/package.json                      |   2 +-
 packages/engine/CHANGELOG.md                       |  59 +++
 packages/engine/package.json                       |   2 +-
 .../src/__tests__/node-routing-policy.test.ts      | 102 +++--
 .../src/__tests__/scheduler-node-routing.test.ts   |  43 +-
 packages/engine/src/index.ts                       |   1 +
 packages/engine/src/node-routing-policy.ts         |  41 +-
 packages/engine/src/scheduler.ts                   |  48 +--
 packages/mobile/CHANGELOG.md                       |  41 ++
 packages/mobile/package.json                       |   2 +-
 packages/pi-claude-cli/CHANGELOG.md                |  41 ++
 packages/pi-claude-cli/package.json                |   2 +-
 packages/plugin-sdk/CHANGELOG.md                   |  57 +++
 packages/plugin-sdk/package.json                   |   2 +-
 .../examples/fusion-plugin-auto-label/CHANGELOG.md |  21 +
 .../examples/fusion-plugin-auto-label/package.json |   2 +-
 .../examples/fusion-plugin-ci-status/CHANGELOG.md  |  21 +
 .../examples/fusion-plugin-ci-status/package.json  |   2 +-
 .../fusion-plugin-notification/CHANGELOG.md        |  21 +
 .../fusion-plugin-notification/package.json        |   2 +-
 .../fusion-plugin-settings-demo/CHANGELOG.md       |  21 +
 .../fusion-plugin-settings-demo/package.json       |   2 +-
 plugins/fusion-plugin-hermes-runtime/CHANGELOG.md  |  21 +
 plugins/fusion-plugin-hermes-runtime/package.json  |   2 +-
 .../fusion-plugin-openclaw-runtime/CHANGELOG.md    |  21 +
 .../fusion-plugin-openclaw-runtime/package.json    |   2 +-
 .../fusion-plugin-paperclip-runtime/CHANGELOG.md   |  21 +
 .../fusion-plugin-paperclip-runtime/package.json   |   2 +-
 70 files changed, 1617 insertions(+), 378 deletions(-)

Fusion-Task-Id: FN-2943
2026-04-29 14:43:10 -07:00
Fusion
3ac07f3207 feat(FN-2951): enforce unavailable-node scheduling and improve active agents panel
- Enforce unavailable-node routing policy in the scheduler and wire policy integration through engine startup
- Expand scheduler and node-routing policy test coverage for unavailable-node handling and policy integration behavior
- Hoist the Active Agents panel above the main agents list and display next-heartbeat ETA details
- Fix Active Agents panel UI issues by resolving stuck "Connecting..." cards and adding spacing adjustments
- Add changesets covering Active Agents panel hoist/heartbeat ETA and connecting-state fixes

Fusion-Task-Id: FN-2951
2026-04-29 14:36:50 -07:00
Fusion
17a072c924 feat(FN-2920): improve remote tunnel setup and heartbeat scheduling
- Add cloudflared install/detection support in remote settings API, UI, and route tests
- Surface Cloudflare tunnel prerequisites in Settings modal with remote access docs updates
- Harden heartbeat runtime scheduling by avoiding stale timeout state and simplifying runtime timeout handling
- Expand CLI/core/dashboard/engine coverage for task lifecycle, agent health, and runtime heartbeat behavior
- Add changesets for heartbeat scheduling fixes and PR approval setting updates

Fusion-Task-Id: FN-2920
2026-04-29 13:49:35 -07:00
gsxdsm
7f42c7fe42 fix(engine): respect autoMerge and mergeStrategy in recover-mergeable-review sweep
The periodic maintenance job `recover-mergeable-review` was silently merging
in-review tasks regardless of `autoMerge` and `mergeStrategy` settings,
defeating the PR-based review flow for users with `autoMerge: false` and
`mergeStrategy: "pull-request"`.

Gate the sweep on `settings.autoMerge` (and globalPause/enginePaused for
consistency with other merge entry points) and route through the engine's
merge queue via the existing `enqueueMerge` callback so `mergeStrategy ===
"pull-request"` is honored. Falls back to the direct `store.mergeTask` path
only when no enqueue callback is wired (standalone/tests).

Closes https://github.com/Runfusion/Fusion/issues/21

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:26:05 -07:00
Fusion
8e3288d94e feat(FN-2950): merge fusion/fn-2950
- Updated routing policy documentation in `docs/architecture.md` and `docs/settings-reference.md`
- Revised docs reflect the latest routing configuration options and behavior

Commits merged:
- feat(FN-2950): complete Step 6 — update routing policy documentation

Files changed:
docs/architecture.md       | 19 ++++++++++---------
 docs/settings-reference.md |  2 +-
 2 files changed, 11 insertions(+), 10 deletions(-)

Fusion-Task-Id: FN-2950
2026-04-29 12:17:18 -07:00
gsxdsm
f1c87c38d4 fix(engine): close executor/merger concurrency races and reviewer pause TOCTOU
FN-2910 surfaced concurrent reviewer + merger activity on the same task.
Root cause: asymmetric in-flight guards let an unpause-resume kick off a
fresh executor session while a recovery path was already running, and the
auto-merge handoff fired before the executor's finally block finished
cleanup. This sweeps the surrounding lifecycle paths for similar races and
tightens the reviewer pause gate against TOCTOU through runtime setup.

- Symmetric in-flight tracking across `executing`, `recoveringCompleted`,
  and `resumingUnpaused`; `recoverCompletedTask` bails when any are set.
- Atomic claim of the recovery slot in the completed-task watchdog before
  any awaited work.
- Workflow-rerun bounce returns "bounced" | "skipped-pending" so the
  watchdog can no longer log a false-success retry when the original
  bounce is still mid-flight.
- Self-healing's completed-task scan re-checks executing IDs inside the
  loop instead of trusting a pre-await snapshot.
- 300ms grace period before auto-merge enqueue, giving the executor's
  finally block (session disposal, child cleanup) time to drain and
  eliminating the residual log-overlap symptom from FN-2910. Test uses
  fake timers, no real sleep added.
- New AgentSemaphore.runNested for synchronously nested helper agents
  (reviewers): bumps activeCount for honest observability while bypassing
  the wait queue, preserving forward-progress fairness for the parent at
  low maxConcurrent. Both createReviewStepTool and triage's
  createReviewSpecTool now use it.
- New beforeSpawnSession hook on AgentRuntimeOptions/AgentOptions fired
  inside createFnAgent immediately before createAgentSession, past every
  awaited setup step. Reviewer wires a pause re-check that throws a
  sentinel error converted to UNAVAILABLE, closing the TOCTOU window
  where pause flipped during runtime resolution or resource loading.

All 2887 engine tests pass; engine + core + cli + dashboard + plugin-sdk
+ pi-claude-cli + desktop typecheck clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 11:26:39 -07:00
gsxdsm
bd14cf84e3 fix(FN-XXX): harden windows path handling 2026-04-29 07:35:23 -07:00
Fusion
995165ea60 feat(FN-2944): merge fusion/fn-2944
- test(FN-2944): cover already checked out worktree conflict recovery
- fix(FN-2944): recognize git already checked out worktree conflict
- fix(engine): auto-recover from squash-merge orphan rebase failures

Fusion-Task-Id: FN-2944
2026-04-29 07:10:52 -07:00
gsxdsm
98fb71c202 fix(engine): auto-recover from squash-merge orphan rebase failures
Adds a layered recovery cascade to the merger's pre-rebase stage so tasks
no longer get stuck in in-review when their declared dependency was
squash-merged to main and left orphan raw commits in the dependent's
history. Also prevents the orphan situation at the source for new tasks.

Why:
- 13 tasks were stuck in in-review for hours, all hitting the same
  pre-merge rebase abort because they shared 6 raw commits inherited
  from FN-2729's branch (declared baseBranch). FN-2729 was then
  squash-merged to main, turning those raw commits into orphans whose
  content is in main but in a different commit shape, conflicting with
  later-merged tasks. The merger's `smart-prefer-main` strategy
  correctly refused -X ours (which would silently re-introduce main's
  deletions), but the only escape hatch was a 30-min cooldown loop
  that retried the same impossible rebase forever.

Recovery cascade (merger.ts pre-rebase stage):
- Layer 1: surgical `git rebase --onto <main> <dep-tip> <branch>` when
  task.baseBranch is set. Resolves the dep tip from the live branch ref
  or recorded baseCommitSha; peels off the dep's inherited commits
  cleanly. Captures the squash-merge-of-dep case end-to-end.
- Layer 2: generic patch-id duplicate-content stripping. Walks the last
  500 main commits, computes patch-ids, then drops branch commits whose
  patch-id matches and cherry-picks the remainder onto main. Captures
  manual cherry-picks, double-merges, and any other duplicate-content
  variant Layer 1 doesn't see. Restores the branch's pre-mutation SHA
  on partial-failure so worst case leaves the worktree no worse than
  before the recovery attempt.
- Layer 3: AI arbitration fall-through. If Layers 1+2 fail, log the
  situation and proceed to the existing 3-attempt AI merge cascade
  instead of throwing. The deterministic post-merge verification
  (test + build) gates whatever the AI produces — that gate is what
  enforces prefer-main's safety contract under fall-through (no silent
  re-introduction of main's deletions).
- Critical: the unsafe `-X ours` Attempt 3 is suppressed under
  fall-through. AI Attempts 1+2 are the only paths that can complete
  the merge; if both fail and verification rejects them, the task
  bounces back to in-progress via the existing engine path rather than
  silently merging.

Prevention (executor.ts worktree creation):
- When a task declares a non-main `baseBranch`, branch the worktree
  off main (origin/<defaultBranch> when worktreeRebaseBeforeMerge is
  enabled and a remote is resolvable; otherwise local rootDir HEAD)
  and `git merge --squash` the dep's content as a single import commit.
  The dependent branch then carries main's history + 1 commit instead
  of inheriting the dep's raw commits, so a future squash-merge of the
  dep produces patch-id-matching content that rebases cleanly.
- Honors settings: respects `worktreeRebaseBeforeMerge`,
  `worktreeRebaseRemote`, and falls back to local HEAD when no remote
  is resolvable. Fully fail-soft: any squash-import error falls back to
  the legacy fork-from-dep behavior so worktree creation still works
  for setups where the squash flow can't run.

Engine-side last-retry fix (project-engine.ts):
- Changed conflict-retry condition from `currentRetries < MAX` to
  `currentRetries + 1 < MAX` so the bounce-to-in-progress code fires
  in the same engine tick as the failing attempt, rather than relying
  on a setTimeout-scheduled Nth attempt that dies on engine restart.
  Without this, a dev-time engine restart between the 3rd and 4th
  retry left the task with mergeRetries=MAX and only the 30-min
  cooldown sweep could try again.

Tests:
- New "Layer 1 recovery" test asserts the surgical --onto rebase fires
  when baseBranch is set and primary rebase aborts, and that Layer 3
  fall-through is NOT triggered when Layer 1 succeeds.
- Updated the "no silent fall-through to -X ours" test to cover the
  new fall-through path: even after Layers 1+2 fail and the merge
  cascade proceeds, -X ours must not run, and the task log must record
  both the Layer 3 fall-through entry and the Attempt 3 suppression.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 07:06:13 -07:00
gsxdsm
15e4cba5e9 fix(engine): prevent auto-merge cooldown loop on unresolvable conflicts
Tasks were getting stuck in `in-review` forever when auto-merge could not
resolve conflicts within MAX_AUTO_MERGE_RETRIES. The conflict-exhaustion
branch silently cleared `status` (no error, no log entry, no comment),
and the 30-min cooldown sweep would reset retries and re-attempt the
same impossible merge — looping silently with no user-facing surface.

Why:
- FN-2918 and FN-2903 both spent hours in this loop with no error/comment
  visible on the task. The only log evidence was repeated
  "Auto-merge retry cooldown elapsed (30m idle)" entries with no
  follow-up outcome.

How to apply:
- Every merge failure now writes a `<Manual|Auto>-merge failed: <msg>`
  entry to the task log so the dashboard surfaces the reason.
- Conflict-retry exhaustion now bounces the task back to `in-progress`
  with a comment + log entry so the executor re-rebases against main
  and retries — mirroring the verification-failure-bounce pattern.
- New `mergeConflictBounceCount` task field caps outer bounces
  (`MAX_MERGE_CONFLICT_BOUNCES = 2`); past the cap, the task is parked
  in `in-review` with `status="failed"` and a follow-up triage task is
  created so a human can resolve the conflict manually.
- Non-conflict and non-direct-strategy errors now also set
  `status="failed"` so the cooldown sweep can't re-pick them up.
- `canMergeTask` skips tasks with `status="failed"` so terminal
  failures (verification cap, bounce cap, non-conflict error) are no
  longer eligible for cooldown re-attempts.

Schema migration v52 adds the `mergeConflictBounceCount` column.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 23:17:10 -07:00
Fusion
531b13e6ad feat(FN-2895): merge fusion/fn-2895
- feat(FN-2895): complete Step 7 — documentation and delivery

Fusion-Task-Id: FN-2895
2026-04-28 21:50:27 -07:00