lean-lockstep 0.1.0__py3-none-any.whl

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 (71) hide show
  1. lean_lockstep-0.1.0.dist-info/METADATA +218 -0
  2. lean_lockstep-0.1.0.dist-info/RECORD +71 -0
  3. lean_lockstep-0.1.0.dist-info/WHEEL +5 -0
  4. lean_lockstep-0.1.0.dist-info/entry_points.txt +3 -0
  5. lean_lockstep-0.1.0.dist-info/licenses/LICENSE +22 -0
  6. lean_lockstep-0.1.0.dist-info/top_level.txt +1 -0
  7. lockstep/__init__.py +17 -0
  8. lockstep/__main__.py +3 -0
  9. lockstep/allowlist.py +40 -0
  10. lockstep/artifact_cache.py +515 -0
  11. lockstep/artifacts.py +185 -0
  12. lockstep/automation_schema.py +30 -0
  13. lockstep/build.py +468 -0
  14. lockstep/bundles.py +37 -0
  15. lockstep/cli.py +148 -0
  16. lockstep/commands/__init__.py +28 -0
  17. lockstep/commands/audit.py +46 -0
  18. lockstep/commands/automation.py +84 -0
  19. lockstep/commands/build.py +61 -0
  20. lockstep/commands/cache.py +58 -0
  21. lockstep/commands/check.py +81 -0
  22. lockstep/commands/claims.py +62 -0
  23. lockstep/commands/close.py +193 -0
  24. lockstep/commands/doctor.py +86 -0
  25. lockstep/commands/extract.py +169 -0
  26. lockstep/commands/falsify.py +108 -0
  27. lockstep/commands/index.py +16 -0
  28. lockstep/commands/jobs.py +188 -0
  29. lockstep/commands/layers.py +52 -0
  30. lockstep/commands/library.py +67 -0
  31. lockstep/commands/lock.py +58 -0
  32. lockstep/commands/log.py +132 -0
  33. lockstep/commands/node.py +429 -0
  34. lockstep/commands/note.py +76 -0
  35. lockstep/commands/probe.py +11 -0
  36. lockstep/commands/proof.py +31 -0
  37. lockstep/commands/ready.py +48 -0
  38. lockstep/commands/rules.py +61 -0
  39. lockstep/commands/search.py +37 -0
  40. lockstep/commands/status.py +172 -0
  41. lockstep/config.py +489 -0
  42. lockstep/context.py +33 -0
  43. lockstep/data/AuditCandidate.lean +18 -0
  44. lockstep/data/CacheArtifacts.lean +37 -0
  45. lockstep/data/Extract.lean.tmpl +362 -0
  46. lockstep/data/node.lean.tmpl +9 -0
  47. lockstep/delivery.py +45 -0
  48. lockstep/errors.py +28 -0
  49. lockstep/finalize.py +102 -0
  50. lockstep/gitutil.py +90 -0
  51. lockstep/hooks.py +143 -0
  52. lockstep/jobs.py +349 -0
  53. lockstep/layers.py +156 -0
  54. lockstep/lean.py +107 -0
  55. lockstep/library.py +188 -0
  56. lockstep/lock.py +68 -0
  57. lockstep/mcp_server.py +84 -0
  58. lockstep/metrics.py +12 -0
  59. lockstep/modules.py +197 -0
  60. lockstep/nodes.py +475 -0
  61. lockstep/operations.py +265 -0
  62. lockstep/output.py +45 -0
  63. lockstep/probes.py +72 -0
  64. lockstep/proofs.py +250 -0
  65. lockstep/resources.py +100 -0
  66. lockstep/shadow_index.py +47 -0
  67. lockstep/spec.py +36 -0
  68. lockstep/stage_runner.py +47 -0
  69. lockstep/storage.py +186 -0
  70. lockstep/store.py +338 -0
  71. lockstep/tags.py +84 -0
@@ -0,0 +1,218 @@
1
+ Metadata-Version: 2.4
2
+ Name: lean-lockstep
3
+ Version: 0.1.0
4
+ Summary: Coordinate several agents on a Lean 4 formalization: state derived from the compiled environment, locked statements, recorded claims and memory-guarded jobs
5
+ Author: Gavin Litchfield
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/GLitchfield/lean-lockstep
8
+ Project-URL: Repository, https://github.com/GLitchfield/lean-lockstep
9
+ Project-URL: Issues, https://github.com/GLitchfield/lean-lockstep/issues
10
+ Project-URL: Changelog, https://github.com/GLitchfield/lean-lockstep/blob/main/CHANGELOG.md
11
+ Keywords: lean4,formalization,theorem-proving,blueprint,ai-agents,mcp
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
22
+ Classifier: Topic :: Software Development :: Build Tools
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: mcp
27
+ Requires-Dist: mcp<3,>=2; extra == "mcp"
28
+ Provides-Extra: test
29
+ Requires-Dist: pytest; extra == "test"
30
+ Provides-Extra: research
31
+ Requires-Dist: numpy; extra == "research"
32
+ Dynamic: license-file
33
+
34
+ # lean-lockstep
35
+
36
+ A project harness for Lean 4 formalization work done by several agents at once: AI coding agents
37
+ of any kind (anything that can run a shell command or call an MCP tool) and people. It keeps the
38
+ state of the project (which statements are open, claimed, proved, and what depends on what)
39
+ derived from the compiled Lean environment, and it records who is doing what, why, and with how
40
+ much memory.
41
+
42
+ - **State comes from Lean, not from a document.** Each open statement is a *node*: a theorem
43
+ with a `sorry` in its own blueprint module, tagged in its docstring. `lockstep extract` reads the
44
+ compiled environment and reports each node as open, claimed or closed (sorry-free with
45
+ allowlisted axioms). There is no hand-kept status file that can drift.
46
+ - **Approved statements are locked.** `harness/statements.lock` records the type hash of every
47
+ approved statement. A proof that quietly weakens its statement shows up as a lock violation;
48
+ changing a statement takes `lockstep node restate`, which logs who approved it and why. This is the
49
+ failure mode that matters most when agents write the proofs.
50
+ - **Agents coordinate through the harness.** Claims expire and carry the intent (`--why`); every
51
+ release records an outcome; `lockstep log` and `lockstep journal` keep the trail; long commands run as
52
+ recorded, memory-capped jobs that every agent can see.
53
+ - **Audits scale.** The axiom audit is a per-module taint scan with a cache, which finishes on
54
+ projects where `#print axioms` does not.
55
+ - **No client or model is assumed.** Every command has a CLI and an MCP tool. A git pre-commit
56
+ hook guards commits for everyone; optional Claude Code hooks add a session banner and a guard
57
+ against compute launched outside the harness.
58
+
59
+ Status: experimental (0.1). Built and used in two research projects; expect rough edges outside
60
+ them. Linux first.
61
+
62
+ ## Requirements
63
+
64
+ - Python 3.11 or newer. The core has no dependencies; extras: `mcp` (MCP server), `test`
65
+ (pytest), `research` (NumPy for research-library probes).
66
+ - Lean 4 through [elan](https://github.com/leanprover/elan), Lake, and git.
67
+ - The memory guard runs each `lake` invocation in a capped `systemd-run --user` scope, so it
68
+ needs Linux with a systemd user session. Elsewhere set `[build] guard = false`.
69
+ - `bwrap` (bubblewrap) for the sandboxed proof checks of the experimental automation layer.
70
+
71
+ ## Try it
72
+
73
+ `examples/minimal` is a Lean-only Lake project (no Mathlib) with one core lemma and an empty
74
+ blueprint. From a checkout of this repository:
75
+
76
+ ```console
77
+ cd examples/minimal
78
+ export LOCKSTEP_AGENT=me:demo # every claim, job and log entry is recorded under this id
79
+ ../../bin/lockstep build core
80
+ ../../bin/lockstep extract # writes harness/nodes.json, index.json, status.md
81
+ ../../bin/lockstep node add --name double_succ --ws A --kind formalization \
82
+ --type "(n : Nat) : (n + 1) + (n + 1) = 2 * n + 2" \
83
+ --description "Doubling a successor." --depends double --dangling-ok "example"
84
+ ../../bin/lockstep ready # Demo.double_succ is open and ready
85
+ ../../bin/lockstep claim double_succ --why "rewrite with Demo.double, then omega"
86
+ # replace the `sorry` in DemoBlueprint/A/DoubleSucc.lean with `rw [double]; omega`
87
+ ../../bin/lockstep check double_succ # sorry=False status=closed
88
+ ../../bin/lockstep close double_succ # moves it into the core library, records the attempt
89
+ ../../bin/lockstep audit && ../../bin/lockstep journal
90
+ ```
91
+
92
+ `tests/test_example_lifecycle.py` runs the same sequence whenever `lake` is installed. To start
93
+ over, run `git checkout -- . && git clean -fdx .` in `examples/minimal`.
94
+
95
+ ## Installing
96
+
97
+ The harness writes Lean files into the project (the extractor, node modules) and its lock hashes
98
+ depend on the toolchain, so pin the version a project uses. Either:
99
+
100
+ - **From PyPI**, which puts `lockstep` and `lockstep-mcp` on the `PATH`:
101
+ ```console
102
+ uv tool install "lean-lockstep[mcp]==0.1.0" # or: pipx install "lean-lockstep[mcp]==0.1.0"
103
+ ```
104
+ Without PyPI access, install a tag from git instead:
105
+ `uv tool install "lean-lockstep[mcp] @ git+https://github.com/GLitchfield/lean-lockstep@v0.1.0"`.
106
+ - **As a git submodule**, pinned by commit and upgraded by bumping the pin, which suits a project
107
+ that also develops the harness:
108
+ ```console
109
+ git submodule add https://github.com/GLitchfield/lean-lockstep tools/lockstep
110
+ uv venv tools/lockstep/.venv && uv pip install -e "tools/lockstep[mcp]"
111
+ ```
112
+ `tools/lockstep/bin/lockstep` and `tools/lockstep/bin/lockstep-mcp` prefer that virtualenv and
113
+ fall back to the system `python3`.
114
+
115
+ The commands below write `lockstep`; with a submodule, that is `tools/lockstep/bin/lockstep`.
116
+
117
+ ## Adopting it in a project
118
+
119
+ 1. Give the Lake package two libraries: a core library (proved results only) and a blueprint
120
+ library whose root file imports every node module. `lockstep node add` maintains that root.
121
+ 2. Copy `examples/minimal/harness/` and edit `harness/config.toml`: namespaces, layers, build
122
+ targets, memory caps. Start `statements.lock` as `{}` and `allowlist.json` as `[]`.
123
+ 3. Ignore the harness state directory (`.lockstep/` with `[project] state_home = ".lockstep"`).
124
+ 4. Write the agent rules into the files your clients read (`AGENTS.md`, `CLAUDE.md`, ...) and
125
+ list them under `[rules]`; `lockstep rules` checks that they carry the same rule list (cheap enough
126
+ for CI). `examples/minimal/AGENTS.md` is a starting point. Tell each agent to export a stable
127
+ `LOCKSTEP_AGENT` (for example `<client>:<session id>`); claims and logs are recorded under it.
128
+ 5. Guard commits with the git hook, which works whoever commits:
129
+ ```console
130
+ printf '#!/bin/sh\nexec lockstep hook pre-commit\n' > .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit
131
+ ```
132
+ It refuses a commit that fails `lockstep layers`, `lockstep extract --check` (generated files out of date
133
+ or a locked statement changed) or `lockstep audit --changed`.
134
+ 6. Register the MCP server with your client: command `lockstep-mcp` (or `tools/lockstep/bin/lockstep-mcp`), stdio,
135
+ no arguments. For example `.mcp.json`:
136
+ ```json
137
+ { "mcpServers": { "lockstep": { "command": "tools/lockstep/bin/lockstep-mcp", "args": [] } } }
138
+ ```
139
+ 7. Optionally, for Claude Code, add the session and shell hooks to `.claude/settings.json`:
140
+ ```json
141
+ { "hooks": {
142
+ "SessionStart": [{ "hooks": [{ "type": "command", "command": "tools/lockstep/bin/lockstep hook session-start" }] }],
143
+ "PreToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "tools/lockstep/bin/lockstep hook pre-bash" }] }] } }
144
+ ```
145
+ `session-start` prints the session's agent id and `lockstep status --brief`. `pre-bash` blocks a
146
+ bare `nohup`/`systemd-run` (compute goes through `lockstep job run`) and runs the commit guard
147
+ before `git commit`/`git push`. Any client whose hooks pass the same JSON on stdin can use them.
148
+ 8. In CI, `python3 -m lockstep.lock BASE_LOCK HEAD_LOCK` (with `PYTHONPATH=tools/lockstep` for a submodule)
149
+ prints the log files a lock change must touch: `restatements.md` when an approved statement
150
+ changed or disappeared, `retired.md` for a refutation. New entries need none.
151
+ 9. Optionally, `tools/lockstep/systemd/install.sh` (from a checkout) installs a `lockstep-nightly-<project
152
+ id>` user timer (03:00) that runs the guarded core build, `lockstep extract --check` and `lockstep audit`.
153
+
154
+ ## Commands
155
+
156
+ | Area | Commands |
157
+ |---|---|
158
+ | State | `status`, `ready`, `node show`, `search`, `extract`, `extract --check`, `doctor` |
159
+ | Statements | `node add`, `node restate`, `node retire`, `lock refresh` (after a toolchain bump) |
160
+ | Work | `claim`, `release`, `check`, `close`, `falsify` (conjecture nodes) |
161
+ | Builds and jobs | `build core` / `blueprint` / `node`, `job run`, `job wait`, `job list`, `worker` |
162
+ | Trail | `log`, `journal`, `note` (weekly summary) |
163
+ | Integrity | `audit`, `layers`, `rules`, `hook pre-commit` |
164
+ | Client hooks | `hook session-start`, `hook pre-bash` |
165
+
166
+ Every command takes `--json`, and all but the hooks are also MCP tools. Node names may be
167
+ dotted relative to the declaration namespace (`--name List.foo` declares `theorem List.foo` in
168
+ it), and `--depends` lists the project declarations a node waits on (library lemmas belong in
169
+ the description).
170
+
171
+ ### Experimental
172
+
173
+ These work in the projects they came from but are less general; see
174
+ [`docs/automation.md`](docs/automation.md):
175
+
176
+ - **Automation layer**: durable `operation …` workflows run by `lockstep worker`, a results `inbox`,
177
+ `proof capture|check|prove`, `node finish`, `probe run|replay`, `context`.
178
+ - **Research library**: `lib search|show|list` over a project catalog
179
+ (`harness/research/catalog.json`).
180
+ - **Certificate layers**: `[layers]` rules for generated proof-module families, and
181
+ `storage share` for their compiled artifacts.
182
+
183
+ ## Things that cost hours to learn
184
+
185
+ - **Never `import` the project modules at the top of a `lake env lean --run` script that also
186
+ calls `importModules` on them.** The script's own import maps the oleans; the second load
187
+ cannot mmap at the same addresses and reads them into anonymous memory instead (37 GB and a
188
+ cgroup OOM kill on a project with large certificate modules). The extractor template imports
189
+ only `Lean`; `main` imports the project.
190
+ - **Never use `importAll := true`** for the extractor environment (30+ GB). A plain import
191
+ exposes every theorem value in `env.header.moduleData`.
192
+ - **Never run bare `lake build` on big targets.** Lake 5 has no `-j`; two dozen parallel
193
+ compilers exhaust a 20 GB guard. `lockstep build` builds Lake's out-of-date list one module per
194
+ guarded invocation first.
195
+ - **`#print axioms` does not finish on large generated proof families** (16 TB read in 3.5 h);
196
+ the extractor's module-order taint scan with a per-module cache is the audit path.
197
+ - **A module-system core root (`module` header) cannot import plain files.** When the core root
198
+ uses it, nodes are written in module form from the start, so a proof elaborates against the
199
+ same imports before and after `lockstep close`.
200
+ - **The elaborator moves parts of a proof into auxiliary declarations** (`foo._proof_1`), so a
201
+ dependency scan of a theorem's value alone reports the auxiliaries instead of the lemmas they
202
+ use. The extractor looks through a declaration's own auxiliaries.
203
+
204
+ ## Development
205
+
206
+ ```console
207
+ uv venv .venv && uv pip install -e ".[test,mcp,research]"
208
+ .venv/bin/python -m pytest
209
+ ```
210
+
211
+ Releases follow semantic versioning (0.x: minor versions may break). Changes are listed in
212
+ [`CHANGELOG.md`](CHANGELOG.md). To release, bump `__version__` in `lockstep/__init__.py`, add the
213
+ changelog entry, and push a `vX.Y.Z` tag: `.github/workflows/release.yml` builds the sdist and
214
+ wheel and publishes them to PyPI through trusted publishing.
215
+
216
+ ## License
217
+
218
+ MIT; see [`LICENSE`](LICENSE).
@@ -0,0 +1,71 @@
1
+ lean_lockstep-0.1.0.dist-info/licenses/LICENSE,sha256=FRI9ysgFGRFWTgdRUuJ7EryPx7thYVvmRICme89SwHo,1133
2
+ lockstep/__init__.py,sha256=jnxyg-EVE_XpyYkgdpkgwerj1D2qImhto_QVByFS0L4,508
3
+ lockstep/__main__.py,sha256=Odn24AAjrNqQllq6d-xtA79UrYAx0ulq-sa6FFhInVY,56
4
+ lockstep/allowlist.py,sha256=g9YdlAlFEk8eBCJLzD3rBDFBd7dmt4owo5tsfhrJfEg,1309
5
+ lockstep/artifact_cache.py,sha256=YKUxb9XPlyKMknoRKYh3Vknq-_68sa5d796149alrCE,21870
6
+ lockstep/artifacts.py,sha256=2uA9vTelY4NbEfvhnYrPiTA0yBoRehsPaFWvJYKnWoE,8190
7
+ lockstep/automation_schema.py,sha256=KcSqxDMPLcvHdhF28hB5qANLhlYURvB-MSZMzp3Zbtk,2007
8
+ lockstep/build.py,sha256=sTJnA48apX0SLShqPCbgBpEDthgQe_4Jt6cDy9ODoTs,22999
9
+ lockstep/bundles.py,sha256=_qAWfO2VYjYzOVy2faujecuWNj9e-vbXlKzSWL5PQC8,2093
10
+ lockstep/cli.py,sha256=aZLpCAtREDTM9VOdjj8T92MgfTtkIYgsxqkTp2Ggfv4,6536
11
+ lockstep/config.py,sha256=9E9TOo-UMYFeMMGnaNV-2zckCbjj9bQ6Jh8-kuZZhIY,18487
12
+ lockstep/context.py,sha256=tLi8_DIwBpBANwcHRmVnWRexVsK899ZcvD10mTVmTps,816
13
+ lockstep/delivery.py,sha256=9KKK3dfdcpjP1ydHvVuWnvyYZxh3z7J2SN6nsjqfqp0,2295
14
+ lockstep/errors.py,sha256=m28f9pjQyUrn3gBmaxcMbR8H3jVmjohrgrwbFi1vOaI,597
15
+ lockstep/finalize.py,sha256=u5NknUm_GClpifJbyDPzbqdA86NMcm6UPgos2RbLXQI,6256
16
+ lockstep/gitutil.py,sha256=P4WbY8SlcgUAI1Oj1UeeOPs9AydAALCHU4H3sCzmKgs,3455
17
+ lockstep/hooks.py,sha256=FUkc81wSslX78Jq4LnTV4bLfQLrUpSWa5tO6Ubfner8,6501
18
+ lockstep/jobs.py,sha256=5alv4UCxo30jyQ1SKb6r2QNt0G4w2B8TQtAEAamG8Bw,17690
19
+ lockstep/layers.py,sha256=IeodoeIuz5DbpKKoLPENnRQz7C5ktkQHcBMbQbnE8-0,7153
20
+ lockstep/lean.py,sha256=Xm2_6-r_MknvM8ACnZ5XQ-WpzBSW4nMLtyqYQj7UIuk,4638
21
+ lockstep/library.py,sha256=dWTz0BUKtym_CgUh6cDMpGgQBjoleVtkF0r4wTZa4Hs,7520
22
+ lockstep/lock.py,sha256=MHFhI276l3_ykmUpFTucOQQc3Y2Z5G3lLwL4A_DhEZ8,2635
23
+ lockstep/mcp_server.py,sha256=Pr98jBYxdQ7SCTKLXYChyYQF8d5e554NWDxvOesMkSk,3277
24
+ lockstep/metrics.py,sha256=7HrVcjCGtrM_KbkfhVOVVPNfb47ALTIPAPctd5dZ69I,463
25
+ lockstep/modules.py,sha256=xIJyovRvA1cQCVjxYa_oUjm9QVda-EodHSKnTr_N5w0,6685
26
+ lockstep/nodes.py,sha256=-jT19FMYdAnF_-XMbFnlRL4u2dgqBBfRpl5EXxwqVas,19203
27
+ lockstep/operations.py,sha256=W7BKc-iGQrOi4_eDq2maILmE1Le3F__p7I2rlyFY9qk,18253
28
+ lockstep/output.py,sha256=TqYzKtCx8FLv_myo4NUEzz4C9N1OR9nEjci-uqF_rCQ,1393
29
+ lockstep/probes.py,sha256=MtUHZJiAVBFBQqVxoUlGEWpzbx93n7dtSPRltC64tVA,3260
30
+ lockstep/proofs.py,sha256=zyJVZJfJXmB7fAgqWdssrUtHPoh4HeqQwNNr8u2XpY8,13212
31
+ lockstep/resources.py,sha256=9uaPqa7rQtL1Kid473-bCKfJpeRW4ThaUSMF51Lp2aM,4677
32
+ lockstep/shadow_index.py,sha256=z626y8BNBIklAt7WFk7Ix-918-SfgFy67qRY8bVyukA,2723
33
+ lockstep/spec.py,sha256=h124-0IVxX23Yjj60Cnm5RVsRLUDdhlF7Wjr8lPNGj4,918
34
+ lockstep/stage_runner.py,sha256=Wu84Wu1JlELSxKuOiVw1IqGWpx9C8qQFjiNcQ8Op3As,1795
35
+ lockstep/storage.py,sha256=Iz74tWn6Mv6C_FjtI4lTOYxL8mXsWjzFIYK8YCc64Z0,6905
36
+ lockstep/store.py,sha256=MoXCDkKTTVGBFFg_ilEmPNK4DzmqPB9jZQWzqdL_9Xg,17071
37
+ lockstep/tags.py,sha256=x7vzm4FCE_1XF8XVwtScoib4e6ozP7fCWs0TxsGf-Vo,2837
38
+ lockstep/commands/__init__.py,sha256=ELPjq-vnW-KlU8JbmPGyoXlM3fHXJyp8dKIBYSLRT4g,403
39
+ lockstep/commands/audit.py,sha256=WNS5CKFw3uAYz6XVMd55XSLCkvmScgODNAMfd2ITBRk,2269
40
+ lockstep/commands/automation.py,sha256=yqWTo8id3FRBdUdEGyesbZjOqySk4hJUH-ITFEgN-dU,4913
41
+ lockstep/commands/build.py,sha256=LTQXLlc8mqnPxolpZ-81Khzw5kpXJxfLIctaZF_3ESY,2699
42
+ lockstep/commands/cache.py,sha256=4OXCGrL1TbGMBkCbHtDy4iBs_zTUl6PTlpgMmOHrX9w,2453
43
+ lockstep/commands/check.py,sha256=jtrG9JoTWW08xTZix7-uRPuqGM5AjBS3PonHd28DXYo,4261
44
+ lockstep/commands/claims.py,sha256=BLBN5wH_BKmstD6pX_aTzdEEyCQwKSGYk8B9z9k4JMA,3962
45
+ lockstep/commands/close.py,sha256=VvulasoNJu5fafYdUei8gw5quSx3_5qyIQ0TV_LBgdk,10617
46
+ lockstep/commands/doctor.py,sha256=TzmOxjXeEesbc4g9K2r71LL9bw137vwpR3UOh53qAk8,4902
47
+ lockstep/commands/extract.py,sha256=TtXMzNyX8OxqfVkfcjFig-R1gwcFubI2_YRUVyaZChQ,8456
48
+ lockstep/commands/falsify.py,sha256=wZDkDUiZIL3uwPSUDMbWAoOQAwaKxWA3JSaDKv61MQw,5557
49
+ lockstep/commands/index.py,sha256=un_w696UgxQPBdauvzn_NDiBpdgZCaPZSD8DW0HN4_o,831
50
+ lockstep/commands/jobs.py,sha256=tAOTY5mH1T1lCJHMZWf4tlhDnFyEy0IsFYJr_mAQlcQ,10797
51
+ lockstep/commands/layers.py,sha256=_qBX2iRFdtDZ4Q7Kn-Gkfbe5k5BVl0FdsN_o3tArYog,2297
52
+ lockstep/commands/library.py,sha256=Z2CiXTkoRvNIdzHNOqLDBZyw1Hx-0zFeIhPvuTQhZFg,2141
53
+ lockstep/commands/lock.py,sha256=YNCSn2xCBAZZokSEJGp0cuD8kW0wl07-GVBvn8h2Zt8,2844
54
+ lockstep/commands/log.py,sha256=1Z-55bfoNV7m1H4WWKBmS2rvuypTe7isKA6hGbi5JWw,6390
55
+ lockstep/commands/node.py,sha256=DprWQUtnvomd2Sc3Si3IeDOxqPvTYxpoXHa4yhl4Z6I,21592
56
+ lockstep/commands/note.py,sha256=6HO5P0e2i4JCiZCSaq6V2JdcCIqZeJrIvDTYgKxgEVg,4428
57
+ lockstep/commands/probe.py,sha256=kAHB5ML5du41rpSjxQ4PpxZPEw5oND1zpSEq0jfKqmM,731
58
+ lockstep/commands/proof.py,sha256=kgQh6AHd8_pjd2F461WmzzTaWpIa4HhgEjHLruVStGA,2506
59
+ lockstep/commands/ready.py,sha256=S4NkDvKLBrWdCjvqMIM-JP_R-5rj9SzLRNMEzs-3L5w,1596
60
+ lockstep/commands/rules.py,sha256=UpbPbINqRqK7fgIcSzbv_bkHHlwzCvDXhi6tzE71cug,2393
61
+ lockstep/commands/search.py,sha256=1z1zp8eJDgfVLpEhaIp9256UzpdIWmuhkfTdPXAZPaQ,1818
62
+ lockstep/commands/status.py,sha256=GOSNiqO7EKNkxLh2cN0Ifq-uHOx3SsnwY5JuaDXNSCs,7882
63
+ lockstep/data/AuditCandidate.lean,sha256=V7aXWsYgsiQA3U2T0cqgJsjkkS_dR3M3hgMGd5latlo,730
64
+ lockstep/data/CacheArtifacts.lean,sha256=hYOp3CJGrhMXagKagOEltwFrlcuF1CXW2iALJDJD_oA,1302
65
+ lockstep/data/Extract.lean.tmpl,sha256=HB68q0ZKqXWY2VYpmLnMdlz6dt_NzEBoAT1lqSJnv3o,16183
66
+ lockstep/data/node.lean.tmpl,sha256=Q_aIfa8-3BPqP1hvdWRMXybJMcgCbsgwL0_KMq3iwjY,140
67
+ lean_lockstep-0.1.0.dist-info/METADATA,sha256=25D-YVzjDILAv801PfdvkpI55_rM1UqGFa6qllrjt3M,12357
68
+ lean_lockstep-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
69
+ lean_lockstep-0.1.0.dist-info/entry_points.txt,sha256=vBNlVbHFrmlj8L6S_bUxPGfRK26ZmhBog90pMkSHkjw,87
70
+ lean_lockstep-0.1.0.dist-info/top_level.txt,sha256=QNoTwkeoY08NJpMS_9r_I9v1_ILr-ubzRM-tL-GAiAM,9
71
+ lean_lockstep-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ lockstep = lockstep.cli:main
3
+ lockstep-mcp = lockstep.mcp_server:main
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gavin Litchfield
4
+ Copyright (c) 2026 Matt Pocock (Wayfinder-derived portions)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ lockstep
lockstep/__init__.py ADDED
@@ -0,0 +1,17 @@
1
+ """lockstep: a blueprint harness whose project state is derived from the compiled Lean environment.
2
+
3
+ Nothing in this package may name a project-specific module, theorem, or path;
4
+ all of that comes from ``harness/config.toml`` in the project root.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ __version__ = "0.1.0"
10
+
11
+ # Lean templates and drivers shipped with the package (package data, so a wheel install works)
12
+ DATA = Path(__file__).resolve().parent / "data"
13
+
14
+ EXIT_OK = 0
15
+ EXIT_CHECK_FAILED = 1
16
+ EXIT_USAGE = 2
17
+ EXIT_LEAN = 3
lockstep/__main__.py ADDED
@@ -0,0 +1,3 @@
1
+ from lockstep.cli import main
2
+
3
+ raise SystemExit(main())
lockstep/allowlist.py ADDED
@@ -0,0 +1,40 @@
1
+ """Axiom allowlist: which non-standard axioms may reach which declarations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import fnmatch
6
+ import json
7
+ from pathlib import Path
8
+
9
+
10
+ def read_allowlist(path: Path) -> list[dict]:
11
+ if not path.exists():
12
+ return []
13
+ data = json.loads(path.read_text() or "[]")
14
+ return data if isinstance(data, list) else []
15
+
16
+
17
+ def write_allowlist(path: Path, entries: list[dict]) -> None:
18
+ path.write_text(json.dumps(entries, indent=2, ensure_ascii=False) + "\n")
19
+
20
+
21
+ def uncovered(entries: list[dict], name: str, axioms: list[str], standard: list[str]) -> list[str]:
22
+ """Axioms of ``name`` (beyond the standard set) not covered by any allowlist entry."""
23
+ out = []
24
+ for ax in axioms:
25
+ if ax in standard:
26
+ continue
27
+ ok = False
28
+ for e in entries:
29
+ pat = str(e.get("axiom", ""))
30
+ # Lean 4.29 gives every `native_decide` its own auxiliary axiom
31
+ # (`<decl>._native.native_decide.ax_1_1`), so entries may be globs.
32
+ if pat != ax and not fnmatch.fnmatchcase(ax, pat):
33
+ continue
34
+ reaches = e.get("reaches", [])
35
+ if "*" in reaches or name in reaches:
36
+ ok = True
37
+ break
38
+ if not ok:
39
+ out.append(ax)
40
+ return out