lean-runtime 2.0.9__tar.gz → 2.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/CHANGELOG.md +63 -1
- {lean_runtime-2.0.9/lean_runtime.egg-info → lean_runtime-2.1.1}/PKG-INFO +19 -1
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/README.md +18 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/cli.md +36 -3
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/development.md +23 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/getting-started.md +12 -2
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/python-api.md +23 -2
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/standalone-files.md +25 -4
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/trust-and-limitations.md +1 -1
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/cli.py +34 -1
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/diagnostics.py +22 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/__init__.py +2 -1
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/engine.py +103 -84
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/policy.py +11 -1
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/probe.py +46 -6
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/environments.py +20 -5
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/facade.py +8 -3
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/models.py +48 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/oci.py +27 -5
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/references.py +14 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/run_cli.py +55 -9
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/runtime.py +37 -6
- lean_runtime-2.1.1/lean_runtime/toolchain_slim.py +209 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/toolchains.py +127 -3
- {lean_runtime-2.0.9 → lean_runtime-2.1.1/lean_runtime.egg-info}/PKG-INFO +19 -1
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime.egg-info/SOURCES.txt +5 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/pyproject.toml +1 -1
- lean_runtime-2.1.1/scripts/announcement_gate.py +188 -0
- lean_runtime-2.1.1/scripts/registry_preflight.py +156 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/discovery/test_engine.py +143 -8
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_bundles.py +51 -0
- lean_runtime-2.1.1/tests/test_diagnostics.py +36 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_facade.py +17 -0
- lean_runtime-2.1.1/tests/test_models.py +61 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_references.py +16 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_run_cli.py +36 -0
- lean_runtime-2.1.1/tests/test_toolchain_slim.py +125 -0
- lean_runtime-2.0.9/tests/test_diagnostics.py +0 -18
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/LICENSE +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/MANIFEST.in +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/catalog/environments.toml +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/catalog/locks/core-v4.32.2.lock.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/catalog/locks/mathlib-v4.30.0.lock.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/catalog/locks/mathlib-v4.31.0.lock.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/catalog/locks/mathlib-v4.32.2.lock.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/compatibility/README.md +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/compatibility/mathlib-4.32.2.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/compatibility/mathlib-4.32.2.toml +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/architecture.md +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/captures.md +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/case-study-v1.md +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/environments.md +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/index.md +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/local-projects.md +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/portable-copies.md +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/ready-programs.md +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/docs/v1-precision.md +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/examples/mathlib.toml +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/__init__.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/__main__.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/_git.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/_paths.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/backends.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/bundles.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/comparison.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/decisions.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/analyzer.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/api.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/candidate.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/catalog.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/catalog_build.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/catalog_cli.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/catalog_manifest.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/data/catalog.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/defaults.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/errors.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/module_inventory.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/planner.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/py.typed +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/result.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/schema_resources.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/schemas/catalog-v1.schema.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/schemas/plan-v1.schema.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/discovery/schemas/result-v1.schema.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/errors.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/events.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/frontmatter.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/health.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/lake.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/lockfiles.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/locking.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/matrix.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/policies.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/profiling.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/programs.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/projects.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/publisher_verification.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/py.typed +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/resolver.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/schema_resources.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/serialization.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/specs.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/store.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/timings.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/verification.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime/wire.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime.egg-info/dependency_links.txt +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime.egg-info/entry_points.txt +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime.egg-info/requires.txt +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/lean_runtime.egg-info/top_level.txt +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/mkdocs.yml +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/schemas/cleanup-v1.schema.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/schemas/comparison-v1.schema.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/schemas/execution-v1.schema.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/schemas/inspect-v1.schema.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/schemas/matrix-v1.schema.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/schemas/profile-v1.schema.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/schemas/verify-v1.schema.json +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/scripts/run_compatibility.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/scripts/run_v1_case_study.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/scripts/smoke_wheel.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/setup.cfg +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/conftest.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/discovery/e2e/test_real_discovery.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/discovery/test_analyzer.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/discovery/test_catalog.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/discovery/test_catalog_build.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/discovery/test_discovery_schema_resources.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/discovery/test_planner.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/discovery/test_policy.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_backend.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_cli.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_environment_integration.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_events_health.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_frontmatter.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_git.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_interactive.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_lockfiles.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_multifile.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_paths.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_prebuilt_policy.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_programs.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_projects.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_runtime.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_schema_resources.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_schemas.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_signatures.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_specs.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_store.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_toolchains.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_v1_precision.py +0 -0
- {lean_runtime-2.0.9 → lean_runtime-2.1.1}/tests/test_verification_inventory.py +0 -0
|
@@ -1,6 +1,68 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 2.1.1 - 2026-08-12
|
|
4
|
+
|
|
5
|
+
- The discovery search budget now gates starting additional candidates and
|
|
6
|
+
no longer kills an in-flight authoritative check, which is bounded by its
|
|
7
|
+
own per-candidate timeout. A slow machine's first Mathlib check can outlive
|
|
8
|
+
the remaining search budget legitimately.
|
|
9
|
+
- OCI blob downloads keep partials on truncated transfers and resume with a
|
|
10
|
+
Range request, retry transport errors mid-stream, and attempt four times.
|
|
11
|
+
- Add `build-and-publish --accelerate`: hydrate artifacts from known package
|
|
12
|
+
caches (Mathlib's `lake exe cache get`) for locked packages that carry no
|
|
13
|
+
artifact command of their own. Acceleration is keyed by exact canonical
|
|
14
|
+
package URL, never changes the lock identity, is recorded in the hydration
|
|
15
|
+
report, and the built environment is still probe-verified before
|
|
16
|
+
publication. The public-cache workflow uses it, turning multi-hour Mathlib
|
|
17
|
+
source builds into minutes.
|
|
18
|
+
- Add a fail-closed release toolkit: `scripts/registry_preflight.py` verifies
|
|
19
|
+
every bundled catalog entry is anonymously downloadable, and the
|
|
20
|
+
announcement-gate workflow runs the advertised PyPI journeys on clean
|
|
21
|
+
unauthenticated Linux and macOS runners (dispatch + daily canary).
|
|
22
|
+
- `lean-run` now warns loudly when a downloadable environment is unavailable
|
|
23
|
+
and states that source builds can take 30+ minutes, with a
|
|
24
|
+
`--no-source-build` hint, instead of falling back silently.
|
|
25
|
+
|
|
26
|
+
## 2.1.0 - 2026-08-11
|
|
27
|
+
|
|
28
|
+
- Add `lean-runtime toolchain-slim` and
|
|
29
|
+
`ToolchainManager.materialize_slim()`: a verified check-profile toolchain
|
|
30
|
+
copy that drops editor indexes, static libraries, bundled LLVM/clang, and
|
|
31
|
+
sources (about 2.6 GB → 2.1 GB for v4.32.2 once `--prune-original` removes
|
|
32
|
+
the full Elan copy). Materialization hardlinks files, verification runs a
|
|
33
|
+
capability corpus with the slim copy's own `lean`, and checking transparently
|
|
34
|
+
routes through the slim copy when the full toolchain is absent. Lean v4.32
|
|
35
|
+
requires all `.olean` facets and per-module IR for ordinary elaboration, so
|
|
36
|
+
those remain; source builds of new environments still need the full
|
|
37
|
+
toolchain.
|
|
38
|
+
|
|
39
|
+
- Exempt environment acquisition (downloads, toolchain installs, source
|
|
40
|
+
builds) from the discovery search budget: a slow first-time download can no
|
|
41
|
+
longer expire an otherwise healthy search. Acquisition is bounded separately
|
|
42
|
+
by `DiscoveryPolicy.acquisition_timeout_seconds` and `lean-run
|
|
43
|
+
--acquire-timeout`; `--search-timeout` and `--check-timeout` name the
|
|
44
|
+
remaining budgets, with `--discovery-timeout` and `--timeout` kept as
|
|
45
|
+
deprecated aliases.
|
|
46
|
+
- Split the candidate probe into `acquire` and `check` phases and announce
|
|
47
|
+
first-time toolchain installation through a `toolchain.install_started`
|
|
48
|
+
event and a `lean-run` progress line. `CandidateProbe` implementers must now
|
|
49
|
+
provide both methods; `acquire` returns the newly exported
|
|
50
|
+
`AcquiredCandidate`, and its acquisition budget is forwarded to
|
|
51
|
+
`open_exact(build_timeout=...)` so `--acquire-timeout` governs source
|
|
52
|
+
builds.
|
|
53
|
+
- Add `ExecutionResult.errors`, `.warnings`, and `.first_error` severity views,
|
|
54
|
+
a `Diagnostic.location` property, and compact `repr` output for both types.
|
|
55
|
+
`to_dict()` payloads are unchanged.
|
|
56
|
+
- Report structured diagnostics against the caller's logical input names
|
|
57
|
+
(for example `Main.lean`) instead of staged sandbox paths, and rewrite the
|
|
58
|
+
staged entrypoint path back to the user's file in `lean-run` text output.
|
|
59
|
+
Raw `stdout`/`stderr` remain authoritative and unmodified in results.
|
|
60
|
+
- Add `lean.setup(toolchain="v4.32.2")` and `Runtime.open_toolchain()` for
|
|
61
|
+
reusable core-only environments; the empty-`deps` error now teaches the
|
|
62
|
+
toolchain form.
|
|
63
|
+
- Accept an exact lock path anywhere `lean-runtime profile` previously
|
|
64
|
+
required an environment name (`Runtime.subject_environment`); a path that
|
|
65
|
+
exists on disk always wins over an environment name.
|
|
4
66
|
|
|
5
67
|
## 2.0.9 - 2026-08-10
|
|
6
68
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lean-runtime
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: Run Lean 4 proofs from Python or standalone files
|
|
5
5
|
Author: Alejandro Radisic
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -131,6 +131,24 @@ result = env.check(
|
|
|
131
131
|
result.raise_for_error()
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
+
Rejected proofs carry parsed diagnostics:
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
result = env.check(broken_proof)
|
|
138
|
+
|
|
139
|
+
for error in result.errors:
|
|
140
|
+
print(error.file, error.line, error.message)
|
|
141
|
+
|
|
142
|
+
result.raise_for_error() # raises LeanCheckError with the same detail
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Core-only work does not need a dependency:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
core = lean.setup(toolchain="v4.32.2")
|
|
149
|
+
core.check("example : 2 + 2 = 4 := rfl").raise_for_error()
|
|
150
|
+
```
|
|
151
|
+
|
|
134
152
|
Batch and asyncio APIs reuse that prepared environment:
|
|
135
153
|
|
|
136
154
|
```python
|
|
@@ -96,6 +96,24 @@ result = env.check(
|
|
|
96
96
|
result.raise_for_error()
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
Rejected proofs carry parsed diagnostics:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
result = env.check(broken_proof)
|
|
103
|
+
|
|
104
|
+
for error in result.errors:
|
|
105
|
+
print(error.file, error.line, error.message)
|
|
106
|
+
|
|
107
|
+
result.raise_for_error() # raises LeanCheckError with the same detail
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Core-only work does not need a dependency:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
core = lean.setup(toolchain="v4.32.2")
|
|
114
|
+
core.check("example : 2 + 2 = 4 := rfl").raise_for_error()
|
|
115
|
+
```
|
|
116
|
+
|
|
99
117
|
Batch and asyncio APIs reuse that prepared environment:
|
|
100
118
|
|
|
101
119
|
```python
|
|
@@ -18,9 +18,14 @@ lean-run Main.lean --offline
|
|
|
18
18
|
|
|
19
19
|
Without explicit context or a pinned Lake project, `lean-run` automatically
|
|
20
20
|
searches its bundled exact-environment catalog. Use `--lock-out` to retain the
|
|
21
|
-
successful lock, `--no-discover` to require explicit context,
|
|
22
|
-
`--catalog PATH` to override the catalog
|
|
23
|
-
`--
|
|
21
|
+
successful lock, `--no-discover` to require explicit context, and
|
|
22
|
+
`--catalog PATH` to override the catalog. Three budgets bound the work:
|
|
23
|
+
`--search-timeout` covers ranking and compiler probes, `--check-timeout`
|
|
24
|
+
covers each Lean invocation, and `--acquire-timeout` independently bounds
|
|
25
|
+
downloading, installing, or building one candidate environment, so a slow
|
|
26
|
+
first-time download cannot expire the search. `--discovery-timeout` and
|
|
27
|
+
`--timeout` remain as deprecated aliases of `--search-timeout` and
|
|
28
|
+
`--check-timeout`. See
|
|
24
29
|
[Standalone Lean files](standalone-files.md) for routing and policy details.
|
|
25
30
|
|
|
26
31
|
## `lean-runtime`
|
|
@@ -79,6 +84,34 @@ identity, package Git trees, computer compatibility, and Lean probe before
|
|
|
79
84
|
making the environment available. See [Portable copies and environment
|
|
80
85
|
libraries](portable-copies.md) for its trust boundary.
|
|
81
86
|
|
|
87
|
+
## Slim toolchains
|
|
88
|
+
|
|
89
|
+
The official Lean toolchain is roughly 2.6 GB installed. Proof checking does
|
|
90
|
+
not need all of it: editor indexes, static libraries, the bundled LLVM/clang,
|
|
91
|
+
and toolchain sources are only used by editors and native compilation.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
lean-runtime toolchain-slim v4.32.2
|
|
95
|
+
lean-runtime toolchain-slim v4.32.2 --prune-original
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`toolchain-slim` materializes a separate check-profile copy by hardlinking the
|
|
99
|
+
kept files (near-zero extra disk), then verifies it against a capability
|
|
100
|
+
corpus — elaboration, core tactics, `decide`, `#eval`, metaprogramming, and
|
|
101
|
+
`Std` imports — using the slim copy's own `lean`. A copy that fails any probe
|
|
102
|
+
is removed and reported.
|
|
103
|
+
|
|
104
|
+
`--prune-original` uninstalls the full Elan toolchain after verification,
|
|
105
|
+
reducing the v4.32.2 footprint from about 2.6 GB to about 2.1 GB. All checking
|
|
106
|
+
continues through the slim copy. Lean v4.32 loads every `.olean` facet and
|
|
107
|
+
per-module IR during ordinary elaboration, so those artifact classes must
|
|
108
|
+
stay; larger reductions require upstream facet-loading changes.
|
|
109
|
+
|
|
110
|
+
After pruning, source builds of *new* environments and native compilation
|
|
111
|
+
need the full toolchain again; reinstall it with `lean-runtime install`.
|
|
112
|
+
Downloads are unaffected: first-time installation still transfers the full
|
|
113
|
+
official release before a slim copy can be derived from it.
|
|
114
|
+
|
|
82
115
|
## Replay
|
|
83
116
|
|
|
84
117
|
```bash
|
|
@@ -78,3 +78,26 @@ a normal publisher and creates the PyPI project.
|
|
|
78
78
|
PyPI does not permit replacing files for an already published version. If a
|
|
79
79
|
release needs a correction, increment the version rather than recreating the
|
|
80
80
|
tag.
|
|
81
|
+
|
|
82
|
+
## Release and announcement protocol
|
|
83
|
+
|
|
84
|
+
Catalog entries are public claims that a prebuilt environment is
|
|
85
|
+
downloadable. The protocol below makes those claims fail-closed:
|
|
86
|
+
|
|
87
|
+
1. Publish downloadable environments for every catalog entry and platform
|
|
88
|
+
(`public-cache.yml`) **before** shipping a wheel that references them, and
|
|
89
|
+
make the GHCR package publicly pullable.
|
|
90
|
+
2. Run `python scripts/registry_preflight.py` — it verifies, anonymously,
|
|
91
|
+
that every catalog lock resolves to an index, platform manifests, and
|
|
92
|
+
readable blobs. CI-cheap; run it on every release.
|
|
93
|
+
3. After publishing to PyPI, dispatch the **Announcement gate** workflow
|
|
94
|
+
(`announcement-gate.yml`). It installs from PyPI on clean unauthenticated
|
|
95
|
+
Linux and macOS runners and runs the advertised journeys from
|
|
96
|
+
`acceptance/`: a cold check with `--no-source-build` (fail-closed: a
|
|
97
|
+
broken registry fails in seconds instead of hiding behind a source
|
|
98
|
+
build), a warm re-check, a failing proof with logical diagnostic paths, a
|
|
99
|
+
lock round-trip, and the Python batch API. Release titles use `vX.Y.Z`,
|
|
100
|
+
matching the tag.
|
|
101
|
+
4. Announce only after the gate is green. The same workflow runs daily as a
|
|
102
|
+
canary: registry permissions and docs deployments can break without any
|
|
103
|
+
code change.
|
|
@@ -75,17 +75,27 @@ result.raise_for_error()
|
|
|
75
75
|
`setup()` resolves and ensures the environment once. Further checks reuse that
|
|
76
76
|
handle, including batch and asynchronous calls.
|
|
77
77
|
|
|
78
|
-
The same entry point opens local projects, exact locks,
|
|
79
|
-
environments:
|
|
78
|
+
The same entry point opens local projects, exact locks, previously named
|
|
79
|
+
environments, and core-only toolchains:
|
|
80
80
|
|
|
81
81
|
```python
|
|
82
82
|
project = lean.setup(project="./my-project")
|
|
83
83
|
locked = lean.setup(lock="environment.lock.json")
|
|
84
84
|
existing = lean.setup(environment="research-stack")
|
|
85
|
+
core = lean.setup(toolchain="v4.32.2")
|
|
85
86
|
```
|
|
86
87
|
|
|
87
88
|
Exactly one context must be supplied.
|
|
88
89
|
|
|
90
|
+
Rejected checks expose parsed diagnostics directly, with `file` naming your
|
|
91
|
+
logical input:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
result = environment.check(broken_proof)
|
|
95
|
+
for error in result.errors:
|
|
96
|
+
print(error.file, error.line, error.message)
|
|
97
|
+
```
|
|
98
|
+
|
|
89
99
|
## Lock for CI
|
|
90
100
|
|
|
91
101
|
Resolve a friendly dependency declaration and retain its exact graph:
|
|
@@ -12,9 +12,13 @@ environment = lean.setup(["mathlib@v4.32.2"])
|
|
|
12
12
|
project = lean.setup(project="./my-project")
|
|
13
13
|
locked = lean.setup(lock="environment.lock.json")
|
|
14
14
|
existing = lean.setup(environment="research-stack")
|
|
15
|
+
core = lean.setup(toolchain="v4.32.2")
|
|
15
16
|
```
|
|
16
17
|
|
|
17
|
-
Exactly one of `deps`, `project`, `lock`,
|
|
18
|
+
Exactly one of `deps`, `project`, `lock`, `environment`, or a bare
|
|
19
|
+
`toolchain` is required. A bare `toolchain` prepares the core-only
|
|
20
|
+
environment for that Lean release; combined with `deps` or `project` it
|
|
21
|
+
remains an override. The
|
|
18
22
|
default `Runtime` is created lazily on the first operation; importing
|
|
19
23
|
`lean_runtime` has no filesystem or network side effects. Supply
|
|
20
24
|
`runtime=Runtime(...)` to any façade function for explicit configuration.
|
|
@@ -53,7 +57,24 @@ runs. Planning metadata narrows candidates but never asserts compatibility.
|
|
|
53
57
|
|
|
54
58
|
## Results
|
|
55
59
|
|
|
56
|
-
Results remain inspectable values.
|
|
60
|
+
Results remain inspectable values. Failed checks expose their parsed
|
|
61
|
+
diagnostics directly:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
result = environment.check(source)
|
|
65
|
+
|
|
66
|
+
for error in result.errors:
|
|
67
|
+
print(error.file, error.line, error.message)
|
|
68
|
+
|
|
69
|
+
if result.first_error is not None:
|
|
70
|
+
print(result.first_error.location)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`errors` and `warnings` are severity-filtered views of `diagnostics`;
|
|
74
|
+
`first_error` returns the first error or `None`. Diagnostic `file` values name
|
|
75
|
+
the caller's logical input (for example `Main.lean`); raw compiler output
|
|
76
|
+
remains authoritative on `stdout`/`stderr` and may contain physical sandbox
|
|
77
|
+
paths. Scripts that prefer exceptions can use:
|
|
57
78
|
|
|
58
79
|
```python
|
|
59
80
|
result.raise_for_error()
|
|
@@ -15,9 +15,21 @@ environment is compatible. Runtime materializes each bounded candidate and
|
|
|
15
15
|
Lean authoritatively checks the source before discovery can succeed.
|
|
16
16
|
|
|
17
17
|
The bundled bootstrap catalog contains core Lean v4.32.2 plus exact Mathlib
|
|
18
|
-
v4.32.2, v4.31.0, and v4.30.0 locks. `--catalog PATH` selects another validated
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
v4.32.2, v4.31.0, and v4.30.0 locks. `--catalog PATH` selects another validated
|
|
19
|
+
catalog and `--no-discover` restores strict explicit-context behavior.
|
|
20
|
+
|
|
21
|
+
Three budgets bound the work independently:
|
|
22
|
+
|
|
23
|
+
- `--max-candidates` and `--search-timeout` bound the search itself: ranking
|
|
24
|
+
plus compiler probes.
|
|
25
|
+
- `--check-timeout` bounds each Lean invocation.
|
|
26
|
+
- `--acquire-timeout` bounds downloading, installing, or building one
|
|
27
|
+
candidate environment, including its source build. Acquisition never
|
|
28
|
+
consumes the search budget, so a slow first-time toolchain download cannot
|
|
29
|
+
expire an otherwise healthy search.
|
|
30
|
+
|
|
31
|
+
`--discovery-timeout` and `--timeout` remain as deprecated aliases of
|
|
32
|
+
`--search-timeout` and `--check-timeout`.
|
|
21
33
|
|
|
22
34
|
## Frontmatter format
|
|
23
35
|
|
|
@@ -53,12 +65,21 @@ environments only.
|
|
|
53
65
|
|
|
54
66
|
## Output
|
|
55
67
|
|
|
56
|
-
Human output is concise
|
|
68
|
+
Human output is concise, and error locations name the file you passed rather
|
|
69
|
+
than an internal staging path:
|
|
57
70
|
|
|
58
71
|
```text
|
|
59
72
|
✓ Main.lean accepted in 0.42s
|
|
60
73
|
```
|
|
61
74
|
|
|
75
|
+
```text
|
|
76
|
+
proofs/Bad.lean:1:23: error: Type mismatch
|
|
77
|
+
✗ proofs/Bad.lean rejected in 0.35s
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Only the checked file's own path is rewritten; dependency paths in compiler
|
|
81
|
+
output are shown as Lean printed them.
|
|
82
|
+
|
|
62
83
|
Cold operations report meaningful dependency, cache, and build phases on
|
|
63
84
|
stderr. `--quiet` suppresses progress and `--json` emits the complete structured
|
|
64
85
|
`ExecutionResult` without progress messages.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Trusted local execution
|
|
4
4
|
|
|
5
|
-
Lean Runtime
|
|
5
|
+
Lean Runtime orchestrates trusted code. It is not a sandbox.
|
|
6
6
|
|
|
7
7
|
Lake configurations are executable, dependencies may contain native code and
|
|
8
8
|
custom build targets, and explicit artifact commands run subprocesses. Lockfile
|
|
@@ -153,6 +153,13 @@ def parser() -> argparse.ArgumentParser:
|
|
|
153
153
|
action="store_true",
|
|
154
154
|
help="publish blobs and platform manifest without updating the lock index",
|
|
155
155
|
)
|
|
156
|
+
push.add_argument(
|
|
157
|
+
"--accelerate",
|
|
158
|
+
action="store_true",
|
|
159
|
+
help="hydrate artifacts from known package caches (e.g. Mathlib's) for locked "
|
|
160
|
+
"packages without an artifact command; the lock identity is unchanged and the "
|
|
161
|
+
"built environment is still probe-verified before publication",
|
|
162
|
+
)
|
|
156
163
|
push.add_argument("--sign", action="store_true", help="sign the published lock index")
|
|
157
164
|
push.add_argument(
|
|
158
165
|
"--attest", action="store_true", help="publish a signed source/probe attestation"
|
|
@@ -271,8 +278,21 @@ def parser() -> argparse.ArgumentParser:
|
|
|
271
278
|
diff.add_argument("right")
|
|
272
279
|
diff.add_argument("--json", action="store_true")
|
|
273
280
|
|
|
281
|
+
toolchain_slim = commands.add_parser(
|
|
282
|
+
"toolchain-slim",
|
|
283
|
+
help="materialize a verified slim check-profile copy of a toolchain",
|
|
284
|
+
)
|
|
285
|
+
toolchain_slim.add_argument("toolchain", help="Lean toolchain, e.g. v4.32.2")
|
|
286
|
+
toolchain_slim.add_argument(
|
|
287
|
+
"--prune-original",
|
|
288
|
+
action="store_true",
|
|
289
|
+
help="uninstall the full Elan toolchain after verification; checking keeps "
|
|
290
|
+
"working through the slim copy, but source builds of new environments and "
|
|
291
|
+
"native compilation need the full toolchain again",
|
|
292
|
+
)
|
|
293
|
+
|
|
274
294
|
profile = commands.add_parser("profile", help="measure repeated checks in one environment")
|
|
275
|
-
profile.add_argument("environment")
|
|
295
|
+
profile.add_argument("environment", help="environment name or exact lock path")
|
|
276
296
|
profile.add_argument("file", type=Path)
|
|
277
297
|
profile.add_argument("--warmup", type=int, default=1)
|
|
278
298
|
profile.add_argument("--repeat", type=int, default=5)
|
|
@@ -378,6 +398,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
378
398
|
EnvironmentLock.load(args.lock),
|
|
379
399
|
name=args.name,
|
|
380
400
|
build_timeout=args.timeout,
|
|
401
|
+
accelerate=args.accelerate,
|
|
381
402
|
)
|
|
382
403
|
_json(
|
|
383
404
|
runtime.publish_environment(
|
|
@@ -519,6 +540,18 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
519
540
|
if args.command == "storage":
|
|
520
541
|
_json(runtime.store_status().to_dict())
|
|
521
542
|
return 0
|
|
543
|
+
if args.command == "toolchain-slim":
|
|
544
|
+
manifest = runtime.toolchains.materialize_slim(args.toolchain)
|
|
545
|
+
if args.prune_original:
|
|
546
|
+
runtime.toolchains.prune_original(args.toolchain)
|
|
547
|
+
_json(
|
|
548
|
+
{
|
|
549
|
+
**manifest.to_dict(),
|
|
550
|
+
"path": str(runtime.toolchains.slim_path(args.toolchain)),
|
|
551
|
+
"pruned_original": args.prune_original,
|
|
552
|
+
}
|
|
553
|
+
)
|
|
554
|
+
return 0
|
|
522
555
|
if args.command == "doctor":
|
|
523
556
|
doctor_report = runtime.doctor()
|
|
524
557
|
_json(doctor_report.to_dict())
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from dataclasses import replace
|
|
6
8
|
|
|
7
9
|
from .models import Diagnostic, Severity
|
|
8
10
|
|
|
@@ -46,6 +48,26 @@ def parse_diagnostics(output: str) -> tuple[Diagnostic, ...]:
|
|
|
46
48
|
return tuple(diagnostics)
|
|
47
49
|
|
|
48
50
|
|
|
51
|
+
def map_diagnostic_paths(
|
|
52
|
+
diagnostics: tuple[Diagnostic, ...],
|
|
53
|
+
path_map: Mapping[str, str] | None,
|
|
54
|
+
) -> tuple[Diagnostic, ...]:
|
|
55
|
+
"""Rewrite staged physical paths to the caller's logical input names.
|
|
56
|
+
|
|
57
|
+
Only exact staged-file matches are rewritten; package files may
|
|
58
|
+
legitimately share basenames, and raw compiler output remains authoritative
|
|
59
|
+
on the execution result.
|
|
60
|
+
"""
|
|
61
|
+
if not path_map:
|
|
62
|
+
return diagnostics
|
|
63
|
+
return tuple(
|
|
64
|
+
replace(item, file=path_map[item.file])
|
|
65
|
+
if item.file is not None and item.file in path_map
|
|
66
|
+
else item
|
|
67
|
+
for item in diagnostics
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
49
71
|
def error_diagnostic(message: str) -> Diagnostic:
|
|
50
72
|
"""Create an infrastructure diagnostic."""
|
|
51
73
|
severity: Severity = "error"
|
|
@@ -21,7 +21,7 @@ from .defaults import DEFAULT_CATALOG_PATH, default_catalog
|
|
|
21
21
|
from .errors import CatalogError, DiscoveryError, PolicyError
|
|
22
22
|
from .planner import Planner
|
|
23
23
|
from .policy import DiscoveryPolicy
|
|
24
|
-
from .probe import CandidateProbe, LeanRuntimeProbe, ProbeOutcome
|
|
24
|
+
from .probe import AcquiredCandidate, CandidateProbe, LeanRuntimeProbe, ProbeOutcome
|
|
25
25
|
from .result import (
|
|
26
26
|
RESULT_SCHEMA,
|
|
27
27
|
CandidateAttempt,
|
|
@@ -39,6 +39,7 @@ __all__ = [
|
|
|
39
39
|
"AvailabilityObservation",
|
|
40
40
|
"Candidate",
|
|
41
41
|
"CandidateAttempt",
|
|
42
|
+
"AcquiredCandidate",
|
|
42
43
|
"CandidateProbe",
|
|
43
44
|
"CandidateReason",
|
|
44
45
|
"Catalog",
|