<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">PROP-032 — The project model as a universal typed graph; the agent-first IDE substrate</title>
  <status stage="spec" state="done" action="continue" comment="B0 2026-07-24: design proposal v0.1, drafted for review; open to challenge until ratified; fact grain 2026-07-24"/>
  <p p="1"><fact id="status-line" status="spec/done">**Status.** Design proposal v0.1 — not implementation-locked. Drafted for review; every decision below is open to challenge until ratified. This PROP names a *model and a direction*; it schedules no implementation of its own. It is the umbrella under which [PROP-014](spec://org.vibevm.ai-native/core-ai-native/mechanisms/PROP-014#index) (traceability) and [PROP-031](spec://org.vibevm.core/vibevm/common/PROP-031#root) (refactoring) become **consumers of one model**, and it fixes the one foundational extension both need: **code as a first-class addressable node.**</fact></p>
  <p p="2"><fact id="companions" status="spec/done">**Companions.** [PROP-014 — specmap bidirectional traceability](spec://org.vibevm.ai-native/core-ai-native/mechanisms/PROP-014#index) (the code↔spec *projection* of this model; its `#edges`, `#queries`, `#runtime` are generalised here) · [PROP-031 — algorithmic refactoring](spec://org.vibevm.core/vibevm/common/PROP-031#root) (the *mutations* over this model) · [PROP-003 — dependency evolution](spec://org.vibevm.core/vibevm/modules/vibe-resolver/PROP-003) §2.5.3 and [PROP-014 §2.7](spec://org.vibevm.ai-native/core-ai-native/mechanisms/PROP-014#llm-boundary) (the LLM boundary this PROP makes the primary interface) · [PROP-000 §3](spec://org.vibevm.core/vibevm/common/PROP-000#license) (permissive-only dependencies) · prior art: LSP, SCIP/LSIF, rustdoc intra-doc links, Sphinx domains (§6).</fact></p>
  <section id="problem" title="1. Problem statement — the reframe">
    <list ordered="false" p="3">
      <item><fact id="ASYMMETRY-CLAIM" status="spec/done">`prop r1` — specmap (PROP-014) gives us a real, deterministic, committed graph of the project — but it is **asymmetric by construction**.</fact></item>
      <item><fact id="EDGE-HARDCODED" status="spec/done">Its `Edge` type is hard-coded `(code item) --verb--&gt; (spec unit)`: a code symbol is always the source, a spec unit always the target, across exactly five verbs (`implements`, `verifies`, `documents`, `deviates`, `informs`).</fact></item>
    </list>
    <p p="4"><fact id="consequences-lead" status="spec/done">Consequences we keep hitting:</fact></p>
    <list ordered="false" p="5">
      <item><fact id="NO-CODE-ADDRESS" status="spec/done">**Code has no stable address.** A `CodeItem` carries a symbol-path, file, and line — all *derived* and *volatile* — but no minted, refactor-stable address. Code can be *pointed from*, never *pointed at*.</fact></item>
      <item><fact id="ONE-DIRECTION-ONLY" status="spec/done">**Only one of four directions exists.** Prose specs cannot cite each other as tracked edges (spec→spec); a spec or a doc cannot point *at* code as the authority (spec→code) — even though sometimes **the code is the best, most precise description** (an algorithm, a wire schema, a canonical example); code cannot reference code across the package boundary as a tracked link (code→code).</fact></item>
    </list>
    <list ordered="false" p="6">
      <item><fact id="AMBITION" status="spec/done">And the ambition is larger than traceability. We want **navigation** (go-to-definition, find-references, impact), **refactoring** (PROP-031), and eventually **surfaces** — a library API, a command line, and one day a graphical view — *all agent-first*.</fact></item>
      <item><fact id="LANGUAGE-SERVER-FRAME" status="spec/done">That is not a traceability index; that is a **language server for the whole project model**: one graph, a query surface, a mutation surface, driven primarily by an agent.</fact></item>
    </list>
    <list ordered="false" p="7">
      <item><fact id="MODEL-NAMED" status="spec/done">This PROP names that model — a **symmetric typed graph over addressable nodes** — and the substrate built on it.</fact></item>
      <item><fact id="CONSUMERS-INSTANTIATE" status="spec/done">PROP-014 and PROP-031 do not compete with it; they instantiate it.</fact></item>
      <item><fact id="SYMMETRY-FIRST" status="spec/done">The model must be symmetric first, or none of navigation, refactoring, or surfaces can be complete, because every one of those is inherently bidirectional.</fact></item>
    </list>
  </section>
  <section id="decisions" title="2. Decisions">
    <section id="graph" title="2.1 The project model is a typed, directed graph over addressable nodes">
      <list ordered="false" p="8">
        <item><fact id="GRAPH-DEF" status="spec/done">`prop r1` — The canonical model of the project is a **typed, directed property graph**: **nodes** are anything with a stable address (spec units today; code items, packages, boot entries as the model grows); **edges** are typed and directed and may connect **any node kind to any node kind**.</fact></item>
        <item><fact id="PROJECTION-NOT-DEFINITION" status="spec/done">specmap's `code→spec` edges are **one projection** of this graph, not its definition.</fact></item>
        <item><fact id="GRAPH-SSOT" status="spec/done">The graph is the single source of truth for navigation and refactoring; everything else (the index file, the queries, the operations, the surfaces) is a view or an action over it.</fact></item>
      </list>
    </section>
    <section id="addressing" title="2.2 Every node carries a stable, minted, location-independent address">
      <list ordered="false" p="9">
        <item><fact id="ADDRESS-MINTED-LAW" status="spec/done">`req r1` — A node's **address of record is minted and travels with the artifact**; its *location* (line number, symbol-path, doc-path, file) is **derived decoration, never the address**.</fact></item>
        <item><fact id="FRAGILITY-LESSON" status="spec/done">This is the property that lets the graph survive refactoring — the lesson [PROP-014 §5.2](spec://org.vibevm.ai-native/core-ai-native/mechanisms/PROP-014#rejected) learned when it rejected line/range anchors as "maximally fragile," here promoted to a model-wide invariant:</fact></item>
      </list>
      <list ordered="false" p="10">
        <item><fact id="ADDR-SPEC-NODE" status="spec/done">**spec node** → `spec://&lt;ns&gt;/&lt;doc-path&gt;#&lt;anchor&gt;`; the `{#anchor}` is minted and immutable, travels via edit-in-place.</fact></item>
        <item><fact id="ADDR-CODE-NODE" status="spec/done">**code node** → `code://&lt;ns&gt;/&lt;id&gt;`; the `&lt;id&gt;` is minted and travels **on an attribute on the item** (§2.3).</fact></item>
        <item><fact id="ADDR-PACKAGE-NODE" status="spec/done">**package node** → the FQID (PROP-029).</fact></item>
      </list>
      <list ordered="false" p="11">
        <item><fact id="ADDRESS-SURVIVES-RENAME" status="spec/done">Because the address is minted, **renaming or moving the artifact does not change its address** — the address moves *with* it.</fact></item>
        <item><fact id="LOCATION-DERIVED" status="spec/done">Location-based addressing is inverted: the symbol-path and line are computed *from* the item at index time, for human navigation, and are free to churn.</fact></item>
      </list>
    </section>
    <section id="code-node" title="2.3 Code is a first-class node (`code://`), not only a source">
      <list ordered="false" p="12">
        <item><fact id="CODE-NODE-EXTENSION" status="spec/done">`req r1` — The concrete extension this PROP exists to fix.</fact></item>
        <item><fact id="CODE-ADDR-FORM" status="spec/done">A code item becomes an **addressable node** under `code://&lt;namespace&gt;/&lt;id&gt;`, where `&lt;id&gt;` is a minted, immutable, kebab-case identifier **carried by a per-language marker on the item** — the `specmark` projection pattern PROP-014 §2.9 already uses (a Rust attribute `#[addr("resolver-fixpoint")]` or a field on `#[spec]`; JSDoc/decorator for the other stacks).</fact></item>
        <item><fact id="CODE-LOCATION-DERIVED" status="spec/done">The item's symbol-path, file, and line are **derived decoration**, exactly as a spec unit's `line` is.</fact></item>
      </list>
      <p p="13"><fact id="code-rules-lead" status="spec/done">Two rules keep it honest:</fact></p>
      <list ordered="false" p="14">
        <item><fact id="MINT-SPARINGLY" status="spec/done">**Mint sparingly.** A `code://` address is minted **only where the code is meant to be pointed at** — a canonical algorithm, a wire schema, a reference example — not on every function. Most code stays addressed only *derivedly* (by symbol-path in the index, which is enough for find-references). Ceremony is proportional to authority.</fact></item>
        <item><fact id="ID-IS-ADDRESS" status="spec/done">**The id is the address, the name is not.** Because the id lives on the attribute, `rename-symbol` / `move-item` (PROP-031) **do not break `code://` links** — the same robustness that makes `#[spec]` survive refactors. This is the whole reason to mint rather than address by symbol-path.</fact></item>
      </list>
      <list ordered="false" p="15">
        <item><fact id="MARKER-ON-ITEM" status="spec/done">**Where the marker lives — on the item, never external.** The address is carried by whatever metadata construct is *idiomatic and scannable* in each language, attached to the item itself, because an address that does not travel with the artifact reintroduces exactly the fragility [PROP-014 §5.1](spec://org.vibevm.ai-native/core-ai-native/mechanisms/PROP-014#rejected) rejected (a sidecar map rots on every refactor).</fact></item>
        <item><fact id="CARRIER-PER-LANGUAGE" status="spec/done">The neutral grammar is the address; the carrier is per-language (PROP-014 §2.9): a **structured attribute** where the language has one (Rust `#[spec(addr = "…")]`, Java/Kotlin annotation, Python decorator), a **structured doc-comment tag** where it does not (TypeScript/JS `/** @addr code://… */`, matching the `@spec` JSDoc choice), and a **comment-directive** for languages with neither (Go `//spec:addr …`, cf. `//go:generate`).</fact></item>
        <item><fact id="CARRIER-CONSTRAINTS" status="spec/done">Three constraints bind every carrier:</fact></item>
        <item><fact id="CC-ON-ITEM" status="spec/done">**on the item** — travels on refactor;</fact></item>
        <item><fact id="CC-SCANNABLE" status="spec/done">**scannable without execution** — read as AST/text, as `#[spec]` is today;</fact></item>
        <item><fact id="CC-STRUCTURED" status="spec/done">**structured, not free prose** — a defined grammar the scanner parses, never a human sentence.</fact></item>
        <item><fact id="ADDR-FACET-RECOMMENDATION" status="spec/done">**Recommendation:** make `addr` a **facet of the existing `specmark` marker**, not a new construct — one code-marker family then carries both a node's *identity* (`addr`) and its *outgoing edges* (the verbs), the whole code-side of the graph in one place.</fact></item>
      </list>
      <p p="16"><fact id="ASYMMETRY-REMOVED" status="spec/done">This single change **removes the asymmetry of §1**: code can now be a *target*, so spec→code, doc→code, and code→code edges become expressible — and the graph is symmetric.</fact></p>
    </section>
    <section id="edges" title="2.4 Edges are typed by authority direction">
      <p p="17"><fact id="EDGE-AUTHORITY-LAW" status="spec/done">`prop r1` — An edge's **verb carries which end is the source of truth**, which is what makes the graph queryable and honest. Generalising [PROP-014 §2.4](spec://org.vibevm.ai-native/core-ai-native/mechanisms/PROP-014#edges) from five code→spec verbs to a directional set:</fact></p>
      <table p="18">
        <tr>
          <td>From → To</td>
          <td>Verb(s)</td>
          <td>Meaning</td>
        </tr>
        <tr>
          <td><fact id="EDGE-CODE-SPEC" status="spec/done">code → spec</fact></td>
          <td><fact id="EDGE-CODE-SPEC-VERB-S" status="spec/done">`implements` `verifies` `documents` `deviates` `informs`</fact></td>
          <td><fact id="EDGE-CODE-SPEC-MEANING" status="spec/done">exist — code defers to the spec as authority</fact></td>
        </tr>
        <tr>
          <td><fact id="EDGE-SPEC-SPEC" status="spec/done">spec → spec</fact></td>
          <td><fact id="EDGE-SPEC-SPEC-VERB-S" status="spec/done">`references` `refines` `supersedes`</fact></td>
          <td><fact id="EDGE-SPEC-SPEC-MEANING" status="spec/done">a prose citation as a tracked edge (the D3 gap, PROP-031 §3.3)</fact></td>
        </tr>
        <tr>
          <td><fact id="EDGE-SPEC-CODE" status="spec/done">**spec → code**</fact></td>
          <td><fact id="EDGE-SPEC-CODE-VERB-S" status="spec/done">**`defined-by` / `canonical`**</fact></td>
          <td><fact id="EDGE-SPEC-CODE-MEANING" status="spec/done">**the normative description of this concept is the code at `code://…`** — the authority *inversion*</fact></td>
        </tr>
        <tr>
          <td><fact id="EDGE-DOC-CODE" status="spec/done">doc → code</fact></td>
          <td><fact id="EDGE-DOC-CODE-VERB-S" status="spec/done">`exemplifies`</fact></td>
          <td><fact id="EDGE-DOC-CODE-MEANING" status="spec/done">the canonical example / reference usage is here</fact></td>
        </tr>
        <tr>
          <td><fact id="EDGE-CODE-CODE" status="spec/done">code → code</fact></td>
          <td><fact id="EDGE-CODE-CODE-VERB-S" status="spec/done">`uses` `see-also`</fact></td>
          <td><fact id="EDGE-CODE-CODE-MEANING" status="spec/done">a cross-item reference (rustdoc intra-doc links, generalised across packages)</fact></td>
        </tr>
      </table>
      <list ordered="false" p="19">
        <item><fact id="INVERSION-RARE" status="spec/done">`canonical` / `defined-by` is a **marked, deliberate, rare inversion** — the peer of `deviates`. It says "this concept's normative content genuinely *is* the code; do not restate it in prose."</fact></item>
        <item><fact id="NO-SHADOW-CODE" status="spec/done">It is **not** a licence for shadow-code: [PROP-014 §3.1.6](spec://org.vibevm.ai-native/core-ai-native/mechanisms/PROP-014#index) ("spec states *what* and *why*, never *how*; a spec that mirrors code is drift fuel") still governs the default.</fact></item>
        <item><fact id="INVERSION-MARKED" status="spec/done">The inversion is the exception you *mark*, exactly as a deviation is.</fact></item>
      </list>
    </section>
    <section id="operations" title="2.5 Three operations over one model: query, mutate, render">
      <p p="20"><fact id="THREE-OPERATIONS" status="spec/done">`prop r1` — The substrate exposes exactly three operation families over the graph, and "the IDE" is nothing more than these three:</fact></p>
      <list ordered="false" p="21">
        <item><fact id="OP-QUERY" status="spec/done">**Query — navigation.** *Go-to-definition* = follow an edge to its target; *find-references* = the reverse edges into a node; *impact* = the transitive closure. specmap already ships these as `explain` / coverage / impact ([PROP-014 §2.6](spec://org.vibevm.ai-native/core-ai-native/mechanisms/PROP-014#queries)); symmetry (§2.3) is what makes them work in *both* directions.</fact></item>
        <item><fact id="OP-MUTATE" status="spec/done">**Mutate — refactoring.** The typed, atomic, gated operations of PROP-031 (`rename-address`, `move-unit`, `rename-symbol`, …), now spanning `spec://` **and** `code://` addresses.</fact></item>
        <item><fact id="OP-RENDER" status="spec/done">**Render — explanation.** The deterministic subgraph plus its optional prose rendering (PROP-014 §2.6); the data layer is always available without an LLM.</fact></item>
      </list>
    </section>
    <section id="agent-first" title="2.6 Agent-first: the primary client emits typed commands; surfaces are progressive">
      <list ordered="false" p="22">
        <item><fact id="AGENT-PRIMARY" status="spec/done">`req r1` — The **primary consumer of the substrate is an agent**, not a human at a keyboard.</fact></item>
        <item><fact id="TYPED-COMMANDS" status="spec/done">An agent drives navigation and refactoring by **emitting typed query/mutation commands** — the LLM boundary of [PROP-031 §2.2](spec://org.vibevm.core/vibevm/common/PROP-031#llm-boundary) and PROP-014 §2.7: *the model proposes a typed command; the deterministic engine executes and gates it.*</fact></item>
        <item><fact id="TRANSPORT-MCP" status="spec/done">The transport is MCP ([PROP-014 §2.8](spec://org.vibevm.ai-native/core-ai-native/mechanisms/PROP-014#runtime), already shipping `specmap_query` / `specmap_explain`).</fact></item>
      </list>
      <list ordered="false" p="23">
        <item><fact id="IDE-HEADLESS" status="spec/done">The consequence reorders the usual notion of "IDE": **the IDE is a headless model-plus-operations server; the GUI is the last, optional client, not the IDE itself.**</fact></item>
        <item><fact id="SURFACES-PROGRESSIVE" status="spec/done">Surfaces are progressive projections of the *same* command set:</fact></item>
      </list>
      <fence p="24">library API  →  command line  →  MCP / agent  →  (last, optional) graphical view
   (exists)       (exists)        (embryo §2.8)        (future, human-facing)</fence>
      <list ordered="false" p="25">
        <item><fact id="GUI-FIRST-INVERTS" status="spec/done">Building GUI-first would invert the dependency — a graphical shell over an incomplete, asymmetric model.</fact></item>
        <item><fact id="MODEL-IS-PRODUCT" status="spec/done">The model and the operations are the product; every surface is a client.</fact></item>
      </list>
    </section>
    <section id="free" title="2.7 Integrity and refactoring fall out of the model, not bespoke code">
      <p p="26"><fact id="FREE-PROPERTIES" status="spec/done">`req r1` — Because everything is one graph with minted addresses, the hard properties are **free**:</fact></p>
      <list ordered="false" p="27">
        <item><fact id="FREE-DANGLING" status="spec/done">a link to an address that resolves to no node is a **dangling** edge (the existing gate);</fact></item>
        <item><fact id="FREE-DUPLICATE" status="spec/done">a duplicate minted id is a **duplicate-address** warning (the existing `duplicate-anchor` machinery);</fact></item>
        <item><fact id="FREE-RENAME" status="spec/done">a rename is a **`rename-address`** operation (PROP-031);</fact></item>
        <item><fact id="FREE-SUSPECT" status="spec/done">a stale pin is a **suspect** (PROP-014 §2.2).</fact></item>
      </list>
      <p p="28"><fact id="SYMMETRY-CHEAP" status="spec/done">This is the reason symmetry is *cheap once the node model generalises*: no new subsystem, only more node kinds and edge directions in the graph that already computes all of this.</fact></p>
    </section>
    <section id="packaging" title="2.8 The substrate is a discipline-neutral, independently-installable tier">
      <p p="29"><fact id="SUBSTRATE-NEUTRAL" status="spec/done">`req r1` — The substrate (specmark + specmap-core + the refactoring operations and their registry, [PROP-033](spec://org.vibevm.core/vibevm/common/PROP-033#root)) is packaged **independently of the ai-native discipline** and delivered as its own installable tier, so vibevm serves a spectrum of users through a **three-tier product model**:</fact></p>
      <list ordered="true" p="30">
        <item><fact id="TIER-BASE" status="spec/done">**Base vibevm** — the package manager itself (resolve / install / lockfile / boot; working with `vibe.toml` projects; loading spec collections). No traceability, no refactoring, no discipline. The "just load a collection of specs" user lives here.</fact></item>
        <item><fact id="TIER-SDD" status="spec/done">**+ the SDD substrate** (a package under `org.vibevm.world`, not `ai-native`) — installs specmark + specmap + the refactoring registry: the `spec://` / `code://` model, integrity checking, navigation, and the algorithmic refactoring core. Proper spec-driven development, **without** the strict discipline.</fact></item>
        <item><fact id="TIER-AI-NATIVE" status="spec/done">**+ the ai-native discipline** (`rust-ai-native`, …) — the strict opt-in: conform, cards, cells, the nine scaffolds. It **depends on** tier 2, contributing its own refactorings to the registry; it never owns the substrate.</fact></item>
      </list>
      <list ordered="false" p="31">
        <item><fact id="DEP-INVERSION" status="spec/done">The dependency runs `ai-native → SDD substrate → base vibevm` — a **dependency inversion** from today, where `rust-ai-native` owns specmap.</fact></item>
        <item><fact id="LEGACY-TIERS" status="spec/done">A legacy tree that cannot adopt the discipline still gets tiers 1–2.</fact></item>
        <item><fact id="REOPENS-RELOCATION" status="spec/done">This re-opens what the Traceability-Relocation plan §1 deferred, for the stronger reason of *product surface* (not cross-language DRY).</fact></item>
        <item><fact id="TIER-CENTER" status="spec/done">The **center of each tier is its Rust library + its spec**, so agents work with it directly (§2.6); the CLI (`vibe refactor …`) and MCP are thin surfaces, never the center.</fact></item>
      </list>
    </section>
  </section>
  <section id="layering" title="3. Layering — what this owns, versus PROP-014 and PROP-031">
    <p p="32"><fact id="layering-lead" status="spec/done">`prop r1` — To avoid duplication (the one real overlap risk), the boundary is explicit:</fact></p>
    <list ordered="false" p="33">
      <item><fact id="OWNS-032" status="spec/done">**PROP-032 (this) owns the *model shape and the vision*:** the universal typed graph (§2.1), the addressing invariant (§2.2), the code node (§2.3), the directional edge set (§2.4), the three operation families (§2.5), and the agent-first substrate (§2.6). It specifies *what the model is*, not *how edges are extracted or gated*.</fact></item>
      <item><fact id="OWNS-014" status="spec/done">**PROP-014 owns the *traceability instantiation and mechanics*:** the `#[spec]`/`scope!` grammar, extraction (`rscan`/`mdspec`), revisions/suspects, the committed `specmap.json`, and the gate. It is the **code↔spec projection** of this model — the first and canonical one — and it **grows** (per this PROP) a `code://` node kind and the spec→spec / spec→code directions. It is not superseded; it is generalised (§7 open question 5).</fact></item>
      <item><fact id="OWNS-031" status="spec/done">**PROP-031 owns the *mutations*:** the typed refactoring operations over the model, gated by re-checking it.</fact></item>
    </list>
    <list ordered="false" p="34">
      <item><fact id="NO-OWN-MECHANICS" status="spec/done">PROP-032 introduces **no extraction or gate mechanics of its own**; it names the model those mechanics populate and the extensions they must grow to cover.</fact></item>
      <item><fact id="ENGINE-HOME" status="spec/done">The engine still lives in `core-ai-native`; the host PROPs (031, 032) drive it, exactly as PROP-031 already does.</fact></item>
    </list>
  </section>
  <section id="anticipation" title="4. Build-in-anticipation">
    <p p="35"><fact id="ANTICIPATION-EXTENDS" status="spec/done">`req r1` — Extends PROP-031 §3 with the model-level disciplines, in force from ratification:</fact></p>
    <list ordered="true" p="36">
      <item><fact id="ANT-ADDRESS-ALL-KINDS" status="spec/done">**Address every node kind; never location-address.** Generalises PROP-031 §3.1 to code and packages: the address of record is always the minted id/anchor/FQID, never a line or a symbol-path. Author nothing that can only be reached by location.</fact></item>
      <item><fact id="ANT-MINT-DELIBERATE" status="spec/done">**Mint `code://` addresses sparingly and deliberately** — only where code is the canonical description (§2.3). Over-minting is noise; under-minting leaves authoritative code unpointable.</fact></item>
      <item><fact id="ANT-EDGE-V3-ONCE" status="spec/done">**Generalise `Edge` from `code→spec` to `node→node` deliberately** (a schema v3 step, §7), not piecemeal — the byte-stable `specmap.json` must migrate once, cleanly.</fact></item>
      <item><fact id="ANT-MODEL-NOT-GUI" status="spec/done">**Build the model and the operations, not the GUI.** The substrate is complete when navigation + refactoring run agent-first over a symmetric, gated graph. A graphical surface is a later, separate, human-facing decision.</fact></item>
    </list>
  </section>
  <section id="rejected" title="5. Rejected alternatives">
    <list ordered="true" p="37">
      <item><fact id="REJ-LOCATION-ADDRESS" status="spec/done">**Address code by location (line or symbol-path).** Fragile — exactly what refactoring changes (PROP-014 §5.2). Retained only as *derived* index decoration, never the address.</fact></item>
      <item><fact id="REJ-BESPOKE-LINK" status="spec/done">**A bespoke "spec→code link type."** Special-cases what should be symmetric. The universal move is a code *node* (§2.3); then spec→code is an edge like any other, and doc→code / code→code come for free. A one-off link type would need a second one for every new direction.</fact></item>
      <item><fact id="REJ-GUI-FIRST" status="spec/done">**A GUI-first IDE.** Inverts the dependency — a shell over an incomplete model. The model + operations are the IDE; the GUI is the last client (§2.6).</fact></item>
      <item><fact id="REJ-SEPARATE-NAV" status="spec/done">**A separate code-navigation tool (a standalone SCIP/LSIF server) beside specmap.** Two graphs, two truths, two things to keep in sync. The code node lives in the *same* graph, so navigation and traceability compose (find every REQ *and* every doc that points at a function, in one query).</fact></item>
      <item><fact id="REJ-COMPUTED-INVERSE" status="spec/done">**Keep the graph `code→spec` only, with a computed inverse.** The inverse answers "what implements this REQ" but cannot represent an *authored* spec→code or spec→spec edge, cannot gate a prose citation, and cannot be refactored — the whole point of §1.</fact></item>
    </list>
  </section>
  <section id="prior-art" title="6. Prior art &amp; license posture">
    <p p="38"><fact id="prior-art-lead" status="spec/done">Conventions and ideas are free; code is not (PROP-000 §3). License fields re-verified before any code-level reuse.</fact></p>
    <table p="39">
      <tr>
        <td>System</td>
        <td>License (verify)</td>
        <td>Role here</td>
      </tr>
      <tr>
        <td><fact id="PA-LSP" status="spec/done">**LSP** (Language Server Protocol)</fact></td>
        <td><fact id="PA-LSP-LICENSE-VERIFY" status="spec/done">n/a (protocol)</fact></td>
        <td><fact id="PA-LSP-ROLE-HERE" status="spec/done">The architecture: one model, a query surface, a mutation surface, many clients. This PROP is "LSP for spec + code + packages, agent-first."</fact></td>
      </tr>
      <tr>
        <td><fact id="PA-SCIP" status="spec/done">**SCIP / LSIF** (Sourcegraph)</fact></td>
        <td><fact id="PA-SCIP-LICENSE-VERIFY" status="spec/done">Apache-2.0</fact></td>
        <td><fact id="PA-SCIP-ROLE-HERE" status="spec/done">**The code-node prior art.** A serialised, committed graph of code symbols + references for navigation without a live server — precisely `specmap.json` for code. They solved the stable-symbol *moniker* problem (§7).</fact></td>
      </tr>
      <tr>
        <td><fact id="PA-RUSTDOC" status="spec/done">rustdoc intra-doc links</fact></td>
        <td><fact id="PA-RUSTDOC-LICENSE-VERIFY" status="spec/done">n/a (rustc)</fact></td>
        <td><fact id="PA-RUSTDOC-ROLE-HERE" status="spec/done">Path-based, compiler-checked in-code references — the `code→code`, integrity-checked precedent.</fact></td>
      </tr>
      <tr>
        <td><fact id="PA-SPHINX" status="spec/done">Sphinx domains + `:ref:`</fact></td>
        <td><fact id="PA-SPHINX-LICENSE-VERIFY" status="spec/done">BSD-2</fact></td>
        <td><fact id="PA-SPHINX-ROLE-HERE" status="spec/done">Prose→object references resolved and checked at build — the `doc→code` precedent.</fact></td>
      </tr>
      <tr>
        <td><fact id="PA-OPENREWRITE" status="spec/done">OpenRewrite (via PROP-031)</fact></td>
        <td><fact id="PA-OPENREWRITE-LICENSE-VERIFY" status="spec/done">Apache-2.0</fact></td>
        <td><fact id="PA-OPENREWRITE-ROLE-HERE" status="spec/done">Typed, gated operations over a lossless model — the mutation half.</fact></td>
      </tr>
    </table>
    <p p="40"><fact id="DIFFERENTIATORS" status="spec/done">**Differentiators.**</fact></p>
    <list ordered="true" p="41">
      <item><fact id="DIFF-ONE-GRAPH" status="spec/done">spec, code, and packages live in **one** graph, so traceability and navigation compose;</fact></item>
      <item><fact id="DIFF-AUTHORITY-TYPED" status="spec/done">edges are **typed by authority direction**, so the graph states who is the source of truth;</fact></item>
      <item><fact id="DIFF-AGENT-CLIENT" status="spec/done">the primary client is an **agent** emitting typed commands, with GUI as the last surface, not the first;</fact></item>
      <item><fact id="DIFF-GATED" status="spec/done">every relation is **gated** by the discipline's own invariant, not merely "compiles."</fact></item>
    </list>
  </section>
  <section id="open" title="7. Open questions">
    <status stage="spec" state="work" comment="B1 2026-07-24: five questions open (q5 decided in place 2026-07-13); ratification pending"/>
    <list ordered="true" p="42">
      <item><fact id="open-code-id-scheme" status="spec/work">**The `code://` id scheme.** A free-minted slug (`resolver-fixpoint`) maximises rename-stability but adds a namespace to manage; a **structured moniker** (SCIP-style: package + descriptor path) needs no minting but moves under refactor. Lean: **free-minted for authoritative nodes** (stability is the point), structured monikers as the *derived* address for everything else.</fact></item>
      <item><fact id="open-node-kinds" status="spec/work">**How many node kinds.** Packages (FQID) and boot entries (INDEX id) are the obvious next nodes (the product tier of PROP-031). Config? Manifests? Grow by demonstrated need, not speculation.</fact></item>
      <item><fact id="open-schema-v3" status="spec/work">**Schema v3 migration.** Generalising `Edge` from `code→spec` (`from_symbol` + `uri`) to `node→node` (two typed addresses) is a `specmap.json` schema change; plan the byte-stable migration (the `check-codegen` idiom, PROP-014 §2.5).</fact></item>
      <item><fact id="open-reverse-edges" status="spec/work">**Reverse-edge storage vs computation.** Find-references can be computed by inverting the edge set (as today) or materialised; decide when the graph grows enough that inversion cost matters.</fact></item>
      <item><fact id="decided-prop-014-grows" status="spec/done">**PROP-014's identity. Decided (owner, 2026-07-13): it grows *in place*.** PROP-014 keeps its title ("specmap: bidirectional traceability") and gains the `code://` node kind + the new edge directions (spec→spec, spec→code); PROP-032 references it as the canonical first projection, not a replacement. No re-scope, no rename — the extension lands as new sections in PROP-014 and new node/edge kinds in its engine.</fact></item>
      <item><fact id="open-gui-when" status="spec/work">**When (and whether) a GUI, and by whom.** Explicitly deferred (§2.6, §4.4). The substrate must be complete and agent-first first; a graphical client is a separate, later, human-facing decision.</fact></item>
    </list>
    <list ordered="false" p="43">
      <item><fact id="ratification-note" status="spec/done">*This PROP is a design proposal. Ratification happens through PR review against this document, PROP-014, and PROP-031.*</fact></item>
      <item><fact id="first-step" status="spec/done">*It commits to no implementation of its own; its first concrete step is the `code://` node (§2.3), sequenced by the SPECMAP Unit-Mobility Plan and PROP-031's operation roadmap.*</fact></item>
      <item><fact id="unexercised-removed" status="spec/done">*Any mechanism specified here that is not exercised by the second shipped node kind or edge direction is removed from the spec rather than carried as aspirational documentation (the PROP-014 §335 discipline, inherited).*</fact></item>
    </list>
  </section>
</spec>
