Skip to content

feat: guard stale stacked base at PR-creation time (Phase 4-A) - #48

Merged
zawakin merged 2 commits into
mainfrom
feature/phase4-stacked-base-guard
Jun 29, 2026
Merged

feat: guard stale stacked base at PR-creation time (Phase 4-A)#48
zawakin merged 2 commits into
mainfrom
feature/phase4-stacked-base-guard

Conversation

@zawakin

@zawakin zawakin commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What

Phase 4-A of stacked-PR support: handle the stale stacked base case that #45 explicitly deferred.

When a stacked branch's recorded base (gw new --stackbranch.<child>.gwBase) merges before the child gets its own PR, gw status previously suggested gh pr create -B <parent> — which fails, because the parent branch no longer exists. Now:

  • gw status checks the recorded base's PR state before the child PR exists.
  • If the parent already merged, the next action becomes rebase onto main + open a normal PR via a new NextAction::StackedBaseMerged, instead of the stale -B <parent> hint.

Also

Fold NextAction::detect's positional argument list into a DetectContext struct (removes the #[allow(clippy::too_many_arguments)] from #45). Named fields keep the call sites legible and let new signals be added without churning every caller — which is exactly what this PR needed.

Test

  • next_action: unit test test_recorded_base_merged_before_pr_suggests_rebase (and the whole detect suite migrated to the DetectContext builder).
  • mise run verify passes.

The GitHub-dependent wiring in status.rs (querying the parent's PR state) mirrors the existing check_base_pr_merged path; the decision logic itself is unit-tested in detect. The merged-parent path isn't reachable from the file-remote integration harness (no gh/GitHub), so it's covered at the unit layer.

Scope

Phase 4-B (cleanup refusing to delete a branch that open child PRs still target) is a separate PR.

🤖 Generated with Claude Code

When a stacked branch's recorded base (gw new --stack) merged before the
branch got its own PR, gw status used to suggest `gh pr create -B <parent>`,
which fails because the parent branch is gone. Now status checks the recorded
base's PR pre-PR; if it merged, the next action becomes "rebase onto main and
open a normal PR" via the new NextAction::StackedBaseMerged.

This closes the stale-gwBase case that Phase 2 explicitly deferred here.

Also fold NextAction::detect's growing positional args into a DetectContext
struct (removing the too_many_arguments allow); named fields keep call sites
legible and let new signals be added without churn.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@zawakin zawakin self-assigned this Jun 29, 2026
The StackedBaseMerged hint suggested `git rebase origin/main`, which on a
stacked branch re-applies the (squash-)merged base's commits too — a doubled,
conflict-prone diff. Use `git rebase --onto origin/main <base>` so only this
branch's own commits are replayed. If the base ref is gone it now fails loudly
instead of silently double-applying (a fuller fix — keeping the base alive and
a recorded-SHA fallback — follows).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@zawakin
zawakin merged commit ad07c3a into main Jun 29, 2026
6 checks passed
@zawakin
zawakin deleted the feature/phase4-stacked-base-guard branch June 29, 2026 12:54
zawakin added a commit that referenced this pull request Jun 29, 2026
Reflect the stacked-PR work (#48-#51) in the skill's stacking section: gw sync
restacks with rebase --onto (replaying only the child's commits, not the merged
parent's), gw status guides the pre-PR case, and gw cleanup keeps a base branch
alive while an open child PR still targets it. Adds a note on why --onto is
required after a squash merge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant