The desktop embedded runtime auto-registered its runtime root (the user's HOME directory) as a
project on first launch, and bare `fusion` / `fn` / `fn dashboard` / `fusion dashboard`
auto-registered the CWD as a project. Both silently created a "cwd-mode" project the operator
never chose and dropped them onto a board for it.
- Desktop: replace ensureDesktopRuntimeProject (which registered home) with
resolveDesktopRuntimePrimaryProject, which only PICKS an already-registered project as the
primary engine target and registers nothing. With no projects the server starts engine-less
(createServer's engine is optional) and the dashboard shows its onboarding empty state.
Applied to both the primary (local-runtime) and legacy (local-server) desktop server paths.
- CLI dashboard command: ensureCwdProjectRegistered now runs with autoRegister:false, so it uses
the CWD project only if already registered, else starts with none and the dashboard onboards.
(serve/daemon keep their existing --no-auto-register flag; the CLI `desktop` launcher unchanged.)
Verified: with zero projects the embedded server starts, /api/health -> 200, /api/projects -> [],
/ serves the client. Unit test asserts resolveDesktopRuntimePrimaryProject registers nothing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two Windows-only breakages in the build path:
- scripts/build-workspace.mjs: the "run as main" guard compared import.meta.url
to `file://${process.argv[1]}`, which never matches on Windows (import.meta.url
is file:///C:/… with forward slashes and a triple slash; argv[1] is C:\… with
backslashes and no scheme). So `pnpm build` at the repo root silently no-opped
(exit 0, no output, no dist) and packaging shipped empty/stale dist. Compare
against pathToFileURL(process.argv[1]).href instead.
- scripts/build-workspace.mjs runPlannedBuilds and packages/cli/tsup.config.ts
runWorkspaceCommand spawned `pnpm` without shell:true; on Windows pnpm is a
.cmd shim Node refuses to spawn without a shell (ENOENT/EINVAL, CVE-2024-27980),
failing with `spawn pnpm ENOENT`. Pass shell on win32 (args are fixed repo build
invocations with no shell metacharacters).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Prevent task-bound callers from soft-deleting the task they are currently executing.
- Add a TaskSelfDeleteError guard in TaskStore.deleteTask before mutation or audit emission.
- Pass the current task id through the fn_task_delete audit context so CLI tool calls inherit the store invariant.
- Cover self-delete rejection and cross-task deletion allowance in core and CLI tests.
- Add a patch changeset for the published CLI package.
Files changed:
.changeset/fn-7411-self-delete-guard.md | 7 +++
.../task-delete-allow-resurrection.test.ts | 48 ++++++++++++++++-
packages/cli/src/extension.ts | 2 +
.../src/__tests__/store-self-delete-guard.test.ts | 60 ++++++++++++++++++++++
packages/core/src/store.ts | 22 +++++++-
5 files changed, 136 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-7411
Fusion-Task-Lineage: 50028769-5396-4435-84fb-2ae182315e81
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Add TaskExecutor.blockOuterDispatchWhenEphemeralDisabled, gating all three
workflow dispatch paths (graph / authoritative / work-engine) on
ephemeralAgentsEnabled at the top of execute(). Previously the toggle was
enforced only on the legacy scheduler/EphemeralWorkerManager path — whose
onTaskStart spawn refusal is a fire-and-forget callback that runs after
execution begins — so unassigned tasks reaching execute() off a non-scheduler
path still ran. Unassigned tasks are now re-queued for permanent-agent
assignment; permanent-agent-bound tasks still run. Adds regression coverage
across all three entry points.
Also includes the ephemeralAgentsCanCreateTasks project setting (default on)
gating fn_task_create for ephemeral callers in both the pi extension and the
executor task-worker tool.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary
- keep malformed planning-session responses persisted as retryable error
state instead of deleting the session
- add `fn dashboard --supervise` to restart unexpected dashboard exits
with bounded exponential backoff
- document the supervised-dashboard run mode and add a patch changeset
## Test Plan
- `corepack pnpm --filter @runfusion/fusion exec vitest run
src/commands/__tests__/dashboard.test.ts --silent=passed-only
--reporter=dot`
- `corepack pnpm --filter @fusion/dashboard exec vitest run
src/__tests__/session-error-recovery.test.ts --silent=passed-only
--reporter=dot`
- `corepack pnpm --filter @fusion/dashboard exec vitest run
src/__tests__/server.test.ts -t "returns health OK independently"
--silent=passed-only --reporter=dot`
- `corepack pnpm lint`
- `corepack pnpm typecheck`
- `corepack pnpm build`
- `corepack pnpm test:gate`
Note: a full `server.test.ts` run also exposes four existing
routine-runner expectation failures unrelated to this change; the added
health check passes when run by name.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added dashboard supervised mode via a new `--supervise` option, with
automatic restarts using a bounded restart budget and exponential
backoff.
* **Bug Fixes**
* Planning sessions now persist as retryable error states when AI output
can’t be parsed, preventing session loss.
* Improved reliability so `GET /api/health` remains available during
these planning error states.
* **Documentation**
* Documented “Dashboard Availability &amp; Supervised Mode”,
including health-check guidance and operational guardrails.
* **Tests**
* Added test coverage for supervised restart behavior, health during
planning errors, and ensuring no unhandled rejections on parse failures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
Task image artifacts can now complete the full loop: agents and chat
flows can register base64 image bytes, and task details can display
those artifacts with an expandable preview instead of leaving them as
undiscoverable metadata.
This keeps binary payloads on the existing managed artifact storage
path, validates that base64 payloads are real non-empty image data, and
documents the new `dataBase64` field for engine-tool callers. The task
details artifacts gallery now treats image cards as expandable while
leaving document, audio, video, and generic artifact cards on their
existing behavior.
## Validation
- `pnpm --filter @fusion/dashboard exec vitest run
app/components/__tests__/TaskDocumentsTab.test.tsx
src/routes/__tests__/artifacts-route-integration.test.ts
--silent=passed-only --reporter=dot`
- `pnpm --filter @fusion/engine exec vitest run
src/__tests__/agent-artifact-tools.test.ts --silent=passed-only
--reporter=dot`
---
[](https://github.com/EveryInc/compound-engineering-plugin)

<!-- stage-review-badge-begin -->
---
<a href="https://stagereview.app/Runfusion/Fusion/pull/1821">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://stagereview.app/assets/gh-open-in-stage-dark.svg">
<img src="https://stagereview.app/assets/gh-open-in-stage-light.svg"
alt="Open in Stage">
</picture>
</a>
<!-- stage-review-badge-end -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added inline base64 (`dataBase64`) support for registering image
artifacts from agent tools, including task-scoped chat registration.
* Task details now allow expanding image media artifacts in a preview
lightbox with accessible keyboard interaction.
* **Bug Fixes**
* Improved verification for media streaming by validating raw binary
responses; added HTTP 200/404 coverage for image endpoints.
* **Documentation**
* Updated `fn_artifact_register` tool documentation to include the
optional `dataBase64` parameter.
* **Tests**
* Added coverage for base64 validation/error handling and lightbox
expand/close behavior (including Escape and Tab focus trapping).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Root cause of "the TUI keeps rendering after I get my terminal back": on
quit, dispose() called logSink.releaseConsole() (re-pointing console.* at
the real terminal) and then tui.stop() left the alt-screen and restored the
user's shell. Every log line from the slow engine/mesh/dev-server teardown
that followed then painted over the recovered prompt.
dispose() now calls a new logSink.silence() instead, which drops all sink
and console.* output from quit through process exit. Shutdown-step
diagnostics (timeShutdownStep + the watchdog stall line) are gated behind
FUSION_DEBUG_SHUTDOWN so a normal quit is pristine; the 3s hard-exit
watchdog still guarantees the process dies.
Adds a silence() regression guard to log-sink.test.ts asserting sink
methods and captured console.* both go silent across surfaces.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
runSkillsInstall already awaits the spawned child exit event, so the
fixed 100ms post-await sleeps were redundant wall-clock time (FN-5048).
Removes ~400ms of dead waits; assertions unchanged, 22 tests still pass.
Fix PR-mode auto-merge status checks to query GitHub with the project repository.
- Resolve the current project owner/repo once from the task cwd before PR status checks.
- Pass owner/repo/number to getPrMergeStatus for shared-group, task, and retry paths.
- Cover repository resolution and PR status argument behavior in lifecycle tests.
- Add a patch changeset for the published CLI fix.
Files changed:
.changeset/FN-7133-pr-merge-status-repo-args.md | 7 ++++
.../src/commands/__tests__/task-lifecycle.test.ts | 39 +++++++++++++++++++++-
packages/cli/src/commands/task-lifecycle.ts | 17 +++++++---
3 files changed, 58 insertions(+), 5 deletions(-)
Fusion-Task-Id: FN-7133
Fusion-Task-Lineage: 3f9bfd65-6950-40dc-9505-53140bd6a6a1
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Each graceful-shutdown teardown step (dev servers, hybrid executor,
engine manager, peer exchange, mesh, central-core) now runs through
timeShutdownStep, which records the in-flight step name. A hang leaves
that name set, so the hard-exit watchdog reports the exact culprit on
stderr before force-exiting — no repro needed. Per-step timings print to
stderr under FUSION_DEBUG_SHUTDOWN=1; otherwise only steps slower than
1s are surfaced. Folds the per-step try/catch into the wrapper so a
throwing step logs and continues instead of stranding the process.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pressing q/Ctrl+C in the TUI routes through SIGINT so the dashboard's
graceful shutdown runs (kills dev-server process groups, engines, mesh,
central-core). That shutdown awaits several teardown steps with no
timeout, so a single hung step left process.exit(0) unreachable: the
process never exited and the still-alive dashboard kept writing output
onto the restored shell. The shutdownInProgress guard also swallowed
repeat signals, so mashing q could not escape.
Both shutdown() and devShutdown() now arm an unref'd 3s hard-exit
watchdog on the first signal and force an immediate process.exit(0) on a
second signal.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Quarantine test files consistently failing on the non-blocking full-suite
CI on main, per the AGENTS.md deletion-ratchet policy:
Engine-default (shard 1-2): ce-workflow-step-conventions,
executor-column-agent-principal, restart.integration,
scheduler-node-unreachable-audit, scheduler-overlap-starvation,
scheduler-ephemeral-toggle, user-configured-command-no-execsync
Engine-reliability (shard 1): lease-recovery-central-claim,
owning-node-unavailable-interactions, todo-inprogress-flapping
CLI (shard 3): extension.test.ts
Each has a matching entry in scripts/lib/test-quarantine.json with the
failing CI run link and quarantinedAt date. Tests will be deleted
after 14 days unless rescued with a root-cause fix.
Sanitize published CLI plugin manifests so off-workspace installs do not resolve private workspace packages.
- Add manifest sanitization for copied bundled plugins and vendored pi extensions during the CLI build.
- Cover built plugin and extension package.json files with a pack-shape regression test.
- Update plugin authoring docs and add a patch changeset for the published CLI fix.
Files changed:
.../fn-7060-fix-plugin-manifest-workspace-deps.md | 7 ++
docs/PLUGIN_AUTHORING.md | 8 ++-
.../cli/src/__tests__/plugin-pack-shape.test.ts | 55 +++++++++++++-
packages/cli/tsup.config.ts | 83 ++++++++++++++++++++--
4 files changed, 142 insertions(+), 11 deletions(-)
Fusion-Task-Id: FN-7060
Fusion-Task-Lineage: e38a4237-7197-4bc4-87bd-117dfd35a0f8