Skip to content

Commit 7d964ee

Browse files
fix: real SHA-pinning check, real Justfile targets, and docs that match the code (#144)
Three independent commits, each droppable on its own. Two fix gates that could never fail; one fixes documentation that actively misdirects. --- ## 1. `docs:` — two files misstate the code they describe ### `PROOF-NEEDS.md` Claimed *"1 `Admitted` in `proofs/coq/lambda/LambdaCNO.v` (y_not_cno)"*. Measured against `absolute-zero 87902bb7`: ``` $ grep -rn "Admitted" absolute-zero --include=*.v | wc -l 0 $ grep -rn "^Axiom" absolute-zero --include=*.v | wc -l 23 ``` **Zero `Admitted`. Twenty-three `Axiom`s across 6 files.** The old wording was wrong in *both* directions — it overstated the incompleteness and understated the trusted base 23×. > **Why this matters operationally:** an `Axiom` **passes** a "no `sorry` / no `Admitted`" gate silently. Counting only `Admitted` measures the wrong thing. `y_not_cno` is a **KEPT AXIOM** with a written rationale (`LambdaCNO.v:388-399`), not an unproven hole — and it is *not* the "concrete, closable proof obligation" the old text claimed. The in-source note explains it needs an invariant closed under the full reduction congruence, or a coinductive/step-indexed argument. The doc now defers to the **AXIOM AUDIT** already in `physics/LandauerDerivation.v`, which is notably self-critical — it records that `cno_zero_energy_dissipation_derived` is an axiom *despite its `_derived` name*, and that the triage docs' "DISCHARGE" marks are inaccurate. **Promoted to the top of "What Needs Proving"** — the audit's own SOUNDNESS WARNINGS: `prob_nonneg` and `prob_normalized` are false over unconstrained function-type distributions, and `shannon_entropy_maximum`'s inequality is **backwards** (asserts uniform *minimises* entropy). All three are currently **unused** — cheap now, expensive later. ### `aletheia/CLAUDE.md` Said *"all core logic lives in `src/main.rs` (~950 lines)"* and *"don't split into modules unless >1000 lines"*. It has been **5 modules / 995 lines** for a while, `main.rs` at 121. That instruction would tell the next agent to **undo the existing structure**. Also corrected: 23 workflows → 16; `flake.nix` listed but absent; 18 integration tests → 32. Added a prominent warning that those 16 nested workflows have **never run** (root-only discovery) — the fault that let this crate stay uncompilable for a month. --- ## 2. `fix(aletheia):` — the SHA-pinning check could never fail ```rust if line.contains("@v") && !line.contains("@") { ``` `contains("@v")` **implies** `contains("@")`, so the second clause is always false and `has_unpinned` could never be set. Proven before changing anything: ``` uses: actions/checkout@v4 old_detects_unpinned=false ``` This is aletheia's Silver-level *"GitHub Actions SHA pinning"* check — and pointedly, the exact check that would have caught `SonarSource/sonarqube-scan-action@master`, the unpinned action that broke this repo's Governance and CodeQL in #139. Replaced with `uses_line_is_pinned`, requiring 40 hex chars after the final `@`, which also: - accepts the inline `- uses:` form (the estate's existing linter anchors to line-start and misses it) - ignores a trailing `# v7.0.1` provenance comment, so a correct pin with a stale comment isn't a false positive - exempts `./…` local actions/reusables and `docker://` refs Also replaced `assert!(true)` in `test_file_exists` with a real assertion, anchored on `env!("CARGO_MANIFEST_DIR")` so it is deterministic regardless of CWD. **Verified:** 29 unit tests (was 26) · `cargo fmt --check` clean · clippy 25 → 23. End-to-end `cargo run -- .` now reports `[FAIL] GitHub Actions SHA pinning`, correctly finding the one genuinely unpinned action — where before the fix it reported a pass. Refs #125. --- ## 3. `fix(#99):` — root `Justfile` was a fake gate ```make build: @echo "Build not configured yet" ``` `build`, `test`, `fmt`, `lint`, `clean` all printed a string and **exited 0**. Wired to the same commands root `rust-ci.yml` runs, in the same order, so `just check` means what CI means. Two deliberate limits, documented **in the recipes** so nobody "fixes" them: - `test` is `--bins` only — the integration suite is a spec for a CLI that doesn't exist; 27/29 fail by design (#124). Adding `--tests` would make the bar green by breaking it. - `lint` is not yet `-D warnings` (#125). When that closes it must be added **here and to `rust-ci.yml` together**, so local and CI never disagree. **Verified by running them, not reading them:** `just deps-check` → `OK: zero dependencies`; `just test` → 29 passed; `just check` → exit 0. **And verified the gate can actually fail** — appending badly-formatted Rust makes `just fmt` exit 1 while `just build` still exits 0; reverting restores 0. A gate nobody has watched fail is not a gate. Closes #99. --- ## Not in this PR - **#124** — still blocked on the source-of-truth question for RSR checks - **`guix.scm`** identity/licence clobber — separate, more urgent: #143 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent b61df34 commit 7d964ee

4 files changed

Lines changed: 262 additions & 48 deletions

File tree

Justfile

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,60 @@ import? "contractile.just"
88
default:
99
@just --list
1010

11-
# Build the project
11+
# These recipes mirror the root `.github/workflows/rust-ci.yml` gate exactly, so
12+
# `just check` locally means the same thing as CI. They MUST fail loudly — a recipe
13+
# that echoes and exits 0 is a fake gate (issue #99 was exactly that).
14+
15+
# Build aletheia (debug + release, locked)
1216
build:
13-
@echo "Build not configured yet"
17+
cd aletheia && cargo build --locked --all-targets
18+
cd aletheia && cargo build --locked --release
1419

15-
# Run tests
20+
# Run aletheia's unit tests (--bins only; see #124 note in recipe)
1621
test:
17-
@echo "Tests not configured yet"
22+
# `--bins` is deliberate. The integration suite is a specification for a CLI
23+
# that has not been built yet — 27 of 29 fail by design (issue #124).
24+
# Do NOT add `--tests` here to make the bar look green.
25+
cd aletheia && cargo test --locked --bins
1826

19-
# Format code
27+
# Check formatting (does not modify files)
2028
fmt:
21-
@echo "Formatting not configured yet"
29+
cd aletheia && cargo fmt --check
30+
31+
# Apply formatting
32+
fmt-fix:
33+
cd aletheia && cargo fmt
2234

23-
# Lint code
35+
# Lint aletheia (not yet -D warnings — issue #125)
2436
lint:
25-
@echo "Linting not configured yet"
37+
# 23 findings remain, mostly dead code that exists because the CLI is
38+
# unwired (#124). When #125 closes, add `-- -D warnings` here AND to
39+
# rust-ci.yml in the same change, so local and CI never disagree about
40+
# what "lint passes" means.
41+
cd aletheia && cargo clippy --locked --all-targets
42+
43+
# Enforce the zero-dependency RSR Bronze constraint (mirrors rust-ci.yml)
44+
deps-check:
45+
#!/usr/bin/env bash
46+
set -euo pipefail
47+
cd aletheia
48+
if cargo tree --depth 1 | tail -n +2 | grep -q '[a-z]'; then
49+
echo "ERROR: Aletheia must have zero dependencies (see aletheia/CLAUDE.md)"
50+
cargo tree --depth 1
51+
exit 1
52+
fi
53+
echo "OK: zero dependencies"
54+
55+
# Everything the root CI gate runs, in the same order
56+
check: build test fmt deps-check
57+
58+
# Self-verify: run aletheia against this repository
59+
self-verify:
60+
cd aletheia && cargo run --locked --quiet -- ..
2661

2762
# Clean build artifacts
2863
clean:
29-
@echo "Clean not configured yet"
64+
cd aletheia && cargo clean
3065

3166
# Run panic-attacker pre-commit scan
3267
assail:

PROOF-NEEDS.md

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,73 @@ Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
66

77
## Current State
88

9+
*Re-measured 2026-07-27 against the `absolute-zero` submodule at `87902bb7`.*
10+
911
- **src/abi/*.idr**: NO
10-
- **Dangerous patterns**: 1 `Admitted` in `proofs/coq/lambda/LambdaCNO.v` (y_not_cno theorem)
12+
- **`Admitted` count**: **0** (`grep -rn Admitted absolute-zero --include=*.v`)
13+
- **Trusted base**: **23 `Axiom` declarations across 6 `.v` files**, each classified
14+
in-source. See the **AXIOM AUDIT** block at the end of
15+
`proofs/coq/physics/LandauerDerivation.v` — that audit, not this file, is the
16+
authoritative record.
1117
- **LOC**: ~22,700 (Rust + Coq)
1218
- **ABI layer**: Missing
13-
- **Existing proofs**: Coq proofs for lambda CNO (3/4 proven), quantum mechanics exactness
19+
- **Existing proofs**: Coq proofs for lambda CNO, Landauer derivation chain,
20+
quantum mechanics exactness
21+
22+
> **Correction (2026-07-27).** This file previously claimed *"1 `Admitted` in
23+
> `proofs/coq/lambda/LambdaCNO.v` (y_not_cno)"*. There are **zero** `Admitted`
24+
> anywhere. `y_not_cno` is a **KEPT AXIOM** — a declared trust assumption with a
25+
> written rationale (`LambdaCNO.v:388-399`), not an unproven hole. The old wording was
26+
> wrong in both directions: it overstated the incompleteness *and* understated the
27+
> trusted base by a factor of 23.
28+
>
29+
> The distinction matters operationally: an `Axiom` **passes** a "no `sorry` /
30+
> no `Admitted`" gate silently, so counting only `Admitted` measures the wrong thing.
31+
> Any proof gate for this repo must scan for `Axiom` too.
32+
33+
### Axiom classification (summarised from the in-source audit)
34+
35+
| Class | Count | Meaning |
36+
|---|---|---|
37+
| METAL-BOUNDARY | 6 | genuine empirical physics, not derivable (k_B, temperature, Second Law, isothermal work bound, Landauer lower bound, reversible ⇒ zero dissipation) |
38+
| SPECIFICATION | 4 | sound, but not dischargeable while `shannon_entropy` / `product_dist` stay opaque |
39+
| NOT-YET-DISCHARGED (class A) | 2 | `cno_preserves_shannon_entropy`, `cno_zero_energy_dissipation_derived` |
40+
| SOUNDNESS WARNINGS | 3 | **false as stated**, currently **unused** — see below |
41+
42+
The audit is notably self-critical: it records that
43+
`cno_zero_energy_dissipation_derived` is an axiom **despite its `_derived` name**, and
44+
that the triage docs' "DISCHARGE" marks on it and on `reversible_zero_dissipation` are
45+
**inaccurate**. Both are kept honestly rather than fake-derived.
1446

1547
## What Needs Proving
1648

1749
| Component | What | Why |
1850
|-----------|------|-----|
19-
| Y combinator non-CNO (y_not_cno) | Close the remaining Admitted proof | 1 of 4 lambda CNO theorems is incomplete |
51+
| **Unsound-but-unused axioms** | Fix or delete `prob_nonneg`, `prob_normalized` (false over unconstrained function-type distributions — need a bundled distribution type) and `shannon_entropy_maximum` (**stated inequality is backwards** — asserts uniform *minimises* entropy) | They are false. Unused today, so harmless today; the moment anything cites one, it proves anything. **Highest priority.** |
52+
| `cno_preserves_shannon_entropy` | Discharge, or accept as a stated postulate | class A — carrier/quotient issue |
53+
| `cno_zero_energy_dissipation_derived` | Rename, or supply `internal_energy` CNO-invariance | `internal_energy` is an opaque `Parameter` with no preservation law, so this cannot be a pure derivation |
2054
| Absolute-zero brainfuck interpreter | Interpreter preserves CNO properties | Claims of computational zero need formal backing |
21-
| Absolute-zero whitespace interpreter | Same as brainfuck — CNO preservation | Both esoteric interpreters need same guarantee |
55+
| Absolute-zero whitespace interpreter | Same as brainfuck — CNO preservation | Both esoteric interpreters need the same guarantee |
2256
| Aletheia verification checks | Verification pipeline produces sound results | Rhodibot extraction depends on correct checks |
2357
| Quantum mechanics proofs | Extend QuantumMechanicsExact.v coverage | Existing proofs are partial |
2458

59+
**Not on this list: `y_not_cno`.** It is not a "concrete, closable proof obligation".
60+
The in-source rationale explains why: a rigorous proof must rule out reaching the
61+
argument under *every* interleaving of `beta_reduce` (which permits reduction under
62+
binders and on either side of an application), requiring an invariant closed under the
63+
full reduction congruence, or a coinductive / step-indexed non-termination argument.
64+
Genuinely out of scope, not merely tedious.
65+
2566
## Recommended Prover
2667

27-
**Coq** — Existing proof infrastructure is in Coq. The `y_not_cno` Admitted needs to be closed in Coq. Aletheia (Rust) verification would benefit from an **Idris2** ABI layer.
68+
**Coq** — the existing proof infrastructure is in Coq. Aletheia (Rust) verification
69+
would benefit from an **Idris2** ABI layer.
2870

2971
## Priority
3072

31-
**MEDIUM** — Has existing proof infrastructure with one known gap. The Admitted y_not_cno is a concrete, closable proof obligation. Aletheia verification correctness is more important long-term.
73+
**MEDIUM** — the proof infrastructure is real and its trusted base is honestly
74+
documented. The one genuinely urgent item is the three **unsound** axioms: they are
75+
currently unused, so this is cheap to fix now and expensive to discover later.
3276

3377
## Template ABI Cleanup (2026-03-29)
3478

aletheia/CLAUDE.md

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,56 @@ Aletheia maintains **zero unsafe blocks** for RSR compliance.
4949

5050
## Architecture Principles
5151

52-
### Single-File Implementation
52+
### Module Layout (updated 2026-07-27 — this section was stale)
5353

54-
All core logic lives in `src/main.rs` (~950 lines). This design is intentional:
54+
> **This file used to say "all core logic lives in `src/main.rs` (~950 lines)" and
55+
> "don't split into modules unless >1000 lines". Both were out of date.** The crate has
56+
> been split for some time. Measured 2026-07-27:
5557
56-
**Benefits**:
57-
- Easy to audit (one file to read)
58-
- Minimal complexity
59-
- Clear code flow
60-
- No hidden abstractions
58+
| File | Lines | Contents |
59+
|---|---|---|
60+
| `src/main.rs` | 121 | CLI entry, arg parsing, `verify_repository`, exit policy |
61+
| `src/checks.rs` | 316 | `check_documentation`, `check_spdx_headers`, `check_workflow_pins`, `check_path_security`, glob matching |
62+
| `src/config.rs` | 243 | `.aletheia.toml` loading, hand-rolled TOML parse |
63+
| `src/output.rs` | 226 | human / JSON / SARIF report printing, date+time formatting |
64+
| `src/types.rs` | 89 | `ComplianceLevel`, `CheckResult`, `ComplianceReport`, … |
65+
| **total** | **995** | |
66+
67+
The single-file rationale still applies *in spirit* — prefer few, auditable files over
68+
deep abstraction — but do not "restore" the single-file layout, and do not treat 1000
69+
lines as a threshold that has not yet been crossed.
6170

6271
**When to add more files**:
6372
- Integration tests in `tests/` directory
6473
- Examples in `examples/` directory
6574
- Documentation in `docs/` directory
6675

6776
**When NOT to add files**:
68-
- Don't split into modules unless >1000 lines
6977
- Don't create abstractions prematurely
7078
- Don't add utility files for one-off functions
7179

80+
### Known gap: the CLI is unfinished (issues #124 / #125)
81+
82+
`main.rs` parses only `<repo-path>` plus `--json` / `--sarif`, and wires **three**
83+
checks. `tests/integration_tests.rs` is 806 lines / 32 tests describing a much larger
84+
tool (16 Bronze checks plus Silver, `--help`, `--version`, `--verbose`, `--badge`,
85+
`--init-hook`, `--format=`, HTML output). **2 pass, 27 fail.**
86+
87+
Two things to know before touching it:
88+
89+
1. **Those tests assert on stdout substrings**, e.g.
90+
`assert!(stdout.contains("Bronze-level RSR compliance: ACHIEVED"))`. They pin the
91+
*wording* of the report and say nothing about what the checks must verify — so they
92+
can be satisfied by checks that verify nothing. Treat them as a UI contract, not a
93+
specification.
94+
2. **A definition of RSR conformance already exists** elsewhere in the estate (hypatia's
95+
`rsr-conformance` oracle). Writing checks to satisfy these strings risks creating a
96+
second, divergent definition. Resolve the source-of-truth question first.
97+
98+
Most of the clippy findings in #125 are dead code that exists *because* those modules
99+
are unwired. **Do not silence them with `#![allow(dead_code)]`** — the root Rust CI
100+
header forbids it, and that dead code is the specification of the missing feature.
101+
72102
### Type Safety First
73103

74104
Leverage Rust's type system:
@@ -274,23 +304,26 @@ When making changes, ensure these remain true:
274304

275305
```
276306
aletheia/
277-
├── src/
278-
│ └── main.rs # Core implementation (~950 lines)
307+
├── src/ # 5 modules, 995 lines total — see Module Layout above
308+
│ ├── main.rs # CLI entry (121)
309+
│ ├── checks.rs # compliance checks (316)
310+
│ ├── config.rs # .aletheia.toml (243)
311+
│ ├── output.rs # human/JSON/SARIF (226)
312+
│ └── types.rs # core types (89)
279313
├── tests/
280-
│ └── integration_tests.rs # Integration tests (18 tests)
314+
│ └── integration_tests.rs # 32 tests — 2 pass, 27 fail (issue #124)
281315
├── benches/ # Performance benchmarks
282316
├── examples/ # Usage examples
283317
├── fuzz/ # Fuzzing infrastructure
284318
├── .well-known/
285319
│ ├── security.txt # RFC 9116 security contact
286320
│ ├── ai.txt # AI training policies
287321
│ └── humans.txt # Human attribution
288-
├── .github/workflows/ # 23 GitHub Actions workflows
322+
├── .github/workflows/ # 16 files — ⚠ ALL INERT, see below
289323
├── Cargo.toml # Zero dependencies, MSRV 1.80
290324
├── Cargo.lock # Lock file (commit this)
291325
├── Justfile # Build automation
292-
├── flake.nix # Nix reproducible builds
293-
├── .gitlab-ci.yml # CI/CD pipeline
326+
├── .gitlab-ci.yml # CI/CD pipeline (GitLab mirror)
294327
├── .gitignore # Git ignore patterns
295328
├── README.adoc # User documentation (AsciiDoc)
296329
├── SECURITY.md # Security policy
@@ -305,6 +338,22 @@ aletheia/
305338
└── META.scm # Project metadata and ADRs
306339
```
307340

341+
### ⚠ The 16 workflows in `aletheia/.github/workflows/` have NEVER run
342+
343+
`aletheia/` is **vendored into `maa-framework` as plain tracked files** (mode 100644),
344+
not a submodule, and GitHub Actions reads `.github/workflows/` **at the repository root
345+
only**. There is no standalone `hyperpolymath/aletheia` repo running them either — it was
346+
deleted around January 2026 and its content vendored here.
347+
348+
Consequence: editing anything under `aletheia/.github/workflows/` has **no effect on
349+
CI whatsoever**. This is not hypothetical — it is how commit `b5322c2` (2026-06-17) left
350+
this crate **failing to compile for over a month** with nobody noticing.
351+
352+
**The real gate is `/.github/workflows/rust-ci.yml` at the repository root.** It runs
353+
`cargo build` (debug + release), `cargo test`, `cargo fmt --check` and a zero-dependency
354+
assertion, with `working-directory: aletheia`. Add gates there, not here. See
355+
`aletheia/.github/workflows/README.md`.
356+
308357
## Troubleshooting
309358

310359
### "Dependency detected" error
@@ -368,7 +417,7 @@ For questions about this document or Aletheia development:
368417

369418
---
370419

371-
**Last Updated**: 2026-02-05
372-
**Version**: 1.1
420+
**Last Updated**: 2026-07-27
421+
**Version**: 1.2
373422

374423
*"Alētheia is not just absence of falsehood, but active unconcealment of truth."*

0 commit comments

Comments
 (0)