lean-runtime 4.0.0__tar.gz → 4.0.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.
Files changed (191) hide show
  1. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/CHANGELOG.md +9 -0
  2. {lean_runtime-4.0.0/lean_runtime.egg-info → lean_runtime-4.0.1}/PKG-INFO +3 -4
  3. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/README.md +2 -3
  4. lean_runtime-4.0.1/docs/getting-started.md +132 -0
  5. lean_runtime-4.0.1/docs/index.md +150 -0
  6. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/environments.py +16 -1
  7. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/runtime.py +14 -2
  8. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/toolchains.py +14 -0
  9. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/verification.py +14 -5
  10. {lean_runtime-4.0.0 → lean_runtime-4.0.1/lean_runtime.egg-info}/PKG-INFO +3 -4
  11. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/mkdocs.yml +42 -9
  12. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/pyproject.toml +1 -1
  13. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_environment_integration.py +7 -0
  14. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_projects.py +1 -0
  15. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_toolchains.py +3 -0
  16. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_verification_probe.py +27 -2
  17. lean_runtime-4.0.0/docs/getting-started.md +0 -42
  18. lean_runtime-4.0.0/docs/index.md +0 -47
  19. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/LICENSE +0 -0
  20. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/MANIFEST.in +0 -0
  21. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/catalog/environments.toml +0 -0
  22. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/catalog/locks/core-v4.32.2.lock.json +0 -0
  23. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/catalog/locks/leancert-v4.30.0.5.lock.json +0 -0
  24. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/catalog/locks/leancert-v4.31.0.lock.json +0 -0
  25. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/catalog/locks/leancert-v4.32.2.4.lock.json +0 -0
  26. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/catalog/locks/leancert-v4.33.0.lock.json +0 -0
  27. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/catalog/locks/mathlib-v4.30.0.lock.json +0 -0
  28. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/catalog/locks/mathlib-v4.31.0.lock.json +0 -0
  29. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/catalog/locks/mathlib-v4.32.2.lock.json +0 -0
  30. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/catalog/locks/mathlib-v4.33.0.lock.json +0 -0
  31. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/compatibility/README.md +0 -0
  32. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/compatibility/lake-artifact-cache-4.33.0.json +0 -0
  33. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/compatibility/mathlib-4.32.2.json +0 -0
  34. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/compatibility/mathlib-4.32.2.toml +0 -0
  35. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/compatibility/mathlib-4.33.0.json +0 -0
  36. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/compatibility/mathlib-4.33.0.toml +0 -0
  37. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/architecture.md +0 -0
  38. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/captures.md +0 -0
  39. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/case-study-v1.md +0 -0
  40. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/cli.md +0 -0
  41. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/development.md +0 -0
  42. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/environments.md +0 -0
  43. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/lake-artifact-cache-design.md +0 -0
  44. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/local-projects.md +0 -0
  45. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/portable-copies.md +0 -0
  46. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/project-publishing.md +0 -0
  47. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/python-api.md +0 -0
  48. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/ready-programs.md +0 -0
  49. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/standalone-files.md +0 -0
  50. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/trust-and-limitations.md +0 -0
  51. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/docs/v1-precision.md +0 -0
  52. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/examples/mathlib.toml +0 -0
  53. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/__init__.py +0 -0
  54. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/__main__.py +0 -0
  55. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/_git.py +0 -0
  56. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/_paths.py +0 -0
  57. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/backends.py +0 -0
  58. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/bundles.py +0 -0
  59. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/capsules.py +0 -0
  60. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/cli.py +0 -0
  61. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/comparison.py +0 -0
  62. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/console.py +0 -0
  63. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/decisions.py +0 -0
  64. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/diagnostics.py +0 -0
  65. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/__init__.py +0 -0
  66. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/analyzer.py +0 -0
  67. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/api.py +0 -0
  68. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/candidate.py +0 -0
  69. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/catalog.py +0 -0
  70. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/catalog_build.py +0 -0
  71. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/catalog_cli.py +0 -0
  72. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/catalog_manifest.py +0 -0
  73. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/data/catalog.json +0 -0
  74. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/defaults.py +0 -0
  75. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/engine.py +0 -0
  76. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/errors.py +0 -0
  77. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/module_inventory.py +0 -0
  78. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/planner.py +0 -0
  79. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/policy.py +0 -0
  80. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/probe.py +0 -0
  81. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/py.typed +0 -0
  82. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/result.py +0 -0
  83. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/schema_resources.py +0 -0
  84. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/schemas/catalog-v1.schema.json +0 -0
  85. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/schemas/plan-v1.schema.json +0 -0
  86. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/discovery/schemas/result-v1.schema.json +0 -0
  87. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/errors.py +0 -0
  88. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/events.py +0 -0
  89. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/facade.py +0 -0
  90. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/frontmatter.py +0 -0
  91. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/header_cache.py +0 -0
  92. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/health.py +0 -0
  93. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/identifier_resolver.py +0 -0
  94. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/lake.py +0 -0
  95. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/lake_cache.py +0 -0
  96. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/lockfiles.py +0 -0
  97. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/locking.py +0 -0
  98. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/matrix.py +0 -0
  99. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/models.py +0 -0
  100. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/oci.py +0 -0
  101. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/oci_protocol.py +0 -0
  102. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/packs.py +0 -0
  103. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/policies.py +0 -0
  104. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/profiling.py +0 -0
  105. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/programs.py +0 -0
  106. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/project_execution.py +0 -0
  107. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/project_sharing.py +0 -0
  108. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/projects.py +0 -0
  109. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/publisher_verification.py +0 -0
  110. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/py.typed +0 -0
  111. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/references.py +0 -0
  112. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/resolver.py +0 -0
  113. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/run_cli.py +0 -0
  114. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/schema_resources.py +0 -0
  115. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/serialization.py +0 -0
  116. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/shared_projects.py +0 -0
  117. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/specs.py +0 -0
  118. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/store.py +0 -0
  119. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/timings.py +0 -0
  120. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/toolchain_oci.py +0 -0
  121. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/toolchain_slim.py +0 -0
  122. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime/wire.py +0 -0
  123. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime.egg-info/SOURCES.txt +0 -0
  124. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime.egg-info/dependency_links.txt +0 -0
  125. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime.egg-info/entry_points.txt +0 -0
  126. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime.egg-info/requires.txt +0 -0
  127. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/lean_runtime.egg-info/top_level.txt +0 -0
  128. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/attestation-v1.schema.json +0 -0
  129. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/check-batch-v1.schema.json +0 -0
  130. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/cleanup-v1.schema.json +0 -0
  131. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/comparison-v1.schema.json +0 -0
  132. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/execution-v1.schema.json +0 -0
  133. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/inspect-v1.schema.json +0 -0
  134. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/matrix-v1.schema.json +0 -0
  135. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/plan-v1.schema.json +0 -0
  136. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/profile-v1.schema.json +0 -0
  137. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/publication-v1.schema.json +0 -0
  138. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/schemas/verify-v1.schema.json +0 -0
  139. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/scripts/announcement_gate.py +0 -0
  140. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/scripts/lake_cache_gate.py +0 -0
  141. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/scripts/registry_preflight.py +0 -0
  142. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/scripts/run_compatibility.py +0 -0
  143. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/scripts/run_v1_case_study.py +0 -0
  144. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/scripts/smoke_wheel.py +0 -0
  145. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/setup.cfg +0 -0
  146. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/conftest.py +0 -0
  147. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/discovery/e2e/test_real_discovery.py +0 -0
  148. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/discovery/test_analyzer.py +0 -0
  149. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/discovery/test_catalog.py +0 -0
  150. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/discovery/test_catalog_build.py +0 -0
  151. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/discovery/test_discovery_schema_resources.py +0 -0
  152. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/discovery/test_engine.py +0 -0
  153. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/discovery/test_planner.py +0 -0
  154. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/discovery/test_policy.py +0 -0
  155. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_announcement_gate.py +0 -0
  156. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_backend.py +0 -0
  157. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_bundles.py +0 -0
  158. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_capsules.py +0 -0
  159. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_cli.py +0 -0
  160. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_console.py +0 -0
  161. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_diagnostics.py +0 -0
  162. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_events_health.py +0 -0
  163. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_facade.py +0 -0
  164. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_frontmatter.py +0 -0
  165. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_git.py +0 -0
  166. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_header_cache.py +0 -0
  167. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_identifier_resolver.py +0 -0
  168. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_interactive.py +0 -0
  169. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_lake_cache.py +0 -0
  170. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_lockfiles.py +0 -0
  171. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_locking.py +0 -0
  172. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_models.py +0 -0
  173. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_multifile.py +0 -0
  174. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_oci_protocol.py +0 -0
  175. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_packs.py +0 -0
  176. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_paths.py +0 -0
  177. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_prebuilt_policy.py +0 -0
  178. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_programs.py +0 -0
  179. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_project_publish.py +0 -0
  180. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_references.py +0 -0
  181. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_run_cli.py +0 -0
  182. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_runtime.py +0 -0
  183. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_schema_resources.py +0 -0
  184. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_schemas.py +0 -0
  185. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_signatures.py +0 -0
  186. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_specs.py +0 -0
  187. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_store.py +0 -0
  188. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_toolchain_oci.py +0 -0
  189. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_toolchain_slim.py +0 -0
  190. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_v1_precision.py +0 -0
  191. {lean_runtime-4.0.0 → lean_runtime-4.0.1}/tests/test_verification_inventory.py +0 -0
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 4.0.1 - 2026-08-18
6
+
7
+ - Keep `verify ENV --offline` strictly local for sparse environments by probing
8
+ a retained capsule module and forbidding projection acquisition during the
9
+ probe.
10
+ - Pin the selected exact toolchain before project scaffolding and put a reused
11
+ user toolchain ahead of private Elan for nested Lake commands, preventing
12
+ `new --core` from downloading an alternate unprefixed toolchain.
13
+
5
14
  ## 4.0.0 - 2026-08-18
6
15
 
7
16
  - Replace the implementation-shaped CLI with a cwd-first workflow: `new`,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lean-runtime
3
- Version: 4.0.0
3
+ Version: 4.0.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
@@ -194,6 +194,5 @@ interfaces for infrastructure code.
194
194
  - Logical Lean rejections exit 1; invalid/infrastructure invocations exit 2;
195
195
  publication failures retain their documented classified exit statuses.
196
196
 
197
- Documentation lives in [`docs/`](docs/index.md). Start with
198
- [`docs/getting-started.md`](docs/getting-started.md),
199
- [`docs/cli.md`](docs/cli.md), and [`docs/local-projects.md`](docs/local-projects.md).
197
+ Documentation lives at
198
+ [alerad.github.io/lean-runtime](https://alerad.github.io/lean-runtime/).
@@ -158,6 +158,5 @@ interfaces for infrastructure code.
158
158
  - Logical Lean rejections exit 1; invalid/infrastructure invocations exit 2;
159
159
  publication failures retain their documented classified exit statuses.
160
160
 
161
- Documentation lives in [`docs/`](docs/index.md). Start with
162
- [`docs/getting-started.md`](docs/getting-started.md),
163
- [`docs/cli.md`](docs/cli.md), and [`docs/local-projects.md`](docs/local-projects.md).
161
+ Documentation lives at
162
+ [alerad.github.io/lean-runtime](https://alerad.github.io/lean-runtime/).
@@ -0,0 +1,132 @@
1
+ # Installation and first check
2
+
3
+ This guide takes you from an empty Python environment to a checked Lean proof.
4
+ Choose the path that matches what you already have; Lean Runtime infers the
5
+ rest from the current directory and the source itself.
6
+
7
+ ## Requirements
8
+
9
+ - Python 3.10 or newer;
10
+ - Git on `PATH`;
11
+ - Linux or macOS.
12
+
13
+ An existing Elan installation is useful but not required. When the exact
14
+ toolchain is already present, Lean Runtime uses its binaries read-only. Missing
15
+ toolchains are kept in Lean Runtime's private store.
16
+
17
+ ## Install
18
+
19
+ Installing in a virtual environment keeps the command isolated from unrelated
20
+ Python tools:
21
+
22
+ ```bash
23
+ python -m venv .venv
24
+ source .venv/bin/activate
25
+ python -m pip install --upgrade pip
26
+ python -m pip install lean-runtime
27
+ lean-runtime --version
28
+ ```
29
+
30
+ The installed wheel provides one executable: `lean-runtime`.
31
+
32
+ ## Choose your first workflow
33
+
34
+ === "Standalone file"
35
+
36
+ Create `Main.lean`:
37
+
38
+ ```lean
39
+ import Mathlib.Data.Nat.Prime.Basic
40
+
41
+ example : Nat.Prime 5 := by decide
42
+ ```
43
+
44
+ Check it:
45
+
46
+ ```bash
47
+ lean-runtime check Main.lean
48
+ ```
49
+
50
+ Outside a Lake project, Lean Runtime analyzes the imports, selects an exact
51
+ catalog environment, and acquires the required verified import closure. The
52
+ second check reuses that environment.
53
+
54
+ === "New project"
55
+
56
+ ```bash
57
+ lean-runtime new MyProof
58
+ cd MyProof
59
+ lean-runtime check
60
+ lean-runtime build
61
+ ```
62
+
63
+ `new` selects a stable cataloged Mathlib/toolchain pair, writes exact Lake
64
+ metadata, and prepares reusable dependencies. Mutating commands show their
65
+ plan before acting; use `--yes` only for non-interactive automation.
66
+
67
+ === "Existing Lake project"
68
+
69
+ ```bash
70
+ cd ExistingProject
71
+ lean-runtime check
72
+ lean-runtime adopt
73
+ ```
74
+
75
+ Checking works before adoption. `adopt` is an optional storage optimization:
76
+ it verifies the pinned manifest and current dependency checkouts, previews
77
+ reuse and recovery, probes a shared graph, and swaps it atomically. It does
78
+ not update `lean-toolchain` or `lake-manifest.json`.
79
+
80
+ === "Python"
81
+
82
+ ```python
83
+ import lean_runtime as lean
84
+
85
+ env = lean.setup(deps=["mathlib@v4.33.0"])
86
+ result = env.check("import Mathlib.Data.Nat.Prime.Basic\nexample : Nat.Prime 5 := by decide\n")
87
+ result.raise_for_error()
88
+ print(result.execution_id)
89
+ ```
90
+
91
+ Keep the returned environment and call it repeatedly; setup and acquired
92
+ artifacts are reused.
93
+
94
+ ## Understand what happened
95
+
96
+ ```bash
97
+ lean-runtime status Main.lean
98
+ lean-runtime storage usage
99
+ lean-runtime doctor
100
+ ```
101
+
102
+ `status` explains context selection, `storage usage` reports retained content,
103
+ and `doctor` checks Git, disk, store health, toolchains, staging areas, and
104
+ abandoned workspaces.
105
+
106
+ For a standalone check, save the exact selected context when you want a durable
107
+ artifact:
108
+
109
+ ```bash
110
+ lean-runtime check Main.lean --lock-out environment.lock.json
111
+ lean-runtime check Main.lean --using environment.lock.json --offline
112
+ ```
113
+
114
+ `--offline` is fail-closed: missing toolchains, environments, or sparse import
115
+ closures produce an error instead of a network request.
116
+
117
+ ## Where to go next
118
+
119
+ - [Standalone files](standalone-files.md) — frontmatter, explicit context, watch,
120
+ and matrix checks.
121
+ - [Lake projects](local-projects.md) — focused checking, adoption, shared
122
+ dependencies, and updates.
123
+ - [Python API](python-api.md) — batch, async, cancellation, multi-file, and
124
+ interactive use.
125
+ - [Trust and limitations](trust-and-limitations.md) — the exact integrity and
126
+ execution boundary.
127
+
128
+ ??? question "Something failed on the first run?"
129
+
130
+ Run `lean-runtime doctor`, then repeat with `--verbose`. A completed Lean
131
+ rejection exits 1; an invalid invocation or infrastructure failure exits 2.
132
+ The [CLI reference](cli.md#exit-status) lists all public exit classes.
@@ -0,0 +1,150 @@
1
+ ---
2
+ hide:
3
+ - navigation
4
+ - toc
5
+ ---
6
+
7
+ <div class="lr-hero" markdown>
8
+
9
+ <span class="lr-eyebrow">LEAN 4 ENVIRONMENTS, WITHOUT THE BUSYWORK</span>
10
+
11
+ # Check the proof. Reuse everything else.
12
+
13
+ Lean Runtime gives standalone files, Lake projects, and Python programs one
14
+ exact, cache-aware way to run Lean. It discovers the right context, reuses
15
+ compatible toolchains and dependencies, and records precisely what ran.
16
+
17
+ [Get started](getting-started.md){ .md-button .md-button--primary }
18
+ [Explore the CLI](cli.md){ .md-button }
19
+
20
+ ```bash
21
+ python -m pip install lean-runtime
22
+ lean-runtime check Main.lean
23
+ ```
24
+
25
+ </div>
26
+
27
+ <div class="lr-proof-line" markdown>
28
+
29
+ **One command** · **Exact dependency graphs** · **Warm and offline reuse** ·
30
+ **Structured provenance**
31
+
32
+ </div>
33
+
34
+ ## Start from where you are
35
+
36
+ <div class="grid cards" markdown>
37
+
38
+ - :material-file-code-outline:{ .lg .middle } **I have a Lean file**
39
+
40
+ ---
41
+
42
+ Let imports describe the environment. Lean Runtime discovers an exact
43
+ compatible Mathlib release, acquires only the required capsule closure,
44
+ and keeps diagnostics on your original filename.
45
+
46
+ [`lean-runtime check Main.lean` →](standalone-files.md)
47
+
48
+ - :material-folder-cog-outline:{ .lg .middle } **I have a Lake project**
49
+
50
+ ---
51
+
52
+ Work in the current directory. Keep the existing toolchain and manifest;
53
+ optionally adopt shared dependency storage without changing revisions.
54
+
55
+ [`lean-runtime check` →](local-projects.md)
56
+
57
+ - :material-creation-outline:{ .lg .middle } **I want a new project**
58
+
59
+ ---
60
+
61
+ Create a catalog-pinned project with exact Lake metadata and a reusable
62
+ dependency graph, then check it immediately.
63
+
64
+ [`lean-runtime new MyProof` →](getting-started.md#new-project)
65
+
66
+ - :material-language-python:{ .lg .middle } **I am calling Lean from Python**
67
+
68
+ ---
69
+
70
+ Prepare once, check many sources, run batches concurrently, and retain
71
+ typed diagnostics, cancellation, identities, and provenance.
72
+
73
+ [`lean.setup(...)` →](python-api.md)
74
+
75
+ </div>
76
+
77
+ ## A small daily interface
78
+
79
+ ```text
80
+ new NAME create a project
81
+ adopt [PATH] share exact dependencies from existing projects
82
+ check [PATH…] check a project, directory, source file, or stdin
83
+ watch FILE re-check on save
84
+ build [TARGET] build the current project
85
+ update preview and apply a transactional dependency update
86
+ status [PATH] explain what Lean Runtime selected
87
+ ```
88
+
89
+ Project commands default to the current directory. `check` uses the nearest
90
+ pinned Lake project when one exists and performs bounded exact-environment
91
+ discovery otherwise. Advanced storage and publication machinery stays under
92
+ noun namespaces such as `env`, `project`, `program`, and `toolchain`.
93
+
94
+ [Command-line reference](cli.md){ .md-button }
95
+
96
+ ## Exact when it matters
97
+
98
+ <div class="lr-pipeline" markdown>
99
+
100
+ ```text
101
+ source or project
102
+ │
103
+ ▼
104
+ context discovery ──► exact lock ──► verified environment
105
+ │
106
+ ▼
107
+ Lean execution
108
+ │
109
+ ▼
110
+ result + diagnostics + provenance
111
+ ```
112
+
113
+ </div>
114
+
115
+ Lean Runtime treats identity and lifecycle as product features:
116
+
117
+ - package tags resolve to full Git commits and tree hashes;
118
+ - locks and environments have canonical content-derived identities;
119
+ - sparse capsules verify manifests, frame digests, and projected artifacts;
120
+ - identical requests share a request digest while each attempt gets a unique
121
+ execution ID;
122
+ - acquisition, project sharing, and updates stage and probe before publication;
123
+ - compatible user Elan toolchains are reused read-only.
124
+
125
+ [How environments work](environments.md){ .md-button }
126
+ [Architecture](architecture.md){ .md-button }
127
+
128
+ !!! warning "Trusted execution, not a sandbox"
129
+
130
+ Lean packages and Lake configuration can execute native programs and build
131
+ commands. Lean Runtime verifies identities and artifacts, but its local
132
+ backend is intended for trusted inputs. Read the
133
+ [trust boundary](trust-and-limitations.md) before running third-party locks
134
+ or packages.
135
+
136
+ ## Go deeper
137
+
138
+ <div class="grid cards" markdown>
139
+
140
+ - **Portable environments** — export complete copies or acquire source-free
141
+ sparse capsules from OCI libraries. [Read the guide →](portable-copies.md)
142
+ - **Verification and replay** — inspect exact identities, capture executions,
143
+ compare environments, and replay requests. [Verification →](v1-precision.md)
144
+ - **Publishing** — generate a multi-platform GitHub workflow with isolated
145
+ capsule probes, signatures, and clean-consumer checks.
146
+ [Publishing guide →](project-publishing.md)
147
+ - **Python automation** — use synchronous, async, batch, multi-file, matrix,
148
+ interactive, and cancellation APIs. [Python reference →](python-api.md)
149
+
150
+ </div>
@@ -530,6 +530,7 @@ class Environment:
530
530
  filename: str = "Main.lean",
531
531
  policy: ExecutionPolicy | None = None,
532
532
  cancel: threading.Event | None = None,
533
+ _allow_sparse_acquisition: bool = True,
533
534
  ) -> ExecutionResult:
534
535
  safe_filename = Path(filename).name
535
536
  if not safe_filename.endswith(".lean"):
@@ -539,6 +540,7 @@ class Environment:
539
540
  entrypoint=safe_filename,
540
541
  policy=policy,
541
542
  cancel=cancel,
543
+ _allow_sparse_acquisition=_allow_sparse_acquisition,
542
544
  )
543
545
 
544
546
  def check_files(
@@ -548,6 +550,7 @@ class Environment:
548
550
  entrypoint: str = "Main.lean",
549
551
  policy: ExecutionPolicy | None = None,
550
552
  cancel: threading.Event | None = None,
553
+ _allow_sparse_acquisition: bool = True,
551
554
  ) -> ExecutionResult:
552
555
  """Check a safe relative tree of Lean files through one entrypoint."""
553
556
  normalized = _source_files(files)
@@ -559,7 +562,12 @@ class Environment:
559
562
  module for source in normalized.values() for module in source_import_roots(source)
560
563
  )
561
564
  )
562
- self.manager.ensure_sparse_modules(self.lock, roots, frozenset({"check"}))
565
+ self.manager.ensure_sparse_modules(
566
+ self.lock,
567
+ roots,
568
+ frozenset({"check"}),
569
+ allow_acquisition=_allow_sparse_acquisition,
570
+ )
563
571
  return self._execute_in_instance(
564
572
  operation="check",
565
573
  files=normalized,
@@ -1112,6 +1120,8 @@ class EnvironmentManager:
1112
1120
  lock: EnvironmentLock,
1113
1121
  roots: tuple[str, ...],
1114
1122
  capabilities: frozenset[str],
1123
+ *,
1124
+ allow_acquisition: bool = True,
1115
1125
  ) -> None:
1116
1126
  """Extend a sparse projection before checking a new import closure."""
1117
1127
  environment_id = environment_identity(lock)
@@ -1130,6 +1140,11 @@ class EnvironmentManager:
1130
1140
  for artifact in required
1131
1141
  ):
1132
1142
  return
1143
+ if not allow_acquisition:
1144
+ raise EnvironmentError(
1145
+ "the retained sparse projection is missing artifacts required by this "
1146
+ "operation; offline verification does not permit acquisition"
1147
+ )
1133
1148
  if self.sparse_acquirer is None:
1134
1149
  raise EnvironmentError("sparse environment has no configured acquisition source")
1135
1150
  self.sparse_acquirer(lock, roots, capabilities)
@@ -1909,6 +1909,11 @@ class Runtime:
1909
1909
  published_entries: list[Path] = []
1910
1910
  modified_existing: dict[Path, bytes] = {}
1911
1911
  try:
1912
+ # Lake chooses its own release channel during `lake init` when the
1913
+ # destination has no pin. Publish the already-selected exact pin
1914
+ # before invoking it so nested Lake/Elan calls cannot select or
1915
+ # install a spelling different from the one the plan verified.
1916
+ (staging / "lean-toolchain").write_text(plan.toolchain + "\n", encoding="utf-8")
1912
1917
  custom_agents = target / "AGENTS.md"
1913
1918
  if custom_agents.is_file():
1914
1919
  (staging / "AGENTS.md").write_bytes(custom_agents.read_bytes())
@@ -1921,10 +1926,16 @@ class Runtime:
1921
1926
  plan.project_name or target.name,
1922
1927
  "lib",
1923
1928
  )
1929
+ environment_for = getattr(self.toolchains, "environment_for", None)
1930
+ command_environment = (
1931
+ environment_for(plan.toolchain)
1932
+ if callable(environment_for)
1933
+ else self.toolchains.environment
1934
+ )
1924
1935
  process = subprocess.run(
1925
1936
  command,
1926
1937
  cwd=staging,
1927
- env=self.toolchains.environment,
1938
+ env=command_environment,
1928
1939
  text=True,
1929
1940
  stdout=subprocess.PIPE,
1930
1941
  stderr=subprocess.STDOUT,
@@ -1935,6 +1946,7 @@ class Runtime:
1935
1946
  raise ProjectError(
1936
1947
  "Lake could not initialize the project" + (f":\n{detail}" if detail else "")
1937
1948
  )
1949
+ (staging / "lean-toolchain").write_text(plan.toolchain + "\n", encoding="utf-8")
1938
1950
  for existing in existing_entries:
1939
1951
  if existing.name in {".git", "AGENTS.md"}:
1940
1952
  continue
@@ -1962,7 +1974,7 @@ class Runtime:
1962
1974
  updated = subprocess.run(
1963
1975
  update_command,
1964
1976
  cwd=staging,
1965
- env=self.toolchains.environment,
1977
+ env=command_environment,
1966
1978
  text=True,
1967
1979
  stdout=subprocess.PIPE,
1968
1980
  stderr=subprocess.STDOUT,
@@ -92,6 +92,20 @@ class ToolchainManager:
92
92
  env["PATH"] = os.pathsep.join((str(elan_home / "bin"), env.get("PATH", "")))
93
93
  return env
94
94
 
95
+ def environment_for(self, toolchain: str) -> dict[str, str]:
96
+ """Return an environment whose nested tools use the selected full toolchain.
97
+
98
+ A directly invoked user Lake can spawn ``lake`` or ``lean`` again while
99
+ scaffolding. Put that already-verified toolchain ahead of private Elan
100
+ so those nested calls cannot bootstrap a differently spelled release.
101
+ """
102
+ env = self.environment
103
+ name = normalize_toolchain(toolchain)
104
+ full = self._full_toolchain_dir(name)
105
+ if (full / "bin" / "lean").is_file():
106
+ env["PATH"] = os.pathsep.join((str(full / "bin"), env.get("PATH", "")))
107
+ return env
108
+
95
109
  def elan_path(self, *, bootstrap: bool = True) -> Path:
96
110
  override = os.environ.get("LEAN_RUNTIME_ELAN")
97
111
  if override:
@@ -104,12 +104,20 @@ def _verify_capsule_state(environment: Environment) -> int:
104
104
  return verified
105
105
 
106
106
 
107
- def _probe(environment: Environment) -> None:
107
+ def _probe(environment: Environment, *, offline: bool = False) -> None:
108
108
  """Probe the immutable compiled environment without asking Lake to resolve it."""
109
109
 
110
- source = (
111
- f"import {ROOT_MODULE}\n" if environment.lock.packages else "example : True := by trivial\n"
112
- )
110
+ if environment.sparse:
111
+ origin = environment._record.get("origin")
112
+ retained = origin.get("modules") if isinstance(origin, dict) else None
113
+ modules = tuple(str(item) for item in retained) if isinstance(retained, list) else ()
114
+ source = f"import {modules[0]}\n" if modules else "example : True := by trivial\n"
115
+ else:
116
+ source = (
117
+ f"import {ROOT_MODULE}\n"
118
+ if environment.lock.packages
119
+ else "example : True := by trivial\n"
120
+ )
113
121
  result = environment.check(
114
122
  source,
115
123
  # The generated environment module itself is named ROOT_MODULE. Giving
@@ -117,6 +125,7 @@ def _probe(environment: Environment) -> None:
117
125
  # correctly reject it as an import cycle.
118
126
  filename="LeanRuntimeVerification.lean",
119
127
  policy=ExecutionPolicy(timeout_seconds=300, max_output_bytes=2_000_000),
128
+ _allow_sparse_acquisition=not offline,
120
129
  )
121
130
  if not result.ok:
122
131
  raise EnvironmentError(
@@ -284,7 +293,7 @@ def verify_environment(
284
293
  raise EnvironmentError(
285
294
  "offline verification requires the locked toolchain to be installed"
286
295
  )
287
- _probe(environment)
296
+ _probe(environment, offline=offline)
288
297
  probe = VerificationCheck("lean_probe_passed", True)
289
298
  except EnvironmentError as exc:
290
299
  probe = VerificationCheck("probe_failed", False, details={"message": str(exc)})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lean-runtime
3
- Version: 4.0.0
3
+ Version: 4.0.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
@@ -194,6 +194,5 @@ interfaces for infrastructure code.
194
194
  - Logical Lean rejections exit 1; invalid/infrastructure invocations exit 2;
195
195
  publication failures retain their documented classified exit statuses.
196
196
 
197
- Documentation lives in [`docs/`](docs/index.md). Start with
198
- [`docs/getting-started.md`](docs/getting-started.md),
199
- [`docs/cli.md`](docs/cli.md), and [`docs/local-projects.md`](docs/local-projects.md).
197
+ Documentation lives at
198
+ [alerad.github.io/lean-runtime](https://alerad.github.io/lean-runtime/).
@@ -7,10 +7,21 @@ copyright: Copyright © Alejandro Radisic
7
7
 
8
8
  theme:
9
9
  name: material
10
+ language: en
11
+ icon:
12
+ repo: fontawesome/brands/github
10
13
  features:
14
+ - navigation.instant
15
+ - navigation.tracking
16
+ - navigation.tabs
17
+ - navigation.tabs.sticky
11
18
  - content.code.copy
19
+ - content.code.annotate
12
20
  - navigation.sections
13
21
  - navigation.top
22
+ - search.highlight
23
+ - search.suggest
24
+ - toc.follow
14
25
  palette:
15
26
  - media: "(prefers-color-scheme: light)"
16
27
  scheme: default
@@ -28,33 +39,55 @@ theme:
28
39
  name: Use light mode
29
40
 
30
41
  nav:
31
- - Overview: index.md
32
- - Getting started: getting-started.md
33
- - Guides:
42
+ - Home: index.md
43
+ - Start here:
44
+ - Installation and first check: getting-started.md
34
45
  - Standalone Lean files: standalone-files.md
35
- - Environments: environments.md
36
- - Lake projects and shared dependencies: local-projects.md
46
+ - New and existing Lake projects: local-projects.md
47
+ - Workflows:
48
+ - Exact environments: environments.md
37
49
  - Portable copies and libraries: portable-copies.md
38
50
  - Publishing a Lean project: project-publishing.md
39
51
  - Ready-to-run programs: ready-programs.md
52
+ - Reference:
53
+ - Command line: cli.md
40
54
  - Python API: python-api.md
41
- - CLI: cli.md
42
55
  - Execution captures: captures.md
43
56
  - Verify, compare, profile, and matrix: v1-precision.md
44
- - V1 release case study: case-study-v1.md
45
57
  - Concepts:
46
58
  - Architecture: architecture.md
47
- - Lake artifact-cache design: lake-artifact-cache-design.md
48
59
  - Trust and limitations: trust-and-limitations.md
49
- - Development: development.md
60
+ - Lake artifact-cache design: lake-artifact-cache-design.md
61
+ - Project:
62
+ - Release case study: case-study-v1.md
63
+ - Development: development.md
64
+
65
+ plugins:
66
+ - search
67
+
68
+ extra_css:
69
+ - stylesheets/extra.css
70
+
71
+ extra:
72
+ social:
73
+ - icon: fontawesome/brands/github
74
+ link: https://github.com/alerad/lean-runtime
75
+ name: Lean Runtime on GitHub
50
76
 
51
77
  markdown_extensions:
52
78
  - admonition
53
79
  - attr_list
80
+ - md_in_html
54
81
  - pymdownx.highlight:
55
82
  anchor_linenums: true
83
+ - pymdownx.details
84
+ - pymdownx.emoji:
85
+ emoji_index: !!python/name:material.extensions.emoji.twemoji
86
+ emoji_generator: !!python/name:material.extensions.emoji.to_svg
56
87
  - pymdownx.inlinehilite
57
88
  - pymdownx.superfences
89
+ - pymdownx.tabbed:
90
+ alternate_style: true
58
91
  - toc:
59
92
  permalink: true
60
93
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "lean-runtime"
7
- version = "4.0.0"
7
+ version = "4.0.1"
8
8
  description = "Run Lean 4 proofs from Python or standalone files"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -309,6 +309,13 @@ def test_resolve_publish_and_reopen_offline_from_second_process(
309
309
  imported_check = imported.check(source)
310
310
  assert imported_check.ok
311
311
  assert imported_check.lock_id == lock.lock_id
312
+ # Offline verification must use only the retained projection. The fixture
313
+ # registry has stopped here, so any attempted sparse extension fails.
314
+ imported_verification = imported_runtime.verify("imported", offline=True)
315
+ assert imported_verification.ok
316
+ assert any(
317
+ item.code == "offline_retained_state_verified" for item in imported_verification.checks
318
+ )
312
319
  assert (runtime.store.executions / f"{first.execution_id}.json").is_file()
313
320
  assert (runtime.store.executions / f"{repeated.execution_id}.json").is_file()
314
321
  version = environment.execute(["lean", "--version"])
@@ -69,6 +69,7 @@ class InitProjectToolchains(ProjectToolchains):
69
69
  )
70
70
  script = (
71
71
  "import pathlib,sys; root=pathlib.Path(sys.argv[1]); name=sys.argv[3]; "
72
+ "assert (root/'lean-toolchain').read_text().strip()==sys.argv[2]; "
72
73
  "(root/'lean-toolchain').write_text(sys.argv[2]+'\\n'); "
73
74
  "(root/'lakefile.toml').write_text(f'name = \\\"{name}\\\"\\n'); "
74
75
  "(root/'.git').mkdir(); "
@@ -112,6 +112,9 @@ def test_existing_user_elan_toolchain_is_reused_read_only(
112
112
  str(directory / "lean"),
113
113
  "--version",
114
114
  ]
115
+ execution_path = manager.environment_for(toolchain)["PATH"].split(os.pathsep)
116
+ assert execution_path[0] == str(directory)
117
+ assert execution_path[1] == str(manager.elan_home / "bin")
115
118
  monkeypatch.setattr(manager, "has_slim", lambda _name: True)
116
119
  with pytest.raises(ToolchainError, match="user-managed"):
117
120
  manager.prune_original(toolchain)