Commit Graph

742 Commits

Author SHA1 Message Date
Fusion
6d2cf27410 feat(FN-2621): guard execution for non-git project directories
- Add isGitRepository utility in worktree-pool using git rev-parse checks
- Fail fast in TaskExecutor with actionable non-git errors before worktree creation starts
- Classify not-a-git-repository worktree add failures as non-retryable in recovery flows
- Warn from in-process runtime startup when the working directory is not a Git repository
- Expand executor and worktree-pool tests to cover non-git, missing-dir, and conflict-classification paths
2026-04-26 22:20:17 -07:00
Fusion
c62e1d7595 feat(FN-2624): surface task token usage on task cards
- Render a compact token usage indicator in TaskCard footer with accessible labeling and token-aware styling
- Track token usage fields in the TaskCard memo comparator and expose a comparator test helper for regression coverage
- Add TaskCard tests for token usage rendering behavior and comparator invalidation on token usage updates
- Configure runtime plugin Vitest setups with an @fusion/engine source alias for reliable workspace test resolution
- Keep restart integration child_process spawn mocking aligned with execSync-driven merge verification behavior
2026-04-26 21:45:46 -07:00
gsxdsm
5162531275 chore(release): v0.6.0
Version bump via changesets.
2026-04-26 21:27:49 -07:00
gsxdsm
53decd1bd2 fix(engine): cap verification-failure bounces, reap unregistered worktrees, dedupe activity log
Three fixes for the worktree-overflow / stuck-task incident:

1. Cap deterministic-verification-failure bounces (fix #2)
   Auto-merge previously bounced an in-review task back to in-progress
   on every verification failure with no upper bound. A single flaky test
   could keep a task ping-ponging in-review→in-progress forever, holding
   its worktree and consuming agent slots. Adds verificationFailureCount
   on Task (DB migration v48), increments on each bounce, and after 3
   failures marks the task failed and creates a follow-up triage task
   so a fresh agent can investigate the underlying flake instead of
   re-running the same fix loop.

2. Reap unregistered orphan worktree dirs even when recycle is on (fix #3)
   cleanupOrphans previously bailed out entirely when recycleWorktrees
   was true, leaving stale dirs (clear-hawk-broken, *-bak, leftover
   crash debris) on disk forever. New reapUnregisteredOrphans pass
   removes only directories that aren't registered git worktrees, so
   the recycle pool keeps its warm worktrees but the trash gets cleared.

3. Idempotence guard on activity-log listener wiring (fix #6)
   setupActivityLogListeners() was registering handlers on every call.
   When init() ran twice, every task:created / task:moved event wrote
   N rows to activityLog, producing the duplicate entries visible in
   the DB. Added activityListenersWired flag so repeated calls no-op.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 21:09:28 -07:00
gsxdsm
07e86e696d test(engine): mock spawn so verification runner works under restart suite
9c7c8ee5 switched merger verification from exec to spawn-based
execWithProcessGroup, but restart.integration.test.ts only mocked
execSync/exec. spawn() returned undefined, so the merger crashed before
running the test command and any in-review merge test that hit the
verification path failed with VerificationError.

Adds a spawn mock that funnels through the existing execSync mock so a
single mockedExecSync.mockImplementation continues to control both git
calls and verification command outcomes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 21:01:27 -07:00
gsxdsm
4ccc8aed11 fix(engine): make global pause actually stop in-flight verification
Hitting Stop (globalPause) disposed the AI merge agent session but left
the spawned `pnpm test` / `pnpm build` child processes running until
they finished naturally. With recurring flaky-test loops at Step 5,
that meant Stop had no visible effect — new test runs kept piling up
across multiple worktrees.

Two gaps:
- project-engine.ts onGlobalPause never called mergeAbortController.abort(),
  so subsequent verification commands (gated by the signal) weren't cancelled.
- merger.ts execWithProcessGroup only listened to its own internal
  timeout — passing an AbortSignal had no effect on the in-flight
  child process group.

Fix: abort the controller on global pause, and have execWithProcessGroup
SIGTERM/SIGKILL the detached process group when its signal aborts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 20:51:40 -07:00
Fusion
32e7ce6f5f feat(FN-2614): merge fusion/fn-2614 (auto-resolved)
- fix(FN-2614): restore workspace green verification gates
2026-04-26 19:26:25 -07:00
gsxdsm
1dddf3252c chore(release): v0.5.0
Manual version bump to 0.5.0 (changeset version produced 1.0.0 from a
single minor changeset against 0.4.1; that release was rolled back and
the 1.0.0 npm version deprecated).

Aggregates: status terminology refresh (planning/replan), Reviewer
rename, in-review pause behavior, dashboard-tui resize hardening,
dev-server experimental toggle fix, version reporting fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 17:31:46 -07:00
gsxdsm
45002257fd Revert "chore(release): v1.0.0"
This reverts commit 26e09c7aa0.
2026-04-26 17:26:56 -07:00
gsxdsm
26e09c7aa0 chore(release): v1.0.0
Version bump via changesets.
2026-04-26 17:25:49 -07:00
Fusion
c4abf39774 feat(FN-2617): merge fusion/fn-2617 (auto-resolved)
- test(FN-2617): stabilize workflow remediation timeout under full suite
- test(FN-2617): complete Step 5 — add openclaw runtime resolution coverage
- feat(FN-2617): complete Step 4 — route step sessions through runtime resolution
- fix(FN-2617): thread runtimeHint through merger rebase push flow
- feat(FN-2617): complete Step 3 — wire runtimeHint across engine subsystems
- feat(FN-2617): complete Step 2 — thread runtimeHint in executor paths
- feat(FN-2617): complete Step 1 — add runtimeHint extraction helper
2026-04-26 16:14:35 -07:00
gsxdsm
9c7c8ee586 fix(merger): bump verification timeout to 10m and reap process group
The 5-minute exec timeout only killed the immediate shell, leaving
vitest/pnpm worker trees alive. Across retries these accumulated and
thrashed the host, starving the engine and TUI. Switch verification to
spawn-based runner with detached process group so timeouts SIGTERM the
whole tree (SIGKILL after 5s grace), and bump the wallclock to 10m for
larger workspaces. Stream-truncate output instead of relying on ENOBUFS.

Also fix two flaky/race-prone dashboard tests that were red on main and
blocking every in-review task at merge verification.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 16:05:40 -07:00
Fusion
56b4386b9c feat(FN-2613): merge fusion/fn-2613 (auto-resolved)
- fix(FN-2613): restore green CI after static engine import changes
- test(FN-2613): complete Step 3 — update mobile and standalone CSS assertions
- feat(FN-2613): complete Step 2 — move standalone token override to global styles
2026-04-26 15:53:50 -07:00
Fusion
2af05119d1 feat(FN-2615): merge fusion/fn-2615 (auto-resolved)
- fix(FN-2615): restore workspace lint and test stability
2026-04-26 15:51:44 -07:00
Fusion
24221cc227 feat(FN-2614): merge fusion/fn-2614 (auto-resolved)
- fix(FN-2614): restore workspace green verification gates
2026-04-26 15:43:07 -07:00
Fusion
112813f122 feat(FN-2615): merge fusion/fn-2615 (auto-resolved)
- fix(FN-2615): restore workspace lint and test stability
2026-04-26 15:16:22 -07:00
Fusion
ab09a42b23 feat(FN-2616): merge fusion/fn-2616 (auto-resolved)
- feat(FN-2616): complete Step 5 — pass full quality gates
- test(FN-2616): complete Step 4 — add Hermes plugin integration tests
- test(FN-2616): complete Step 3 — add Hermes engine integration coverage
- feat(FN-2616): complete Step 2 — align Hermes adapter option contract
2026-04-26 14:54:46 -07:00
gsxdsm
544d8d77e3 fix(dashboard,core,engine): statically import @fusion/engine to fix createFnAgent undefined in published CLI
The dashboard modules used a variable-specifier dynamic import
(`const m = "@fusion/engine"; await import(m)`) to defeat bundler static
analysis. tsup honored that and left the dynamic import in dist/bin.js,
so the published `@runfusion/fusion` package failed at runtime with
"createFnAgent2 is not a function" — `@fusion/engine` isn't on npm and
the silent catch set the binding to undefined. Replaces the trick with
static imports across planning, chat, subtask-breakdown, mission-interview,
agent-generation, ai-refine, roadmap-suggestions, milestone-slice-interview,
and routes. Core can't statically import engine (cycle), so it now exposes
setCreateFnAgent and engine wires itself in at module load. Documents the
pattern in AGENTS.md.

Fixes Runfusion/Fusion#9.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 14:43:03 -07:00
Fusion
79ce48c51e feat(FN-2608): merge fusion/fn-2608 (auto-resolved)
- feat(FN-2608): complete Step 6 — verify lint test build gates
- feat(FN-2608): complete Step 5 — resume auto-merge on in-review unpause
- feat(FN-2608): complete Step 4 — pause-aware self-healing recovery
- feat(FN-2608): complete Step 3 — interrupt active merges on pause
- feat(FN-2608): complete Step 2 — guard auto-merge for paused review tasks
- feat(FN-2608): complete Step 1 — pause status for in-review tasks
2026-04-26 13:39:27 -07:00
Fusion
429b9671b2 feat(FN-2606): merge fusion/fn-2606 (auto-resolved)
- fix(FN-2606): complete Step 4 — clean up mkdtemp test directories
- test(FN-2606): complete Step 3 — add isolation guard coverage
- feat(FN-2606): complete Step 2 — add engine/dashboard HOME test isolation setup
2026-04-26 13:00:56 -07:00
Fusion
bbc872cee9 feat(FN-2603): merge fusion/fn-2603 (auto-resolved)
- test(FN-2603): update downstream tests for planning label expectations
- test(FN-2603): complete Step 6 — update engine tests for planning terminology
- feat(FN-2603): complete Step 5 — rename self-healing planning APIs
- feat(FN-2603): complete Step 4 — rename needs-respecify status to needs-replan
- feat(FN-2603): complete Step 3 — rename specifying and re-specification text
- feat(FN-2603): complete Step 2 — rename triageLog usages to planLog
- feat(FN-2603): complete Step 1 — rename triage logger to plan logger
- feat(FN-2602): complete Step 7 — add release changeset
- test(FN-2602): complete Step 6 — align migration and schema tests
- test(FN-2602): complete Step 5 — update store status assertions
- feat(FN-2602): complete Step 4 — rename triage prompt labels
- feat(FN-2602): complete Step 3 — add status rename migration
- feat(FN-2602): complete Step 2 — rename respecify status literals
- feat(FN-2602): complete Step 1 — rename triage display labels
2026-04-26 12:45:05 -07:00
gsxdsm
80514718ed chore(release): v0.4.1
Version bump via changesets.
2026-04-26 12:24:08 -07:00
gsxdsm
ec3e2cb280 fix(FN-2586): restore 0.4.x release line and agent log stability 2026-04-26 12:22:06 -07:00
gsxdsm
b5200ba81b feat(FN-2586): merge fusion/fn-2586 2026-04-26 11:49:43 -07:00
Fusion
c3f522c8e9 fix(FN-2583): persist token usage on step completion
- Persist task token usage asynchronously whenever a step completes in StepSession execution
- Log non-fatal warnings if per-step token usage persistence fails
- Add executor integration coverage verifying incremental tokenUsage updates before moving tasks to in-review
2026-04-26 09:33:00 -07:00
Fusion
70fe99f936 feat(FN-2585): remove top-level remote access toggle
- Remove the standalone remoteEnabled setting from CLI, core settings defaults/types, and dashboard settings APIs/UI
- Treat remote access as enabled when an active provider is selected and that provider is configured as enabled
- Update remote auth and engine lifecycle checks to gate on provider activation instead of a global flag
- Adjust tests and add a changeset documenting the remote access configuration simplification
2026-04-26 09:19:03 -07:00
Fusion
f09346a9da fix(FN-2525): harden remote access auth and tunnel regression coverage
- Add regression tests across CLI, core, dashboard, and engine for remote access auth, settings parity, and serve/TUI callback wiring
- Expand dashboard route and modal coverage for remote settings/auth flows including node environment behaviors
- Redact provider-switch failure details in tunnel process manager to avoid leaking sensitive provider diagnostics
- Update route registration and engine lifecycle tests to lock in remote-access behavior under real execution paths
2026-04-26 06:35:46 -07:00
Fusion
dd81a12e77 feat(FN-2523): add safe restart restore lifecycle diagnostics
- Add ProjectEngine restore lifecycle core to perform safe restarts and surface detailed restore state transitions
- Expose restore diagnostics through remote-access status types and settings/memory route context, including legacy API mapping updates
- Add comprehensive regression coverage for restore lifecycle behavior in engine and dashboard headless remote-access tests
- Document the restore lifecycle contract in architecture/settings docs and include a patch changeset for @runfusion/fusion
2026-04-26 05:18:12 -07:00
Fusion
cb1da0c659 feat(FN-2519): add remote tunnel manager for settings sync
- Add remote-access contracts, provider adapters, and a tunnel process manager with lifecycle handling
- Wire tunnel manager into ProjectEngine startup/shutdown flow and export new remote-access modules
- Update settings modal UX for remote auth URLs, including wrapping and related UI test coverage
- Document tunnel manager behavior and remote settings sync details in architecture, CLI, and settings docs
2026-04-26 02:20:28 -07:00
Fusion
1f2ce56593 fix(FN-2580): persist executor token usage before in-review moves
- Add per-task token usage baselines in TaskExecutor to track agent token deltas safely
- Persist token usage snapshots before every in-progress → in-review transition path, including failures and retries
- Initialize and clear token baselines during execute() lifecycle to avoid cross-run leakage
- Add executor tests covering token usage persistence across completion, failure, and pre-existing usage scenarios
2026-04-26 00:40:47 -07:00
Fusion
82cd58fe13 feat(FN-2579): merge fusion/fn-2579 (auto-resolved)
- fix(FN-2579): complete Step 3 — refine split-button accessibility
- fix(FN-2579): resolve workspace lint regression in provider
- test(FN-2579): complete Step 2 — update header engine control tests
- feat(FN-2579): complete Step 1 — style engine split-button dropdown
- feat(FN-2579): complete Step 0 — add engine control split-button behavior
- chore(release): v1.0.0
2026-04-26 00:29:19 -07:00
gsxdsm
7bc8cf945f chore(release): v0.3.0
Version bump via changesets (consumed 11 changesets). Forced 0.3.0
instead of changesets' default escalation to 1.0.0 for the pre-1.0
minor bump.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 00:15:09 -07:00
gsxdsm
c1a2b6edd7 fix(pi-claude-cli): unblock parameterless MCP tool calls in triage
Triage with claude-sonnet-4-6 via pi-claude-cli kept looping on
fn_review_spec calls that were rejected by pi's validator with
"root: must be object". Parameterless MCP tools (schema
{type:"object", properties:{}}) emit zero input_json_delta events,
so partialJson stayed "" and the catch fell through to
finalArgs = "" — a string, which TypeBox's Type.Object({}) rightly
refuses. Default empty partialJson to {} so the call lands.

Also:
- Add a 2-step reminder loop in triage before swapping to the
  fallback planning model — primary models that wrote PROMPT.md
  but forgot fn_review_spec recover from a nudge, no need to pay
  the cold-start tax of a new triage on a different model.
- Inject @runfusion/fusion's own pi extension into dashboard/
  daemon/serve sessions and propagate the path to createFnAgent
  via setHostExtensionPaths so fn_* tools register globally
  without requiring `pi install npm:@runfusion/fusion`.
- Drop the "historical" qualifier from replayed tool labels —
  Claude was reading "TOOL RESULT (historical Read):" as
  "previous session, ignore" and looping on verification.
- Remove subprocess-lifecycle stderr debug logs that landed for
  hang diagnosis — root cause is fixed, the noise can go.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 00:00:49 -07:00
Fusion
9aff532787 feat(FN-2571): enforce merger aborts through shutdown and git flow
- Add merger abort primitives and track active merge runs for coordinated cancellation
- Abort in-flight merges during engine shutdown and propagate AbortError through fallback catch paths
- Honor abort signals before commit, push, and dependency sync to prevent post-cancel side effects
- Expand merger and project-engine tests to cover abort propagation and merge-abort-on-stop behavior
2026-04-25 21:39:35 -07:00
gsxdsm
2026132132 feat(FN-2565): merge fusion/fn-2565 2026-04-25 18:08:27 -07:00
Fusion
39622f0398 fix(FN-2546): harden scheduled automation catch-up reliability
- Preserve overdue nextRunAt when schedule updates only touch non-cadence fields
- Recompute nextRunAt only when cadence changes, schedules are re-enabled, or nextRunAt is missing
- Sync memory dreams automation during ProjectEngine startup before CronRunner begins ticking
- Add core/engine regression coverage and a patch changeset for @runfusion/fusion release notes
2026-04-25 17:06:38 -07:00
gsxdsm
73ff095ccc fix(engine): register grep/find/ls alongside read/bash/edit/write for coding sessions
pi-coding-agent 0.70's createCodingTools preset only includes read/bash/edit/write,
but pi-claude-cli's tool-mapping translates Claude's Glob→find and Grep→grep.
Triage sessions running through Claude CLI hit "Tool find not found" the moment
the model called Glob and looped on the error.

Compose the built-in set explicitly so every tool referenced by tool-mapping.ts
is registered. Read-only sessions also gain ls (was silently dropped earlier
when readonly was redefined upstream).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 16:34:31 -07:00
Fusion
9d8852e26a feat(FN-2496): add overlap ignore paths support to scheduler settings
- Add overlap-ignore path validation and typed settings support in core schema
- Apply overlap ignore paths in scheduler overlap detection with dedicated engine tests
- Add Settings modal UI and routes handling for overlap ignore paths including path-picker feedback fixes
- Document overlap ignore paths in storage/settings docs and include a changeset for @runfusion/fusion
2026-04-25 15:48:36 -07:00
gsxdsm
825fecbb35 fix(extensions): always prefer vendored @fusion/pi-claude-cli over external installs
When users have an external pi-claude-cli (e.g. a global `npm install -g
pi-claude-cli`, or `npm:pi-claude-cli` in ~/.pi/agent/settings.json packages),
pi's extension discovery loaded the upstream copy and shadowed our fork. The
upstream has a once-and-lock MCP-config bug that throws "Extension runtime not
initialized" during early streamSimple calls and never recovers.

Adds reconcileClaudeCliPaths in @fusion/core, used by both the daemon's
extension assembly and the engine's per-session registerExtensionProviders, to
drop any path with a `pi-claude-cli` segment that isn't our vendored fork and
prepend the vendored path. Engine resolves the fork via require.resolve and
gracefully no-ops when it isn't reachable (e.g. embedded standalone usage).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 15:25:08 -07:00
gsxdsm
1a8058f334 feat(FN-2501): merge fusion/fn-2501 2026-04-25 14:24:35 -07:00
gsxdsm
55cef71b8f fix: kill agent-spawned bash trees and dev servers on dashboard shutdown
TUI quit ('q'/Ctrl+C) bypassed signal handlers via process.exit(0), and
neither shutdown path closed the HTTP server, so server.close()'s
stopAllDevServers() listener never ran. In-flight agent bash commands
(spawned detached for their own pgroup) were also never aborted, so
their subprocess trees — including vitest workers — survived as orphans.

Route the TUI quit through SIGINT so the registered shutdown handler
runs, await stopAllDevServers() in both shutdown paths, and abort
in-flight bash on every active agent session at the start of the
runtime drain so killProcessTree reaches every grandchild.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 14:13:30 -07:00
gsxdsm
dfb566ebc6 feat(FN-2508): merge fusion/fn-2508 2026-04-25 13:21:02 -07:00
gsxdsm
1d3d7438ff feat(FN-2506): merge fusion/fn-2506 2026-04-25 12:21:33 -07:00
gsxdsm
7f5ffc5920 chore(release): v0.2.7
Version bump via changesets.
2026-04-25 11:38:48 -07:00
gsxdsm
147419022e chore(release): v0.2.6
Version bump via changesets.
2026-04-25 10:21:52 -07:00
gsxdsm
c85dbc9bc6 feat(tui+release): persist vitest memory guard, aggregate root CHANGELOG, lockstep all packages
TUI: vitest memory-guard threshold and on/off toggle now persist to
global settings (vitestAutoKillEnabled / vitestKillThresholdPct), so
they survive dashboard restarts. Stats panel shows the system-memory
used percentage next to used/free. Utilities panel exposes [+/-] to
adjust the threshold in 5% steps (50–99%).

Release: scripts/release.mjs auto-syncs a root CHANGELOG.md aggregated
from every packages/*/CHANGELOG.md, grouped by version with one
sub-block per package.

Versioning: all private @fusion/* packages joined the changesets fixed
group with the public cli + cli-alias and were aligned to 0.2.5, so
every release bumps every package and produces per-package CHANGELOG
entries that the aggregator picks up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 09:09:31 -07:00
gsxdsm
d7a0cc6dcc feat(FN-2490): merge fusion/fn-2490 2026-04-25 07:59:48 -07:00
Fusion
c039af066c feat(FN-2408): merge fusion/fn-2408 2026-04-24 22:54:44 -07:00
gsxdsm
18bae531de fix(self-healing): use slim listTasks in maintenance recover loops
Batch 2 of runMaintenance() runs ~10 recover passes back-to-back, each
calling listTasks({ column: ... }) without slim. On busy boards this
materializes every task's activity log into memory ~10× per cycle,
walking the dashboard heap toward the 8 GB V8 limit until OOM. The
archive pass at line 610 already had this fix; extend it to the in-progress
and in-review recover passes that only read steps / paused / worktree /
mergeDetails / postReviewFixCount — all included in the slim projection.

Triage recovers are left non-slim because hasLatestSpecReviewApproval
scans task.log to find the most recent spec review; the triage column
is small so the memory cost is bounded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 22:25:57 -07:00
gsxdsm
6685d832fa chore: consolidate remaining tests into __tests__/ dirs and refactor mocks
Mostly mechanical cleanup left over from the earlier test-consolidation pass:
- Update import paths to ../../ for mocks now that test files moved deeper
- Simplify mock setup (drop usePluginUiSlots inline mock, etc.)
- Move engine ipc + runtimes tests into __tests__/ subdirs
- Move dashboard utils tests into __tests__/ subdir
- Refresh fusion-plugin-hermes-runtime/dist artifacts

build-exe.test.ts: spawn-import fix from a parallel branch (resolved during
worktree merge of the CSS extraction work).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 19:39:20 -07:00