From 38e4d91a851ac458e043280470eb12bdd5596eab Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Oct 2026 12:26:58 +0000 Subject: [PATCH 1/2] fix(ci): re-pin mirror and ci-pipeline off a commit that left main's reach MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mirror.yml and ci-pipeline.yml called standards reusables at 427eb35c. That commit is on #1301's branch only: #1301 merged as a squash with an empty diff and its branch was deleted at 2026-10-19T17:14:40Z. From the next push GitHub refused both callers at startup (failure, 0 jobs, run name == path): Mirror to Git Forges and Self CI on every main push since cd477f24, whose tree is identical to 333b06a0, where Mirror still ran. Re-pin all three calls to d55304a0 (on main, lock-selfcheck SELF-CONSISTENT) and relock with relock-standards-pin.sh. The reusables' inputs and secrets are unchanged between the two commits. relock-standards-pin.sh refused this relock: its stale-pin and entry-match scans read every line, so commented caller examples (`# uses: …@571cc734`) in three reusables counted as pins. Both scans now read `uses:` lines only, through one helper. New test case; it fails without the fix. The older per-forge job failures (host verify, push) are WO-2's and are untouched here. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01N6my4F3ohjwFReLW8cYYqC --- .github/workflows/actions.lock | 17 ++++++----------- .github/workflows/ci-pipeline.yml | 4 ++-- .github/workflows/mirror.yml | 2 +- scripts/relock-standards-pin.sh | 8 ++++++-- scripts/tests/relock-standards-pin-test.sh | 7 +++++++ 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock index ebb88ef7..64a2183d 100644 --- a/.github/workflows/actions.lock +++ b/.github/workflows/actions.lock @@ -35,7 +35,7 @@ workflows: '.github/workflows/ci-pipeline.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - 'haskell-actions/setup@0f8e8c99d88aeb3fbfd523f1ef2c6f762d10d64d' - - 'hyperpolymath/standards@427eb35c40552d912d8c757518e8326f0d20f597' + - 'hyperpolymath/standards@d55304a01b5260b0511aae0d14ed8b8770b00293' - 'oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6' '.github/workflows/codeql-reusable.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' @@ -109,7 +109,7 @@ workflows: - 'dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8' - 'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555' '.github/workflows/mirror.yml': - - 'hyperpolymath/standards@427eb35c40552d912d8c757518e8326f0d20f597' + - 'hyperpolymath/standards@d55304a01b5260b0511aae0d14ed8b8770b00293' '.github/workflows/no-js-scan.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' '.github/workflows/pages-archive.yml': @@ -239,11 +239,6 @@ dependencies: commit: 'sha1-683b588c487a69d01f6c6ddf40f036ff682cc2c8' owner_id: 1940490 repo_id: 260749683 - 'dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f': - ref: 'v1' - commit: 'sha1-e2a55d2ffb04f378e9626c28d38b36d230d1e12f' - owner_id: 1940490 - repo_id: 260749683 'editorconfig-checker/action-editorconfig-checker@51f63319f592f97930c73d9c46184d20bd206393': ref: 'v3.0.0' commit: 'sha1-51f63319f592f97930c73d9c46184d20bd206393' @@ -269,14 +264,14 @@ dependencies: commit: 'sha1-0f8e8c99d88aeb3fbfd523f1ef2c6f762d10d64d' owner_id: 75048950 repo_id: 623796603 - 'hyperpolymath/standards@427eb35c40552d912d8c757518e8326f0d20f597': - ref: '427eb35c40552d912d8c757518e8326f0d20f597' - commit: 'sha1-427eb35c40552d912d8c757518e8326f0d20f597' + 'hyperpolymath/standards@d55304a01b5260b0511aae0d14ed8b8770b00293': + ref: 'd55304a01b5260b0511aae0d14ed8b8770b00293' + commit: 'sha1-d55304a01b5260b0511aae0d14ed8b8770b00293' owner_id: 6759885 repo_id: 1116521501 uses: - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f' + - 'dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8' - 'goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406' - 'swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6' - 'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555' diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 6b69f765..d0e7dc32 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -319,7 +319,7 @@ jobs: name: Secret scanning # Deliberately NOT gated on `detect`: a repo with no recognised ecosystem # can still be leaking credentials. - uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@427eb35c40552d912d8c757518e8326f0d20f597 + uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@d55304a01b5260b0511aae0d14ed8b8770b00293 with: runs-on: ${{ inputs.runs-on }} @@ -330,7 +330,7 @@ jobs: name: Rust needs: detect if: ${{ needs.detect.outputs.has_rust == 'true' }} - uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@427eb35c40552d912d8c757518e8326f0d20f597 + uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@d55304a01b5260b0511aae0d14ed8b8770b00293 with: runs-on: ${{ inputs.runs-on }} enable_coverage: ${{ inputs.enable_coverage }} diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index 9298823f..a80c824e 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -14,7 +14,7 @@ permissions: jobs: mirror: - uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@427eb35c40552d912d8c757518e8326f0d20f597 + uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@d55304a01b5260b0511aae0d14ed8b8770b00293 # Exactly the seven optional secrets the callee declares at the # pinned SHA (verified declared ⊇ referenced). Was `secrets: # inherit`, which forwarded every repo/org secret (standards#1108 diff --git a/scripts/relock-standards-pin.sh b/scripts/relock-standards-pin.sh index 34b98887..f1f28694 100755 --- a/scripts/relock-standards-pin.sh +++ b/scripts/relock-standards-pin.sh @@ -70,7 +70,11 @@ PIN_RE='hyperpolymath/standards/\.github/workflows/[A-Za-z0-9._-]+\.ya?ml@[0-9a- shopt -s nullglob wfs=("$WF"/*.yml "$WF"/*.yaml) shopt -u nullglob -pins=$(grep -hoE "$PIN_RE" "${wfs[@]}" 2>/dev/null | sort -u || true) +# standards_pins FILE... — the standards reusable pins on `uses:` lines only. +# Reusables carry commented caller examples (`# uses: …@`) that no +# run resolves; counting them refused every relock of standards' own callers. +standards_pins() { grep -hE "^[[:space:]]*-?[[:space:]]*uses:" "$@" 2>/dev/null | grep -oE "$PIN_RE"; } +pins=$(standards_pins "${wfs[@]}" | sort -u || true) # A short pin (7+ hex) that prefixes TARGET names TARGET: the applier counts it # FRESH and leaves it as written, and the lock keys it by that short ref in a # record of its own, which is left as it is. Only full pins feed TARGET's record. @@ -218,7 +222,7 @@ dangling=$(LC_ALL=C comm -23 "$tmp/edges" "$tmp/recs") # The gates match an entry to a `uses:` by its ref as written, so an entry # re-keyed to TARGET for a workflow that pins a short ref is a desync they reject. for w in "${wfs[@]}"; do - want=$(grep -oE "$PIN_RE" "$w" | sed 's#^hyperpolymath/standards/.*@#hyperpolymath/standards@#' | LC_ALL=C sort -u || true) + want=$(standards_pins "$w" | sed 's#^hyperpolymath/standards/.*@#hyperpolymath/standards@#' | LC_ALL=C sort -u || true) have=$(awk -v k=" '.github/workflows/${w##*/}':" '$0==k{f=1;next} f&&!/^ - /{exit} f' "$tmp/out" \ | grep -oE "'hyperpolymath/standards@[0-9a-fA-F]+'" | tr -d "'" | LC_ALL=C sort -u || true) [ "$want" = "$have" ] || refuse "${w##*/}: lock entries [${have//$'\n'/ }] would not match its pins [${want//$'\n'/ }]" diff --git a/scripts/tests/relock-standards-pin-test.sh b/scripts/tests/relock-standards-pin-test.sh index bdb202fe..fa4d7889 100755 --- a/scripts/tests/relock-standards-pin-test.sh +++ b/scripts/tests/relock-standards-pin-test.sh @@ -180,6 +180,13 @@ cp "$D/actions.lock" "$T/once"; bash "$RELOCK" --to "$NEW" --standards "$S" "$D" cmp -s "$T/once" "$D/actions.lock" || fail "second run changed the lock" echo " PASS idempotent" +# A commented caller example pinned at another commit is not a pin. +D=$(consumer commented-example) +printf '# Caller example:\n# uses: hyperpolymath/standards/.github/workflows/x-reusable.yml@%s\n' "$OLD" >> "$D/caller.yml" +bash "$RELOCK" --to "$NEW" --standards "$S" "$D" >/dev/null 2>&1 || fail "a commented caller example at another commit refused the relock" +grep -q "^ 'hyperpolymath/standards@$NEW':\$" "$D/actions.lock" || fail "commented example: no record for the new pin" +echo " PASS a commented caller example at another commit is not counted as a pin" + # 3. Refusals leave the lock byte-identical. refuse_case() { # name mutate-command local d; d=$(consumer "$1"); eval "$2"; cp "$d/actions.lock" "$T/before" From b3862040a6ba91f63f7e252b0fa9a724d81076f0 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Oct 2026 12:42:15 +0000 Subject: [PATCH 2/2] fix(lock): count flow-style reusable calls in relock-standards-pin's pin scan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous commit anchored the pin scan at `^\s*-?\s*uses:` to stop counting commented caller examples. That also dropped one-line flow (KYAML) calls such as `build: { uses: "hyperpolymath/standards/…@" }`, which the old unanchored scan found: a relock of such a caller would refuse with no full target pin. Skip full-line comments instead, and take the pin wherever a `uses:` key holds it, block or flow style. New test case; it fails on the anchored scan. (Codex review on #1317.) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01N6my4F3ohjwFReLW8cYYqC --- scripts/relock-standards-pin.sh | 13 +++++++++---- scripts/tests/relock-standards-pin-test.sh | 7 +++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/scripts/relock-standards-pin.sh b/scripts/relock-standards-pin.sh index f1f28694..ecb05431 100755 --- a/scripts/relock-standards-pin.sh +++ b/scripts/relock-standards-pin.sh @@ -70,10 +70,15 @@ PIN_RE='hyperpolymath/standards/\.github/workflows/[A-Za-z0-9._-]+\.ya?ml@[0-9a- shopt -s nullglob wfs=("$WF"/*.yml "$WF"/*.yaml) shopt -u nullglob -# standards_pins FILE... — the standards reusable pins on `uses:` lines only. -# Reusables carry commented caller examples (`# uses: …@`) that no -# run resolves; counting them refused every relock of standards' own callers. -standards_pins() { grep -hE "^[[:space:]]*-?[[:space:]]*uses:" "$@" 2>/dev/null | grep -oE "$PIN_RE"; } +# standards_pins FILE... — the standards reusable pins that a `uses:` key holds, +# block or flow style (`build: { uses: "…@" }`). Full-line comments are +# skipped: reusables carry commented caller examples (`# uses: …@`) +# that no run resolves, and counting them refused every relock of standards' +# own callers. +standards_pins() { + grep -hvE '^[[:space:]]*#' "$@" 2>/dev/null \ + | grep -oE "(^|[{,[:space:]])uses:[[:space:]]*['\"]?$PIN_RE" | grep -oE "$PIN_RE" +} pins=$(standards_pins "${wfs[@]}" | sort -u || true) # A short pin (7+ hex) that prefixes TARGET names TARGET: the applier counts it # FRESH and leaves it as written, and the lock keys it by that short ref in a diff --git a/scripts/tests/relock-standards-pin-test.sh b/scripts/tests/relock-standards-pin-test.sh index fa4d7889..69297451 100755 --- a/scripts/tests/relock-standards-pin-test.sh +++ b/scripts/tests/relock-standards-pin-test.sh @@ -187,6 +187,13 @@ bash "$RELOCK" --to "$NEW" --standards "$S" "$D" >/dev/null 2>&1 || fail "a comm grep -q "^ 'hyperpolymath/standards@$NEW':\$" "$D/actions.lock" || fail "commented example: no record for the new pin" echo " PASS a commented caller example at another commit is not counted as a pin" +# A flow-style (KYAML) call is still a pin. +D=$(consumer flow-style) +printf 'on: push\njobs: { call: { uses: "hyperpolymath/standards/.github/workflows/x-reusable.yml@%s" } }\n' "$NEW" > "$D/caller.yml" +bash "$RELOCK" --to "$NEW" --standards "$S" "$D" >/dev/null 2>&1 || fail "a flow-style call refused the relock" +grep -q "^ - 'hyperpolymath/standards@$NEW'\$" "$D/actions.lock" || fail "flow-style: workflow entry not re-keyed" +echo " PASS a flow-style call is counted as a pin" + # 3. Refusals leave the lock byte-identical. refuse_case() { # name mutate-command local d; d=$(consumer "$1"); eval "$2"; cp "$d/actions.lock" "$T/before"