Files
fusion/.changeset/fix-fn-5345-empty-commit-and-empty-own-diff-finalize.md
Fusion (runfusion.ai) 8e67404680 fix(FN-5345): address code-review findings on engine fixes
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
2026-05-20 17:54:26 -07:00

1.9 KiB

@runfusion/fusion
@runfusion/fusion
patch

Engine reliability: prevent the FN-5345 in-review wedge class.

  • Fusion task worktrees now install a prepare-commit-msg empty-commit guard that refuses git commit --allow-empty and other zero-staged-diff commits, while still allowing legitimate amend / merge / squash / cherry-pick / revert / rebase paths. Amend detection scans ps -o args= (with /proc/$PPID/cmdline fallback for Alpine/busybox) tokenized, stopping at the first message-supplying flag (-m, -F, --message, --file) so a commit message containing the substring --amend cannot bypass the guard.
  • Merger gains an early empty-own-diff fast-path in reuse-task-worktree integration mode: branches with own commits but zero net tree change vs merge-base now auto-finalize as no-op BEFORE any reuse-handoff acquisition runs, preventing registered-branch-mismatch + merge-deadlock-detected: verified content not on main wedges. The fast-path best-effort cleans up the stranded worktree and fusion/<id> branch so empty-own-diff residuals do not accumulate.
  • classifyOwnedLandedEvidence also detects the empty-own-diff case and returns proven-no-op so downstream self-healing and post-handoff finalize paths benefit too.
  • Merger's reuse-fallback path now consults git worktree list --porcelain before creating a new worktree, reusing extant usable registrations of fusion/<id> and pruning stale ones, eliminating FN-5083-class branch-registration double-registration. The direct-reuse shortcut is guarded by FN-4811 (refuses paths owned by a different task in activeSessionRegistry) and FN-4954 (skipped when recycleWorktrees=true with a pool attached, so WorktreePool.acquire lease bookkeeping stays consistent). Two new audit subtypes (merge:reuse-fallback-pruned-stale-registration, merge:reuse-fallback-reused-existing-registration) replace the prior overloading of merge:reuse-fallback-new-worktree for these cases.