The actions-lock gate prints a remedy that cannot be followed in any of the 368 consumer repos. The gate itself works; only its advice is wrong.
Measured
Read from scripts/check-actions-lock-gate.sh at da2c748aad55c1a1dcba00b60fe4a35017bc6540 — the SHA metadatastician/marid pins today:
| line |
text |
| 48 |
::error::actions-lock gate: lockfile verification FAILED (exit $rc). Regenerate with **scripts/update-actions-lock.sh** in the same PR as the uses: change. |
| 62 |
Prefer `gh actions-lock` (**scripts/update-actions-lock.sh**): it also locks the… |
| 68 |
::warning::… the lockfile becomes REQUIRED on $ENFORCE_FROM. Run **scripts/update-actions-lock.sh**. |
| 73 |
::error::… the grace window closed on $ENFORCE_FROM. Run **scripts/update-actions-lock.sh** and commit the lockfile. |
All four name a repo-relative path. In a consumer repo that path does not exist and never will:
$ ls marid/scripts/update-actions-lock.sh
ls: cannot access ...: No such file or directory
$ grep -rn "update-actions-lock" marid/ # the whole tree
(no matches)
A developer hitting line 48 on a red PR follows the instruction, finds nothing, and has no route forward from the message alone.
This is not a missing-file bug — the machinery is correct
governance-reusable.yml:1256-1287 self-supplies the script, so nothing is actually broken at runtime:
path: .standards-lock
sparse-checkout: |
scripts/check-actions-lock-gate.sh
scripts/update-actions-lock.sh
...
for f in check-actions-lock-gate.sh update-actions-lock.sh; do
cp "$SRC/$f" "$RUNNER_TEMP/$f"
done
ACTIONS_LOCK_VERIFIER="$RUNNER_TEMP/update-actions-lock.sh" \
bash "$RUNNER_TEMP/check-actions-lock-gate.sh" .github/workflows
standards does ship the script (5,103 B at that SHA), and ACTIONS_LOCK_VERIFIER correctly overrides the $SCRIPT_DIR default at line 32. The defect is confined to the four human-readable strings, which were written from the perspective of the repo that owns the script rather than the repos that consume it.
Suggested remedy
Name the thing a consumer can actually run. Line 62 already gets this right parenthetically — gh actions-lock is the consumer-facing tool.
⚠ One caveat that should go into the text, from a defect measured on marid this week (metadatastician/marid#36): bare gh actions-lock fix mode de-pins SHA-pinned refs to floating tags and rewrites the workflow file. Reproduced deterministically on codeql.yml: github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1 → @v4.38.1 — a supply-chain regression emitted by the very tool the gate recommends. gh actions-lock --no-narrow records the SHA in the lock and leaves the workflow pin intact; whole-repo --no-fix then returns rc=0.
So the remedy string should read approximately:
Regenerate with gh actions-lock --no-narrow in the same PR as the uses: change.
Acceptance criteria
- No user-facing string in
check-actions-lock-gate.sh names a path that does not resolve in a consumer checkout — lines 48, 62, 68 and 73 amended.
- The recommended command is
gh actions-lock --no-narrow, with a one-line note saying why the bare form is unsafe for a SHA-pinned repo.
- A control: run the gate in a consumer repo with a deliberately stale lockfile and confirm every path named in the emitted message resolves, or is a command on
PATH.
- Related, not required here:
scripts/update-actions-lock.sh itself should be checked for the same de-pinning behaviour marid#36 records, since the gate uses it as ACTIONS_LOCK_VERIFIER.
Related
hyperpolymath/standards#670 — Dependabot bumps uses: without regenerating actions.lock (the upstream cause of the failures this text is printed for).
metadatastician/marid#36 — the gh actions-lock de-pinning defect and the --no-narrow cure.
🤖 Generated with Claude Code
https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo
The actions-lock gate prints a remedy that cannot be followed in any of the 368 consumer repos. The gate itself works; only its advice is wrong.
Measured
Read from
scripts/check-actions-lock-gate.shatda2c748aad55c1a1dcba00b60fe4a35017bc6540— the SHAmetadatastician/maridpins today:::error::actions-lock gate: lockfile verification FAILED (exit $rc). Regenerate with **scripts/update-actions-lock.sh** in the same PR as the uses: change.Prefer `gh actions-lock` (**scripts/update-actions-lock.sh**): it also locks the…::warning::… the lockfile becomes REQUIRED on $ENFORCE_FROM. Run **scripts/update-actions-lock.sh**.::error::… the grace window closed on $ENFORCE_FROM. Run **scripts/update-actions-lock.sh** and commit the lockfile.All four name a repo-relative path. In a consumer repo that path does not exist and never will:
A developer hitting line 48 on a red PR follows the instruction, finds nothing, and has no route forward from the message alone.
This is not a missing-file bug — the machinery is correct
governance-reusable.yml:1256-1287self-supplies the script, so nothing is actually broken at runtime:standardsdoes ship the script (5,103 B at that SHA), andACTIONS_LOCK_VERIFIERcorrectly overrides the$SCRIPT_DIRdefault at line 32. The defect is confined to the four human-readable strings, which were written from the perspective of the repo that owns the script rather than the repos that consume it.Suggested remedy
Name the thing a consumer can actually run. Line 62 already gets this right parenthetically —
gh actions-lockis the consumer-facing tool.⚠ One caveat that should go into the text, from a defect measured on marid this week (
metadatastician/marid#36): baregh actions-lockfix mode de-pins SHA-pinned refs to floating tags and rewrites the workflow file. Reproduced deterministically oncodeql.yml:github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1→@v4.38.1— a supply-chain regression emitted by the very tool the gate recommends.gh actions-lock --no-narrowrecords the SHA in the lock and leaves the workflow pin intact; whole-repo--no-fixthen returns rc=0.So the remedy string should read approximately:
Acceptance criteria
check-actions-lock-gate.shnames a path that does not resolve in a consumer checkout — lines 48, 62, 68 and 73 amended.gh actions-lock --no-narrow, with a one-line note saying why the bare form is unsafe for a SHA-pinned repo.PATH.scripts/update-actions-lock.shitself should be checked for the same de-pinning behaviour marid#36 records, since the gate uses it asACTIONS_LOCK_VERIFIER.Related
hyperpolymath/standards#670— Dependabot bumpsuses:without regeneratingactions.lock(the upstream cause of the failures this text is printed for).metadatastician/marid#36— thegh actions-lockde-pinning defect and the--no-narrowcure.🤖 Generated with Claude Code
https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo