verifying-crypto-with-lean/check-book.sh

127 lines
5.7 KiB
Bash
Raw Normal View History

move 7: the book's button — check-book.sh + check-book.py The only source of 'ALL GREEN' for this repository. Rebuilds the PDF, then verifies 93 countable claims printed in the book against reality measured at run time: - source hygiene: inputs<->files both directions, contiguous ch01..ch14, every chapter (and the interlude) ends on its checkpoint, per-chapter exercise count == solution count with hand-typed numbering N.1..N.k - built PDF: >=100 pages, zero unresolved references, any page-count claim in prose must equal pdfinfo - internal congruence: chapter-count words in README/ch01 vs measured N ('spent twelve chapters' in ch13 is checked as a positional count, not grepped as stale — the spelling-vs-property lesson, applied to the checker itself); week-plan heading == max table row; the discussion-exercise roster parsed from prose == measured set; the SLH-DSA arithmetic recomputed from scratch (digest split 21/7/2, sig 7856, fixed 254, per-layer max 510 by brute force, worst 3824, checksum digit examples) and each value required present in ch13 - cross-repo congruence: 19 leaves derived by property (six-digit filenames + index fields — the entries/ glob counts 25); every nineteen/19 claim in prose parsed and compared; leaves 13-16 subjects + 44 certs; leaves 12/17 = 61; leaves 0-11 = 16; leaf 18 = 11 certs, apex cone kernel-3+5 oracles, ht cone f,h,t_l, four kernel-3-only plumbing certs, all cones exact; first dual-signed head at size 14; final head size == leaf count; ch13 parameter card == the const-generic arguments parsed out of the extracted Funs.lean; ch07's 71-digit Q == P25519.lean digit for digit Fails closed: a missing sibling repo is a FAILURE, not a skip; BOOK_LOCAL_ONLY=1 skips cross-repo loudly and never prints ALL GREEN. --selftest mutates copies of the sources seven ways (count drift, deleted solution, one Q digit, leaf-count drift, arithmetic drift, stray box after a checkpoint, plan/heading divergence) and requires each to be caught BY ITS OWN CHECK, plus an unmutated control that must pass. Full run: ALL GREEN (93 checks). Selftest: 8/8. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-08 12:16:30 +00:00
#!/usr/bin/env bash
# check-book.sh — THE button for verifying-crypto-with-lean.
#
# This script is the only source of the words "ALL GREEN" for this
# repository. It rebuilds the book from the committed sources and then
# verifies that every countable claim printed in the book matches reality
# measured at run time: chapter counts, the week plan, exercise/solution
# pairing, the recomputed SLH-DSA arithmetic, the transparency log's leaf
# and certificate counts, the first dual-signed head, the extracted
# parameter card, and the 71-digit Q — digit for digit.
#
# Phases
# 0 source hygiene (check-book.py)
# 1 build (tectonic via build.sh; fails on TeX errors)
# 1b built-PDF claims (pages, unresolved refs, page-count claims)
# 2 internal congruence (counts and arithmetic inside the book)
# 3 cross-repo congruence (log + fips205 + P25519 siblings)
#
# Environment
# BOOK_LOCAL_ONLY=1 skip phase 3; verdict is downgraded, never ALL GREEN
# ESTATE_ROOT parent dir of the sibling repos (default: ../)
# LTL_DIR / FIPS205_DIR / P25519_FILE override individual siblings
#
# Modes
# ./check-book.sh full run
# ./check-book.sh --selftest adversarial self-test: mutates copies of the
# sources and asserts the button turns RED
set -euo pipefail
cd "$(dirname "$0")"
HERE="$(pwd)"
selftest() {
echo "=== SELFTEST: the button must go red for the right reasons ==="
command -v python3 >/dev/null || { echo "python3 required"; exit 1; }
# the mutated copy keeps the REAL sibling repos: only the book is mutated,
# so a red verdict proves the mutation was caught, not that a repo was lost
local ESTATE; ESTATE="${ESTATE_ROOT:-$(dirname "$HERE")}"
local tmp out pass=0 fail=0
run_copy() {
tmp="$(mktemp -d)"; mkdir -p "$tmp/chapters"
cp main.tex README.md "$tmp/"; cp chapters/*.tex "$tmp/chapters/"
}
run_mutated() { # $1 description, $2 mutation cmd, $3 expected FAIL substring
run_copy
( cd "$tmp" && eval "$2" )
out="$(SKIP_BUILD=1 ESTATE_ROOT="$ESTATE" python3 "$HERE/check-book.py" "$tmp" 2>&1)" \
&& { echo " FAIL mutation NOT caught: $1"; fail=$((fail+1)); rm -rf "$tmp"; return; }
if echo "$out" | grep -q "FAIL.*$3"; then
echo " ok caught for the right reason: $1"; pass=$((pass+1))
else
echo " FAIL red, but not on the expected check ('$3'): $1"; fail=$((fail+1))
echo "$out" | grep " FAIL" | head -3
fi
rm -rf "$tmp"
}
# control: the unmutated copy must pass (proves the harness can go green)
run_copy
if SKIP_BUILD=1 ESTATE_ROOT="$ESTATE" python3 "$HERE/check-book.py" "$tmp" >/dev/null 2>&1; then
echo " ok control: unmutated copy passes"; pass=$((pass+1))
else
echo " FAIL control: unmutated copy should pass but is red"; fail=$((fail+1))
SKIP_BUILD=1 ESTATE_ROOT="$ESTATE" python3 "$HERE/check-book.py" "$tmp" | grep FAIL || true
fi
rm -rf "$tmp"
run_mutated "chapter-count claim drifts (fourteen -> thirteen)" \
"sed -i 's/fourteen chapters/thirteen chapters/' README.md" \
"README chapter count"
run_mutated "a solution deleted (ch13 solhead 13.6 dropped)" \
"sed -i 's/\\\\solhead{13.6}/% gone/' chapters/ch13-second-summit.tex" \
"ch13: exercises == solutions"
run_mutated "one digit of the 71-digit Q changed in ch07" \
"sed -i 's/740582127325613583022312264370627886761/740582127325613583022312264370627886762/' chapters/ch07-primality-certificates.tex" \
"printed Q == repository"
run_mutated "leaf-count claim drifts (nineteen leaves -> twenty)" \
"sed -i \"s/log's nineteen leaves/log's twenty leaves/\" chapters/ch14-attestation-protocol.tex" \
"ch14 'nineteen leaves'"
run_mutated "worst-case arithmetic drifts (3,824 -> 3,689)" \
"sed -i 's/3{,}824/3{,}689/' chapters/ch13-second-summit.tex" \
"ch13 prints worst total"
run_mutated "a chapter stops ending on its checkpoint" \
"printf '\n\\\\begin{aha}\nstray box after the checkpoint\n\\\\end{aha}\n' >> chapters/ch05-numbers-and-automation.tex" \
"ch05.*last environment is checkpoint"
run_mutated "week plan and heading diverge (heading says fifteen)" \
"sed -i 's/A fourteen-week plan/A fifteen-week plan/' main.tex" \
"week-plan heading"
echo
if [ "$fail" -gt 0 ]; then
echo "SELFTEST RED: $fail defect(s) in the button itself"; exit 1
fi
echo "SELFTEST GREEN: $pass/$pass (control + 7 mutations, each caught on its own check)"
exit 0
}
[ "${1:-}" = "--selftest" ] && selftest
echo "=== Phase 1: build ==="
print-quality pass: the book gets looked at, and the looking becomes a gate The operator caught what no check had ever tested: nobody had LOOKED at the rendered pages. A ten-inspector visual audit of all 129 pages (every page opened as an image) found 40 defects, including didactic correctness bugs invisible to the text layer: BAD, fixed: - ch03 printed WRONG Lean operators: \lean{P /\ Q} lost its backslash ('P / Q') and \lean{P \/ Q} lost the operator entirely ('P Q') — TeX ate them inside the non-verbatim macro. Now the unicode ∧/∨ the book uses everywhere else. - ch12: the doubling display overflowed its box border, slicing the math; stacked on two lines. - toolkit Card 6: the headroom-audit display was clipped by the page edge; now an align* stack. UGLY, fixed: - title page: the 'pyramid motif' at 5% white opacity on near-black rendered as smudge artifacts, plus a clipped ∀ glyph in the corner — redrawn with solid mixed colors (no transparency), glyph removed; the footer's mid-word paragraph gap was a \vspace landing inside horizontal mode; fixed with \par - ch06: both clock diagrams' wrap-around arrows ran counterclockwise, retracing over earlier arcs — target position expressed as 12 (one revolution) so the arc continues clockwise, landing on 0 (mod 12) and 1 (mod 11) correctly - ch04: two_mul'' printed as two_mul" (quote ligature) - one-line orphaned box fragments and stranded solution headings throughout: bigidea/tryit/pitfall/aha/checkpoint are now unbreakable (none exceeds half a page), worked boxes announce '(continued)' after a break, \solhead keeps four lines with \Needspace - --all/--receipt flags printed as one merged dash: \ddash macro - inline code no longer hyphen-breaks at underscores (codeguards) - ch09's 2^{...} smudge, glossary margin overflow, ch08 orphaned listing line, ch13 command-line layout, three >10pt overfulls THE STRUCTURAL LESSON, encoded: the two worst clipping bugs had been announced as 80pt/73pt overfull warnings in every build log and ignored. check-book.sh now FAILS on any overfull box past 10pt — the machine was telling us; now it is allowed to stop us. 132 pages; publication-history and README counts synced; every fixed page re-rendered and verified by eye. Button: ALL GREEN (96 checks). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-08 17:11:09 +00:00
BUILDLOG="$(mktemp)"
./build.sh 2>&1 | tee "$BUILDLOG"
move 7: the book's button — check-book.sh + check-book.py The only source of 'ALL GREEN' for this repository. Rebuilds the PDF, then verifies 93 countable claims printed in the book against reality measured at run time: - source hygiene: inputs<->files both directions, contiguous ch01..ch14, every chapter (and the interlude) ends on its checkpoint, per-chapter exercise count == solution count with hand-typed numbering N.1..N.k - built PDF: >=100 pages, zero unresolved references, any page-count claim in prose must equal pdfinfo - internal congruence: chapter-count words in README/ch01 vs measured N ('spent twelve chapters' in ch13 is checked as a positional count, not grepped as stale — the spelling-vs-property lesson, applied to the checker itself); week-plan heading == max table row; the discussion-exercise roster parsed from prose == measured set; the SLH-DSA arithmetic recomputed from scratch (digest split 21/7/2, sig 7856, fixed 254, per-layer max 510 by brute force, worst 3824, checksum digit examples) and each value required present in ch13 - cross-repo congruence: 19 leaves derived by property (six-digit filenames + index fields — the entries/ glob counts 25); every nineteen/19 claim in prose parsed and compared; leaves 13-16 subjects + 44 certs; leaves 12/17 = 61; leaves 0-11 = 16; leaf 18 = 11 certs, apex cone kernel-3+5 oracles, ht cone f,h,t_l, four kernel-3-only plumbing certs, all cones exact; first dual-signed head at size 14; final head size == leaf count; ch13 parameter card == the const-generic arguments parsed out of the extracted Funs.lean; ch07's 71-digit Q == P25519.lean digit for digit Fails closed: a missing sibling repo is a FAILURE, not a skip; BOOK_LOCAL_ONLY=1 skips cross-repo loudly and never prints ALL GREEN. --selftest mutates copies of the sources seven ways (count drift, deleted solution, one Q digit, leaf-count drift, arithmetic drift, stray box after a checkpoint, plan/heading divergence) and requires each to be caught BY ITS OWN CHECK, plus an unmutated control that must pass. Full run: ALL GREEN (93 checks). Selftest: 8/8. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-08 12:16:30 +00:00
command -v pdfinfo >/dev/null && command -v pdftotext >/dev/null || {
echo "FAIL: poppler-utils (pdfinfo/pdftotext) required"; exit 1; }
print-quality pass: the book gets looked at, and the looking becomes a gate The operator caught what no check had ever tested: nobody had LOOKED at the rendered pages. A ten-inspector visual audit of all 129 pages (every page opened as an image) found 40 defects, including didactic correctness bugs invisible to the text layer: BAD, fixed: - ch03 printed WRONG Lean operators: \lean{P /\ Q} lost its backslash ('P / Q') and \lean{P \/ Q} lost the operator entirely ('P Q') — TeX ate them inside the non-verbatim macro. Now the unicode ∧/∨ the book uses everywhere else. - ch12: the doubling display overflowed its box border, slicing the math; stacked on two lines. - toolkit Card 6: the headroom-audit display was clipped by the page edge; now an align* stack. UGLY, fixed: - title page: the 'pyramid motif' at 5% white opacity on near-black rendered as smudge artifacts, plus a clipped ∀ glyph in the corner — redrawn with solid mixed colors (no transparency), glyph removed; the footer's mid-word paragraph gap was a \vspace landing inside horizontal mode; fixed with \par - ch06: both clock diagrams' wrap-around arrows ran counterclockwise, retracing over earlier arcs — target position expressed as 12 (one revolution) so the arc continues clockwise, landing on 0 (mod 12) and 1 (mod 11) correctly - ch04: two_mul'' printed as two_mul" (quote ligature) - one-line orphaned box fragments and stranded solution headings throughout: bigidea/tryit/pitfall/aha/checkpoint are now unbreakable (none exceeds half a page), worked boxes announce '(continued)' after a break, \solhead keeps four lines with \Needspace - --all/--receipt flags printed as one merged dash: \ddash macro - inline code no longer hyphen-breaks at underscores (codeguards) - ch09's 2^{...} smudge, glossary margin overflow, ch08 orphaned listing line, ch13 command-line layout, three >10pt overfulls THE STRUCTURAL LESSON, encoded: the two worst clipping bugs had been announced as 80pt/73pt overfull warnings in every build log and ignored. check-book.sh now FAILS on any overfull box past 10pt — the machine was telling us; now it is allowed to stop us. 132 pages; publication-history and README counts synced; every fixed page re-rendered and verified by eye. Button: ALL GREEN (96 checks). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-08 17:11:09 +00:00
# Print-quality gate: an overfull box past 10pt is text visibly leaving the
# margin or a border slicing through content. The 2026-08-08 visual audit
# found the two worst rendering defects in the book had been announced in
# every build log as 80pt/73pt overfull warnings — and ignored. Never again.
if grep -oE "Overfull \\\\hbox \([0-9]+\.[0-9]+pt" "$BUILDLOG" \
| grep -oE "[0-9]+\.[0-9]+" | awk '$1 > 10 {bad=1} END {exit bad}'; then
echo " ok no overfull box exceeds 10pt (print-quality gate)"
else
echo " FAIL overfull boxes past 10pt — text is leaving the page:"
grep -E "Overfull \\\\hbox \([0-9]{2,}" "$BUILDLOG" | sort -u | head -5
rm -f "$BUILDLOG"; exit 1
fi
rm -f "$BUILDLOG"
move 7: the book's button — check-book.sh + check-book.py The only source of 'ALL GREEN' for this repository. Rebuilds the PDF, then verifies 93 countable claims printed in the book against reality measured at run time: - source hygiene: inputs<->files both directions, contiguous ch01..ch14, every chapter (and the interlude) ends on its checkpoint, per-chapter exercise count == solution count with hand-typed numbering N.1..N.k - built PDF: >=100 pages, zero unresolved references, any page-count claim in prose must equal pdfinfo - internal congruence: chapter-count words in README/ch01 vs measured N ('spent twelve chapters' in ch13 is checked as a positional count, not grepped as stale — the spelling-vs-property lesson, applied to the checker itself); week-plan heading == max table row; the discussion-exercise roster parsed from prose == measured set; the SLH-DSA arithmetic recomputed from scratch (digest split 21/7/2, sig 7856, fixed 254, per-layer max 510 by brute force, worst 3824, checksum digit examples) and each value required present in ch13 - cross-repo congruence: 19 leaves derived by property (six-digit filenames + index fields — the entries/ glob counts 25); every nineteen/19 claim in prose parsed and compared; leaves 13-16 subjects + 44 certs; leaves 12/17 = 61; leaves 0-11 = 16; leaf 18 = 11 certs, apex cone kernel-3+5 oracles, ht cone f,h,t_l, four kernel-3-only plumbing certs, all cones exact; first dual-signed head at size 14; final head size == leaf count; ch13 parameter card == the const-generic arguments parsed out of the extracted Funs.lean; ch07's 71-digit Q == P25519.lean digit for digit Fails closed: a missing sibling repo is a FAILURE, not a skip; BOOK_LOCAL_ONLY=1 skips cross-repo loudly and never prints ALL GREEN. --selftest mutates copies of the sources seven ways (count drift, deleted solution, one Q digit, leaf-count drift, arithmetic drift, stray box after a checkpoint, plan/heading divergence) and requires each to be caught BY ITS OWN CHECK, plus an unmutated control that must pass. Full run: ALL GREEN (93 checks). Selftest: 8/8. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-08 12:16:30 +00:00
python3 "$HERE/check-book.py" "$HERE"
echo
if [ "${BOOK_LOCAL_ONLY:-0}" = "1" ]; then
echo "VERDICT: build green + local claims green; cross-repo NOT verified."
else
echo "ALL GREEN — the book builds and every countable claim matches"
echo "measured reality (sources, PDF, transparency log, extracted code)."
fi