lean-runtime 2.9.1__tar.gz → 2.9.2__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.9.1 → lean_runtime-2.9.2}/CHANGELOG.md +12 -0
- {lean_runtime-2.9.1/lean_runtime.egg-info → lean_runtime-2.9.2}/PKG-INFO +1 -1
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/cli.md +3 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/environments.md +6 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/portable-copies.md +6 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/cli.py +89 -15
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/console.py +12 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/environments.py +4 -10
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/errors.py +25 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/header_cache.py +6 -1
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/health.py +13 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/models.py +2 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/oci.py +96 -13
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/programs.py +2 -6
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/project_sharing.py +3 -1
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/resolver.py +5 -2
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/runtime.py +38 -11
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/shared_projects.py +5 -2
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/store.py +122 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/toolchains.py +30 -1
- {lean_runtime-2.9.1 → lean_runtime-2.9.2/lean_runtime.egg-info}/PKG-INFO +1 -1
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/pyproject.toml +1 -1
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/schemas/cleanup-v1.schema.json +7 -3
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/schemas/execution-v1.schema.json +1 -1
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/schemas/publication-v1.schema.json +2 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_bundles.py +81 -5
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_cli.py +23 -6
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_console.py +12 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_events_health.py +1 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_projects.py +7 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_store.py +35 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/LICENSE +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/MANIFEST.in +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/README.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/catalog/environments.toml +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/catalog/locks/core-v4.32.2.lock.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/catalog/locks/leancert-v4.30.0.5.lock.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/catalog/locks/leancert-v4.31.0.lock.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/catalog/locks/leancert-v4.32.2.4.lock.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/catalog/locks/leancert-v4.33.0.lock.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/catalog/locks/mathlib-v4.30.0.lock.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/catalog/locks/mathlib-v4.31.0.lock.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/catalog/locks/mathlib-v4.32.2.lock.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/catalog/locks/mathlib-v4.33.0.lock.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/compatibility/README.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/compatibility/lake-artifact-cache-4.33.0.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/compatibility/mathlib-4.32.2.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/compatibility/mathlib-4.32.2.toml +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/compatibility/mathlib-4.33.0.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/compatibility/mathlib-4.33.0.toml +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/architecture.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/captures.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/case-study-v1.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/development.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/getting-started.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/index.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/lake-artifact-cache-design.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/local-projects.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/project-publishing.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/python-api.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/ready-programs.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/standalone-files.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/trust-and-limitations.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/docs/v1-precision.md +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/examples/mathlib.toml +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/__init__.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/__main__.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/_git.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/_paths.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/backends.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/bundles.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/capsules.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/comparison.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/decisions.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/diagnostics.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/__init__.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/analyzer.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/api.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/candidate.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/catalog.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/catalog_build.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/catalog_cli.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/catalog_manifest.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/data/catalog.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/defaults.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/engine.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/errors.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/module_inventory.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/planner.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/policy.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/probe.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/py.typed +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/result.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/schema_resources.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/schemas/catalog-v1.schema.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/schemas/plan-v1.schema.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/discovery/schemas/result-v1.schema.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/events.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/facade.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/frontmatter.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/identifier_resolver.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/lake.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/lake_cache.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/lockfiles.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/locking.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/matrix.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/oci_protocol.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/packs.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/policies.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/profiling.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/project_execution.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/projects.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/publisher_verification.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/py.typed +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/references.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/run_cli.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/schema_resources.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/serialization.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/specs.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/timings.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/toolchain_oci.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/toolchain_slim.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/verification.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime/wire.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime.egg-info/SOURCES.txt +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime.egg-info/dependency_links.txt +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime.egg-info/entry_points.txt +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime.egg-info/requires.txt +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/lean_runtime.egg-info/top_level.txt +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/mkdocs.yml +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/schemas/comparison-v1.schema.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/schemas/inspect-v1.schema.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/schemas/matrix-v1.schema.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/schemas/profile-v1.schema.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/schemas/verify-v1.schema.json +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/scripts/announcement_gate.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/scripts/lake_cache_gate.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/scripts/registry_preflight.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/scripts/run_compatibility.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/scripts/run_v1_case_study.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/scripts/smoke_wheel.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/setup.cfg +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/conftest.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/discovery/e2e/test_real_discovery.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/discovery/test_analyzer.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/discovery/test_catalog.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/discovery/test_catalog_build.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/discovery/test_discovery_schema_resources.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/discovery/test_engine.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/discovery/test_planner.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/discovery/test_policy.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_backend.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_capsules.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_diagnostics.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_environment_integration.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_facade.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_frontmatter.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_git.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_header_cache.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_identifier_resolver.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_interactive.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_lake_cache.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_lockfiles.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_models.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_multifile.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_oci_protocol.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_packs.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_paths.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_prebuilt_policy.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_programs.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_project_publish.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_references.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_run_cli.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_runtime.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_schema_resources.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_schemas.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_signatures.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_specs.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_toolchain_oci.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_toolchain_slim.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_toolchains.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_v1_precision.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_verification_inventory.py +0 -0
- {lean_runtime-2.9.1 → lean_runtime-2.9.2}/tests/test_verification_probe.py +0 -0
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 2.9.2 - 2026-08-16
|
|
6
|
+
|
|
7
|
+
- Keep one fail-closed publication authentication session from push preflight through
|
|
8
|
+
upload, propagate explicit publication timeouts to credential and registry I/O,
|
|
9
|
+
and report credential-provider failures without labeling them anonymous.
|
|
10
|
+
- Use logical project names during atomic initialization, show compact TTY-only check
|
|
11
|
+
progress, cache Lean executable identities across invocations, and report check
|
|
12
|
+
command-preparation timing.
|
|
13
|
+
- Track disposable execution and resolution workspaces with process-held leases;
|
|
14
|
+
include their footprint in storage reporting and reclaim abandoned workspaces with
|
|
15
|
+
`clean` while protecting active work.
|
|
16
|
+
|
|
5
17
|
## 2.9.1 - 2026-08-15
|
|
6
18
|
|
|
7
19
|
- Make GHCR credential discovery a single bounded GitHub CLI status read so a
|
|
@@ -215,6 +215,9 @@ lean-runtime check research-stack Main.lean --include Support/Defs.lean
|
|
|
215
215
|
```
|
|
216
216
|
|
|
217
217
|
Resolution and materialization print structured lifecycle progress to stderr.
|
|
218
|
+
One-shot checks show a compact in-place status on interactive terminals while Lean
|
|
219
|
+
is working. Redirected output, `--json`, and `--quiet` remain free of human progress;
|
|
220
|
+
`--timings` separates command preparation from Lean execution.
|
|
218
221
|
Pass global `--quiet` before the subcommand to suppress it.
|
|
219
222
|
|
|
220
223
|
Pass global `--timings` before the subcommand for stable phase timing output. Machine-readable
|
|
@@ -93,6 +93,12 @@ Short-lived execution leases prevent deletion during cloning without
|
|
|
93
93
|
serializing concurrent checks. Locks and source snapshots remain retained in
|
|
94
94
|
the current store schema.
|
|
95
95
|
|
|
96
|
+
Disposable execution and dependency-resolution workspaces carry their own
|
|
97
|
+
process-held ownership leases. `storage` includes them under `Scratch`, and
|
|
98
|
+
`clean` previews and reclaims abandoned workspaces while retaining every
|
|
99
|
+
workspace with a live owner. Legacy scratch directories created before ownership
|
|
100
|
+
metadata are removed only by an explicit `clean --execute` after the safety grace.
|
|
101
|
+
|
|
96
102
|
Sparse downloads are stored once by artifact digest under the shared module
|
|
97
103
|
CAS and hardlinked into environment projections when the filesystem permits.
|
|
98
104
|
`lean-runtime storage` reports this category separately. Because it is shared,
|
|
@@ -135,6 +135,12 @@ run:
|
|
|
135
135
|
gh auth refresh -s write:packages,read:packages
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
+
Credential discovery is fail-closed: a configured provider that times out or
|
|
139
|
+
returns an unusable token stops publication before any registry request. The same
|
|
140
|
+
verified credential is retained from preflight through upload; it is not rediscovered
|
|
141
|
+
after a long environment build. An explicitly supplied publication `--timeout`
|
|
142
|
+
also applies to credential discovery and registry network operations.
|
|
143
|
+
|
|
138
144
|
Publish the current platform after ensuring the lock:
|
|
139
145
|
|
|
140
146
|
```bash
|
|
@@ -8,12 +8,13 @@ import os
|
|
|
8
8
|
import re
|
|
9
9
|
import sys
|
|
10
10
|
import time
|
|
11
|
+
from dataclasses import replace
|
|
11
12
|
from datetime import datetime
|
|
12
13
|
from importlib.metadata import version as distribution_version
|
|
13
14
|
from pathlib import Path
|
|
14
15
|
from typing import Any, cast
|
|
15
16
|
|
|
16
|
-
from .console import styler_for
|
|
17
|
+
from .console import ConsoleRenderer, styler_for
|
|
17
18
|
from .environments import ExecutionCapture
|
|
18
19
|
from .errors import (
|
|
19
20
|
LeanRuntimeError,
|
|
@@ -89,6 +90,7 @@ def _render_storage(status: StoreStatus) -> None:
|
|
|
89
90
|
("Project packages", status.project_packages, status.project_packages_bytes),
|
|
90
91
|
("Toolchains", None, status.toolchains_bytes),
|
|
91
92
|
("Executions", status.executions, status.executions_bytes),
|
|
93
|
+
("Scratch", status.scratch_workspaces, status.scratch_bytes),
|
|
92
94
|
)
|
|
93
95
|
for label, count, bytes_used in rows:
|
|
94
96
|
counted = f"{count:>5}" if count is not None else " "
|
|
@@ -139,7 +141,11 @@ def _render_doctor(report: DoctorReport) -> None:
|
|
|
139
141
|
print(f"{symbols[check.status]} {check.name}: {check.message}")
|
|
140
142
|
|
|
141
143
|
|
|
142
|
-
def _render_cleanup(
|
|
144
|
+
def _render_cleanup(
|
|
145
|
+
environments: CleanupReport,
|
|
146
|
+
downloads: DownloadCleanupReport | None,
|
|
147
|
+
scratch: CleanupReport | None = None,
|
|
148
|
+
) -> None:
|
|
143
149
|
style = styler_for(sys.stdout)
|
|
144
150
|
retained_note = style.dim(
|
|
145
151
|
f"Retained {len(environments.retained)} environment(s) (named, recent, or in use)."
|
|
@@ -169,17 +175,36 @@ def _render_cleanup(environments: CleanupReport, downloads: DownloadCleanupRepor
|
|
|
169
175
|
)
|
|
170
176
|
else:
|
|
171
177
|
print("No unreferenced cached downloads to remove.")
|
|
178
|
+
if scratch is not None:
|
|
179
|
+
if scratch.candidates:
|
|
180
|
+
anything = True
|
|
181
|
+
print(
|
|
182
|
+
style.bold(
|
|
183
|
+
f"Would remove {len(scratch.candidates)} abandoned workspace(s) · "
|
|
184
|
+
f"{format_byte_size(scratch.candidate_bytes)}"
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
else:
|
|
188
|
+
print("No abandoned workspaces to remove.")
|
|
172
189
|
print(retained_note)
|
|
173
190
|
if anything:
|
|
174
191
|
print()
|
|
175
192
|
print("This was a preview. Re-run with --execute to delete.")
|
|
176
193
|
return
|
|
177
194
|
reclaimed = environments.reclaimed_bytes + (downloads.reclaimed_bytes if downloads else 0)
|
|
178
|
-
|
|
195
|
+
if scratch is not None:
|
|
196
|
+
reclaimed += scratch.reclaimed_bytes
|
|
197
|
+
removed = (
|
|
198
|
+
len(environments.removed)
|
|
199
|
+
+ (len(downloads.removed) if downloads else 0)
|
|
200
|
+
+ (len(scratch.removed) if scratch else 0)
|
|
201
|
+
)
|
|
179
202
|
if removed:
|
|
180
203
|
parts = [f"{len(environments.removed)} environment(s)"]
|
|
181
204
|
if downloads is not None:
|
|
182
205
|
parts.append(f"{len(downloads.removed)} cached download(s)")
|
|
206
|
+
if scratch is not None:
|
|
207
|
+
parts.append(f"{len(scratch.removed)} abandoned workspace(s)")
|
|
183
208
|
print(
|
|
184
209
|
style.green(f"Removed {' and '.join(parts)} · reclaimed {format_byte_size(reclaimed)}")
|
|
185
210
|
)
|
|
@@ -290,11 +315,15 @@ def _print_publication_failure(exc: PublicationError) -> None:
|
|
|
290
315
|
file=sys.stderr,
|
|
291
316
|
)
|
|
292
317
|
print(f" {exc}", file=sys.stderr)
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
f"
|
|
296
|
-
|
|
297
|
-
|
|
318
|
+
if exc.attempted_provider is not None:
|
|
319
|
+
print(" Authentication: unavailable (source: none)", file=sys.stderr)
|
|
320
|
+
print(f" Attempted provider: {exc.attempted_provider}", file=sys.stderr)
|
|
321
|
+
else:
|
|
322
|
+
identity = exc.username or "anonymous"
|
|
323
|
+
print(
|
|
324
|
+
f" Authentication: {identity} (source: {exc.credential_source})",
|
|
325
|
+
file=sys.stderr,
|
|
326
|
+
)
|
|
298
327
|
if exc.partial:
|
|
299
328
|
print(
|
|
300
329
|
" No verified final release was produced; immutable platform content may exist.",
|
|
@@ -436,7 +465,12 @@ Run `lean-runtime COMMAND --help` for examples and options.""",
|
|
|
436
465
|
publish_environment.add_argument("--publish-to", required=True)
|
|
437
466
|
publish_environment.add_argument("--tag", action="append", default=[])
|
|
438
467
|
publish_environment.add_argument("--name")
|
|
439
|
-
publish_environment.add_argument(
|
|
468
|
+
publish_environment.add_argument(
|
|
469
|
+
"--timeout",
|
|
470
|
+
type=float,
|
|
471
|
+
default=None,
|
|
472
|
+
help="override timeouts for credential, registry, hydration, and build operations",
|
|
473
|
+
)
|
|
440
474
|
publish_environment.add_argument("--platform-only", action="store_true")
|
|
441
475
|
publish_environment.add_argument("--accelerate", action="store_true")
|
|
442
476
|
publish_environment.add_argument("--sign", action="store_true")
|
|
@@ -511,8 +545,8 @@ Run `lean-runtime COMMAND --help` for examples and options.""",
|
|
|
511
545
|
push.add_argument(
|
|
512
546
|
"--timeout",
|
|
513
547
|
type=float,
|
|
514
|
-
default=
|
|
515
|
-
help="
|
|
548
|
+
default=None,
|
|
549
|
+
help="override timeouts for credential, registry, hydration, and build operations",
|
|
516
550
|
)
|
|
517
551
|
push.add_argument(
|
|
518
552
|
"--platform-only",
|
|
@@ -933,6 +967,10 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
933
967
|
args.mathlib = None if args.core else args.mathlib_version
|
|
934
968
|
operation_started = time.monotonic()
|
|
935
969
|
display_path: str | None = None
|
|
970
|
+
renderer = ConsoleRenderer(
|
|
971
|
+
mode="quiet" if args.quiet or getattr(args, "json", False) else None,
|
|
972
|
+
verbose=args.verbose,
|
|
973
|
+
)
|
|
936
974
|
try:
|
|
937
975
|
if args.command == "completion":
|
|
938
976
|
print(_completion_script(args.shell), end="")
|
|
@@ -947,7 +985,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
947
985
|
)
|
|
948
986
|
runtime = Runtime(
|
|
949
987
|
home=args.home,
|
|
950
|
-
on_event=
|
|
988
|
+
on_event=renderer,
|
|
951
989
|
availability=selected_availability,
|
|
952
990
|
libraries=args.libraries,
|
|
953
991
|
max_download_bytes=selected_download_limit,
|
|
@@ -1190,7 +1228,13 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1190
1228
|
_json(environment.inspect().to_dict())
|
|
1191
1229
|
return 0
|
|
1192
1230
|
if args.command == "build-and-publish":
|
|
1193
|
-
|
|
1231
|
+
timeout_override = args.timeout
|
|
1232
|
+
publisher = runtime.begin_publication(
|
|
1233
|
+
args.publish_to,
|
|
1234
|
+
auth_timeout=timeout_override if timeout_override is not None else 10,
|
|
1235
|
+
registry_timeout=timeout_override if timeout_override is not None else 30,
|
|
1236
|
+
)
|
|
1237
|
+
access = publisher.check_access()
|
|
1194
1238
|
if args.check_access:
|
|
1195
1239
|
_json(
|
|
1196
1240
|
envelope(_schema_for(args.command), ok=True, data=access.to_dict())
|
|
@@ -1203,7 +1247,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1203
1247
|
environment = runtime.open_exact(
|
|
1204
1248
|
EnvironmentLock.load(args.lock),
|
|
1205
1249
|
name=args.name,
|
|
1206
|
-
build_timeout=
|
|
1250
|
+
build_timeout=timeout_override if timeout_override is not None else 1800,
|
|
1207
1251
|
accelerate=args.accelerate,
|
|
1208
1252
|
)
|
|
1209
1253
|
publication = runtime.publish_environment(
|
|
@@ -1213,6 +1257,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1213
1257
|
finalize=not args.platform_only,
|
|
1214
1258
|
sign=args.sign,
|
|
1215
1259
|
attest=args.attest,
|
|
1260
|
+
publisher=publisher,
|
|
1216
1261
|
).to_dict()
|
|
1217
1262
|
publication["consumer_command"] = (
|
|
1218
1263
|
f"lean-runtime --library {args.publish_to} download {args.lock}"
|
|
@@ -1487,10 +1532,15 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1487
1532
|
if args.include_downloads
|
|
1488
1533
|
else None
|
|
1489
1534
|
)
|
|
1535
|
+
gc_scratch = runtime.clean_scratch(
|
|
1536
|
+
dry_run=not args.execute,
|
|
1537
|
+
minimum_age_seconds=min(args.minimum_age_hours * 3600, 3600),
|
|
1538
|
+
)
|
|
1490
1539
|
if args.json:
|
|
1491
1540
|
gc_payload: dict[str, Any] = {
|
|
1492
1541
|
"environments": gc_report.to_dict(),
|
|
1493
1542
|
"downloaded_files": gc_downloads.to_dict() if gc_downloads else None,
|
|
1543
|
+
"scratch": gc_scratch.to_dict(),
|
|
1494
1544
|
}
|
|
1495
1545
|
_json(
|
|
1496
1546
|
envelope(
|
|
@@ -1500,7 +1550,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1500
1550
|
)
|
|
1501
1551
|
)
|
|
1502
1552
|
else:
|
|
1503
|
-
_render_cleanup(gc_report, gc_downloads)
|
|
1553
|
+
_render_cleanup(gc_report, gc_downloads, gc_scratch)
|
|
1504
1554
|
return 0
|
|
1505
1555
|
if args.command == "check":
|
|
1506
1556
|
if args.across is not None:
|
|
@@ -1590,6 +1640,14 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1590
1640
|
)
|
|
1591
1641
|
_emit_result(watched_result, False)
|
|
1592
1642
|
time.sleep(args.watch_interval)
|
|
1643
|
+
check_subject = (
|
|
1644
|
+
Path(args.inputs[-1]).name
|
|
1645
|
+
if args.inputs and args.inputs[-1] != "-"
|
|
1646
|
+
else "stdin"
|
|
1647
|
+
if args.inputs
|
|
1648
|
+
else Path(args.project or ".").resolve().name
|
|
1649
|
+
)
|
|
1650
|
+
runtime.events.emit("check.started", "Checking Lean input", subject=check_subject)
|
|
1593
1651
|
if args.project is not None and args.package_refs:
|
|
1594
1652
|
raise ValueError("check cannot combine --project with --with")
|
|
1595
1653
|
if not args.inputs:
|
|
@@ -1672,9 +1730,11 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1672
1730
|
shared=args.shared,
|
|
1673
1731
|
)
|
|
1674
1732
|
except KeyboardInterrupt:
|
|
1733
|
+
renderer.close()
|
|
1675
1734
|
print("lean-runtime: interrupted", file=sys.stderr)
|
|
1676
1735
|
return 130
|
|
1677
1736
|
except (ResolutionError, MaterializationError) as exc:
|
|
1737
|
+
renderer.close()
|
|
1678
1738
|
details = {
|
|
1679
1739
|
"phase": exc.phase,
|
|
1680
1740
|
"command": list(exc.command),
|
|
@@ -1694,6 +1754,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1694
1754
|
_print_operation_failure(exc, verbose=args.verbose)
|
|
1695
1755
|
return 2
|
|
1696
1756
|
except PublicationError as exc:
|
|
1757
|
+
renderer.close()
|
|
1697
1758
|
if getattr(args, "json", False):
|
|
1698
1759
|
_json(
|
|
1699
1760
|
envelope(
|
|
@@ -1707,6 +1768,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1707
1768
|
_print_publication_failure(exc)
|
|
1708
1769
|
return exc.exit_code
|
|
1709
1770
|
except (LeanRuntimeError, OSError, UnicodeError, ValueError, json.JSONDecodeError) as exc:
|
|
1771
|
+
renderer.close()
|
|
1710
1772
|
if getattr(args, "json", False):
|
|
1711
1773
|
_json(
|
|
1712
1774
|
envelope(
|
|
@@ -1719,6 +1781,18 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1719
1781
|
else:
|
|
1720
1782
|
print(f"lean-runtime: {exc}", file=sys.stderr)
|
|
1721
1783
|
return 2
|
|
1784
|
+
if args.command in {"check", "check-file"}:
|
|
1785
|
+
runtime.events.emit("check.completed", "Lean check completed", ok=result.ok)
|
|
1786
|
+
total_ms = round((time.monotonic() - operation_started) * 1000)
|
|
1787
|
+
accounted_ms = sum(timing.duration_ms for timing in result.timings)
|
|
1788
|
+
result = replace(
|
|
1789
|
+
result,
|
|
1790
|
+
timings=(
|
|
1791
|
+
PhaseTiming("command_preparation", max(0, total_ms - accounted_ms)),
|
|
1792
|
+
*result.timings,
|
|
1793
|
+
),
|
|
1794
|
+
)
|
|
1795
|
+
renderer.close()
|
|
1722
1796
|
_emit_result(result, args.json, display_path=display_path)
|
|
1723
1797
|
if args.timings:
|
|
1724
1798
|
print(render_timings(result.timings), file=sys.stderr)
|
|
@@ -215,6 +215,18 @@ class ConsoleRenderer:
|
|
|
215
215
|
def _render_capability_required(self, event: RuntimeEvent) -> None:
|
|
216
216
|
self._print(event.message)
|
|
217
217
|
|
|
218
|
+
def _render_check_started(self, event: RuntimeEvent) -> None:
|
|
219
|
+
if self.mode != "tty":
|
|
220
|
+
return
|
|
221
|
+
subject = str(event.data.get("subject") or "Lean input")
|
|
222
|
+
message = f"Checking {subject}…"
|
|
223
|
+
self.stream.write("\r" + self.style.cyan(message))
|
|
224
|
+
self.stream.flush()
|
|
225
|
+
self._line_length = len(message)
|
|
226
|
+
|
|
227
|
+
def _render_check_completed(self, _event: RuntimeEvent) -> None:
|
|
228
|
+
self._end_progress_line()
|
|
229
|
+
|
|
218
230
|
# -- low-level output -----------------------------------------------
|
|
219
231
|
|
|
220
232
|
def _verbose_line(self, event: RuntimeEvent) -> None:
|
|
@@ -707,14 +707,11 @@ class Environment:
|
|
|
707
707
|
},
|
|
708
708
|
)
|
|
709
709
|
job_parent = self.manager.store.jobs / execution_id
|
|
710
|
-
|
|
710
|
+
workspace_lease = self.manager.store.lease_workspace(job_parent, "interactive-environment")
|
|
711
711
|
instance = job_parent / f"instance-{uuid.uuid4().hex}"
|
|
712
712
|
|
|
713
713
|
def cleanup() -> None:
|
|
714
|
-
|
|
715
|
-
remove_tree(instance)
|
|
716
|
-
with suppress(OSError):
|
|
717
|
-
job_parent.rmdir()
|
|
714
|
+
workspace_lease.close()
|
|
718
715
|
|
|
719
716
|
try:
|
|
720
717
|
with self.manager.store.execution_lease(self.id):
|
|
@@ -844,7 +841,7 @@ class Environment:
|
|
|
844
841
|
},
|
|
845
842
|
)
|
|
846
843
|
job_parent = self.manager.store.jobs / execution_id
|
|
847
|
-
|
|
844
|
+
workspace_lease = self.manager.store.lease_workspace(job_parent, f"environment-{operation}")
|
|
848
845
|
instance = job_parent / f"instance-{uuid.uuid4().hex}"
|
|
849
846
|
try:
|
|
850
847
|
instance_started = time.monotonic()
|
|
@@ -994,10 +991,7 @@ class Environment:
|
|
|
994
991
|
)
|
|
995
992
|
return result
|
|
996
993
|
finally:
|
|
997
|
-
|
|
998
|
-
remove_tree(instance)
|
|
999
|
-
with suppress(OSError):
|
|
1000
|
-
job_parent.rmdir()
|
|
994
|
+
workspace_lease.close()
|
|
1001
995
|
|
|
1002
996
|
def _result(
|
|
1003
997
|
self,
|
|
@@ -81,6 +81,23 @@ class RegistryRequestError(DownloadUnavailable):
|
|
|
81
81
|
self.retryable = retryable
|
|
82
82
|
|
|
83
83
|
|
|
84
|
+
class CredentialAcquisitionError(EnvironmentError):
|
|
85
|
+
"""A configured credential provider could not produce usable credentials."""
|
|
86
|
+
|
|
87
|
+
def __init__(
|
|
88
|
+
self,
|
|
89
|
+
message: str,
|
|
90
|
+
*,
|
|
91
|
+
provider: str,
|
|
92
|
+
failure_kind: str,
|
|
93
|
+
retryable: bool,
|
|
94
|
+
) -> None:
|
|
95
|
+
super().__init__(message)
|
|
96
|
+
self.provider = provider
|
|
97
|
+
self.failure_kind = failure_kind
|
|
98
|
+
self.retryable = retryable
|
|
99
|
+
|
|
100
|
+
|
|
84
101
|
class PublicationError(EnvironmentError):
|
|
85
102
|
"""A required publication did not reach a remotely verified terminal state."""
|
|
86
103
|
|
|
@@ -97,6 +114,8 @@ class PublicationError(EnvironmentError):
|
|
|
97
114
|
credential_source: str = "anonymous",
|
|
98
115
|
username: str | None = None,
|
|
99
116
|
hint: str | None = None,
|
|
117
|
+
attempted_provider: str | None = None,
|
|
118
|
+
auth_failure_kind: str | None = None,
|
|
100
119
|
) -> None:
|
|
101
120
|
super().__init__(message)
|
|
102
121
|
self.phase = phase
|
|
@@ -108,11 +127,15 @@ class PublicationError(EnvironmentError):
|
|
|
108
127
|
self.credential_source = credential_source
|
|
109
128
|
self.username = username
|
|
110
129
|
self.hint = hint
|
|
130
|
+
self.attempted_provider = attempted_provider
|
|
131
|
+
self.auth_failure_kind = auth_failure_kind
|
|
111
132
|
|
|
112
133
|
@property
|
|
113
134
|
def exit_code(self) -> int:
|
|
114
135
|
if self.partial:
|
|
115
136
|
return 5
|
|
137
|
+
if self.phase == "credential_acquisition":
|
|
138
|
+
return 4 if self.retryable else 3
|
|
116
139
|
if self.status_code in {401, 403}:
|
|
117
140
|
return 3
|
|
118
141
|
if self.retryable:
|
|
@@ -130,6 +153,8 @@ class PublicationError(EnvironmentError):
|
|
|
130
153
|
"credential_source": self.credential_source,
|
|
131
154
|
"username": self.username,
|
|
132
155
|
"hint": self.hint,
|
|
156
|
+
"attempted_provider": self.attempted_provider,
|
|
157
|
+
"auth_failure_kind": self.auth_failure_kind,
|
|
133
158
|
"message": str(self),
|
|
134
159
|
}
|
|
135
160
|
|
|
@@ -50,11 +50,14 @@ class LeanHeaderCache:
|
|
|
50
50
|
self.home = home / "header-snapshots"
|
|
51
51
|
self.toolchains = toolchains
|
|
52
52
|
self._support: dict[str, bool] = {}
|
|
53
|
+
self._toolchain_keys: dict[str, str] = {}
|
|
53
54
|
|
|
54
55
|
def _toolchain_key(self, toolchain: str) -> str:
|
|
56
|
+
if toolchain in self._toolchain_keys:
|
|
57
|
+
return self._toolchain_keys[toolchain]
|
|
55
58
|
digest = getattr(self.toolchains, "executable_digest", None)
|
|
56
59
|
executable = str(digest(toolchain, "lean")) if callable(digest) else toolchain
|
|
57
|
-
|
|
60
|
+
key = sha256_id(
|
|
58
61
|
"lean-header",
|
|
59
62
|
{
|
|
60
63
|
"toolchain": toolchain,
|
|
@@ -62,6 +65,8 @@ class LeanHeaderCache:
|
|
|
62
65
|
"platform": platform_compatibility(),
|
|
63
66
|
},
|
|
64
67
|
).removeprefix("lean-header-")
|
|
68
|
+
self._toolchain_keys[toolchain] = key
|
|
69
|
+
return key
|
|
65
70
|
|
|
66
71
|
def supported(self, toolchain: str) -> bool:
|
|
67
72
|
key = self._toolchain_key(toolchain)
|
|
@@ -86,6 +86,18 @@ def diagnose(toolchains: ToolchainManager, store: EnvironmentStore) -> DoctorRep
|
|
|
86
86
|
status = "warning" if staging else "pass"
|
|
87
87
|
message = f"{len(staging)} incomplete staging directories" if staging else "No stale builds"
|
|
88
88
|
checks.append(DoctorCheck("staging", status, message))
|
|
89
|
+
scratch = store.clean_scratch(dry_run=True, minimum_age_seconds=3600)
|
|
90
|
+
if scratch.candidates:
|
|
91
|
+
checks.append(
|
|
92
|
+
DoctorCheck(
|
|
93
|
+
"scratch",
|
|
94
|
+
"warning",
|
|
95
|
+
f"{len(scratch.candidates)} abandoned workspaces use "
|
|
96
|
+
f"{scratch.candidate_bytes // (1024**2)} MiB",
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
else:
|
|
100
|
+
checks.append(DoctorCheck("scratch", "pass", "No abandoned workspaces"))
|
|
89
101
|
store_status = store.status()
|
|
90
102
|
cutoff = datetime.now(timezone.utc).timestamp() - 7 * 24 * 3600
|
|
91
103
|
stale = tuple(
|
|
@@ -114,6 +126,7 @@ def repair(toolchains: ToolchainManager, store: EnvironmentStore) -> DoctorRepor
|
|
|
114
126
|
"""Apply the safe remedies represented by doctor checks, then diagnose again."""
|
|
115
127
|
for staging in store.environments.glob(".staging-*"):
|
|
116
128
|
remove_tree(staging)
|
|
129
|
+
store.clean_scratch(dry_run=False, minimum_age_seconds=3600, include_legacy=False)
|
|
117
130
|
with suppress(ToolchainError):
|
|
118
131
|
toolchains.elan_path(bootstrap=True)
|
|
119
132
|
return diagnose(toolchains, store)
|
|
@@ -19,6 +19,7 @@ TimingPhase = Literal[
|
|
|
19
19
|
"environment_open",
|
|
20
20
|
"instance_creation",
|
|
21
21
|
"input_staging",
|
|
22
|
+
"command_preparation",
|
|
22
23
|
"execution",
|
|
23
24
|
"result_collection",
|
|
24
25
|
"result_publication",
|
|
@@ -38,6 +39,7 @@ TIMING_PHASES = frozenset(
|
|
|
38
39
|
"environment_open",
|
|
39
40
|
"instance_creation",
|
|
40
41
|
"input_staging",
|
|
42
|
+
"command_preparation",
|
|
41
43
|
"execution",
|
|
42
44
|
"result_collection",
|
|
43
45
|
"result_publication",
|