Skip to content

chore(ci): bump standards pins fcb566cf → e977cc67, regenerating actions.lock in the same commit - #226

Merged
hyperpolymath merged 2 commits into
mainfrom
chore/bump-standards-pins-e977cc67
Sep 22, 2026
Merged

hyperpolymath merged 2 commits into
mainfrom
chore/bump-standards-pins-e977cc67

Conversation

@hyperpolymath

@hyperpolymath hyperpolymath commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #225.

All three checks that were red on main after #224 merged share one cause: burble was pinned
to hyperpolymath/standards@fcb566cf (2026-09-07), which predates two upstream fixes. Both are now
on standards main, so this is a pure pin bump with no upstream work outstanding.

red check defect at the old pin fixed by
Workflow syntax and action locks (step 6) wrapper counted advisory findings as blocking standards#946, merged 09-22T09:46Z
governance / Actions lockfile verify (step 5) same wrapper, reached via a standards checkout at the same pin same
scan / Hypatia Neurosymbolic Analysis (step 9) validator's severity list omitted warn; 14 of 144 findings are warn already on standards main

What changed

Six workflow files, nine replacements, all to e977cc67:

  • governance.yml:21, hypatia-scan.yml:25, scorecard.yml:20, secret-scanner.yml:21,
    spark-theatre-gate.yml:18 — reusable-workflow refs
  • workflow-safety.yml:46,54 — the two curl URLs, and both sha256sum -c - digests,
    recomputed from the fetched files (dd5b1308…→476027a9…, 2361fc7e…→877902ec…)

Plus actions.lock, regenerated in the same commit.

mirror.yml (pinned 4d104d32) is deliberately out of scope.

Why the lock had to move with it

Bumping the YAML alone would have recreated the exact desync that killed this repo at startup in
#223. The stale SHA lived in actions.lock too — five per-workflow list items and one dependency
block.

gh actions-lock cannot do this itself. It is blind to job-level reusable-workflow refs
(github/gh-actions-lock#129), so a regeneration run left the standards entries untouched and
instead pruned eight unrelated orphan entries. The standards entry was therefore updated by hand,
including its transitive uses: list, which the reusables moved upstream:

action old new
editorconfig-checker v2.2.0 v3.0.0
github/codeql-action v4.37.9 v4.38.1

That transitive list was not guessed. The extraction method was positive-controlled first: run
against the old reusables it reproduced the seven entries already recorded in the lock exactly,
with no additions or omissions; only then was it trusted against the new ones.

Verified before pushing

probe result
scripts/check-lock-sync.sh rc=0
post-#946 wrapper --verify-local run against this tree rc=0 — predicts step 6 green
uses: $/... rewrites 0
old SHA anywhere in .github/workflows/ 0
five reusables exist at e977cc67 5 × HTTP 200
workflow_call contracts compatible both directions — no required input added, none that burble passes removed
lock diff 16 insertions / 16 deletions, every line accounted for

The gate added in #224 was also mutant-tested against this exact change class: a fake SHA on
governance.yml:21 with the lock untouched takes it from rc=0 to rc=1, flagged in both
directions. It is not vacuous for the one thing this PR does.

Expectations

This crosses ~15 days of standards history across five reusables at once. Per the standing stopping
rule, any new red that appears after the bump is an issue with acceptance criteria, not a reason
to revert — the pins are stale in every direction today, and reverting restores the three reds in
#225.

Two housekeeping notes, neither blocking: the eight orphan lock entries gh actions-lock wanted to
prune are left alone as unrelated churn, and the tool's duplicate-banner bug
(github/gh-actions-lock#130) was stripped from the five touched files so the diff carries only the
deliberate change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01X3hgXxWm6umMgZkjYyHnnm

Summary by CodeRabbit

  • Chores
    • Updated the versions of automated governance, security scanning, scorecard, secret scanning, and quality-gate checks.
    • Refreshed verification checksums and the security baseline used by workflow safety validation.
    • Existing permissions and workflow behavior remain unchanged.

Cures all three red checks on main, which share one cause: burble was
pinned to a standards SHA predating two upstream fixes.

  governance / Actions lockfile verify   \ both are the same wrapper defect,
  Workflow syntax and action locks       / fixed by standards#946
  scan / Hypatia Neurosymbolic Analysis    severity list omitted "warn"

Bumped, all to e977cc67:
  governance.yml:21, hypatia-scan.yml:25, scorecard.yml:20,
  secret-scanner.yml:21, spark-theatre-gate.yml:18   (reusable refs)
  workflow-safety.yml:46,54                          (curl URLs)
and both sha256sum digests recomputed from the fetched files:
  update-actions-lock.sh   dd5b1308... -> 476027a9...
  estate-baseline.toml     2361fc7e... -> 877902ec...

actions.lock is regenerated in the SAME commit. Bumping the YAML alone
would recreate the desync that killed this repo at startup (#223): the
stale SHA appears in the lock as five per-workflow list items and one
dependency block. `gh actions-lock` cannot do this itself -- it is blind
to job-level reusable-workflow refs (github/gh-actions-lock#129) and
leaves the standards entries untouched -- so the entry was updated by
hand, including its transitive uses: list, which the reusables moved:
  editorconfig-checker  v2.2.0  -> v3.0.0
  github/codeql-action  v4.37.9 -> v4.38.1

Verified before pushing:
  scripts/check-lock-sync.sh                     rc=0
  post-#946 wrapper --verify-local on this tree  rc=0  (predicts step 6)
  no `uses: $/...` rewrites                      0
  reusable workflow_call contracts               compatible both directions

mirror.yml (pinned 4d104d32) is deliberately out of scope.

Closes #225

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X3hgXxWm6umMgZkjYyHnnm
@hyperpolymath

Copy link
Copy Markdown
Collaborator Author

Status: 2 reds left, both diagnosed, neither a defect in this PR

Cured by this PR ✅ — scan / Hypatia Neurosymbolic Analysis and
Workflow syntax and action locks, both green on 2b4e6be.

1. governance / Actions lockfile verify — needs a standards merge and a re-bump here

The lock gate is staged from a third pin: a SHA hardcoded inside governance-reusable.yml for
its own actions/checkout, independent of this PR's uses: ref and of actions.lock. The failing
job logs HEAD is now at 4f7f02c — a commit older than the e977cc67 this PR pins, and one that
predates standards#946's fix to the verifier.

Fix: hyperpolymath/standards#962, which bumps that pin and adds a freshness guard so it cannot
rot again (10 mutant controls; Repo self-tests green in CI).

⚠ Merging #962 will not turn this PR green on its own. This PR pins e977cc67, and that copy
of the workflow still carries 4f7f02ca. Pin 3 travels with the pinned YAML.

Required sequence: merge standards#962 → take the new standards main SHA → re-bump this PR
to it
(all 9 sites + actions.lock, transitive uses: list re-extracted against a positive
control) → green.

2. scan / gitleaks — not a defect in this PR

One finding, in git history only (the working-tree scan reports no leaks found):
generic-api-key at input_sanitizer_test.exs:94 in commit e8e6020d from 2026-03-24. The string
is abc123-_DEF= — a base64url alphabet sample in a test asserting the sanitizer accepts a valid
token. Not a credential; nothing to rotate.

It appeared now because this PR's pin bump switched on a new gating step: the standards
secret-scanner-reusable.yml has Gitleaks secret scan — git history (gating) at 9c256b67 and
does not have it at fcb566cf, which is what main pins. gitleaks was green on burble main
at 09:50 today and on the #224 branch.

Filed as #227, with the estate-wide consequence: ~368 governance callers inherit a gating
git-history secret scan on their next pin bump.

I will fold the one-line .gitleaksignore classification into the re-bump commit, since this PR has
to be touched again anyway.

🤖 Generated with Claude Code

https://claude.ai/code/session_01X3hgXxWm6umMgZkjYyHnnm

hyperpolymath added a commit to hyperpolymath/standards that referenced this pull request Sep 22, 2026
…it past #946 (#962)

## What this fixes

The lock gate is staged from a **third pin**.

There are not two pins in this system, there are three:

1. the caller's `uses: hyperpolymath/standards/...@<sha>` ref,
2. `actions.lock`'s record of that ref, and
3. **a SHA hardcoded inside `governance-reusable.yml`** for its own
   `actions/checkout` of the lock-gate tooling.

Bumping a caller cannot reach the third one. A *called* reusable
workflow has no
reliable context exposing its own commit (`github.workflow_sha` resolves
to the
**caller's**), which is what forces the hardcode in the first place.

`standards#946` fixed `scripts/update-actions-lock.sh` so advisory
findings stop
counting toward the blocking tally — and did not bump pin 3. So every
caller
kept being judged by the **pre-#946** verifier, including

[`metadatastician/burble#226`](metadatastician/burble#226),
which had bumped its own pin *specifically to pick that fix up* and
still went
red on `governance / Actions lockfile verify`.

Measured, not inferred: the failing job logs `HEAD is now at 4f7f02c`,
and the
two wrappers disagree on the same tree —

| wrapper staged from | `--verify-local` rc | `grep -c
is_advisory_category` |
|---|---|---|
| `4f7f02ca` (what CI ran) | **1** | 0 |
| `e977cc67` (post-#946) | **0** | present |

## Why no existing control caught it

The pin's **shape** was already guarded, correctly:
`tests/test_governance_reusable_shape.sh:63-64` asserts `ref:
[0-9a-f]{40}` and
refuses `ref: main`, scoped to the `actions-lock-verify` job.

Its **currency** was guarded by nothing. A perfectly well-formed 40-hex
SHA can
point at stale tooling, and this one did for the whole life of #946.

That is the guard/consumer trap in its plainest form: **the guard asks
"is this
40 hex characters?", the consumer needs "does this contain today's
verifier?"**

The file already carried a `⚠ BUMP THIS whenever ... changes` comment. A
comment
is not a gate, and this PR is the difference.

Separately, `scripts/tests/governance-reusable-contract-test.sh` bound
its
checkout assertions only to the step named `Checkout the pinned
Standards policy
helpers` — the **dupkey** step. The lock gate is a *different* step,
`Checkout standards for the lock gate`, and the two share the nouns
"checkout",
"pinned" and "standards", so a name-match guard written for one proves
nothing
about the other. It now names the lock-gate step too.

## The predicate, and why it is not the obvious one

The obvious assertion — *the pin contains the working tree's helpers* —
**deadlocks**. A PR that edits a helper would have to pin to its own
merge
commit, which does not exist yet. Unsatisfiable-in-PR is the same
failure class
as a required check that can never report.

So the assertion is:

> the pinned commit must already contain everything on the **compare**
ref,
> path-scoped to the step's own `sparse-checkout:` list.

- **`pull_request`** → compare is the PR's base SHA. A PR that edits a
helper
**passes** (its edit is not on base yet). A PR opened while `main` is
*already*
stale is **forced to bump**, and can, because the needed commit exists.
- **`push` to `main`** → compare is `HEAD`. Red exactly when a helper
change has
just landed and the bump is owed; healed by the very next PR, which the
  `pull_request` run will not let through unbumped.

Under this predicate, **#954 would have been forced to bump after #946
landed**,
and burble#226 would have gone green on its first attempt.

The pin is therefore **one change behind by construction**. That is
inherent, it
is acceptable, and the comment at the pin now says so rather than asking
a human
to remember.

Comparison is **path-scoped**, so a rebase or any unrelated commit
cannot fail
it — only a real divergence in the staged tooling can.

**Scope is read out of the step's own `sparse-checkout:` list, never
hardcoded**,
so adding a file to what the gate stages automatically extends what the
guard
protects. A hardcoded list here would itself be a guard asking a
different
question than its consumer.

## Verification

`scripts/tests/check-lock-gate-pin-freshness-test.sh` — **10 controls**,
each
against a throwaway git repo with real commits, fully offline:

| control | asserts |
|---|---|
| stale pin is refused | rc=1, names `scripts/update-actions-lock.sh` |
| stale report is path-scoped | never names the unrelated file that also
changed |
| fresh pin is accepted | rc=0 |
| unrelated divergence does not fail it | a rebase must not redden the
gate |
| `ref: main` is refused | pinning is the point |
| abbreviated sha is refused | 40-hex only |
| **renamed step fails loudly** | rc=1 — the exact way the contract test
lost its subject |
| **unresolvable pin fails, not skips** | a skip is indistinguishable
from a pass |
| missing `ref:` is refused | would follow the default branch |
| empty staged scope is refused | nothing to compare is not a free pass
|

**Meta-mutant.** Removing the path scoping from the guard
(`git diff --name-only $pin $compare -- $paths` → without `-- $paths`)
kills
**exactly the two controls that assert it**, 8 passed / 2 failed.
Restored, 10/10.

**Contract-test mutants.** `ref: main` → `FAIL: the lock gate is not
staged from
an immutable 40-hex commit`. Renaming the step → `FAIL: governance
workflow has
no step named 'Checkout standards for the lock gate'`. Both rc=1.

Full suite: **all 51 test files pass** on this branch.

The guard **fails the job**. It is not `continue-on-error` and it is not
a
`::warning::`, which cannot fail a job.

## Notes

- `self-test.yml` gains `fetch-depth: 0`. The guard compares two commits
and
**fails rather than skips** on an unresolvable pin, so the history is a
requirement, not an optimisation. This is a `with:` change only — no
`uses:`
  ref moves, so `actions.lock` is untouched.
- The new Self Test step passes the base SHA through `env:`, not by
interpolating an expression into the `run:` body. The repo's own
injection
  scanner (`tests/test_tag_ruleset_canon.sh`) still passes.
- `grep -A N` cannot delimit the step block: it is 19 lines today, so
any fixed
`N` is either short of the `ref:` or long enough to capture the **next**
step's
`ref:` and assert against the wrong pin. Both the guard and the contract
test
  take the range from `- name:` to `- name:` with awk.

## ⚠ This does not turn burble#226 green on its own

`metadatastician/burble#226` pins standards at `e977cc67`, and **that**
copy of
`governance-reusable.yml` still carries `4f7f02ca` at the lock-gate
step. Pin 3
travels with the pinned YAML.

Sequence: **merge this → take the resulting SHA → re-bump burble#226 to
it**
(all 9 sites plus `actions.lock`, transitive `uses:` list re-extracted
against a
positive control) → then #226 can go green.

## Out of scope, filed separately

The **dupkey** pin `317101e0` is also stale — 45 files differ under
`scripts/`
versus `main`. Its `sparse-checkout` is the whole `scripts` directory,
so the
same predicate applied verbatim would be permanently red and useless; it
needs a
scope narrowed to what that step actually executes. Per the stopping
rule that is
an issue with acceptance criteria, not scope for this PR.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01X3hgXxWm6umMgZkjYyHnnm

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 94873299-f41b-44b0-996e-c0d6a8d9161c

📥 Commits

Reviewing files that changed from the base of the PR and between e36ecdd and fc353ed.

⛔ Files ignored due to path filters (1)
  • .github/workflows/actions.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • .github/workflows/governance.yml
  • .github/workflows/hypatia-scan.yml
  • .github/workflows/scorecard.yml
  • .github/workflows/secret-scanner.yml
  • .github/workflows/spark-theatre-gate.yml
  • .github/workflows/workflow-safety.yml
 ________________________
< Tree-sitter is my GPS. >
 ------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
🧪 Generate unit tests (beta)

❌ Error committing Unit Tests locally.

  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hyperpolymath
hyperpolymath merged commit 70f6d04 into main Sep 22, 2026
41 of 45 checks passed
@hyperpolymath
hyperpolymath deleted the chore/bump-standards-pins-e977cc67 branch September 22, 2026 16:02
@coderabbitai

coderabbitai Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Note

Unit test generation is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai

coderabbitai Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Failed to create Coding Agent finishing-touch task.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Three red checks on main all trace to one stale hyperpolymath/standards pin (fcb566cf) — cure is a single pin bump

1 participant