A login link could be reused for two hours.
- obligations
- 94/94
- controls
- 90/90
- tests
- ~1,800
- forced a change
- 2
- date
- 2026-08-19
Make it prove it. Closure grades your agent’s work against what the feature owes, using your own test results.
No LLM inside. Same inputs, same verdict.
$30 once · No account · Runs on your machine
Works with Claude Desktop, Cursor, Claude Code, the ChatGPT app and any local MCP client.

A passing invitation test shows that a valid link creates a membership. It leaves three questions open.
Does an expired link still work? Does a revoked invitation still work? Can a repeated request create two memberships? Passing the happy path doesn’t answer them.
api.invitations.createnotify.transportapi.invitations.acceptdb.membershipsSEND.004 · 549d6926unprovenREVOKE.001 · 2af84dfeunprovenRACE.020 · f116fed0staleClosure gives your agent a requirement and the proof it will accept.
The shipped fixture expands one selection into 58 obligations. This is one of them, with its grading rules, exactly as the agent receives it.
teams can invite people58 obligations5 proven
No LLM. Same inputs, same verdict.closure next · a3bb0264POLICY.TENANT_ISOLATION.ISO.001 tier 4 (hoisted to the skeleton) CRITICALAUDIT.EVENTSbehavioralUNPROVENFor every actor A and tenant T where A is not a member of T, no operation performed by A returns or mutates any audit_event owned by T.
<- POLICY.TENANT_ISOLATION@2.0.0 selector matched resource audit_event of AUDIT.EVENTS
evidence kind test.property (primary), test.example (fallback)
negative control REQUIRED. This obligation is critical, so a passing
test is not admissible on its own. You must also show the test FAILS when the
implementation is perturbed. Suggested perturbation: drop.authz
Record which perturbation you used and that the test failed under it.
name the test so that it contains the literal string [a3bb0264]
(that is how a passing test binds back to this obligation)1. closure test --repo . 2. the report at .closure/test-report.json is read for a passing test matching [a3bb0264] 3. the files that test depends on are hashed; the proof expires when they change Nothing else counts. The grader is deterministic and this is its whole rubric.
closure next on fixtures/example-saas, the fixture Closure ships with. The whole envelope, including what to do when blocked.Closure removes the protection in an isolated copy and reruns the test. If it still passes, the evidence is inadmissible.
How a control is gradedprotects administrator actions
export const allowed = role => Boolean(role);- export const allowed = role => Boolean(role);
+ export const allowed = role => true;protects administrator actionsstill passes
INADMISSIBLE
+ assert.equal(allowed("guest"), false);protects administrator actionsfails
CONTROL VERIFIED
RELEASE(closure-tutorial) = READY
closure demo as shipped, then with its solution applied. Full outputDone is not a feeling. It is a list of clauses, pinned to the commit, and the failing ones name what is still owed.
On the shipped fixture, 5 of 58 obligations are proven and 3 clauses block. The grid beneath is every obligation the verdict counted, in the state the engine gave it.
Read the full ledgerDONE(example-saas) = FALSE
This verdict is a property of the repository at this commit, not of this run.
One square per obligation, grouped by the feature that owes it.
AUDIT.EVENTSBILLING.SEAT_ACCOUNTINGCOLLAB.INVITATIONEMAIL.DELIVERYIDENTITY.ACCOUNTORG.MEMBERSHIPSCENARIOSfixtures/example-saas, the fixture Closure ships with. Full output and why each feature is owedThree codebases, all green before Closure ran.
Authored from the run reports of the author’s own projects; the marked cells show a count, not a position. Run reports
closure next hands the agent one requirement, the proof that will count, and what it may not change.
The catalog lives outside the graded repository; an obligation found inside it is refused.
implementation/tests/migrations/configuration/a3bb0264For every actor A and tenant T where A is not a member of T, no operation performed by A returns or mutates any audit_event owned by T.
test.property[a3bb0264] in the test nameA local MCP server. Claude Desktop installs it as an extension; everywhere else, closure mcp-config --repo . --client cursor (or claude-code, codex) prints the entry in your app’s own form. Setup for each app.
closure_doctorclosure_statusclosure_planclosure_nextclosure_explain{
"mcpServers": {
"closure": {
"command": "node",
"args": [
"closure",
"mcp",
"--repo",
"fixtures/example-saas",
"--catalog",
"catalog",
"--selection",
"fixtures/example-saas/.closure/selection.yaml",
"--timeout",
"1800000"
]
}
}
}Printed by closure mcp-config for the fixture; absolute paths shortened.
Closure grades the requirements the selected catalog supplies, against evidence at that commit. It does not discover scenarios the catalog lacks, and a verified control shows sensitivity to one perturbation, not general correctness.
closure-profile@0.1.0saas-core@0.1.10.2.3 at 910439e5f7285fa42closure init drafts the bindings; you review them. Your own agent can draft catalog entries; the engine never trusts the draft.saas-core ships with it. Your project’s own catalog lives beside your repository and loads with --catalogs.No. Closure has no LLM. It evaluates requirements and evidence, and a coding agent, or a person, writes the code.
No. It reads your test results and runs negative controls to check the evidence you selected.
The framework for one user and this version, for as long as you like: the catalogs, the local MCP server, the Claude Desktop extension and the command-line tools. Delivered by email within one business day, with a 14-day refund window. Future versions are not promised.
No. The verdict covers the requirements in the catalog you selected. Its coverage report counts HTTP routes; it is not an inventory of every product behaviour. See the field guide.
$30 USD · one-time purchase. Delivered by email within one business day, with a 14-day refund window. Stripe shows the final total before you pay.

Install the emailed package, then run the included demo: a passing test, rejected evidence, a repair, and the resulting verdict. Then follow the setup guide to connect your project and its test results.
npm install --global ./closure-engine-0.2.0.tgz
closure demo --out closure-demo