Commit Graph

1394 Commits

Author SHA1 Message Date
gsxdsm
2bee6b0824 fix(tests): drop SIGTERM handlers + skip flaky reconciliation test
The SIGTERM/SIGINT/SIGHUP handlers added to db.test.ts and the engine
tmp-dir tests re-raised signals after cleanup, which killed vitest itself
(exit 143) under the full engine reliability suite. Keep `afterAll` +
`beforeExit`/`exit` + lock-child kill — those cover the macOS file-handle
leak that was the actual driver of the merge-verification cascade.

Also skip project-engine-manager `retries failed project starts on
subsequent reconciliation ticks` — flake under full-suite load (30s
timeout) that passes in ~46ms standalone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 00:22:19 -07:00
gsxdsm
d3ad0641c4 feat(FN-5486): merge fusion/fn-5486 2026-05-22 23:42:44 -07:00
gsxdsm
380f8b8e5e fix(core-tests): plug kb-db-test-* leaks on SIGTERM fork recycle
Vitest's forks pool SIGTERMs a fork when a test times out, which skips
`beforeExit`/`exit` handlers and leaves `kb-db-test-*` dirs behind.
`holdWriteLock` child processes also kept WAL/SHM handles open, blocking
recursive removal on macOS. Both paths now run cleanup: SIGTERM/SIGINT/
SIGHUP handlers sweep tracked dirs and re-raise the signal, and active
lock-helper children are tracked and SIGKILLed during cleanup so the
parent dir can be removed.

These leaks tripped scripts/check-test-isolation.mjs during deterministic
merge verification, failing auto-merge with "Completion handoff limbo
recovery exhausted" (e.g. FN-5521, FN-5486).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 23:27:44 -07:00
gsxdsm
2a3a07a612 feat(FN-5403): merge fusion/fn-5403 2026-05-22 23:12:49 -07:00
gsxdsm
23a0c27bd5 fix(engine-tests): subprocess timeout attribution + ENOTEMPTY retry on cleanup
Two test-infrastructure fixes from agent #1's flake-stabilization pass.
Skipped its DESC-order assertion rewrite (semantically equivalent no-op
that conflicted with the prior boilerplate consolidation in 848a226ca)
and its vitest.config additions (already in flight on main).

1. vitest-setup.ts: completedSubprocessFailures was a plain string[]. When
   a 30s subprocess-guard timer fired during a *later* test's execution
   window (because the owning test ran for e.g. 40s under its 60s
   timeout budget), the failure surfaced in the innocent successor test's
   afterEach. Typed the array as { ownerTestName, message }[] and filter
   on the current test name; orphaned entries are dropped silently.

2. worktree-contamination-attribution.real-git.test.ts: afterEach rm
   occasionally hits ENOTEMPTY on macOS when a git rebase internal dir
   isn't fully flushed. Added maxRetries: 3, retryDelay: 100.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 22:10:45 -07:00
gsxdsm
e291d86444 feat: attribute Fusion as Co-authored-by trailer instead of primary author
Switch commits Fusion produces (both executor step commits and merger squash
commits) from setting `--author="Fusion <noreply@runfusion.ai>"` to appending
`-m "Co-authored-by: Fusion <noreply@runfusion.ai>"`. The user's configured
git identity now stays as the primary author/committer, and Fusion is recorded
as a co-author (recognized by GitHub for shared attribution). The
`commitAuthorEnabled` toggle and `commitAuthorName`/`commitAuthorEmail`
settings keep their existing keys; the dashboard settings UI relabels them
from "Author" to "Co-author" to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 20:38:11 -07:00
gsxdsm
ec6643e4d9 fix(test-utils): cancel subprocess tracking timer for every proc in afterEach
The vitest subprocess guard's 60 s tracking timer could outlive the test
that spawned it and fire during a later test's afterEach, producing
spurious "Timed out after 60000ms" failures attributed to a different
test name under concurrent recursive test load.

Scope "Left running" reporting + SIGKILL to the current test's procs but
always clear each tracked subprocess's timer so it cannot fire later.
Bump the post-test grace from 200 ms to 1 s to absorb event-loop
contention from slow git shells.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 18:38:51 -07:00
gsxdsm
3a6a4ece6a feat(FN-5432): merge fusion/fn-5432 2026-05-22 16:09:43 -07:00
Fusion (runfusion.ai)
c3890a9b43 feat(FN-5496): reconcile soft-deleted tasks with active blockers
Added soft-delete blocker recovery logic to the scheduler and self-healing systems, enabling reconciliation of stale blocker reasons when tasks are archived or restored. The changes include corresponding tests for the completion guard behavior, scheduler recovery paths, and self-healing integration,

Fusion-Task-Id: FN-5496
2026-05-22 10:58:44 -07:00
gsxdsm
16b18bf338 chore(dashboard): publish MobileNavBar render decision to vpdebug
Surface the live mode / modalOpen / keyboardOpen / footerVisible / view
values that MobileNavBar uses for its early-return so the ?vpdebug overlay
can show which one is hiding the bar on Android. Also dumps the
.project-content className so we can correlate with `--with-mobile-nav`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 09:37:23 -07:00
Fusion (runfusion.ai)
4b484fd818 feat(FN-5485): clear userPaused state on manual retry reset with regression
Adds retry-reset logic that clears the user-paused flag on tasks, ensuring they can resume automatically after a retry is triggered, with regression tests covering the behavior across the CLI extension and core manual-reset module.

Fusion-Task-Id: FN-5485
2026-05-22 08:23:45 -07:00
gsxdsm
3a0d179ba2 Fn-5196 2026-05-22 04:09:22 -07:00
Fusion (runfusion.ai)
9a09498397 feat(FN-5196): return 410 Gone for hard-archived task deletions
Implement the hard-archived delete contract: add a typed `ArchivedTaskDeleteError`, map hard-archived task deletes to HTTP 410 Gone at both the store and routes layers, and document the invariant in the soft-delete verification matrix.

Fusion-Task-Id: FN-5196
2026-05-22 02:04:42 -07:00
Fusion (runfusion.ai)
9c2b61eec6 feat(FN-5204): add test mode activation across settings, engine, and dashboard
- Add core settings schema/types support for testMode with model-resolution override handling
- Enforce engine session lane overrides in test mode with targeted helper coverage
- Add dashboard settings toggle plus persistent test-mode banner and related component tests
- Update settings documentation and parity/roundtrip tests for the new test mode behavior
2026-05-22 00:15:14 -07:00
Fusion (runfusion.ai)
025683ca60 feat(FN-5438): add manual merge blocker bypass mode for queued tasks
Adds a manual merge blocker mode (FN-5438) that prevents automatic merging and provides a bypass mechanism to resume, wired through the merger, project engine, and task workflow API routes. Includes tests across core, engine route registration, and project engine layers, plus a changeset and documen

Fusion-Task-Id: FN-5438
2026-05-21 18:29:03 -07:00
Fusion (runfusion.ai)
f6f38676b4 feat(FN-5226): add scope auto-widen layer 2.5 to merger for attribution-bas
Merges the Layer 2.5 scope-auto-widen feature (FN-5226) into the merger: a new evaluator module that automatically widens a task's declared file scope based on git attribution prior to the existing scope partition gate, wired into `merger.ts` with full audit taxonomy, persisted task metadata, and re

Fusion-Task-Id: FN-5226
2026-05-21 16:30:31 -07:00
Fusion (runfusion.ai)
216c32bfe5 feat(FN-5347): reset manual retry counters across task retry surfaces
- Add a shared manual retry reset helper in core and export it for consumers
- Wire retry counter resets into CLI task retry, extension task retry, and dashboard task workflow routes
- Align retry reset behavior with task typing updates and remove superseded task-helper reset paths
- Add focused core/CLI/extension/dashboard tests plus docs and a changeset describing retry reset behavior
2026-05-21 15:45:48 -07:00
Fusion (runfusion.ai)
8df21a6b68 feat(FN-5353): fix merge-reuse handoff race by gating reacquire and strict
Fixes merge handoff stalls by enforcing strict queue targeting and self-enqueue in the merger (FN-5353 Step 4), forcing reacquire before reuse handoff gates (Step 5), and aligning integration-root contract tests (Steps 1 & 7). Consolidates two prior changesets into `fn-5353-merge-reuse-stall-fix.md`

Fusion-Task-Id: FN-5353
2026-05-21 15:30:13 -07:00
Fusion (runfusion.ai)
b8147dd3b1 feat(FN-5405): remove broad-scope triage heuristics and UI advisory chips/b
Removes the broad-scope detection feature end-to-end: the TaskCard chip and TaskDetailModal advisory banner are gone from the dashboard, the triage heuristic that flagged tasks as broad-scope has been deleted from the engine along with its associated run-audit events, and documentation references ha

Fusion-Task-Id: FN-5405
2026-05-21 15:07:15 -07:00
gsxdsm
109f969f06 Merge commit '0c2416903f4f7d29fc5933d440a46a9c55f80235' 2026-05-21 13:40:25 -07:00
Fusion (runfusion.ai)
0c2416903f feat(FN-5363): enforce strict target lease to prevent merge queue pollution
Enforces strict target-lease behavior on merge queue rows, gates and scrubs polluted entries, enriches no-lease handoff diagnostics, and adds regression tests covering leased-target no-lease and polluted queue reuse paths, with audit registration and docs updates.

Fusion-Task-Id: FN-5363
2026-05-21 13:40:25 -07:00
gsxdsm
9bc5b5f4e9 feat(FN-5443): merge fusion/fn-5443 2026-05-21 13:36:39 -07:00
Fusion (runfusion.ai)
b3f995c857 feat(FN-5348): remove cwd-main integration mode fallback
Removes the `cwd-main` integration fallback mode (FN-5348), eliminating the legacy shortcut path where the merger would operate directly on the project root instead of a dedicated worktree. Steps normalize the `reuse-task-worktree` integration mode as the sole path, wire stricter mode invariants in

Fusion-Task-Id: FN-5348
2026-05-21 12:49:50 -07:00
Fusion (runfusion.ai)
79850b233f feat(FN-5349): add integration branch resolver with auto-recovery fallback
FN-5349 adds a dedicated integration branch resolution module (`packages/engine/src/integration-branch.ts`) replacing ad-hoc dynamic fallbacks, routes merger branch conflict resolution through it, wires auto-recovery handlers (branch-worktree, contamination) to use integration branch fallback, and w

Fusion-Task-Id: FN-5349
2026-05-21 12:04:58 -07:00
gsxdsm
2d425b1e28 fix: scrub queued/blockedBy/overlapBlockedBy on in-review transition
A task that picked up status='queued' or overlapBlockedBy while waiting in
todo (file-scope overlap with a higher-priority peer) was carrying those
todo-dispatch markers into in-review, where the merge gate then permanently
refused with "task is marked 'queued'". Ghost-review → todo → scheduler
re-queue → stranded-completed-todo recovery → in-review formed a steady-
state loop that never let the task merge.

moveTaskInternal now treats queued/blockedBy/overlapBlockedBy as todo-only
dispatch state and clears them on every transition into in-review. failed
and awaiting-* statuses are left untouched (already covered by an existing
test, plus a new regression test for the queued case).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 11:08:14 -07:00
gsxdsm
933cea434a feat(FN-5256): merge fusion/fn-5256 2026-05-21 11:06:26 -07:00
Fusion (runfusion.ai)
a04ba3cf21 feat(FN-5413): add null description persist regression test
Added a regression test for null description persistence in the core task store and a CLI patch changeset to ship the fix.

Fusion-Task-Id: FN-5413
2026-05-21 08:20:42 -07:00
gsxdsm
04648a4a68 Merge commit '5f9f7776300afbc935d651949c50c60bca2cafd4' 2026-05-21 07:05:48 -07:00
Fusion (runfusion.ai)
5f9f777630 feat(FN-5374): raise room transcript defaults and align compaction settings
Raised room transcript defaults (`messagesBefore` and `daysBefore`) in the core settings schema and updated project-level setting defaults, with corresponding documentation refresh in the settings reference. Added full test coverage for room compaction defaults, pinned room default settings in Setti

Fusion-Task-Id: FN-5374
2026-05-21 07:05:48 -07:00
gsxdsm
97e6a0cc0e fix(FN-5256): skip cycle preflight when new task has no deps
The unconditional listTasks() in assertNoDependencyCycle was wasted work
for the common no-dependency write and broke the same-agent duplicate
intake fail-open path: tests that stub listTasks to throw had the cycle
check consume the rejection before _maybeAutoArchiveSameAgentDuplicate's
try/catch could swallow it, propagating the error out of createTask.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 06:40:15 -07:00
Fusion (runfusion.ai)
e12adeb3fa feat(FN-5256): complete Step 2 — enforce cycle checks on writes 2026-05-21 04:15:21 -07:00
gsxdsm
5c15031416 fix(health): re-run integrity check on Refresh health, not just re-read cache
The dashboard's corruption banner refresh action was a no-op for clearing
stale corruption flags after the user repaired the DB. Database.
scheduleBackgroundIntegrityCheck runs the integrity check exactly once at
engine boot and then early-returns forever after, so corruptionDetected
was sticky for the life of the process. POST /api/health/refresh just
read the cached flag back.

Add Database.refreshIntegrityCheck() and TaskStore.refreshDatabaseHealth()
which synchronously re-run the integrity check and update the cached
state, and have the route use them. After REINDEX / fn db --vacuum / any
in-place repair, users can now clear the banner without restarting the
engine.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:02:53 -07:00
gsxdsm
d90da81079 fix(core): default null task.description to empty string on persist
The tasks table description column is NOT NULL, so a task arriving with
description == null/undefined would fail the insert with a constraint
error. Default to "" in getTaskPersistValues, matching the ?? null / ?? 0
treatment of other optional fields.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 22:25:15 -07:00
gsxdsm
57dbff4ba4 fix(FN-5407): stop checkpoint-truncating live DB during backup
Backups opened a second node:sqlite connection against the live fusion.db
and ran PRAGMA wal_checkpoint(TRUNCATE) before copying. A node:sqlite
SIGSEGV mid-checkpoint (the recurring pager_write crash noted in db.ts)
could leave the main DB file extended-but-zeroed, which is exactly the
failure mode that wiped a 1GB fusion.db tonight.

Replace the in-process checkpoint with a plain cp of the main DB plus any
sibling -wal/-shm files. SQLite replays the WAL on first open, so
uncheckpointed pages survive without us ever opening a second connection
against the live database.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 22:09:30 -07:00
Fusion (runfusion.ai)
2baaad743a feat(FN-5407): add paired central backup support to backup command and stor
FN-5407 adds paired central backup support to the Fusion task management system, with both the core backup engine and CLI commands updated to handle central database backup pairs. Documentation was updated to reflect the new capability, and two stabilization fixes were included to handle central bac

Fusion-Task-Id: FN-5407
2026-05-20 20:05:08 -07:00
Fusion (runfusion.ai)
c60045df22 feat(FN-5223): anchor staleness and stall detectors to engine activation ti
The merge introduces an engine-activation timestamp as the staleness floor for task age calculations, replacing arbitrary wall-clock thresholds with a runtime-relative anchor. Step 1 adds settings defaults, Steps 2–4 wire the floor helper through project engine, in-process runtime, and task store hy

Fusion-Task-Id: FN-5223
2026-05-20 14:29:07 -07:00
Fusion (runfusion.ai)
8f2d5e7e61 feat(FN-5220): guard explicit duplicate markers in triage and self-healing
Adds an explicit duplicate-marker guard (FN-5220) spanning core helper, dashboard API endpoint, triage short-circuit, and self-healing sweep to detect and handle duplicate task creation attempts; includes comprehensive test coverage across unit, API, and integration layers plus documentation.

Fusion-Task-Id: FN-5220
2026-05-20 14:28:45 -07:00
gsxdsm
d6196a8665 fix(FN-5363): implement targetTaskId in store SQL so lease targets correct task
The previous commit wired targetTaskId through the engine caller but the
store's acquireMergeQueueLease SQL still grabbed the queue head unconditionally,
leaving the no-lease loop intact. This lands the store-side change: when
targetTaskId is provided it attempts a direct-match UPDATE first; only falls
back to queue-head ordering if that row isn't available (backward-compatible).

Adds regression test covering the polluted-queue-head scenario (FN-5363).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 12:05:41 -07:00
gsxdsm
31b403ea3c feat(FN-5363): remove queue-head fallback in acquireMergeQueueLease targetTaskId path
When targetTaskId is passed, the lease attempt must target that task only.
The previous code silently fell back to queue-head selection if the targeted
task was not available — producing a lease for a different task, then
returning it with the wrong taskId.  acquireReuseHandoff would then see
lease.taskId !== input.task.id and emit a misleading 'no-lease' diagnostic
that hid the real cause (queue head was occupied by an unrelated task).

The fix: when targetTaskId is set and the lease for that task returns null,
return null immediately instead of falling through to the queue-head SELECT.
Callers (acquireReuseHandoff) already validate the returned taskId and emit
structured 'no-lease' diagnostics including acquiredTaskId so the polluter
is identifiable in audit logs.

Queue-head fallback is preserved for callers that omit targetTaskId
(backward-compatible).
2026-05-20 12:05:03 -07:00
gsxdsm
1b7f492227 feat(FN-5353): wire fresh-worktree-acquire to ActivityLogModal 2026-05-20 10:58:29 -07:00
Fusion (runfusion.ai)
321c170b90 feat(FN-5143): clear agent logs when task is soft-deleted
Clears agent logs when a task is soft-deleted, with new regression tests covering the end-to-end behavior and documentation updated in the storage guide. The core logic lives in `store.ts` while `store-upsert.test.ts` is updated to reflect the new expectations.

Fusion-Task-Id: FN-5143
2026-05-20 09:42:40 -07:00
Fusion (runfusion.ai)
22d59b5f9a feat(FN-5279): add merge integration worktree feature with settings UI and
Implements the `mergeIntegrationWorktree` setting (FN-5279) that allows tasks to reuse their own worktree as the integration root instead of spawning a separate one. Steps 1–2 added the settings schema, types, and SettingsModal surface with documentation; Step 3 wired an integration-root resolver th

Fusion-Task-Id: FN-5279
2026-05-20 09:42:40 -07:00
Fusion (runfusion.ai)
dd6ccc67a2 fix(FN-5257): restore SecretsView action icon visibility
- Standardize SecretsView action icon sizing and color so header, row, loading, and modal toggle icons stay visible in dark and light themes
- Expand SecretsView tests to load app CSS and assert icon visibility across both themes
- Stabilize the process supervisor fallback test by removing an unnecessary maxLifetime override

Fusion-Task-Id: FN-5257
2026-05-20 06:20:16 -07:00
Fusion (runfusion.ai)
35b2971f54 feat(FN-5216): sanitize duplicate paths in file scope when parsing task sto
The merge adds a file scope sanitizer to the task store that deduplicates and normalizes path entries, with test coverage in `store-parsing.test.ts`; a small documentation fix accompanies the change in AGENTS.md.

Fusion-Task-Id: FN-5216
2026-05-20 06:14:47 -07:00
Fusion (runfusion.ai)
1b49cbc94d feat(FN-5284): surface db corruption via health checks, self-healing, and d
- fix(FN-5284): add db corruption audit mutation type
- feat(FN-5284): complete Step 7 — document corruption surfacing
- feat(FN-5284): complete Step 6 — add db corruption banner
- feat(FN-5284): complete Step 5 — extend health payload
- feat(FN-5284): complete Step 3 — surface db corruption in self-healing
- feat(FN-5284): complete Step 2 — add db corruption notification event
- feat(FN-5284): complete Step 1 — expose integrity check errors

Fusion-Task-Id: FN-5284
2026-05-20 04:13:43 -07:00
gsxdsm
c89d68dd2d feat(FN-5203): merge fusion/fn-5203 2026-05-20 02:48:39 -07:00
gsxdsm
b1c0a91752 feat(FN-5195): merge fusion/fn-5195 2026-05-20 02:47:34 -07:00
Fusion (runfusion.ai)
c9fd41ef26 feat(FN-5175): thread soft-delete audit context and add reconciliation scri
Adds a reconcile script to recover leaked soft-deleted tasks, threads delete audit context through all callers, and records soft-delete audit events with archive column tracking across core/engine/cli/dashboard, with reliability backstop tests covering caller alignment.

Fusion-Task-Id: FN-5175
2026-05-20 02:46:49 -07:00
Fusion (runfusion.ai)
6ecef44ab3 fix(FN-5193): restore task source typing for workspace typecheck
- Add the optional Task.source field back to the core Task interface
- Preserve durable task creation and import provenance typing alongside sourceIssue metadata
- Unblock workspace typechecking for consumers that read task source metadata

Fusion-Task-Id: FN-5193
2026-05-20 02:04:39 -07:00
Fusion (runfusion.ai)
ab0a253004 feat(FN-5264): abort in-flight executor/merge/triage work on soft-delete (F
Implements in-flight abort for soft-deleted tasks across all three execution lanes: executor, merger, and triage now check for `deletedAt` before proceeding and emit `task:soft-delete-in-flight-abort` audits rather than continuing work on a deleted task. The 829-line addition is dominated by integra

Fusion-Task-Id: FN-5264

Fusion-Task-Lineage: 4ee8e63b-abf0-43e2-9130-39a05434d8f9
2026-05-20 01:16:06 -07:00