Skip to content

feat: add lake check to check a project against external checkers - #14990

Open
Kha wants to merge 3 commits into
masterfrom
lake-check-cmd
Open

feat: add lake check to check a project against external checkers#14990
Kha wants to merge 3 commits into
masterfrom
lake-check-cmd

Conversation

@Kha

@Kha Kha commented Sep 1, 2026

Copy link
Copy Markdown
Member

This PR adds lake check, a challenge-less variant of lake challenge, which builds the current project's default targets, exports them, replays the result through the kernel, and fails on any use of non-standard axioms.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

@Kha
Kha requested a review from tydeu as a code owner September 1, 2026 14:59
@Kha
Kha requested review from hargoniX and removed request for tydeu September 1, 2026 14:59
@Kha Kha added the changelog-lake Lake label Sep 1, 2026
@github-actions github-actions Bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Sep 1, 2026
@mathlib-lean-pr-testing

mathlib-lean-pr-testing Bot commented Sep 1, 2026

Copy link
Copy Markdown

Mathlib CI status (docs):

  • ❗ Mathlib CI can not be attempted yet, as the nightly-testing-2026-09-01 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-mathlib, Mathlib CI should run now. You can force Mathlib CI using the force-mathlib-ci label. (2026-09-01 15:16:03)
  • ✅ Mathlib branch lean-pr-testing-14990 has successfully built against this PR. (2026-09-02 10:42:34) View Log
  • ✅ Mathlib branch lean-pr-testing-14990 has successfully built against this PR. (2026-09-02 13:04:32) View Log

builtin_facet transDeps : Package => Array Package

/-- The Lean modules of the package's default targets. -/
builtin_facet modules : Package => Array Module

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tydeu FYI, this is for retrieving the modules for lean4export under the sandbox

Comment thread src/lake/Lake/CLI/Check.lean Outdated
@leanprover-bot leanprover-bot added the breaks-manual This is not necessarily a blocker for merging, but there needs to be a plan. label Sep 1, 2026
@leanprover-bot

leanprover-bot commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Reference manual CI status:

@Kha

Kha commented Sep 2, 2026

Copy link
Copy Markdown
Member Author

@tydeu @hargoniX I pushed a refactoring that removes both the lake query :modules and the leanexport call by moving their caller into the sandbox. I did leave the new modules facet as is as it is still triggered via Lean code and seems consistent with existing facets.

@Kha Kha added the downstream Request a downstream-lean4 adaptation PR. label Sep 2, 2026
@downstream-lean4

downstream-lean4 Bot commented Sep 2, 2026

Copy link
Copy Markdown

The adaptation PR for this PR is leanprover/downstream-lean4#33.

@github-actions github-actions Bot added the mathlib4-nightly-available A branch for this PR exists at leanprover-community/mathlib4-nightly-testing:lean-pr-testing-NNNN label Sep 2, 2026
leanprover-bot added a commit to leanprover/reference-manual that referenced this pull request Sep 2, 2026
@mathlib-lean-pr-testing mathlib-lean-pr-testing Bot added the builds-mathlib CI has verified that Mathlib builds against this PR label Sep 2, 2026
Kha and others added 3 commits September 2, 2026 11:57
This PR adds a `modules` facet to packages, so `lake query :modules` reports the Lean modules of a package's default targets: the modules of each default library, and the root of each default executable together with its local transitive imports. A default target that builds no Lean modules, such as a custom target, contributes nothing.

Libraries have had a `modules` facet for some time. This is its package-level counterpart, and like it the facet is not buildable, so it is reached through `lake query` rather than `lake build`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This PR adds `lake check`, which builds a project's default targets, exports them, replays the result through the kernel, and reports the axioms that code rests on, failing on any beyond `propext`, `Classical.choice` and `Quot.sound`. There is no challenge to compare against.

Nothing about the project is evaluated outside the sandbox. `lake env` resolves its dependencies and `lake query :modules` names the modules to check, both inside it, so the project's configuration is never elaborated in Lake's own address space; the build and the export follow in the same sandbox. As for `lake challenge`, this requires the project to carry a `lake-manifest.json`, since the sandbox cannot write one into the project directory.

The exporter is given no declaration list, so the export covers everything in scope rather than only what the project declares, and a check costs roughly the same whatever the project's size: about a minute for a project holding a single theorem. The axiom report copes with that without a list of roots: an axiom that is merely importable is referred to by nothing, so the axioms that some other constant refers to are exactly the ones the code rests on. Note that the kernel accepts `sorryAx`, so a `sorry` is caught by this report and by nothing else.

All the default targets' modules go through the pipeline together, in one sandboxed `lake build`, one export and one kernel replay. Since each module's export already covers its whole import closure, a pass per module would re-check what they share: on a two-root project the roots' exports agree on 6,437,744 of 6,437,817 lines, so the second pass would double the run for two extra constants.

The sandbox invocations in `Lake.Check` get one definition each. `landrunSpawnArgs` builds the `IO.Process.SpawnArgs` that both `runSandBoxedWithStdout` and `runSandBoxedExitCode` use, and `runSandBoxed` is the latter plus the exit-code check. `runExternalKernel` goes through `runSandBoxedExitCode` rather than spawning `landrun` itself, keeping its own messages. `runExporter` holds the exporter's grants, which `safeExport` and `exportModules` had spelled out identically.

The two commands share the tool resolution and the sandbox context through `mkContext`; the vendored comparison path is untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ocess

This PR collapses `lake check`'s four sandboxed invocations into two. `lake resolve-deps` materializes the project's dependencies, still the only step allowed to reach the network, and a second `lake` resolves the targets, builds them and dumps the export, all in one process. Only the export crosses back.

The inner half is `lake check` itself, selected by the `LAKE_CHECK_EXPORT` environment variable that the outer half sets when it spawns, so no new command-line surface is added. It loads the workspace, fetches the root package's `modules` facet, builds the default targets and writes the export to standard out, leaving standard error for progress. It is also the half that a platform without a sandbox would run directly, since it is exactly the work that has to happen next to the project.

What this removes: `safeQueryModules` and the parsing of module names out of its output, `exportModules` and the separate `leanexport` spawn, and, because the exporting process now loads the workspace itself, the `(LEAN_PATH, PATH)` round trip. Resolution keeps its own process precisely so the network stays confined to it, but it no longer has to report anything back, so it is `lake resolve-deps` rather than `lake env` parsed for its output. The module list never crosses a process boundary, which matters beyond tidiness: passing it as arguments would not survive a platform whose command line is capped in the tens of kilobytes.

`LeanExport.dumpEnv` is the export loop that the `leanexport` binary's `main` already had, lifted so that both callers share it rather than keeping two copies that can drift. The binary's output is byte-identical.

`lake challenge` is untouched and keeps `safeResolveWorkspace`, `safeLakeBuild` and `safeExport`.

Note that the process holding the untrusted `.olean` files is now Lake rather than the smaller `leanexport`. The containment is the same, and the process that reports the verdict still never maps them, which is what the wording in `Lake.Check` and in `lake help check` now says.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mathlib-nightly-testing Bot pushed a commit to leanprover-community/batteries that referenced this pull request Sep 2, 2026
mathlib-nightly-testing Bot pushed a commit to leanprover-community/mathlib4-nightly-testing that referenced this pull request Sep 2, 2026
leanprover-bot added a commit to leanprover/reference-manual that referenced this pull request Sep 2, 2026
@tydeu

tydeu commented Sep 4, 2026

Copy link
Copy Markdown
Member

@Kha The modules facet feels like it should perhaps be called defaultModules (like the name of the function) to make it clearer that is not all the modules of the package. Other than that minor bikeshedding, this LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaks-manual This is not necessarily a blocker for merging, but there needs to be a plan. builds-mathlib CI has verified that Mathlib builds against this PR changelog-lake Lake downstream Request a downstream-lean4 adaptation PR. mathlib4-nightly-available A branch for this PR exists at leanprover-community/mathlib4-nightly-testing:lean-pr-testing-NNNN toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants