Adds durable heartbeat model fallback logic to the engine's heartbeat subsystem (`agent-heartbeat.ts`, `agent-session-helpers.ts`, `pi.ts`), allowing heartbeats to gracefully use alternative AI models when the primary model is unavailable, with documentation updates to `agents.md` and `settings-refe
Fusion-Task-Id: FN-3914
- Add resolveMergerSessionModel helper to centralize merger model selection precedence
- Route merger session creation paths through the helper for commit, push/rebase, and autostash recovery flows
- Add comprehensive engine tests for merger model resolution and fallback behavior
- Document merger model hierarchy in settings reference and add a patch changeset for @runfusion/fusion
Fusion-Task-Id: FN-3892
Implements assigned-agent triage inheritance (FN-3703), allowing triage logic to be delegated to the assigned agent rather than always routing through the original owner, with test coverage and documentation. Also adds immediate wake controls for agent inbox and message API (FN-3087), wires shared s
Fusion-Task-Id: FN-3703
This merge delivers five major feature clusters: a fully rebuilt dependency graph plugin with draggable nodes, position persistence, modular architecture, highlighting and selection states, toolbar navigation, and keyboard controls; a new roadmap plugin with domain store, ordering logic, and compreh
Fusion-Task-Id: FN-3581
Merges five commits implementing centralized runtime skill forwarding that preserves Fusion context across the Hermes runtime layer. The engine's `agent-runtime` and `agent-session-helpers` were updated to forward skills at runtime, with `runtime-adapter.ts` and its types extended to carry context.
Fusion-Task-Id: FN-3612
Heartbeat read non-existent split modelProvider/modelId fields while the
dashboard saves runtimeConfig.model as combined "provider/modelId", so
sessions fell through to pi's default model and failed with
"No API key for provider: openai-codex". Add extractRuntimeModel helper
that prefers the combined string and use it from heartbeat.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
Replace lazy `await import("./pi.js")` and `require("./pi.js")` calls in
runtime-resolution, agent-session-helpers, agent-heartbeat, and
cron-runner with top-level static imports. These dynamic imports were
documented as plugin-decoupling, but pi.js is already eagerly loaded
through index.ts re-exports and static imports in executor/merger/
reviewer/triage/mission-execution-loop, so the deferral never paid off
in practice.
The deferral did, however, introduce a TOCTOU race: a tsc rebuild that
momentarily emptied dist/pi.js would let the engine load fine and only
fail minutes later when the first session was created (e.g. FN-2860
errored two minutes into execution while pi.js was being rewritten).
With static imports, a missing/half-built dist now fails immediately at
process startup with a clear stack — verified by `mv dist/pi.js
dist/pi.js.bak` reproducing ERR_MODULE_NOT_FOUND on the first import of
runtime-resolution.js.
Also drops the DefaultPiRuntime.describeModelFn cache, which only
existed to paper over the require-on-first-call latency.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Hermes / OpenClaw plugin index.ts now re-export `probeHermesBinary` /
`probeOpenClawBinary` and their status types so the dashboard's
`runtime-provider-probes.ts` façade can import them via the public
package entry instead of deep paths.
- Dashboard `package.json` adds `@fusion-plugin-examples/hermes-runtime`,
`…/openclaw-runtime`, `…/paperclip-runtime` as workspace deps so
pnpm symlinks them into `packages/dashboard/node_modules/`. Without
these, the new probe imports failed with "Cannot find module" during
`pnpm typecheck`.
This clears 6 of the 9 outstanding typecheck errors. The remaining 3 are
in the in-flight Hermes plugin rewrite (runtime-adapter still imports
from a deleted `./pi-module.js`; the new `index.ts` calls a factory
with the wrong arg type) and should be resolved by the same change set
that landed the rewrite.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Clears the remaining no-unused-vars warnings across the dashboard app and
server, desktop main, and engine sources. Dead React state destructures are
collapsed to setter-only, unused props are underscore-prefixed to preserve
API shape, and unreferenced catch bindings are dropped. No behaviour change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>