Skip to the content.

0004: A math LTS stack

Status: accepted. Author: drafted by the AI operations agent at Le Chen’s request. Created: 2026-10-17. Decided: accepted 2026-10-17 by Le Chen, with the recommended answers to open questions 1 to 5 and 7; question 6 stays open (see Open questions). Implemented in: stage 0 as documents (#258, #259); stage 1 in (release) (#264), except doctor --stack-from/--stack-to and the advisory hook, which follow.

Summary

Every six months lean-pkg names, tests and supports one LTS stack: a dated triple of a Lean toolchain, a Mathlib revision and a lean-pkg version, for example lts-2026.10 = Lean v4.35.0, Mathlib tag v4.35.0, lean-pkg 0.12.x. A package that opts in gets pins it can keep for the life of a paper: later lean-pkg releases keep verifying, paging and publishing on that stack for a stated window, advisories about its toolchain are published against it, and moving to the next stack has a written migration note and a preflight. Stage 0 is a document only (the first stack, published under docs/stacks/); stage 1 adds the CLI support. Nothing changes for a package that does not opt in.

Motivation

A paper companion is verified once, cited for years. Its readers expect the page, the receipts and receipt check to keep meaning the same thing long after the author has moved on. Upstream does not offer that kind of promise, and says so:

So the ecosystem gives a paper a pin (a tag) but no statement that anything built on top of that pin keeps working. lean-pkg is the part a paper’s author does control, and it moves faster still: 0.8.0, 0.9.0, 0.10.0 and 0.11.0 were all tagged on 2026-10-17. Concretely, lean-pkg’s own pins already drift underneath its users: lean-pkg new writes v4.35.0-rc2 (new), the toolchain of Palomar’s minimum when it was recorded, and the comparator receipt depends on per-toolchain tools (lake, lean4export, the kernels; COMPARATOR_TOOLCHAIN_DIGESTS). An author who pins today cannot tell which later lean-pkg releases were tested against that pin, or when one stops being.

The analogy is a Linux distribution’s long-term-support release: Lean and Mathlib are the kernel and the core userland; lean-pkg is the distribution on top, and an LTS is its promise to hold a tested combination still.

Design

What a stack is

A stack is a committed file in lean-pkg, docs/stacks/lts-YYYY.MM.yaml (schema lean-pkg-stack/1), with a human page beside it, the same pairing as docs/upgrades/:

schema: lean-pkg-stack/1
name: lts-2026.10
published: 2026-10-24          # the day the stack is declared
lean_toolchain: leanprover/lean4:v4.35.0
mathlib:
  rev: v4.35.0                 # a Mathlib tag, never a branch
  commit: 56a005855ea17e0b0958f73ec801ae140b0a1679
lean_pkg: ">=0.12.0,<1.0"      # the lean-pkg releases that promise to support it (below)
comparator_tools:              # what the comparator receipt runs on this toolchain
  lean4export: <rev>
  comparator: <rev>
supported_until: 2027-10-31    # end of the window
successor: null                # lts-2027.04 once it exists
tested:                        # the matrix run that admitted it
  - package: <public package>
    commit: <sha>
    result: verified           # verify, page, publish --dry-run, receipt check all passed
advisories: []                 # entries from the toolchain advisory list (#237) that apply

The mathlib.commit is recorded beside the tag because a tag can be moved; doctor refuses a stack whose tag no longer resolves to it. The stack names one patch level of Lean; Mathlib’s tag for that patch is the pin.

Cadence and choice

The first stack under this rule would be lts-2026.10. Strictly, the three-week rule picks v4.34.1 today; v4.34.1 is below Palomar’s minimum, so the first stack is v4.35.0 (Mathlib v4.35.0), declared once v4.35.0 is three weeks old (from 2026-11-02) or earlier if Le decides.

What “supported” means

For each stack, from published to supported_until:

  1. Every lean-pkg release in the lean_pkg range keeps the whole path working on the stack: new --stack, verify, gate, page, publish, receipt check, index check, and the comparator receipt with the stack’s comparator_tools. A lean-pkg change that would break that is either fixed or, after 1.0, waits for a major release; this is the release gate (below), not a hope.
  2. Upgrade records keep working. doctor --upgrade-from between any two lean-pkg versions in the range reports nothing that requires a rebuild of a package on the stack; a record entry that would is a blocker for that release.
  3. Site profiles and templates. The new templates and the shipped site profiles have a version for the stack (the scaffold’s lean-toolchain and Mathlib rev), kept for the window.
  4. Advisories. When the toolchain advisory list (#237, warn-only: a Lean release flagged after a kernel soundness bug) gains an entry for the stack’s toolchain, the stack file lists it, the warning names the stack, and the stack’s page says what to do; a stack is never silently withdrawn.
  5. A migration note to the successor is published with the successor (below).

Not promised: that Mathlib accepts fixes on an old tag (it does not backport), that a newer Mathlib lemma is available, or anything about Lean or Mathlib themselves. The stack only promises what lean-pkg does.

Window: about 18 months. Each stack is supported until six months after its second successor is declared, so two stacks are supported at any time and a package always has at least six months to move (open question 3).

How a package opts in (additive)

Stage 1 adds one flag and one optional key; nothing is required.

The key is a claim the author makes, checked against the committed pins. It is never part of what a receipt binds, and a receipt’s meaning does not depend on it.

How a stack is tested

Migration between stacks

How this differs from pinning

A pin (lean-toolchain plus a Mathlib tag in lake-manifest.json) freezes Lean and Mathlib, and every package already has one. It says nothing about the tool around them. Today a newer lean-pkg may change the template, a page rule, the comparator tool versions or the Palomar minimum, and the author learns that when a command fails. A stack adds: the combination was tested end to end on named packages; later lean-pkg releases are gated on it for a stated window; advisories are mapped onto it; and leaving it has a written path. A package on a stack is still just a pin; the support is lean-pkg’s.

Palomar, Reservoir and the trust model

Compatibility and migration

Trust model

What a receipt proves, and what gate, publish and index check accept, do not change: the stack key never makes a check pass or fail. What could mislead:

Unknown: whether referees will read a stack name as a quality label. The stack page should say what it does and does not promise, in one line.

Alternatives

Open questions

  1. Cadence and names: April and October, lts-YYYY.MM? Or tie the name to the Lean version (lts-4.35), which is clearer to Lean users but hides the date a referee cares about. Decided 2026-10-17: names lts-YYYY.MM, cut in April and October.
  2. Palomar’s floor vs held back: when Palomar’s minimum is newer than the held-back choice (as on 2026-10-17: v4.34.1 vs v4.35.0-rc2), the floor wins (recommended), or the stack is declared without Palomar support? Decided 2026-10-17: the Palomar floor wins over the held-back choice.
  3. Window: about 18 months (two stacks supported at once, six months of overlap), or 12 months (one stack plus a short overlap)? The 18 months roughly cover a journal review; whether it covers a revision cycle is Le’s call. Decided 2026-10-17: about 18 months.
  4. Where the key lives: coverage.yaml stack: (recommended for stage 1), or the committed binding file of 0002 if that is accepted. Decided 2026-10-17: opt in by a stack: key in coverage.yaml.
  5. What the stack pins beyond the triple: the comparator tools (yes, recommended, since the comparator receipt depends on them), the Python floor, a container image? Decided 2026-10-17: the stack also pins the comparator tools.
  6. Who runs the release-gate matrix for lab packages, and whether the lab’s own packages are expected to stay on a stack (they currently follow the newest toolchain). Open: not decided on 2026-10-17.
  7. Should new default to the current stack once stage 1 ships, instead of the newest toolchain? Recommended: yes for --kind paper, the newest for --kind library (libraries aimed at Mathlib must follow master). Decided 2026-10-17: new --kind paper defaults to the current stack; --kind library keeps the newest.

Staged plan

Guardrails for every stage: no lock-in (a package on a stack is a plain Lake project that builds with lake build and no lean-pkg); upstream first (general lemmas go to Mathlib; lean-pkg never forks or patches Lean or Mathlib); steward, not owner (stacks are chosen in the open, by this proposal process).

Costs

AI assistance

Drafted by Claude (Anthropic), the lean-pkg operations agent, from Le Chen’s approved brainstorm (a distribution track with an LTS stack), the lean-pkg sources (scaffold.py, palomar_check.py, the upgrade preflight), and the primary sources cited above, each retrieved on 2026-10-17. To be reviewed and decided by the maintainer.