Repository navigation
#263 PF-24: runtime bounds a law proof cites (split_exact, UTF-8 decode, UInt32 checked_add) - #296
Conversation
…f_24 (#263, R3 skeleton) The row states three runtime bounds a language-1.2 law proof cites: split_exact_fits, utf8_decode_length and checked_add_fits. The fold-laws example gains the module Guards, which mirrors prism-code's three request guards (too-many-lines, line-overflow, response too-large) and proves each branch unreachable by law. Before the implementation the case fails at its first assertion (`LexLeanLaws.splitExact_fits` is not a declaration of the laws module), and `lexlean check` of the example refuses the mirror at the citation: error[LLT4001]: phase link: `split_exact_fits` is not a registered law --> src/Guards.lex.tex:6:1 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LexLeanRuntime.Laws states three bounds of the runtime, registered in language/runtime-1.2/laws.toml as laws a language-1.2 `law` proof applies: - split_exact_fits (s d : String) (m : UInt32) (n : Nat), premises equal d "" = false and n < toNat m: length (utf8_encode s) <= n -> split_exact s d m is some. - utf8_decode_length (b : Bytes) (s : String) (n : Nat): utf8_decode b = some s -> length b <= n -> length (utf8_encode s) <= n. - checked_add_fits (a b n : UInt32), premise toNat n + toNat b < 2^32: a <= n -> checked_add a b is some. They are proved from splitOnAux_length_le: the loop of String.splitOn emits at most the string's UTF-8 byte length plus one pieces. The authored Lean was exported into the native module by the laws oracle of b58f195 (its base reproduces the committed source byte for byte), printed in the notation with lexlean::sdk::to_notation; the regenerated environment equals the export in 150 of 150 declarations (tests/runtime-library/LAWS.md). Lean does not expose the bodies of String.splitOn and its loop, so the decoder of core module 2 imports Init.Data.String.Legacy in full (LEAN_CORE_V2_IMPORTS, SPEC §17.10); the native module still imports only Init and the earlier runtime modules (RT-01). The fold-laws example's Guards module verifies under Lean 4.32.1: it proves prism-code's too-many-lines, line-overflow and response too-large branches unreachable by law. PF-22 keeps the fold-law rows within Quot.sound and propext and leaves the bounds, which observe Classical.choice through the split and the decoder, to PF-24. SPEC §16 and §17.12 document the bounds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…generated by the writers laws.toml, Laws.lex.tex and the decoder header of core module 2 are in the language-1.2 compiler semantics, so its ID moves from 5262e5b4... to 9fdf4d30...; languages 1.0 and 1.1 are unchanged. The ID was substituted in the 503 files that carried it, the fold-laws lock rewritten for its new entrypoint, and every record rewritten by its own writer: check-golden, check-calculus, check-production-export and check-fixtures with --write, then verify-examples --write for every example but uor-atlas (language 1.0, whose identity does not move); 18 projects verified. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A law weakened by one, an unregistered law, the piece-count lemma without its plus one, and each guard claiming one more than its law gives; each refused, and the reverted tree passes PF-20..PF-24 and RT-01..RT-04. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…runtime-bounds CHANGELOG and VERIFICATION keep both sides, the line first. README and the PF-24 entry count 445 registered IDs (AU-14 landed on the line). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e-bounds CHANGELOG and VERIFICATION keep both sides, the line first. README takes the line, counts 448 registered IDs (RP-17, PC-01 and PC-02 landed) and ends the PF row at PF-24. SPEC.md and spec/lexlean.lock take the line and are regenerated in the next commit. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…rated records after merging #289 The language-1.2 compiler-semantics ID of this branch (9fdf4d30) differs from the line's, so spec/lexlean.lock, examples/performance-corpus/lexlean.lock and expected/, the golden, fixtures, calculus and production export are rewritten by their writers; verify-examples --write ran without the Atlas. SPEC.md is the projection of spec/src. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Merged Commits on top of
Numbers: PF-24 is still free on the line, so nothing is renumbered. The register is 448 (AU-14, RP-17, PC-01 and PC-02 landed). README's count says 448, its PF row ends at PF-24, and this PR's CHANGELOG entry says Register 448. Run locally, all green on the final tree: Not verified: the Atlas ( |
|
Merged into |
…ail-call The line took PF-24 (register 448); RB-21 keeps its number, the register is 449. README, SPEC.md and CONFORMANCE.md state 449, the CHANGELOG bullet ends "Register 449". CHANGELOG.md merged with both sides, the line's first. #296 moved the language-1.2 compiler-semantics ID, and this change's renderer digest moves it again, so every lock, calculus record, fixture expectation, verification record, golden oracle and production export is regenerated by the writers from the merged tree; the Atlas is not regenerated. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Resolves #263 (draft). Targets
release/v0.5.The three lemmas, as shipped
They are theorems of the native runtime module
LexLeanRuntime.Laws, registered inlanguage/runtime-1.2/laws.tomlas laws a language-1.2lawproof applies by name. No raw Lean is involved (§16.12). Each conclusion is an implication from a bound on the input. Each closed side condition is a premise that a prior theorem discharges.split_exact_fitsLexLeanLaws.splitExact_fitsClassical.choice, Quot.sound, propextutf8_decode_lengthLexLeanLaws.utf8Decode_lengthClassical.choice, Quot.sound, propextchecked_add_fitsLexLeanLaws.checkedAdd_fitsQuot.sound, propextThe first two observe
Classical.choicebecause the runtime definitions ofsplit_exactandutf8_decodepin it.The piece count is proved from
splitOnAux_length_le: the loop ofString.splitOnemits at most the string's UTF-8 byte length plus one pieces. The proof is a recursion on the loop's own termination measure.Reading of the issue's second lemma: the issue says "the UTF-8 byte length is bounded by the encoded length". It ships as "a string decoded from
bhas a UTF-8 byte length of at mostlength b". This is the step from the request's bytes to the decoded text that both prism-code guards need.The mirror module
examples/fold-laws/src/Guards.lex.texmirrors prism-code's three guards and proves each branch unreachable. Each proof is one law application:request_text_fitsgives the same bound at 4096. It is the step from an admitted request to the text thattoo_many_lines_unreachabletakes.lexlean verify src/Guards.lex.texpasses under Lean 4.32.1:verified 1 module; attestation cef84e9408639d951f225171ead32845ab926e74cb2c8edbde53fb8ed118bfd3.Rows
PF-24(new,proofs, §16, §17.12): the runtime bounds, the mirror, and both refusals. Register 443 → 444. README'sPF-01..PF-24row and its count are updated.PF-22(case only, statement unchanged): the fold-law rows stay withinQuot.soundandpropext. The bound rows are pinned byPF-24instead.Plants
They are recorded with their real output in VERIFICATION.md.
split_exact_fitsweakened by one (premisen + 1 < m.toNat), re-exported and built into the compilerlexlean verifyrefuses the mirror:LLV7002 … Application type mismatch: The argument lines_fit … but is expected to have type 4096 + 1 < UInt32.toNat 4097atGuards.lex.tex:52split_exact_bounderror[LLT4001]: phase link: \split_exact_bound` is not a registered law`+ 1omega could not prove the goal, then a type mismatch at≤ s.utf8ByteSizeLLV7002type mismatches, atGuards.lex.tex:52,:74and:96.conformance_pf_24runs the same plant.One design point for afflom
Lean's module system does not expose the bodies of
String.splitOnand its loop. A generated native module therefore could not unfold the split. The regeneratedLawswas refused atString.splitOnAux.eq_defwith "unknown constant", and atsplitOn_length_lebecause the kernel cannot unfoldString.splitOn.This PR adds one line to the decoder of core module 2 (
LEAN_CORE_V2_IMPORTS). It importsInit.Data.String.Legacyin full, next toLean.Meta.Constructions.SparseCasesOn, and SPEC §17.10 says so. The native module still imports onlyInitand the earlier runtime modules, so RT-01 holds.The alternative is a runtime
split_exactover an exposed split. That would change the runtime and its Rust correspondence, so I did not take it. Please say if you want it the other way.A related limit: semantic proofs have no
have. A chain such as "admitted request, then decoded text, then pieces" is therefore two theorems, not one.Identity
laws.toml,Laws.lex.tex, and the decoder header are part of the language-1.2 compiler semantics. The 1.2 compiler-semantics ID moves from5262e5b4…to9fdf4d30…. Languages 1.0 and 1.1 are unchanged. Locks, goldens, calculus, production export, fixtures, and verification records were regenerated by the repository's writers, in a separate commit. Every sibling PR onrelease/v0.5that moves the ID will conflict on those records. The fix is to rerun the writers after merging.Run locally
cargo xtask validate-modelandvalidate-spec-links: 444 rows, clean (at the R3 commit).lexlean verify src/Guards.lex.texon the fold-laws example: verified (attestation above).check-golden,check-calculus,check-production-export,check-fixtures(each--write) andverify-examples --writewithout uor-atlas: 18 projects verified.conformance_pf_20..pf_24andconformance_rt_01..rt_04: 9 passed, on the merged head.validate-model(444 ids, audits clean) andvalidate-spec-linkson the merged head.just vv(workspace clippy and tests,bdd,repro,deny) and the uor-atlas verify. A draft runs only therestleg in CI.systemd-run --userscope capped at 10G (/user.slice/user-1000.slice/user@1000.service/app.slice/run-….scope).🤖 Generated with Claude Code