gdp-wired

Open source · MIT · every proof checked again by Lean

gdp-wired

An automatic prover for stateful rules.

Budgets, caps, rate limits, workflows, access policies. You write the rule and the laws it must keep. gdp-wired proves them with no proof to write, shows a real run that breaks a law when it's false (found by searching on the GPU), has every proof checked again by Lean, and ships the rule as JavaScript.

The same law, three ways

The proof is one line.

A request of cost c is admitted while spend s is under budget b; each request is capped at m. The law: spend stays within b + m after any sequence of requests. Real code from the repository's compare/, each one checked.

import {min, nat, proveRule, rule, when} from 'gdp-wired'

// A request of cost c is admitted while spend s is under budget b; each request is capped at m.
const budget = rule('budget')
  .params({b: nat, m: nat})
  .inputs({c: nat})
  .state({s: 0})
  .step(({b, m, c, s}) => ({s: when(s.lt(b), s.plus(min(c, m)), s)}))

// The law
const bounded = budget.law('spend stays within b + m', ({s, b, m}) => s.atMost(b.plus(m)))

// The proof
proveRule(budget, [bounded]) // {proven: true, checked: true}

Proven by induction over steps; the kernel checks the tree the prover grows. 25 ms, whole command.

Measured on the same three rules: one Modal run, 2 CPUs per job, median of 5 (source)
RuleToolProof linesCheck, median
budgetgdp-wired125 ms
Lean8488 ms
Bend84137 ms
capsgdp-wired144 ms
Lean30547 ms
Bend74161 ms
windowgdp-wired242 ms
Lean29571 ms
Bend117156 ms

Most of each check time is the tool's startup floor: 17 ms for gdp-wired, 134 ms for Bend, 453 ms for Lean. Every tool was also handed the same bug for each rule, and rejected it.

When a law is false

You get a real run that breaks it.

Forget the cap: write s.plus(c) instead of s.plus(min(c, m)). The kernel refuses the proof, and a search from the start turns the failure into a run you can replay.

Searches over short histories run on the GPU; every hit is replayed before it counts.

// the step, with the cap forgotten
.step(({b, c, s}) => ({s: when(s.lt(b), s.plus(c), s)}))

proveRule(budget, [bounded])
// refused, and a run that breaks the law:
// {params: {b: 1, m: 0}, trace: [{c: 2}]}

What it proves

Laws about state, automatically.

92 rules from nine domains in the examples (finance, access control, public services, operations, protocols, commerce, supply chains, games, education), each checked three ways.

59 of 59 laws from a Bend project's policy core (jev-fabric), ported and proven automatically.

Two structures, one boundary

Win the boundary. Hand off the rest.

Where gdp-wired, Lean and Bend sit Lean is the outer region: anything you write the proof for. Inside it, gdp-wired decides laws about stateful rules automatically, fed by the run algebra and Handwired. Bend sits beside, overlapping Lean. Arrows show the handoff: every gdp-wired proof leaves as a Lean theorem, and a function proven in Lean enters the rule as facts. Lean anything you write the proof for Bend proved programs, run on GPUs gdp-wired laws of stateful rules, decided automatically proveRule(rule, laws) {proven: true, checked: true} run algebra Handwired every proof, a Lean theorem facts proven in Lean

The run algebra

Every obligation the kernel builds is one inclusion over runs, made from a few moves: start, assume, read a request, take a step. Invariants, step laws, histories, liveness, refinement and loops all reduce to it, and one Lean twin of it (SMachine) is proven sound.

Handwired

Rules compile to GPU loop programs, through a fork of Cheng Lou's Handwired: the search that finds a breaking run, and the synthesizer that finds a missing invariant or rank for the kernel to prove.

The handoff to Lean

Past the boundary are proofs a prover would have to invent: induction nobody stated, products of unknowns. Integer arithmetic with induction or products is undecidable, so no automatic prover proves all of them. Define the function in Lean, prove its facts there, and the rule uses them. Going the other way, toLean and leanProject turn every gdp-wired proof into a Lean theorem.

Why you can trust a proof

A small kernel checks everything.

Trusted

The kernel (kernel/kernel.ts) turns a rule and its laws into goals and checks a proof tree for each: case splits on linear facts, then a linear refutation at each leaf.

Untrusted

The prover that finds the trees, the builders, the runtimes and the GPU searches. If the prover is wrong, the kernel rejects the tree.

Proven

The kernel's twin in Lean 4.34.0, proven sound with the standard axioms only. The exporter sends the kernel's real trees; tampered ones compute to false.

Prove your first rule.

Plain JavaScript with types: Node 20+, Bun or a browser. The skill teaches your coding agent to write rules and laws.

Built on

Credits