Repository navigation
Conversation
Review at c479f49Verdict: Needs a maintainer decision on size, then fixes and a restack. This is layer 5 of the statement-review stack (#212 -> #213 -> #214 -> #215 -> #216 -> #75 -> #217 -> #218 -> #219). It adds Fixes before merge
Optional
Landing
Decision for the maintainer
This was a static review: no tests were run locally. CI at this head: all 9 checks pass, but on the stack's old base 8575a15. Posted by PR swarm: PR Swarm Lead |
c479f49 to
511757b
Compare
f02614b to
26b589c
Compare
511757b to
d9df55b
Compare
26b589c to
4efe159
Compare
d9df55b to
0fed56a
Compare
4efe159 to
00aa414
Compare
00aa414 to
b4d650a
Compare
0fed56a to
87f9b7c
Compare
b4d650a to
fa8a0d3
Compare
87f9b7c to
0108ce4
Compare
fa8a0d3 to
835e357
Compare
0108ce4 to
78bc493
Compare
835e357 to
d00cb14
Compare
78bc493 to
5a80f03
Compare
5a80f03 to
f6767bb
Compare
d00cb14 to
473a605
Compare
5a980e0 to
26832e6
Compare
26832e6 to
f8148cb
Compare
A read-back is an independent model's mathematical-English account of one blind skeleton packet. This adds the card that stores one in the vault (blueprint/readbacks/<article_id>/<encoded-declaration>.md: frontmatter, the packet in a Lean block, the testimony in a text block), a library API that builds, files, loads and judges cards, and the validator that decides whether testimony is safe to show. Testimony is plain text with TeX formulas between dollar signs: GitHub shows it verbatim, the site escaped, and only the formulas split_testimony finds are typeset. The validator refuses hidden, reordering, unassigned and overstacked characters, TeX outside a flat allowlist with no spacing or phantom commands, and testimony over 32 KiB or 500 lines. A write takes the card directory's flock and replaces a card only under compare-and-swap, through a staging file an interruption removes. Part 5 of the split of #75.
f8148cb to
65d1319
Compare
A read-back is an independent model's mathematical-English account of one blind skeleton packet, written without the article or the source. This PR adds the card that stores a read-back in the vault, the library API that files and loads cards, and the validator that decides whether testimony is safe to show. Testimony is plain text with TeX formulas between dollar signs; it is refused if it could hide or reorder what it says, or use TeX outside a flat allowlist. There is no command yet: #284 adds
review recordandreview checkon top of this API.What it adds
autoform_cli/readback.py, new. A card lives atblueprint/readbacks/<article_id>/<encoded-declaration>.md, schemaautoform-readback/v1: frontmatter (article_id, declaration, skeleton and packet hashes, model label), the exact packet in aleanblock under## Skeleton, then the testimony in atextblock under## Read-back. Each block is fenced one backtick longer than its longest run (_fence), so nothing inside can close it.prepare_readbackchecks everything and builds aPreparedReadbackfrom a declaration name,skeleton_hash,packet_hashandpacket_text(which must hash topacket_hash) without touching the filesystem;publish_readbackwrites it.load_readbacks,readback_for,readback_keys,readback_pathandReadback.validate(expected)load and judge cards;split_testimonyis the one reading of where formulas are.load_readbacks,_card_files,_read_card_file):os.walkdoes not enter linked directories, each card is skipped if it is a link and openedO_NOFOLLOW|O_NONBLOCK, and at most 4 MiB plus one byte is read. A FIFO, directory, unreadable, non-UTF-8 or oversized file at a card path is an invalid card, not skipped. A card is attributed to the declaration its path names; a body that is not one skeleton block then one read-back block, or bytes not in canonical form, make it invalid. An unlistable directory stops loading with an error naming it.publish_readback,_open_card_directory,_publish_card):mkdireach ofreadbacks/andreadbacks/<id>, refusing a symlink before the next; open the directoryO_DIRECTORY|O_NOFOLLOW;flockit (10 s timeout); hash the current card (_card_hash_at) and apply compare-and-swap (_card_conflict); stage.autoform-readback-*.tmpwithO_EXCL,fsync, oneos.replace;LOCK_UN, then close. Identical content is not rewritten, so it files even in a read-only directory._require_publication_supportrefuses before anything is created wherefcntl,O_DIRECTORYorO_NOFOLLOWis missing (Windows); cards still load there._testimony_errors,_formula_errors): 32 KiB and 500 lines; invisible, reordering and unassigned characters, overstacked and baseless combining marks; an unclosed dollar sign ("write $"); TeX outside the flat frozenset_TESTIMONY_TEX, refused by name with a rewrite where_TEX_INSTEADhas one (no spacing,\not,\phantom,\color, macros,arrayor equation environments); structural rules a flat list cannot see: a bracket right after\begin{aligned}/\begin{gathered},[or*right after\\,&and\\only inside an environment, balanced braces,\left/\rightand\begin/\end, depth 16, 2048 UTF-16 units per formula, no TeX comments, no characters MathJax 3.2.2 cannot set, no combining marks in a formula. At least one letter or digit must show. No Markdown is read; text is shown as typed.skeleton.py:declaration_filename(name, *, suffix=".lean")replaces the private_packet_filename(same.leannames; refuses an empty name or unsafe suffix);evidence_hash_ofis exported.render.pyskipsreadbacks/, so cards never become pages, and a link to a card keeps only its text.mathjax.py's version comment names the testimony allowlist. Docs:skills/human-review/references/readback.md(the read-back guide, kept in step with the validator by a test), a card section inautoform_cli/README.md, andreadback-faithfulness.mdnow asks the auditor for plain text with TeX between dollar signs instead of Markdown. The blueprint.gitignoretemplate ignores staging files.What changed in this revision
Size: +2,947/-8 in 13 files before, +2,984/-9 in 14 files now.
render.py's imports: the rebuild addedshown_as_typedto thepublishableimport and droppedfrom .snapshot import BlueprintSnapshot, sofrom .readback import READBACKS_DIRnow followsfrom .publishable import publishable_article, shown_as_typed.mkdocs build --strictfinds nothing missing. The site leaves read-back cards out as well, but they were not in that set, so an article linking to its card published a dangling link and failed the strict build._publicationnow puts every file underreadbacks/inleft_out, andtest_a_link_to_a_read_back_card_keeps_only_its_text(tests/test_site_math.py) fails without it.markdown.blueprint_root.load_readbacksandprepare_readbackstill usedPath.resolve, so for a blueprint behind a link the system follows but will not let anyone read,review record(Add statement-review commands #284) failed with a permission error on Python 3.10 to 3.12 and filed the card under the link's spelling on 3.13. Both now useblueprint_root, andtest_cards_file_and_load_in_a_blueprint_behind_a_link_that_cannot_be_readfails without it on 3.10 and 3.13.BlueprintSnapshot,graph.article_text,formula_fence,FormulaExtension, the tuplepublishable_articlereturns). Thereadbacks/skip in_publicationis still needed: the captured files it walks, now adict[Path, bytes]rather than aBlueprintSnapshot, still includereadbacks/, so without the skip a card's.mdwould become a page.skeleton:hash is the declaration's statement hash (Extract Lean skeletons one probe per root module #213), so a proof edit leaves the card valid:Readback.validatecomparesstatement_hash, the module docstring says so,tests/skeleton_fixtures.pybuilds declarations with empty statement fields, andtest_readbacks_are_filed_per_declaration_and_validatechecks that a declaration that stops usingpropextkeeps its card valid. This came with the previous revision's restack on the reworked Extract Lean skeletons one probe per root module #213 (since merged) and is unchanged.Review findings it answers
flockon the card directory in place of a lock file a crash could strand (205fc84), one rename under it so no Autoform write lands between compare and replace (e68a3c1),LOCK_UNbefore close so a forked child cannot keep the lock (181d83d), no-follow card loading (2b0adf6, now a link-skipping walk plusO_NOFOLLOWleaf opens). 181d83d's post-lock re-walk is dropped: a directory moved while a write waits on the lock is not detected, and the README says so."is refused before JSON decoding, so nested[give an invalid card, not a RecursionError (6dc8f6a, de011d8).split_testimony, which the site will use; GitHub pairs nothing inside a text block. Replaces e220eab's paired-dollar rule.found Nonewhen a named card is gone (ad2f9a8).\(in code, list markers in the nesting count: no Markdown) and ba25fae (cmarkgfm on Intel Macs: dependency gone).Until the next layers land
review record(builds from the packet and manifest hashes, runs no Lean) andreview checkarrive in Add statement-review commands #284; the site shows cards from Show statement review on the site #217.$x^^y$) will show MathJax's error in its place on the site; GitHub shows its source.Validation
Run 39103604181 on
65d13198passed every job:Windows inspection, subprocess, and publication hardening,real Lean (fixture toolchain),real Lean skeleton suite (fixture toolchain),real REPL (fixture toolchain),test (3.10),test (3.13).tests/test_readback.py: 13 tests, 35 cases: filing, path containment, a 21-row hand-edit damage table, frontmatter round trip, crash and replace behaviour.tests/test_readback_publication.py: 27 tests, 52 cases: lock with a blocking thread rival, forked child, compare-and-swap table, FIFO and directory under a no-block guard, links, a blueprint behind a link that cannot be read, unlistable directories, the interrupt tables, the Windows-like loader check (O_NOFOLLOWremoved, link still skipped), platform refusal.tests/test_readback_testimony.py: 7 tests, 86 cases: dollar pairing, accept and refuse tables, writer refusal, message naming, five worst cases timed at the size limit, guide sync.tests/test_site_math.py: a link to a read-back card keeps only its text, and no card is published.tests/test_scaffold.py: the staging-file ignore;tests/skeleton_fixtures.py: shared skeleton fixture.Stack