Commands and files¶
Everything Leanify provides, in the order a project uses it. The tutorial shows each in context.
The command line¶
lake exe leanify runs natively. Its first run builds the executable.
leanify check¶
Compiles the article natively, in about a second, and prints findings in the
file:line:column: severity: message format of editors. It certifies nothing.
| Finding | Severity |
|---|---|
| a sentence that did not compile (an undefined symbol, a type mismatch, an unsupported construction, …) | warning |
| a sentence of a theorem, lemma, proposition, corollary or definition without a reading | warning |
| a definition without a reading whose symbols later sentences use | warning |
with --claims: every definition and the formal reading of every claim |
info |
with --prose: every sentence of a proof, a remark, an example or a conjecture without a reading, a proof sentence whose construction is not supported, and every definition of the running text without a reading |
info |
An undefined symbol is reported once. If the sentence that defines it was not
read, the finding is at that sentence: … are $\beta(C)\coloneqq…$,
$\xi(C)\coloneqq…$ fails on \partial, and \beta and \xi stay undefined in 5
later sentences (lines …). The defining sentence is the one with the symbol
before \coloneqq, a Let that binds it, or, in a proof, the statement it
proves. Otherwise the finding is at the first sentence that uses the symbol, with
the lines of the later sentences that fail for it: they follow from the first,
and defining the symbol fixes them all. Remarks, examples and conjectures
discuss rather than state, so their prose is not a gap in a statement.
The last lines count the compiled, failed and prose sentences of the text, the
results and the proofs. The exit status is 1 if a sentence failed to compile.
--vocab unitsquare adds the vocabulary of probability on the unit
square (Vocabularies and models).
leanify init¶
Writes four Lean files next to the article and prints the lean_lib entry for
lakefile.toml. NAME, the Lean namespace, is by default the name of the
article's folder. An existing file is never overwritten.
| File | Contents |
|---|---|
Compiled.lean |
#leanify_article NAME "article.tex" "fnv1a64:…" |
Article.lean |
#leanify_semantics NAME "article.tex" |
Proofs.lean |
namespace NAME.Proofs with definedI for every definition and a stub proofK for every claim, each with the claim's reading, place and premises |
Certified.lean |
#leanify_certify NAME "article.tex" using NAME.Proofs |
leanify prepare¶
Run it after every edit of the article. It updates the pin, the hash of the
article in COMPILED.lean, so that Lake recompiles the article. With
--cache, it also writes the lexing cache, one Lean module per section of the
article, so that the kernel relexes only the sections that changed
(Incremental compilation).
The Lean commands¶
| Command | Declares |
|---|---|
#leanify_article NS "article.tex" "fnv1a64:…" [with V] |
NS.source, NS.doc and NS.compiled : compileArticle NS.vocab NS.source = some NS.doc, checked by the kernel. It fails if the pin does not match the file. with V names the vocabulary (default: the core vocabulary). |
#leanify_semantics NS "article.tex" [with M] |
For every definition I: a Lean definition named after its symbol and wellDefinedI. For every claim K: claimK (what the sentence says), meaningfulK (every term in it is defined) and obligationK (its premises imply meaningfulK ∧ claimK). Each is tied to the compiled document by a kernel-checked rfl theorem. with M names the model of the vocabulary. |
#leanify_certify NS "article.tex" using J |
NS.certificate, checked by the kernel, NS.verifiedK : NS.meaningfulK ∧ NS.claimK for every verified claim and NS.refutedK for every refuted one. It writes the reports below and logs a summary. |
What #leanify_certify reads¶
In namespace J:
| Declaration | Type | Required |
|---|---|---|
J.definedI |
NS.wellDefinedI |
for every definition, without sorry |
J.proofK |
NS.obligationK |
for each claim to verify |
J.refuteK |
NS.meaningfulK ∧ ¬ NS.claimK |
for a claim that is false as stated |
A claim is verified when it has a proof without sorry and every claim it rests
on is verified. A claim the text derives (a proof step, or a result whose proof
compiled) is audited: its proof may use Lean, mathlib, Leanify, the compiled
article and helper declarations of the justification modules, which are audited
in turn. The certificate and every refutation may use only the axioms
propext, Classical.choice and Quot.sound.
Tactics¶
| Tactic | Does |
|---|---|
intro_premises |
Unfolds obligationK and introduces every premise J as mJ : meaningfulJ and cJ : claimJ. |
definedness [h₁, …] |
Proves a definedness condition (meaningfulK, wellDefinedI): divisions by nonzero terms, arguments in their domains. Give it the facts it cannot find. |
Options¶
| Option | Effect |
|---|---|
set_option leanify.chunk n |
Sentences per kernel-checked chunk of the compilation. |
set_option leanify.timing "file" |
Appends the time of every stage of #leanify_article to file. |
Long articles need set_option maxRecDepth 100000 and
set_option maxHeartbeats 0 before #leanify_article, as init writes them.
The reports¶
#leanify_certify writes two files next to the article.
article.leanify.json records every sentence (position, environment, outcome
and, if it failed, why), every definition (name, symbol, Lean value,
well-definedness condition, justification) and every claim (reading, Lean
statement, definedness condition, premises, status, justification, and for an
unverified claim why it is not verified). The status of a claim is text
(derived from its citations), companion (proved without a compiled proof in
the text), unverified or refuted. sourceHash pins the article.
article.leanify.tex holds the status of every labelled result and a
summary, for leanify.sty.
leanify_diagnostics.py¶
python .lake/packages/leanify/scripts/leanify_diagnostics.py article.leanify.json \
[--verified] [--strict] [--prose] [--pin Compiled.lean] [--relative-to DIR]
Prints the findings of a report in editor format: a refuted claim is an error,
an unverified claim and a sentence that did not compile are warnings. The exit
status is 1 if the article changed after it was certified, if a claim is
refuted, with --verified if a compiled claim is not verified, and with
--strict on any warning. --pin updates the pin in the Lean file instead.
leanify_prove.py¶
python .lake/packages/leanify/scripts/leanify_prove.py ARTICLE.tex [--proofs Proofs.lean] \
[--hook CMD] [--jobs 4] [--rounds 1] [--timeout 900] [--dry-run]
Fills in the stubs of Proofs.lean that still end in sorry. It needs the
report, so build the certificate once first (lake build NS.Certified).
- Tactics, no model. For every open claim it tries a fixed portfolio: it
introduces the premises and the claim's variables and hypotheses, applies each
premise to them, splits conjunctions, and closes the goal with
assumption,linarith,positivity,ring,field_simp; ring,norm_num(unfolding the article's definitions), or each conjunct in turn; then, for what is left,nlinarith,aesop,grindandtauto. All candidates go into one Lean file under.lake/leanify-prove/, which Lean elaborates once, and the first candidate of each claim that elaborates without an error replaces itssorry. - A hook, optional.
--hook CMDgives every claim still open toCMD, one at a time and--jobsin parallel, as JSON on its standard input: the claim, its formal reading, its Lean statement and definedness condition, its premises (available ascJ), the sentence and the sentences of the proof around it, the article's definitions, the stub, and the errors of the last attempt.CMDprints the tactic block of a proof (the lines after:= by; the stub's first two lines are added if missing). Each block is checked the same way, and--rounds 2givesCMDthe errors of a failed block for a second try. A model behindCMDproves single steps with their premises in context, not whole theorems.
Nothing is written that Lean has not accepted, and lake build checks every
proof again, with the citation audit. Proofs are cached by the statement they
prove (.lake/leanify-prove/cache.json), so after an edit only what changed is
proved again. The exit status is 1 if a claim is still open.
The PDF: leanify.sty¶
\usepackage{leanify} % loads mathtools and amssymb; checks the article as it compiles
\usepackage[status]{leanify} % and marks every labelled result in the margin
\usepackage[certify]{leanify} % and builds the certificate first, so the marks are current
\leanifymodule{Note.Certified} % optional: the module that certifies the article
\leanifyreport % optional: a one-line summary, where it appears
| Option | Effect |
|---|---|
status |
The margin of every labelled result shows derived (every sentence compiled and derived in the text), checked (every sentence compiled and verified), partly checked, compiled (not yet verified) or false (a claim is refuted), read from \jobname.leanify.tex. If the article is newer than that file, a warning says the marks may be out of date. |
check=false |
No quick check during the compile. |
certify |
Before the marks are read, prepare updates the pin and lake build builds the certificate. The first time, when the article has no Lean files yet, init writes them, and a warning gives the [[lean_lib]] entry to add to lakefile.toml. Implies status. |
vocab=unitsquare |
The vocabulary of the article, for check and init. |
lean=FILE |
The compiled Lean file of the article, by default Compiled.lean next to it. The module to build is \leanifymodule, or else NS.Certified for the namespace NS that this file compiles. |
Checking as you compile. When the compiler may run programs (shell escape:
pdflatex -shell-escape, latexmk -shell-escape, or the setting of the
editor) and the article lies in a Lean project (a lakefile.toml or
lakefile.lean in its folder or up to three folders above), every compile runs
lake exe leanify check on the article. Its findings become LaTeX warnings
at their lines of the article,
Package leanify Warning: sentence not compiled (undefined symbol: g); it
(leanify) asserts nothing checked on input line 70.
so editors that read the LaTeX log list them with the other warnings, and the
summary goes to the terminal. With certify, the errors of the Lean build and
the refuted claims are warnings too. The full output of Leanify is in
\jobname.leanify.log. lake must be on the PATH of the compiler; the
first check also builds the checker, which takes a few minutes once.
Without shell escape nothing runs, and in a Lean project a warning says so.
Outside a Lean project, as on arXiv or a journal's server, the package runs
nothing and says nothing. Without status the typeset article is unchanged,
which is what you submit. Once leanify.sty is on CTAN, arXiv and journals have
it; until then, upload it with the article, or leave it out: Leanify reads the
article without it.
The web reader¶
npm ci --prefix .lake/packages/leanify
node .lake/packages/leanify/reader/build.mjs ARTICLE.tex \
[--out DIR] [--title TITLE] [--bbl FILE.bbl] [--date YYYY-MM-DD] [--home URL]
Writes DIR/index.html (default article-reader/ next to the article) with its
stylesheet, script and fonts, a copy of the article and of its report. The page
renders the article from its source, with the status of every sentence. It
refuses a report whose pin does not match the article. --home adds a link
back to a page of yours.
Editors and CI¶
editors/vscode/tasks.json has two VS Code tasks, quick check (the native
check of the open file) and certify (update the pin, build, report), whose
findings appear as squiggles in the .tex file. A GitHub Actions workflow that
certifies an article on every push is in
step 9 of the tutorial.