feat(gate): grade the merged-main projection + self-verify the required mount#24
Merged
Merged
Conversation
…ed mount Contract: the battery must block at PR time, evaluated against what the base branch BECOMES on merge, with the gate actually required. World: a tower shipped PRs that passed isolated CI yet reddened main on merge. Failure: (1) the gate ran on each PR's stale checked-out ref, not the merged-main projection — a branch forked before a change landed on main passed in isolation; (2) the required-check mount was procedural (DESIGN §4.8 PARTIAL), so even a correctly-failing gate could not block a merge. Merged-main projection: on pull_request the gate now checks out the PR head (a SHA) with full history and merges the CURRENT base branch into it, grading the result; a tree that cannot cleanly merge its base is refused, never silently passed. In-band self-verifying mount: a new step reuses check-required-mount.sh against the calling repo and REFUSES to pass unless the gate is a required, non-bypassable check — the Elegance Law's e2e on the gate itself, converting the mount from procedure into mechanism. Needs administration:read (declared in the workflow + granted in the caller stub). Adds templates/mount-required.sh (one-shot full-PUT apply that proves itself via the audit) and the runbook section. Scope: Python reusable-workflow path; TS parity is a fast-follow. Disjoint from the cf-no-bon-ref gauge PR (merges in any order). All workflow invariants preserved (33 tests: zero inputs, one aggregating battery step, no continue-on-error/paths, SHA-pinned uses). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…test) origin/main carries a ticket reference in ts/README.md that the kit's own no-ticket-ids self-test bans tree-wide — main is red on it. This is the identical one-line scrub also made in the cf-no-bon-ref gauge PR; git reconciles the matching change cleanly on merge. The lawgiver's house obeys the law. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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 free
to 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.
Contract → World → Failure
Contract: the battery must BLOCK at PR time, evaluated against what the base branch becomes on merge, with the gate actually required.
World: a tower shipped PRs that each passed isolated CI, yet two reddened
mainon merge (a 658-line file; lint-dirty code) and were fixed forward by hand.Failure: (1) the gate graded each PR's stale checked-out ref, not the merged-main projection — branches that forked before a change landed on
mainpassed in isolation; (2) the required-check mount was procedural (DESIGN §4.8, verdict PARTIAL), so even a correctly-failing gate could not block a merge (branches/main/protection→404 not protected).What this adds (two teeth)
1. Merged-main projection. On
pull_request, the gate checks out the PR head (a SHA) with full history and merges the current base branch into it, grading the result — never the default merge ref against a possibly-stale base. A tree that cannot cleanly merge its base is refused, not silently passed.2. In-band self-verifying mount. A new step reuses
check-required-mount.shagainst the calling repo and refuses to pass unless the gate is a required, non-bypassable check. The Elegance Law's e2e on the gate itself — a gate that cannot prove it is the law is treated as unmounted. Converts the mount from procedure into mechanism (the in-band leg of the previously out-of-band canary). Needsadministration: read(declared in the workflow, granted in the caller stub).Supporting:
templates/mount-required.sh(one-shot full-PUT apply that proves itself via the audit) + an enforcement-runbook section + the caller-stub permission grant.Verification
workflow_callinputs, exactly one aggregating battery step, nocontinue-on-error/paths, SHA-pinneduses:) plus new assertions for the projection step, the in-band canary, theadministration: readgrant, and the apply/audit script pair. YAML parses; shell syntax clean.cf-gatedirectly, not via this reusable workflow. A consumer dogfood (mount on one repo, push a stale-base PR + an unmounted-repo PR, confirm both are refused) is the next step.Scope
Python reusable-workflow path (per the scope decision). TS parity (
cf-gate-ts) is a fast-follow. Disjoint from thecf-no-bon-refgauge PR — they touch non-overlapping files and merge in any order.Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com