Research & instruments

How Proof turns intent into executable evidence.

Requirements are compiled, specifications checked, code traced, obligations generated, coverage measured, and evidence rerun. Every stage leaves a versioned artifact you can inspect.

01 · The boundary

We build the instruments we audit with.

Proof is one company with two halves. The platform is the engine and the intent graph. The assurance practice runs the audits and validates what the engine reports. We build the engine ourselves, and every audit is run with it: it compiles requirements, runs the solvers, measures the coverage, and refuses to pass anything it cannot trace.

The engine carries the breadth of the work: every requirement, every annotation, every decision point, checked the same way on every run. Review carries the judgment. Machines check everything, every time; a person validates every finding before it reaches you; findings derive their authority from runnable reproducers; people sign the methodology bar and the promises that require a person’s judgment. The boundary between the two is a policy we hold to: publish our evidence, keep the engine.

The engine is not open source, and what it produces for a client never lands anywhere public, for reasons the trust page explains. What it produces for our public work lands in the open where it can be re-run — the fullest example is the jsonparser corpus, and you can audit our audit there. The clauses these instruments enforce are on Methodology.

02 · The verification chain

The verification chain. Every link leaves an artifact.

The chain runs from the first written sentence to one exit code. Break any link and the gate refuses the whole of it.

01 · Compiled requirements

Requirements are written in structured English (sentences constrained enough for a machine to check their meaning) and compiled through a template compiler descended from NASA’s FRET, the flight-software requirements language whose template semantics are formally specified. Structural ambiguity fails at compile time; what the author meant is still read by a person.

artifact: each shall-line’s template ID, with its formal semantics attached

02 · The spec judged first

Realizability, consistency and vacuity are checked before any code is judged, by two independent proof engines: Kind2, a model checker, and Z3, a theorem prover. A specification that cannot be satisfied never reaches review, and neither does one a do-nothing system would already satisfy.

artifact: a solver verdict on the specification itself

03 · Solver proofs over encoded invariants

Z3 proofs run over encoded core invariants. Within the stated encoding and type domain, the solver establishes that no counterexample exists. The encoding is tied back to the code through the traceability layer, and behavior the encoding does not express stays outside the proof.

artifact: an UNSAT result on the negated property: the solver’s report that no counterexample exists

04 · Traceability

Every annotation that exists is machine-checked to resolve; a link that fails to resolve fails the gate. That is precision. Recall is covered from the other side: code that answers to no requirement is flagged as orphan.

artifact: a requirement tag on the function, a Verifies: tag on its test

05 · The obligation catalog

A catalog of obligation classes, each declaring the evidence that proves it: fuzz targets (mechanically generated hostile inputs) for parsers that must not panic, property-based tests for algebraic laws, race-detector runs for concurrency, negative tests for malformed input, solver lemmas for invariants. Classes cite the frameworks auditors recognize, OWASP ASVS, CWE and NIST controls among them, and projects extend the catalog: application-specific classes live in your repo next to the requirements they guard.

artifact: a recorded decision on every class considered

06 · MC/DC at code level

Code-level MC/DC (modified condition/decision coverage, which requires every condition in every scoped decision to be shown to matter on its own) is measured on the scoped decisions and fed into the same gate for every language. This measurement has mostly lived inside certification suites built for embedded work; ours runs in ordinary CI, and the shapes it cannot measure are counted and reported, never silently dropped. How the measurement is obtained differs by language, and so does the public evidence behind it: the table below states both, language by language.

artifact: a per-decision verdict, condition by condition

07 · The gate

The audit gate is one battery of machine checks, sized to the corpus it guards. It admits or rejects the whole chain, it runs in the client’s CI, and it needs nothing from us.

artifact: one exit code, re-runnable by anyone with the repo

Where each language stands

Two things vary by language: how the condition-level measurement is obtained, and whether there is a public corpus you can open. The middle column states a capability. The right-hand column states evidence, and most rows have none yet.

LanguageHow MC/DC is obtainedPublic evidence
Go Native MC/DC. Proof instruments the source in a staged workspace and runs go test; statement coverage comes off the same run. jsonparser — the published depth. The dossier.
JavaScript
TypeScript
Native MC/DC. A Babel source transform with a trace recorder, driven through node:test or Vitest. None published yet.
Rust Native MC/DC, with a prerequisite on one of the two paths. The default engine is a rustc driver reading MIR, and it needs a driver binary built against a pinned nightly, which we do not publish. The instrument-in-place engine needs no compiler internals and runs on stock stable. None published yet.
Java Native MC/DC. Source instrumentation with a recorder on the classpath, run through Maven or Gradle. Not JaCoCo, and not line coverage rebadged. None published yet.
C# Native MC/DC. Source instrumentation with a generated recorder, run through dotnet test. No coverlet dependency. None published yet.
PHP Native MC/DC. Source instrumentation with an injected recorder, run through Composer and PHPUnit. None published yet.
Zig Native MC/DC. AST-guided source probes, run through zig build test. None published yet.
Solidity Native MC/DC. Contract instrumentation with an injected runtime, run through Foundry forge test. None published yet.
Python Native measurement; independence pairs not certified yet. On CPython 3.12+ the runtime monitor records which conditions were exercised, without rewriting the source. Older interpreters import branch data from coverage.py, labelled as imported. Neither path reconstructs the independence witness today, so the report carries condition-level signal and says which it is. None published yet.
C
C++
Imported compiler coverage. There is no Proof instrumentation here. The gate ingests llvm-cov MC/DC summaries or gcov condition JSON that your build produced, and requires that export to exist. An uncovered condition arrives without its decision structure, so it is reported as feasibility-unknown rather than counted against you. rsync — 99 findings filed. The case study.
Kotlin
Ruby
Swift
Svelte
Parse-only. Annotations and trace links resolve and the traceability clause applies. There is no condition-level measurement, so the MC/DC clause does not. Not applicable.
Everything else Unsupported for coverage. A handful of languages are scanned for annotation comments only. Line-coverage import through Cobertura, LCOV or Go profiles satisfies the coverage gate for any language and never the MC/DC gate. Not applicable.

A native engine means the measurement exists and runs in ordinary CI. It does not mean we have published an audit in that language. Two rows carry public evidence today, and every other row says so in its own words.

03 · Change evidence

What the gate enforces about a change.

The methodology says every change carries its evidence. The engine enforces part of that clause today. The chain above is the list of things the gate refuses to pass, and change evidence is not all the way inside it, so the split is printed here.

Enforced on every run

A change record that names the requirements it affects must be cited back by each of those requirements, or the check fails. A closed record that moved no spec is caught there. Separately, a change that edits a formalized requirement’s wording while leaving its formal semantics and its evidence untouched blocks verification until somebody reviews that delta.

Shipped, off until switched on

The check that reads a change’s declared kind (feature, refactor, fix) and demands the evidence that kind requires is opt-in. It ships as change_evidence_complete, disabled by default, and a project turns it on in its configuration. Our own repository has not turned it on: the check records skip in our audit, so what is listed under “enforced on every run” is the whole of what our gate enforces about a change today. Our public jsonparser corpus has turned it on: change_evidence_complete: enabled: true, on master, in a proof.yaml anyone can open.

What a record contains, and why a defect fix is held to more than a feature, is on the changes page. The clause is clause 8 on Methodology.

04 · Invalidation and re-verification

When the ground moves, the evidence stops counting.

This half is enforced. Several checks that run by default exist for one purpose: to withdraw confidence that has stopped binding to what is in the repository now.

Approval fingerprints

An approval is recorded against a fingerprint of the requirement it approved. Edit the requirement and the approval stops counting until somebody approves the text that is there now.

Suspect links

A trace link whose code or test has moved under it is marked suspect. It stays suspect until a reviewer records that the link still holds and cites where.

Interface drift

An interface requirement is reviewed against a fingerprint of the code that implements it. Edit that code and the review is reported stale on the next run.

Calendar staleness

An approved requirement that has gone longer than the project’s review cadence is reported stale even when its fingerprint still matches. Nothing moved under it. Time passed.

Expired exemptions

A coverage exemption granted because of a known issue becomes an error once that issue is fixed. A waiver cannot outlive the bug that justified it.

Stale and violated are different states, and they ask you for different things. A stale claim asks for a rerun or a review. A violated claim asks for a fix, and it arrives with a reproducer that proves it. Methodology sets out the three states; the changes page shows one going stale on a record.

05 · The shapes

See the artifacts, not just the architecture.

Requirement, compiled

While in degraded mode, when queue_depth exceeds MAX_DEPTH,
the component shall, within 250 ms, satisfy reject_new_work.

template ID attached · semantics: NASA FRET

Annotation pair

// SW-REQ-XXX
func RejectWhenSaturated(q *Queue) error { … }

// Verifies: SW-REQ-XXX
func TestRejectWhenSaturated_AtBound(t *testing.T) { … }

MC/DC verdict

mcdc  component.go:XX   decision (a && (b || !c))
      3/3 conditions independently affect the outcome   ✓

shapes only · placeholders throughout · drawn from no client engagement

06 · Self-verification

The engine runs under its own gate.

Proof runs under its own gate: just over two thousand requirements across four specification levels, from stakeholder intent down to integration contracts, every production function annotated, zero orphan code, checked on every change the same way client work is checked.

Private / anonymized

Not publicly inspectable

Requirements

2,012 requirement files across the four levels, 1,584 of them approved.

Orphan code

13,619 of 13,619 production functions carry a requirement annotation that resolves.

What you can check

Neither figure. Both come off our own audit of 28 August 2026, on a repository we do not publish. The public reference below is the one you can re-run.

The same discipline covers its own defect history: every recorded defect is root-caused to the gap that let it through and closed with evidence. The vacuity checks in the chain above are what keep “green” from being gamed on a corpus that size.

That corpus stays private, for the same reason client corpora do: a full requirements tree describes its system completely enough to rebuild it, and this one describes the engine. The public reference is the jsonparser audit, whose requirements, defect records and evidence are browsable file by file.

07 · Public instruments

Some instruments are public.

An OSS-Fuzz harness (Google’s continuous fuzzing service for open-source projects) had run for years on jsonparser. It caught one real panic; a whole defect class still got past it, because the harness held key paths fixed while varying everything else. We built fuzzers that hold nothing fixed, for JSON and then for GraphQL, and published them. The third public instrument, probe, is the search tool that walks code and corpus together.

probelabs/probe ↗

Semantic code search over large trees: ripgrep speed with tree-sitter structure, used inside engagements to traverse code and corpus in one pass.

language: Rust

probelabs/json-fuzz ↗

Structure-aware JSON fuzzer: grammar-based generator, JSON-aware mutations, and correctness gates for differential testing of JSON parsers.

language: Go

probelabs/graphql-fuzz ↗

Structure-aware GraphQL fuzzer: grammar-based query, operation and schema generators, with correctness gates for differential testing of GraphQL parsers.

language: Rust

08 · Research lineage

Where the semantics come from.

The requirement templates descend from NASA’s FRET program, built to state flight-software requirements precisely enough to check by machine. In FRET’s published research, a realizability check caught, in 14 seconds, an eVTOL specification that permitted flying backwards.

In December 2025, Martin Kleppmann described where he wants software verification to go: “have the AI prove to me that the code it has generated is correct.” That is the direction of travel; what ships today is the enforcement half — a bar such proofs would have to clear.

09 · Limits

What the instruments cannot prove.

No instrument here proves total correctness, and we claim none. Performance is outside the chain: it judges declared behavior and says nothing about latency or throughput. This complements security scanners; it does not replace them.

And the limit we paid to learn in public: unspecified behavior is invisible to every check in the chain. The two jsonparser escapes are the standing proof. What the instruments deliver is bounded on purpose: within a declared scope, for declared behaviors, with evidence commensurate with the consequence of failure. The longer table of what the audit cannot see is on the methodology page.

10 · Where this goes

The audit is the first deployment model—not the whole product.

We sell audits because accountability is what the market can buy today, and because it is the honest way to prove the discipline works: one component, one engagement, evidence a client can re-run. Look at what each engagement leaves behind: a machine-readable graph of what a system promises, how each promise is verified, what broke, why it broke, and what retired the class.

Software engineering has never had that graph. Code-writing agents make decisions in the dark: no ground truth for intent, no memory of past failures, nothing to check their work against except their own output. Give the agents the graph and the gate, and the loop changes — for the first time there is something independent to be accurate against. The first piece already ships: every known issue in the register carries a copy-ready prompt, context and reproducer included, that any coding agent can work from. What the agent receives is its own page, and the dashboard is live for our public audit: the jsonparser register seeded product demo; read the labels first.

Proof was founded by Leonid Bugaev and operates both the Proof platform and its named assurance practice. The audit is how the platform gets installed, and how its claims get tested in public. Each client’s corpus compounds for that client, in their own repository. Corpus by corpus, the same artifacts add up to the missing evidence layer for engineering that increasingly runs itself, with humans setting intent and signing what matters.

11 · Onward

Two places to go from here.