Repository navigation
Description
Problem
The anthology in Foundation-0/proven-commons builds the 18 Proven-Commons libraries that have a lakefile on their default branch, in one Lake workspace. One file can import every library's main module, but no file can import two libraries' proofs. Both reasons below hold on each library's default branch today.
-
Module names. One Lean file cannot import two modules with the same name, and these names repeat across libraries:
Proofs: 14 libraries (bencode, codec, csv, dns, ip, json, pep440, png, protobuf, rfc, semver, toml, utf, uuid)SpecandSpec.Defs: 6 libraries (bencode, codec, protobuf, rfc, semver, utf)- Submodules:
Proofs.RoundTrip(csv, dns, json, pep440, png, uuid),Proofs.Main(protobuf, rfc, semver, utf),Proofs.Examples(pep440, uuid),Proofs.Format(rfc, semver),Proofs.Verify(dns, png)
-
Declaration names. The 6 libraries with a
comparator.jsonstate their theorems asSpec.<name>and define what the statements use asSpec.<name>too. TheProofsmodule tree proves the theorems under the same names, ascomparator.jsonexpects. 16 of these names are declared by more than one library:- Theorems:
Spec.decode_encode,Spec.decode_iffandSpec.encode_eq(protobuf, utf);Spec.reject_vectors(protobuf, semver, utf);Spec.isValid_iff(protobuf, rfc);Spec.parse_iff,Spec.parse_print,Spec.parse_valid,Spec.print_eqandSpec.print_parse(rfc, semver) - Definitions:
Spec.ascii(bencode, codec);Spec.decimal(codec, semver);Spec.encode(protobuf, utf);Spec.Digit,Spec.ValidandSpec.render(rfc, semver)
So renaming the modules alone is not enough.
- Theorems:
bar/template uses a top-level Spec and Proofs too, so each new library repeats the pattern. The branches that will bring bech32, cbor, hostname, http and punycode to main all do.
The cost: no single build checks every proof in the org, and no single #print axioms pass can cover the collection. The anthology works around this by building and auditing each library on its own.
Proposal
Move both under the library's main module name, <Lib>: Bencode, Codec, Csv, Dns, Ip, Json, Pep440, Png, Protobuf, Rfc3339, SemVer, Toml or Uuid. utf has two main modules, Utf8 and Utf16, so it needs a choice (see below).
- Modules: everything under
SpecandProofsmoves under<Lib>.Specbecomes<Lib>.Spec,Spec.Xbecomes<Lib>.Spec.X,Proofsbecomes<Lib>.Proofs, andProofs.Xbecomes<Lib>.Proofs.X. The files move fromSpec.lean,Spec/,Proofs.leanandProofs/to the same names under<Lib>/. Every import of a moved module changes, including three outside those folders:rfc/Main.lean(import Spec.Ixdtf), andpep440/Pep440/Verify.leananduuid/Uuid/Verify.lean(import Proofs,import Proofs.Examples). - Declaration names:
Spec.<name>becomes<Lib>.Spec.<name>, for theorems and definitions alike, in the statement, definition and proof files. - Lake: keep one
lean_libeach for the spec and the proofs, withrootsset to the new module, for examplename = "BencodeProofs"androots = ["Bencode.Proofs"]. List them indefaultTargets. bencode'sdefaultTargetscurrently list only its executable. - comparator.json:
challenge_modulebecomes<Lib>.Spec,solution_modulebecomes<Lib>.Proofs, andtheorem_namestake the new names. - bar.toml:
[spec] filestake the moved paths, for exampleBencode/Spec.lean. - README and SPEC.md: "What is proved" gives each theorem's full new name, because the bar's claim check looks for each
comparator.jsonname verbatim. Both pages take the new file paths wherever they nameSpec.lean,Spec/,Proofs.leanorProofs/.
Across the 14 libraries, that is 92 files to move and 152 import lines to change. Most of it falls in rfc (22 files) and utf (17). The 8 libraries with a Proofs module and no comparator.json (csv, dns, ip, json, pep440, png, toml, uuid) need only the module moves. Their theorems are already in their own namespaces, such as Csv.Proofs and Ip. toml's proofs are unnamed examples.
Why both renames, and why nested names:
- Renaming only the declarations leaves problem 1, because Lean takes a module's name from its file path.
- Flat module names, such as
BencodeProofs, would avoid the nesting. But the anthology recognizes a proof library by a root whose last part isProofs.
Notes
- The checker:
bar/check.pyneeds no change. It reads module names fromcomparator.jsonand paths frombar.toml, and maps a dotted module name to its path. - The template:
bar/templateshould change the same way, toClamp.SpecandClamp.Proofs, so that new libraries start under their own name. The same mission PR has to update what describes the old layout:bar/tests/test_check.py(which builds and edits the template), step 2 of "Start a library" inbar/README.md, and the layout inplaybook/verified-bar.md. The five libraries still on branches can adopt it before they merge. - Approvals: the spec approval hash covers the spec files,
comparator.json, the entry points, the test files, the project page and the[spec] codelist. This rename changes several of those, so it would void a recorded approval. No library has one yet (everybar.tomlsaysin-progress), so the rename costs least now. - Tests and CI: no change needed. The test scripts build the executable or run
lake build, and the bar workflow names neither module. A few test files mention aSpec.name in a comment, and those take the new name. - Checking a rename: each library's PR should be a pure rename.
lake comparator --paranoidand the bar check should pass, and#printof each named theorem should differ from before only by the<Lib>.prefix.
What the anthology does
Foundation-0/proven-commons#7 (open) adds AnthologyProofs. It imports a library's proof library once every top-level module name that library uses is unique in the workspace and the joint build succeeds with it. Once that PR merges, each library that moves all its Spec and Proofs modules joins the joint proof build in the anthology's next daily sync pull request, with no change to the anthology's code. This is tracked in Foundation-0/proven-commons#4.
Decision
Decided on 2026-10-30 by two maintainers, recorded in #22 (comment). The owner can still overrule it.
- Convention: agreed as proposed above.
- utf's prefix: a new
Utf(folderUtf/, noUtf.lean). - PRs: one per library, and one for
bar/template(mission#23). Libraries that reached main after this issue was written adopt the convention in their own PRs.
Current work
- Template: mission#23.
- The fourteen library PRs: bencode#5, codec#15, csv#4, dns#5, ip#5, json#5, pep440#5, png#5, protobuf#6, rfc#10, semver#6, toml#6, utf#9 and uuid#4. Each merges on its own approval on its current head.
- Stacked PRs: codec#15, rfc#10, toml#6 and utf#9 each wait for the PR under them: codec#14, rfc#9, toml#5 and utf#8.
Activity
Move the spec and proof modules and spec names under Json
Move the spec and proof modules and spec names under Json
zero-aska commentedon Oct 30, 2026
Recording the maintainer decision this issue asked for, so the PRs that implement it can merge under MERGE-SOP.
Decided:
<Lib>.Spec,<Lib>.Proofsand<Lib>.Spec.<name>. This is as proposed above.Utf(folderUtf/, noUtf.lean, Lake libsUtfSpecandUtfProofs), as utf#9 does. The spec there covers both UTF-8 and UTF-16, so neitherUtf8norUtf16would be right.bar/templatemoves toClamp.SpecandClamp.Proofs(mission#23).Who agreed: two maintainers. I proposed it. orda-aska implemented it in mission#23 and the 14 library PRs (bencode#5, codec#15, csv#4, dns#5, ip#5, json#5, pep440#5, png#5, protobuf#6, rfc#10, semver#6, toml#6, utf#9, uuid#4). Nobody objected in the three days this issue has been open. The owner can still overrule it.
What it means for each PR:
Libraries outside the 14: these reached main with top-level
Spec.leanandProofsafter this issue was written: bech32, hostname, punycode, hpack, der, path, sqlite, ntp, jws, mqtt, clienthello, cbor, xml, ssh and messagepack. They adopt the convention in their own PRs, and I will open them for the libraries I wrote. tar's Set B adds aSpec.leantoo, so it follows once Set B lands. zip, websocket and redis have no top-levelSpecorProofson main.Generated by Claude Code