Skip to content

fix(ci): merge a stacked PR against the newest commit it holds of the landed PR below it - #422

Merged
DrunkOnJava merged 5 commits into
mainfrom
fix/train-stacked-base
Oct 28, 2026
Merged

DrunkOnJava merged 5 commits into
mainfrom
fix/train-stacked-base

Conversation

@DrunkOnJava

Copy link
Copy Markdown
Owner

Summary

refresh.sh merges a PR that is stacked on a landed PR against the newest commit it holds of that landed PR, instead of the usual merge base. A PR that is not stacked merges exactly as before.

The problem. A stacked PR's merge base with main is an old main commit. The train's own commits on the landed lower PR then conflict with the stacked copies of the same lines: its merges of main, its renumbered ARCHITECTURE.md section, its measured baselines. When #329 landed on 2026-10-27, the train refused #330 to #341 on examples/probe_dim_assoc.rs (train.log 23:49). A lane then hand-merged each PR with git merge-tree --merge-base=<that commit>, as it had after every earlier landing.

How the train finds that base now.

  1. For each PR main squashed since the merge base, take the PR's head (headRefOid; fetched from refs/pull/N/head if missing).
  2. Take that head's merge base with the branch.
  3. Keep the nearest such commit that main does not hold.

It then merges against that base with git merge-recursive, which leaves the same index stages as git merge, so the existing resolvers run unchanged. It writes MERGE_HEAD so the result is a signed two-parent merge, and records the base in merge-base.sha for oracle_base.py.

Cross-references. arch.py renumber also rewrites references, in the PR's own lines, to a section that main gave a new letter when the PR below landed. Sections are matched by title, when the title is unique on both sides. This is the step the lanes did by hand, for example #332's "§7bi" for #330.

Spec reference

Maintainer tooling only.

Test plan

Source-provenance declaration

By submitting this PR I certify that my contribution does not incorporate executable code from any source whose license is incompatible with Apache-2.0. Specifically:

  • No Autodesk DWG SDK source (RealDWG, ObjectARX, ObjectDBX) or NDA-protected Autodesk documentation was consulted or imported.
  • No Open Design Alliance Teigha / Drawings SDK source was consulted or imported. The ODA's public Open Design Specification for .dwg files PDF is explicitly allowed (see CLEANROOM.md).
  • No GPL-licensed DWG implementation source (LibreDWG, etc.) was consulted or imported. This matters because dwg-rs is Apache-2.0 and must remain compatible.

My contribution is based on:

  • The ODA's freely-redistributable Open Design Specification for .dwg files (v5.4.1);
  • Public reverse-engineering notes, research papers, or blog posts cited inline;
  • Reading algorithm-description comments (not executable code) in permissively-licensed projects (MIT / Apache / BSD) to resolve spec ambiguities — disclose any such reading in this PR body so it can be recorded in CLEANROOM.md.

See CLEANROOM.md for the full allowed/forbidden source list and the honest scope of what "clean-room" means for this project.

Developer Certificate of Origin

By submitting this PR, I certify that the contribution complies with the
Developer Certificate of Origin 1.1.
Specifically, I affirm that the contribution is my own work (or rightfully
licensed to me) and that it can be distributed under the project's Apache-2.0
license.

I will sign off commits with git commit -s when asked, which adds a
Signed-off-by trailer to the commit message asserting the DCO.

… landed PR below it

Every time a PR of a stack landed, the train refused every PR above it: their merge base was an
old main commit, so the train's own commits on the landed PR (its merges of main, the renumbered
section, the measured baselines) conflicted with the stacked copies of the same lines. After #329
landed, #330 to #341 all refused on examples/probe_dim_assoc.rs, and a lane hand-merged each with
`git merge-tree --merge-base=<newest commit of the landed PR it holds>`. refresh.sh now finds that
base itself (the head of each PR main squashed since the merge base, its merge base with the
branch, the nearest one main does not hold), merges against it with git merge-recursive and the
usual conflict handling, and writes it to merge-base.sha for the oracle comparison. A PR that is not
stacked merges exactly as before. arch.py renumber also rewrites references in the PR's lines to a
section main renumbered when the PR below landed, matched by title.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review 🔄 Running since 2026-10-28T04:55:15.997562Z fa8c1a7 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bf7e00baaa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/maintainer/train/arch.py Resolved
arch.py renumber printed every section main had renumbered under a stacked PR's base, even when
none of the PR's lines cited one; refresh.sh then ran `git commit -qam` with nothing to commit and
refused a mergeable PR. It now prints only the moves that rewrote a line, nothing when none did, and
refresh.sh commits the renumber only when the tree changed. Checked at a47e1bf against main: the
old script printed "§7bh->§7bi §7bi->§7bj" with no change, the new one prints nothing; at #331's
head it prints only 7bj->7bk, at #332's 7bj->7bk 7bk->7bl §7bi->§7bj.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f71d571f3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tools/maintainer/train/refresh.sh Resolved
…branch holds

The landed PR's head and the stacked branch can have several merge bases, a commit of the landed
PR and a main commit, and `git merge-base` returns one. When the branch merged main after taking the
landed PR's commits, merging against that PR's commit drops the main history the branch already
holds, and a change main later reverted comes back. refresh.sh now considers every merge base, and
takes one only when each of the branch's ordinary merge bases with main is its ancestor; otherwise
the branch merges as it always has. Reproduced in a scratch repository: with the landed PR's commit
as base the merge kept the reverted f=1, the new rule rejects that base and git merge gives f=0;
a plain stack still takes the PR's commit and merges cleanly where git merge conflicts. On the real
branches #331, #332 and #341 still take a47e1bf (#330), and #383 takes none.
@DrunkOnJava
DrunkOnJava enabled auto-merge (squash) October 28, 2026 05:01
@DrunkOnJava
DrunkOnJava merged commit 04fe6ff into main Oct 28, 2026
24 checks passed
@DrunkOnJava
DrunkOnJava deleted the fix/train-stacked-base branch October 28, 2026 05:10
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