Skip to content

fix(ci): revive Rust CI — it had never run (60/60 startup failures) - #358

Merged
hyperpolymath merged 3 commits into
mainfrom
worktree-ephapax-rust-ci-fix
Jul 27, 2026
Merged

fix(ci): revive Rust CI — it had never run (60/60 startup failures)#358
hyperpolymath merged 3 commits into
mainfrom
worktree-ephapax-rust-ci-fix

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

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 29b1f65ca 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.ymlfile 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

hyperpolymath and others added 2 commits July 27, 2026 18:52
`.github/workflows/rust-ci.yml` failed 60 consecutive runs, every one at 0s
with zero jobs and no logs, between 2026-06-27 and 2026-07-27. That is a
startup failure: GitHub rejected the file before scheduling anything.

Found via the workflow-name fallback: GitHub reported this workflow's name as
`.github/workflows/rust-ci.yml` (its path) rather than the declared `Rust CI`,
which is what it does when a file has never been successfully parsed. Every
other workflow in this repo resolves its declared name.

Impact: `cargo build` and `cargo test` live only in this workflow, so the Rust
implementation — 70 source files — had no build or test gate for a month while
the board showed 13/14 green. The `wasm-validate` job that guards 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. The estate reusable's own header calls this out
as a recurring failure mode, and solves it properly with a `detect` job whose
output gates the rest.

Ruled out first, so the next reader need not repeat it: encoding/CRLF/BOM (clean
— the only non-ASCII is an em-dash in a comment), YAML validity (parses), all
three pinned action SHAs (resolve), and caller-vs-reusable permissions (both
exactly `contents: read`).

The guard was redundant regardless: this repo unconditionally has a Cargo.toml.

Also salvaged from uncommitted sweep debris, keeping only what is useful:
- .editorconfig: adds per-language indent widths (rust/zig 4, ada 3, Justfile 4)
  while RESTORING the SPDX header and dropping the sweep's rebrand of this file
  to "RSR-template-repo" (a template self-name leak).
- .gitignore: adds 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 is newly ignored.

Discarded from the same debris: a `guix.scm` clobbered to identify as
`squisher-corpus` (and relicensed to PMPL-1.0-or-later), a deletion of
`.tool-versions` (which pins coq 8.18.0 / ocaml 5.4.1), a `.gitattributes`
regression dropping *.zig and *.a2ml rules, and 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.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ough

Direct consequence of the previous commit. With Rust CI reviving, the
`cargo fmt --all -- --check` step ran for the first time since 2026-06-27 and
failed immediately: 24 files had drifted out of rustfmt shape while nothing was
checking them.

This is purely mechanical `cargo fmt --all` output — no semantic edits.
`cargo check --locked --all-targets` was already passing in the same CI job, so
the drift was cosmetic, but it was enough to keep the revived gate red.

Verified locally with rustfmt 1.9.0-stable: `cargo fmt --all -- --check` is clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@hyperpolymath
hyperpolymath merged commit d7f1b49 into main Jul 27, 2026
22 of 23 checks passed
@hyperpolymath
hyperpolymath deleted the worktree-ephapax-rust-ci-fix branch July 27, 2026 18:22
hyperpolymath added a commit that referenced this pull request Jul 27, 2026
## Why main is currently red

PR #358 revived Rust CI. It merged **before** this commit landed on the
branch, so main
now has a *working* Rust CI that immediately fails its `Cargo check +
clippy + fmt` step.

That is not a regression — it is the gate doing its job for the first
time since
2026-06-27. This PR is the backlog it found.

Current state of the revived gate on main (`d7f1b49`):

```
success  wasm-tools validate (emitted modules)
success  Cargo build + test (ephapax-cli, --no-default-features)
success  rust-ci / Detect Cargo.toml
failure  rust-ci / Cargo check + clippy + fmt     <-- this PR
```

## What this fixes

`cargo clippy --all-targets -- -D warnings` failed crate after crate.
All resolved;
it now exits 0.

**Mechanical, behaviour-preserving:**

| Lint | Fix |
|---|---|
| `derivable_impls` | `impl Default for Visibility` →
`#[derive(Default)]` + `#[default]` |
| `manual_try_fold` ×2 | `.fold(Ok(acc), ..)` → `.try_fold(acc, ..)` in
the surface and core parsers' statement-sequence desugaring |
| `collapsible_if` ×2, `match_like_matches_macro` | via `cargo clippy
--fix` |
| `ptr_arg` | `&PathBuf` → `&Path` in two `ephapax-cli` signatures |
| `unnecessary_unsafe` | removed an **empty** `unsafe {}` block wrapping
only comments in a placeholder test |

That last one is worth a second look in a language whose entire thesis
is memory safety:
`ephapax-runtime::list::tests::test_list_new` contained `unsafe { /*
comments only */ }`.

**Deliberately allowed, each with an inline reason** (no blanket
crate-level allow):

- `approx_constant` — `lex("3.14")` is a float literal *under test*, not
an approximation of PI
- `type_complexity` — replaced with a `TokenPredicate` type alias
- `too_many_arguments` ×3 — 8 params vs clippy's default threshold of 7,
on option-heavy CLI
  entry points and the recursive import resolver
- `large_enum_variant` — `Value::Closure` is ~264 bytes vs ~48 for the
next largest, so every
`Value` pays for it. The real fix is boxing the payload, which touches
every construction
and match site **in the interpreter**. That is a behavioural-risk
refactor that does not
belong in a CI-infrastructure change. Allowed here with a comment,
tracked in **#360**.

## Verification — all local, all green

```
cargo check --locked --all-targets          ok
cargo clippy --all-targets -- -D warnings   exit 0
cargo fmt --all -- --check                  clean
cargo test --workspace                      285 passed, 0 failed
```

The 285 passing tests matter here: the `try_fold` rewrites and the
`unsafe` removal are the
only changes that could alter behaviour, and the parser/interpreter
suites cover both.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

1 participant