Skip to content

fix(foreman): anchor recovery soft-reset at merge-base branch point#1044

Merged
Defilan merged 1 commit into
defilantech:mainfrom
joryirving:fix/basebranchsha-mergebase
Jul 10, 2026
Merged

fix(foreman): anchor recovery soft-reset at merge-base branch point#1044
Defilan merged 1 commit into
defilantech:mainfrom
joryirving:fix/basebranchsha-mergebase

Conversation

@joryirving

Copy link
Copy Markdown
Collaborator

What

Anchor the recovery soft-reset at the true branch point — merge-base(base, HEAD) — instead of the current upstream tip, so intervening upstream delta is never squashed into a recovered self-commit.

Why

Fixes #1002

repo.BaseBranchSHA (#995) returns the current upstream tip at recovery time, but the branch point was captured at task-branch-cut time in CreateBranchFromUpstream (#813). If upstream advances between those two points, SoftResetToBase's git reset --soft <baseBranchSHA> reverts the intervening upstream delta into the index and repo.Commit squashes it into the recovered commit. Same class as the #982/#813 stale-base bug, along the mid-run-advance axis.

How

SoftResetToBase now resolves branchPoint := git merge-base <base> HEAD — the lowest common ancestor of the current upstream tip and the task branch, i.e. exactly where the branch was cut — and soft-resets there. The commits-ahead count is anchored at the same branchPoint, so the guard and the reset stay consistent. The intervening upstream delta stays on the branch and is never re-staged; only the model's own commits are recovered. Matches how the normal commit path already behaves (it never re-anchors).

Contained to pkg/foreman/agent/repo/commit.go — the executor caller is unchanged (it already passes BaseBranchSHA). No CRD/API change.

Checklist

  • Tests added/updated — TestSoftResetToBase_AnchorsAtBranchPointNotUpstreamTip (upstream advances mid-run → only the model's file is staged, the upstream delta is not re-staged); TestSoftResetToBase_NoSelfCommitIsNothingToCommit (no self-commit + advanced upstream → ErrNothingToCommit). Existing TestRecoverSelfCommitsOrNoChange_* still pass.
  • make test passes locally (full suite; envtest included)
  • make lint passes locally (0 issues)
  • Commit messages follow conventional commits
  • All commits are signed off (git commit -s) per DCO
  • AI assistance disclosed — AI-assisted contribution
  • Documentation updated — N/A (internal recovery-path behavior; doc comment on SoftResetToBase updated)

repo.BaseBranchSHA (defilantech#995) returns the CURRENT upstream tip at recovery
time, but the task branch was cut from the upstream tip at branch-cut
time (defilantech#813). If upstream advanced between those points, SoftResetToBase's
`git reset --soft <baseBranchSHA>` re-staged the intervening upstream
delta into the recovered commit (squashed alongside the model's edits).

Anchor the reset at the true branch point instead: merge-base(base, HEAD),
the lowest common ancestor of the current upstream tip and the task
branch = exactly where the branch was cut. The commits-ahead count is
anchored there too, keeping the two consistent. Only the model's own
commits are re-staged; the upstream delta between branch point and tip is
preserved on the branch, never re-staged.

Closes defilantech#1002

Signed-off-by: Jory Irving <jory.irving@stackadapt.com>
@joryirving joryirving requested a review from Defilan as a code owner July 10, 2026 03:56
@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 37.50000% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/foreman/agent/repo/commit.go 37.50% 2 Missing and 3 partials ⚠️

📢 Thoughts on this report? Let us know!

@Defilan Defilan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Clean fix, Jory. Verified the reasoning: anchoring the soft-reset at merge-base(base, HEAD) instead of the current tip means a mid-run upstream advance can't drag the intervening delta into the recovered commit — same stale-base family as #813/#1042, on the mid-run axis. Real-git tests reproduce it well and pass locally. Approving.

@Defilan Defilan merged commit 2492d15 into defilantech:main Jul 10, 2026
24 checks passed
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.

fix(foreman): pin BaseBranchSHA recovery point with merge-base to avoid re-staging mid-run upstream delta

2 participants