Repository navigation
main is CI-dead since #830: tests.yml startup_failure (jobs=0) and Actions lockfile verify red #837
Description
The finding
Two faults appeared on main together with #830 (chore(deps): bump the actions group across 1 directory with 4 updates, head 0aa89724).
1. tests.yml is startup_failure — zero jobs
2026-09-22T14:22 startup_failure push 0aa89724 <- #830
2026-09-22T14:21 startup_failure pull_request b3e4057a
2026-09-22T14:20 failure push 0e121c94 <- last run that ran
2026-09-22T14:00 startup_failure pull_request 2e0e7bba
2026-09-22T13:51 failure pull_request c22ce6c1
2026-09-22T13:20 failure push 3bf9674a
Run 35739874762 on 0aa89724 has jobs = 0. A 0-job run is a startup death,
not a verdict — the workflow was never parsed into jobs, so nothing it would have
checked was checked, and the run does not report a failure anyone would read as
one.
The only diff between the last run that started (0e121c94) and the first that
did not (0aa89724) is the Dependabot pin bumps across five workflows — for
tests.yml a pure step-level tag bump, taiki-e/install-action@v2.87.15 →
v2.87.16. A step-level tag bump should not startup-kill a workflow, so the
cause is not obvious and is not yet established. The check-runs API returns 404
for annotations on this run.
Note this fault masks #836 rather than replacing it: the test tier was already
dead by needs:-skip before the workflow stopped starting at all.
2. governance / Actions lockfile verify is red on main
The same Dependabot commit changed uses: refs without regenerating
.github/workflows/actions.lock. A hyperpolymath/standards reusable does
verify the lockfile, so it is now inconsistent with the tree.
This also corrects an earlier note in the #120 planning that said "no hypatia
workflow enforces actions.lock" — one does, via a standards reusable.
Acceptance criteria
- Root cause of the
startup_failurenamed and evidenced, not guessed. Bisect
by dispatchingtests.ymlon a branch that reverts only thetests.ymlhunk of
chore(deps): bump the actions group across 1 directory with 4 updates #830, and confirm jobs > 0. State which change did it. tests.ymlreaches jobs > 0 on apushtomain. Verify by the job count
in the run, never by a green tick — a startup death has no red tick to see..github/workflows/actions.lockregenerated in generate mode only. Never
fix/rewrite mode: it has previously de-pinned 24 SHAs and invented invalid
uses:refs that themselves cause startup death.git diffthe lock before
staging and confirm the change is purely additive.governance / Actions lockfile verifygreen onmain, evidenced from
/commits/<sha>/check-runs, not fromgh run list.- The lockfile must be transitively closed — a dangling edge to an
unresolvable ref is itself a jobs=0 killer. Absent is harmless; unresolvable
is fatal. - A regression guard: any Dependabot commit touching a
uses:ref must either
updateactions.lockin the same commit or fail. Prove it with a mutant —
hand-edit oneuses:tag without touching the lock and confirm red.
Sequencing
(1)-(2) before (3)-(4). Regenerating the lock while the workflow cannot start
leaves you unable to tell which change fixed what.
Activity
hyperpolymath commentedon Sep 22, 2026
The startup death is four workflows, not one — and it hides a dead doctest tier
Measured 2026-09-22 while landing #840. This issue names
tests.yml; the samefault is live on four workflows on
main:Reproduced identically on the
fix/cargo-testcontainersbranch, so it is aproperty of the tree, not of the
mainref. This is consistent with the causealready identified here — the #830 pin bumps landed across five workflows,
and this issue only followed one of them.
The consequence worth naming: the only doctest run in the repo is dead
Job-name mapping, measured from the workflow files:
rust.yml("Rust CI")Check,Test,Format,Clippy,Cargo check + clippy + fmt,Cargo testquality.yml("Docs & Code Quality")Build AsciiDoc,Validate Documentation, …ci.yml("CI")Rust Check & Clippy,Rust Format,Rust Tests,Rust Coverage, Haskell jobs,CI Statusci.yml:98is the onlycargo test --docin the entire repository:Those doctests exist and pass —
cargo test --workspace --doclocally onmain@4fa2e39reports 4 passed (integration/src/lib.rs,ci_simulation/{mod,scenarios,assertions}.rs). They execute nowhere in CI.Rust Coverageis likewise never produced.This is the same shape as #836 — a tier that exists, passes locally, and runs
in no pipeline — reached by a different route. #836 is a
needs:-skip; this isa startup death. Both are invisible in the checks list for the same reason: the
absence of a check reads like nothing rather than like a failure.
Suggested addition to the acceptance criteria
tests.ymlmust be verified on all four workflows, eachevidenced by jobs > 0 on a real run — not by the workflow reappearing in
the checks list.
cargo test --workspace --docactually executes inCI and reports a non-zero denominator, so the doctest tier is provably live
rather than merely present.
Found while landing #840 (#838). Related: #836, #841.
fix(ci): pin taiki-e/install-action v2.87.16 in actions.lock
fix(ci): revive four startup-dead workflows -- codeql-action v4.38.0 …
hyperpolymath commentedon Sep 22, 2026
Fixed by #842, squash-merged to
mainas450734e(
verified=true reason=valid).Root cause -- two faults, not four
1. codeql-action pinned to the version its own comment forbids.
#830 (
chore(deps): bump the actions group) moved all 8 sites to1c5b675653bb5c22dbe9b12b556ec555138e09fdwhile leaving the trailing commentreading
# v4.38.0 (4.38.1 blocked estate-wide; nexia-list#100). That SHA isv4.38.1, which GitHub refuses at workflow startup estate-wide. Reverted to
b96794f015dfd88f77b49b1c93e0fa7110f94c63(genuinely v4.38.0).2. An unparseable
actions.lockundersha_pinning_required.taiki-e/install-action@v2.87.16was used while the lock pinned onlyv2.87.15, and the lock carried an entry whose full-40-hex key did not resolveto itself (
codeql-action@1c5b675...claiming commitb96794f...). Aself-contradicting entry makes the whole lockfile unreadable, which is why
ci.ymlandtests.ymldied too although neither uses codeql-action.How it was localized
actionlintreported zero errors andyqparsed all four files, andactions.lockalready covered 32 of 32 workflows -- so neither the workflowfiles nor the "absent from the lock" cure applied. Comparing each workflow's
normalized
uses:refs against the lock (collapsingcodeql-action/init@Xand/analyze@Xtocodeql-action@X) implicatedexactly the four dead workflows and no others.
⚠
gh actions-lock --no-fixexits 0 while printinglockfile is unreadable. Branch on the message, never the exit code.Verification on
main@450734eAll four previously 0-job / 0s startup deaths now produce jobs:
gh actions-lock --no-fixnow scans 32 workflows with zero findings.What the cure surfaced
Reviving
tests.ymlalso repaired theneeds:chain:Build Test Imagespasses, so
Integration Testsexecuted and passed --mix testhas now runfor the first time, which retires the premise behind #836.
It also made
End-to-End Testsrun for the first time ever, and it fails --docker composecannot find its configuration file, so the E2E suite is stillskipped. That job was
skippedon every run before the startup death andabsent after, so it has never once executed. This is a first measurement of
pre-existing breakage, not a regression from #842. Filed as #843.
Integration Statusis red purely as the rollup of that job.🤖 Generated with Claude Code
https://claude.ai/code/session_0113HQM9LVGkNCzU1WwkJZSV