Skip to content

feat(gates): strict Rust CI, Creusot, SPARK and miniKanren reusable gates - #54

Merged
hyperpolymath merged 3 commits into
mainfrom
claude/rust-ci-codeac-improvements-395dus
Oct 14, 2026
Merged

hyperpolymath merged 3 commits into
mainfrom
claude/rust-ci-codeac-improvements-395dus

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Why

Every rust-ci / Cargo check + clippy + fmt that calls hyperpolymath/standards rust-ci-reusable.yml at a pre-fix SHA has been red for six seconds since 2026-09-29 (hyperpolymath/plasma-parser-writer#105, run 38564229091). The reusable pinned dtolnay/rust-toolchain by commit and passed no toolchain:; a SHA ref carries no channel, so the action exits 1 with 'toolchain' is a required input before a compiler exists. The fix landed in standards (edbe311), and the callers stayed pinned behind it. That is a class of failure, not an instance: a gate that dies in setup and reads as a code failure.

This PR makes the class impossible by construction and, as asked, makes the Rust gate stricter, adds a parallel Creusot gate, and adds Ada/SPARK and miniKanren gates to this suite so the estate has one place to call them from. It also answers hyperpolymath/standards#692 (Rust + Creusot without proof theatre, with a planted failing contract).

What

Four reusable workflows, each consumed like the estate audit (thin caller at a full SHA, de-onboarded from actions.lock), each with a verdict job that turns a skipped mandatory job into red (a gate that did not run is void, not green — proven-tests-and-benches, corpus unit cancelled-gate-void):

Reusable Oracle
.github/workflows/rust-ci.yml actions/rust-ci-check: toolchain resolved before any action runs and refused when empty; every call --locked; RUSTFLAGS/RUSTDOCFLAGS -D warnings; doctests (--all-targets never ran one); cargo doc with warnings denied; the declared rust-version built; cargo-deny advisories/bans/sources by default (licences only against an owner-authored deny.toml); a missing Cargo.lock named before cargo runs. Existing context names kept.
.github/workflows/creusot-gate.yml actions/creusot-check: detect → theatre (a "verified with Creusot" claim with no contracts is a hard failure; a hollow creusot-std dependency is named; #[trusted] axioms listed) → prove (Creusot v0.14.0 at its pinned nightly; a planted FALSE contract must be refused and a planted TRUE one proved before the caller's crates are proved, else the verdict is void).
.github/workflows/spark-gate.yml standards' SPARK Theatre Gate nested at a pin for the claims side; actions/spark-check: GNATprove 16.1.0 via Alire, --checks-as-errors=on --warnings=error, same planted controls; refuses to guess between several .gpr files.
.github/workflows/kanren-gate.yml actions/kanren-check: relational sources (Scheme family, Rust kanren crates) must have goal-level tests; every relational test is executed by the interpreter its dialect names; impure operators (conda/condu/project/…) listed and enforceable; a miniKanren claim with no relations named.

How the scripts are pinned: each job reads the caller's own uses: SHA back out of the caller's checked-out workflow file (GITHUB_WORKFLOW_REF names it; inside a reusable the github context is the caller's), checks this repository out at that SHA and verifies it (scripts/verify-suite-checkout.sh), then runs the scripts from there. One pin, held by the caller, selects both the workflow and its scripts; no repin commit after a change to actions/. tests/lock-transitive-closure.sh now compares the composites a pin actually references rather than the whole actions/ tree, so unrelated additions under actions/ no longer force a repin of the estate audit.

Consumption: templates/{rust-ci,creusot-gate,spark-gate,kanren-gate}-caller.yml, scripts/deonboard-workflow.sh (the estate-audit script now delegates to it), templates/track-estate-audit.yml generalised to move every cicd-suite pin weekly, rollout_language_gates.sh installs callers by what a tree contains.

Evidence

Run locally under the exact composite shell (bash --noprofile --norc -e -o pipefail):

  • actions/rust-ci-check/test.sh: 31 assertions, 0 failures (planted fmt, clippy, doctest, intra-doc-link, missing-lock and empty-toolchain defects all go red; a mutant that swallows cargo's exit goes green, proving the red was not vacuous).
  • actions/creusot-check/test.sh: 27/0. actions/spark-check/test.sh: 19/0. actions/kanren-check/test.sh: 19/0 (a real microKanren executed by Guile, a planted wrong expectation fails, conda is listed).
  • tests/lock-transitive-closure.sh: 31/0 at the new HEAD. tests/composite-shell-contract.sh: 28/0. actionlint clean on the five new workflows. The estate-audit composites (code-hygiene, spdx, formatting, linguist, secrets, required-files) pass against this tree.

Not yet witnessed live

The Creusot and GNATprove install steps and the exit-code contracts of cargo creusot prove and gnatprove --checks-as-errors=on were validated against the tools' documentation and against stand-in oracles, not on a runner. The planted controls are the safeguard: if either prover cannot refuse a false contract on the runner, the gate reports void (exit 2), never green. The first live SPARK subject is cicd-squabbler's spark/squabble_gate.gpr; no repository in the first rollout carries Creusot obligations yet. The .github/workflows/language-gates-self-test.yml run on this PR is the first live run of the four self-tests.

Commits on this branch are unsigned: no signing key is available in this session (the configured key file is empty). GitHub signs the squash merge.

Consumers

Callers pinned at this branch's head are opened in plasma-parser-writer (replacing the broken standards pin and closing hyperpolymath/plasma-parser-writer#105 once green), cicd-squabbler (Rust, Creusot, SPARK, miniKanren), hypatia, gitbot-fleet and proven-tests-and-benches. After this PR merges, their pins move to the merged commit (the weekly track-estate-audit.yml bot does this by PR, or a one-line repin).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xn9nqHVbUTRLgBdedoXAc8


Generated by Claude Code

…ates

Four reusable workflows, each consumed like the estate audit (thin caller
at a full SHA, de-onboarded from actions.lock), each able to fail for what
it claims to check, each with a verdict that treats a skipped mandatory job
as void.

Rust CI (rust-ci.yml): replaces callers of standards' rust-ci-reusable.yml.
Root cause of the estate-wide "Cargo check + clippy + fmt: failing after
6s" (plasma-parser-writer#105): a SHA-pinned dtolnay/rust-toolchain with no
`toolchain:` input exits before cargo runs. resolve.sh now computes the
channel first and refuses an empty one. Stricter than before: -D warnings
on every compile, doctests (--all-targets never ran one), cargo doc with
warnings denied, the declared rust-version built, cargo-deny advisories/
bans/sources by default (licences only with an owner-authored deny.toml),
a missing Cargo.lock named before cargo runs. Existing context names kept.

Creusot (creusot-gate.yml): detect, theatre (a "verified with Creusot"
claim with no contracts is a hard failure; a hollow dependency is named),
prove (Creusot at a pinned release; a planted false contract must be
refused and a planted true one proved before the caller's crates are
proved, else the verdict is void). Answers standards#692.

SPARK (spark-gate.yml): standards' SPARK Theatre Gate nested at a pin for
the claims side, GNATprove via Alire at pinned versions with
--checks-as-errors=on --warnings=error and the same planted controls.

miniKanren (kanren-gate.yml): relational sources must have goal-level
tests, every relational test is executed by the interpreter its dialect
names, impure operators are listed (enforceable), claims without relations
are named.

Scripts are pinned by reading the caller's own `uses:` SHA back out of the
caller's checked-out workflow file, so one pin selects both the workflow
and its scripts; scripts/verify-suite-checkout.sh refuses anything else.
tests/lock-transitive-closure.sh now compares the composites a pin
actually references rather than the whole actions/ tree.

Self-tests under the exact composite shell with planted defects and
mutants: rust 31, creusot 27, spark 19, kanren 19 assertions. Templates,
a generalised pin-tracking bot, deonboard-workflow.sh and
rollout_language_gates.sh complete the consumption path.

Not yet witnessed live: the Creusot and GNATprove installs and the
provers' exit-code contracts; the planted controls make the gate report
void rather than green if either assumption fails on a runner.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xn9nqHVbUTRLgBdedoXAc8
@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 15 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 8df8afb9-df2f-48ca-823f-b50cfcdb4418
📥 Commits

Reviewing files that changed from the base of the PR and between fe13738 and 7ea1774.

⛔ Files ignored due to path filters: 1
  • .github/workflows/actions.lock is excluded by !**/*.lock
📒 Files selected for processing: 29
  • .github/workflows/creusot-gate.yml
  • .github/workflows/kanren-gate.yml
  • .github/workflows/language-gates-self-test.yml
  • .github/workflows/rust-ci.yml
  • .github/workflows/spark-gate.yml
  • ARCHITECTURE.adoc
  • README.adoc
  • actions/creusot-check/action.yml
  • actions/creusot-check/check.sh
  • actions/creusot-check/test.sh
  • actions/kanren-check/action.yml
  • actions/kanren-check/check.sh
  • actions/kanren-check/test.sh
  • actions/rust-ci-check/action.yml
  • actions/rust-ci-check/check.sh
  • actions/rust-ci-check/resolve.sh
  • actions/rust-ci-check/test.sh
  • actions/spark-check/action.yml
  • actions/spark-check/check.sh
  • actions/spark-check/test.sh
  • rollout_language_gates.sh
  • scripts/deonboard-workflow.sh
  • scripts/verify-suite-checkout.sh
  • templates/creusot-gate-caller.yml
  • templates/kanren-gate-caller.yml
  • templates/rust-ci-caller.yml
  • templates/spark-gate-caller.yml
  • templates/track-estate-audit.yml
  • tests/lock-transitive-closure.sh
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hyperpolymath
hyperpolymath marked this pull request as ready for review October 14, 2026 13:53
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
@hyperpolymath
hyperpolymath merged commit 9a947fa into main Oct 14, 2026
14 of 17 checks passed
@hyperpolymath
hyperpolymath deleted the claude/rust-ci-codeac-improvements-395dus branch October 14, 2026 14:20
@sonarqubecloud

Copy link
Copy Markdown

hyperpolymath pushed a commit that referenced this pull request Oct 19, 2026
Move all 24 hyperpolymath/cicd-suite/actions/* refs in
.github/workflows/main-estate-audit.yml from 1aa6bfb (#48) to 9a947fa,
the current main HEAD (#54's merge commit).

#51 changed actions/manifest-check and left the pins at 1aa6bfb, so
main's "Composite shell contract" has been red since 8bf6d92:
tests/lock-transitive-closure.sh reports that manifest-check is pinned at
1aa6bfb, which differs from HEAD's. The pin moves to 9a947fa rather than
8bf6d92 so it serves everything on main, including #54's additions.

This also makes #51's manifest-deed-paths-ignore and
manifest-k9-paths-ignore inputs take effect: manifest-check@1aa6bfb does
not declare them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kjdf4Mf4Z41bNQh2TrsEp9
(cherry picked from commit 80bea8c)
hyperpolymath added a commit that referenced this pull request Oct 19, 2026
## Why

#51 changed `actions/manifest-check` and, by design, left the gate pins
at `1aa6bfb` (#48). Since then main's **Composite shell contract** has
been red on every push (runs on 8bf6d92, fe13738 and 9a947fa).
`tests/lock-transitive-closure.sh` reports:

```
FAIL main-estate-audit.yml pins actions/manifest-check at 1aa6bfb, which differs from HEAD's
PASS=30 FAIL=1
```

Until the repin, #51's `manifest-deed-paths-ignore` /
`manifest-k9-paths-ignore` inputs have no effect, because
`manifest-check@1aa6bfb` does not declare them.

## What

All 24 `hyperpolymath/cicd-suite/actions/*` refs in
`.github/workflows/main-estate-audit.yml` move from `1aa6bfb` to
`9a947faad4f7f6640148980dd892b39f216fd091`. That is current main HEAD,
#54's merge commit. I chose it over #51's merge commit (`8bf6d92`) so
the pin serves everything now on main.

The diff is 24 lines out and 24 in, nothing else. Pins stay full SHAs,
and the workflow stays de-onboarded from `actions.lock`.

## Verification

- **Reproduced on main first:** `tests/lock-transitive-closure.sh`
PASS=30 FAIL=1, the failure above.
- **On this branch:**
  - `tests/lock-transitive-closure.sh`: PASS=31 FAIL=0.
  - `tests/composite-shell-contract.sh`: PASS=28 FAIL=0.
  - `tests/deonboard-lock-schemas.sh`: PASS=33 FAIL=0.
  - `tests/deonboard-estate-audit.sh`: PASS=9 FAIL=0.
- **Structure:** exactly 24 refs, all at `9a947fa…`; no `1aa6bfb` or
`@main` refs remain. `9a947fa` is an ancestor of `origin/main`.
- **actionlint:** clean on `main-estate-audit.yml`.

## Next

januskey's thin caller pins this PR's merge commit and passes
`manifest-deed-paths-ignore` for `audits/assail-classifications.a2ml`.
That clears januskey's red `manifests` check.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Kjdf4Mf4Z41bNQh2TrsEp9)_

Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request Oct 19, 2026
…; pin Alire by hash; re-pin the theatre gate (#57)

## What the first live caller showed

The first cross-repository call of `rust-ci.yml`
(hyperpolymath/plasma-parser-writer#108, [run
39251770946](https://github.com/hyperpolymath/plasma-parser-writer/actions/runs/39251770946))
died at startup:

> The action
EmbarkStudios/cargo-deny-action@3c63498
is not allowed in hyperpolymath/plasma-parser-writer because all actions
must be from a repository owned by hyperpolymath, created by GitHub,
verified in the GitHub Marketplace, or match one of the patterns: …

`creusot-gate.yml` from the same commit resolved and ran on that PR
(detect, theatre gate and verdict all green), which also answers the
callee-lock question #54 left open: a gate workflow that is deliberately
not keyed in this repository's lock resolves fine. The Actions policy is
evaluated in the **caller's** repository, so a reusable may only use
what every caller is allowed, and nothing in this repository's own CI
could ever see the refusal.

## What this PR does

* **`rust-ci.yml`** — cargo-deny is installed through
`taiki-e/install-action` (the installer the coverage job and hypatia's
green workflows already use) at the version cargo-deny-action shipped
(`0.20.2`, new input `cargo_deny_version`), and run as plain `cargo
deny` steps with the argument shape the action used (global args,
`--manifest-path`, command).
* **`spark-gate.yml`** — Alire is a sha256-pinned release binary (alr
`2.1.1` x86_64 Linux, the version `setup-alire` v6.0.0 defaults to; new
inputs `alr_version` / `alr_sha256`, hash recorded from the downloaded
asset) followed by `alr -n toolchain --select gnat_native=<v> gprbuild`,
which is what `alire-project/setup-alire` does on Linux. That action is
also outside the allowed owners, and it nests `actions/cache/restore@v4`
and `actions/setup-node@v4`, floating tags no caller under
`sha_pinning_required` may carry. The nested standards theatre gate
moves from `95de3df` to `75bd599`: since about 2026-10-15 GitHub
validates a called reusable against the callee's `actions.lock` and
rejects records whose `ref:` is their own SHA; `95de3df`'s lock has them
(hypatia PIN-003, hyperpolymath/hypatia#931, lists the 545 such
standards commits), `75bd599` is the first that does not. The theatre
gate's content is identical at both commits.
* **`tests/gate-action-owners.sh`**, run by
`language-gates-self-test.yml` — every `uses:` in the four gates names
an owner in {actions, github, hyperpolymath, dtolnay, swatinem,
goto-bus-stop, taiki-e} at a full SHA; a planted disallowed owner and a
planted tag pin must both be refused or the guard reports NO CHECK (exit
2).
* **README** — what a gate may use, what the callee lock must look like,
and how a consumer with a lock-sync gate onboards a caller
(hyperpolymath/cicd-squabbler#135 is the worked example for its
standards callers).

## Evidence

actionlint clean on the three workflows; shellcheck clean on the guard;
the four gate test suites (31/27/19/19) and the composite shell contract
(28) still pass; the owners guard passes with its planted control
tripping. `tests/lock-transitive-closure.sh` fails 6 checks on this
branch **and on main alike** (`manifest-check` pinned at `1aa6bfb` in
`main-estate-audit.yml`, the subject of #56);
nothing here touches it.

## Not yet witnessed live

The pinned-alr path and `cargo deny` through install-action run for the
first time on the first consumer that pins this commit; the planted
controls still make a broken install report void, never green. After
this merges, plasma-parser-writer#108's pin moves to the merged SHA and
`Rust CI` runs there for the first time; cicd-squabbler can then onboard
the Rust and SPARK gates with a closure that no longer needs ids this
session could not obtain.

Commits on this branch are unsigned: no signing key is available in this
session (the configured key file is empty). GitHub signs the squash
merge.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Xn9nqHVbUTRLgBdedoXAc8)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
hyperpolymath added a commit that referenced this pull request Oct 19, 2026
… the schema guard and the case fix (#56)

## What was wrong

`scripts/deonboard-workflow.sh` (#54) is a copy of the estate-audit
de-onboard script, taken before #52 and #53 landed. It has neither fix:

1. **No schema guard.** It accepts any `actions.lock` schema. On a
`v9.9.9` lock it exits 0 and edits the lock. #53's fail-closed guard
(exit 3) lives only in `deonboard-estate-audit.sh`.
2. **Case-sensitive prune.** It compares dependency keys byte for byte.
Take a lock where the `hyperpolymath/standards` record reaches
`swatinem/rust-cache@6323deb…` but the record key is
`Swatinem/rust-cache@6323deb…`. The script prunes that record and leaves
a dangling edge, which startup-fails the run. This is the januskey shape
#52 fixed, but only in the estate-audit copy.

**Who was exposed:** `rollout_language_gates.sh` de-onboards every Rust
CI, Creusot, SPARK and miniKanren caller through
`deonboard-workflow.sh`. Rust CI callers are exactly the repositories
whose locks carry the `standards` → `rust-cache` edge.

As far as this session knows, no rollout has run since #54 merged, so
this is a latent defect rather than a broken estate. That is ASSUMED: I
have no rollout logs.

The `deonboard-workflow.sh` header and README line 273 on main already
said the estate-audit script "now delegates" to it. It did not; it was a
second copy.

## The change

- **`scripts/deonboard-workflow.sh`** is now the one implementation. It
carries #53's `known_versions` guard and #52's `lower_repo` prune, with
their comments carried over verbatim.
- **`scripts/deonboard-estate-audit.sh`** is now just a usage check and
one `exec …/deonboard-workflow.sh "$repo"
.github/workflows/main-estate-audit.yml`. `rollout_estate.sh`, the
templates and the README keep working through it unchanged.
- **`tests/deonboard-lock-schemas.sh`**:
  - It reads `known_versions` from the generic script.
  - Every fixture and the v9.9.9 control run through both entry points.
- The prune-skipping mutant is applied to the generic script and must be
killed through the wrapper as well, which fails if the wrapper ever
stops delegating.
  - The optional argument is now a scripts directory.
- **`tests/deonboard-estate-audit.sh`** (#52):
  - Both entry points run the same checks.
  - The two entry points must produce byte-identical locks.
- The `| lower_repo` mutant is applied to the generic script and must be
killed through both.
- **CI** (`code-hygiene-self-test.yml`):
- `tests/deonboard-estate-audit.sh` was never run in CI. It now runs in
the Composite shell contract job.
  - The workflow also triggers on `scripts/deonboard-workflow.sh`.
  - No `uses:` added.
- **Docs:** README and ARCHITECTURE now describe the delegation as it
is.
- **Ported from #55:** `3325927` is #55's repin, cherry-picked with
`-x`; the diff is byte-identical.
- **Why:** main's `lock-transitive-closure` failure would otherwise stop
the Composite shell contract job before the de-onboard steps run.
  - **If #55 merges first:** this commit becomes a no-op.

## Evidence (TESTED)

I copied the new suites into a tree of `origin/main` (`9a947fa`) and ran
them against main's scripts.

`tests/deonboard-estate-audit.sh`: PASS=14 FAIL=4
- `FAIL pruned Swatinem/rust-cache, which the standards record still
reaches`
- `FAIL dangling edge(s):
Swatinem/rust-cache@6323deb`
- `FAIL the entry points disagree: …`
- `FAIL mutant is identical to the script: the case-folding the test
exists for is gone`

`tests/deonboard-lock-schemas.sh`: PASS=57 FAIL=4
- `FAIL script declares no known_versions`
- `FAIL exit 0 on schema v9.9.9 (want 3)`
- `FAIL lock modified despite refusal`
- `FAIL orphan check passed a mutant that does not prune` (main's
wrapper does not delegate)

On this branch:

| Check | Result |
| --- | --- |
| `tests/deonboard-estate-audit.sh` | PASS=19 FAIL=0 |
| `tests/deonboard-lock-schemas.sh` | PASS=63 FAIL=0 |
| `tests/lock-transitive-closure.sh` | PASS=31 FAIL=0 |
| `tests/composite-shell-contract.sh` | PASS=28 FAIL=0 |
| `bash -n` | clean |
| `shellcheck -S warning` | clean (default severity: same SC2015/SC2016
counts as main) |
| `actionlint` | no new findings (the 8 `"$/actions/…"` findings in the
hygiene self-test are also on main) |

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01VTeVWDEJgdYKsUNr4uhnXX

---------

Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/gitbot-fleet that referenced this pull request Oct 20, 2026
…in this repo's standards callers (#615)

## Why

Three defect classes killed Rust CI across the estate this fortnight,
each a setup failure that reads as a code failure.
hyperpolymath/cicd-suite#54 built gates in which they cannot occur;
hypatia (hyperpolymath/hypatia, companion PR) detects them; this is the
actuation half: a fix script per class, a registry row, and a contract
test run by `rust.yml`.

| Class | Rule | Script |
|---|---|---|
| SHA-pinned `dtolnay/rust-toolchain` with no `toolchain:` input
(`'toolchain' is a required input`;
hyperpolymath/plasma-parser-writer#105) | WF026 |
`scripts/fix-rust-toolchain-input.sh` |
| Caller pinned at a reusable revision the estate has **measured** dead
(June 2026 toolchain window, 83 commits; 2026-08-19..10-19 lock window,
545 commits) | WF027, PIN-003, WF016 |
`scripts/fix-stale-reusable-pin.sh` +
`scripts/lib/stale-reusable-pins.tsv` |
| `actions.lock` record whose `ref:` is its own SHA, which GitHub
rejects at `Set up job` since ~2026-10-15 (`invalid lockfile pin`) |
PI006 | `scripts/fix-lock-self-sha-refs.sh` +
`scripts/lib/action-ref-tags.tsv` |

Design points worth a reviewer's eye:

* The stale-pin script moves a pin **only** to the replacement the table
names, never to "newest" (standards' `lock-selfcheck.sh` exists because
newer can be less usable). The table was generated from a walk of
standards' history, file content and lock records checked per commit,
not dates.
* If the caller's `actions.lock` names the stale SHA, it follows the
pin; two dead SHAs moving to one replacement are merged into one record.
The nested `uses:` list is **not** recomputed here and the script says
so (that closure is the `gh actions-lock` / `check-lock-sync.sh` step).
* The self-SHA script takes tags from a map whose every row comes from
the lock GitHub accepts (standards@`75bd599`), falling back to `git
ls-remote --tags`; a commit with no tag is reported and left, exit 1.
Reusable-workflow records keep their SHA ref, as the accepted lock does.
* `AGENTIC.a2ml` names what an agent may and may not do with these:
never choose a replacement SHA, never recompute a closure here, always
idempotent.

## Dogfooded on this repository

The five standards callers (governance, hypatia-scan, mirror, scorecard,
secret-scanner) were pinned inside the lock window (`da2c748`,
`571cc73`) and have been dying at `Set up job` since 2026-10-16
([Governance run
39105727502](https://github.com/hyperpolymath/gitbot-fleet/actions/runs/39105727502)
and every run after). They now pin `75bd599`; `actions.lock` holds one
`standards@75bd599` record whose nested list is the union of what those
five reusables use at that commit, every third-party record copied
verbatim from standards' own lock, the seven self-SHA refs given their
tags, and the three Dependabot bumps the lock had missed
(`download-artifact` v8.0.2, `upload-artifact` v7.0.2) resynced.
`scripts/check-lock-sync.sh`: in sync, transitively closed.

## Evidence

* `scripts/tests/fix-workflow-pins.sh`: 28 checks — planted defects
fixed, planted non-defects untouched, second runs byte-identical,
controls with an empty table. Wired into `rust.yml`'s
`dispatch-contracts` job.
* `scripts/tests/dispatch-paths.sh` still passes. `bash -n` and the
fleet's JSON registry parse.

No bot slot, manifest or quarantine change; `[mass-delete-ok]` not
needed (no deletions).

Commits on this branch are unsigned: no signing key is available in this
session (the configured key file is empty). GitHub signs the squash
merge.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Xn9nqHVbUTRLgBdedoXAc8)_

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Updated shared governance, security scanning, mirroring, and scorecard
workflows, with explicit secret mappings where needed.
* Added tools to repair stale workflow references, missing Rust
toolchain settings, and lockfile references.
* **Bug Fixes**
* Rust formatting checks now block CI when formatting requirements are
not met.
* **Tests**
* Added offline checks for workflow maintenance tools, including
verification that repeated runs leave corrected files unchanged.
  * CI now runs these checks.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
hyperpolymath added a commit to hyperpolymath/cicd-squabbler that referenced this pull request Oct 20, 2026
…sure (#135)

## What was failing

Rust CI has been red on every run since 2026-10-16 ([run
38846539059](https://github.com/hyperpolymath/cicd-squabbler/actions/runs/38846539059)
and each one after it), dying in `rust-ci / Detect Cargo.toml` at **Set
up job**:

```
Unable to resolve action `actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1`: invalid lockfile pin. Run `gh actions-lock` to update the lockfile
```

Nothing in this repository changed between the last green run
(`60e8f7a`, 2026-10-15) and the first red one: the lock and the
workflows are byte-identical across the flip. GitHub began validating a
called reusable workflow against the **callee** repository's
`actions.lock` at the called SHA, and rejects a dependency record whose
`ref:` is the bare commit SHA instead of the tag it was resolved from.
standards' lock at `8f2ee50` and `da2c748` records
`actions/checkout@3d3c42e5…` with `ref: '3d3c42e5…'`; at `75bd599`
(standards main, 2026-10-19) the same record reads `ref: 'v7.0.1'`, and
callers pinned there create jobs again (hyperpolymath/hypatia#929
witnessed it first). A walk of standards' first-parent history shows 454
main commits from 2026-08-19 to 2026-10-19 carry such a record;
`75bd599` is the first that does not. Governance, Mirror, Secret
Scanner, Hypatia Scan, Scorecard and the standards pipeline were dying
the same way, so all seven callers move together.

## What this PR does

* Re-pins the seven standards callers to
`75bd5994470661a099df562d6d5ad2fe744dbd66`. The pipeline caller passes
no inputs, so the inputs `ci-pipeline.yml` dropped since `ed5e3f6` do
not affect it.
* Rebuilds `actions.lock` instead of patching it: one
`hyperpolymath/standards@75bd599` record whose `uses:` is the union of
what the seven called reusables use at that commit, and every
third-party record copied verbatim from standards' own lock at
`75bd599`, which GitHub accepts. The two actions this repository pins
directly by SHA (`actions/attest-build-provenance`,
`softprops/action-gh-release`) now carry the tag that resolves to their
commit (`v4.2.2`, `v3.0.3`). Records nothing references are pruned.
`scripts/check-lock-sync.sh`: in sync and transitively closed.
* Resyncs two Dependabot bumps the lock had been missing since #133
(`smtp-notify-action` v0.5.0; `upload-artifact` v7.0.2 /
`download-artifact` v8.0.2), which were startup-failing
`push-email-notify.yml` and `static-analysis-gate.yml`.
* Two rustdoc fixes in `squabble-core` for the strict warnings-denied
doc build of cicd-suite's Rust gate (hyperpolymath/cicd-suite#54):
public docs linked the private items `step_concluded` and `propose_for`.

## Verified locally

`cargo fmt --check`, `cargo clippy --all-targets --locked -D warnings`,
doctests, `cargo +1.85 check --workspace --locked` (the declared MSRV)
and `cargo doc --document-private-items` with `RUSTDOCFLAGS=-D warnings`
all pass. `scripts/check-lock-sync.sh` exits 0.

## Not in this PR

Calling cicd-suite's strict Rust gate and the SPARK gate (for
`spark/squabble_gate.gpr`) from here. This repository's lock-sync gate
requires every called reusable's transitive closure in `actions.lock`,
and that closure needs records for `EmbarkStudios/cargo-deny-action` and
`alire-project/setup-alire` whose numeric repository ids this session
cannot obtain (the GitHub API is scoped to the estate's own
repositories). hyperpolymath/plasma-parser-writer#108 is the first live
caller of the cicd-suite gate under the new callee-lock validation; what
it shows decides whether cicd-suite must key its gate workflows in its
own lock first. Either way the adoption here is a follow-up, with those
two ids or with `gh actions-lock` run by someone who can.

Commits on this branch are unsigned: no signing key is available in this
session (the configured key file is empty). GitHub signs the squash
merge.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Xn9nqHVbUTRLgBdedoXAc8)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
hyperpolymath added a commit to hyperpolymath/proven-tests-and-benches that referenced this pull request Oct 20, 2026
…-suite#54 (#96)

## What

Three new proven-exact corpus units under
`corpus/provenance/reflexive/`, each a bare `module Test` with
base-library imports only (R-43), total lemmas as the warrant, and the
0/1/2 fixture triple. They are the defect classes
hyperpolymath/cicd-suite#54's gates exist to refuse, stated once and
firable forever:

| Unit | Fires when | Ground truth |
|---|---|---|
| `setup-failure-reported-as-subject-failure` | a gate claims **FAIL**
while every failure it records is a setup failure (toolchain install,
checkout, action input validation) — the subject was never checked, so
the honest verdict is VOID | plasma-parser-writer `rust-ci / Cargo check
+ clippy + fmt`, red on every run 2026-09-29 to 2026-10-14 from
`'toolchain' is a required input` (run 38564229091);
hyperpolymath/plasma-parser-writer#105 |
| `skipped-mandatory-reported-as-pass` | a gate claims **PASS** while a
job it declared mandatory concluded `skipped` — the skipped twin of
`cancelled-gate-void` | platform behaviour (a required check concluded
`skipped` does not block a merge), the reason every cicd-suite gate ends
in a verdict job; the manifest's `warrant_class` says so until a dated
estate firing exists |
| `proof-claim-without-prover` | a gate claims **PASS** while a prover
the tree advertises never ran or ran over no obligations (proof theatre)
| the contract of standards' SPARK Theatre Gate and
hyperpolymath/standards#692; cicd-suite's `creusot-gate`/`spark-gate`
theatre jobs |

Lemmas, named in each `error-model.a2ml` and checked by
`check_unit_ledger`: `firesOnSetupOnlyFail` / `silentOnSubjectFail` /
`silentOnNoFailure` / `voidClaimNeverFires`;
`firesOnSkippedMandatoryPass` / `silentOnCleanPass` /
`optionalSkipIsNotMandatory` / `failedMandatoryIsNotSkipped`;
`firesOnTheatrePass` / `silentOnHonestPass` / `unclaimedIsNotTheatre` /
`dischargedClaimIsNotTheatre`.

Registries: the three `covering main` entry points are allowlisted in
`scripts/check-escape-hatches.sh`; the firing and calibration fixtures
are registered in `.machine_readable/testing/adversarial-content.a2ml`;
`corpus/COUNT.a2ml` is regenerated (deployed 4, fired_with_date 4,
diagnosticity_complete 4, proven_exact 4, repeat_tested 4); DEBT S-9
names all four units.

## Evidence

Scripted on 2026-10-19: each unit compiled three times from a clean
`build/` under the three-signal predicate (rc 0, zero `^Error:` lines,
binary present) and fired its triple identically each time — silent 0,
firing 1, calibration 2. `stability.a2ml` carries the timestamps and the
`Test.idr` sha256.

From the repository root: `check-doc-facts.sh corpus` compiles and fires
all four units; `corpus-selftest` passes its 20 trees (with
`en_US.UTF-8` present for the collation tree); `check-doc-facts.sh
source` and `check-escape-hatches.sh` pass.

## Stated, not claimed

The authoring machine had Idris2 **0.8.0** only; the repository pins
**0.7.0**. Every new `stability.a2ml` says the first compile at the
pinned toolchain is this PR's `corpus-check` job, and
`[reproduce]`/`[replicate]` remain `no` (DEBT S-9). If `corpus-check` is
red here on something 0.7.0-specific, that is the first finding of this
PR and I will fix it here.

Commits on this branch are unsigned: no signing key is available in this
session (the configured key file is empty). GitHub signs the squash
merge.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Xn9nqHVbUTRLgBdedoXAc8)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/plasma-parser-writer that referenced this pull request Oct 20, 2026
…ate (#108)

## Why

`rust-ci / Cargo check + clippy + fmt` was red for a fortnight on every
PR (#105, fixed by the one-line re-pin
in #107). The red was a setup failure
read as a code failure: a SHA-pinned `dtolnay/rust-toolchain` given no
`toolchain:` input died before a compiler existed.
hyperpolymath/cicd-suite#54 built a Rust gate in which that class cannot
occur (the toolchain is resolved before any action runs and an empty
resolution is refused), made it stricter, and added a parallel Creusot
gate. This PR makes this repository a consumer of both.

## What

* `.github/workflows/rust-ci.yml` now calls
`hyperpolymath/cicd-suite/.github/workflows/rust-ci.yml@9a947fa`
(cicd-suite main, the merge of #54). The job id and the contexts
`rust-ci / Cargo check + clippy + fmt` and `rust-ci / Cargo test` are
unchanged, so existing branch rules keep matching. `rust-ci / Rust CI
verdict` is the context to require from now on: it goes red when any
gate failed **or was skipped while expected**.
* `.github/workflows/creusot-gate.yml`: the Rust deductive-verification
gate. This tree carries no Creusot obligations, so it reports a notice,
not assurance.
* `.github/workflows/track-estate-audit.yml`: weekly PR that moves every
cicd-suite pin here to cicd-suite HEAD, so a fix in the gate arrives as
a reviewable PR. Needs the `AUTOMATION_TOKEN` secret described in its
header to open PRs that trigger CI.

## What the stricter gate found, fixed at source

* **`cargo doc` with warnings denied**: three doc comments in
`plasma-parser/src/zone/boundary.rs` wrote `[project]`, `[[zone]]` and
`[family]` as bare brackets, which rustdoc reads as unresolved intra-doc
links. They are code spans now.
* **The declared MSRV was false**: `rust-version = "1.74"` while a
dependency needs edition 2024. Verified: `cargo +1.78 check --locked`
fails on `edition2024`; `cargo +1.85 check --locked` passes. The gate's
MSRV job builds the declared version, so the declaration now says 1.85.

## Evidence

Run locally on rustc 1.97 against this tree: `cargo fmt --check`, `cargo
clippy --all-targets --locked -D warnings`, `cargo test --locked
--all-targets`, `cargo test --locked --doc`, and `cargo doc --no-deps
--document-private-items` with `RUSTDOCFLAGS=-D warnings` all pass;
`cargo +1.85 check --workspace --locked` passes.

## Not yet witnessed live

This is the first cross-repository call of the cicd-suite Rust gate
since GitHub began validating a called workflow against the callee
repository's `actions.lock` (around 2026-10-15). cicd-suite's gate
workflows are deliberately not keyed in cicd-suite's own lock. If this
PR's `rust-ci` run dies at `Set up job` with "invalid lockfile pin" or a
workflow-file error, the fix belongs in cicd-suite (key the gate
workflows in its lock), not here, and I will report it on this PR.

Commits on this branch are unsigned: no signing key is available in this
session (the configured key file is empty). GitHub signs the squash
merge.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Xn9nqHVbUTRLgBdedoXAc8)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/hypatia that referenced this pull request Oct 20, 2026
…estate's dead Rust CI (#931)

## Why

Three defect classes killed Rust CI across the estate between 2026-09-29
and 2026-10-19, each a setup failure that reads as a code failure.
hyperpolymath/cicd-suite#54 built gates in which they cannot occur; this
PR is hypatia's half of the propagation architecture (hypatia detects →
gitbot-fleet actuates, hyperpolymath/gitbot-fleet#615 →
.git-private-farm propagates, hyperpolymath/.git-private-farm#166).
Every rule here has a fleet fix script carrying the same facts.

## What

| Rule | Where | Fires on | Fleet repair |
|---|---|---|---|
| **WF026** | `workflow_audit.ex` | a SHA-pinned
`dtolnay/rust-toolchain` step with no `toolchain:` input — the step
exits with `'toolchain' is a required input` before any cargo command
runs (hyperpolymath/plasma-parser-writer#105; standards#439 fixed the
reusable). Step bodies are bounded by indentation; tag pins never fire.
| `fix-rust-toolchain-input.sh` |
| **WF027** | `workflow_audit.ex` | a caller pinned at a reusable
revision the estate has **measured** dead for that reusable — a data
table keyed by reusable path; first row: the 83 standards main commits
of June 2026 whose `rust-ci-reusable.yml` carries the WF026 defect
(every first-parent commit `d73c93e0..49ed4715`, file content checked).
Unlike WF016 these commits resolve: the run starts and the reusable's
first step fails. | `fix-stale-reusable-pin.sh` (Window A) |
| **PIN-003** | `pr-automerge-policy.json` (read by PI001 and PA001) |
the 545 standards commits reachable from main, 2026-08-19..2026-10-19,
whose `actions.lock` carries an action record with its own SHA as
`ref:`. Since ~2026-10-15 GitHub validates a called reusable against the
**callee's** lock at the called SHA and rejects those records (`invalid
lockfile pin`), so every standards reusable at those revisions dies at
`Set up job` for every caller (#929; cicd-squabbler
run 38846539059, byte-identical to its last green run). `known_good_sha`
is `75bd599`, the first main commit with a clean lock. |
`fix-stale-reusable-pin.sh` (Window B) |
| `known_reusables` | `sha_bump_propagation.ex` | cicd-suite's estate
audit and the Rust, Creusot, SPARK and miniKanren gates, so a cicd-suite
bump feeds the propagator like a standards bump. | — |

A note on PIN-003's provenance: standards' own
`scripts/lock-selfcheck.sh` rates those commits SELF-CONSISTENT, because
it checks that every ref is *keyed*, not that a key's `ref:` is a tag.
The list was produced by a walk of every reachable commit, lock content
parsed per commit.

## Tests

* `test/rules/workflow_audit_pins_test.exs` (new, 13 tests): fires /
silent / the indentation boundary / the per-reusable window / the
table's edges (83 rows, edges in, replacement out) / the audit's counts.
* `test/rules/pin_integrity_test.exs`: reads the committed policy with
OTP's `:json`; PIN-003 denylists `8f2ee50` through a reusable path,
while `75bd599` and the June revisions are not denylisted.
* `test/rules/sha_bump_propagation_test.exs`: the cicd-suite rows.

Hex is unreachable from this session, so `mix test` could not run here.
The WF026/WF027 tests were run against a scratch build of the new
functions (13/13), and the pin-integrity, lock and SHA-bump suites
against the compiled modules (all pass; the two pre-existing
`actions_lock_test` failures outside Mix — v0.0.3 lock, `Hypatia.Rules`
not loaded — are unrelated). `mix format --check-formatted` passes on
every changed file. CI's `mix test` is the first full run; if it finds
something, I fix it here.

`AGENTIC.a2ml` records the contract: tables extend only from a measured
walk, an agent never names a replacement revision, and the WF027 table /
PIN-003 mirror gitbot-fleet's `stale-reusable-pins.tsv` windows A and B
and are regenerated together.

Commits on this branch are unsigned: no signing key is available in this
session (the configured key file is empty). GitHub signs the squash
merge.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Xn9nqHVbUTRLgBdedoXAc8)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
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.

2 participants