Everything else here checks code that already exists. polygen writes code that arrives already checked.
Give it a sentence describing a feature. It drafts a contract, authors a state machine against it, proposes the invariants, model-checks its own output, repairs the violations it finds, and hands you a module with a passing exhaustive check plus a synthesized regression trace corpus.
The second of five engines: Polygraph audits, polygen authors, polyrun executes, polyvers evolves, polynv elicits.
The normal way to get verified code is to write it, then verify it. That ordering is why most code is never verified at all — by the time the machine exists, the contract is implicit, the invariants were never written down, and reconstructing both to check something already shipped is work nobody scheduled.
It also produces the wrong argument. When you audit existing code, a clean result means "the code matches an independent reading of itself." When the code is generated against a contract and checked before it ships, the result means something stronger: the state space was explored and the rules held, before anyone integrated it.
polygen inverts the order. The verification is not a review step at the end — it's part of the authoring loop, and code that can't pass it doesn't get presented as finished.
node scripts/polygen.mjs --intent "<feature description>" --model opus-5 --out out/Six stages, each gated:
- Draft the contract — the observable state fields, the action alphabet, the data each action carries, which states are terminal.
- Author the module — a SAM v2 strict-profile machine against that
contract. Every authored (and every repaired) module must pass the
library's own strict
validate()at the stage boundary; schema and shape errors block the stage rather than becoming report lines, and an unloadable or truncated rewrite gets exactly one retry with the load error appended. - Propose invariants — the rules the machine should never break, written as plain JS predicates.
- Model-check — exhaustive exploration from
init()over the declared domains, exactly the same checker the audit path uses. - Self-repair — every reachable violation goes back to the model with
its counterexample path, capped at
--repair-maxrounds. - Synthesize a corpus — drive the final code to produce
traces/*.ndjson, then replay them in a separate process as an independent check.
The output is the same artifact family every other engine consumes:
contract.json, next.cjs, invariants.mjs, traces/*.ndjson, and
polygen-report.md.
It reuses the audit core, not a friendlier copy of it. The
model-checking (check.mjs), corpus hygiene (validate_corpus.mjs), and
independent replay (replay.mjs) are literally the same modules the audit
path runs. polygen cannot grade its own homework with a softer ruler, and a
fix to that core improves both directions at once.
A non-converging run is reported as NOT converged. If self-repair burns its rounds and violations remain, the report says so. It is never presented as clean — which matters, because the entire value of generated code is the claim attached to it.
There's a subtler failure this engine had to learn about. The contract and
the code come from independent model calls, so they can disagree — most
insidiously on an enum's spelling. A machine whose contract says
"cancelled" while the code emits "canceled" still model-checks
"successfully": the checker explores the tiny reachable fragment that
spelling allows and reports no violations over almost nothing. polygen now
cross-checks that contract and code agree on their action/data vocabulary.
examples/case-study-polygen-domain-gap.md
narrates the real run where this collapsed the explorable state space —
including a false positive the fix itself introduced.
polygen hands you artifacts, not a merge. Three steps stay with you, in order:
- Review the contract and the invariants. They are the model's reading of your intent, not ground truth. Everything the check proved is relative to them, so this is where your judgment actually lands. (If you want help making that set strong rather than merely present, that's polynv's job — it grades an invariant set by mutation testing.)
- Wire the module into your real handler — call it, don't reimplement it. A verified module that gets paraphrased into your codebase is no longer the thing that was verified.
- Re-verify the integrated code with
/polygraph:verifyagainst traces captured from the integrated system. That last step catches drift between the pure model and the glue around it — the seam polygen cannot see.
From there the artifact family flows onward: polyrun can execute it durably, polyvers gates its next version against the live fleet.
- OTP flow (
examples/polygen-otp/) — authored from one sentence: 8 states, 0 violations, a 134-window synthesized corpus, 0 independent-replay failures. - Cart checkout, and the bug polygen found in itself
(
examples/polygen-cart-checkout/, narrated incase-study-polygen-domain-gap.md) — the contract/code vocabulary mismatch that motivated the domain cross-check.
- JS/TS only. The generated module is directly usable in a JS/TS codebase. Porting a verified machine to another language is a separate problem — the port itself would need a differential check against the original — and is out of scope.
- Needs
ANTHROPIC_API_KEY. Authoring is the LLM half; everything that checks, replays, and explores runs locally. - "Exhaustive" means exhaustive over the finite (action, data) domains the contract declares — the same bound, and the same unmeasured domain-representativeness gap, as everywhere else in this toolset.
- A passing polygen run means the generated machine satisfies the generated invariants over the declared domain. Whether those invariants capture what you actually meant is the one judgment no engine here makes for you.
Entry points: /polygraph:polygen (skill and command) for a guided run,
the polygen subagent to hand off the whole loop. Where this sits among
the five engines: ARCHITECTURE.md.