Skip to content

Merge guard: read the required checks' buckets, not gh pr checks' exit code (a cancelled required check exits 0) - #494

Merged
seathatflowsinourveins merged 2 commits into
mainfrom
claude/merge-guard-buckets-20260929
Sep 29, 2026
Merged

seathatflowsinourveins merged 2 commits into
mainfrom
claude/merge-guard-buckets-20260929

Conversation

@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator

Scope

  • What this PR changes: the merge-guard text that GitHub practice: document the --match-head-commit merge guard; re-require sota-sources #430 added. docs/lanes.md documented gh pr checks <N> --required as a pre-merge read whose exit code says whether every required check passed. That is wrong: a cancelled required check exits 0, and a failed check wins over a pending one. The guard now prints the required-check count and the set of buckets (--json name,bucket) and merges only on pass with the ruleset's count. The decision record gets a dated correction, the anti-pattern log a row, and a structural test fails if the text drifts back.
  • Base commit: 3ce6f532 (main, after Token report: retain selected upstream usage, status and cache reports beside each tool's row #415), merged in by the hot-file protocol; head e845256a.
  • Lane: lane:shared. docs/lanes.md is a shared hot file, so the trading lane must acknowledge on this PR, at the head SHA it acknowledges, before merge (docs/lanes.md L149-150). No trading path changes.
  • Owned paths touched: docs/lanes.md (merge-guard block and its first bullet), docs/decisions/2026-09-22-github-automation-closure.md (correction after the "Merge-guard mechanics" entry), docs/harness-defaults.md (one anti-pattern row), tests/test_merge_guard_doc.py (new), manifests/evidence.json (re-registration, last commit).

SOTA sources

  • cli/cli v2.101.0 pkg/cmd/pr/checks/checks.go L248-252: if counts.Failed > 0 { return cmdutil.SilentError } else if counts.Pending > 0 { return cmdutil.PendingError }, otherwise nil. L189-191: the JSON export returns before that logic, so --json exits 0 in every state. L70-75: the help names the bucket field (pass, fail, pending, skipping, cancel) and "Additional exit codes: 8: Checks pending".
  • cli/cli v2.101.0 pkg/cmd/pr/checks/aggregate.go L72-88: CANCELLED becomes bucket cancel and increments counts.Canceled, which the exit logic never reads; SKIPPED and NEUTRAL become skipping.
  • gh pr checks manual: the --required and --json flags.

Evidence-class table

Claim Evidence class Command / result
A cancelled required check makes gh pr checks --required exit 0 local integration, measured 2026-09-29 on #437 (its queued validate-macos run cancelled on purpose) rtk proxy gh pr checks 437 --required: seven pass rows and validate-macos fail, exit 0; --json name,bucket: validate-macos bucket cancel; --jq line prints 8 required checks, buckets: cancel,pass
The exit-code precedence and the bucket mapping source review (gh v2.101.0, the lines above); not run the linked lines
The new read prints pass only when every required check passed local integration on #415 before its merge: 8 required checks, buckets: pass; on #409, #417 and #492 while validate-macos was pending: 8 required checks, buckets: pass,pending
The ruleset lists 8 required contexts source review .github/main-ruleset.json; the test compares the documented count with it
The text cannot silently drift back local integration tests/test_merge_guard_doc.py: 3 tests fail against the previous docs/lanes.md (red-first, 3 failures) and pass now

Local commands run

Measured 2026-09-29 by the coordinator at head e845256a; local integration checks, not upstream tests.

$ TMPDIR=/var/tmp/... python3 -B -m unittest tests.test_merge_guard_doc tests.test_adoption_docs_consistency
Ran 40 tests ... OK (skipped=1)
$ python3 -B -m unittest tests.test_blind_checkout tests.test_osv_lockfile_coverage tests.test_workflow_security_coverage
Ran 80 tests ... OK
$ python3 -B scripts/validate.py; scripts/evidence_manifest.py --check; scripts/component_matrix.py --check    (run by the merge script)   exit 0
$ python3 -B scripts/new_host_grand_list.py --check   {"status": "passed", "layers": 32, "winners": 66}
$ python3 -B scripts/build_ecosystem.py --check   status passed

Decision record

docs/decisions/2026-09-22-github-automation-closure.md, "Correction (2026-09-29, after the entry above)": it keeps the earlier measured entries (passing, failing and pending PRs gave exit 0, 1 and 8, which fits the source) and adds the cancelled case, the failed-beats-pending precedence, why no merge was wrongly allowed (GitHub's ruleset still refuses a cancelled required check), and the overturn condition (a newer gh that counts cancel as failing or changes the --json exit code; re-read checks.go when the pinned gh moves).

Residuals

  • Nothing here was reviewed by a second family: it is a documentation correction backed by source lines and one measurement, and the structural test is a local check of the text, not an upstream test. The trading-lane acknowledgement is the review it needs.
  • The bucket read cannot tell that a required check never started when the list is shorter than the ruleset's; the doc says to compare the count, and GitHub refuses the merge anyway while a required check is missing.

Checklist

  • No workflows or Actions are changed.
  • No secrets are printed, logged or committed.
  • No new paid hosting, subscription or billing surface.
  • Peer-owned untracked files and worktrees were preserved.

🤖 Generated with Claude Code

Scout and others added 2 commits September 29, 2026 01:07
…t code

`gh pr checks --required` exits 0 for a cancelled required check (gh v2.101.0
checks.go L248-252: only failed and pending change the exit code; aggregate.go
L72-88 sends CANCELLED to bucket cancel), and a failed check wins over a
pending one. Measured on #437 after its macOS smoke run was cancelled. The
documented guard printed the exit code as the verdict; it now prints the count
and the set of buckets and merges only on `pass`. Adds a dated correction to the
merge-guard mechanics entry, an anti-pattern log row and a structural test that
fails on the previous text.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
…t, branch files re-registered)

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
@seathatflowsinourveins seathatflowsinourveins added the lane:shared Touches files owned by both lanes; needs both lanes' acknowledgement label Sep 29, 2026
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

Trading lane acknowledgement (docs/lanes.md:149-150). Reviewed at head e845256a by ecosystem-roadmap-2026, which holds the trading lane.

  • Scope: docs, one merge-guard doc test and the evidence re-registration. No trading paths.
  • Effect on trading PRs: the corrected guard, which merges only when every required check's bucket is pass, applies to them too. This lane will follow it.

No objection.

@seathatflowsinourveins
seathatflowsinourveins merged commit 16f3c7f into main Sep 29, 2026
25 checks passed
@seathatflowsinourveins
seathatflowsinourveins deleted the claude/merge-guard-buckets-20260929 branch September 29, 2026 05:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:shared Touches files owned by both lanes; needs both lanes' acknowledgement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant