- Rework logs viewport calculation to budget by rendered rows and keep content above footer hints
- Add zero-row safety handling for short terminals with a dedicated expansion hint instead of overlapping output
- Cap wrapped log rendering by remaining row budget so long messages cannot overflow into footer space
- Add regression tests for footer-safe list windowing and wrapped-line truncation, plus a patch changeset for @runfusion/fusion
- Add reusable skill-installation helper that targets Claude, Codex, and Gemini skill homes
- Wire bundled skill installation into fn init with per-client installed/skipped/warning logging
- Add init command tests for install success, preserving existing installs, and non-fatal warning behavior
- Document the new init behavior in CLI/getting-started docs and add a patch changeset for @runfusion/fusion
- Update Fusion skill docs, prompts, and capability references to use public fn_* tool names consistently
- Align engine system prompts and tool schemas for messaging/task actions with fn_send_message, fn_read_messages, fn_task_* naming
- Refresh related tests across CLI, engine, dashboard, and core to match normalized tool naming and behavior
- Add a patch changeset for @runfusion/fusion describing the skill-tool namespace normalization
- Add explicit operation metadata to agent-generation and ai-session-store diagnostics for cleanup, recovery, and scheduled cleanup paths
- Extend dashboard guardrail coverage to explicitly enforce diagnostics protection for agent-generation.ts and ai-session-store.ts
- Stabilize plugin module reload imports by using temporary reload files with deterministic file URLs and cache updates
- Tighten CLI Vitest workspace cleanup to safely skip missing hidden dist directories during restore
- Add severity control markers to core and engine structured loggers while keeping info logs on stderr transport
- Parse and strip internal severity markers in dashboard TUI console capture so logger.log entries render with info icons instead of error icons
- Expand dashboard TUI tests to cover captured console severity mapping and structured logger behavior, plus logger unit tests in core/engine
- Add a patch changeset for @runfusion/fusion describing the TUI log severity icon fix
- Add structured ai-session diagnostics for summarize-title and agent-generation error paths in dashboard routes
- Emit debug-gated summarize request/model resolution diagnostics when FUSION_DEBUG_AI is enabled
- Add route tests that assert diagnostics payloads for summarize and agent generation failures
- Reduce test flakiness by increasing core Vitest timeouts and relaxing brittle extension-discovery argument matching
The build-exe and build-exe-cross suites invoke `bun build` in beforeAll
hooks and pegged CPU for ~6 min on every test run (one cached-on-miss
build plus three unconditional cross-target builds). Move them to a
dedicated vitest project, skip them unless CI=1 or FUSION_TEST_BUILD_EXE=1
is set, and add cache guards so CI re-runs skip rebuilds when the target
binary already exists. With build-exe out of the default cli run, the
main config can enable fileParallelism.
Run on demand via `pnpm --filter @runfusion/fusion test:build-exe`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously the vendored @fusion/pi-claude-cli extension was conditionally
loaded based on GlobalSettings.useClaudeCli. That forced a Fusion restart
every time the user toggled the provider card — confusing UX.
Key insight: pi-claude-cli registers a NEW provider id ("pi-claude-cli")
rather than overriding "anthropic", so loading it unconditionally is
safe — direct Anthropic auth and CLI-routed models coexist peacefully.
The extension also gracefully no-ops when the `claude` binary is missing
(see packages/pi-claude-cli/index.ts:106 — the throw is caught locally).
Changes:
- serve/daemon/dashboard: always append the resolved pi-claude-cli path
to discoverAndLoadExtensions, no settings lookup.
- resolveClaudeCliExtensionPaths() takes no args now; always returns the
resolved path.
- /api/models filter flipped: hide provider === "pi-claude-cli" when
the toggle is OFF (previously: restricted to those models when ON).
- POST /api/auth/claude-cli drops restartRequired semantics — toggling
now has immediate effect on the picker.
- Provider card UX updated to match: "Claude-CLI-routed models are
now visible/hidden from the model picker" instead of "Restart Fusion
to activate".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Every agent-facing quality gate that used to pair tests with typecheck now
also includes lint. Specifically:
- core/src/types.ts: QA Check skill prompt runs lint, tests, typecheck (was
tests only) and gates task_done() on all three.
- core/src/agent-prompts.ts + engine/src/reviewer.ts: "Do NOT issue REVISE"
exclusion list now covers lint as well, so out-of-scope fixes that
restore lint remain allowed (matches the already-lint-aware completion
gate text at the top of the same prompts).
- engine/src/executor.ts: task_done() pre-flight checklist adds an explicit
"if the repo has a lint command, run it and fix failures" bullet, mirrors
the typecheck bullet, and expands the CRITICAL line from "ALL test
failures" to "ALL lint, test, and typecheck failures".
- core/src/store.ts: default Step 2 checklist (Testing & Verification) now
includes Lint and Typecheck alongside "All tests pass".
- cli/src/commands/plugin-scaffold.ts: generated plugin README and the
"Next steps" CLI output include \`pnpm lint\` between install and test.
Existing prompts that already paired lint with tests+typecheck (the
Completion section, hard quality gates, triage testing requirements) are
unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- TaskCard: four catch((err: any) => err.message) promise handlers in
archive/unarchive/delete/move → catch((err) => getErrorMessage(err)).
- InlineCreateCard + QuickEntryBox: .catch((err: any)) model-load handlers
→ getErrorMessage(err) with existing @fusion/core import.
- TerminalModal: drop (navigator as any).maxTouchPoints — modern lib.dom
types already expose the property.
- serve.ts: remove unused any annotation on OpenRouter model mapper; the
array element type is already inferred from json.data.
- pi.js, runtime-resolution.ts, dashboard.ts, serve.ts, dev-server-port-
detect.ts, devserver-manager.ts: drop now-stale eslint-disable comments
that the cleanup made redundant.
Fix a prompt-builder regression surfaced by agent's `any` cleanup: toolCall
with a raw string `arguments` field must be preserved verbatim (JSON-quoted)
rather than coerced to `{}`; restores a previously-passing test.
Then promote @typescript-eslint/no-explicit-any from warn → error. Future
new anys must either come with a one-line disable + justification or use a
real type. Workspace is now lint-clean (0 problems).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Parallel subagent pass: four typescript-pro agents on non-overlapping scopes.
Patterns applied:
- catch (err: any) { ... err.message ... } → catch (err) { ... getErrorMessage(err) ... }
using the new @fusion/core helper. Bare catch {} where the error was unused.
- SQLite row types: defined typed XxxRow interfaces per table and cast
.all()/.get() results via `as unknown as XxxRow[]` (the double cast is
required because better-sqlite3 returns Record<string, SQLOutputValue>).
- rowToX(row: any) converters: typed argument with the matching row interface.
- Dynamic settings key writes: (settings as Record<string, unknown>)[key].
- React event handlers and setState callbacks: inferred types or concrete
React.{Mouse,Change,Form}Event<...> where needed.
- pi-claude-cli: local PiMessage / PiContext duck types to avoid re-typing
pi-ai concrete shapes; typed Claude stream event message fields.
72 files changed, ~400 anys eliminated. Typecheck passes across the workspace.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- no-useless-escape: drop needless backslashes in character classes and
URL/path regexes (gh-cli, store, task, modelFilter, useFileMention,
RoutineEditor, ScheduleForm).
- no-case-declarations: wrap case bodies in ProjectOverview and
SettingsModal with block scopes.
- prefer-const: convert a never-reassigned slug binding in agent-import;
annotate legitimate forward-declared let bindings in dashboard.ts that
callbacks close over before assignment.
- no-fallthrough: add missing break after settings-subcommand error.
- no-empty-interface/no-empty-object-type: convert ProjectManifest from
empty interface extension to a type alias.
- no-unused-expressions: replace `x && x.method()` short-circuits in
TerminalModal with optional chaining.
Then ratchet these rules from warn → error so regressions are blocked.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Widen config match from top-level *.cjs to **/*.cjs so nested CommonJS
scripts (e.g. mcp-schema-server.cjs) get Node globals and require() allowance.
- Replace lazy require() in claude-skills.ts with a normal top-level fs import.
- Tighten an any-typed tool map in pi-claude-cli to { name: string }.
Clears the remaining 12 lint errors; workspace now has 0 errors, 450 warnings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Eliminates no-unused-vars warnings across the CLI package by dropping
dead type imports, unused destructured helpers, and simplifying try/catch
blocks whose caught errors and intermediate results were never read.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The pi-coding-agent SDK moved from @sinclair/typebox 0.34.x to the new
typebox 1.x package in 0.69. Our direct imports in merger.ts and
extension.ts need to follow so tool schemas resolve to the same TSchema
the SDK consumes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ModelRegistry's public constructor became private in pi-coding-agent 0.64.
Direct `new ModelRegistry(...)` calls no longer compile. Switch the five
production sites to the factory (`ModelRegistry.create`) and update the
four test modules that mocked the class as a constructor to now mock it
as an object with `create` and `inMemory` static methods.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops the .kb/kb.db migration path, legacy backup filename handling, and
backward-compat test suites. Renames internal kbDir identifiers to
fusionDir and hasKbProject/isValidKbProject to their fusion equivalents.
- Remove needsCentralMigration, autoMigrateToCentral, and the
"needs-migration" FirstRunState; checkAndMigrate and KB_SKIP_MIGRATION
env var are gone
- Remove LEGACY_BACKUP_DIR and canonicalizeBackupDir; listBackups no
longer matches kb-* filenames
- Delete backward-compat.test.ts and store-backward-compat.test.ts;
update remaining tests to new 3-state first-run model
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the stray useClaudeCli settings checkbox + onboarding question
with a proper provider-card UX. The card lives next to OAuth + API-key
cards in onboarding and settings, with Enable/Disable + Test actions.
Backend:
- Vendors rchern/pi-claude-cli@0.3.1 as packages/pi-claude-cli
(MIT, attribution in UPSTREAM.md). Lets us bump peer-dep on
pi-coding-agent in lockstep with Fusion (upstream pinned ^0.52.0
vs ours ^0.62.0) and fix bugs without waiting on upstream.
- Adds @fusion/pi-claude-cli as a workspace dep of @runfusion/fusion
so users don't have to `npm install -g pi-claude-cli` manually.
- serve/daemon/dashboard conditionally load the extension via
discoverAndLoadExtensions() when GlobalSettings.useClaudeCli is on;
no side-effects on user ~/.fusion/agent/settings.json.
- New GET /api/providers/claude-cli/status: claude --version probe
+ toggle state + cached extension resolution.
- New POST /api/auth/claude-cli: flips useClaudeCli, refuses if the
claude binary is missing, fires the existing skill-backfill hook.
- /api/auth/status now injects a synthetic {id:"claude-cli", type:"cli"}
provider entry so onboarding + settings see a consistent list.
Frontend:
- New ClaudeCliProviderCard component shared between ModelOnboardingModal
and SettingsModal's Authentication section.
- New AuthProvider.type = "cli" variant.
- Removed the old "Route AI calls through the Claude CLI" checkbox from
Global Models settings and the opt-in step from the onboarding wizard.
- ProviderIcon gets a composite Anthropic-mark-plus-terminal glyph for
the claude-cli provider id.
Tests:
- 8 unit tests for extension resolution (@fusion/pi-claude-cli is
workspace-linked so these run in-tree).
- 2 unit tests for the binary probe.
- Existing /auth/status tests filter out the new synthetic entry so
they keep asserting structural OAuth/API-key behavior in isolation.
- The vendored package's own 296 tests still pass unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Assert contributing docs explicitly state that pnpm test must run without prior build outputs
- Add CI workflow test coverage to keep docs and verify:workspace ordering aligned
- Expand Vitest workspace alias assertions to include @fusion/test-utils and src-only replacements
- Validate real symbol imports from workspace packages when dist directories are absent
PUT /api/settings/global now fires an onUseClaudeCliToggled hook on an
actual transition so the UI toggle has immediate effect — serve/daemon/
dashboard wire it to ensureClaudeSkillsForAllProjectsOnStartup so every
registered project picks up .claude/skills/fusion without a restart.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PluginStore's constructor treats its rootDir arg as a project root and
internally appends `.fusion` before opening the SQLite DB. Several CLI
call sites were passing the already-resolved `.fusion` directory,
producing a doubled `.fusion/.fusion/fusion.db` that the dashboard
process kept recreating on every project load.
Pass the project root instead so the DB lands in the canonical
`.fusion/fusion.db` alongside the rest of the project's state.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PluginStore's constructor treats its rootDir arg as a project root and
internally appends `.fusion` before opening the SQLite DB. Several CLI
call sites were passing the already-resolved `.fusion` directory,
producing a doubled `.fusion/.fusion/fusion.db` that the dashboard
process kept recreating on every project load.
Pass the project root instead so the DB lands in the canonical
`.fusion/fusion.db` alongside the rest of the project's state.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add root verify:workspace script enforcing lint -> test -> build order
- Update CI workflow to run verify:workspace as the single workspace gate before binary packaging
- Add CLI guardrail tests for workflow sequencing and root script contract invariants
- Document deterministic workspace bootstrap expectations in contributing guide
- Clarify bundle-output test bootstrap intent for explicit artifact setup
- Convert internal @fusion workspace aliases in packages/cli/vitest.config.ts to exact anchored regex entrypoint mappings
- Preserve subpath-before-root alias order so @fusion/core/gh-cli and @fusion/dashboard/planning resolve correctly
- Add vitest-workspace-resolution regression coverage for alias definitions and ordering
- Simulate clean worktrees by temporarily hiding internal dist/ directories and verify dynamic imports resolve from source
- Add a shared runtime logger contract and dashboard runtime logger implementation for structured diagnostics
- Route dashboard CLI/runtime logs through the TUI sink and replace ad-hoc console diagnostics in server paths
- Update CLI and dashboard tests to assert structured runtime logging behavior across sync and error flows
- Document the structured logging architecture updates and include a changeset for @runfusion/fusion
- Add shared test setup helpers that always build dashboard client assets before assertions run
- Remove skip-gated build-output tests and make CLI/dashboard suites deterministic by owning artifact setup
- Enforce hashed vendor chunk naming checks for vendor-react and vendor-xterm in generated assets
- Verify copied CLI client index references real built chunks and does not contain the dashboard stub marker
- Update AgentImportModal preview to preselect all agents and skills, support per-item toggles plus select-all/clear controls, and keep directory preview enabled when parsed files exist.
- Send selectedAgents and selectedSkills from paste, directory, and browse import flows, with dynamic import CTA labels and guardrails when nothing is selected.
- Extend /agents/import to accept selection filters, allow skill-only imports, and parse downloaded company archives directly without shell tar extraction.
- Expand dashboard import tests to cover directory parsing, subset selection, browse-mode skill visibility, and related UI/style assertions.
- Restore full-suite CLI test reliability by adding workspace alias mappings in vitest config and retrying slow cross-platform binary help probes.
The dashboard TUI Logs tab only showed the handful of lines emitted
through DashboardLogSink directly. Everything from @fusion/engine
(scheduler, executor, triage, merger, PR monitor, heartbeat, etc.)
logs via createLogger() which writes straight to console.error —
bypassing the sink. Under the TUI's alt screen those writes either
overdrew the frame or scrolled off, leaving the Logs tab near-empty.
DashboardLogSink now offers captureConsole() / releaseConsole():
while the TUI is running, console.log/warn/error are intercepted
and routed into the ring buffer. A leading `[prefix]` tag is
extracted so entries carry the subsystem name. Original console
functions are restored (by identity) on TUI shutdown.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Keep the Logs tab viewport anchored to selection so users can navigate the full in-memory ring buffer with arrow keys and Home/End
- Route streamed merge agent text through the dashboard log sink via a buffered line assembler to avoid raw fragment writes in TTY mode
- Expand dashboard and dashboard-tui command tests to cover viewport behavior, expanded log interactions, and streamed merge log handling
- Update CLI reference docs and add a @runfusion/fusion patch changeset describing the TUI log behavior fixes
- Reorder dashboard TUI sections so System is tab [1] and the initial active view
- Update header rendering across wide, medium, and narrow terminal layouts to reflect the new tab order
- Expand dashboard TUI tests to assert system-first labels and default active section behavior
- Document system-first startup behavior in CLI reference and add a patch changeset for @runfusion/fusion
- Raise mobile .toast-container bottom offset by adding --space-2xl to clear footer/nav overlap
- Update utility-mobile CSS regression assertion to match the new toast offset formula
- Extend build-exe test timeout from 20s to 90s to reduce flaky CLI packaging failures
- Add rich Logs tab keyboard controls including arrow/j-k movement, Home/End jumps, and Enter/Space/e expansion toggles
- Introduce expanded log inspection view with escape-to-close behavior and wrap mode support for long entries
- Improve log wrapping to hard-wrap long unbroken tokens like URLs and stack traces at terminal width
- Expand dashboard TUI command tests and document the new interactive log navigation shortcuts in CLI reference
- Add two patch changesets for @runfusion/fusion covering log inspection and navigation fixes
- Add buildHelpLines() to construct box and compact help overlay rows from shared width-safe logic
- Replace manual padRight-based row padding with visibleLength-driven padding for consistent right border alignment
- Compute overlay centering from raw uncolored line widths and apply coloring during render
- Add targeted tests validating box row geometry, border width consistency, and padding calculations
The Plugin Manager section had a global .settings-section-heading { margin: 0; }
rule that was unintentionally removing margins from all settings pane headings,
not just plugin detail headings. Scoped the rule to .plugin-settings-form so
other settings panes inherit the base spacing again.
- Update dashboard TUI header copy from "fn board" to "fusion" branding
- Add CLI tests that validate the new header text and related rendering behavior
- Include a changeset documenting the published @runfusion/fusion patch for the branding update
- Add a new dashboard TUI renderer with logs, system, utilities, stats, and settings sections
- Wire runDashboard to auto-enable TUI in TTY sessions with reactive task/agent updates and utility keybindings
- Keep non-TTY behavior unchanged by falling back to the existing plain-text startup output
- Add CLI tests and docs for TUI behavior, keyboard shortcuts, and auth/usage guidance
- Ensure dashboard WebSocket auth checks respect --no-auth consistently
Three orthogonal fixes bundled together so they re-land as a unit after
earlier worktree-based reverts kept wiping them individually.
1. `--no-auth` flag now actually disables auth. Previously a stale
FUSION_DAEMON_TOKEN in .env silently re-armed bearer-token auth despite
the CLI flag. Added a `noAuth` option to ServerOptions; auth-middleware's
isDaemonAuthActive/getDaemonToken short-circuit to false/undefined when
set; CLI plumbs opts.noAuth through both createServer call sites.
2. Workflow review failures no longer reset every completed step. Previously
a single CSS nit from a workflow reviewer could drag 5+ already-approved
steps back through plan review, code review, and re-execution because
determineRevisionResetStart fuzzy-matched feedback tokens against step
names. handleWorkflowRevisionRequest, handleWorkflowStepFailure, and
sendTaskBackForFix now call a new reopenLastStepForRevision helper that
flips only the last non-pending step back to pending (with currentStep
rewind via a newly-accepted updateTask field) — all earlier done steps
stay done, and the agent applies the feedback as an in-place patch per
the updated PROMPT.md instructions. determineRevisionResetStart stays
exported as @deprecated so existing unit tests still link.
3. Heartbeat scheduling is now state-driven. Previously a non-ephemeral
agent with a stale runtimeConfig.enabled=false on disk would never tick
and the Pause/Resume button couldn't arm the timer without also flipping
that hidden flag. HeartbeatTriggerScheduler's watchAgentLifecycle now
registers on transitions into active/running and clears on transitions
out; the tick and assignment-trigger guards key off state + ephemeral
classification. InProcessRuntime's created/updated listeners and startup
scan mirror the same semantics. runtimeConfig.enabled is only retained
for ephemeral (task-worker) opt-out.
Tests updated: agent-heartbeat.test.ts — one test renamed from "skips
registration when enabled is false" (obsolete behavior) to
"registers regardless of the legacy enabled flag"; 4 assignment-watching
tests now pass a realistic `state: "active"` on mock agents. 207 heartbeat
tests + 330 executor tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On loaded CI hosts the bundled binary occasionally takes longer than the
15s timeout to warm up, causing a SIGTERM and a flaky failure even though
the build is healthy. Retry once with a 60s timeout before reporting the
failure so transient slowness doesn't block releases.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add termination-driven cleanup in InProcessRuntime so ephemeral agents are disposed when the runtime terminates
- Extend in-process runtime tests with comprehensive coverage for ephemeral cleanup behavior and lifecycle expectations
- Fix ephemeral termination cleanup assertions to align test checks with actual teardown semantics
- Update CLI tests to skip obsolete changeset validation and reduce flakiness in binary timeout handling
- Fetch unread inbox messages whenever messageStore is available, not only wake-on-message triggers
- Include pending messages in execution prompts for task and no-task heartbeat runs across timer, assignment, and on-demand sources
- Extend heartbeat messaging tests to cover run-wide mailbox prefetch and read-marking behavior
- Document heartbeat mailbox checking semantics and messageResponseMode behavior in agents docs
- Replace Header mailbox badge class with existing header-badge style token
On every CLI invocation, parse .env (and .env.local if present) from
the working directory into process.env before dispatching to command
handlers. Existing shell-exported variables always win — the loader
never clobbers an explicitly-set value. .env.local overrides .env.
Motivation: FUSION_DAEMON_TOKEN (and soon other config knobs) is more
ergonomic as a gitignored local file than as a shell export each
session. Without this, `fn dashboard` falls back to auto-generating a
new token on every restart, which means the banner URL changes every
time and stale localStorage tokens silently return 401 on every API
call.
SSE and WebSocket clients already carry the token via appendTokenQuery
(fn_token= query-string fallback, since EventSource and WebSocket
constructors cannot set Authorization headers) — verified: every
`new EventSource` and `new WebSocket` call site is wrapped.
Hand-rolled minimal parser (no new dependency) to keep the bundled
single-binary CLI lean. Supports KEY=value, quoted values, comments,
blank lines.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-release polish. Two related changes bundled because they both land the
project on public-release footing:
Dashboard auth
- fn dashboard now gates the HTTP API + terminal/badge WebSockets behind a
bearer token by default. Token resolution order: --token flag,
FUSION_DASHBOARD_TOKEN env, FUSION_DAEMON_TOKEN env (back-compat), or an
auto-generated fn_<32 hex>. --no-auth disables. The startup banner prints
a click-to-open URL with ?token=<token> embedded.
- Auth middleware now also accepts fn_token=<token> as a query-string
fallback so EventSource and WebSocket clients (which can't set custom
headers) still authenticate.
- setupTerminalWebSocket / setupBadgeWebSocket now refuse unauthenticated
upgrades with a proper 401 + socket close.
- Frontend: new auth.ts module captures ?token= off the URL into
localStorage (key fn.authToken), strips it from the visible URL via
replaceState, and installs a window.fetch wrapper that injects
Authorization: Bearer <token> on every same-origin /api/* request.
EventSource/WebSocket URL builders (api.ts, sse-bus.ts, useTerminal,
useBadgeWebSocket) route through appendTokenQuery().
MIT license
- LICENSE file at repo root.
- license: "MIT" on root package.json and every packages/*/package.json,
plus description/bugs metadata on the CLI package.
Docs
- docs/cli-reference.md documents --token / --no-auth / FUSION_DASHBOARD_TOKEN
and the click-to-open auth flow.
- docs/getting-started.md, docs/docker.md, README.md point at the new flow
and the CLI reference section.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the engine restarts mid-step, an in-progress step may have already
passed plan + code review but not yet been flipped to done by the agent's
next task_update call. Previously, the next executor pass re-entered the
step and replayed both reviews — measured at 5-20 min of pure waste per
restart (observed in FN-2215 Step 1 and FN-2207 Step 6).
recoverApprovedStepsOnResume scans the task log for any in-progress step
whose most recent "code review Step N: APPROVE" entry is newer than its
most recent "Step N → pending" transition, and marks those steps done
before execute() runs. Safely skips steps that were reset after approval
(e.g. by a workflow revision) or only received REVISE verdicts.
Called from both the engine-restart path (resumeOrphaned) and the
unpause path, matching the two places the task log shows as vulnerable
to this race.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Move the assigned agent badge out of the card header into a dedicated metadata row below task details
- Add a new .card-agent-row container to control spacing and alignment for the badge block
- Update .card-agent-badge styling to use token-aligned pill radius and color-mix backgrounds while removing monospace/fixed-width conventions
- Expand TaskCard agent badge tests to verify new DOM placement and enforced badge style rules