{
  "markdown": "<!-- mcp-name: io.github.Jujitae/invara -->\n# INVARA\n\n**Engineering invariants for AI-built software.**\n\nINVARA works with **Claude Code, Codex, and any coding agent that can use a\nshell**. It verifies declared constraints against observable evidence; it does\nnot prove software correctness.\n\n```text\nseal before work -> agent does the work -> judge\n                                             |\n                    PASS / BLOCK / UNVERIFIABLE / HUMAN_REVIEW\n```\n\nStart with the path that matches your environment:\n\n- **Claude Code:** install the bundled editor/plugin experience with\n  `/plugin marketplace add Jujitae/invara`, then `/plugin install invara`.\n- **Codex or another shell-capable agent:** run `uvx invara list`, or install\n  persistently with `pip install invara`.\n- **Tell your agent:** use the copy-paste instructions in\n  [AI Agent Quickstart](docs/AI_AGENT_QUICKSTART.md), then preserve the exact\n  verdict it receives.\n\nThe first result is a verdict, not an agent self-report. `PASS` means every\ndeclared check returned what it promised and protected paths stayed unchanged.\n`BLOCK`, `UNVERIFIABLE`, and `HUMAN_REVIEW` stay exactly that; none is success\nby reinterpretation.\n\nStatus: **Alpha.** It is dogfooded daily and has not been sold. It is\nnot autonomous authorization and not an enterprise compliance control.\n\n## New in 0.2: transformation assurance, Gen 1\n\nTwo local CLI workflows can now check a declared behavior envelope around a\nrefactor or migration:\n\n- `invara assure` compares an existing before/after pair under an Equivalence\n  Manifest and can search for a minimized counterexample.\n- `invara repair` governs a repair one unit at a time, keeping a unit only\n  after the declared checks accept it.\n\nGen 1 measures only the inputs, observations, policies, and claims declared in\nthe manifest. A `PASS` is bounded to that envelope; it is not a general proof\nof correctness, security, or bug-free software. The workflows run user-named\ncommands with the user's permissions. They make no outbound network call; an\nHTTP probe may connect only to a loopback service that the manifest starts for\nthe session.\n\nStart with the [CLI guide](docs/transformation-assurance/CLI.md) and the\n[manifest guide](docs/transformation-assurance/MANIFEST.md). Synthetic examples\nand display reports are under `fixtures/` and\n`docs/transformation-assurance/samples/`.\n\n---\n\n## What this is not\n\nRead this part before the install line. It is short on purpose, and the word\nthat carries the promise above is *verifiable* — not *correct*.\n\n> **INVARA does not prove software correctness.**\n> **It verifies declared constraints against observable evidence.**\n\nSpecifically:\n\n- **It does not inspect your codebase.** It never asks whether the code is\n  good, whether the architecture holds, or whether the tests are the right\n  tests. Stack a new floor on junk and, if this floor was built to the\n  declared spec, the verdict is `PASS`.\n- **It does not find bugs.** A completion check that runs your suite is only as\n  strong as your suite. INVARA reports the exit code; it does not have an\n  opinion about coverage.\n- **It does not decide what should have been promised.** You write the\n  contract. A weak contract earns a weak `PASS`, and the contract is stored\n  verbatim so anyone can see how weak it was.\n- **It is not a sandbox.** Completion checks are commands and they run with\n  your permissions. Do not seal a contract you have not read.\n- **It does not judge intent.** `intent` is prose; nothing checks that the\n  work matched it. The checks are what bind.\n- **It is not an AI code generator and not an LLM code-review bot.** There is\n  no model anywhere in the verdict path.\n\nThe narrow claim, which is what the machine actually does:\n\n> **It decides, independently, whether this change kept the promises it made.**\n\n---\n\n## CLI first verdict, in more detail\n\nNothing to configure. No API key, no service, no account. Python 3.12+ and uv.\n\n```bash\nuvx invara list\n```\n\nor, to keep it:\n\n```bash\npip install invara\n```\n\nThe package declares **zero runtime dependencies**, so this pulls only the\nstandard library. `pip install invara` reports the installed INVARA version,\nand `pip list` shows no additional runtime packages.\n\nFrom a checkout it is the same program, but install it first — the source\nlives under `src/`, so a bare `python -m invara` in the repository root\nfinds nothing to run:\n\n```bash\npip install -e .\npython -m invara list\n```\n\n### Release-candidate verification before publish\n\nThe bundled plugin and the distributable package must expose the same six MCP\ntools. Before a maintainer publishes a new package version, build its wheel and\nrun the repository's clean-environment proof. It creates a fresh virtual\nenvironment, installs only that wheel without using an index, starts the MCP\nserver over stdio, verifies the exact tool list, then seals, judges, lists,\nlogs, rebuilds the chain, and replays a verdict.\n\n```bash\npython -m pip wheel --no-deps . --wheel-dir .runtime/invara-dist\npython scripts/verify_fresh_install.py --wheel-dir .runtime/invara-dist --plugin-root plugin\n```\n\nThis is a release-candidate proof, not a publish command. The CI workflow runs\nit independently on Windows and Ubuntu for every candidate pull request.\n\n### 1. Write the contract *before* the work\n\n`task.json`, next to the repository you are about to change:\n\n```json\n{\n  \"task_id\": \"2026-08-17-tidy-the-parser\",\n  \"intent\": \"Speed up the CSV parser without changing what it accepts\",\n  \"constraints\": [\n    {\n      \"kind\": \"paths_unchanged\",\n      \"paths\": [\"tests/test_parser.py\"],\n      \"reason\": \"a speedup that edits its own test is not a speedup\"\n    }\n  ],\n  \"done_when\": [\n    {\n      \"id\": \"suite\",\n      \"command\": [\"python\", \"-m\", \"pytest\", \"-q\"],\n      \"expect_exit\": 0,\n      \"reason\": \"the whole suite\"\n    }\n  ]\n}\n```\n\n```bash\ninvara seal task.json\n```\n\nSealing takes the digests of the protected paths **now**, before anyone knows\nwhat the verdict will be. That ordering is the entire guarantee.\n\n### 2. Do the work.\n\n### 3. Judge\n\n```bash\ninvara judge 2026-08-17-tidy-the-parser            # dry run\ninvara judge 2026-08-17-tidy-the-parser --commit   # record it\n```\n\n```\n  BLOCK: 1 protected path(s) changed: tests/test_parser.py: changed\n         (a speedup that edits its own test is not a speedup)\n  decided by: constraint_breaks\n```\n\nThat is the first verdict. Everything below is detail.\n\n---\n\n## The four verdicts\n\n| Verdict | Meaning | Exit |\n|---|---|---|\n| `BLOCK` | A protected path changed, or a completion check failed | 1 |\n| `UNVERIFIABLE` | A check could not be run at all. **Unchecked is not passed** | 2 |\n| `HUMAN_REVIEW` | Machine checks passed; something was declared as needing eyes | 0 |\n| `PASS` | Every check returned what it promised, every protected path is byte-identical | 0 |\n\nConstraint breaks outrank everything. A run that touched what it promised not\nto touch is not partially fine.\n\n`BLOCK` is two rules wearing one word — a protected path that changed and a\ncheck that came back wrong are not the same accusation. So the verdict also\nrecords which rule decided it, named after the evidence it decided on\n(`constraint_breaks`, `failed`, `unrunnable`, `needs_human`, `passed`), and\n`judge` and `log` print it. Verdicts recorded before this existed do not have\none, and do not get one fitted after the fact.\n\n## Sealing refuses more than it accepts\n\n`seal` will not write a contract that cannot fail the work. It refuses a task\nwith no completion condition, a condition with no command to check it, a\ncontract with no protected paths (\"a task allowed to change anything cannot be\nsaid to have respected anything\"), a duplicate check id, a protected path that\ndoes not exist, and — the one that matters most — a contract where **every**\ncondition defers to a person.\n\nThat last one is why this is not a rubber stamp: if the only evidence is\nsomebody saying yes, there is no contract.\n\n## Other commands\n\n```\ninvara init              print a task.json template for this repository\ninvara list              sealed tasks and their latest verdict\ninvara log    <task_id>  every verdict this task has ever had\ninvara show   <task_id>  the contract, exactly as sealed\ninvara replay <task_id>  recompute a recorded verdict and compare it\ninvara chain             rebuild both hash chains\n```\n\n`invara replay` is the one that answers \"was this verdict reproducible?\" — it\nrecomputes from the observations stored at the time. A verdict recorded before\nreplay support refuses with `no_current_stored` rather than guessing.\n\nVerdicts live in `.runtime/verify.db` (`--db` to move it). A contract is sealed\nonce and judged many times; the history is append-only and chained.\n\n---\n\n## Inside the editor\n\nThe buyer this was built for does not open a terminal. So the same package\nships an MCP server, self-contained as a Claude Code plugin:\n\n```bash\n/plugin marketplace add Jujitae/invara\n/plugin install invara\n```\n\nThe plugin bundles the INVARA source and runs via `python -m`, requiring only\nPython 3.12+ — no uv, no network, zero runtime dependencies. If the server\nwill not start, `/invara:doctor` diagnoses the environment without assuming\nPython exists — the known silent case is Windows without Python, where the\nMicrosoft Store's `python` alias spawns and dies with exit 9009 and seven\nbytes of stderr (`Python `); that death happens before any INVARA code runs.\nThe configuration the plugin writes looks like this:\n\n```json\n{\n  \"mcpServers\": {\n    \"invara\": {\n      \"type\": \"stdio\",\n      \"command\": \"python\",\n      \"env\": {\n        \"PYTHONPATH\": \"${CLAUDE_PLUGIN_ROOT}/src\"\n      },\n      \"args\": [\"-m\", \"invara.mcp\"]\n    }\n  }\n}\n```\n\nSix tools — `invara_seal`, `invara_judge`, `invara_list`, `invara_log`,\n`invara_chain`, `invara_replay`. They are the commands above, and they change\nnothing about what a verdict is: it is still computed from file digests and\nexit codes, the checks that run are the ones a sealed contract already named,\nand there is still no field anywhere for an agent to assert that the work is\ndone. An agent can ask for a verdict here. It cannot give one.\n\n`invara` there is a local label — call it what you like. The server's actual\nidentity is `io.github.Jujitae/invara`, which is how it is listed in the\n[MCP registry][registry] and how a client that resolves through the registry\nwill find it. It cannot be used as the key above: `claude mcp add` answers\n`Names can only contain letters, numbers, hyphens, and underscores`.\n\n[registry]: https://registry.modelcontextprotocol.io/v0/servers?search=invara\n\nNot a sandbox, and this does not make it one. `invara_seal` takes a task file,\nthat file names commands, and judging runs them. An agent that can write a\ntask file can cause those commands to run — which is no more than the shell it\nalready has, but better said here than discovered.\n\n---\n\n## Determinism\n\nSame repository state, same contract, same environment → same verdict. The\nverdict is a function of file digests and command exit codes, and nothing else;\nthere is no model in the path and no clock in the decision.\n\nMeasured rather than asserted, 2026-08-17: contract\n`2026-08-17-route-discovery` was judged twice, four minutes apart, against an\nunchanged tree — 7 checks each including a 2,021-test suite. Both runs returned\nthe same status and the same reason string, and both rows are in the chain:\n\n```\n$ invara log 2026-08-17-route-discovery\n2026-08-17 09:17 UTC  PASS\n    7 check(s) passed and 6 protected path(s) are unchanged\n2026-08-17 09:21 UTC  PASS\n    7 check(s) passed and 6 protected path(s) are unchanged\n```\n\nRun that yourself on your own contract before you trust it on ours.\n\nThe word doing work there is **environment**. See the first failure story\nbelow: a contract that passed locally and failed in CI was not\nnon-deterministic — it was two different environments, and INVARA reported\neach one correctly. If you want the verdict to be reproducible, make the\ncompletion commands reproducible.\n\n---\n\n## Failure stories\n\nThese are real, from building and using this tool. They are here because a\nverification tool that only shows its successes is asking to be trusted on\nexactly the grounds it tells you not to trust anything.\n\n**Environment contamination.** A contract passed on the machine that wrote it\nand failed in CI. The tree was clean; the *environment* was not.\n`PYTHONIOENCODING` was set in the shell, child processes inherited it, and the\ncompletion command only worked because of it. Verification runs now use\n`env -u PYTHONIOENCODING`. Clean tree is not clean environment.\n\n**A seal that broke itself.** A fresh clone rewrote a sealed ontology file to\nCRLF on checkout, so its SHA-256 no longer matched. The file whose entire job\nwas to prove nothing had changed failed its own seal. Fixed in\n`.gitattributes`, not in the digest rule — the digest was right.\n\n**The first verdict was `UNVERIFIABLE`, and it was correct.** A completion\ncommand could not be found, because `subprocess` does not use `cwd` to resolve\nthe executable. The verdict was right and the tool was useless. Both facts are\nrecorded; only one of them was a bug.\n\n**It did not pass the work that built it.** The first contract INVARA ever\nsealed was the task of building it. It returned `UNVERIFIABLE`, then\n`PASS`, then `PASS`. All three are still in `.runtime/verify.db`, and\n`invara log` prints them.\n\n---\n\n## Where it came from\n\nThe shape is lifted from a sibling engine in the same private repository:\nseal the contract\nbefore the evidence exists, refuse to create anything you cannot kill, score\nonly observed records, and chain the result. Change \"world claim\" to \"agent's\nwork\" and the same machine applies.\n\nINVARA was built and is dogfooded inside a private working repository (WIE);\nsee [`PROVENANCE.md`](PROVENANCE.md) for what that means for this source.\n",
  "bytes": 13872,
  "sha": "f48173f7c55399240bb24c97c4c84735a20a4ef738d532adbe1982341778744c",
  "repo_slug": "jujitae/invara",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_jujitae_invara_d5bcd416/readme"
}