Skip to content

Recover stranded approved AI merge commits - #1997

Merged
gsxdsm merged 3 commits into
Runfusion:mainfrom
plarson:fix/ai-merge-detached-finalization-recovery
Jul 11, 2026
Merged

Recover stranded approved AI merge commits#1997
gsxdsm merged 3 commits into
Runfusion:mainfrom
plarson:fix/ai-merge-detached-finalization-recovery

Conversation

@plarson

@plarson plarson commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • recover approved detached AI merge clean-room commits during completion-handoff self-healing
  • fast-forward the integration branch when the stranded commit is safe and task-owned
  • finalize the task instead of blindly re-emitting merge handoff

Why

A merger can crash or stop after producing/reviewing a clean-room commit but before landing it, leaving the task stuck in review and the commit only reachable from a detached temporary worktree. The existing watchdog clears stale merging state and re-emits handoff, but loses the chance to land the already-approved commit.

Tests

  • pnpm --filter @fusion/engine exec tsc --noEmit --pretty false
  • pnpm --filter @fusion/engine exec vitest run --silent=passed-only --reporter=dot --project=engine-default src/__tests__/self-healing.test.ts -t "stranded AI merge clean-room recovery"

Note: full pnpm --filter @fusion/engine test currently aborts with Node unmanaged file descriptor warnings/SIGABRT in this worktree; the targeted engine-default regression test passes.

Summary by CodeRabbit

  • New Features
    • Added pre-prune recovery for AI-merge clean-room flows, recovering and landing the approved reviewed clean-room commit when tasks are stranded.
    • Reuses an existing approved clean-room worktree commit when there’s exactly one unambiguous candidate.
  • Bug Fixes
    • Prevented tasks from getting stuck in completion-handoff limbo.
    • Skips unnecessary merge-queue retries when recovery succeeds, and improves approved squash logging.
  • Tests
    • Added new recovery test coverage across multiple AI-merge roots and added integration behavior assertions.

Copilot AI review requested due to automatic review settings July 11, 2026 05:38
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a0d18149-eb36-492c-bc19-4111185a5e6a

📥 Commits

Reviewing files that changed from the base of the PR and between d0cca51 and 1d2a846.

📒 Files selected for processing (5)
  • .changeset/fuzzy-ai-merge-recovery.md
  • packages/engine/src/__tests__/merger-ai.test.ts
  • packages/engine/src/__tests__/self-healing.test.ts
  • packages/engine/src/merger-ai.ts
  • packages/engine/src/self-healing.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/fuzzy-ai-merge-recovery.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/engine/src/merger-ai.ts
  • packages/engine/src/tests/self-healing.test.ts

📝 Walkthrough

Walkthrough

Changes

Adds recovery for approved stranded AI merge clean-room commits in self-healing and standalone AI merge flows. Commits are matched to approval evidence, validated, landed safely, and finalized with coverage for task state, metadata, logging, and merge-agent reuse.

AI merge recovery

Layer / File(s) Summary
Detect and finalize stranded commits
packages/engine/src/self-healing.ts, packages/engine/src/__tests__/self-healing.test.ts
Self-healing scans approved clean-room worktrees, validates ownership and ancestry, advances integration when needed, finalizes recovered tasks, and verifies resulting state and logs.
Reuse approved clean-room commits during AI merge
packages/engine/src/merger-ai.ts, packages/engine/src/__tests__/merger-ai.test.ts, .changeset/fuzzy-ai-merge-recovery.md
The landing flow recovers a unique approved pre-existing commit before pruning, skips mergeAgent, records the approved SHA, and returns the recovered result with parametrized coverage and a patch changeset.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant landOneRepo
  participant recoverApprovedPreexistingAiMergeWorktree
  participant landSquash
  participant mergeAgent
  landOneRepo->>recoverApprovedPreexistingAiMergeWorktree: inspect approved clean-room worktrees
  recoverApprovedPreexistingAiMergeWorktree->>landSquash: land validated stranded commit
  landOneRepo->>mergeAgent: skip merge-agent execution after recovery
Loading

Suggested reviewers: gsxdsm

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: recovering stranded approved AI merge commits.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR recovers approved AI merge clean-room commits that were left stranded. The main changes are:

  • Records the approved squash SHA in AI merge review logs.
  • Searches repo-local, legacy, and temp clean-room roots for recoverable worktrees.
  • Lands one safe recovered clean-room commit before pruning or re-merging.
  • Lets self-healing finalize completion-handoff limbo after a successful recovery.
  • Adds tests for pre-prune recovery and self-healing recovery.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
packages/engine/src/merger-ai.ts Adds SHA-bound pre-prune recovery for approved AI merge clean-room worktrees.
packages/engine/src/self-healing.ts Adds completion-handoff recovery that can land and finalize one safe stranded clean-room commit.
packages/engine/src/tests/merger-ai.test.ts Covers pre-prune recovery from modern, legacy, and temp clean-room roots.
packages/engine/src/tests/self-healing.test.ts Covers self-healing finalization after landing a stranded approved clean-room commit.
.changeset/fuzzy-ai-merge-recovery.md Adds a patch changeset for the recovery fix.

Reviews (3): Last reviewed commit: "fix(FN-1997): bind stranded AI merge rec..." | Re-trigger Greptile

Comment thread packages/engine/src/self-healing.ts
Comment thread packages/engine/src/self-healing.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the engine’s self-healing logic to recover “stranded” approved AI-merge clean-room commits (e.g., when the merger crashes after producing/reviewing a clean-room commit but before landing it). Instead of re-emitting merge handoff and potentially losing the already-approved work, it attempts to safely fast-forward the integration branch to the stranded commit and then finalize the task.

Changes:

  • Add a completion-handoff-limbo recovery path that searches AI merge worktree candidates, verifies task ownership of the commit, and lands it via fast-forward (directly or via advanceIntegrationBranchRef).
  • Finalize the task using the recovered commit metadata (commitSha, landedFiles, mergeConfirmed) once the integration branch is safely advanced.
  • Add a regression test covering stranded clean-room recovery behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
packages/engine/src/self-healing.ts Adds stranded approved AI-merge clean-room commit recovery and integration-branch advancement during completion-handoff-limbo self-healing.
packages/engine/src/tests/self-healing.test.ts Adds a regression test asserting recovery lands the stranded commit and finalizes the task without re-emitting merge handoff.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/engine/src/self-healing.ts Outdated
Comment thread packages/engine/src/self-healing.ts Outdated
Comment thread packages/engine/src/__tests__/self-healing.test.ts Outdated
Comment thread packages/engine/src/__tests__/self-healing.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
packages/engine/src/__tests__/self-healing.test.ts (1)

10693-10772: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extend coverage beyond the single ff-only landing path.

This validates only the happy path where HEAD is already on the integration branch (the git merge --ff-only branch). The higher-risk surfaces of recoverApprovedStrandedAiMergeCommit are untested: the advanceIntegrationBranchRef branch (currentBranch !== integrationBranch) and, importantly, the safety-rejection guards — foreign ownership (!ownership.owned) and the non-ancestor case (!alreadyAncestor && !tipIsAncestor) that must not finalize. A regression test for this recovery should assert those refusal invariants, not just the successful land.

As per path instructions: "Bug regression tests must assert the general invariant across all known surfaces and reproduce the original symptom, rather than testing only the reported reproduction."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/engine/src/__tests__/self-healing.test.ts` around lines 10693 -
10772, Expand the “stranded AI merge clean-room recovery” tests around
recoverApprovedStrandedAiMergeCommit to cover advanceIntegrationBranchRef when
currentBranch differs from integrationBranch, plus refusal cases for
!ownership.owned and !alreadyAncestor && !tipIsAncestor. Assert rejected
recoveries do not finalize the task: no moveTask, no completion update, and no
success log; retain the existing successful ff-only landing assertions.

Source: Path instructions

packages/engine/src/self-healing.ts (1)

9010-9136: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add an FNXC comment documenting this recovery's requirement/decision.

Per coding guidelines, important requirements and technical decisions must carry an FNXC comment. recoverApprovedStrandedAiMergeCommit introduces a significant, safety-sensitive behavior (advancing the integration ref / fast-forwarding and finalizing an approved detached clean-room commit), yet unlike its peers in this file it has no FNXC annotation explaining the ownership/ancestry gating and the ff-only-vs-advanceIntegrationBranchRef split.

As per coding guidelines: "Add FNXC comments for important requirements and technical decisions. Each comment must begin with FNXC:Area-of-product, include a timestamp in yyyy-MM-dd-hh:mm format, explain the relevant behavior or requirement concisely".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/engine/src/self-healing.ts` around lines 9010 - 9136, Add an FNXC
comment immediately above recoverApprovedStrandedAiMergeCommit documenting its
safety-sensitive recovery behavior, including ownership and ancestry checks,
approved-completed-step gating, and the ff-only versus
advanceIntegrationBranchRef path. Begin with the required FNXC:Area-of-product
prefix and include the current timestamp in yyyy-MM-dd-hh:mm format.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/engine/src/__tests__/self-healing.test.ts`:
- Around line 10693-10772: Expand the “stranded AI merge clean-room recovery”
tests around recoverApprovedStrandedAiMergeCommit to cover
advanceIntegrationBranchRef when currentBranch differs from integrationBranch,
plus refusal cases for !ownership.owned and !alreadyAncestor && !tipIsAncestor.
Assert rejected recoveries do not finalize the task: no moveTask, no completion
update, and no success log; retain the existing successful ff-only landing
assertions.

In `@packages/engine/src/self-healing.ts`:
- Around line 9010-9136: Add an FNXC comment immediately above
recoverApprovedStrandedAiMergeCommit documenting its safety-sensitive recovery
behavior, including ownership and ancestry checks, approved-completed-step
gating, and the ff-only versus advanceIntegrationBranchRef path. Begin with the
required FNXC:Area-of-product prefix and include the current timestamp in
yyyy-MM-dd-hh:mm format.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2dcc8f22-a858-445c-a673-b32f03e7d80b

📥 Commits

Reviewing files that changed from the base of the PR and between a734f00 and b9a64ae.

📒 Files selected for processing (2)
  • packages/engine/src/__tests__/self-healing.test.ts
  • packages/engine/src/self-healing.ts

Comment thread packages/engine/src/self-healing.ts
Comment thread packages/engine/src/merger-ai.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
packages/engine/src/merger-ai.ts (1)

693-695: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Preserve this pruning-order invariant with an FNXC comment.

This ordering is an important recovery requirement and should use the repository’s timestamped FNXC:AIMerge convention.

As per coding guidelines, important requirements and technical decisions require an up-to-date FNXC:<Area-of-product> yyyy-MM-dd-hh:mm: comment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/engine/src/merger-ai.ts` around lines 693 - 695, The
recovery-critical pruning order near the merger finalization logic lacks the
required FNXC annotation. Add an up-to-date `FNXC:AIMerge yyyy-MM-dd-hh:mm:`
comment directly above the existing clean-room squash recovery comment,
documenting that the approved commit must be landed before pre-merge pruning can
remove its only reference.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/engine/src/__tests__/merger-ai.test.ts`:
- Around line 280-310: Expand the regression test around runAiMerge to exercise
all supported clean-room roots: the modern resolved root, the legacy
.fusion/ai-merge root, and a direct tmpdir() root. Parameterize setup and
stranded worktree creation per root while preserving the existing assertions
that the commit lands on main, the result reports merged with the stranded SHA,
recovery is logged, and mergeAgent is not called.

In `@packages/engine/src/merger-ai.ts`:
- Around line 173-180: Reverse the condition ordering in the candidate recovery
logic: evaluate alreadyLanded using merge-base before requiring squashSha to
descend from tipSha, and skip or recover already-landed candidates accordingly.
Update both occurrences near the checks following getCommitTaskOwnership,
ensuring the mutually exclusive ancestor checks no longer make recovery
unreachable.
- Around line 162-163: Honor cancellation in the early task-loading and recovery
path before any checkout, recovery, or landing work begins. In the logic
surrounding ctx, store.getTask, and stashResolveAgent, inspect ctx.signal and
immediately abort when cancellation is requested, preserving the existing
user-paused semantics and matching the later abort check near the integration
flow. Apply the same guard to the related 181–192 path.
- Around line 134-138: The task-level check in taskHasApprovedAiMergeReview must
be replaced with approval data bound to the exact squash commit SHA. Persist the
approved SHA alongside the review result, and update candidate recovery logic to
require that the candidate’s SHA matches the recorded approval; add a regression
covering two owned candidates where only one is approved.

---

Nitpick comments:
In `@packages/engine/src/merger-ai.ts`:
- Around line 693-695: The recovery-critical pruning order near the merger
finalization logic lacks the required FNXC annotation. Add an up-to-date
`FNXC:AIMerge yyyy-MM-dd-hh:mm:` comment directly above the existing clean-room
squash recovery comment, documenting that the approved commit must be landed
before pre-merge pruning can remove its only reference.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4b966c2f-f58f-4a63-8a98-e0ef487d4dd7

📥 Commits

Reviewing files that changed from the base of the PR and between b9a64ae and d0cca51.

📒 Files selected for processing (2)
  • packages/engine/src/__tests__/merger-ai.test.ts
  • packages/engine/src/merger-ai.ts

Comment thread packages/engine/src/__tests__/merger-ai.test.ts Outdated
Comment thread packages/engine/src/merger-ai.ts
Comment thread packages/engine/src/merger-ai.ts Outdated
Comment thread packages/engine/src/merger-ai.ts
@gsxdsm

gsxdsm commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Review feedback follow-up (nitpicks from review bodies)

Expand stranded AI merge recovery tests beyond the happy-path ff-only case; add FNXC for recovery/prune-order invariants.

Addressed in 39aa6ca:

  • Self-healing recovery tests now cover update-ref when checkout ≠ integration branch, plus refusal when ownership fails or the commit is neither landed nor a fast-forward of tip.
  • FNXC notes added on recoverApprovedStrandedAiMergeCommit and on the pre-prune land-before-prune order in landOneRepo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants