{"id":50446888,"url":"https://github.com/verilean/mechproof","last_synced_at":"2026-05-31T22:02:27.160Z","repository":{"id":357311377,"uuid":"1236354339","full_name":"Verilean/mechproof","owner":"Verilean","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-12T09:13:40.000Z","size":199,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-26T00:29:33.128Z","etag":null,"topics":["formal-verification","lean4","physics","robotics"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Verilean.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-12T07:10:47.000Z","updated_at":"2026-05-13T06:54:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Verilean/mechproof","commit_stats":null,"previous_names":["verilean/mechproof"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Verilean/mechproof","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Verilean%2Fmechproof","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Verilean%2Fmechproof/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Verilean%2Fmechproof/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Verilean%2Fmechproof/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Verilean","download_url":"https://codeload.github.com/Verilean/mechproof/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Verilean%2Fmechproof/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33750476,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["formal-verification","lean4","physics","robotics"],"created_at":"2026-05-31T22:02:26.378Z","updated_at":"2026-05-31T22:02:27.153Z","avatar_url":"https://github.com/Verilean.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MechProof\n\n\u003e **Formally-verified hardware compiler.** Robot designs that don't pass\n\u003e the Lean 4 proofs simply never generate any CAD or simulation\n\u003e artefacts — the build halts. Designs that do are guaranteed by\n\u003e construction to satisfy every geometric, kinematic, energetic,\n\u003e environmental, and safety property the library defines.\n\n```\n$ make poc16                # full headline pipeline (PoC 1 → 16, ~5 min)\n$ make test                 # 13 mutated bad designs — Lean must reject all\n$ make help                 # every available target\n```\n\n------------------------------------------------------------------------\n\n## Why MechProof exists\n\nMost robot specs live in Word documents, then get translated by humans\ninto CAD, then into URDF, then into MuJoCo, then into firmware — drifting\nat every step. MechProof flips that:\n\n1. The spec is a **Lean 4 structure** with theorems attached.\n2. Lean's `native_decide` discharges those theorems against concrete\n   numbers.\n3. **Only if all theorems pass** does the build emit CAD (STEP files),\n   URDF, MuJoCo XML, and ROS-compatible JSON metadata.\n4. The same numbers Lean proved are the numbers the simulator runs.\n   Mismatches are impossible by construction.\n\nThis is exactly the discipline `cargo build` enforces for Rust types,\nbut applied to physical correctness conditions like\n\"the thumb doesn't crush the index finger when the swivel goes to max\"\nor \"the knee motor can hold up 2.3 tonnes.\"\n\n------------------------------------------------------------------------\n\n## Repo layout\n\n```\nmechproof/\n├── MechProof.lean              ← library entry point (re-exports modules)\n├── MechProof/                  ← reusable Lean modules (the *library*)\n│   ├── Basic.lean              ← PoC 1   moldability\n│   ├── Finger.lean             ← PoC 2   3-link finger kinematics\n│   ├── TendonFinger.lean       ← PoC 3   tendon-driven flexion\n│   ├── HandAssembly.lean       ← PoC 4   5-finger capsule clearance\n│   ├── DFM.lean                ← PoC 5   manufacturing rules\n│   ├── ArmAssembly.lean        ← PoC 6   arm static torque\n│   ├── LegAssembly.lean        ← PoC 8   leg balance + squat torque\n│   ├── Walking.lean            ← PoC 10  ZMP / LIPM\n│   ├── CapturePoint.lean       ← PoC 11  capture-point stability\n│   ├── Energy.lean             ← PoC 12  power + endurance\n│   ├── Environment.lean        ← PoC 13  EnvironmentParams (air/subsea/lunar/mars/…)\n│   ├── Subsea.lean             ← PoC 13  pressure / buoyancy / drag\n│   ├── HeavyMachinery.lean     ← PoC 15  scale-up + yield\n│   └── PilotSafety.lean        ← PoC 16  override + crash brace\n│\n├── Tests/                      ← per-PoC entrypoints (one Lean exe + one orchestrator each)\n│   ├── Main.lean               ← `verify_mechproof`\n│   ├── VerifyFinger.lean       ← `verify_finger`\n│   ├── …                       ← VerifyTendon / VerifyHand / VerifyArm / VerifyLegs /\n│   │                             VerifyWalking / VerifyCapture / VerifyEnergy /\n│   │                             VerifySubsea / VerifyEnvMatrix / VerifyHeavy /\n│   │                             VerifySafety\n│   └── run_poc*.sh             ← orchestrators (Lean → Python → simulator → report)\n│\n├── python/                     ← CAD generators + MuJoCo simulators + report writers\n├── schema/                     ← JSON schemas for Lean-emitted ground-truth files\n├── lakefile.toml               ← Lake project root (Lean 4 build config)\n├── lean-toolchain              ← pinned Lean version (leanprover/lean4:v4.x.y)\n├── Makefile                    ← human-facing interface (`make help`)\n├── shell.nix                   ← Nix dev shell (lean, OCP runtime libs, etc.)\n└── out/                        ← generated artefacts (gitignored)\n```\n\n------------------------------------------------------------------------\n\n## How a MechProof theorem is structured\n\nEvery PoC follows the same pattern. Here's the **DFM** check (PoC 5) as\nthe canonical example.\n\n### 1.  Declare the data the theorem operates on\n\nIn `MechProof/DFM.lean`:\n\n```lean\nstructure TendonChannelGeom where\n  channelRadius : Float    -- m\n  momentArm     : Float    -- m, offset from joint axis\n  deriving Repr, Inhabited\n```\n\n### 2.  Encode the physical rule as a `Prop`\n\n```lean\nabbrev linkManufacturable\n    (linkThickness : Float) (g : TendonChannelGeom) : Prop :=\n  MIN_TENDON_HOLE_DIA_M / 2 ≤ g.channelRadius ∧\n  MIN_WALL_THICKNESS_M ≤\n    linkThickness / 2 - g.momentArm - g.channelRadius\n```\n\n* `abbrev` rather than `def` so the inequality is **reducible** during\n  typeclass inference — that's what lets `native_decide` see it as a\n  computable boolean.\n* The body is a strict inequality on `Float`. `Float.\u003c` is decidable in\n  Lean, so the whole proposition is decidable; `native_decide` evaluates\n  it at compile time using compiled IR.\n\n### 3.  Instantiate concrete numbers in `Tests/VerifyHand.lean`\n\n```lean\ndef stdChannels : FingerChannels :=\n  { ch1 := { channelRadius := 0.0006, momentArm := 0.0025 },\n    ch2 := { channelRadius := 0.0006, momentArm := 0.0020 },\n    ch3 := { channelRadius := 0.0006, momentArm := 0.0015 } }\n\ndef candidateManufacturable :\n    candidate.Manufacturable candidateChannels := by\n  native_decide\n```\n\nIf any number ever drifts to a non-compliant value (say\n`channelRadius := 0.0003` — too small for injection moulding),\n`native_decide` evaluates the conjunction to `false` and the build\naborts with\n\n```\nerror: Tactic `native_decide` evaluated that the proposition\n       candidate.Manufacturable candidateChannels is false\n```\n\n### 4.  Emit the proven numbers as JSON so downstream tools can consume them\n\n```lean\ndef main : IO Unit := do\n  let _ : candidate.WellFormed := candidateWellFormed\n  let _ : candidate.Manufacturable candidateChannels := candidateManufacturable\n  IO.FS.createDirAll \"out\"\n  IO.FS.writeFile \"out/hand_params.json\"\n    (renderJson candidate candidateChannels)\n```\n\nCrucially `IO.FS.writeFile` only runs *after* the `let _ : … := …`\nlines, and those lines only typecheck if the proofs hold. So **the JSON\nfile exists ⇔ the proofs passed**.\n\n### 5.  Python tools blindly trust the JSON\n\n`python/generate_hand_cad.py` reads `hand_params.json` and turns it into\nSTEP files. It does **not** re-validate the numbers — the file's\nexistence is the validation.\n\n------------------------------------------------------------------------\n\n## How a PoC orchestrator (run script) is structured\n\n`Tests/run_pocN.sh`:\n\n```bash\n#!/usr/bin/env bash\nset -euo pipefail\n\ncd \"$(dirname \"$0\")/..\"     # always run from repo root\nmkdir -p out\n\n# 1. Discharge the Lean proof. `set -e` makes the script abort if\n#    `lake exe` exits non-zero (which happens when `native_decide`\n#    rejects).\nif ! ( lake build verify_xxx \u0026\u0026 lake exe verify_xxx ); then\n  echo \"Verification Failed: ...\" \u003e\u00262\n  exit 1\nfi\n\n# 2. Generate CAD from the JSON Lean just wrote.\n./venv/bin/python python/generate_xxx_cad.py\n\n# 3. Run MuJoCo simulation against the CAD.\n./venv/bin/python python/simulate_xxx.py\n```\n\nThe Makefile wraps every script in `nix-shell --run …` so users never\nhave to think about the Nix environment.\n\n------------------------------------------------------------------------\n\n## Quick-start (5 minutes)\n\n```bash\n# 1. Enter the Nix dev shell (one-time setup).\nnix-shell\n\n# 2. Build the Lean library (downloads the toolchain on first run).\nmake build\n\n# 3. Run the full headline pipeline.\nmake poc16\n# → out/Manned_Safety_Report.txt   \"RESULT: PASS\"\n# → out/safety_params.json         (Lean-certified pilot safety params)\n# → out/cockpit_g_force.json       (MuJoCo 1 kHz accelerometer trace)\n\n# 4. Prove the proof gate actually works by deliberately breaking\n#    13 designs.\nmake test\n# → 13/13 PASS — every bad design correctly rejected by Lean.\n\n# 5. List every available target.\nmake help\n```\n\n------------------------------------------------------------------------\n\n## Negative tests (the gate's gate)\n\n`make test` runs 13 sed-mutated builds, one per PoC, each demonstrating\nthat a deliberately-broken design **cannot** pass Lean. The mutations:\n\n| Test                | Mutation                                                | Theorem that catches it      |\n|---------------------|---------------------------------------------------------|------------------------------|\n| `test-moldability`  | `draftDeg := 2.0` → `-1.0`                              | `wellFormed_implies_moldable` |\n| `test-tendon`       | `r2 := 2.5` → `-1.0`                                    | `PositiveFlexion`            |\n| `test-collision`    | thumb mount onto index finger                            | `ThumbIndexClear`            |\n| `test-dfm-wall`     | finger thickness 10 mm → 2 mm                            | `Manufacturable`             |\n| `test-dfm-hole`     | tendon channel ⌀ 1.2 mm → 0.6 mm                         | `Manufacturable`             |\n| `test-torque`       | shoulder stall 30 N·m → 5 N·m                            | `StallSufficient`            |\n| `test-balance`      | foot length 160 mm → 20 mm                               | `Balanced`                   |\n| `test-zmp`          | CoM accel 0 → 5 m/s²                                     | `allStable` (ZMP)            |\n| `test-capture`      | CoM velocity 0.3 → 5.0 m/s                               | `allCapturable`              |\n| `test-energy`       | battery 800 Wh → 100 Wh                                  | `MissionPossible`            |\n| `test-crush`        | subsea 500 m → Mariana trench (110 MPa)                  | `PressureClearance`          |\n| `test-square-cube`  | 4 m mech with PoC 8's 40 N·m motors                      | `HeavyTorqueSufficient`      |\n| `test-lethal-crash` | brace stroke 100 mm → 10 mm (cockpit G = 100)            | `SurvivalBrace`              |\n\nEach script-mutated file is restored from a backup via `trap`, so\nfailed tests never leave the repo in a bad state.\n\n------------------------------------------------------------------------\n\n## How to add a new theorem\n\n1. **Define the structure + Prop** in a new file under `MechProof/`.\n   Mark the `Prop` `abbrev` so it's decidable.\n2. **Instantiate concrete numbers** in `Tests/VerifyYourThing.lean`:\n\n   ```lean\n   import MechProof\n   open MechProof\n\n   def candidate : YourStruct := …\n   def candidateOk : candidate.YourProperty := by native_decide\n\n   def main : IO Unit := do\n     let _ : candidate.YourProperty := candidateOk\n     IO.FS.writeFile \"out/your_params.json\" (renderJson candidate)\n   ```\n\n3. **Wire it into Lake**: add an `[[lean_exe]]` entry to `lakefile.toml`:\n\n   ```toml\n   [[lean_exe]]\n   name = \"verify_your_thing\"\n   root = \"Tests.VerifyYourThing\"\n   ```\n\n4. **Add a Make target** in `Makefile`:\n\n   ```make\n   verify-your-thing: ## one-line description\n     $(NIX_RUN) \"cd $(LEAN_DIR) \u0026\u0026 lake build verify_your_thing \u0026\u0026 lake exe verify_your_thing\"\n   ```\n\n5. **Add a negative test** so `make test` keeps proving the gate works:\n\n   ```make\n   test-your-thing:\n     $(call expect_fail,$(LEAN_DIR)/Tests/VerifyYourThing.lean, \\\n            s|good_value|bad_value|, \\\n            cd $(LEAN_DIR) \u0026\u0026 lake build verify_your_thing)\n   ```\n\nThat's the whole pipeline. Each PoC in `MechProof/` and `Tests/` is a\nworked example of this five-step recipe.\n\n------------------------------------------------------------------------\n\n## Coverage matrix\n\n| PoC | Topic                            | Library file             | Verify exe              |\n|-----|----------------------------------|--------------------------|-------------------------|\n| 1   | Injection-mould draft            | `Basic.lean`             | `mechproof`             |\n| 2   | 3-link finger kinematics         | `Finger.lean`            | `verify_finger`         |\n| 3   | Tendon-driven flexion            | `TendonFinger.lean`      | `verify_tendon`         |\n| 4   | 5-finger capsule clearance       | `HandAssembly.lean`      | `verify_hand`           |\n| 5   | DFM (wall thickness + hole dia)  | `DFM.lean`               | (in `verify_hand`)      |\n| 6   | Arm static torque                | `ArmAssembly.lean`       | `verify_arm`            |\n| 7   | Grasp matrix + v1 packaging      | (Python-only)            | —                       |\n| 8   | Lower-body balance + squat       | `LegAssembly.lean`       | `verify_legs`           |\n| 9   | Humanoid v1.0 release archive    | (Python-only)            | —                       |\n| 10  | LIPM / ZMP walking               | `Walking.lean`           | `verify_walking`        |\n| 11  | Capture-Point + URDF + IMU       | `CapturePoint.lean`      | `verify_capture`        |\n| 12  | Battery / endurance              | `Energy.lean`            | `verify_energy`         |\n| 13  | Subsea 500 m operation           | `Subsea.lean`            | `verify_subsea`         |\n| 14  | Multi-environment catalog        | `Environment.lean`       | `verify_env_matrix`     |\n| 15  | 4 m / 2.3 t heavy machinery      | `HeavyMachinery.lean`    | `verify_heavy`          |\n| 16  | Piloted-mech safety              | `PilotSafety.lean`       | `verify_safety`         |\n\n------------------------------------------------------------------------\n\n## Dependencies\n\nCaptured declaratively in `shell.nix`:\n\n* **Lean 4** (`elan default stable` on first entry)\n* **CadQuery / OCP** native runtime libs (`libstdc++`, `libGL`,\n  `libGLU`, `fontconfig`, `libXi`, …) surfaced via `LD_LIBRARY_PATH`\n* **MuJoCo 3.8**, **Pillow**, **mujoco-python** in `./venv/`\n* **Verilator / iverilog / yosys** + RISC-V cross-compilers (legacy\n  HDL toolchain — unused by the active PoCs but kept for parity with\n  earlier hardware tooling work)\n\n`./venv/` is created via `pip install cadquery mujoco Pillow` and is\ngitignored — re-create with the same `pip install` calls you'll see in\nthe PoC scripts' comments if you're starting fresh.\n\n------------------------------------------------------------------------\n\n## Continuous Integration\n\n`.github/workflows/ci.yml` runs on every push to `main` and on every\npull request. Two jobs execute in parallel:\n\n| Job | What it does | Typical duration |\n|---|---|---|\n| `lean-proofs` | `lake build` every verify exe, then `make verify-all` and `make test` (13 negatives) | ~5 min |\n| `cad-and-sim` | `make poc15` (Lean → CAD → MuJoCo physics for the 4 m heavy mech) plus `make preview` — a pygfx/WebGPU renderer that draws each scene from 4 angles to PNG, with **zero OpenGL dependency** | ~25 min |\n\nThe `cad-and-sim` job uploads `out/` as an **artifact**\n(`mechproof-out-\u003csha\u003e`) containing:\n\n* **STEP files** — every CAD part (palm, fingers, arm links, torso,\n  legs, foot, brackets, wrist flange, heavy-machinery tubes)\n* **MuJoCo `.xml` scenes** — drop-in for IsaacSim / Brax / RaiSim too\n* **JSON specs** — Lean-certified ground-truth values\n* **PNG previews** — `preview_\u003cscene\u003e_\u003cangle\u003e.png` (front / side / iso /\n  top), rendered offscreen via WebGPU (Vulkan + Lavapipe, no OpenGL)\n* **Reports** — `Manufacturing_Certificate.txt`, `Stand_Report.txt`,\n  `Heavy_Construction_Catalog.txt`, `Manned_Safety_Report.txt`, …\n* **URDF** — `mechproof_humanoid.urdf` (ROS 2 / Gazebo / RViz)\n\nDownload the zip from the PR's \"Checks\" tab → \"Summary\" → \"Artifacts\"\nsection, unzip, and review the geometry without needing any CAD viewer\ninstalled locally — every part has at least one rendered preview.\n\n------------------------------------------------------------------------\n\n## License\n\nLicensed under the **Apache License, Version 2.0** — see\n[`LICENSE`](LICENSE) for the full text and [`NOTICE`](NOTICE) for the\nattribution. In short: use it, modify it, redistribute it, ship it in\ncommercial products; just preserve the copyright + license notice and\nmark any files you modified.\n\n```\nCopyright 2026 Junji Hashimoto\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fverilean%2Fmechproof","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fverilean%2Fmechproof","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fverilean%2Fmechproof/lists"}