From bca98baa3495ae08e4da0363a6a3419d3303878d Mon Sep 17 00:00:00 2001 From: yoshi49535 Date: Tue, 4 Aug 2026 19:26:03 +0900 Subject: [PATCH] ci: promote E2E_REF to pins.env and let a job keep it current MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit e2e.yml gates every commit here against a pinned harness revision, and nothing noticed when that pin went stale: a harness fix lands over there, this gate keeps testing the version before it, and the runs stay green while saying less and less. It happened the day the gate was built, and again for the eight nights after 0.1.0 was cut. The counterpart repository used to report this by failing its own nightly job. That is replaced by a pair of workflows that file the work instead — this is the half that lives here. e2e-pin-bump.yml reads provin-line/e2e's nightly crosscheck (whose conclusion now means exactly "did the pair work" — the harness moved its own bookkeeping out of it for this reason), and when a harness revision has been proven green against this product's then-current HEAD it prepares the bump on chore/bump-e2e-pin and files an issue linking the run that proved it. e2e.yml on the bump pull request re-verifies the pairing against the actual merge target. When no proven revision exists, or the proven one is not strictly ahead of the pin, it does nothing: a bump nobody has tested is worse than a stale pin, and a backwards bump would weaken the gate while looking exactly like progress. The bumper refuses to touch a branch with an open pull request or a tip it did not write (committer checked as well as author — --amend preserves bot authorship), pushes with a force-with-lease pinned to the tip it inspected, and treats any non-default-ref dispatch as a forced dry run. E2E_REF had to leave the workflow file for any of that to work. Its comment anticipated a promotion "when a second pin appears"; a second pin has not appeared, but a harder constraint did — GITHUB_TOKEN has no `workflows` scope, so nothing running in CI can edit a pin that lives inside a workflow file, and a pin only a human can move is a pin that goes stale. The move costs one real property, stated plainly in pins.env rather than left for someone to discover: in the workflow file the pin was immune to pull request edits; as an ordinary file a pull request can change it. e2e.yml bounds that twice — exactly one E2E_REF line, a literal 40-hex commit id — and then re-asserts the checkout landed on the pinned revision after the fact, the same backstop the harness's own ci.yml gets from `make verify-pin`. The residual exposure is a pull request naming an OLDER harness, which every check passes and only review catches; pins.env says so in those words. This commit deliberately does not move the pin. It is the structural change only, so the first bump arrives through the mechanism rather than alongside it. --- .github/workflows/e2e-pin-bump.yml | 377 +++++++++++++++++++++++++++++ .github/workflows/e2e.yml | 78 +++++- pins.env | 49 ++++ 3 files changed, 495 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/e2e-pin-bump.yml create mode 100644 pins.env diff --git a/.github/workflows/e2e-pin-bump.yml b/.github/workflows/e2e-pin-bump.yml new file mode 100644 index 0000000..048bf8d --- /dev/null +++ b/.github/workflows/e2e-pin-bump.yml @@ -0,0 +1,377 @@ +# Keeps pins.env's E2E_REF from silently falling behind the harness, without +# ever asking by failing. +# +# e2e.yml gates every commit here against a pinned revision of +# provin-line/e2e, and nothing in that arrangement notices when the pin goes +# stale: a harness fix lands over there, this gate keeps testing the version +# before it, and the runs stay green while saying less and less. That is not +# hypothetical — it happened the day the gate was built, and again for eight +# consecutive nights after 0.1.0 was cut, which is what prompted this job. +# +# The evidence comes from provin-line/e2e's oss-crosscheck, which runs both +# runtimes nightly against that repository's HEAD and this one's. Its run +# conclusion means exactly "did the pair work" — the harness deliberately keeps +# its own bookkeeping (oss-pin-bump.yml, this file's mirror) OUT of that +# workflow so that gating on the conclusion here is sound. A green run proves a +# specific harness revision works against this product, so this job proposes +# exactly that revision and nothing newer. When no such run exists it does +# nothing at all: a bump nobody has tested is worse than a stale pin, because +# it converts a quiet gap into a red gate. +# +# Not a gate: no push or pull_request trigger, and a red run here never means +# the product or the harness is broken — only that this machinery is. The bump +# is prepared on a branch and tracked in an issue; the pull request is opened +# by a human, which is both what the organization's policy requires +# (GITHUB_TOKEN may not create pull requests) and what makes e2e.yml actually +# run on it. Reading the harness diff before merging is the part that wanted a +# human in the first place. +name: e2e-pin-bump + +on: + schedule: + # After provin-line/e2e's oss-crosscheck (41 22 * * *) has had time to + # finish. Nothing depends on that ordering being right — this job looks + # for the most recent green run at any time, not tonight's — but asking on + # the same day it was produced keeps the issue's timestamps legible. + - cron: '30 23 * * *' + # For rehearsal. On any ref other than the default branch, mutation is + # forced off (see DRY_RUN below), so a dispatch against a work branch is + # always a dry run regardless of the input. + workflow_dispatch: + inputs: + dry_run: + description: report what this would do, without pushing a branch or filing an issue + type: boolean + default: false + +permissions: + contents: read + +# The branch and the issue are shared mutable state; two runs interleaving +# (a dispatch overlapping the nightly) could double-file the issue or race the +# push. Queue instead. +concurrency: + group: e2e-pin-bump + cancel-in-progress: false + +jobs: + bump: + runs-on: ubuntu-latest + permissions: + # To push the bump branch. + contents: write + # To file, refresh and close the tracking issue. + issues: write + # To see whether the bump branch already has an open pull request. + pull-requests: read + env: + HARNESS: provin-line/e2e + CROSSCHECK: oss-crosscheck.yml + BRANCH: chore/bump-e2e-pin + ISSUE_TITLE: 'pins.env: E2E_REF is behind provin-line/e2e' + ISSUE_LABEL: pin-bump + BOT_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com + GH_TOKEN: ${{ github.token }} + # Two ways to be a dry run: asked for one, or running anywhere other + # than the default branch — a dispatch against a work branch must never + # mutate shared state from unreviewed history. Scheduled runs happen on + # the default branch with an empty input, so nightly operation is live. + DRY_RUN: ${{ inputs.dry_run == true || github.ref_name != github.event.repository.default_branch }} + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + # Full history: a push from a shallow clone is refused, and this job + # exists to push. + fetch-depth: 0 + + - id: evidence + name: which harness revision has been proven green? + run: | + set -o pipefail + # The newest crosscheck run that actually passed, on the harness's + # default branch (a constant here: the harness addresses its own + # default branch as main throughout). Its head_sha is the harness + # revision that run tested, which is the only revision this job is + # entitled to propose. + target=$(gh api \ + "repos/$HARNESS/actions/workflows/$CROSSCHECK/runs?branch=main&status=success&per_page=1" \ + --jq '.workflow_runs[0].head_sha // empty') + if [ -z "$target" ]; then + echo "no successful $CROSSCHECK run found in $HARNESS — nothing is proven yet." + echo "found=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + printf '%s' "$target" | grep -Eq '^[0-9a-f]{40}$' || { + echo "the crosscheck run reported a head_sha that is not a commit SHA: '$target'" + exit 1 + } + run_url=$(gh api \ + "repos/$HARNESS/actions/workflows/$CROSSCHECK/runs?branch=main&status=success&per_page=1" \ + --jq '.workflow_runs[0].html_url') + + # pins.env forbids naming a revision that is not on the branch it + # claims to track. A crosscheck run is recorded against main, but + # main can be rewritten afterwards, which would leave this pointing + # at a commit no longer reachable — stale the moment it is written, + # and quiet about it. + status=$(gh api "repos/$HARNESS/compare/${target}...main" --jq .status) + case "$status" in + ahead|identical) ;; + *) + echo "$target is no longer on $HARNESS's main (compare says '$status') — refusing to name it." + echo "found=false" >> "$GITHUB_OUTPUT" + exit 0 + ;; + esac + + echo "proven green: $target" + { + echo "found=true" + echo "target=$target" + echo "evidence=$run_url" + } >> "$GITHUB_OUTPUT" + + - id: decide + name: is pins.env behind that revision? + if: steps.evidence.outputs.found == 'true' + env: + TARGET: ${{ steps.evidence.outputs.target }} + run: | + current=$(sed -n 's/^E2E_REF=//p' pins.env | head -1) + # The value reaches a compare URL here and e2e.yml feeds its twin + # into a checkout ref — assert it is a commit id everywhere it is + # consumed, not just where it is written. + printf '%s' "$current" | grep -Eq '^[0-9a-f]{40}$' || { + echo "pins.env: E2E_REF must be a full 40-character commit SHA, got '$current'" + exit 1 + } + echo "current=$current" >> "$GITHUB_OUTPUT" + if [ "$current" = "$TARGET" ]; then + echo "pins.env names $current — current." + echo "behind=false" >> "$GITHUB_OUTPUT" + echo "reason=caught-up" >> "$GITHUB_OUTPUT" + exit 0 + fi + + # A pin only ever moves forward. "Newest green run" is not the same + # as "newer than the pin": when the crosscheck has been failing for + # a while, the newest GREEN one can predate the pin entirely, and + # proposing it would quietly revert the gate to an older harness + # while looking exactly like progress. On 2026-08-04 that was the + # live state — the newest green run was eight days older than the + # pin — which is how this check came to exist. + status=$(gh api "repos/$HARNESS/compare/${current}...${TARGET}" --jq .status) + if [ "$status" != "ahead" ]; then + echo "pins.env names $current" + echo "newest green $TARGET" + echo "compare says the proven revision is '$status' relative to the pin, not 'ahead' — nothing to propose." + echo "behind=false" >> "$GITHUB_OUTPUT" + echo "reason=not-ahead" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "pins.env names $current" + echo "proven green $TARGET" + echo "behind=true" >> "$GITHUB_OUTPUT" + + - id: branch + name: prepare the bump on a branch + if: steps.decide.outputs.behind == 'true' + env: + TARGET: ${{ steps.evidence.outputs.target }} + EVIDENCE: ${{ steps.evidence.outputs.evidence }} + run: | + set -o pipefail + # Three reasons to leave the branch alone, checked in order of how + # much a force-push would destroy: + # + # 1. An open pull request. Its reviewer read a specific diff, and its + # title and body name a specific target; force-pushing a newer one + # under them silently converts an approval of X into a merge of Y + # — and a GITHUB_TOKEN push would not even rerun e2e.yml on it. + # 2. A tip this job did not write. Someone took the branch to fix a + # bump by hand; their work is not this job's to overwrite. The + # committer is checked as well as the author because --amend + # preserves the original author — a hand-amended commit still + # carries the bot's authorship. + # 3. A tip that already says what tonight would say. + pr=$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number // empty') + if [ -n "$pr" ]; then + echo "pull request #$pr is open on $BRANCH — leaving it exactly as its reviewer sees it." + echo "state=in-review" >> "$GITHUB_OUTPUT" + echo "pr=$pr" >> "$GITHUB_OUTPUT" + exit 0 + fi + + lease="$BRANCH:" + if git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then + git fetch --quiet origin "$BRANCH" + remote_tip=$(git rev-parse FETCH_HEAD) + lease="$BRANCH:$remote_tip" + author=$(git log -1 --format=%ae FETCH_HEAD) + committer=$(git log -1 --format=%ce FETCH_HEAD) + if [ "$author" != "$BOT_EMAIL" ] || [ "$committer" != "$BOT_EMAIL" ]; then + echo "refusing to overwrite $BRANCH: its tip is by $author/$committer, not this job." + echo "state=blocked" >> "$GITHUB_OUTPUT" + exit 0 + fi + if git show "FETCH_HEAD:pins.env" | grep -q "^E2E_REF=${TARGET}\$"; then + echo "$BRANCH already names $TARGET — leaving it alone." + echo "state=unchanged" >> "$GITHUB_OUTPUT" + exit 0 + fi + fi + + git config user.name 'github-actions[bot]' + git config user.email "$BOT_EMAIL" + # Always from the default branch's tip as checked out by this run — + # never from a dispatch ref's history. The DRY_RUN guard makes a + # non-default dispatch inert anyway; this is the second lock on the + # same door. + git checkout --quiet -B "$BRANCH" "$GITHUB_SHA" + # Not `sed -i`: that spelling is GNU-only, and the difference does + # not surface until someone runs this logic somewhere other than the + # hosted Ubuntu runner — where it silently rewrites nothing and the + # commit below turns into an empty-tree failure instead of an error + # about the thing that actually went wrong. + rewritten=$(mktemp) + sed "s|^E2E_REF=.*|E2E_REF=${TARGET}|" pins.env > "$rewritten" + mv "$rewritten" pins.env + grep -q "^E2E_REF=${TARGET}\$" pins.env || { + echo "pins.env has no E2E_REF= line to rewrite — has its format changed?" + exit 1 + } + git add pins.env + git commit --quiet --file - <> "$GITHUB_OUTPUT" + exit 0 + fi + # The lease pins the push to the tip the ownership check above + # actually read. If anything moved the branch in between, the push + # fails instead of overwriting what it never inspected. + git push --quiet --force-with-lease="$lease" origin "$BRANCH" + echo "state=pushed" >> "$GITHUB_OUTPUT" + + - name: file or refresh the tracking issue + if: steps.decide.outputs.behind == 'true' + env: + TARGET: ${{ steps.evidence.outputs.target }} + EVIDENCE: ${{ steps.evidence.outputs.evidence }} + CURRENT: ${{ steps.decide.outputs.current }} + BRANCH_STATE: ${{ steps.branch.outputs.state }} + PR_NUMBER: ${{ steps.branch.outputs.pr }} + run: | + set -o pipefail + compare="$GITHUB_SERVER_URL/$HARNESS/compare/${CURRENT}...${TARGET}" + branch_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/tree/$BRANCH" + + # A compare link with quick_pull=1 lands on the pull request form + # with the title and body already filled in, so "open it" stays one + # click even though this job is not the one opening it. + pr_title="ci: move E2E_REF to ${TARGET:0:12}" + pr_body=$(printf '%s\n\n%s\n' \ + "Proven green by [oss-crosscheck]($EVIDENCE), which ran both runtimes against this harness revision." \ + "Read [what changed in the harness]($compare) before merging.") + quick_pull="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/compare/main...${BRANCH}?quick_pull=1" + quick_pull="${quick_pull}&title=$(printf '%s' "$pr_title" | jq -sRr @uri)" + quick_pull="${quick_pull}&body=$(printf '%s' "$pr_body" | jq -sRr @uri)" + + { + cat <Filed and refreshed by \`e2e-pin-bump.yml\`. It closes itself once \`pins.env\` catches up. + FOOT + } > "$RUNNER_TEMP/issue-body.md" + + number=$(gh issue list --state open --label "$ISSUE_LABEL" --limit 20 --json number,title \ + | jq -r --arg t "$ISSUE_TITLE" '.[] | select(.title == $t) | .number' | head -1) + + if [ "$DRY_RUN" = "true" ]; then + if [ -n "$number" ]; then + echo "dry run: would refresh issue #$number" + else + echo "dry run: would file a new issue" + fi + cat "$RUNNER_TEMP/issue-body.md" + exit 0 + fi + if [ -n "$number" ]; then + gh issue edit "$number" --body-file "$RUNNER_TEMP/issue-body.md" + else + gh label create "$ISSUE_LABEL" --description "filed by pin-bump automation" --force + gh issue create --title "$ISSUE_TITLE" --label "$ISSUE_LABEL" --body-file "$RUNNER_TEMP/issue-body.md" + fi + + - name: close the tracking issue once there is nothing left to bump + if: steps.decide.outputs.behind == 'false' + env: + TARGET: ${{ steps.evidence.outputs.target }} + CURRENT: ${{ steps.decide.outputs.current }} + REASON: ${{ steps.decide.outputs.reason }} + run: | + set -o pipefail + number=$(gh issue list --state open --label "$ISSUE_LABEL" --limit 20 --json number,title \ + | jq -r --arg t "$ISSUE_TITLE" '.[] | select(.title == $t) | .number' | head -1) + [ -n "$number" ] || exit 0 + # Two distinct ways to have nothing to bump, and the closing comment + # is a permanent record, so it must not claim the wrong one. + if [ "$REASON" = "caught-up" ]; then + comment="\`pins.env\` now names \`${TARGET}\`. Nothing left to bump." + else + comment="Nothing left to bump: \`pins.env\` names \`${CURRENT}\`, and the newest proven revision (\`${TARGET}\`) is not ahead of it." + fi + if [ "$DRY_RUN" = "true" ]; then + echo "dry run: would close issue #$number: $comment" + exit 0 + fi + gh issue close "$number" --comment "$comment" diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 7cd0c91..c405998 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -17,9 +17,11 @@ # # Bumping E2E_REF is deliberate work, same discipline as the harness's own # pins.env: read what changed in the harness, run both jobs, then commit the new -# SHA. It lives here rather than in a pins file because it has exactly one -# reader; promote it to a file when a second pin appears (a quickstart auth -# smoke would want the auth image digests, for instance). +# SHA. The pin used to live in this file's env: block on the grounds that it had +# exactly one reader. It now lives in ./pins.env — not because a second pin +# appeared, but because nothing automated can edit a pin inside a workflow file +# (GITHUB_TOKEN has no `workflows` scope), and a pin only a human can move goes +# stale. e2e-pin-bump.yml maintains it; pins.env states what that cost. # # Every action here is pinned to a commit SHA, unlike this repository's other # workflows. The original reason was that these steps handled a GitHub App @@ -45,10 +47,6 @@ on: permissions: contents: read -env: - # github.com/provin-line/e2e — the harness revision this commit is gated by. - E2E_REF: 9bfcce34430e6360a6db4c5fa3a02fa375a45573 - jobs: process: runs-on: ubuntu-latest @@ -61,6 +59,30 @@ jobs: uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: path: oss + # pins.env says in prose that a pin is a SHA and never a branch name; this + # makes that enforceable rather than aspirational. It matters more here + # than in the harness's mirror of it: this workflow runs on pull requests, + # including from forks, and pins.env is an ordinary file a pull request can + # edit. Exactly one E2E_REF line is accepted — `sed -n p` prints every + # match and a validator that checks "some line is a SHA" while a checkout + # consumes a different line is two behaviours wearing one assertion. + # This cannot stop a pull request from naming an OLDER harness — see + # pins.env on why that is a review question, not one a workflow can + # answer. What it names is verified AFTER checkout, below. + - id: pin + name: read and validate the harness pin + run: | + count=$(grep -c '^E2E_REF=' oss/pins.env || true) + if [ "$count" != "1" ]; then + echo "pins.env: expected exactly one E2E_REF= line, found $count" + exit 1 + fi + ref=$(sed -n 's/^E2E_REF=//p' oss/pins.env | head -1) + printf '%s' "$ref" | grep -Eq '^[0-9a-f]{40}$' || { + echo "pins.env: E2E_REF must be a full 40-character commit SHA, got '$ref'" + exit 1 + } + echo "e2e_ref=$ref" >> "$GITHUB_OUTPUT" # No credential: provin-line/e2e is public, so an anonymous checkout # reaches it. This used to mint a GitHub App installation token because # GITHUB_TOKEN is scoped to this repository and could not read a private @@ -71,11 +93,26 @@ jobs: uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: repository: provin-line/e2e - ref: ${{ env.E2E_REF }} + ref: ${{ steps.pin.outputs.e2e_ref }} path: e2e # Still false: checkout defaults to persisting GITHUB_TOKEN in the # clone's git config, and this clone has no use for it. persist-credentials: false + # The harness's own ci.yml re-asserts its checkout with `make verify-pin`; + # this is that backstop, pointed at this job's checkout. It makes the + # whole class of "the validator passed but the checkout landed somewhere + # else" dead rather than each instance patched: whatever string tricks + # survive the step above, the suite only runs if the tree IS the pinned + # revision. + - name: verify the harness landed on the pin + env: + EXPECTED: ${{ steps.pin.outputs.e2e_ref }} + run: | + have=$(git -C e2e rev-parse HEAD) + [ "$have" = "$EXPECTED" ] || { + echo "e2e checkout is at $have but pins.env names $EXPECTED" + exit 1 + } - name: point the harness at this oss checkout run: | mkdir -p e2e/repos @@ -103,13 +140,36 @@ jobs: uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: path: oss + - id: pin + name: read and validate the harness pin + run: | + count=$(grep -c '^E2E_REF=' oss/pins.env || true) + if [ "$count" != "1" ]; then + echo "pins.env: expected exactly one E2E_REF= line, found $count" + exit 1 + fi + ref=$(sed -n 's/^E2E_REF=//p' oss/pins.env | head -1) + printf '%s' "$ref" | grep -Eq '^[0-9a-f]{40}$' || { + echo "pins.env: E2E_REF must be a full 40-character commit SHA, got '$ref'" + exit 1 + } + echo "e2e_ref=$ref" >> "$GITHUB_OUTPUT" - name: checkout the pinned harness uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: repository: provin-line/e2e - ref: ${{ env.E2E_REF }} + ref: ${{ steps.pin.outputs.e2e_ref }} path: e2e persist-credentials: false + - name: verify the harness landed on the pin + env: + EXPECTED: ${{ steps.pin.outputs.e2e_ref }} + run: | + have=$(git -C e2e rev-parse HEAD) + [ "$have" = "$EXPECTED" ] || { + echo "e2e checkout is at $have but pins.env names $EXPECTED" + exit 1 + } - name: point the harness at this oss checkout run: | mkdir -p e2e/repos diff --git a/pins.env b/pins.env new file mode 100644 index 0000000..0b73cf0 --- /dev/null +++ b/pins.env @@ -0,0 +1,49 @@ +# External revisions this repository is gated against. +# +# A pin is a SHA, never a branch name. A branch tip moves, so a green run +# against one is not attributable to anything: the next run tests different +# code and nobody can say which change turned it red. CI checks out exactly +# this revision, so a bump is a reviewable diff carrying its own evidence +# rather than silent drift. +# +# Bumping a pin is deliberate work, the same discipline the harness applies to +# its own pins.env: read what changed in the harness, let both jobs run, then +# merge the new SHA. In practice e2e-pin-bump.yml has already done the running — +# it prepares the bump on chore/bump-e2e-pin only once provin-line/e2e's +# nightly crosscheck has proven that harness revision green against this +# product's then-current HEAD, and files an issue linking the run that proved +# it. e2e.yml on the bump pull request re-verifies the pairing against the +# actual merge target. What is left is the reading. +# +# Pin a commit that is ON the branch it claims to track — never a PR-branch +# SHA. A rebase or squash merge rewrites it, so such a pin is stale the instant +# the pull request lands while still resolving through the merged PR's ref, +# which is the worst of both: wrong and quiet. e2e-pin-bump.yml re-checks this +# property before proposing a SHA, because a scheduled job cannot be trusted to +# have read that paragraph. +# +# WHY THIS FILE EXISTS. E2E_REF lived in .github/workflows/e2e.yml until +# 2026-08-04, on the stated grounds that it had exactly one reader and should +# be promoted "when a second pin appears". A second pin has not appeared; a +# different reason did. GITHUB_TOKEN has no `workflows` permission — there is no +# such scope to grant under a workflow's `permissions:` key — so nothing running +# in CI can edit a pin that lives inside a workflow file. A pin that only a +# human can move is a pin that goes stale, which is the failure this file and +# its bumper exist to end. +# +# The move has a cost worth stating plainly, because it is a real one. While +# E2E_REF lived in the workflow file it was immune to pull request edits: +# `pull_request` runs use the BASE repository's workflow definition, so a fork +# could not choose which harness gated it. Here it is an ordinary file, and a +# pull request can change it — which is exactly what makes a bump reviewable, +# and also means a pull request can now choose which harness revision gates +# it. e2e.yml bounds that choice twice: the single-line 40-hex assertion +# confines the value to a literal commit id (never a ref string, never a +# second smuggled line), and a rev-parse after checkout confirms the tree IS +# that commit before anything runs. What remains is exactly what a review must +# catch: a pull request naming an OLDER harness proposes a weaker gate while +# every check passes. A change to this line is a change to the gate itself — +# read it as one. + +# github.com/provin-line/e2e — the harness revision this commit is gated by. +E2E_REF=9bfcce34430e6360a6db4c5fa3a02fa375a45573