Uh oh!
There was an error while loading. Please reload this page.
fix(pm): window the governed-merge sweep on landing order, not committer dates (#12633) - #12643
Merged
Merged
Conversation
…ter dates (#12633) The merge queue writes a batch entry's commit when the batch is BUILT and main receives it when the batch LANDS, so a governed landing can sit above another commit on the first-parent chain while carrying an earlier committer date. A knife-edge --since boundary then drops it with nothing marking the gap, and the sweep prints a clean window at exit 0 — the one reading #4690 and #9902 forbid. --since-ref is now TOPOLOGICAL (REF..origin/main, per repo, repeatable as <repoId>=<ref>); a bare --since is backed off by a declared 3600 s skew budget and the report line says so; and the date window is closed topologically down to the deepest commit inside it, refusing to read clean when the walk never reached below the boundary.
This was referenced Aug 27, 2026
os-litant
marked this pull request as ready for review
August 27, 2026 03:03
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#12633
The merge queue writes a batch entry's commit when the batch is built, and
mainreceives it when the batch lands. Those are not the same moment, so a governed landing can sit above another commit onmain's first-parent chain — it landed later — while carrying an earlier committer date.git log --since=DATEcuts on committer date, so at a knife-edge boundary that landing is simply absent, with nothing in the output marking the gap; where it is the only governed landing in the window, the sweep prints✅ clean windowand exits 0 = "swept COMPLETELY", the one reading #4690 and #9902 say must never be producible.Implements the route ruled on the card — B for
--since-ref, A for--since. C (detect and refuse) and D (document) stay declined. The audit's report-only posture is unchanged, no judgment is weakened, and every pre-existing--self-testassertion is kept verbatim.What changed — one file,
scripts/pm/check-governed-merges.mjs--since-refis topological. The window is the first-parent range from the ref toorigin/main; committer dates are not consulted at all, so no skew of any size can move the boundary. Multi-repo: a bare--since-refis tried in every governed repo and used wherever it resolves, and--since-ref repoId=REFpins one repo (repeatable). A repo no ref resolves in falls back to the date window and its report line says so — one repo's ref silently dating four repos' windows is the same class of bug as the one being fixed. Recording the previous round's tip is the caller's obligation (this script keeps no state), so the PM assumption on the card is discharged by printing the line to use next round on every sweep:next round, exactly: --since-ref objectstack=SHA --since-ref objectui=SHA …. Bonus: for a topological window the Three seat-run tools ask windowed history questions with no shallow guard, so each answers plausibly and wrongly in an agent container #9902 horizon question answers itself — the ref being present in a checkout is necessary and sufficient for the range to be complete.--sinceis backed off by a declared budget,SKEW_BUDGET_SECONDS = 3600, and the report line states both boundaries and the back-off out loud, so a re-listed boundary entry reads as re-recognition rather than noise.WINDOW EDGE, the green tick is suppressed and the sweep exits 2.Part 3 is an addition to the ruled route A, not a substitute for it, and it is why the card's invariant now holds mechanically rather than up to a constant: a governed entry at a skew boundary is either listed, or the sweep is INCOMPLETE — never clean-and-absent.
Why 3600 s, and why not 874 s
git log --first-parent origin/mainThe re-measurement reproduces the card exactly (10 / max 874 s / median 539 s; one extra pair because
mainadvanced), and two of the ten inverted commits touch a governed surface. 3600 s is 1.86× the largest directly measured skew and 4.1× the largest inversion. It is deliberately not set to the measured maximum: a bound written exactly at today's worst case invalidates itself the first time a slower batch lands — the same trap as an upper bound pinned at the version that fixes it. The cost is re-listing whatever landed in the hour before the boundary; on the documented default (--since 24h) that widens the window by 4.2%, and consecutive default rounds already overlap by nearly a full day.Before / after
Real history, the card's own probe (enumeration only — the sweep minus its attribution round-trips, which are one GET per entry and have nothing to do with the window):
The two boundaries that used to disagree by one governed ADR now return the identical list. The
190 → 193growth is the hour of back-off plus the topological close, i.e. the re-listings named in the report line.End to end, real exit codes, on a constructed QS-7 repo (a queue chain whose governed entry landed above the round tip while dated 874 s — the measured maximum — before it; subjects carry no PR number on purpose, so the run costs zero API lookups and the exit code under test is the window's). The BEFORE column is the pristine
origin/maincopy of the script run against the same repo:The multi-repo half of route B, a ref that resolves in
objectstackbut not in the swept sibling — it falls back, names why, and still lists the governed entry:Verification
Union re-run after the final commit, on
fdff4bad1, one&&chain underscripts/pm/os-verify-lock.shso the verdict certifies all of it:covering
check:pm-governed-merges,check:pm-governed-prose,check:pm-dispatch-gates,bare-root-worklist --self-test,check-governed-queue-guard --self-test,ci-failure --self-test,check:nul-bytes,check:agent-test-spelling,check:bash32-floor,check:cli-command-ids,check:cross-package-test-inputs,check:entry-guard,check:parse-guard,check:pnpm-filter-targets,check-ci-filter-parity,check-skills-token-ratchet, and whole-repopnpm lint(no narrowing —eslint . --no-inline-config, 65 s). The gate family was derived from the diff bynode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, plus the two convention-triggered obligations it names for a gate-script edit, plus the three sibling scripts that import this module (check-governed-queue-guard,ci-failure,check-skills-token-ratchet) — an import is not a path literal, so the derivation cannot name them.Baseline on this tree was 159, not the 157 the card recorded —
mainmoved between the measurement and the dispatch; no pre-existing assertion was removed or weakened, and 34 were added. The new ones pin the QS-7 shape in both directions (the old bare cut drops the entry as a control; the budgeted window lists it), the topological close carrying an entry skewed past the budget, the unproven-boundary EDGE, the listed-or-INCOMPLETE invariant as a property over every fixture, the escalating floors (one walk in the ordinary case), per-repo--since-refresolution with its named fallback, and the window words an operator actually reads.Notes
node scripts/pm/check-governed-merges.mjs --test scripts/pm/check-governed-merges.mjs→NOT governed, exit 0, derived from the register rather than recalled.WINDOW EDGEis a backstop and the header says so. On a complete clone the widened walk always reaches the root commit, so it cannot fire; on a shallow one the Three seat-run tools ask windowed history questions with no shallow guard, so each answers plausibly and wrongly in an agent container #9902 horizon guard classifies the repo UNAUDITED before enumeration begins. It is the mechanical statement of an invariant that otherwise rests entirely on a predicate living in another file, and it is exercised in--self-testrather than by a real sweep.skip-changesetapplied: this is a CI-internal script that publishes nothing — the textbook case.github/workflows/lint.ymlnames in its own prose.Generated by Claude Code