Repository navigation
actions.lock: list the lock-sync gate, and make the checker require coverage - #137
Conversation
…overage
Two defects, one cause: a workflow file that has NO KEY in actions.lock is
refused by GitHub at startup (jobs=0, startup_failure) even when it contains
zero `uses:` refs and therefore has nothing to pin.
1. Add the missing key for the gate this repo already ships:
'.github/workflows/lock-sync-gate.yml': []
MEASURED, single-variable flip on two independent repositories:
* hyperpolymath/verisimdb - 7 consecutive startup_failure -> success
* hyperpolymath/blocky-writer - 2 of 2 startup_failure -> success
Nothing else changed in either case. An empty commit with the lock
untouched still failed; the commit adding this line passed. `gh actions-lock`
already emits this empty-list form for other zero-`uses:` workflows in this
very lockfile (labels.yml), so the spelling is the generator's own
convention - the generator simply omitted this file.
2. Teach scripts/check-lock-sync.sh to catch it (clause 4, COVERAGE).
The gate could not defend the very fix it ships. Clauses 1-3 ask "is every
`uses:` locked under its own workflow path?" GitHub asks a DIFFERENT
question: "is every workflow file represented in the lock?" A workflow with
no `uses:` satisfies clauses 1-3 vacuously and is still refused. Thirteen
repositories passed the gate with exactly this gap present.
Clause 4 diffs the set of files under .github/workflows/ against the set of
lockfile keys and fails on any file with no key, naming it and quoting the
empty-list form. Mutation-tested both ways: deleting the lock-sync-gate key
fails the gate, and deleting the unrelated labels.yml key fails it too;
the unmutated tree passes.
3. Add `workflow_dispatch:` to the gate so it can be exercised on demand.
A startup-failed run cannot be re-run (`gh run rerun` refuses it), which is
what made this defect expensive to diagnose.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X3hgXxWm6umMgZkjYyHnnm
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📜 Recent review details⏰ Context from checks skipped due to timeout. (24)
|
| Layer / File(s) | Summary |
|---|---|
Manual workflow trigger .github/workflows/lock-sync-gate.yml |
Adds the workflow_dispatch trigger to the lock-sync gate. |
Workflow coverage validation scripts/check-lock-sync.sh |
Adds coverage checks for unlisted workflows. The guidance and success output now include workflows with zero uses: references. |
Priority: ➖ Normal
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Medium
Merge Risk: ⚪ Minimal · up to ed1ff
The lock-sync gate remains manually runnable, and workflow coverage validation now includes workflows without action references. No merge-blocking risk is identified.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | The title clearly summarises the main changes: adding the lock-sync gate to actions.lock and enforcing lockfile coverage. |
| Description check | ✅ Passed | The description directly explains the startup failure, the coverage check, workflow_dispatch support, mutation testing, and verification results. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1… |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
✨ Finishing Touches
🛠️ Fix failing CI checks
- Commit to this branch
- Create a new PR
📝 Generate docstrings
- 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.
A rabbit checks the workflow gate,
Empty lists now count their weight.
Missing keys raise a careful sign,
Manual runs start on command line,
Lock and workflow paths align.
Comment @coderabbitai help to get the list of available commands.
|
ℹ️ Nothing to fix from this PR. All 1 failing check(s) are already failing on ⏭️ 1 check(s) skipped — already failing on `main` (not caused by this PR)
These need to be addressed on |
…he freeze bypass — with the sources cured (#141) ## What this sorts out Closes the acceptance criteria of #138 and goes after the three *sources* behind today's reds, in one change set. Each cure carries its inverse (januskey); nothing was muted, demoted, or removed from any required set (standards#994 AC5). ### 1. `lint-workflows` ×2 (issue #138) — determination: **FIXED** Two governors claimed the same byte: `gh actions-lock` inserts `# This workflow is managed by gh actions-lock.` at **line 1** whenever it mints or refreshes a lockfile, while the local `Check SPDX headers` step demanded the SPDX identifier on **line 1**. Every lock refresh re-failed the check. Measured same-commit (`a045f44`): | check | predicate | result on identical files | |---|---|---| | `lint-workflows` (local `workflow-linter.yml`) | SPDX on `head -1` | 🔴 18 of 19 files "missing" headers they all have (including its own file) | | `governance / Workflow security linter` (canonical, `standards@fad242d`) | SPDX in the leading comment block | 🟢 green | The canonical predicate has existed in `hyperpolymath/standards` `governance-reusable.yml` **since 2026-08-07**, with the exact warning recorded: a line-1 test "fights the estate's own tool and re-fails every time a lockfile is refreshed" — it falsely reported 27 hypatia + 13 other workflows and "fixing" it mis-licensed 3 files. The local copy was a stale divergent mutant of the estate's own check. The fix converges the local copy to the canonical form (`scripts/check-workflow-headers.sh`, byte-faithful): SPDX anywhere in the leading comment block (banner- and doc-marker-tolerant) + top-level `permissions:`. Same requirements, correct frame. Job name `lint-workflows` kept; the check stays blocking. **Expected-rejection controls** (`--self-test`, from occupancy-types' gate contract and pons-asinorum's falsifier rule): 3 fixtures that must pass and 2 that must be killed, run *first* in the job. A predicate that cannot kill its own mutant is a Certified Null Operation (absolute-zero) and is not allowed to judge the tree. This promotes PR #137's manual mutation notes into a permanent control. ### 2. The freeze bypass — determination: **FIXED** (gate-enforced) Dependabot #140 moved `github/codeql-action` `b96794f0` (v4.38.0) → `2892aa5e` (a 2026-09-24 `releases/v4` merge, `update-v4.38.2`) **in SHA form while copying the `# v4.38.0 (4.38.1 blocked estate-wide; nexia-list#100)` comment verbatim** — the witness of intent survived the rewrite with its meaning inverted. That pin is under an estate freeze (nexia-list#100: v4.38.1+ refused at startup; `standards` main still pins `b96794f0` today). This is the **second** documented bypass of the hold (nexia-list#101: versions-scope; nexia-list#104: unconditional; then this). An ignore rule is a request to a robot; this PR reverts the bump and adds `scripts/check-frozen-pins.sh` — the freeze as a check *this repo owns*, with its own mutants (SHA-form and tag-form bump both killed in self-test). Lifting the freeze becomes a deliberate, reviewable one-line table edit. ### 3. The lock re-desync (standards#968 class) — determination: **FIXED**, source cured #140 bumped `haskell-actions/setup` v2.12.1 and did not regenerate `actions.lock` ("60 of 60 repos have Dependabot AND a lockfile AND no regeneration step — repos appear to go bad again; nobody broke them, the clock did"). Measured on main today: Lock Sync Gate 🔴, `governance / Actions lockfile verify` 🔴, CodeQL + GitHub Pages `startup_failure` (jobs=0), cflite poised to die. The lock is re-synced (`haskell-actions/setup@v2.12.1` peeled via API; all four `check-lock-sync.sh` clauses verified), and `lock-sync-heal.yml` is the source cure: `gh actions-lock` (the sanctioned writer) on every workflow change + weekly backstop, opening one standing refresh PR whose body carries the checker's output as a **receipt** — obtained on the regenerated tree before the PR exists (epistemic-types: transported proof arrives with a sound check of the receiver's claim). Inverse: close the PR. ## Residue list (honest boundary, echo-types/OND) Not claimed, not erased — listed with dates: * `hypatia / Hypatia Neurosymbolic Analysis` — red on `main` since 2026-09-29 (`Build Hypatia scanner`). Cause not established from here (job logs unreachable from the triage sandbox); candidate classes: `hyperpolymath/hypatia` HEAD build-rot or transient hex.pm failure. It is standards#994's class 3; the reusable builds the scanner from a *moving HEAD*, which is the fragile contract. **It is a required context and may block this PR's merge mechanically** — per the stopping rule, nothing is required of a branch that its base does not satisfy. * `mirror / mirror-gitea`, `mirror / mirror-disroot` — red on `main` (infrastructure/credentials). Not measured further. ## Verification - [x] `bash -n` clean on every script and every `run:` block (extracted and parsed) - [x] YAML parse clean on every touched workflow + lockfile - [x] header predicate self-test: 3 accepted, 2 rejected - [x] freeze gate self-test: 1 accepted, 2 rejected (SHA-form + tag-form mutants killed) - [x] both predicates green on the full tree (all 20 workflow files) - [x] `check-lock-sync.sh` clauses 1–4 pass on the repaired lock (verified via a clause-faithful port; gawk is not in the triage sandbox — the gate itself runs the real script on ubuntu-latest) - [ ] `lint-workflows` green on this PR head (both legs) - [ ] Lock Sync Gate green on this PR head ## Theory basis (full map in `docs/ci-guard-cures-2026-09-29.adoc`) pons-asinorum (contradiction taxonomy; negative corpus) · absolute-zero (CNO vacuous gates; OND residue lists) · januskey (inversion metadata; shared core over divergent copies) · echo-types (structured loss; comments that outlive their meaning) · epistemic-types (warrant ≠ knowledge; receipts) · choreographic-types (YAML+lock is one cut) · occupancy-types (expected-rejection controls; rung contracts) · panic-attack (signatures: `TWO-GOVERNORS-ONE-INVARIANT`, `ROBOT-PROMISE-WITHOUT-GATE`, `STATE-CURE-WITHOUT-SOURCE-CURE`). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
What this fixes
The lock-sync gate merged into this repository cannot start, and the
checker it ships cannot detect why. Both are fixed here.
A workflow file with no key in
.github/workflows/actions.lockis refusedby GitHub at startup —
jobs=0,startup_failure— even when it containszero
uses:refs and so has nothing to pin.Evidence — single-variable flip, two independent repositories
hyperpolymath/verisimdbstartup_failurehyperpolymath/blocky-writerstartup_failureNothing else changed in either case. A control commit that touched the tree but
not the lock still failed; the commit adding the key passed. This is a state
effect, not a re-indexing side effect of "any lock change".
The spelling is not invented —
gh actions-lockalready emits the empty-listform for other zero-
uses:workflows in this same lockfile (labels.yml). Thegenerator simply omitted this file, which is itself an upstream defect.
The gate could not defend its own fix
This is the guard-asks-a-different-question-than-its-consumer trap:
uses:locked under its own workflow path?A workflow with no
uses:satisfies clauses 1–3 vacuously and is stillrefused. Thirteen repositories passed the gate with exactly this gap present,
so a green gate today is not evidence a lock is complete.
Clause 4 (COVERAGE) diffs the set of files under
.github/workflows/against the set of lockfile keys, fails on any file with no key, names it, and
quotes the empty-list form to add. Remediation step 4 warns that re-running
gh actions-lockmay not add it, because the omission is the tool's own defect.Mutation-tested, both directions
lock-sync-gate.ymlkeylabels.ymlkeyA passing gate proves nothing until it kills a mutant, so both are recorded here.
Also included
workflow_dispatch:on the gate. A startup-failed run cannot be re-run(
gh run rerunrefuses it), which is what made this defect expensive todiagnose; a dispatch handle makes it reproducible on demand.
Scope
The checker is patched in place — each repository's copy has diverged
slightly in comments, and only the clause-4 block, its remediation step and one
success line are added. No existing clause is altered.
Verification
bash -n scripts/check-lock-sync.shcleanjobs > 0(it could not start before)🤖 Generated with Claude Code
https://claude.ai/code/session_01X3hgXxWm6umMgZkjYyHnnm