You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(ci): revive Rust CI — it had never run (60/60 startup failures) (#358)
## The finding
`.github/workflows/rust-ci.yml` **failed 60 consecutive runs, every one
at 0s**, with
zero jobs and no logs, from 2026-06-27 to 2026-07-27. That is a *startup
failure* —
GitHub rejected the file before scheduling anything. Not a flake, not a
failing test.
It was found via a **workflow-name fallback**: GitHub reports a
workflow's `name` as its
*file path* when it has never successfully parsed the file.
```
{"name": ".github/workflows/rust-ci.yml", "path": ".github/workflows/rust-ci.yml"} <- this one
{"name": "Governance", "path": ".github/workflows/governance.yml"}
{"name": "Coq Build (formal/)", "path": ".github/workflows/coq-build.yml"}
```
`rust-ci.yml` declares `name: Rust CI`. GitHub never saw it.
## Why it matters
`cargo build` and `cargo test` exist **only** in this workflow. So the
Rust
implementation — 70 source files — had **no build or test gate for a
month**, while the
board read 13/14 green. The `wasm-validate` job guarding against invalid
emitted wasm
(cf. #348) was equally dead.
## Cause
`if: hashFiles('Cargo.toml') != ''` used as a **job-level** conditional
on both local
jobs. Job-level `if:` is evaluated server-side before any checkout, so
`hashFiles()` has
no workspace to hash. The estate reusable's own header names this exact
construct as a
recurring failure mode, and solves it correctly with a `detect` job
whose output gates
the rest.
The guard was redundant anyway — this repo unconditionally has a
`Cargo.toml`.
## Ruled out first
So the next reader doesn't repeat the work:
| Hypothesis | Result |
|---|---|
| Encoding trap (CRLF / BOM / tabs) | **Falsified** — clean; only
non-ASCII is an em-dash in a comment |
| Invalid YAML | **Falsified** — parses |
| Unresolvable action SHA pins | **Falsified** — all three resolve |
| Reusable requests perms caller doesn't grant | **Falsified** — both
exactly `contents: read` |
## Also in this PR — salvage from uncommitted sweep debris
**Kept (useful):**
- `.editorconfig` — per-language indent widths (rust/zig 4, ada 3,
Justfile 4), but with
the SPDX header **restored** and the sweep's rebrand of this file to
`RSR-template-repo` (a template self-name leak) dropped.
- `.gitignore` — build/tooling artefact patterns, **minus** the sweep's
`.claude/` and
`.editorconfig` entries: both are tracked here, so ignoring them would
hide real
changes from `git status`. Verified no tracked file becomes newly
ignored.
**Discarded (harmful):**
- `guix.scm` clobbered to identify as `squisher-corpus`, **relicensed to
PMPL-1.0-or-later**, Owner line deleted — and carrying a `//` comment in
a Scheme file.
- Deletion of `.tool-versions` (pins `coq 8.18.0` / `ocaml 5.4.1` /
`rust stable`).
- `.gitattributes` regression dropping `*.zig` and `*.a2ml` rules.
- Commit `55dbd3b`, which replaced a valid CodeQL pin with `29b1f65c` —
**a SHA that
does not exist (HTTP 422)** — and would have taken the currently-green
CodeQL gate down.
## How to verify
The check is self-demonstrating: **if this PR's Rust CI runs at all, the
fix worked.**
Sixty prior runs produced zero jobs. Confirm the workflow now reports as
`Rust CI`
rather than its path, and that `no-default-features` and `wasm-validate`
actually execute.
## Note for follow-up (not in this PR)
The same detector found two more `name == path` entries here. Both are
benign, but worth
recording:
- `workflow-linter.yml` — **file deleted**, registration lingers.
Harmless orphan.
- `instant-sync.yml` — file exists, `disabled_manually` (deliberately
frozen). It parses
as YAML, so its cause differs; it would need diagnosis before being
re-enabled.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
0 commit comments