Follow-up to 1983dac6e addressing nine findings from a code review of the
FN-5345/FN-5377 engine fixes. Includes a real bug fix (commit-message bypass
of the amend detection), two reliability invariant restorations (FN-4811 +
FN-4954 in the new D3 reuse-fallback path), a resource-leak cleanup, plus
test/audit/taxonomy polish.
HIGH
- D3 reuse-fallback now respects FN-4811 active-session safety: matches whose
path is currently owned by a different task in activeSessionRegistry are
skipped, never silently rebound. Skipped owners are recorded in audit
metadata for forensics.
- D3 reuse-fallback now respects FN-4954 pool-lease bookkeeping: when
recycleWorktrees=true AND a worktree pool is attached, the direct-reuse
shortcut is bypassed and the existing acquireTaskWorktree path is used so
WorktreePool.acquire/.release stays consistent. Without this guard the
new path could trip PoolDoubleLeaseError.
- prepare-commit-msg amend detection tokenizes the parent command line and
stops at the first message-supplying flag (-m/-F/--message/--file/=variants)
so a commit message containing the substring '--amend' cannot bypass the
guard. New regression test in prepare-commit-msg-empty-guard.real-git.test.ts.
MEDIUM
- Early empty-own-diff fast-path extracted into tryEarlyEmptyOwnDiffFinalize()
helper. Removes the exception-as-control-flow sentinel ('skip-early-fast-path:
not-reuse-mode') in favor of a plain if (eligible) { try { ... } catch {} }
block.
- Fast-path best-effort cleans up the stranded fusion/<id> worktree and branch
before completeTask(), so empty-own-diff residuals do not accumulate in
.worktrees/ or the branch namespace. FN-4811 guard ensures we never remove
a foreign-owned worktree.
- Two new audit subtypes in run-audit.ts replace the prior overloading of
merge:reuse-fallback-new-worktree:
- merge:reuse-fallback-pruned-stale-registration
- merge:reuse-fallback-reused-existing-registration
merge:reuse-fallback-new-worktree is now reserved for actual new-worktree
creation. Local emitReuseHandoffAuditEvent type union updated to match.
- New direct classifier test in merger-finalize-unproven.real-git.test.ts
('classifies proven-no-op for empty-own-diff branches') covers the new
branch in classifyOwnedLandedEvidence that self-healing and post-handoff
paths also depend on.
LOW
- Alpine/busybox ps fallback: prepare-commit-msg hook reads /proc/$PPID/cmdline
if 'ps -o args=' returns empty (busybox ps often lacks '-o args=' support).
- New backstop test variant 'FN-5345: empty-own-diff fast-path fires even
when branch is registered to two worktrees' reproduces the actual FN-5345
production wedge geometry where fusion/<id> was double-registered to two
worktrees.
Tests
- Full @fusion/engine suite: 448 files / 5881 tests / 9 skipped, all green
- pnpm lint green, pnpm build green
Three engine-level fixes for the in-review wedge class identified via FN-5345
(verification-only task with empty handoff commit + drifted worktree mapping
escalating to 'merge-deadlock-detected: verified content not on main' after
FN-4999 completion-handoff-limbo recovery exhausts).
D1 — prepare-commit-msg empty-commit guard
Fusion task worktrees install a prepare-commit-msg hook that refuses
'git commit --allow-empty' and other zero-staged-diff commits. Amend
(detected via $2==commit source arg or '--amend' in 'ps -o args= -p $PPID')
and merge/squash/cherry-pick/revert/rebase ceremonies are allowed.
D5 — early empty-own-diff fast-path in aiMergeTask
In reuse-task-worktree integration mode, BEFORE any reuse-handoff acquisition,
detect branches with own_commit_count >= 1 but zero net diff vs merge-base
(git diff --quiet <mergeBase>..<branch>) and finalize as no-op with
mergeDetails.noOpMerge=true + task:auto-recover-finalize-already-on-main
audit (reason: empty-own-diff-early-fast-path). cwd-main integration mode
is unchanged. classifyOwnedLandedEvidence also detects empty-own-diff so
self-healing and post-handoff finalize paths benefit too.
D3 — reuse-fallback consults existing branch registration
Before creating a fresh worktree in merger's reacquireReuseIntegrationWorktree,
consult 'git worktree list --porcelain' for existing registrations of
fusion/<id>. Reuse extant usable registrations directly. Prune stale
registrations first. Eliminates FN-5083-class double-registration where
'git worktree add -f' on an already-registered branch produced two worktrees
both claiming the branch and wedged the next handoff gate.
Tests
- New real-git backstop: prepare-commit-msg-empty-guard.real-git.test.ts
- New reliability interaction backstop in merge-reuse-task-worktree.test.ts
('FN-5345: empty-own-diff branch auto-finalizes via early fast-path')
- commit-msg-trailer.real-git.test.ts updated to use real commits (it was
relying on --allow-empty, which the new guard now refuses)
- Full @fusion/engine suite: 448 files / 5879 tests / 9 skipped, all green
- pnpm lint green, pnpm build green
Removes the branch-recovery CLI surface, orphan-rescue engine primitives, and their associated tests (over 1,500 lines deleted), while restoring a minimal prune-only orphan branch sweep with proper git audit mutation types. Documentation across `cli-reference.md`, `task-management.md`, and `AGENTS.m
Fusion-Task-Id: FN-5329
Implements external integration validation (FN-5321) with a manifest validator scaffold, worktrunk manifest wiring, and an evidence gap detector that runs during spec validation and triage; the reviewer also gates on external integration readiness. Includes tests for manifest, evidence gap, and tria
Fusion-Task-Id: FN-5321
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
The merge delivers several meaningful features and fixes: a **priority-aware overlap deferral fix** (FN-5325) in the scheduler that aligns the queued-overlap helper with the priority-sortable type, preventing inversion; a **merge integration worktree feature** (FN-5279) with settings UI, reusable wo
Fusion-Task-Id: FN-5325
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
The merge fixes a stale cache-miss path in the heartbeat executor and adds `reports-health` diagnostics for cache-state reporting, with a regression test covering a sparse-cache false-positive scenario. It also adds a two-line tweak to the merger and updates the diagnostics documentation.
Fusion-Task-Id: FN-5362
In reuse-task-worktree mode the merger detaches HEAD in the task worktree so
the squash commit lands on detached HEAD; nothing previously advanced the
project root's local integration branch, so changes never appeared on main.
Step 5c now applies the squash to projectRootDir via git merge --ff-only,
falling back to a regular merge with AI conflict resolution if main has
diverged. pushAfterMerge (when enabled) now runs from projectRootDir where
the branch was just advanced, so parsePushRemoteTarget can resolve a branch
instead of failing on the worktree's detached HEAD.
Also tightens acquireReuseHandoff: the executor-lease check above the
queue-lease acquisition was non-atomic, letting a local executor grab the
task between checks. Re-check after acquisition and release the queue
lease with a precise diagnostic instead of proceeding into a generic
failure later.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
The merge handoff path in acquireReuseHandoff called acquireMergeQueueLease
without a targetTaskId, which grabbed the priority/FIFO-sorted queue head
instead of the specific in-review task. When the queue head was a different
task (e.g. a polluted non-review entry), the returned lease had a mismatched
taskId and triggered 'no-lease' for every in-review task.
Fix:
- Pass targetTaskId: input.task.id to acquireMergeQueueLease so the merge
lane targets its specific task instead of grabbing the queue head.
MergeQueueAcquireOptions.targetTaskId is already wired in store.ts.
- Replace the broken typeof check (typeof object !== 'object' is always false
for plain JSON objects returned by RETURNING *) with a proper 'taskId' in
lease guard.
- Add acquiredTaskId to the no-lease error payload for better observability.
Reliability backstop: merge-reuse-task-worktree.test.ts guards this path.
Fixes: FN-5363
The behavioral cwd-main fallback is gone (fresh-acquire on refusal
replaces it), but the type string was left as a dead entry in the
emitReuseHandoffAuditEvent union (merger.ts) and the
DatabaseMutationType union (run-audit.ts). Remove both so the dead
string cannot be accidentally reintroduced.
Before: when reuse-task-worktree was configured but task worktree was missing/unusable,
merger fell back to cwd-main, losing the task worktree isolation benefit.
After: merger creates a fresh worktree for the task branch inline (using the standard
git worktree add pattern with identity guard installation) and retries the reuse handoff.
Only falls back to cwd-main if fresh acquisition also fails.
Three new audit events track the recovery path:
- merge:reuse-worktree-fresh-acquire — fresh acquisition started
- merge:reuse-worktree-fresh-acquired — fresh worktree created and bound to task
- merge:reuse-fallback-cwd-main — only when fresh acquisition itself fails (last resort)
Behavior:
- Missing/unusable task worktree → fresh worktree created, merge continues from it
- Fresh acquisition fails → cwd-main fallback (last resort, fully audited)
- Genuine liveness conflict (usable worktree but lease refused) → re-thrown, not masked
Regression test covers the missing-worktree case: verifies fresh acquisition + handoff
succeeds without any cwd-main fallback event.
After merge:reuse-handoff-refused with no usable task worktree:
- Acquire a fresh worktree and restore the fusion/<task-id> branch
from baseCommitSha before continuing merge
- Hard-fail only if fresh acquisition itself fails (not cwd-main fallback)
- Emit merge:reuse-worktree-fresh-acquire / merge:reuse-worktree-fresh-acquired
audit events around the acquisition lifecycle
Replaces the incorrect cwd-main fallback (499784581) with correct
reacquire path. Updates regression test in merge-reuse-task-worktree.test.ts
to assert fresh-acquire audit trail instead of cwd-main fallback.
Refs: FN-5353
When mergeIntegrationWorktree=reuse-task-worktree but the task has no
worktree or the worktree classifies as unusable, the merger now:
1. Creates a fresh worktree at the standard path with the fusion/<id> branch
2. Installs identity-guard hooks
3. Updates task.worktree + task.branch in the store
4. Emits merge:reuse-worktree-fresh-acquire / merge:reuse-worktree-fresh-acquired
5. Retries the handoff from the new worktree
Only falls back to cwd-main as last resort when fresh acquisition also
fails. Lease/liveness conflicts (worktree exists and classifies OK but
handoff refused on active-session or lease grounds) are re-thrown — not
masked with cwd-main.
New audit event types: merge:reuse-worktree-fresh-acquire,
merge:reuse-worktree-fresh-acquired
Adds broad-scope advisory chips to TaskCard and banner to TaskDetailModal with comprehensive test coverage and a dashboard guide entry. TaskCard gains an inline advisory chip (with styles), TaskDetailModal gets a matching banner, and both components have dedicated test suites covering the new UI ele
Fusion-Task-Id: FN-5314
Fusion-Task-Lineage: cbc88f36-d029-4e4b-ac9c-32a77560b8b9
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
- Add a merger guard that verifies source fusion/FN branch attribution when rebase capture reports zero own commits
- Fail finalize with explicit no-op attribution mismatch handling instead of marking mergeConfirmed on ambiguous no-op ranges
- Type and emit dedicated audit events for mismatch and source-ref-unavailable skip diagnostics
- Expand branch attribution, merger, and reliability interaction tests to cover the full no-op guard matrix
Fusion-Task-Id: FN-5304
Implements canonical worktrunk binary naming and manifest handling (FN-5320), adding a worktrunk installer that canonicalizes the executable name and manifest data, with documentation updates for architecture and settings, plus test alignments across routes, audit, and worktree acquisition fixtures.
Fusion-Task-Id: FN-5320
Add regression tests for queued concurrency in the scheduler and tighten the memo key used to track queued tasks, improving correctness of scheduler dispatch decisions.
Fusion-Task-Id: FN-5319
Adds pre-commit identity guard handling for branch case normalization (FN-5271), updating the worktree hooks implementation and adding a real-git integration test alongside a changeset for `@runfusion/fusion`.
Fusion-Task-Id: FN-5271
Restores visibility of action icons in SecretsView (CSS styling and component adjustments), accompanied by updated test coverage. A test stabilization commit for the process supervisor fallback rounds out the merge.
Fusion-Task-Id: FN-5257
The merge adds a new self-healing recovery path for tasks stuck in `in-progress` limbo (no pending step updates but not marked done), hardening `resetTask` and `recoverInProgressLimboTasks` with proper worker binding cleanup, audit event coverage, and integration tests validating the invariant acros
Fusion-Task-Id: FN-5219
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
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
The merge introduces an atomic review handoff seam in the core store (`packages/core/src/store.ts`) and migrates executor and self-healing transitions to use it, replacing the previous multi-step mutable-state handoff with a single transactional operation. Extensive reliability backstops and regress
Fusion-Task-Id: FN-5241
Adds a per-machine singleton lock that engages in
ProjectEngineManager.createAndStart() before any engine subsystems
spin up. Two fn dashboard processes can no longer run engines for the
same project on the same host — previously they would share .fusion/
state and corrupt worktrees / task rows for in-process projects.
The guard combines two independent checks:
- A proper-lockfile file at <project>/.fusion/engine.lock with
stale-lock recovery (auto-released on process death).
- A loopback listener on a hashed per-project address — UDS on
POSIX, named pipe on Windows. Stale UDS files are probed and
unlinked before a retry bind.
Failures raise EngineAlreadyRunningError. Both guards are released
from stopAll() and pauseProject(); a release on engine.start()
failure lets retries re-acquire cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implements deterministic followup deduplication for the project engine, routing eval and PR followups through a new `verification-followup-dedup` helper that excludes the parent task to prevent self-referential loops, with tests covering eval-followups, merge-error-recovery, PR comments, and the new
Fusion-Task-Id: FN-5232
The doc was rewritten to cover "every task-creation path" (with an
explicit enumeration of surfaces) instead of the older "task creation
flows (including ...)" wording, and uses "best-effort and non-blocking"
instead of "Creation is best-effort and non-blocking". Update the
documentation contract test to match the current phrasing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fusion-Task-Id: FN-5208