Traditional
BUG #481
"Sometimes nested arrays seem to return wrong values."
- reproduce?
- understand?
- intended behavior?
- related code?
- regression?
- blast radius?
- test?
- fix?
a person digests the ambiguity
Proof turns what your software must do into executable requirements that stay aligned as the system changes.
One requirement
In Proof, a requirement is a living object connected to what implements it, what proves it, what depends on it, and what could break it.
A refund never exceeds the captured amount.
Approved by Alice · Payments
refund.go:82-104TestRefundNeverExceeds...One card, one promise · Every field is generated from the graph. Nothing here is maintained by hand.
The graph of intent
See the blast radius before you change the code.
Code graph
Structure · What calls what. No box in it says what the code promises.
Proof
Intent · What must stay true, what depends on it, and what proves it.
A code graph tells you what calls what. Proof tells you what depends on what being true.
Blast radius
Before changing the implementation, Proof can show the promises potentially affected by the change.
Same change, seen as a graph · The illuminated path is the set of promises the change can reach. What dims is out of scope.
SELF-INVALIDATION
Knowledge about software becomes dangerous when it silently goes stale. When the implementation, the requirements, or the documentation change, Proof identifies the evidence and intent that may no longer be valid.
VERIFY runs. Fresh evidence restores every node.
The invalidation loop · The figure cycles while it is in view. Hover it, or focus a phase button, to hold a state.
It does not just remember what was true. It knows what needs to be checked again.
Agents
Your agent shouldn't have to rediscover your system every time.
The handoff · The developer states the change. The agent asks Proof, over MCP, what the change touches, and the answers come from the intent graph.
> I'm changing Set() to support nested arrays. What can this affect? Proof: Relevant intent KI-3 Set() must preserve sibling values KI-7 Nested updates preserve parent structure KI-11 Array indexes cannot mutate adjacent entries Blast radius 4 requirements 3 implementation areas 7 tests 2 known hazards Known issue KI-3 was previously violated. Reproducer available →
Actual interaction · KI-3 is a real known issue on buger/jsonparser: Set() dropped sibling values, found by a signed requirement test and fixed upstream.
MCP is how agents reach the graph. The understanding is the product.
Agent use cases
The same four moves, whether an engineer or an agent does the work.
Navigate by intent, not files. Ask what a subsystem promises, why a behavior exists, and what depends on it.
Know the blast radius before editing. The requirements, hazards, and historical issues around the change come with it.
Start from executable evidence. Findings include reproducers, so the failure can be observed before the implementation is touched.
Prove the change, not just the patch. Run the evidence around the underlying requirement and reconsider anything the change invalidated.
The loop · Verification writes its evidence back into the graph, and the next round of understanding starts from it.
The queue
Proof changes the quality of the work entering the engineering queue. Instead of asking an engineer or agent to investigate an ambiguous report, the work starts with the requirement, the context, and the executable evidence.
Traditional
BUG #481
"Sometimes nested arrays seem to return wrong values."
a person digests the ambiguity
Proof
FINDING #481
Public receipt
We ran Proof on a mature open-source project. Everything below is public, and you can run it again.
buger/jsonparser, a 5,600-star Go library, more than ten years in production.
Promises signed
Real upstream bugs found and fixed
Missed promise published
Each finding is a test that failed on main.
Not an opinion, not a warning, not a suggestion.
A boolean is only true for the exact token true.
A unicode escape is rejected unless four hex digits follow it.
Fixed upstream #271Set() on an array-index path never drops a sibling value.
An integer too large for int64 returns an error and never wraps.
Fixed upstream #279A UTF8 decode never reads past the length the config declares.
Fixed upstream #283An empty array returns the empty sentinel and never a nil slice.
Fixed upstream #287EachKey visits a key once, even when the document repeats it.
Seven promises, seven failing tests, seven merges in the project's own repository.
Don't take our word for it.
We publish the promises we get wrong on the same register as the ones we get right. That is the only way you can check us.
How it works
Five stages. Your engineers own the second one. The gate owns the last two.
Proof reads your code and writes down the promises it already makes.
Your engineers read each promise and sign it. Nothing counts before a person signs.
Each signed promise gets a test that fails when that promise breaks.
The gate runs on every commit. A broken promise stops the merge.
The test stays in your suite. The same break cannot return unseen.
The promise graph
Every promise is joined to the code that carries it and to the tests that check it. The gate reads those joins on every change.
Now picture 123 of these across one repository.
A commit changes refund.go. The map shows the promises of that file.
Fig. 02 · The blast radius of one promise that is not written down. Example. The promise is only in a document. No check can fail on it. The failure occurs at your customers.
The product
The product is two screens. One asks a person to accept a promise, and the other refuses a merge that broke one.
Proof found 3 new promises in this pull request.
“A refund never exceeds the captured amount.”
82func Refund(ctx, id string, amt Money) error {··+96 if amt.Cents > ch.CapturedCents {+97 return ErrRefundExceedsCapture98 }
$proof gate --base mainloading 123 signed promises123 checked in 4.2s122 passFAIL TestRefundNeverExceedsCapture promise SYS-0182 “A refund never exceeds the captured amount.” broke at refund.go:96 signed by leonid, 14 Jul 2026exit 1merge blockedread the promise:portal.reqproof.com/p/SYS-0182
The register it all lands in
The objection
Of course.
Tests check what your engineers remembered to write down.Proof finds the promises they never wrote down.
Fig. 05 · The arrows run opposite ways. A test starts in one person's memory and ends at one assertion. A promise starts in the code, passes through a person who signs it, and ends at every commit after that.
Attached
A promise stays attached to the code it governs, so it moves with the code as the code changes.
Named
A failure tells you which promise broke, not only which assertion failed.
Before the merge
You can see everything one change touches before you merge it.
Who it is for
“We ship ten times faster now. Review speed did not increase ten times. I approve releases that I cannot examine myself.”
What Proof gives you: a map and a gate that you keep. The gate held the release to its promises before you sign it.
“I open the register and search for bad work.”
What Proof gives you: a live map, a published miss, and tests that fail on main. Run the tests again. Then tell your CTO.
“One bug in routing, auth, or billing touches every customer at the same time.”
What Proof gives you: the shared path as signed promises. A break on that path is a test that fails.
“My agents write most of the code now. I need a record that they must obey.”
What Proof gives you: a written record of the promises in the code. Agents can read the record. Agents cannot approve the record.
Accountability
Machines check everything, every time. People decide what a machine must not decide alone. This limit is written in the configuration. You can move it.
Agents
Run every check, on every commit. The quantity is more than a person can read.
A person
One person validates each finding before it reaches you. People sign the promises, the bar, and our misses.
Your engineers
Sign the promises. Each item an agent writes has a draft mark. An agent cannot approve its own requirement.
Fig. 03 · CI is green in the two pictures. The second picture is possible only after the promises are written down.
The whole method →Our misses are published. MISS-001, signed by Leonid Bugaev.
Enterprise
Proof sits between your repository and your CI. Nothing else about your setup changes.
Fig. 06 · One box in the middle. Your repository on one side, your CI on the other, and a person inside the box on every promise.
The six questions we are asked first
Three questions we answer in writing rather than on a page: running Proof on your own hardware, which models we may use, and where the data sits. Ask at [email protected] and you get a written answer.
What you keep
Four artifacts. They stay in your repository, under your licence.
We recover every promise of your component from the code. Your engineers sign each one.
Each break has a test that fails on your current main. A person validates each break before you see it.
Select a function or a promise. The map shows what else changes. Your engineers, your CI, and your agents use the same map.
The gate reads the map on each change. A broken promise stops the merge.
If we stop work tomorrow, your map, your gate, and your register continue to operate.
Final receipt
Set() replaces one value and changes nothing else.
This promise was implicit for years. Proof made it explicit, found the violation, produced the failing test, and the maintainer fixed it upstream.
We run Proof on one public project each quarter, at our own cost. There is no invoice and no follow-up.
Leonid Bugaev · founder
signs the promises we publish, and the ones we miss