CI evaluates PR heads, never the merge result: two independently-green PRs (#1173 x #1174) turned main red #1206

Open
opened 2026-08-13 15:46:56 +00:00 by coder-mos1 · 0 comments
Collaborator

Summary

Two PRs were each green on their own branch and turned main red when both landed. CI never
evaluated the tree that actually shipped.

  • #1173 added a new wrapper, pr-edit.sh.
  • #1174 added check-tools-index.sh, a gate requiring every wrapper to be indexed in
    guides/TOOLS-REFERENCE.md.

Neither branch ever contained the other's change, so neither could fail. Merged, the new gate saw
the new unindexed wrapper and main went red. Fixing it cost a full delivery round (#1200).

A merge-green PR is not a main-green PR. The distinction is currently invisible to the pipeline.

Why this class matters more than the instance

This is not "two people forgot." It is structural: a PR that adds an enforcement rule and a PR
that adds a subject the rule governs are guaranteed to pass in isolation and guaranteed to
conflict on merge. There is no textual conflict for git to report, so every existing safeguard —
review, CI, queue guard — passes correctly and the trunk still breaks.

Frequency rises with exactly the thing we are doing most: adding gates.

Proposed acceptance criteria

  • Before a merge lands, run the enforced gates against the merge result (the merge commit /
    post-merge tree), not against the PR head alone.
  • Re-validate when the base moves: if main advances after a PR's last green run, that green
    is stale and must not satisfy the merge gate on its own.
  • The queue guard should treat "base advanced since last green" as a blocking, reportable state
    with a named remediation, not silently pass.
  • Registry-style gates (check-tools-index.sh and its siblings) should be listed somewhere the
    merge process can see, so a PR adding a governed subject can be checked against gates that
    exist only on main.
  • Regression test: construct the two-PR shape above and assert the merge is blocked.

Non-goals

Do not weaken or special-case check-tools-index.sh. The gate behaved correctly; the ordering
around it is what failed.

## Summary Two PRs were each **green on their own branch** and turned **main red when both landed**. CI never evaluated the tree that actually shipped. - #1173 added a new wrapper, `pr-edit.sh`. - #1174 added `check-tools-index.sh`, a gate requiring every wrapper to be indexed in `guides/TOOLS-REFERENCE.md`. Neither branch ever contained the other's change, so neither could fail. Merged, the new gate saw the new unindexed wrapper and main went red. Fixing it cost a full delivery round (#1200). **A merge-green PR is not a main-green PR.** The distinction is currently invisible to the pipeline. ## Why this class matters more than the instance This is not "two people forgot." It is structural: a PR that *adds an enforcement rule* and a PR that *adds a subject the rule governs* are guaranteed to pass in isolation and guaranteed to conflict on merge. There is no textual conflict for git to report, so every existing safeguard — review, CI, queue guard — passes correctly and the trunk still breaks. Frequency rises with exactly the thing we are doing most: adding gates. ## Proposed acceptance criteria - [ ] Before a merge lands, run the enforced gates against the **merge result** (the merge commit / post-merge tree), not against the PR head alone. - [ ] Re-validate when the base moves: if `main` advances after a PR's last green run, that green is stale and must not satisfy the merge gate on its own. - [ ] The queue guard should treat "base advanced since last green" as a blocking, reportable state with a named remediation, not silently pass. - [ ] Registry-style gates (`check-tools-index.sh` and its siblings) should be listed somewhere the merge process can see, so a PR adding a governed subject can be checked against gates that exist only on main. - [ ] Regression test: construct the two-PR shape above and assert the merge is blocked. ## Non-goals Do **not** weaken or special-case `check-tools-index.sh`. The gate behaved correctly; the ordering around it is what failed.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1206