{
  "markdown": "# SPARDA\n\n<div align=\"center\">\n  <img src=\"assets/sparda-readme-banner-dark-1600x480.png\" alt=\"SPARDA — AI writes. SPARDA proves.\" width=\"800\" />\n</div>\n\n<br/>\n\n> 🇫🇷 **Français** — _L'IA écrit. SPARDA prouve._ Un gate déterministe et hors-ligne qui détecte quand une modif d'IA retire une garde, expose une route ou casse un invariant — sans clé API, directement dans la boucle d'édition de l'agent. Pour tout comprendre en 10 minutes (douleur, architecture, vision) : [SPARDA-EXPLIQUE.md](docs/SPARDA-EXPLIQUE.md).\n\n---\n\n<h1 align=\"center\">AI writes. SPARDA proves.</h1>\n<p align=\"center\"><em>L'IA écrit. SPARDA prouve.</em></p>\n\n**The trust layer for AI-written backends.** SPARDA compiles your backend — routes, database queries, state mutations, guards, side-effects — into one deterministic behavior graph, then **statically proves what can and can't break before you ship**: no unguarded mutation, no broken invariant, no non-atomic aggregate write.\n\n[![npm](https://img.shields.io/npm/v/sparda-mcp)](https://www.npmjs.com/package/sparda-mcp)\n[![CI](https://github.com/zakariagharzouli/sparda/actions/workflows/ci.yml/badge.svg)](https://github.com/zakariagharzouli/sparda/actions/workflows/ci.yml)\n![node](https://img.shields.io/badge/node-%3E%3D18-brightgreen)\n![runtime deps](https://img.shields.io/badge/runtime%20deps-4%20pinned-4c1)\n[![license](https://img.shields.io/badge/license-BUSL--1.1-blue)](./LICENSE)\n\n100% local · deterministic · zero API key · no cloud account. It fails loudly on a real risk, and when it can only see part of your app it says **PROVEN (PARTIAL)** — never a false green. And when it can prove it was not even looking at your whole app, it says **PREMISE NOT VERIFIED** and claims nothing at all.\n\n## 60-second proof\n\nFrom your Express, FastAPI, Flask, Next.js, NestJS or Medusa app — nothing to configure:\n\n```bash\nnpx sparda-mcp apocalypse   # prove the tree is safe to deploy — exit 1 on any real risk, or on an unverified premise\nnpx sparda-mcp prove        # the whole verdict: proof + coverage + shareable seal\nnpx sparda-mcp badge        # a README badge: proven · coverage% · routes\n```\n\nUnder the hood it compiles your backend into one language-agnostic graph — the **Unified Behavior Graph (UBG)**, serialized as `.sparda/ubg.json` under the **SBIR** specification ([SPARDA Behavior IR](docs/SBIR_SPEC_V1.1.md)) — and every command is a pass over that graph.\n\n## The wedge — catch an AI edit that removes a guard, in the loop\n\nThe one thing a text-diff review and a pattern scanner structurally can't do: prove that **this specific edit** dropped a protection the previous version had. `sparda gate` diffs the behavior graph before/after an edit and blocks a regression — deterministic, offline, sub-second, exit 2 (the Claude Code `PostToolUse` contract that stops the agent's edit loop). See it end-to-end in one command, zero setup:\n\n```bash\nnpm run wedge     # (from a clone)  — or drive it on your own app with `sparda gate --arm` then `sparda gate --hook`\n```\n\n```\n  1. baseline armed on the guarded code   (POST /admin/delete-user · requireAdmin)\n  2. an AI edit \"simplifies\" requireAdmin → a pass-through (still compiles, still 200s)\n  3. sparda gate on the edit:\n       ✗ [critical] GUARD_REMOVED — POST /admin/delete-user was guarded in the baseline\n                    and is now reachable without any guard (src/app.js:11)\n     ⏱  ~40 ms · deterministic · offline · no API key\n     ⛔ exit 2 on --hook — Claude Code PostToolUse blocks the edit\n```\n\n**Wire it into Claude Code in one line** — the [plugin](integrations/claude-code-plugin) registers a `PostToolUse` hook that runs `npx -y sparda-mcp gate --hook` after every `Edit`/`Write`, so a guard-removing edit is caught before it lands.\n\n> [!IMPORTANT]  \n> **The Route-Compilation Proof — reproduce it yourself.** SPARDA compiles real open-source monsters to their behavior graph with **zero crashes**, each in **≈1–2 seconds**: Next.js _Dub_ (579 routes), NestJS _Immich_ (281), _MedusaJS_ (477). It natively resolves deep Dependency Injection, external controllers, and Next.js handlers. One command clones them and re-measures on your machine:\n>\n> ```bash\n> node bench/repro.mjs        # → bench/route-proof.json\n> ```\n>\n> Honesty first: _compiling_ a route is a parser result (the number above); _proving_ it safe is a separate per-repo verdict — and most real apps come back **NOT_PROVEN**, which is the true state, not a failure. (Our full 25-repo corpus stress compiles **3,565 routes** at ~150 routes/s; that one needs the corpus checked out.)\n\n**What the graph unlocks — 100% local, deterministic, 4 exact-pinned dependencies, zero API key:**\n\n| Command            | What it does                                                                                                                                                                                                                         |\n| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **`prove`**        | _The whole trust verdict in one gesture_ — proof + coverage + premise check + a shareable seal (`--json` / `--markdown`)                                                                                                                             |\n| **`apocalypse`**   | _Prove the deploy_ — no guard, invariant, transaction or aggregate boundary can be broken (SARIF + CI gate)                                                                                                                          |\n| **`heal`**         | _Self-heal, **proven**_ — the gate Copilot Autofix doesn't have: a fix ships **only if** replay matches, `verify` still passes, and `apocalypse` finds no new risk / no dropped guard. Whoever wrote the fix, the machine judges it. |\n| **`badge`**        | _The shareable artifact_ — a self-contained SVG badge + README snippet (verdict · coverage · routes)                                                                                                                                 |\n| **`dossier`**      | _The public report_ — one self-contained HTML page: verdict, risks, and SPARDA's own blind spots                                                                                                                                     |\n| **`ubg`**          | Compile the codebase to its behavior graph (Express · FastAPI · Flask · Next.js · NestJS · Medusa natively; **any** stack via OpenAPI)                                                                                               |\n| **`timeless`**     | _Time-travel_ — record a production request, replay it byte-identically, export the bug as a test                                                                                                                                    |\n| **`mirror`**       | _Execute the graph_ — serve the compiled behavior over HTTP with no framework and no source                                                                                                                                          |\n| **`init` / `dev`** | _Runtime, optional_ — expose the graph to AI clients as a live MCP server (+ Twin, Immune, Evolution)                                                                                                                                |\n\nThe prover is the product. The MCP server is one _output_ of the graph, not the point — SPARDA compiles the whole system's behavior, then proves, replays, heals, and (optionally) serves it.\n\n**Nomenclature:** **SBIR** is the specification (the format, like \"JSON\"); **UBG** is the compiled graph itself (the artifact, `ubg.json`). The MCP server is one _output_ of the graph, not the product.\n\n## Optional: expose the graph to AI clients (MCP runtime)\n\nBeyond proving, SPARDA can turn your running app into a live MCP server — the graph, executable, with write-safety and an immune layer. This is optional and separate from the prover above.\n\n1. **Scan + inject** — run once, from your app's directory:\n\n   ```bash\n   npx sparda-mcp init\n   ```\n\n   SPARDA parses your routes (AST), generates a marked `/mcp` router, injects it into\n   your app (with a backup), and writes `sparda.json`. Every step is reversible.\n\n2. **Start your app, then start the bridge:**\n\n   ```bash\n   npx sparda-mcp dev\n   ```\n\n3. **Connect your client.** `init` prints a ready-to-paste block for\n   `claude_desktop_config.json`, pre-filled with your app's name and path:\n   ```json\n   {\n     \"mcpServers\": {\n       \"your-app\": {\n         \"command\": \"npx\",\n         \"args\": [\"sparda-mcp\", \"dev\"],\n         \"cwd\": \"/absolute/path/to/your-app\"\n       }\n     }\n   }\n   ```\n   Claude Code connects to the same bridge. That's it — your running app is now a set\n   of MCP tools your AI can call.\n\n## Try the Standalone Demo\n\nTo see SPARDA in action instantly without modifying your codebase:\n\n```bash\nnpx sparda-mcp demo\n```\n\nThis runs the entire MCP lifecycle (detect → parse → generate → inject → remove) on a bundled demo app in a temporary folder, in about 10 seconds. For the compiler itself, run `npx sparda-mcp ubg` then `apocalypse` on any Express/FastAPI app.\n\n## Black Box Report\n\nSPARDA is designed as a local organism. To see what it remembers and how much compute it has recycled:\n\n```bash\nnpx sparda-mcp report\n```\n\nThis prints a terminal dashboard aggregating your exposed tools, write opt-ins, proof journal decisions, and crystallized composite tools.\n\nTo write a self-contained, offline HTML dashboard at `.sparda/report.html`, append the `--html` flag:\n\n```bash\nnpx sparda-mcp report --html\n```\n\nTo output raw JSON for integration:\n\n```bash\nnpx sparda-mcp report --json\n```\n\n## Deployment Proof: Apocalypse\n\nSPARDA's Behavior Graph is a formal model of your system. Instead of waiting for runtime failures or relying on static analysis vibes, you can statically prove the safety of your backend before any deployment:\n\n```bash\nnpx sparda-mcp apocalypse\n```\n\nThis command reads the compiled `.sparda/ubg.json` (with zero source code parsing at runtime) and discharges five static correctness obligations:\n* **Unguarded Mutation (Critical)**: Flags any mutation path that does not cross a security `guard`.\n* **Non-Atomic Aggregate Write (High)**: Flags when an API writes to multiple tables of the same Consistency Domain (Aggregate) outside a single transaction scope.\n* **Unvalidated Constrained Write (Medium)**: Flags writes into columns with declared invariants (CHECK, NOT NULL, UNIQUE — parsed from your `.sql` DDL **or `schema.prisma`**, Prisma enums included) without prior validation (Zod/Pydantic).\n* **Irreversible Observable Effect (High)**: Flags out-of-process actions (like Stripe charges) that happen alongside state writes without a structural compensation path (like a catch-refund).\n* **Aggregate Member Bypass (Info)**: Flags mutating a member table directly without routing through the aggregate root.\n\nTo save your current graph as a safe baseline:\n\n```bash\nnpx sparda-mcp apocalypse --save-baseline\n```\n\nSubsequent runs will diff the candidate graph against this baseline to detect regression vectors:\n* Deletion of any security `guard` (Critical).\n* Deletion of a database SQL invariant (High).\n* API blast radius expansion (Medium).\n\nIf any Critical or High finding is found, `apocalypse` exits with a non-zero code to block your CI pipeline.\n\n**One step in your workflow — findings land in the GitHub Security tab (SARIF):**\n\n```yaml\n- uses: zakariagharzouli/sparda@main\n  with:\n    sarif: 'true'\n```\n\n## Time Travel: Timeless\n\nEvery production request is deterministic between its effects — the compiler knows exactly where the nondeterminism lives (db, http, clock, random, uuid: the effect nodes of the graph). Timeless records only those points (a few KB per request) and replays the request **byte-identically** against your current code, with the database, webhooks and clock virtualized from the recording:\n\n```bash\nnpx sparda-mcp timeless                # list recorded flights\nnpx sparda-mcp timeless replay <id>    # re-fly it — byte-identical or loud divergence\nnpx sparda-mcp timeless export <id>    # the production bug is now a vitest test\n```\n\nRecording is two lines in your app (ESM), with deterministic sampling and GDPR redaction built in:\n\n```js\nimport { getFlightBox } from 'sparda-mcp/src/flight/box.js';\nconst box = getFlightBox(); box.arm();\napp.use(box.middleware({ sample: 100 }));   // 1 request in 100; passwords/tokens redacted by default\nconst db = box.wrapClient(pgPool);           // your query client, tapped\n```\n\nThe closed loop nobody else has: **production bug → recorded flight → failing test → AI writes the fix → `apocalypse` proves the fix breaks no guard, invariant or transaction → deploy.** Replay is per-request (concurrent-race capture is out of scope for v1 — stated, not hidden).\n\n## Self-Healing, Proven: `sparda heal`\n\nThe loop above, as **one gesture** — and the machine judges the fix, whoever wrote it:\n\n```bash\nnpx sparda-mcp heal <flightId>                       # diagnose + write the fix brief\n# ...apply the fix (a human, or --agent \"your-ai-cli\")...\nnpx sparda-mcp heal <flightId> --check --expect '{\"status\":404}'\n```\n\nThe brief is built from the graph itself — it hands the fixer the handler's `file:line`, the capabilities the fix must not grow, and the guards it must not remove. Then the **gate** — the actual product — proves the fix on three axes at once:\n\n1. **Behavior** — lenient replay of the recorded flight (same deterministic inputs) now produces the *expected* response, not the recorded bug. The fix may reformulate a query (the tap is relabeled, allowed); it may **not** change the effect order or kinds.\n2. **Compiler laws** — `verify` still passes: the graph is still sound and deterministic.\n3. **No regression** — `apocalypse` diff against the frozen pre-fix graph: zero new critical/high findings, no guard removed, no blast radius grown.\n\n```\n✓ HEALED & PROVEN — same recorded inputs, correct output, zero law broken, zero protection lost. Ship it.\n```\n\nThe gate is honest in both directions: an unfixed bug, or a \"fix\" that silently drops a guard, keeps it **closed** (exit 1). This is the difference between an AI that writes plausible code and a system that *proves* the code is correct — the trust layer the agent era is missing.\n\n## Any Backend On Earth: OpenAPI Lowering\n\nSPARDA parses Express, FastAPI and Next.js natively — and **every other stack through the format the industry already agreed on**. Go, Java, Rails, Laravel, .NET: if it has an OpenAPI spec, it compiles.\n\n```bash\nnpx sparda-mcp ubg --openapi openapi.json\n```\n\nSecurity schemes become gating `guard` nodes, response schemas become typed returns, declared request bodies count as validated input. Pair the spec with your `.sql` or `schema.prisma` files and the full state layer — invariants, aggregates, state machines — fills in from declared truth. (JSON specs in v1; we refuse to half-parse YAML with zero dependencies.)\n\n## The Mirror VM: delete the framework, the app still answers\n\nThe graph is not a diagram — it executes:\n\n```bash\nnpx sparda-mcp mirror\n```\n\n```\nMIRROR — the graph is serving. 3 entrypoint(s) on http://127.0.0.1:4477\n  GET    /orders/{orderId}  → {amount, id, status}\n  POST   /orders  🔒 bearerAuth  → {amount, id, status}\n```\n\nNo Express. No FastAPI. No source code — just `ubg.json` answering HTTP: guards actually deny (401), responses render the compiled return schemas, unknown paths 404 with the full route table. Front-end teams develop against backends that aren't deployed yet — or aren't written yet (point `mirror` at an OpenAPI spec). Every response carries `x-sparda-mirror: true`; the mirror serves declared behavior, it never invents business values.\n\nTo undo everything: **`npx sparda-mcp remove`** restores your code byte-for-byte.\n\n## The promise — every word is backed by a test in CI\n\n<div align=\"center\">\n  <img src=\"assets/features-presentation.png\" alt=\"SPARDA Features\" width=\"800\" />\n</div>\n\n<br/>\n\n1. **Three minutes, one command.** AST scan, router generation, reversible injection — no config.\n2. **Try it for free, leave for free.** `npx sparda-mcp remove` restores your code **byte-for-byte** (tested on JS, TS, Python, even Windows CRLF files). No trace, no lock-in.\n3. **The AI cannot write until you say so.** Every POST/PUT/DELETE is disabled by default; you enable per tool, and your choice survives every re-run.\n4. **Your app defends itself.** A route failing 3 times in a row is quarantined — the AI can't hammer your broken production. Latency anomalies are flagged. Zero LLM needed.\n5. **Nothing leaves your machine.** No telemetry to us, no cloud, local key auth, 4 exact-pinned dependencies.\n6. **What it learns is never lost.** Diagnoses, descriptions, settings — versioned with your git, surviving every re-init.\n\nWhat we *don't* promise: the honest limits in [docs/SECURITY.md](./docs/SECURITY.md).\n\n## How it works\n\n1. `npx sparda-mcp init` parses your codebase (AST), extracts every route, and injects a tiny marked router (`/mcp`) into your app — fully reversible with `npx sparda-mcp remove`.\n2. Tool calls run **inside your live app process** — warm DB pools, real auth chain, real data. SPARDA adds no infrastructure: compute comes from your host process, intelligence from your AI client's own model (MCP sampling), storage from `sparda.json` + git.\n3. Write tools (POST/PUT/DELETE) are **disabled by default**. You opt in per tool in `sparda.json` — your choices survive re-runs.\n4. Suspicious docstrings are sanitized before they ever reach the AI (prompt-injection defense).\n5. `npx sparda-mcp doctor --app` audits your codebase for drift: it detects stale tools (IA seeing ghosts), unsynced routes, schema drift via fingerprints, and zombie configurations. High severity issues trigger a non-zero exit code for your CI pipeline.\n6. `npx sparda-mcp seed export/import` lets you package and share your app's \"genome\" (semantic memory, workflows, antibodies) securely, transferring immune memory between environments or across similar stacks with zero data leak.\n7. `npx sparda-mcp twin` starts a safe, simulated mock server of your backend on the original port. It serves GET calls from learned exemplars (observed response shapes & mock data) and returns simulated 202 writes without ever touching your real database or production APIs. Learn exemplars by running `npx sparda-mcp twin --learn`.\n8. `npx sparda-mcp grammar` maps the graph of valid sequences of tool calls (observed circuits and candidate hypotheses) to prevent LLM hallucination of routes.\n9. `npx sparda-mcp evolve` mutates candidate chains and tests them against the twin in-memory, promoting successful chains to evolved workflow suggestions.\n\n## What SPARDA gives your AI\n\n### Operate, not just read\nEvery route becomes a tool that runs against your live process — real auth, real data,\nwarm connections. One call to **`sparda_get_context`** hands the AI the whole living\npicture: enabled tools, suggested workflows, runtime telemetry, quarantine state, and\nimmune memory — so every session resumes where the last one stopped.\n\n### Write-safety: the AI can't write until you say so\n- Writes (POST/PUT/DELETE) ship **disabled**. Enable them per tool in `sparda.json`; your choice survives every re-init.\n- An enabled write is **never executed on the first call**. SPARDA returns an `awaiting_confirmation` envelope — a single-use token plus a preview of the action — and commits only after an explicit confirm step.\n- When your client supports MCP elicitation, that confirmation prompt appears **in the AI's own UI**.\n- **Proof-after-write**: every successful write is followed by a read-back of the same resource, so the AI — and you — see the real effect, not a hopeful guess.\n\n### Your app defends itself — zero LLM on the hot path\n- **Quarantine.** A tool that returns 3 consecutive 5xx is quarantined: further calls get a `503` with a reason and a retry delay instead of hammering your broken route. After a cooldown it half-opens for a single probe.\n- **Latency & anomaly flags.** The router learns each route's baseline and flags deviations locally, in a few lines of math.\n- **Adaptive diagnosis, only on surprise.** A genuinely new failure wakes your AI client's own model to diagnose it once; the diagnosis is cached as an \"antibody\" in `sparda.json`, so the same failure later costs zero tokens. Cloning your code doesn't clone its immune memory.\n\n### A free intelligence layer, zero API key\nOn first connection your AI client's own model (via MCP sampling) rewrites raw routes\ninto business-language tool descriptions and proposes multi-step workflows — cached in\n`sparda.json` and exposed as MCP prompts. Nothing to configure, nothing to pay.\n\n### It gets cheaper the more you use it\n- **Response recycling.** When a read keeps returning the same answer, SPARDA serves the next identical call straight from memory — without touching your host app. Reads only; writes always hit the host.\n- **A recycling gauge.** `GET /mcp/stats` counts how many calls were answered from SPARDA's own knowledge vs. how many paid the host route. It reads 0% on day one and fills with usage — a measure, never a promise.\n\n### Tools nobody wrote — Labs, opt-in, default OFF\nTurn it on with `\"labs\": { \"recordSequences\": true }` in `sparda.json`. SPARDA then\nnotices when one tool's output feeds the next tool's input and records the *circuit* —\nstructure only (tool names, argument names, counts), never your data. A read-only\ncircuit seen enough times **crystallizes into a composite tool**, announced\nmid-session: one call runs the whole chain, auto-feeding each step from the previous\nstep's real response. Write routes are never absorbed — their per-call confirmation\nalways stands.\n\n### Living context & telemetry\n`GET /mcp/stats` (per-tool calls/errors, tool \"purity\", quarantine state) and\n`GET /mcp/events` (errors, latency anomalies, cached diagnoses) expose exactly what\nyour app is doing — surfaced to the AI as live notifications.\n\n## Built for AI clients: the bundled Skill\nSPARDA ships with an Agent Skill ([`SKILL.md`](./SKILL.md)) that teaches any compatible\nAI client how to drive a SPARDA server to its **full potential** — call\n`sparda_get_context` first, exploit response recycling, honor quarantine, prefer\ncrystallized circuits over re-walking a chain, and follow the two-phase write-confirm\nprotocol. The live, per-project tool list always comes from `sparda_get_context` at\nruntime, so the guidance never goes stale.\n\n## Supported frameworks\n\n- **Next.js App Router (13/14/15)** — file-based injection. SPARDA creates a catch-all route handler. It natively resolves wrapped handlers (`export const POST = withAuth(h)`) and deep effect chains.\n- **NestJS** — AST-based router injection. Deeply resolves Multi-hop Dependency Injection (Controller → Service → Repository), inherited DI, and `baseUrl`/`paths` imports. Supports Prisma, TypeORM, and Kysely.\n- **Express 4/5** (JS/TS, ESM/CJS) — AST-based router injection. Deeply resolves external controllers, Mongoose schemas, and barrel re-exports. Uses dynamic tree-scanning to find non-standard entry points (`bootstrap.ts`, etc).\n- **MedusaJS** — Native AST ingestion of complex e-commerce routing.\n- **Any Backend On Earth (Go, Java, Rails, Laravel)** — Compiles flawlessly from OpenAPI 3.x specs.\n- **FastAPI** (Python >= 3.9) — AST-based router injection.\n\n## Security posture (honest)\n- 4 runtime dependencies, exact-pinned.\n- **Dynamic Local Key Resolution.** The generated router contains no baked secrets. It resolves authorization keys at runtime from the `SPARDA_LOCAL_KEY` environment variable or the local gitignored `.sparda/key` file, and fails closed (503) when neither is found. For custom production or staging setups, you can override this behavior by exposing `SPARDA_LOCAL_KEY` in your environment.\n- Local key on every router call; self-reference loop protection; 30s timeouts; 8 KB output truncation.\n- AST-positioned injection with backup and post-injection re-parse; `npx sparda-mcp remove` leaves a clean git diff.\n- Persistence is **value-free**: SPARDA records structure (tool names, field names, fingerprints), never your payloads.\n\nFull threat model and known gaps: [docs/SECURITY.md](./docs/SECURITY.md).\n\n## Documentation\n- [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md) — how `init`, the injected router, and the bridge fit together, plus the `sparda.json` schema.\n- [docs/SECURITY.md](./docs/SECURITY.md) — threat model, defenses, and honest known gaps.\n- [docs/TESTING.md](./docs/TESTING.md) — how the promises above are kept honest in CI.\n- [docs/ERRORS.md](./docs/ERRORS.md) — the error knowledge base.\n\n## Beyond the open core\nSPARDA is free, including in production (see License). Team-scale capabilities —\nfine-grained per-person access policies and a signed, tamper-evident audit log — are\nplanned for a future paid tier. The open core stands on its own; nothing here is\ncrippled to upsell you.\n\n## License\n[Business Source License 1.1](./LICENSE) — free to use, including in production.\nYou may not resell SPARDA or offer it as a competing commercial service.\nEach version converts to Apache 2.0 four years after its release.\n\n<div align=\"center\">\n  <img src=\"assets/github-star.png\" alt=\"Leave a Star\" width=\"600\" />\n</div>\n\n<br/>\n\nBy [Residual Labs](https://residual-labs.fr)\n",
  "bytes": 25584,
  "sha": "3e6238a39cbd127d072f946a5214c5cd1058814692aaf09bfd0d6668aa29eae4",
  "repo_slug": "zyx77550/sparda",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_zyx77550_sparda_mcp_383ca7fe/readme"
}