chore(release): v0.23.0

Version bump via changesets.
This commit is contained in:
gsxdsm
2026-05-06 22:47:53 -07:00
parent 8bdac36c54
commit ecb5f60152
77 changed files with 685 additions and 370 deletions

View File

@@ -1,7 +0,0 @@
---
"@runfusion/fusion": patch
---
Make the agent error details modal taller on mobile so the full error
message is visible from the top, with the error pre flexing to fill the
available height instead of capping at a small fixed height.

View File

@@ -1,12 +0,0 @@
---
"@runfusion/fusion": patch
---
Stop the dashboard from auto-marking another agent's messages as read when
the user opens them while browsing that agent's mailbox. Previously, viewing
a message in an agent's inbox (e.g. the CEO's mailbox) would call
`POST /messages/:id/read`, which silently consumed the agent's unread state.
The agent's heartbeat would then never see the message as pending, and the
agent's `fn_read_messages` tool (which defaults to `unread_only: true`)
returned nothing. The mark-as-read call now only fires for the dashboard
user's own inbox tab.

View File

@@ -1,10 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix the misleading "X active · Y running" label in the Agents overview
dropdown. Both numbers previously counted agents whose state was either
`active` or `running`, so the "running" tally over-reported by including
idle-but-enabled agents. The label now counts each state distinctly:
"active" reflects only `state === "active"` and "running" reflects only
`state === "running"`.

View File

@@ -1,17 +0,0 @@
---
"@runfusion/fusion": patch
---
Two mobile chat fixes:
1. Tapping the ChatView send button no longer dismisses the soft
keyboard. preventDefault now fires on `pointerdown` for touch
pointers (before iOS blurs the textarea — the synthesized mousedown
it previously relied on fires too late). Click still runs the send
action so quick taps remain reliable.
2. The bottom executor status bar is now hidden on mobile while the
keyboard is open, mirroring `MobileNavBar`. The bar is
`position: fixed` against the layout viewport, which iOS leaves
anchored below the keyboard — during a swipe/pan it would slide
over the message list.

View File

@@ -1,10 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix chat sending silently failing on flaky networks (especially mobile).
The SSE reader in the dashboard client now treats a closed stream without
a terminal `done`/`error` event as an error so streaming state unwinds
instead of getting stuck. The `useChat` and `useQuickChat` hooks also now
show a toast when a message is queued behind an in-flight response, so
the previous stuck state is observable rather than silent.

View File

@@ -1,13 +0,0 @@
---
"@runfusion/fusion": patch
---
Workaround long-standing bug where ChatView's mobile send button only
fired on a long press — quick taps silently did nothing. The previous
implementation used `pointerdown` + `touchstart` with `preventDefault`
and a focus-preservation dance so the keyboard would stay up while
sending; on iOS that path made quick taps fall through entirely. The
button now uses plain `onClick` with `touch-action: manipulation`. The
soft keyboard may dismiss on send, which is a minor UX regression
compared to silent failure. QuickChat is unchanged (it already works
on mobile).

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix Codex weekly usage pace calculation when the API returns `reset_at` as epoch milliseconds instead of seconds. The dashboard now parses both formats correctly so weekly reset countdowns and pace status reflect reality.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": minor
---
Add host support for plugin-registered top-level dashboard views and ship a plugin-first dependency graph view with interactive navigation and project-scoped layout persistence.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": minor
---
Add native-shell remote connection management across desktop/mobile, including saved server profiles, optional auth token support, and shell-owned connection switching APIs used by dashboard onboarding/connection UI.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Restore the documented agent lifecycle by removing `terminated` as an agent state again. Agent stop flows now land on `paused`, while heartbeat run history continues to use `terminated` as a run-status value and existing persisted terminated agents migrate to `paused` on startup.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix duplicate ntfy merge notifications by ensuring `ProjectEngine` uses a single `NotificationService` listener graph and passes that shared service into the `NtfyNotifier` compatibility shim.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix bundled runtime plugin settings behavior for fresh installs: bundled Hermes/OpenClaw/Paperclip settings now open without a 404 before install, first save still lazy-installs, missing bundles return explicit server errors, and bundled install entry resolution now prefers workspace source entrypoints over stale build artifacts.

View File

@@ -1,12 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix `scripts/check-test-isolation.mjs` false-failing when `--before` and the
post-run check are invoked from different working directories (e.g. a worktree
recorded the baseline, then the main repo ran the check). The shared baseline
file in `tmpdir()` is now namespaced by a hash of the cwd so concurrent
worktrees don't clobber each other, and protected `.fusion` dirs that were
absent from the baseline are now skipped with a warning instead of being
treated as `{exists: false}` (which previously flagged the entire pre-existing
directory tree as a "test mutation").

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Improve full Chat mobile tool-call cards by keeping collapsed summaries on a single row and tightening spacing for denser scanning without changing expand/collapse behavior.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Forward engine skill selection into runtime `skills` metadata for all session paths, and improve Hermes runtime behavior so first-turn prompts preserve Fusion system/skill context instead of silently dropping coordination capability hints on non-pi runtime runs.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Auto-install the bundled Fusion skill when the Hermes runtime plugin loads, including profile-aware Hermes skill-path resolution and safe idempotent replacement behavior. Hermes runtime startup now continues with warnings if skill mirroring fails.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix Claude dashboard OAuth on remote hosts by using the pasted authorization-code flow instead of callback URL rewriting, while preserving callback proxy behavior for providers that still require it.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Preserve agent inline memory in Agent Companies import/export flows so AGENTS manifests round-trip memory without loss.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix an engine compatibility bug where reviewer/triage/executor runs could fail when a provider extension rejected both `thinking` and `reasoning_effort` together. Fusion now retries without the explicit thinking-level override for that conflict instead of marking the run unavailable.

View File

@@ -1,10 +0,0 @@
---
"@runfusion/fusion": patch
---
Wire `TaskStore` into the runtime's `AgentStore` so the heartbeat auto-claim
path can call `claimTaskForAgent` without warning
`TaskStore not configured for task-claim operations`. The `InProcessRuntime`
previously built its `AgentStore` with only `rootDir`, which left task-claim,
checkout, and release operations unconfigured even though the runtime had a
`TaskStore` available.

View File

@@ -1,9 +0,0 @@
---
"@runfusion/fusion": patch
---
Manual heartbeat runs (POST /api/agents/:id/runs) now respond as soon
as the run record is created instead of blocking on the full
executeHeartbeat call. Long-running heartbeats no longer cause the
dashboard to surface "Failed to start heartbeat run: load failed" when
the client socket times out before the run completes.

View File

@@ -1,9 +0,0 @@
---
"@runfusion/fusion": patch
---
Convert the heartbeat executor's dynamic `import("./agent-session-helpers.js")`
and `import("./session-skill-context.js")` calls to static imports. This makes
missing or partial engine dist surface at module load time (matching the
existing static `pi.js` import) instead of failing mid-heartbeat with a
confusing `ERR_MODULE_NOT_FOUND`.

View File

@@ -1,11 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix merger subject derivation and add a race-rescue layer to the autostash.
The deterministic fallback now prefers the lowest-numbered `complete Step N` headline (or the oldest commit) over the most-recent commit, and the AI subject/body prompts weight by commit theme instead of file size — so a small token-cleanup fixup that touches a large file no longer hijacks the squash-merge subject.
The pre-merge autostash now re-snapshots the working tree after the primary stash is persisted but before `git reset --hard` runs, capturing any dirty paths that landed between the initial snapshot and the destructive wipe (concurrent dev edits during a long merger run, parallel merger runs interleaving, or late test/build artifacts) into a separate `race-rescue` stash so they're recoverable from `git stash list`.
Adds an advisory `.git/.fusion-merger-active.json` written for the duration of each merger run (taskId, pid, hostname, startedAt) so dashboards / status lines / pre-Edit hooks can surface that `rootDir` is volatile. Not a lock — dev edits are never blocked. Race-rescue stashes are now also surfaced on the task feed via `store.logEntry` with the recovery command, instead of only appearing as a `mergerLog.warn`. `resetMergeWithWarn` now wraps each `git reset --merge` in a snapshot-before/after observer so any silent wipe of unrelated dirty paths emits an actionable warning instead of going unnoticed. Exports `readActiveMergerStatus(rootDir)` for consumers.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix race-rescue stash duplicating the primary autostash. `git add -A && git stash create` registers a stash commit but does not clean the working tree, so the rescue loop's subsequent `snapshotDirtyFiles` saw the same files the primary stash already captured and stashed them again on every merger run. Now the rescue diffs current dirty paths against the primary stash's recorded path set and only rescues paths that weren't already captured, plus a tree-SHA equality check that drops any rescue whose tree exactly matches the primary.

View File

@@ -1,10 +0,0 @@
---
"@runfusion/fusion": patch
---
Address code-review findings on the merger autostash work:
- `parsePorcelainZ` now correctly handles rename/copy entries (`R` / `C` status), which emit two NUL-separated entries for one logical change. Previously the old name was treated as an independent dirty path, causing `runObservedDestructiveSyncOp` to emit spurious "cleared N path(s)" warnings whenever a rename was in flight.
- The race-rescue loop in `stashUnrelatedRootDirChanges` now runs `git reset` between attempts so each `git add -A` starts from a clean index, preventing iteration-2+ stashes from drifting due to stale staging rather than genuine new writes.
- `writeActiveMergerStatus` now writes the advisory file via temp-path + atomic `renameSync` so dashboard readers can't observe a partial write.
- `deriveDeterministicSubjectSummary`'s Step regex switched from `[—\-:]` to `(?:—|-|:)` — same matches, but the em-dash intent is obvious to anyone auditing.

View File

@@ -1,18 +0,0 @@
---
"@runfusion/fusion": patch
---
Reduce redundant test/build runs during merge verification:
- **Skip the verification re-run after a no-op in-merge fix.** When the fix
agent doesn't actually modify the working tree (compared via a git
`diff HEAD` + `status --porcelain` content fingerprint), there's nothing
new to verify. The merger now logs "fix agent made no changes — skipping
verification re-run" and records the attempt as failed without paying the
multi-minute test/build cost.
- **Skip `pnpm install --frozen-lockfile` when the lockfile hash hasn't
changed since the last successful install.** A `node_modules/.fusion-install-marker`
file records the lockfile SHA-256 after a successful install; subsequent
merge attempts in the same worktree skip install when the lockfile content
is unchanged, even when `package.json` is staged. Existing
`shouldSyncDependenciesForMerge` filtering still applies as a first gate.

View File

@@ -1,7 +0,0 @@
---
"@runfusion/fusion": minor
---
Add plugin-managed binary installation/setup lifecycle. Plugins can now declare
setup hooks (check, install, uninstall) for required binaries/runtimes. Dashboard
API and CLI commands support checking setup status and triggering install/uninstall.

View File

@@ -1,11 +0,0 @@
---
"@runfusion/fusion": patch
---
Remove the dead `reportDashboardPerf` client and its five call sites in
`App.tsx` / `useProjects.ts`. The companion server route `/_perf/dashboard-load`
no longer exists, so every call was a silently-swallowed 404. Also drops the
`dashboard-perf.log` runtime ignore-list entry from
`scripts/check-test-isolation.mjs` since nothing creates that file anymore.
Console-side perf logging via `console.log("[App] …")` and
`console.log("[useProjects] …")` is preserved.

View File

@@ -1,18 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix a race in the stuck-task requeue path that could clobber a task back to
`todo` (with all step progress reset and worktree torn down) immediately
after `SelfHealingManager.recoverCompletedTasks` had already moved it to
`in-review`. The executor's stuck-kill cleanup ran in `execute()`'s
`finally` block and used a stale captured `task.column` snapshot, so it
would happily overwrite a fresh recovery. The cleanup now re-reads the
latest column and skips entirely when the task has moved past
`in-progress`/`todo`.
Also adds a new setting `preserveProgressOnStuckRequeue` (default: `true`,
toggle in Settings → Engine, near "Stuck Task Timeout"). When enabled, the
stuck detector's requeue passes `{ preserveProgress: true }` to `moveTask`
so completed step statuses survive the bounce and the agent can resume
from where it left off instead of restarting every step from pending.

View File

@@ -1,16 +0,0 @@
---
"@runfusion/fusion": patch
---
Stop inadvertently pausing user-facing tasks during heartbeat-unresponsive
recovery. Adds a `cascadeToTasks` option to `pauseAgent`/`resumeAgent`
(default `true`) and passes `false` from `recoverUnresponsiveAgent` — the
internal pause/resume cycle there is just to set
`pauseReason="heartbeat-unresponsive"` on the agent and shouldn't toggle
the user's task pause state.
Also auto-clears `paused`/`pausedByAgentId` in `updateTask` when the agent
that paused a task is unassigned (or replaced). Previously a task could be
left orphaned-paused with no UI affordance to recover, since the
`Pause/Unpause` action in `TaskDetailModal` is hidden whenever an agent is
assigned.

View File

@@ -1,10 +0,0 @@
---
"@runfusion/fusion": patch
---
Extend `scripts/check-test-isolation.mjs` runtime ignore list to cover live
fusion app paths that previously tripped the merge-time check when a fusion
instance was running on the same HOME during tests: `tasks/`, `messages/`,
`memory-insights.md`, `test-cache.json`, `HEARTBEAT.md`, `kb.db.backup-*`,
and `fusion.db.pre-*` snapshots. Tests still must not write to these paths;
the filter only suppresses noise from a concurrently-running app.

View File

@@ -1,5 +0,0 @@
---
"@runfusion/fusion": patch
---
scripts: make `check-test-isolation` resilient to a concurrently-running fusion app on the same HOME. Filter out paths the live app legitimately writes (databases, agent sessions/memory, plugins, automations, logs, config), sample the baseline over a longer window, and re-sample on suspected violations to avoid false positives during local `pnpm test:isolated`.

View File

@@ -1,20 +0,0 @@
---
"@runfusion/fusion": minor
---
Add a horizontal log split to the TUI's narrow single-pane main view. When
the terminal is too narrow for the multi-pane grid, the bottom of the
screen now shows a live log strip while the top keeps the active section
(System, Stats, Utilities, or Settings). The split is dynamic: the top
pane gets exactly the rows it needs to render its content without
truncating (computed from the System chip wrap at the current width, or
each panel's known row count for Stats/Utilities/Settings), and the log
strip absorbs all remaining rows — maximizing log visibility without
clipping the active section. The split disables itself if the leftover
would give the log strip fewer than 6 rows. Down-arrow shifts sub-focus
into
the strip with the same key bindings as the dedicated logs section
(j/k, Home/G, Enter to expand, w to wrap, c to copy, f to filter).
Up-arrow at the top of the strip returns focus to the main pane; Esc
also exits the split. Right/Left/Tab continue to cycle sections,
including the dedicated full-screen logs view.

View File

@@ -1,12 +0,0 @@
---
"@runfusion/fusion": minor
---
Add a sender-side "wake recipient immediately" override for messages. The
message composer now offers a checkbox (when sending to an agent) that sets
`metadata.wakeRecipient: true` on the message. When honored, the recipient
agent is woken on receipt regardless of their own `messageResponseMode`
setting. To prevent agents from forcing wakes on each other, only
human-originated messages (`fromType: "user"`) trigger the override —
agent-to-agent traffic continues to respect the recipient's configured
behavior.

View File

@@ -1,37 +0,0 @@
---
"@runfusion/fusion": patch
---
Fix worktree collisions when tasks are manually moved into in-progress.
Two related bugs caused two in-progress tasks to share a single
`.worktrees/<name>` directory:
1. The dashboard `POST /tasks/:id/move` route promoted tasks to
in-progress without allocating a fresh worktree path, so a queued
task carrying a stale `worktree` field from a prior
`preserveResumeState` requeue could land in-progress on a directory
already owned by another active task.
2. `TaskStore.moveTask({ preserveResumeState: true })` kept the
worktree pointer on requeue. When the on-disk checkout was later
removed or reassigned, the next dispatch could collide with a
worktree the scheduler had since handed to another task.
Fixes:
- `moveTask` now releases the worktree pointer on every reopen-to-todo
hop. The `branch` field is preserved so the next run reattaches via
`git worktree add <path> <branch>` and resumes any committed
progress. A new `preserveWorktree: true` option opts internal
bounces (workflow-rerun) out of the release so listeners never see
an interim `worktree=null` state.
- `moveTask` accepts an `allocateWorktree` callback that runs under a
cross-task allocation lock in `TaskStore`, building `reservedNames`
from a fresh `listTasks` snapshot so two concurrent moves cannot
pick the same name.
- The manual-move route and the scheduler dispatch path both flow
through the new allocator, sharing the lock.
- `planTaskWorktreePath` is exported from `@fusion/engine` for
consumers that need to plan worktree paths the same way the
scheduler does.