Traceability: specs, code and the map
01Every public piece of code in vibe points at the rule it implements, and a generated map lets you ask in either direction: which code implements this rule, which rule does this code answer to.
vibe explain "spec://org.vibevm.core/vibevm/common/PROP-000#KIND-SET"
spec unit spec://org.vibevm.core/vibevm/common/PROP-000#KIND-SET
unmarked — `kind ∈ {flow, feat, stack, tool, mcp, lang, doc, app}` — eight kinds; `mcp` shipped with [PROP-027](../modules/vibe-mcp/PROP-027-mcp-packages.xml); `doc` and `app` admitted by [PROP-057](PROP-057-documentation-packages-and-site.xml) through the `VIBEVM-SPEC.md` §4.1 amendment of 2026-09-12 (pending the owner's ratification at the merge of the docs-2026-09 branch; the code learns the two kinds in that campaign's phase 2). (§Invariants `INV-VOCABULARY` in this file carries the same list.) <status stage="spec" state="done" action="continue" actionstage="impl"/> (vibevm/vibespecs/common/PROP-000.xml:75)
hash sha256:1effee7da317e236ec9b0745d0e02f922cd93134fd731a758428dce62db2a81f
edges in:
documents ← `authoring::write-a-lang-package` (vibevm/vibepacks/org.vibevm.core/vibevm-docs/v1.0.0/vibevm/vibespecs/authoring/write-a-lang-package.xml:14)
documents ← `glossary::index` (vibevm/vibepacks/org.vibevm.core/vibevm-docs/v1.0.0/vibevm/vibespecs/glossary/index.xml:107)
documents ← `model::packages-and-kinds` (vibevm/vibepacks/org.vibevm.core/vibevm-docs/v1.0.0/vibevm/vibespecs/model/packages-and-kinds.xml:45)
Marks in the code
03A Rust item that implements a rule carries an attribute naming the rule's address; a test that verifies one carries a verifying attribute; a module that serves one section as a whole declares a scope. The links live in the code, beside the thing they describe, so they travel with every refactor and every copy. The verbs are implements, verifies, documents, deviates and informs; a deviation must say why.
04 Edges travel with the artefacts. Code-side links live in the code (attributes on items) and survive any refactor that moves the item. Spec-side links live in the spec (stable anchors). External sidecar maps are rejected (§5.1).
05 Verbs:implements,verifies,documents,deviates,informs.deviatesREQUIRESreason.
06implements is a claim about code that runs. A type declaration does not carry it: an edge from a declaration is indistinguishable from coverage, and a map that counted declarations would be green about nothing.
07implementsis a claim about code that RUNS, and a bare declaration does not carry one. A trait, an abstract signature or any other declared shape that no production code implements gets noimplementsedge, however faithfully it describes the requirement. The edge arrives with the implementation.
The map
08cargo xtask specmap walks the crates for marks and the specification tree for units, and writes specmap.json: nodes for every spec unit with its revision and content hash, nodes for every tagged code item, and the edges between them. The map is committed, and cargo xtask specmap --check fails when the tree moved and the map did not. The policy of what is scanned, which crates are gated and which are exempt lives in specmap.toml; the engine itself ships with the discipline package and is vendored, never edited in place.
09 Invariants are machine-checked. Dangling references, uncovered requirements, orphan code, and — the load-bearing one — staleness: a spec unit carries a revision + content hash; when it changes, every edge pinned to the old revision flips to suspect until re-affirmed.
10Three gates guard the map. The orphan ratchet: a public item in a gated crate without a mark fails the check, unless it is dispositioned with a debt id. The resolve gate: every edge into this project's own namespace must land on an existing anchor. The suspect rule: when a spec unit's revision bumps, every edge pinned to the old revision becomes suspect and the check names it, so the code is re-read against the rule that moved.
11 Spec unitrbumps → every edge pinned to the oldrbecomes suspect; CI gate lists them; each is cleared by re-affirming (updating the pin) after review.
12Generated code is excluded from the orphan gate; the generator's input, the schema, carries the marks instead, and a schema scanner reads them.
13 Generated code (e.g.vibe-wire/src/generated/) is excluded from orphan checks via a directory marker; the generator input (JTD schema file) is the taggable unit instead. BUILT 2026-08-05 — both halves are now real. The exclusion half always was:rscanandratchetskip a path containing/generated/. The designation half was a decision nobody could act on, because no scanner opened a.jsonat all and the edge model hangs an address off a code SYMBOL, which a JSON document has no obvious equivalent of. Both are answered: a schema's units are its ROOT and eachdefinitionsentry (symbol=<stem>and<stem>::<def>,item_kind=schema/schema-def), and the tag lives in JTD's ownmetadata.specblock as a verb → URI map. The scanner is opt-in per project throughschema_roots, empty by default. Measured on the host that raised this: seven wire contracts tagged, 16 units and 7 edges in the map, andvibe explainnow answers «what implements PROP-000 §16» with all seven, by file and line.
Asking the map
14The commands below run in a checkout of vibe itself, whose specifications carry a map; an installed package answers only if it shipped one. vibe explain "spec://…#anchor" builds the map fresh in memory and prints one target's subgraph: what implements, verifies or documents it. vibe query filters the map by address, symbol or kind and returns the many nodes that fit. vibe select --where "lacks:verifies scope:spec://…" walks the graph with a predicate: every rule with no verifier, the implementers of a rule and one hop around them. --json gives each answer to an agent.
vibe select --where "uri:spec://org.vibevm.core/vibevm/common/PROP-000#KIND-SET depth:1"
map select · grammar v1 · uri=spec://org.vibevm.core/vibevm/common/PROP-000#KIND-SET AND depth=1
4 results
d0 spec - `kind ∈ {flow, feat, stack, tool, mcp, lang, doc, app}` — eight kinds; `mcp` shipped with [PROP-027](../modules/vibe-mcp/PROP-027-mcp-packages.xml); `doc` and `app` admitted by [PROP-057](PROP-057-documentation-packages-and-site.xml) through the `VIBEVM-SPEC.md` §4.1 amendment of 2026-09-12 (pending the owner's ratification at the merge of the docs-2026-09 branch; the code learns the two kinds in that campaign's phase 2). (§Invariants `INV-VOCABULARY` in this file carries the same list.) <status stage="spec" state="done" action="continue" actionstage="impl"/> vibevm/vibespecs/common/PROP-000.xml:75 spec://org.vibevm.core/vibevm/common/PROP-000#KIND-SET
d1 code doc-page authoring::write-a-lang-package vibevm/vibepacks/org.vibevm.core/vibevm-docs/v1.0.0/vibevm/vibespecs/authoring/write-a-lang-package.xml:1
d1 code doc-page glossary::index vibevm/vibepacks/org.vibevm.core/vibevm-docs/v1.0.0/vibevm/vibespecs/glossary/index.xml:1
d1 code doc-page model::packages-and-kinds vibevm/vibepacks/org.vibevm.core/vibevm-docs/v1.0.0/vibevm/vibespecs/model/packages-and-kinds.xml:1
Documentation in the map
16This manual enters the same map. Every rule block on a page is a documents edge from the page to the rule it quotes, scanned on the host side through the engine's scanner seam. The edge carries no revision pin: the citation is live, the page shows the rule's current text, and the only check is that the anchor exists. Whether the prose around a citation went stale is a human's question, not a suspect flag.
17 Theruleelement is read on the host side: a host module scans documentation pages and injects into the traceability engine through its publicCodeScannerseam (build_with_scanner,check_with_scanner,write_with_scanner,CompositeScanner). The engine and its vendored copies are not edited andsync-enginesis not run. Documentation pages lie outsidespec_roots, the page-scan policy lives in a host file rather than inspecmap.toml, and the scanner is injected at both points ofxtask/src/specmap.rs— the main pass and the resolve gate — so the coverage gate cannot be green by emptiness. The edge's tail is aCodeItemwith the sentinelcrate_name = "<doc>", after the precedent of the JTD scanner's"<schema>"; the engine's wire schema does not change.
18 Everyruleyields adocumentsedge without a pin: the citation is live, and the page shows the fact's current text by address at every render.vibe doc check --citationschecks one thing — that the anchor exists; a vanished anchor without a tombstone fails the build. There are no revisions, no text hashes and no «the spec moved ahead»: such checks would need a history the project does not keep by design.
Edge cases and rules
19Units come in four kinds, and each has a default edge: a requirement is implemented and verified, a design informs, a guide documents; a proposal decides, which is not yet a verb the system carries.
20 Decision. Four unit kinds, each with a different default edge semantics:
21The map is carried, not generated: a mapping between prose and code cannot be inferred, only authored and verified, which is why the marks are in the code and the gates are in the build.
22
The mapping cannot be generated; it can only be carried and verified. Until M1.5's vibe build exists, every edge is authored metadata.
23A package can carry its own map, package.specmap.json, generated by vibe specmap before publishing, so a consumer queries an installed package without rebuilding it.