lean-runtime 2.4.0__tar.gz → 2.6.0__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 (174) hide show
  1. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/CHANGELOG.md +70 -0
  2. {lean_runtime-2.4.0/lean_runtime.egg-info → lean_runtime-2.6.0}/PKG-INFO +53 -6
  3. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/README.md +51 -5
  4. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/architecture.md +23 -0
  5. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/cli.md +47 -7
  6. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/environments.md +14 -0
  7. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/getting-started.md +53 -1
  8. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/index.md +7 -4
  9. lean_runtime-2.6.0/docs/local-projects.md +189 -0
  10. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/portable-copies.md +22 -6
  11. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/project-publishing.md +13 -8
  12. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/python-api.md +22 -3
  13. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/trust-and-limitations.md +17 -5
  14. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/__init__.py +20 -0
  15. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/bundles.py +517 -1
  16. lean_runtime-2.6.0/lean_runtime/capsules.py +530 -0
  17. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/cli.py +344 -11
  18. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/api.py +3 -3
  19. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/probe.py +2 -0
  20. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/environments.py +145 -22
  21. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/models.py +1 -0
  22. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/oci.py +444 -5
  23. lean_runtime-2.6.0/lean_runtime/packs.py +380 -0
  24. lean_runtime-2.6.0/lean_runtime/project_sharing.py +627 -0
  25. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/projects.py +49 -2
  26. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/resolver.py +36 -0
  27. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/run_cli.py +28 -9
  28. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/runtime.py +972 -27
  29. lean_runtime-2.6.0/lean_runtime/shared_projects.py +886 -0
  30. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/store.py +89 -1
  31. lean_runtime-2.6.0/lean_runtime/toolchain_oci.py +498 -0
  32. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/toolchain_slim.py +55 -18
  33. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/toolchains.py +7 -1
  34. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/verification.py +55 -6
  35. {lean_runtime-2.4.0 → lean_runtime-2.6.0/lean_runtime.egg-info}/PKG-INFO +53 -6
  36. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime.egg-info/SOURCES.txt +8 -0
  37. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime.egg-info/requires.txt +1 -0
  38. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/mkdocs.yml +1 -1
  39. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/pyproject.toml +2 -2
  40. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/scripts/announcement_gate.py +117 -16
  41. lean_runtime-2.6.0/scripts/registry_preflight.py +184 -0
  42. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/scripts/smoke_wheel.py +1 -1
  43. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/discovery/test_engine.py +4 -2
  44. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_bundles.py +262 -1
  45. lean_runtime-2.6.0/tests/test_capsules.py +250 -0
  46. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_cli.py +76 -0
  47. lean_runtime-2.6.0/tests/test_packs.py +82 -0
  48. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_project_publish.py +1 -1
  49. lean_runtime-2.6.0/tests/test_projects.py +932 -0
  50. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_run_cli.py +5 -4
  51. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_runtime.py +22 -0
  52. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_store.py +36 -1
  53. lean_runtime-2.6.0/tests/test_toolchain_oci.py +86 -0
  54. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_toolchain_slim.py +28 -3
  55. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_verification_probe.py +41 -2
  56. lean_runtime-2.4.0/docs/local-projects.md +0 -58
  57. lean_runtime-2.4.0/scripts/registry_preflight.py +0 -156
  58. lean_runtime-2.4.0/tests/test_projects.py +0 -162
  59. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/LICENSE +0 -0
  60. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/MANIFEST.in +0 -0
  61. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/catalog/environments.toml +0 -0
  62. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/catalog/locks/core-v4.32.2.lock.json +0 -0
  63. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/catalog/locks/leancert-v4.30.0.5.lock.json +0 -0
  64. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/catalog/locks/leancert-v4.31.0.lock.json +0 -0
  65. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/catalog/locks/leancert-v4.32.2.4.lock.json +0 -0
  66. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/catalog/locks/leancert-v4.33.0.lock.json +0 -0
  67. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/catalog/locks/mathlib-v4.30.0.lock.json +0 -0
  68. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/catalog/locks/mathlib-v4.31.0.lock.json +0 -0
  69. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/catalog/locks/mathlib-v4.32.2.lock.json +0 -0
  70. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/catalog/locks/mathlib-v4.33.0.lock.json +0 -0
  71. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/compatibility/README.md +0 -0
  72. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/compatibility/mathlib-4.32.2.json +0 -0
  73. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/compatibility/mathlib-4.32.2.toml +0 -0
  74. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/compatibility/mathlib-4.33.0.json +0 -0
  75. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/compatibility/mathlib-4.33.0.toml +0 -0
  76. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/captures.md +0 -0
  77. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/case-study-v1.md +0 -0
  78. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/development.md +0 -0
  79. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/ready-programs.md +0 -0
  80. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/standalone-files.md +0 -0
  81. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/docs/v1-precision.md +0 -0
  82. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/examples/mathlib.toml +0 -0
  83. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/__main__.py +0 -0
  84. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/_git.py +0 -0
  85. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/_paths.py +0 -0
  86. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/backends.py +0 -0
  87. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/comparison.py +0 -0
  88. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/console.py +0 -0
  89. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/decisions.py +0 -0
  90. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/diagnostics.py +0 -0
  91. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/__init__.py +0 -0
  92. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/analyzer.py +0 -0
  93. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/candidate.py +0 -0
  94. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/catalog.py +0 -0
  95. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/catalog_build.py +0 -0
  96. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/catalog_cli.py +0 -0
  97. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/catalog_manifest.py +0 -0
  98. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/data/catalog.json +0 -0
  99. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/defaults.py +0 -0
  100. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/engine.py +0 -0
  101. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/errors.py +0 -0
  102. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/module_inventory.py +0 -0
  103. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/planner.py +0 -0
  104. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/policy.py +0 -0
  105. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/py.typed +0 -0
  106. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/result.py +0 -0
  107. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/schema_resources.py +0 -0
  108. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/schemas/catalog-v1.schema.json +0 -0
  109. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/schemas/plan-v1.schema.json +0 -0
  110. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/discovery/schemas/result-v1.schema.json +0 -0
  111. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/errors.py +0 -0
  112. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/events.py +0 -0
  113. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/facade.py +0 -0
  114. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/frontmatter.py +0 -0
  115. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/health.py +0 -0
  116. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/lake.py +0 -0
  117. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/lockfiles.py +0 -0
  118. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/locking.py +0 -0
  119. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/matrix.py +0 -0
  120. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/policies.py +0 -0
  121. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/profiling.py +0 -0
  122. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/programs.py +0 -0
  123. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/publisher_verification.py +0 -0
  124. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/py.typed +0 -0
  125. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/references.py +0 -0
  126. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/schema_resources.py +0 -0
  127. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/serialization.py +0 -0
  128. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/specs.py +0 -0
  129. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/timings.py +0 -0
  130. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime/wire.py +0 -0
  131. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime.egg-info/dependency_links.txt +0 -0
  132. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime.egg-info/entry_points.txt +0 -0
  133. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/lean_runtime.egg-info/top_level.txt +0 -0
  134. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/schemas/cleanup-v1.schema.json +0 -0
  135. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/schemas/comparison-v1.schema.json +0 -0
  136. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/schemas/execution-v1.schema.json +0 -0
  137. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/schemas/inspect-v1.schema.json +0 -0
  138. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/schemas/matrix-v1.schema.json +0 -0
  139. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/schemas/profile-v1.schema.json +0 -0
  140. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/schemas/verify-v1.schema.json +0 -0
  141. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/scripts/run_compatibility.py +0 -0
  142. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/scripts/run_v1_case_study.py +0 -0
  143. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/setup.cfg +0 -0
  144. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/conftest.py +0 -0
  145. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/discovery/e2e/test_real_discovery.py +0 -0
  146. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/discovery/test_analyzer.py +0 -0
  147. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/discovery/test_catalog.py +0 -0
  148. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/discovery/test_catalog_build.py +0 -0
  149. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/discovery/test_discovery_schema_resources.py +0 -0
  150. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/discovery/test_planner.py +0 -0
  151. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/discovery/test_policy.py +0 -0
  152. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_backend.py +0 -0
  153. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_console.py +0 -0
  154. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_diagnostics.py +0 -0
  155. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_environment_integration.py +0 -0
  156. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_events_health.py +0 -0
  157. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_facade.py +0 -0
  158. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_frontmatter.py +0 -0
  159. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_git.py +0 -0
  160. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_interactive.py +0 -0
  161. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_lockfiles.py +0 -0
  162. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_models.py +0 -0
  163. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_multifile.py +0 -0
  164. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_paths.py +0 -0
  165. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_prebuilt_policy.py +0 -0
  166. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_programs.py +0 -0
  167. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_references.py +0 -0
  168. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_schema_resources.py +0 -0
  169. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_schemas.py +0 -0
  170. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_signatures.py +0 -0
  171. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_specs.py +0 -0
  172. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_toolchains.py +0 -0
  173. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_v1_precision.py +0 -0
  174. {lean_runtime-2.4.0 → lean_runtime-2.6.0}/tests/test_verification_inventory.py +0 -0
@@ -2,6 +2,76 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 2.6.0 - 2026-08-14
6
+
7
+ - Make the local-project path a four-command workflow: `init`, `check`,
8
+ `build`, and `update`. New projects use the newest stable cataloged Mathlib
9
+ by default; `--core` opts out, while `--mathlib VERSION` selects a release.
10
+ - Make `init` adopt an existing pinned Lake project without changing its graph,
11
+ or create a new project transactionally after its exact dependencies are
12
+ ready. `--plan`, `--offline`, `--max-download`, and `--seed-from` expose its
13
+ acquisition policy, and failed initialization leaves no partial project.
14
+ - Add persistent discovery of exact local Lake graphs. `scan` registers existing
15
+ projects as zero-download seeds for future initialization and updates.
16
+ - Preserve verified sparse-capsule build artifacts when materializing exact Git
17
+ sources for a mutable project, instead of throwing them away and forcing a
18
+ dependency rebuild.
19
+ - Add explicit, transactional `update` to the newest cataloged Mathlib, with an
20
+ old/new revision and toolchain preview and rollback after failed adoption.
21
+ - Include exact package revisions, Git tree hashes, and the shared workspace ID
22
+ in mutable-project check and build provenance.
23
+
24
+ ## 2.5.0 - 2026-08-14
25
+
26
+ - Make `lean-runtime init` create a concise `AGENTS.md` with build, checking,
27
+ and shared-dependency safety instructions by default. `--no-agents` opts out,
28
+ and existing guides are preserved.
29
+ - Make `scripts/release.sh` provision an isolated release environment and allow
30
+ safe retries after a pre-tag failure instead of depending on undeclared
31
+ packages in the invoking Python environment.
32
+
33
+ - Add shared Lake project onboarding and migration. `lean-runtime init` creates
34
+ a standard core or cataloged-Mathlib project; `attach` previews or
35
+ transactionally adopts one project or an entire recursive tree; and `detach`
36
+ materializes independent copies again. Adoption preserves root build output,
37
+ rejects dirty or mismatched dependencies, verifies both generated overrides
38
+ and ordinary Lake package links, and rolls back failed swaps. Attached
39
+ projects automatically use shared mode in `lean-runtime build`.
40
+ - Add content-addressed Lake dependency workspaces. Each exact package is reused
41
+ across root manifests when its effective transitive closure, toolchain, and
42
+ platform match. Concurrent runtime builds are serialized, existing clean
43
+ artifacts seed the store with copy-on-write clones, and local Git object
44
+ databases seed other revisions without another network clone. Plain
45
+ `build --shared` never modifies the checkout; only explicit
46
+ `attach --execute` removes verified generated duplicates.
47
+
48
+ - Add versioned check capsules: publisher-built manifests record every retained
49
+ module facet, exact import edges, content digest, package owner, and
50
+ capability. Publication now fails unless the full environment and a
51
+ physically isolated capsule both accept the locked public import.
52
+ - Replace monolithic environment pulls with deterministic seekable zstd packs.
53
+ A clean check downloads only the pack frames covering its transitive import
54
+ closure; verified raw artifacts are shared in a cross-environment CAS and
55
+ projected atomically. `lean-run --plan` reports closure and check-runtime
56
+ costs before transfer, and `--max-download` gates their combined known cost.
57
+ - Publish independently verified check-only Lean toolchains through the same
58
+ multi-platform OCI library. Consumers prefer the slim signed runtime before
59
+ installing the full official toolchain, while retaining an Elan fallback for
60
+ libraries that have not published the new artifact yet.
61
+ - Add explicit sparse capabilities. Batch checking includes every olean facet
62
+ and IR file Lean actually requires; editor indexes are acquired only when
63
+ requested. Native/development requests fail with an actionable full-build
64
+ requirement instead of pretending that a check capsule supports them.
65
+ - Make project export source-free and closure-scoped. `project export` now
66
+ creates a portable sparse capsule, and `open-copy` verifies its OCI digest
67
+ chain, per-artifact CAS hashes, exact lock/platform identity, and Lean probe
68
+ before publishing it locally.
69
+ - Include shared sparse artifacts in `lean-runtime storage` and safely reclaim
70
+ old unleased CAS entries with `clean --include-downloads`.
71
+ - Make releases tag-driven and fail closed: the helper waits for CI on the exact
72
+ release commit; the tag workflow independently checks version, changelog,
73
+ tests, docs, wheel metadata, and wheel installation; PyPI must succeed before
74
+ the GitHub release is created.
5
75
  - Extend the bundled catalog through Mathlib v4.33.0 and add exact LeanCert
6
76
  environments for the supported Lean 4.30, 4.31, 4.32, and 4.33 lines.
7
77
  Otherwise-equivalent discovery candidates now prefer the smallest exact
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lean-runtime
3
- Version: 2.4.0
3
+ Version: 2.6.0
4
4
  Summary: Run Lean 4 proofs from Python or standalone files
5
5
  Author: Alejandro Radisic
6
6
  License-Expression: Apache-2.0
@@ -22,6 +22,7 @@ Requires-Python: >=3.10
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
24
  Requires-Dist: tomli>=2; python_version < "3.11"
25
+ Requires-Dist: zstandard<1,>=0.23
25
26
  Provides-Extra: dev
26
27
  Requires-Dist: pytest>=8; extra == "dev"
27
28
  Requires-Dist: ruff>=0.6; extra == "dev"
@@ -90,6 +91,21 @@ environment libraries, then builds the exact source environment when necessary.
90
91
  `--no-source-build` to forbid that potentially large fallback or `--offline` to use
91
92
  retained environments only.
92
93
 
94
+ Before a cold run, inspect its cost without changing the store:
95
+
96
+ ```bash
97
+ lean-run Main.lean --plan
98
+ lean-run Main.lean --max-download 2GiB
99
+ ```
100
+
101
+ New-format libraries publish two independently verified pieces: a slim Lean
102
+ check runtime and seekable module packs. Lean Runtime computes the source's
103
+ transitive import closure, downloads only the corresponding compressed frames,
104
+ and shares verified module artifacts across Mathlib, LeanCert, and future
105
+ environments. A warm check is silent apart from its result. Older published
106
+ environments remain readable and automatically use the legacy full-bundle
107
+ path, so this optimization does not invalidate existing locks.
108
+
93
109
  Explicit frontmatter remains available when the desired context is already known:
94
110
 
95
111
  ```lean
@@ -165,6 +181,35 @@ project = lean.setup(project="./my-project")
165
181
  result = project.check_file("./my-project/MyProject/Main.lean")
166
182
  ```
167
183
 
184
+ Create a normal Lake project. The newest stable cataloged Mathlib is the
185
+ default, and exact dependencies are shared automatically:
186
+
187
+ ```bash
188
+ lean-runtime init MyProof
189
+ cd MyProof
190
+ lean-runtime check MyProof/Basic.lean
191
+ lean-runtime build
192
+ ```
193
+
194
+ `init` also writes an `AGENTS.md` with the project build, checking, dependency,
195
+ and shared-package rules for coding agents. Pass `--no-agents` to omit it; an
196
+ existing `AGENTS.md` is never overwritten. Use `--core` for no Mathlib, or
197
+ `--mathlib 4.33.0` to select a cataloged release. `lean-runtime update`
198
+ explicitly moves a project to the newest cataloged Mathlib after a preview.
199
+
200
+ Running `lean-runtime init .` in an existing pinned Lake project adopts its
201
+ current exact graph without running `lake update`. If you already have many
202
+ Lake checkouts, register them once as local dependency seeds:
203
+
204
+ ```bash
205
+ lean-runtime scan ~/research
206
+ lean-runtime init .
207
+ ```
208
+
209
+ `init --plan` is side-effect free; `--max-download 500MiB` and `--offline`
210
+ enforce cold-start policy. Advanced bulk migration remains available through
211
+ `attach`, and `detach --execute` materializes an independent project again.
212
+
168
213
  One-shot helpers are available when setup reuse is unnecessary:
169
214
 
170
215
  ```python
@@ -217,7 +262,9 @@ lean-runtime project init-publish . \
217
262
  ```
218
263
 
219
264
  The workflow builds and verifies Linux and macOS environments, finalizes the
220
- index atomically, then checks clean consumers. See
265
+ environment and slim-toolchain indexes atomically, then checks clean consumers.
266
+ For a one-machine handoff, `lean-runtime project export` writes a source-free
267
+ portable capsule containing only the selected public module's closure. See
221
268
  [Publishing a Lean project](https://alerad.github.io/lean-runtime/project-publishing/).
222
269
 
223
270
  For an already-built executable, Lean Runtime can also create a verified
@@ -229,10 +276,10 @@ library. See [Ready-to-run programs](https://github.com/alerad/lean-runtime/blob
229
276
 
230
277
  The simple API is backed by exact Git commits and trees, Lake-resolved locks,
231
278
  platform-aware content-addressed environments, atomic cross-process builds,
232
- downloadable environment reuse, replayable provenance, verification, and trusted
233
- publishers. The libraries use OCI-compatible storage internally, but users do
234
- not need Docker or container concepts. Advanced protocol details remain in the
235
- architecture documentation.
279
+ downloadable environment reuse, sparse content-addressed module packs,
280
+ replayable provenance, verification, and trusted publishers. The libraries use
281
+ OCI-compatible storage internally, but users do not need Docker or container
282
+ concepts. Advanced protocol details remain in the architecture documentation.
236
283
 
237
284
  ## Documentation
238
285
 
@@ -55,6 +55,21 @@ environment libraries, then builds the exact source environment when necessary.
55
55
  `--no-source-build` to forbid that potentially large fallback or `--offline` to use
56
56
  retained environments only.
57
57
 
58
+ Before a cold run, inspect its cost without changing the store:
59
+
60
+ ```bash
61
+ lean-run Main.lean --plan
62
+ lean-run Main.lean --max-download 2GiB
63
+ ```
64
+
65
+ New-format libraries publish two independently verified pieces: a slim Lean
66
+ check runtime and seekable module packs. Lean Runtime computes the source's
67
+ transitive import closure, downloads only the corresponding compressed frames,
68
+ and shares verified module artifacts across Mathlib, LeanCert, and future
69
+ environments. A warm check is silent apart from its result. Older published
70
+ environments remain readable and automatically use the legacy full-bundle
71
+ path, so this optimization does not invalidate existing locks.
72
+
58
73
  Explicit frontmatter remains available when the desired context is already known:
59
74
 
60
75
  ```lean
@@ -130,6 +145,35 @@ project = lean.setup(project="./my-project")
130
145
  result = project.check_file("./my-project/MyProject/Main.lean")
131
146
  ```
132
147
 
148
+ Create a normal Lake project. The newest stable cataloged Mathlib is the
149
+ default, and exact dependencies are shared automatically:
150
+
151
+ ```bash
152
+ lean-runtime init MyProof
153
+ cd MyProof
154
+ lean-runtime check MyProof/Basic.lean
155
+ lean-runtime build
156
+ ```
157
+
158
+ `init` also writes an `AGENTS.md` with the project build, checking, dependency,
159
+ and shared-package rules for coding agents. Pass `--no-agents` to omit it; an
160
+ existing `AGENTS.md` is never overwritten. Use `--core` for no Mathlib, or
161
+ `--mathlib 4.33.0` to select a cataloged release. `lean-runtime update`
162
+ explicitly moves a project to the newest cataloged Mathlib after a preview.
163
+
164
+ Running `lean-runtime init .` in an existing pinned Lake project adopts its
165
+ current exact graph without running `lake update`. If you already have many
166
+ Lake checkouts, register them once as local dependency seeds:
167
+
168
+ ```bash
169
+ lean-runtime scan ~/research
170
+ lean-runtime init .
171
+ ```
172
+
173
+ `init --plan` is side-effect free; `--max-download 500MiB` and `--offline`
174
+ enforce cold-start policy. Advanced bulk migration remains available through
175
+ `attach`, and `detach --execute` materializes an independent project again.
176
+
133
177
  One-shot helpers are available when setup reuse is unnecessary:
134
178
 
135
179
  ```python
@@ -182,7 +226,9 @@ lean-runtime project init-publish . \
182
226
  ```
183
227
 
184
228
  The workflow builds and verifies Linux and macOS environments, finalizes the
185
- index atomically, then checks clean consumers. See
229
+ environment and slim-toolchain indexes atomically, then checks clean consumers.
230
+ For a one-machine handoff, `lean-runtime project export` writes a source-free
231
+ portable capsule containing only the selected public module's closure. See
186
232
  [Publishing a Lean project](https://alerad.github.io/lean-runtime/project-publishing/).
187
233
 
188
234
  For an already-built executable, Lean Runtime can also create a verified
@@ -194,10 +240,10 @@ library. See [Ready-to-run programs](https://github.com/alerad/lean-runtime/blob
194
240
 
195
241
  The simple API is backed by exact Git commits and trees, Lake-resolved locks,
196
242
  platform-aware content-addressed environments, atomic cross-process builds,
197
- downloadable environment reuse, replayable provenance, verification, and trusted
198
- publishers. The libraries use OCI-compatible storage internally, but users do
199
- not need Docker or container concepts. Advanced protocol details remain in the
200
- architecture documentation.
243
+ downloadable environment reuse, sparse content-addressed module packs,
244
+ replayable provenance, verification, and trusted publishers. The libraries use
245
+ OCI-compatible storage internally, but users do not need Docker or container
246
+ concepts. Advanced protocol details remain in the architecture documentation.
201
247
 
202
248
  ## Documentation
203
249
 
@@ -114,6 +114,29 @@ renames the stage to its final identity.
114
114
  Crashes cannot publish a partially ready environment. Concurrent processes
115
115
  requesting the same identity converge on the same published directory.
116
116
 
117
+ ## Check capsules and sparse acquisition
118
+
119
+ Publication derives a normalized capsule manifest from the authoritative full
120
+ build with the selected Lean version's import parser. Each module records exact
121
+ imports and all retained artifact facets. The publisher physically projects a
122
+ source-free copy and requires both the full build and that isolated projection
123
+ to accept the locked public import before it can upload anything.
124
+
125
+ Artifacts are grouped by package and capability into deterministic zstd packs.
126
+ Each pack is a sequence of independently compressed and hashed frames; the OCI
127
+ manifest still addresses the complete pack, while consumers use exact HTTP
128
+ Range requests for only the frames intersecting a source's transitive import
129
+ closure. Decompressed artifacts are verified into a raw-content CAS and
130
+ hardlinked into a growing environment projection. The generated versioned
131
+ `--setup` file points Lean directly at those facets, bypassing Lake and source
132
+ metadata during checks.
133
+
134
+ The Lean executable and core libraries use a separate multi-platform check
135
+ toolchain index keyed by normalized toolchain identity. Platform selection is
136
+ encoded only in child descriptors, so one atomic index serves Linux AMD64,
137
+ macOS AMD64, and macOS ARM64. Consumers verify the exact Lean commit and run a
138
+ capability corpus before publishing the downloaded runtime locally.
139
+
117
140
  ## Execution
118
141
 
119
142
  A published build is not used as an ordinary mutable working directory. Each
@@ -109,8 +109,29 @@ stay; larger reductions require upstream facet-loading changes.
109
109
 
110
110
  After pruning, source builds of *new* environments and native compilation
111
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.
112
+
113
+ Libraries produced by the current publication workflow also carry this
114
+ verified check profile directly. A cold consumer downloads that compressed
115
+ profile instead of first transferring the full official release. If the
116
+ library has no compatible published check runtime, Lean Runtime falls back to
117
+ the official Elan installation path. Local `toolchain-slim` remains useful for
118
+ older stores and for testing a profile before publication.
119
+
120
+ ## Sparse acquisition and capabilities
121
+
122
+ `lean-run FILE --plan` reads capsule metadata and reports the exact compressed
123
+ frames required by `FILE`'s transitive import closure, plus the selected Lean
124
+ check-runtime cost. The operation has no store side effects. `--max-download`
125
+ applies before acquisition to the combined known cost; an unknown component is
126
+ reported explicitly instead of treated as zero.
127
+
128
+ The ordinary check capability retains `.olean`, `.olean.server`,
129
+ `.olean.private`, `.ir`, and `.ir.sig`. This is empirical, not conservative
130
+ guesswork: Lean 4.32 and 4.33 reject ordinary imports when the corresponding
131
+ server/private or IR facets are omitted. `.ilean` editor indexes are a separate
132
+ on-demand capability through `Environment.require_capabilities(["editor"],
133
+ imports=[...])`. Native compilation and development builds require a full
134
+ environment and full toolchain; check capsules reject those requests clearly.
114
135
 
115
136
  ## Replay
116
137
 
@@ -125,18 +146,37 @@ environment can replay offline.
125
146
  ## Existing projects and core Lean
126
147
 
127
148
  ```bash
128
- lean-runtime check-file Main.lean --toolchain 4.32.2
129
- lean-runtime check-file ./existing-project/MyProject/Main.lean
130
- lean-runtime build ./existing-project MyLibrary
149
+ lean-runtime check Main.lean --toolchain 4.32.2
150
+ lean-runtime check ./existing-project/MyProject/Main.lean
151
+ lean-runtime build
152
+ lean-runtime init MyProof
153
+ lean-runtime init MyProof --core
154
+ lean-runtime init --plan --max-download 500MiB
155
+ lean-runtime update --plan
156
+ lean-runtime scan ~/research
157
+ lean-runtime attach ~/research --recursive
158
+ lean-runtime attach ~/research --recursive --execute
159
+ lean-runtime detach ./existing-project --execute
131
160
  lean-runtime install 4.32.2
132
161
  ```
133
162
 
134
- Without `--with`, the environment-aware `check` command requires an environment
135
- identifier. `check-file` is the direct local-project route. When no
163
+ `check FILE` is the direct standalone/local-project route; the legacy
164
+ `check ENVIRONMENT FILE` spelling remains accepted. When no
136
165
  `--project` or `--toolchain` is supplied, it discovers the nearest directory
137
166
  containing a Lake configuration and `lean-toolchain`, then passes the actual
138
167
  project-relative file to `lake env lean`.
139
168
 
169
+ `init` defaults to the newest stable cataloged Mathlib, or adopts an existing
170
+ pinned Lake project without changing its graph. `--core` opts out of Mathlib.
171
+ It prepares dependencies before atomically publishing a new project. `update`
172
+ is the explicit transactional move to the newest cataloged Mathlib; `scan`
173
+ records exact existing graphs as future local seeds. `attach` is read-only
174
+ unless `--execute` is present;
175
+ recursive mode inventories a project tree, reports blockers and estimated disk
176
+ recovery, and adopts each valid project transactionally. `detach` is likewise a
177
+ preview unless `--execute` is present. Attached projects use shared mode by
178
+ default in `lean-runtime build`; detach before requesting `--local`.
179
+
140
180
  Add supporting source files with repeatable `--include` options:
141
181
 
142
182
  ```bash
@@ -11,6 +11,12 @@ Lean Runtime separates three states:
11
11
  The separation lets one process resolve a lock and another materialize it. A
12
12
  completed environment can subsequently be opened offline.
13
13
 
14
+ Downloadable environments may use the legacy full-workspace representation or
15
+ the current sparse check-capsule representation. Both resolve to the same exact
16
+ lock and platform environment identity. A capsule stores a normalized module
17
+ graph and content digest for each Lean artifact; its local projection grows as
18
+ new imports are checked without changing that identity.
19
+
14
20
  Package references are an input compiler for `EnvironmentSpec`, not another
15
21
  environment type:
16
22
 
@@ -87,6 +93,14 @@ Short-lived execution leases prevent deletion during cloning without
87
93
  serializing concurrent checks. Locks and source snapshots remain retained in
88
94
  the current store schema.
89
95
 
96
+ Sparse downloads are stored once by artifact digest under the shared module
97
+ CAS and hardlinked into environment projections when the filesystem permits.
98
+ `lean-runtime storage` reports this category separately. Because it is shared,
99
+ its logical byte count can overlap environment projections and should not be
100
+ added to their logical sizes as an estimate of physical disk use.
101
+ `clean --include-downloads` reclaims old OCI blobs and unleased CAS artifacts;
102
+ per-artifact locks and recency updates prevent collection during projection.
103
+
90
104
  ```python
91
105
  report = runtime.clean(dry_run=True)
92
106
  report = runtime.clean(dry_run=False, minimum_age_seconds=30 * 24 * 60 * 60)
@@ -6,11 +6,63 @@
6
6
  python -m pip install lean-runtime
7
7
  ```
8
8
 
9
- On macOS and Linux, Lean Runtime installs requested Lean versions through its
9
+ On macOS and Linux, Lean Runtime first uses a published slim check toolchain when
10
+ one is available and otherwise installs the requested Lean version through its
10
11
  private, checksum-verified Elan installation. It does not change the user's
11
12
  default toolchain or shell profile. Windows currently requires an existing Elan
12
13
  executable through `LEAN_RUNTIME_ELAN`.
13
14
 
15
+ ## Start a Lake project
16
+
17
+ Create a standard Lake library with the newest cataloged Mathlib release and
18
+ shared exact dependencies:
19
+
20
+ ```bash
21
+ lean-runtime init MyProof
22
+ cd MyProof
23
+ lean-runtime check MyProof/Basic.lean
24
+ lean-runtime build
25
+ ```
26
+
27
+ By default, `init` writes an `AGENTS.md` explaining the project workflow and
28
+ shared-dependency safety rules to coding agents. Pass `--no-agents` to omit it.
29
+ An existing file is preserved.
30
+
31
+ Use `--mathlib 4.33.0` to select that release explicitly, or `--core` for a
32
+ core-only library. The root project remains an ordinary mutable Lake project;
33
+ its dependency sources and build artifacts are reused by other projects with
34
+ the same exact graph.
35
+
36
+ Before doing any work, `init --plan` reports the exact release, local reuse, and
37
+ known download size. `--max-download 500MiB` refuses a larger transfer and
38
+ `--offline` requires a matching local graph. Initialization is transactional:
39
+ the target appears only after Lake and the shared dependency graph both verify.
40
+ Project development requires one full Lake-capable Lean toolchain per Lean
41
+ version. When it is absent, the plan says its Elan download size is unknown;
42
+ `--offline` and `--max-download` fail closed instead of silently installing it.
43
+
44
+ Dependency upgrades are explicit:
45
+
46
+ ```bash
47
+ lean-runtime update --plan
48
+ lean-runtime update
49
+ ```
50
+
51
+ The update preview names both exact Mathlib revisions and toolchains. In a
52
+ terminal, the second command asks for confirmation; use `--yes` in automation.
53
+
54
+ For one existing pinned Lake project, preserve and adopt its current exact graph:
55
+
56
+ ```bash
57
+ lean-runtime init .
58
+ lean-runtime scan ~/research
59
+ ```
60
+
61
+ `scan` only records exact local graphs as possible future zero-download seeds.
62
+ Advanced bulk migration remains available through `attach`. See [Local Lake
63
+ projects](local-projects.md) for detachment, storage estimates, and the complete
64
+ safety model.
65
+
14
66
  ## Run a file
15
67
 
16
68
  For a file inside a pinned Lake project:
@@ -1,7 +1,7 @@
1
1
  # Lean Runtime
2
2
 
3
3
  Lean Runtime runs Lean proofs from Python or a single `.lean` file. It discovers
4
- local Lake projects or compiles friendly exact dependencies into a
4
+ local Lake projects or compiles friendly exact dependencies into an
5
5
  exact reusable environment, then returns structured results and a record of what
6
6
  was used.
7
7
 
@@ -28,9 +28,12 @@ It deliberately does not replace the official tools:
28
28
 
29
29
  The front-facing API supports setup-once Python environments, one-shot helpers,
30
30
  friendly exact package references, standalone TOML frontmatter, local-project
31
- discovery, exact lock output, batch checking, and asyncio. The explicit runtime
32
- also exposes environment libraries, portable copies, trusted publishers,
33
- verification, captures, policies, and storage lifecycle operations.
31
+ discovery, shared Lake dependencies, exact lock output, batch checking, and
32
+ asyncio. New projects can begin with a shared catalog-pinned Mathlib graph;
33
+ existing project trees can preview and transactionally adopt the same layout.
34
+ The explicit runtime also exposes environment libraries, portable copies,
35
+ trusted publishers, verification, captures, policies, and storage lifecycle
36
+ operations.
34
37
 
35
38
  The local backend executes **trusted inputs only**. Lean packages and Lake
36
39
  configuration can run native programs and arbitrary build commands; the local
@@ -0,0 +1,189 @@
1
+ # Local Lake projects
2
+
3
+ Lean Runtime can discover and operate on an existing trusted Lake checkout
4
+ without converting it into an immutable managed environment:
5
+
6
+ ```python
7
+ from lean_runtime import Runtime
8
+
9
+ project = Runtime().project("./my-project")
10
+ project.build()
11
+ result = project.check_file("./my-project/MyProject/Main.lean")
12
+ ```
13
+
14
+ `Runtime.project()` accepts either the project root or any contained path. It
15
+ walks upward and selects the nearest directory containing both `lean-toolchain`
16
+ and `lakefile.toml` or `lakefile.lean`.
17
+
18
+ `Runtime.check_file(path)` performs the same discovery automatically when no
19
+ managed environment, dependency list, or explicit toolchain is supplied:
20
+
21
+ ```python
22
+ result = Runtime().check_file("./my-project/MyProject/Main.lean")
23
+ ```
24
+
25
+ The primary CLI equivalent is:
26
+
27
+ ```bash
28
+ lean-runtime check ./my-project/MyProject/Main.lean
29
+ ```
30
+
31
+ The actual project-relative file is passed to `lake env lean`, so imports of
32
+ local modules retain normal Lake semantics. Checking a source string writes a
33
+ uniquely named disposable file under `.lake/lean-runtime/` and removes it after
34
+ execution:
35
+
36
+ ```python
37
+ result = project.check("import MyProject\nexample : True := by trivial")
38
+ ```
39
+
40
+ ## Reusing dependencies across projects
41
+
42
+ Ordinary Lake workspaces put remote dependencies and their build artifacts in
43
+ each repository's `.lake/packages`. New projects can start in shared mode:
44
+
45
+ ```bash
46
+ lean-runtime init MyProof
47
+ cd MyProof
48
+ lean-runtime check MyProof/Basic.lean
49
+ lean-runtime build
50
+ ```
51
+
52
+ The generated files are a standard Lake project plus a small
53
+ `lean-runtime.toml`. Root build outputs stay local; exact dependencies are
54
+ shared. The newest stable cataloged Mathlib is selected by default. Select a
55
+ release with `--mathlib 4.33.0`, or use `--core` for a core-only library.
56
+ `init` also creates an `AGENTS.md` describing the safe
57
+ build and dependency workflow unless `--no-agents` is passed; it never
58
+ overwrites an existing guide.
59
+
60
+ Initialization acquires and verifies the exact graph before publishing the
61
+ target directory. Use `--plan` for a side-effect-free cost report, `--offline`
62
+ to require local data, `--max-download SIZE` to enforce a transfer ceiling, or
63
+ `--seed-from PROJECT` to name an exact local donor.
64
+ The plan separately reports whether the full Lake-capable toolchain is already
65
+ installed. Because Elan does not publish a preflight byte count, a missing full
66
+ toolchain is rejected under `--offline` or `--max-download` rather than silently
67
+ bypassing the policy.
68
+
69
+ For an existing pinned project, `lean-runtime init .` adopts its current
70
+ manifest without changing versions. Register a collection once with
71
+ `lean-runtime scan ~/research`; future exact matches are preferred over
72
+ downloads automatically.
73
+
74
+ Move an adopted TOML project to the newest cataloged Mathlib explicitly:
75
+
76
+ ```bash
77
+ lean-runtime update --plan
78
+ lean-runtime update
79
+ ```
80
+
81
+ The plan reports old and new release, commit, toolchain, local donor, and known
82
+ download bytes. Acquisition happens before metadata changes, and failures
83
+ restore the prior Lake files and attachment metadata.
84
+
85
+ For advanced bulk onboarding, preview before changing anything:
86
+
87
+ ```bash
88
+ lean-runtime attach .
89
+ lean-runtime attach . --execute
90
+ ```
91
+
92
+ For a directory containing many projects:
93
+
94
+ ```bash
95
+ lean-runtime attach ~/research --recursive
96
+ lean-runtime attach ~/research --recursive --execute
97
+ ```
98
+
99
+ The preview groups exact graphs, reports current and estimated shared storage,
100
+ and identifies missing local paths, dirty dependencies, and revision
101
+ mismatches. Execution continues through independent projects while reporting
102
+ per-project failures. It first prepares the exact shared workspace and probes it
103
+ through Lake. Only then does it atomically replace `.lake/packages` with package
104
+ links, probe the resulting project through ordinary Lake, and discard the old
105
+ generated copies. Any failure restores the original package directory.
106
+
107
+ The project itself remains portable. To return to independent package copies:
108
+
109
+ ```bash
110
+ lean-runtime detach .
111
+ lean-runtime detach . --execute
112
+ ```
113
+
114
+ Detachment copy-on-write clones the exact packages where the filesystem allows,
115
+ probes the standalone graph, and only then removes the attachment metadata. The
116
+ preview reports the maximum independent-copy size and available disk space;
117
+ execution refuses to rely on copy-on-write support when there is not enough
118
+ space for a full fallback copy.
119
+
120
+ The lower-level opt-in remains available without changing project layout:
121
+
122
+ ```bash
123
+ lean-runtime build . --shared
124
+ ```
125
+
126
+ Or from Python:
127
+
128
+ ```python
129
+ Runtime().project(".").build(shared=True)
130
+ ```
131
+
132
+ Lean Runtime reads the existing `lake-manifest.json` and passes Lake a generated
133
+ `--packages` override. Each remote package is keyed by its exact revision,
134
+ effective transitive dependency closure, Lean toolchain, and host platform;
135
+ local-path dependency contents are part of the surrounding workspace identity.
136
+ Dependency sources and their `.lake/build` artifacts live under the runtime
137
+ store, while the root project's own `.lake/build` remains in the checkout. This
138
+ lets two different root manifests share the same Mathlib package safely. Builds
139
+ that touch any of the same package keys are serialized because Lake may update
140
+ their artifacts.
141
+
142
+ The first shared build imports a clean, revision-matching local dependency copy
143
+ when one exists, using copy-on-write filesystem clones where supported. Missing
144
+ sources are fetched at the exact manifest commit. A plain shared build never
145
+ deletes the old `.lake/packages`; only an explicit `attach --execute` replaces
146
+ those generated copies after verification. `lean-runtime storage` reports
147
+ shared project package usage; automatic cleanup of those packages is not yet
148
+ implemented.
149
+
150
+ This mode requires a manifest and never runs `lake update`, so it cannot silently
151
+ change dependency revisions. It also reuses an existing local Git object database
152
+ when that database contains another requested revision, avoiding redundant Git
153
+ downloads. Local `path` dependencies remain at their declared locations and are
154
+ included in the workspace identity. Attached projects automatically use shared
155
+ mode when run through `lean-runtime build`; `--local` is an explicit escape
156
+ hatch for unattached checkouts. An attached project must be detached before a
157
+ local build, so `--local` cannot silently continue using shared links. After
158
+ changing the manifest or a local path dependency, rerun `lean-runtime attach .
159
+ --execute` to refresh the ordinary-Lake links.
160
+
161
+ This differs from `lake env lean File.lean`: that command only constructs the
162
+ current workspace's environment and checks one file; it neither builds missing
163
+ imports nor shares dependencies with another checkout. The shared build still
164
+ uses Lake's real build graph and project targets—it only changes where locked
165
+ dependencies come from. Attached links also let ordinary `lake build` and the
166
+ editor load the graph; prefer `lean-runtime build` when several projects may
167
+ build concurrently, because it serializes writes to shared artifacts.
168
+
169
+ ## Mutable-project provenance
170
+
171
+ A local project is intentionally represented by `ProjectEnvironment`, not the
172
+ content-addressed `Environment` used for locked dependency graphs. Its results
173
+ therefore have `environment_id=None` and include project provenance containing:
174
+
175
+ - the canonical project root;
176
+ - a content digest excluding `.git` and `.lake`;
177
+ - Lake configuration and manifest digests;
178
+ - the Git revision and dirty state when Git metadata is available.
179
+
180
+ The workspace digest changes when local source or configuration changes, while
181
+ generated Lake artifacts do not affect it.
182
+
183
+ Lean Runtime does not run `lake update` or rewrite the manifest.
184
+ `project.build()` explicitly runs the pinned toolchain's `lake build`; checks
185
+ otherwise use the project exactly as it exists. Shared builds copy or fetch only
186
+ locked dependencies into the runtime store and leave the mutable root checkout
187
+ in place.
188
+ As with managed environments, Lake configuration and dependencies are trusted
189
+ code and the local backend is not a sandbox.