See what your agents built, against what you specified.
Coding agents merge code faster than people can understand it. ad2v reads your repository and its spec-driven development (SDD) specs, pairs them up, and writes one SQLite file you can explore as a zoomable map, diff on every pull request, and ask questions about from Claude, ChatGPT or VS Code.
Comprehension debt
Specs say one thing. Agents write another. Tests cover a third. Nobody reads every diff, so the gap grows quietly until an audit, an incident or a new hire exposes it. ad2v makes that gap visible and measurable, per requirement, per endpoint, per container, per commit.
Specified but missing
A requirement or endpoint with no code behind it, shown as missing, with the exact spec line.
Built but drifting
Code that exists but no longer matches its spec (path, method, shape): drift. Or the spec changed after the code: stale.
Built but unasked
Routes, jobs and tools nobody specified: orphan. Often debug endpoints an agent left behind.
Read. Pair. Explore.
Extraction is deterministic and makes no LLM calls: the same code, specs and test results give the same file on any OS. ad2v only reads; it never imports or runs your code or tests.
Code, specs, tests, infra
Tree-sitter reads Python (FastAPI, Flask, Starlette routes, workers, env vars). Specs come from OpenAPI, Gherkin, Markdown (spec-kit, Kiro, requirement tables, user stories, EARS; English and Spanish). JUnit results and Terraform plans are optional.
One graph, one file
Spec items and code nodes are linked by ids, routes, test names and your manifest. Each node gets a status and a reason. Git history becomes epochs you can diff, with renames followed through lineage.
Map, PR diff, MCP
ad2v view opens a local 2.5D map. ad2v diff --format md fits a PR comment. ad2v mcp lets any MCP host find and explain components, and draws the map inline.
$ ad2v extract --repo fixtures/payments-recon --spec fixtures/payments-recon/specs \ --test-results fixtures/payments-recon/test-results/junit.xml --out recon.ad2v 20 code files (417 lines), 4 spec files, 127 nodes, 226 edges, 16 workflows in 0.24s $ ad2v status recon.ad2v --side spec status kind qualified_name reasons drift spec_endpoint GET /reconciliations/{run_id}/unmatched link:drift(http:api:GET /v1/…/unmatched) implemented requirement REQ-004 link:implemented(test_req_004_…) missing spec_endpoint POST /reconciliations/{run_id}/approve link:missing needs_review spec_endpoint GET /reconciliations/{run_id}/audit link:needs_review(http:api:GET /{run_id}/audit) specified requirement REQ-007 link:specified $ ad2v view recon.ad2v # opens the map on 127.0.0.1, read-only
Every node says where it stands, and why
Line style carries the status on the map, so you read the state of a system at a glance, in dark and light themes. Every status comes with machine-readable reasons.
One file, many readers
Like mermaid.js, ad2v is an open format plus reference implementations. The .ad2v file is plain SQLite, validated against a published schema, so you can build your own readers too.
An isometric map with more levels than C4
System → containers → modules → functions, plus spec files floating above. Glyph shape is the node kind; line style is the status. Zoom with the wheel, double-click to enter, / to search, Esc to go up. A deterministic layout keeps boxes in place across epochs.
Served on 127.0.0.1 only, GET/HEAD only, strict CSP. The viewer never writes the file.


Replay a request, step by step
Pick an endpoint such as POST /v1/reconciliations and walk its static call workflow. A detail slider follows the zoom and Dim greys out everything but the current step. Risky loops, retries and slow I/O inside transactions are flagged with a severity.


History as epochs, diffs as PR comments
ad2v history extracts one epoch per commit with git archive (no checkout, nothing runs). ad2v diff reports added, removed and renamed nodes, status transitions, risk changes and spec changes. --format md stays under 60 lines, ready for a GitHub Action.


A C4 view built from code, specs and Terraform
Feed a Terraform/OpenTofu plan JSON (or let ad2v read .tf statically) and get, per environment: which service runs which container, env vars the code reads that no deployment provides, and resources nobody uses. Export to Structurizr. ad2v never runs Terraform.


Ask Claude, ChatGPT or VS Code about your system
ad2v mcp is a read-only MCP server (protocol 2026-07-28, older hosts too). Tools like ad2v_locate, ad2v_get_node, ad2v_workflow, ad2v_diff and ad2v_architecture answer with node ids. Hosts that support MCP Apps render the map inline in the chat.
No network, no LLM calls from the server, SQLite opened read-only.


Bring your own model, with a budget
The optional ad2v llm layer adds a semantic judge, link suggestions, summaries, narrations and prose-spec extraction. Use Vertex AI, any OpenAI-compatible server, or the offline fake provider. plan estimates cost; run refuses to start without a USD cap.
Model output is informative only: it can flag drift, never clear a problem. Humans confirm by editing committed files.


Existing project? Start with ad2v init
ad2v init reads the repository (and runs nothing) to propose an ad2v.yaml: spec folders, containers and their languages, test-name prefixes, non-functional requirements. --check later tells you what changed. Team formats in Spanish and English are first-class.


Built to be trusted in audits and CI
Deterministic
Same inputs, same normative dump, byte for byte, on Linux, macOS and Windows (LF vs CRLF+BOM is tested in CI).
Read-only
Never imports or runs repository code, tests or Terraform. Plug-ins are opt-in per repository.
Local-first
The viewer and the MCP server bind to 127.0.0.1 and make no outbound calls. Your code stays on your machine.
AI as advisor
LLM rows carry full provenance and never change an epoch id. Repository content is sent as fenced, untrusted data.
Open format
Versioned spec, SQLite DDL, IR JSON Schema, glyph grammar and visual tokens. ad2v validate checks any file.
Extensible
Stable plug-in API (ad2v.api 1.0) for language extractors and framework packs, with a conformance kit.
Who uses ad2v, and for what
Review what the agent actually did
- Post an ad2v diff on every PR: new orphans, new drift, requirements that lost their tests.
- Catch debug endpoints and unrequested features before merge.
ad2v diff pr.ad2v --from parent --to head --format mdMeasure spec coverage, not just test coverage
- spec-kit, Kiro, OpenAPI, Gherkin or your own Markdown, side by side.
- See which requirements are specified, implemented, verified, or gone stale.
ad2v status app.ad2v --side spec --status staleOnboard onto a brownfield codebase
- Zoom from the system down to a function, replay request flows.
- Ask an MCP host “where is reconciliation approved?” and get node ids back.
ad2v init --repo . && ad2v view app.ad2vKeep code and infrastructure honest
- Env vars the code reads that no deployment provides, per environment.
- Unused resources, and a C4 view you can export to Structurizr.
ad2v extract … --infra-plan prod=plan.json && ad2v c4 app.ad2v --env prodTraceability you can re-derive
- Requirement → code → test links with reasons, in one SQLite file per release.
- A deterministic, canonical JSONL dump as evidence; pin epochs to release labels.
ad2v pin app.ad2v head --label v1.2 && ad2v dump app.ad2v --normative-onlyBuild on an open format
- Read
.ad2vwith any SQLite client, or write an extractor for your language. - Use the read-only MCP tools from your own agents.
ad2v extractor check my-lang --fixture tests/fixtureUp and running in five minutes
ad2v is a pre-release and is not on PyPI yet. Install it from source. You need Python ≥ 3.11, git, and Node ≥ 20 to build the map viewer (the CLI itself is pure Python).
git clone https://github.com/shanglai/ad2v.git cd ad2v python3 -m venv .venv source .venv/bin/activate pip install -e . (cd viewer && npm ci && npm run fixtures && npm run build && npm run build:app) ad2v --version
git clone https://github.com/shanglai/ad2v.git cd ad2v python -m venv .venv .\.venv\Scripts\Activate.ps1 pip install -e . cd viewer; npm ci; npm run fixtures; npm run build; npm run build:app; cd .. ad2v --version
No git? Download the source as a ZIP and run the same steps from the unpacked folder.
Then map the bundled example
ad2v extract --repo fixtures/payments-recon \ --spec fixtures/payments-recon/specs \ --test-results fixtures/payments-recon/test-results/junit.xml \ --out recon.ad2v ad2v status recon.ad2v --side spec ad2v view recon.ad2v
CLI only (CI, MCP tools)
pip install "git+https://github.com/shanglai/ad2v.git"
This installs ad2v without the built viewer: extract, status, diff and mcp work, ad2v view does not.
Works with the specs you already have
| Input | Formats | Notes |
|---|---|---|
| Code | Python (built-in extractor, tree-sitter) | FastAPI, Flask, Starlette routes; workers; env reads. Other languages show as not_evaluable; annotate with // ad2v: REQ-001, or add a plug-in. |
| API specs | OpenAPI | Paired with routes by method and path; x-ad2v-refs ties endpoints to requirements. |
| Behaviour | Gherkin (EN, # language: es) | Scenarios tagged @REQ-001. |
| Markdown | ad2v convention, spec-kit, Kiro, requirement tables, user stories, EARS (EN/ES), custom regexes | Auto-detected in specs/, spec/, docs/specs/, .kiro/specs/, sdd/… |
| Prose docs | Any Markdown | Optional LLM extraction into a proposal you approve (ad2v specs bootstrap). |
| Tests | JUnit XML | Turns implemented into verified. Tests are never run by ad2v. |
| Infrastructure | Terraform / OpenTofu plan JSON, static .tf | GCP and AWS core types; only allowlisted attributes and env var names are stored. |
Where ad2v is today
Built in public, phase by phase, with a report and ADRs for every decision (81 so far).
| Phase | Scope |
|---|---|
| P1–P2 | Format spec, SQLite schema, deterministic extractors, spec↔code pairing, statuses, drift, visual tokens |
| P3 | Multi-epoch storage, parse cache, git history, epoch diff, lineage, stale |
| P4 | Bring-your-own-model LLM layer: judge, suggestions, summaries, prose extraction, budgets |
| P5 | three.js viewer: deterministic layout, LOD map, replay, epoch diff |
| P6–P7 | MCP server + MCP App, retrieval, real-repo readiness, viewer chat |
| P8–P8.1 | Plug-in API, blind eval, packaging, CI, security review, not_evaluable |
| P9 | Brownfield onboarding: ad2v init, Spanish and English team formats |
| P10 | Infrastructure layer, env-var bridge, deterministic C4 view (format v0.7) |
| Next | Public package on PyPI, more language extractors |
Questions
Does ad2v need an LLM or an API key?
No. Extraction, pairing, statuses, diff, the viewer and the MCP server are fully deterministic and offline. The LLM layer is optional and you bring your own model (Vertex AI, an OpenAI-compatible server, or the offline fake provider).
Does it run my code or my tests?
Never. It parses source files, reads JUnit XML you produced, and exports history with git archive. It also never runs Terraform; you hand it a plan JSON.
Which languages does it read?
Python today, through the built-in extractor. Code in other languages is shown as not_evaluable instead of being reported as missing, and you can pair it with // ad2v: REQ-001 comments. The plug-in API lets anyone add an extractor.
Is it on PyPI?
Not yet. Version 0.7.0.dev0 is a development pre-release; install from source as shown above.
Should I commit the .ad2v file?
No. It contains code snippets and optional LLM outputs; treat it like source. Keep it outside the repo or in a gitignored .ad2v/. Commit your specs and ad2v.yaml instead.
Can I use it in CI?
Yes. An example GitHub Actions workflow builds two epochs (merge base and PR head) and posts ad2v diff --format md as a single PR comment. See the CI guide.
What is the license?
Apache-2.0, for the format and the reference implementation. Dependencies are checked by license gates in CI.
Pay down your comprehension debt
Try the demo in your browser, then point ad2v at your own repository.