Skip to content

feat(proofs): program equalities over all inputs: integer order, linear_arithmetic over the runtime, fold laws, and the law form (PF-20..PF-23, #117) - #158

Merged
afflom merged 12 commits into
mainfrom
claude/dazzling-cerf-cgz94p
Oct 16, 2026
Merged

afflom merged 12 commits into
mainfrom
claude/dazzling-cerf-cgz94p

Conversation

@afflom

@afflom afflom commented Oct 16, 2026

Copy link
Copy Markdown
Member

Closes #117 (plan item L3.4 of #106).

The probe (first step of the issue)

Re-run on main at 32afe5da with Lean 4.32.1 (recorded in tests/runtime-library/LAWS.md):

  • Integer kernel (clampStep monotonicity, written with less_than) under linear_arithmetic{definitions: [clampStep]} fails with omega … No usable constraints found. The script unfolds none of less_than, quotient or negate, and nothing splits the clamp's ifs. This confirms the three gaps from the earlier probe on the issue.
  • Two folds (doubledTotal xs = total xs + total xs): omega sees two unrelated listFold atoms. The missing lemma is a normal form for additive folds: a fold whose step adds k x equals initial + Σ k, and Σ is linear in k. With both sides in that form, the equality is linear over one atom.

What changes

  1. Integer order (PF-20). Under language 1.2, <= and < take two operands of one integer type (Nat, Int, or one fixed-width type) and lower to Lean's order on that type. Language 1.1 keeps Nat only and is byte-identical.

  2. linear_arithmetic reads the runtime (PF-21). The script is still one fixed script (SPEC.md §17.12). Its simplifier pass now covers:

    • the runtime bridges for less_than on every integer key type, equal, negate, quotient and remainder (a zero divisor becomes an if; truncating division by a positive or negative literal becomes Euclidean division with a sign case);
    • the registered rewrite set of the laws module;
    • fixed-width order and equality on mathematical values, with literals evaluated first.

    A second pass reads every remaining fixed-width value as the bounded natural number of its bits, so omega knows its range. Then all_goals (repeat' split) splits every if/match left in the goal, and all_goals omega decides each case.

  3. The fold laws as LexLean source (PF-22). LexLeanRuntime.Laws (namespace LexLeanLaws) is the fifth native runtime module, importing Portable and Collections. It contains:

    • sumNat/sumInt;
    • the bridges;
    • the additive-fold normal form for list, set and map folds (a map's fold is the fold of its entries);
    • linearity of sums, and constant contributions as length;
    • invariance of sums under permutation (sumNat_perm, sumInt_perm), append and reverse, plus the cons- and snoc-folds;
    • fusion, the fold of a pair, and the fold of an append.

    Every row pins its exact axioms, and none uses Classical.choice. The registry language/runtime-1.2/laws.toml names the rewrite set and the applicable laws; the runtime build refuses a registry that names anything the module lacks.

  4. The law proof form (PF-23). law{name, type_arguments, arguments, premises} applies a registered law (list_fold_fusion, list_fold_pair, list_fold_append). Linking checks the counts, the types and that each premise names a prior theorem; Lean checks the statement. It lowers to exact @L ….

  5. Corpus. examples/fold-laws covers integer kernels (clamped requantization monotone and in range for every Int, truncating division by ±7, UInt8/Int8 order and equality) and fold equalities over lists, sets and maps (doubling, counting, weighting, append both ways, reverse, debits against credits, a map's keys and values). It includes a one-pass statistics fold by list_fold_pair and a fused parity fold by list_fold_fusion; decide appears only on closed instances.

Provenance of the laws module

Commit b58f1952 is an oracle checkpoint: the authored Laws.lean plus the runtime migration's exporter narrowed to Laws. The next commit removes it, as #144's migration did, and RT-01 now also requires laws-oracle to be absent. Running run.sh from the checkpoint gives:

  • the export printed in the notation is the committed Laws.lex.tex, byte for byte;
  • the regenerated environment matches in 118 of 119 rows, and the remaining row (a sparse casesOn) is equal up to binder names.

Identity

semantic_ir 11, lean_backend 18, proof_lowering 3. Every language-1.2 lock, golden, fixture expectation, calculus package, production export and verified record was regenerated by the repository's writers. The existing linear_arithmetic proofs of models, recursion, reasoning, production(-coverage) and compiler all verify under the extended script. Languages 1.0 and 1.1, Atlas included, are byte-identical to main. New reserved names (BitVec, LexLeanLaws, beq_iff_eq, decide_eq_true_eq, decide_eq_false_iff_not, reduceIte) keep a module or binder from capturing what the script writes. The register has 391 IDs after merging main; there is no new diagnostic code.

Evidence

  • R3 order in the history: register rows, scenarios and failing tests (cb02f8d3), then the checkpoint, then the implementation.
  • Local runs on Linux x86-64 with pinned Lean:
    • fmt, validate-model, validate-spec-links, clippy, test, features, check-test-inventory, check-golden and check-reproducibility passed;
    • verify-examples --write verified every example except Atlas;
    • cargo test -p repo-conformance: 384 cases passed and 6 failed on the first run; all 6 now pass, and the runtime cases pass against the merge of main.
  • Planted defects for each case are in VERIFICATION.md ("the fold laws can fail").

Full just vv runs in CI.

🤖 Generated with Claude Code

https://claude.ai/code/session_018risLc2kcmeqW2hL5pcQNs


Generated by Claude Code

claude added 12 commits October 16, 2026 14:34
R3, before any implementation: four `proofs` rows (SPEC.md §31 and
model/ids.toml, 390 IDs), one scenario each in features/suites/proofs.feature,
and `conformance_pf_20`..`conformance_pf_23`, with the corpus they quantify
over, `examples/fold-laws` (integer kernels, fold equalities over lists,
sets, and maps, and law applications). PF-19's case now pins the extended
fixed script; RT-01 lists five runtime modules and requires the laws oracle
absent. The cases fail: no order over Int, no laws module, no `law` form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018risLc2kcmeqW2hL5pcQNs
`LexLeanRuntime.Laws` (namespace `LexLeanLaws`) joins the runtime project:
sums of a function over a list, the bridges from the runtime's comparison,
division, and collection operations to propositions, the normal form of
additive folds, linearity and permutation invariance of sums, fusion, the
fold of a pair, and the fold of an append. Every row pins its exact axioms,
none depends on Classical.choice.

This commit is the export checkpoint: it carries the one-time oracle,
tests/runtime-library/laws-oracle/ (the authored Lean and the migration's
exporter narrowed to `Laws`), which the next commit removes. The record is
tests/runtime-library/LAWS.md: the export printed in the notation is the
committed source byte for byte, and the regenerated environment equals it in
118 of 119 rows, the last equal up to binder names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018risLc2kcmeqW2hL5pcQNs
…e law form

Language 1.2 types `le`/`lt` over Nat, Int, and every fixed-width type.
`linear_arithmetic` lowers to the extended fixed script: the runtime bridges
and the registered rewrite set of `LexLeanRuntime.Laws`, fixed-width order
and equality on mathematical values with bit-level bounds, a split of every
`if` and `match` left in the goal, then omega. The closed `law` proof applies
a registered law (`language/runtime-1.2/laws.toml`) with linking checks; the
runtime build refuses a registry naming what the module lacks. A module with
either proof imports the laws module. The one-time laws oracle is removed.

semantic_ir 11, lean_backend 18, proof_lowering 3: every language-1.2 lock,
golden, calculus package, and production export is regenerated by the
repository's writers (fixtures and verified records follow).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018risLc2kcmeqW2hL5pcQNs
…-1.2 identity

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018risLc2kcmeqW2hL5pcQNs
…-23 fragments that quote them

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018risLc2kcmeqW2hL5pcQNs
…cal writer had set it aside

The language-1.0 Atlas is untouched by this change; the tree equals main's
byte for byte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018risLc2kcmeqW2hL5pcQNs
…guage-1.2 projects

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018risLc2kcmeqW2hL5pcQNs
…s' fragments

A module or binder named like a namespace or lemma the extended
linear_arithmetic script writes unqualified (BitVec, LexLeanLaws,
beq_iff_eq, decide_eq_true_eq, decide_eq_false_iff_not, reduceIte) would
capture it, so each is a backend bare name, and LexLeanLaws a shipped root
(SP-09). RP-07 counts 390 rows; SM-16's downstream match covers the law
form; the PF cases quote the rendered Lean exactly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018risLc2kcmeqW2hL5pcQNs
…he PF-21 case

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018risLc2kcmeqW2hL5pcQNs
…cgz94p

# Conflicts:
#	CHANGELOG.md
#	README.md
#	SPEC.md
#	crates/conformance/src/cases/repository.rs
#	xtask/src/spec_links.rs

afflom commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

atlas (cert4-replay) (job 117145703530) failed before any verification ran. Its actions/download-artifact step reported Unable to download artifact(s): Failed to ListArtifacts: Unable to make request: ECONNRESET. The next step, ci-parts/atlas-xtask/xtask ci-summary, then exited 126 (Permission denied) because the download had not completed.

This is the runner's connection to the artifact service, not this PR: the job never reached a test body, and this PR does not change the Atlas or the workflow. The other Atlas parts downloaded the same artifacts successfully.

Re-running the failed jobs from this session is refused (403 Resource not accessible by integration), so it needs one re-run from someone with Actions write access. I'm keeping the PR watched until it is green.


Generated by Claude Code

afflom commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

Run 38941418389 on aa58c1d7 has finished: 21 of 22 checks are green, including the 14 Atlas jobs but atlas (join). The one red check is atlas (cert4-replay), which died at "Take the gate's executable and the shards before this one from the run" with Failed to ListArtifacts: ECONNRESET, before any shard ran. atlas (join) was skipped because it needs it, so nothing about this head has been judged by a test.

The failed job needs a re-run, and neither this session nor the one that wrote the PR can do it: rerun-failed-jobs returns 403 (Resource not accessible by integration) for both of us. @humuhumu33 or @afflom, could one of you with Actions access press "Re-run failed jobs" on the run? That is the one allowed re-run (a failure before any test body). Nothing else on this head needs to change, and it still contains main 80331cb4.

If nobody has re-run it by 21:15Z, I will instead push a small, real change to this branch (RT-01 and RT-04 do not yet list LexLeanLaws, the fifth runtime namespace this PR adds, so a module or a source literal under it would escape both gates) and take the fresh run that push starts. That costs about 500 runner-minutes against about 60 for the re-run, so I would rather not.


Generated by Claude Code

@humuhumu33

Copy link
Copy Markdown
Contributor

The atlas (cert4-replay) failure was infrastructure, not the change: its first step could not download the run's artifacts (Failed to ListArtifacts: Unable to make request: ECONNRESET, exit 126), so no verification ran. I re-ran the run's failed jobs.


Generated by Claude Code

afflom commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

Maintainer review: approved at aa58c1d7.

Checked against #117's acceptance and the repository rules, on the head that ran:

  • CI. Run 38941418389, attempt 2 (hh re-ran the one job that died at artifact download): all 22 checks green, including the 14 Atlas jobs and atlas (join). The head contains main 80331cb4.
  • [0.5.0] Lemmas for universal equalities over list folds #117, first step. The probe is recorded before the change, in tests/runtime-library/LAWS.md: the integer kernel fails under linear_arithmetic with No usable constraints found, and the two folds need a normal form for additive folds. The missing lemma is named, not assumed.
  • [0.5.0] Lemmas for universal equalities over list folds #117, accepted when. examples/fold-laws states equalities over lists, sets and maps and integer kernels for all inputs. decide appears only on the two closed instances (doubled_total_closed, requantize_closed).
  • R3. The register rows, scenarios and failing tests come first (cb02f8d3), then the oracle checkpoint, then the implementation.
  • R8 / provenance. Laws.lean is an oracle checkpoint removed by the next commit, as feat(#90): the runtime of generated Lean is native modules (RT-01..RT-04) #144's migration was, and RT-01 now requires its absence. The exported notation is byte-identical to the committed Laws.lex.tex.
  • R9 / R10. Every row of the laws module pins its exact axioms and none uses Classical.choice. The language-1.2 identity moved once (semantic_ir 11, lean_backend 18, proof_lowering 3) and every record was regenerated by the repository's writers. Languages 1.0 and 1.1 are byte-identical.

One gap found in review, not a blocker: RT-01 and RT-04 do not list LexLeanLaws, the fifth runtime namespace, so a copy of the laws module in a generated module or a source literal would pass them. I have the fix and its plants (the list is now asserted equal to the namespaces the shipped runtime declares; both halves fail without it). It is not pushed here, because a push would void this run; it rides with my next PR.

Merging with a merge commit, pinned to this head.


Generated by Claude Code

@afflom
afflom merged commit 378628e into main Oct 16, 2026
41 of 42 checks passed
afflom pushed a commit that referenced this pull request Oct 16, 2026
…sue-89-typed-certificates

The register has 392 IDs: 388 on this side (main's 387 with SP-14) and #158's four PF rows. The records that conflicted are taken from #158's side here and regenerated on the combined tree in the next commit.
afflom pushed a commit that referenced this pull request Oct 16, 2026
…combined tree (certificate E as data, main with #158)

The verification records of the four certificate corpora and the two certificate fixtures are regenerated by the repository's writers on the tree that merges #158; check-calculus, check-golden, check-production-export, validate-model and validate-spec-links pass on it.
afflom pushed a commit that referenced this pull request Oct 16, 2026
The merge commit of #158 (378628e) has the tree of its head aa58c1d, which this branch already contains; the merge records main in the history and changes no file.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QppGKetUURseXowZun9KY
humuhumu33 added a commit that referenced this pull request Oct 16, 2026
CHANGELOG: both Unreleased entries kept. The four new IDs (PF-20..PF-23)
run in the bdd remainder; check-test-inventory reports the 429 tests of bdd
as the five parts. Register 391, CONFORMANCE.md current.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
humuhumu33 pushed a commit that referenced this pull request Oct 16, 2026
…to issue-30-language-model

Hand-written conflicts:
- language/semantics-1.2.toml: main (#158) and this branch each moved
  semantic_ir 10 -> 11 and lean_backend 17 -> 18 for different changes, so
  the combined tree takes fresh numbers past both: semantic_ir 12,
  lean_backend 19, latex_backend 12 (this branch), proof_lowering 3 (main).
- crates/lexlean/src/ir/semantic.rs: BACKEND_BARE_NAMES is main's 43 names
  plus LexLeanText (44).
- schemas/semantic-module-v2.schema.json: merged structurally; every change
  of either side is kept.
- SPEC.md, CHANGELOG.md: both sides kept.
- The register is 395 (main's 391 plus LM-01..LM-03 and LM-13); the 391
  both sides wrote merged cleanly and is corrected in README.md, SPEC.md
  §31, repository.rs, spec_links.rs and the CHANGELOG entry.

Generated records take main's side here and are regenerated for the
combined tree in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
humuhumu33 pushed a commit that referenced this pull request Oct 16, 2026
…with #158

The merged tree's language-1.2 compiler-semantics ID is 7a7834c6...
(from main's 7c6ad912...): locks (230 of 283 moved, a second relock moved
none), goldens, calculus packages, CONFORMANCE.md and ERRORS.md, negative
fixtures, the production export, and every example's verification records
(uor-atlas is language 1.0 and unchanged). Also the register count 395 in
README.md, repository.rs and spec_links.rs, which the merge commit left at
the 391 both sides wrote.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
humuhumu33 pushed a commit that referenced this pull request Oct 16, 2026
The register has 392 rows; SL-01 stays the last row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
humuhumu33 pushed a commit that referenced this pull request Oct 16, 2026
…ed compiler, after #158 (#92)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[0.5.0] Lemmas for universal equalities over list folds

3 participants