Skip to content

fix(land): eject a conflicting PR only once the chain before it lands - #289

Merged
moq-bot[bot] merged 1 commit into
mainfrom
fix/land-rechain
Oct 30, 2026
Merged

moq-bot[bot] merged 1 commit into
mainfrom
fix/land-rechain

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Summary

quest land push ejected every PR that conflicted with the chain built before it as merge_conflict, even when that chain did not land in the run. The PR then lost its place over a conflict with PRs that never reached the base.

moq-dev/quest#287 already rebuilds the chain in the same run after a PR fails alone. That covers the live cases:

Both runs used quest 01d051cf, which predates #287. The same wrong ejection still happened on main whenever the chain before the conflicting PR did not land:

  • A passing prefix stopped short of it. Queue A, B, C with C conflicting with B. A lands at once and B stays queued unchecked, but C was ejected.
  • A head moved.
  • A PR was withdrawn or no longer queued as it was.
  • The landing push was refused.

This change:

  • build records, for each conflict, how many links were built before it (after).
  • push ejects a conflicting PR only once every one of those links has landed in this run. With nothing before it, that means a conflict with the base, which is ejected at once. Otherwise the PR stays queued, and the next run builds it again without the PRs that did not land.
  • Conflict ejections now run after the landing, so they see its outcome. The comment says what the PR conflicts with: "it conflicts with the base now that chore(deps): bump the nix group with 2 updates #1, feat: name the branches a quest merges through #2, quest: plan converging MoQ onto standalone Quest #3 landed before it in code.txt; merge the base, push, and land it again".
  • check logs what each PR conflicts with (the base, or the PRs before it), and logs it again when that changes after a rebuild.
  • The refused-push handling moved into stopper(), so every path reaches the conflict step.

The three-phase split is unchanged. check and replay build and validate the same chains as before. push decides only from the replayed chain and what actually landed, so the outcome is deterministic. --budget stays coherent: when the budget stops the run after an ejection, nothing lands, so a PR behind the ejected one stays queued. The replayed chain already leaves out the ejected PR, so a PR that conflicted only with it no longer conflicts and also stays queued.

There is no stall: whenever a conflicting PR waits, the run either landed or ejected something, or reported a withdrawn PR. In every case push prints a line, so the workflow runs again.

Test evidence

New and updated tests in test/land.test.ts:

Against main's src/cli/land.ts, the two new push-phase tests and the updated conflict test fail. With this change, all 28 land tests pass.

  • just check: passed.
  • just test: passed (626 vitest tests plus the shell, lifecycle, and Worker suites). This session leaked CLAUDE_CONFIG_DIR into the environment, which broke two unrelated agent.test.ts cases. Re-run with it unset, everything passes.

Decisions for review

  • A PR that conflicts with the base itself, but sits behind PRs that do not land, now waits one run before ejection. Telling it apart from a conflict with the PRs before it would take an extra trial merge onto the bare base per conflict. I left that out for simplicity; it costs a run of delay, not a lost place.
  • Conflict ejections now post after the landing push. If the landing throws, they are not posted that run and are found again on the next.

Review

  • Reviewer: Codex (quest review --base origin/main), gpt-6.1-sol, medium effort, round 1
  • Head: 5246292
  • Findings: none ("patch is correct")

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

@coderabbitai

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7b8235d0-d02c-4965-be62-e7f5e0b97d2c
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

…#289)

* fix(land): eject a conflicting PR only once the chain before it lands

push ejected every PR that conflicted with the chain built before it as
merge_conflict, even when that chain did not land in the run: a passing
prefix that stopped short of it, a moved head, a withdrawn PR, or a refused
push. The PR then lost its place for a conflict with PRs that never reached
the base. Now push ejects it only once every PR built before it has landed,
which includes a conflict with the base alone, and the comment names the PRs
that landed. Otherwise it stays queued, and the next run builds it again
without the PRs that did not land. check names what each PR conflicts with.

The rechaining after a PR fails alone (#287) already covers the
moq-dev/moq queue #6985, #7027, #6999; its test now uses that shape.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@moq-bot
moq-bot Bot force-pushed the fix/land-rechain branch from 5246292 to 33fa0f4 Compare October 30, 2026 16:06
@moq-bot
moq-bot Bot merged commit 33fa0f4 into main Oct 30, 2026
@moq-bot
moq-bot Bot deleted the fix/land-rechain branch October 30, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant