mirror of
https://github.com/saymrwulf/verifying-crypto-with-lean.git
synced 2026-09-03 19:53:45 +00:00
publication history: dated edition record in the front matter, machine-bound
The current-edition line (fourteen chapters, 129 pages, published 2026-08-08) is now a live claim: check-book.sh verifies its chapter and page counts against the built book AND verifies the COMMITTED main.pdf carries the line — so the PDF a GitHub visitor downloads can no longer silently lag the sources. Historical lines are exempt from the whole-book claim scans (BEGIN/END PUBHIST markers). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
311f60d4d0
commit
e2660e8e71
4 changed files with 81 additions and 6 deletions
|
|
@ -24,7 +24,9 @@ Lean 4 against models extracted from the actual Rust sources:
|
|||
|
||||
**[`main.pdf`](main.pdf)** — fourteen chapters + interlude + three
|
||||
appendices, full color, built with LaTeX/TikZ from the sources in this
|
||||
repo (`./build.sh`, tectonic, no root needed). No prior Lean or formal
|
||||
repo (`./build.sh`, tectonic, no root needed). **Second edition,
|
||||
published August 8, 2026** (129 pages; the full publication history is
|
||||
printed in the book's front matter). No prior Lean or formal
|
||||
methods assumed; high-school algebra and a little programming suffice.
|
||||
|
||||
1. **Why Verify?** — the carry bug testing cannot find
|
||||
|
|
|
|||
|
|
@ -69,6 +69,13 @@ def main():
|
|||
readme = read(os.path.join(book, "README.md"))
|
||||
chdir = os.path.join(book, "chapters")
|
||||
|
||||
# the publication-history block: its CURRENT-edition line is bound to
|
||||
# measurements below; its historical lines are frozen and exempt from
|
||||
# the whole-book claim scans, so strip the span for scanning purposes
|
||||
mhist = re.search(r"% BEGIN PUBHIST.*?% END PUBHIST", main_tex, re.S)
|
||||
pubhist = mhist.group(0) if mhist else ""
|
||||
main_scan = main_tex.replace(pubhist, "")
|
||||
|
||||
# ── Phase 0: source hygiene ────────────────────────────────────────────
|
||||
print("=== Phase 0: source hygiene ===")
|
||||
|
||||
|
|
@ -128,12 +135,44 @@ def main():
|
|||
bad = [l for l in txt.splitlines() if "??" in l]
|
||||
check(not bad, "no unresolved references ('??') in rendered PDF",
|
||||
bad[0][:60] if bad else "clean")
|
||||
page_claims = re.findall(r"(\d{2,4}) pages", readme + main_tex)
|
||||
page_claims = re.findall(r"(\d{2,4}) pages", readme + main_scan)
|
||||
if page_claims:
|
||||
for pc in page_claims:
|
||||
check(int(pc) == pages, f"page-count claim {pc} == built {pages}")
|
||||
else:
|
||||
ok("no page-count claim in prose (nothing to bind)")
|
||||
ok("no page-count claim outside the history block (nothing to bind)")
|
||||
|
||||
# publication history: the current-edition line is a live claim
|
||||
med = re.search(r"\\textbf\{(\w+) edition\} --- published "
|
||||
r"([A-Za-z]+ \d+, \d{4}): (\w+)\s*\n?chapters, "
|
||||
r"(\d+) pages", pubhist)
|
||||
if not (pubhist and med):
|
||||
fail("publication-history block with parseable current-edition line",
|
||||
"missing" if not pubhist else "line not parseable")
|
||||
else:
|
||||
check(WORDS.get(med.group(3)) == n_ch,
|
||||
"current edition's chapter count == measured",
|
||||
f"{med.group(3)} vs {n_ch}")
|
||||
check(int(med.group(4)) == pages,
|
||||
"current edition's page count == built PDF",
|
||||
f"{med.group(4)} vs {pages}")
|
||||
# committed PDF must carry the current-edition line: this is what
|
||||
# a GitHub visitor downloads, and it must not lag the sources
|
||||
if os.path.isdir(os.path.join(book, ".git")):
|
||||
blob = subprocess.run(["git", "-C", book, "show", "HEAD:main.pdf"],
|
||||
capture_output=True)
|
||||
tmp = os.path.join(book, ".committed-main.pdf.tmp")
|
||||
with open(tmp, "wb") as fh:
|
||||
fh.write(blob.stdout)
|
||||
ctxt = subprocess.run(["pdftotext", tmp, "-"],
|
||||
capture_output=True, text=True).stdout
|
||||
os.unlink(tmp)
|
||||
check(f"published {med.group(2)}" in ctxt,
|
||||
"COMMITTED main.pdf carries the current-edition line "
|
||||
"(the PDF a visitor downloads is not stale)",
|
||||
med.group(2))
|
||||
else:
|
||||
ok("committed-PDF binding skipped (no git repo here)")
|
||||
|
||||
# ── Phase 2: internal countable claims ─────────────────────────────────
|
||||
print("=== Phase 2: internal countable claims ===")
|
||||
|
|
@ -151,9 +190,10 @@ def main():
|
|||
# stale-total scan is scoped to the front matter, where whole-book totals
|
||||
# live; inside a chapter, "N chapters" is a positional count checked next
|
||||
for stale in ("twelve chapters", "thirteen chapters"):
|
||||
hits = [f for f in ("main.tex", "README.md")
|
||||
if stale in read(os.path.join(book, f))]
|
||||
check(not hits, f"no stale '{stale}' in front matter", ",".join(hits) or "clean")
|
||||
hits = [name for name, txt in (("main.tex", main_scan), ("README.md", readme))
|
||||
if stale in txt]
|
||||
check(not hits, f"no stale '{stale}' in front matter (history block exempt)",
|
||||
",".join(hits) or "clean")
|
||||
# any "spent N chapters" phrase inside chapter chNN counts its predecessors
|
||||
for cf in chapter_files:
|
||||
num = int(re.search(r"ch(\d\d)-", cf).group(1))
|
||||
|
|
|
|||
BIN
main.pdf
BIN
main.pdf
Binary file not shown.
33
main.tex
33
main.tex
|
|
@ -37,6 +37,39 @@ claim it makes about a proof, a proof assistant has checked.\par}
|
|||
\restoregeometry
|
||||
\pagecolor{paper}\color{ink}
|
||||
|
||||
% BEGIN PUBHIST ==================== publication history =====================
|
||||
% The current-edition line is machine-checked by check-book.sh: its chapter
|
||||
% count and page count must match the built book, and the committed PDF must
|
||||
% contain it. Historical lines are frozen and exempt from the claim checks.
|
||||
\thispagestyle{empty}
|
||||
\vspace*{2cm}
|
||||
{\small
|
||||
\noindent\textbf{Second edition} --- published August 8, 2026: fourteen
|
||||
chapters, 129 pages.
|
||||
|
||||
\medskip
|
||||
\noindent\emph{Publication history}
|
||||
\begin{itemize}[leftmargin=1.4em]
|
||||
\item \textbf{First edition}, July 3, 2026 --- twelve chapters and the
|
||||
Interlude; expanded the same day with the pen-and-paper program and
|
||||
in-book solution pathways (53 to 106 pages).
|
||||
\item July 28, 2026 --- the Attestation Protocol added as a thirteenth
|
||||
chapter.
|
||||
\item \textbf{Second edition}, August 8, 2026 --- full didactic overhaul
|
||||
(seven moves, from a seven-reader audit); new Chapter~13, \emph{The
|
||||
Second Summit} (SLH-DSA, post-quantum); the Attestation Protocol becomes
|
||||
the fourteen-chapter book's single finale; \code{check-book.sh} added ---
|
||||
the script that verifies every countable claim in this book, including
|
||||
the line at the top of this page, against measured reality.
|
||||
\end{itemize}
|
||||
|
||||
\medskip
|
||||
\noindent The complete revision record is the git history of
|
||||
\code{github.com/saymrwulf/verifying-crypto-with-lean}.
|
||||
}
|
||||
\clearpage
|
||||
% END PUBHIST ================================================================
|
||||
|
||||
% ===================== HOW TO READ =====================
|
||||
\chapter*{How to read this book}
|
||||
\markboth{How to read this book}{}
|
||||
|
|
|
|||
Loading…
Reference in a new issue