<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">PROP-035: The spec compiler — directive preprocessor, package formats, and the two-mode boot linker</title>
  <status stage="impl" state="done" action="continue" comment="C 2026-07-25: §5-§13 shipped as vibe-spec (07-15), rename (07-16), normal+static AOT end to end (07-20); the §13 JIT loader and §10 link tables remain"/>
  <p p="1"><fact id="status-line" status="impl/done">**Status: IMPLEMENTED** (designed 2026-07-14 at the owner's request — the flagship "static-compiler vision"; verified against the tree 2026-07-25 by the spec-actualization campaign). §17 records the compiler shipping three times over: §5–§13 as the `vibe-spec` crate wired into `bootgen` (2026-07-15), the link-type rename (2026-07-16), and `normal + static` compiled end to end with the `link × format` question resolved as eager AOT (2026-07-20). **What remains:** the structural / JIT loader of §13 (`normal + dynamic`) and the §10 link tables, both still marked *(provisional)*.</fact></p>
  <p p="2"><fact id="extends" status="spec/done">**Extends:** [PROP-009](PROP-009-loading-model.xml) (the loading model — inclusion types, the two-tree model, the `STATIC.md` / `INDEX.md` artifacts). This PROP turns PROP-009's "ordered list of contributions" into a real **preprocessor + linker**.</fact></p>
  <p p="3"><fact id="supersedes-line" status="spec/done">**Supersedes / folds in:** [PROP-034](PROP-034-transitive-links-boot-graph.xml) (transitive links + the static boot-link graph). PROP-034's linker becomes the *emission layer* of this system (§12); PROP-034 is retained as the narrower, already-drafted contract for that layer until this PROP is ratified.</fact></p>
  <p p="4"><fact id="related" status="spec/done">**Related:** [PROP-028](../../common/PROP-028-package-families.xml) (families — the aggregator role), [PROP-029](../../common/PROP-029-fully-qualified-addresses.xml) (`spec://` addressing, the `/` group↔name joiner), [PROP-008](../vibe-registry/PROP-008-qualified-naming.xml) (pkgref grammar `kind:group/name@version`), the `addressable-specs` flow (anchor / section grammar), [`vibevm/vibespecs/design/loading-and-boot-model.xml`](../../design/loading-and-boot-model.xml) (the static/dynamic-linking metaphor this PROP completes), [PROP-014 specmap](../../../vibepacks/org.vibevm.ai-native/core-ai-native/v1.0.0/vibevm/vibespecs/mechanisms/PROP-014-specmap-bidirectional-traceability.xml) (the `uri↔file` index the router extends).</fact></p>
  <section id="motivation" title="1. Motivation — boot loading must become a toolchain">
    <list ordered="false" p="5">
      <item><fact id="frame-established" status="impl/done">PROP-009 established the frame: **installing a dependency must never modify authored spec** — "the C++ rule that you do not paste a header's text into your `#include`" (PROP-009 §1) — and gave each direct edge an inclusion type (`static` / `dynamic`, PROP-009 §2.4).</fact></item>
      <item><fact id="predecessors-limits" status="impl/done">PROP-034 added transitive links and pinned the boot as a static-linked, deduplicated, topologically-ordered graph. Both are correct and both are **package-granular and directive-free**.</fact></item>
    </list>
    <p p="6"><fact id="gaps-lead" status="impl/done">Three things they do not yet give:</fact></p>
    <list ordered="true" p="7">
      <item><fact id="GAP-PREPROCESSOR" status="impl/done">**A preprocessor.** There is no way for one spec to say "splice this exact section here" (`#embed`), "I depend on this — pull it, in order, before me" (`#use`), or "this contract is implemented over there" (`#source`). Cross-spec composition is done today by prose citation, which the loader does not act on.</fact></item>
      <item><fact id="GAP-RESOLVER" status="impl/done">**A resolver.** Every directive takes a `spec://` address, and the static compiler must turn it into a concrete file/section **algorithmically, without an LLM**. The codebase has no `spec:// → path` function today — resolution is the *inverse* (a filesystem scan mints `path → URI` into `specmap.json`). See §6.</fact></item>
      <item><fact id="GAP-SECTION-GRAIN" status="impl/done">**Section granularity.** Real economy needs the unit of loading to be a **section of a document**, not a whole package or file. PROP-034's graph is over packages; the cascade this PROP needs (`a` pulls one file of a big package, which pulls the next) requires a graph over document **sections** (§5).</fact></item>
    </list>
    <list ordered="false" p="8">
      <item><fact id="context-budget-stake" status="spec/done">The stake is the context budget. Loading vibevm itself already spends ~10% of a 1M window; an operating-system-scale project authored in Spec-Driven Development does not fit at all if every dependency loads whole.</fact></item>
      <item><fact id="TWO-MODE-COMPILER" status="impl/done">This PROP makes boot a **two-mode compiler**: an algorithmic *static* compiler that statically links a whole closure into one file, and a *structural* loader that reads only what is actually used, lazily, in dependency order — the same economy delegation-first buys for *work*, bought here for *loading*.</fact></item>
    </list>
  </section>
  <section id="modes" title="2. Two build modes — static vs structural (AOT vs JIT)">
    <p p="9"><fact id="ONE-SEMANTICS-TWO-EXECUTORS" status="impl/done">The system is one directive semantics with two executors, exactly the GraalVM / Project Leyden split the owner names:</fact></p>
    <list ordered="false" p="10">
      <item><fact id="MODE-STATIC" status="impl/done">**Static build** — packages are concatenated into one (or few) files (`STATIC.md`). Directives are resolved **statically, by code, without an LLM**. This is the AOT / devirtualized path: no runtime indirection, the agent reads a finished file.</fact></item>
      <item><fact id="MODE-STRUCTURAL" status="spec/done">**Structural build** — the agent reads specs **on demand**, following directives as it meets them. This is the JIT / late-binding path; it subsumes PROP-009's current `static` and `dynamic` modes.</fact></item>
    </list>
    <list ordered="false" p="11">
      <item><fact id="EQUIVALENCE-INVARIANT" status="impl/done">**The equivalence invariant.** Both executors MUST produce the *same effective spec* — as AOT and JIT must run the same program. The **static compiler is the reference semantics**; the structural loader (a prompt today, a hard algorithmic agent later, §13) is checked against it.</fact></item>
      <item><fact id="DIFF-TEST-DEFERRED" status="spec/done">Differential testing of the two is real, empirical, and expensive; it is **deferred and planned separately** (§16), not part of the first build. Until then, the structural side is best-effort and the static side is authoritative.</fact></item>
    </list>
    <p p="12"><fact id="contract-lead" status="impl/done">Two executors, one contract:</fact></p>
    <list ordered="false" p="13">
      <item><fact id="EXEC-STATIC" status="impl/done">**Static compiler** — code, fully algorithmic. Buildable now (§8).</fact></item>
      <item><fact id="EXEC-STRUCTURAL" status="spec/done">**Structural loader** — a set of first-loaded instructions (§13) that make the agent honour the directives, pending the future algorithmic agent.</fact></item>
    </list>
  </section>
  <section id="formats" title="3. Package formats — `simple` and `normal`">
    <p p="14"><fact id="FORMAT-FIELD" status="impl/done">A new `vibe.toml` `[package]` field `format`, alongside `version`:</fact></p>
    <list ordered="false" p="15">
      <item><fact id="FORMAT-SIMPLE" status="impl/done" action="continue" actionstage="doc" audience="author">**`format = "simple"`** — **the default** (absent `format`, a package is `simple`). Legacy / adapted prompts, carried **whole**, with no VibeVM-specific structure — for importing existing corpora without rewriting them, and the fail-safe posture. Rules: inclusion in `[requires.packages]` means (a) structural — the agent reads the file; (b) static — its text is compiled into the target. If `[boot_snippet].source` names a file, only that file is read/spliced; **absent even that, every file in the package is read/spliced by a recursive walk** — the over-load is the author's problem, the deliberate cost of not adopting `normal`.</fact></item>
      <item><fact id="FORMAT-NORMAL" status="impl/done" action="continue" actionstage="doc" audience="author">**`format = "normal"`** — the VibeVM-native form, **opt-in**: the `contract` / `source` split (§4), directives (§7), and the compiler (§8). A `normal` package is **not read just because it is present** — it participates only when something actually `#use`s it (§7.2). This is tree-shaking; the optimized posture for authors who understand the machinery, at the price of structuring the package correctly.</fact></item>
    </list>
    <list ordered="false" p="16">
      <item><fact id="SIMPLE-DEFAULT-WHY" status="impl/done">**Why `simple` is the default (owner decision, 2026-07-15).** A forgotten `format` must **fail safe, not silent**.</fact></item>
      <item><fact id="fail-safe-argument" status="spec/done">With `normal` as the default, a naive or mis-built package that nobody `#use`s loads **nothing** — a silent no-op, the worst failure. With `simple` as the default it loads **everything** — noisy and unoptimized, but visibly working; the author opts into `normal` and its discipline deliberately.</fact></item>
      <item><fact id="migration-non-event" status="spec/done">Migration (§15) is thereby a non-event: the existing corpus keeps working as `simple`, and packages convert to `normal` one at a time as their authors optimize them.</fact></item>
    </list>
  </section>
  <section id="contract-source" title="4. Normal packages — the contract / source split">
    <p p="17"><fact id="hpp-cpp-inspiration" status="impl/done">Inspired by C/C++ `.h` / `.cpp`:</fact></p>
    <list ordered="false" p="18">
      <item><fact id="DIR-CONTRACT" status="impl/done" action="continue" actionstage="doc" audience="author">**`contract/`** — small, simple, boot-snippet-like. The surface a package exposes outward; short files, cheap to load. The analogue of a header.</fact></item>
      <item><fact id="DIR-SOURCE" status="impl/done" action="continue" actionstage="doc" audience="author">**`source/`** — large, heavy. The full implementation; pulled only when actually needed. The analogue of a translation unit.</fact></item>
    </list>
    <list ordered="false" p="19">
      <item><fact id="SOURCE-HACK" status="impl/done">Because the structural executor lacks a C++ compiler's global view of the source tree, we use a deliberate hack: **the contract author declares what implements it, via `#source`** (§7.3). The author hand-draws edges a globally-aware compiler would infer.</fact></item>
      <item><fact id="link-tables-give-back" status="spec/work">That global view *does* exist in static mode and can be pre-compiled into **link tables** (§10), which is how we give the same knowledge back to the structural executor cheaply and make the hand-drawn `#source` edges verifiable.</fact></item>
    </list>
    <p p="20"><fact id="CONTRACT-IS-SURFACE" status="impl/done">The `contract` surface is what other packages include; `source` is reached only through a resolved contract edge or an explicit `#use`/`#embed` into it.</fact></p>
  </section>
  <section id="ir" title="5. The document IR — one hierarchical tree, two frontends">
    <p p="21"><fact id="DOCUMENT-IR" status="impl/done">Everything downstream operates on a single **document IR**: a DOM-like tree. Markdown and (future) XML are two frontends parsed into the same tree, so algorithms written against the IR scale to deeply nested XML for free.</fact></p>
    <list ordered="false" p="22">
      <item><fact id="IR-NODE" status="impl/done">**Node** = `{ id (anchor / tag), depth, kind, body-span, children[] }`.</fact></item>
      <item><fact id="IR-MD-FRONTEND" status="impl/done">**Markdown frontend.** Headings form the tree by level (`#` ⊃ `##` ⊃ `###`). A node's `id` is its explicit `{#anchor}`. A node's **body span runs from its anchored heading to the next heading of the same or higher level** (the owner-fixed rule); its children are the nested headings inside that span.</fact></item>
      <item><fact id="IR-FACT-LEAVES" status="impl/done">**Fact leaves** *(fact amendment, owner-ratified 2026-07-24)*. A `##&lt;ID&gt;` first token of a paragraph or list item (the fact unit of PROP-014 §2.1 / PROP-043 §3.8) is a **leaf node** of the IR: `kind = fact`, `id = &lt;ID&gt;`, body-span = the carrying paragraph or item with its continuation lines; its parent is the enclosing section node. Fact ids share the document's one anchor namespace. The resolver (§6) resolves a fact address like any node; `#embed` of a fact splices exactly its unit (§7.1's arbitrary granularity, unchanged); `#use` of a fact address pulls the top-level anchored ancestor of its **enclosing section** (the existing rule, unchanged).</fact></item>
      <item><fact id="IR-XML-FUTURE" status="spec/done">**XML frontend (future).** Elements already are the tree; `tag`/`id` is the address. Held for later, but the IR is designed for it now.</fact></item>
      <item><fact id="IR-ADDRESS-DEPTH" status="impl/done">**Addressing depth.** A `spec://…#a.b.c` fragment is a **path down the tree** (`a` → `b` → `c`), which already matches addressable-specs' dotted anchors (`#verification.timeout`). Sections at any depth are addressable.</fact></item>
    </list>
    <p p="23"><fact id="granularity-rules-lead" status="impl/done">**Granularity rules** (owner-set), stated over the IR:</fact></p>
    <list ordered="false" p="24">
      <item><fact id="USE-ANCESTOR-RULE" status="impl/done" action="continue" actionstage="doc" audience="author">**`#use` pulls the whole top-level anchored ancestor** of the addressed node — reference a subsection, load its enclosing top-level section as one connected block. It does **not** pull that ancestor's siblings; siblings are read only when themselves needed.</fact></item>
      <item><fact id="EMBED-EXACT-RULE" status="impl/done" action="continue" actionstage="doc" audience="author">**`#embed` has arbitrary granularity** — it splices exactly the addressed node, no more.</fact></item>
      <item><fact id="ANCESTOR-PARAMETER" status="impl/done">"Top-level anchored ancestor" is a **parameter of the resolver**, not a hardcoded heading level, so the XML frontend can define it structurally.</fact></item>
    </list>
  </section>
  <section id="addressing" title="6. `spec://` addressing and the resolver (&quot;router&quot;)">
    <list ordered="false" p="25">
      <item><fact id="FORMAT-CHOICE" status="impl/done">**Format choice.** `spec://` stays. Alternatives are strictly worse: path-based is fragile across `packages/`→`vibedeps/` materialization and drops versions; content-addressed (by hash) is unreadable and cannot "name a section"; query-based (by tag) is non-deterministic (may match N nodes) where a preprocessor needs exactly one. `spec://` is already symbolic, human-readable, and carries `group`/`name`/`path`/`anchor`. The gap is not the format — it is the **missing resolver**.</fact></item>
    </list>
    <p p="26"><fact id="UNIFIED-GRAMMAR" status="impl/done">**Unified grammar** (reconciled with the pkgref grammar of PROP-008):</fact></p>
    <fence p="27">spec://&lt;group&gt;/&lt;name&gt;[@&lt;version&gt;]/&lt;doc-path&gt;#&lt;anchor&gt;[.&lt;sub&gt;…][~r&lt;N&gt;]</fence>
    <list ordered="false" p="28">
      <item><fact id="URI-JOINER" status="impl/done">`group` ↔ `name` joiner is **`/`, never `.`** (PROP-029).</fact></item>
      <item><fact id="URI-VERSION-OPTIONAL" status="impl/done" action="continue" actionstage="doc" audience="author">`@&lt;version&gt;` is **optional — a feature, never an obligation (owner-ruled 2026-08-04, B-028: «указание версий — опциональная фича; если версия не указана — используется самая свежая»)**; absent, the address resolves against the **freshest installed version** of the package (semver-newest among the materialised `vibedeps/` slots — the one deterministic offline reading of «самая свежая»). Several coexisting slots are therefore not an ambiguity but an ordered set with a defined maximum; an explicit `@&lt;version&gt;` still picks its exact slot, including a non-newest one.</fact></item>
      <item><fact id="URI-TREE-PATH" status="impl/done">`#&lt;anchor&gt;.&lt;sub&gt;…` is a **tree path** into the document IR (§5).</fact></item>
      <item><fact id="URI-REVISION-PIN" status="spec/done">`~r&lt;N&gt;` pins a spec-unit revision (PROP-014), not a package version.</fact></item>
    </list>
    <p p="29"><fact id="THE-ROUTER" status="impl/done">**The router** is the new component: a deterministic function `spec:// → IR node`, evaluated over the resolved, materialized tree. It is the prerequisite everything else stands on. It must handle, without an LLM:</fact></p>
    <list ordered="false" p="30">
      <item><fact id="ROUTER-SELF-COORDINATE" status="impl/done">**The self coordinate (B-031, owner-approved 2026-08-04)** — the root project's own `&lt;group&gt;/&lt;name&gt;` (declared in `[project]`, e.g. `org.vibevm.core/vibevm`) resolves to the workspace's **authored `spec/` tree**, matched before any `vibedeps/` slot lookup and never versioned; an undotted authority (the retired host token, illustrative fixtures) parses but never resolves — a hard error carrying the rename hint.</fact></item>
      <item><fact id="ROUTER-DOC-ID" status="impl/done">**Doc-id truncation** — `PROP-NNN` / `FEAT-NNN` in a URI resolve to `PROP-NNN-&lt;slug&gt;.md`; other docs use the full stem. (This is `canonical_doc_path` in the specmap engine, reused, not reinvented.)</fact></item>
      <item><fact id="ROUTER-VIBEDEPS" status="impl/done">**`packages/` (source) vs `vibedeps/` (materialized slot)** — the compiler resolves against the **materialized `vibedeps/` tree** (the installed reality), consistent with the specmap engine, which never scans `packages/`.</fact></item>
      <item><fact id="ROUTER-VERSION" status="impl/done">**Version selection when `@version` is absent — the freshest installed** (semver-newest slot; owner-ruled 2026-08-04, B-028, superseding the earlier lockfile wording). A lockfile-informed selection layer above the router remains possible machinery, but the router's own default is the newest materialised slot — deterministic over the installed set.</fact></item>
    </list>
    <list ordered="false" p="31">
      <item><fact id="ROUTER-DETERMINISM" status="impl/done">Determinism is a hard requirement: the static compiler must resolve every address to exactly one node or fail loudly.</fact></item>
      <item><fact id="ROUTER-EXTENDS-SPECMAP" status="impl/done">The router extends the `specmap.json` index (already a `uri↔file` table) rather than duplicating it.</fact></item>
    </list>
  </section>
  <section id="directives" title="7. The three directives">
    <list ordered="false" p="32">
      <item><fact id="DIRECTIVE-SHAPE" status="impl/done">Common shape: `#&lt;directive&gt; [options] &lt;specpath&gt;`, where `specpath` is a `spec://` address (§6) — a section, or a whole file.</fact></item>
      <item><fact id="DIRECTIVE-MANIFEST-AGREE" status="impl/done" action="continue" actionstage="doc" audience="author">Every file referenced by any directive MUST be declared in the package's `vibe.toml` (the directive graph and the manifest cannot disagree).</fact></item>
      <item><fact id="DIRECTIVES-FIRST-LOADED" status="spec/done">The directive instructions are among the first things loaded, in every project, package, and library (§13).</fact></item>
    </list>
    <section id="embed" title="7.1 `#embed` — the macro (materialization-time)">
      <p p="33"><fact id="EMBED-DEF" status="impl/done">The simplest preprocessor directive: splice one section (or whole file) into another — a C-macro substitution over `spec://` addresses.</fact></p>
      <list ordered="false" p="34">
        <item><fact id="EMBED-FIRES" status="impl/done">**Fires at materialization** (`vibe install` into `vibedeps`) **and** must be fully expanded during `STATIC.md` compilation. **No unexpanded `#embed` may survive in a compiled `STATIC.md`.**</fact></item>
        <item><fact id="EMBED-MODE-INDEPENDENT" status="impl/done">**Mode-independent.** `#embed` is purely a materialization concern — it produces the same text in both build modes. Therefore `vibedeps` stores embeds **already expanded**, while `#use`/`#source` (mode-dependent) remain as directives. This split removes a large part of the ordering problem: embeds are fixed early and identically for both executors.</fact></item>
        <item><fact id="EMBED-CONTRACT-RULE" status="impl/done">**Contract-section rule.** An `#embed` targeting a `contract`-section of a `normal` package inherits the full **`#source` compilation rules** (§7.3) for that paragraph — so the merged (contract+source) text is what gets spliced.</fact></item>
        <item><fact id="EMBED-UNRESTRICTED" status="impl/done">**Unrestricted otherwise.** `#embed` may splice any paragraph of any spec, or a whole spec (including `format = "simple"`), with no structural checks.</fact></item>
        <item><fact id="EMBED-PURPOSE" status="impl/done">**Arbitrary granularity** (§5). Algorithmic; the tool of building highly-optimized statically-assembled package hierarchies — its main purpose.</fact></item>
      </list>
    </section>
    <section id="use" title="7.2 `#use` — the dependency edge (tree-shaking)">
      <p p="35"><fact id="USE-DEF" status="impl/done">The harder directive: pull only the packages actually needed.</fact></p>
      <list ordered="false" p="36">
        <item><fact id="use-problem" status="spec/done">**Problem it solves.** Specs refer to entities defined elsewhere, often without an explicit link, and linking constantly is tedious. Without `#use`, the smallest script would have to pull the whole standard library.</fact></item>
        <item><fact id="USE-TREE-SHAKING" status="impl/done" action="continue" actionstage="doc" audience="author">**Tree-shaking default.** A `format = "normal"` package that nobody `#use`s does not participate — not read, not used, anywhere. The moment any text does `#use spec://…`, that package **enters the build** and MUST be linked **before** its user in topological order.</fact></item>
        <item><fact id="USE-STRUCTURAL" status="spec/done">**Structural mode.** `#use` is an instruction to read the target's content **when it is needed** — not eagerly, but definitely **before using anything inside it**. Reads **cascade**: `a` `#use`s `b`, `b` `#use`s `c`, so using `a` loads `b` and `c` transitively. The cascade is what lets a big package be entered through one file and expand from there, rather than loaded whole.</fact></item>
        <item><fact id="USE-INLINE" status="impl/done">**Inline mode.** The same, statically: the `#use`d library's text is **fully copied higher up in `STATIC.md`** so it is available before the user.</fact></item>
        <item><fact id="USE-GRANULARITY" status="impl/done">**Granularity.** Pulls the whole top-level anchored ancestor of the addressed node (§5).</fact></item>
        <item><fact id="USE-CONTRACT-RULE" status="impl/done">**Contract-section rule.** A `#use` into a `contract`-section of a `normal` package inherits the `#source` rules (§7.3). Otherwise `#use` may pull any paragraph or whole spec (even `simple`) with no structural checks.</fact></item>
        <item><fact id="USE-AS-ALIAS" status="spec/work">**The `as` clause (B-011, owner-approved 2026-08-04).** `#use [options] &lt;specpath&gt; as &lt;Alias&gt;` additionally binds `&lt;Alias&gt;` — an identifier under the anchor-segment grammar (§6) — to the directive's address. The alias is **file-scoped** (visible throughout the declaring file regardless of declaration position, never exported, never inherited by `#use`-ers); two declarations of one alias name in one file are a compile error. The alias binds to the **address**, never to any compiled text — so it survives splicing and any later cleaning of the compiled lane. A trailing `as` clause is ignored by pre-B-011 scanners (the token tail after the address was never parsed), so the clause is backward-compatible by construction.</fact></item>
      </list>
    </section>
    <section id="source" title="7.3 `#source` — contract↔implementation virtual linking">
      <p p="37"><fact id="SOURCE-DEF" status="impl/done">Like a C++ interface, but with section-level merging. `contract` sections are the exposed surface; `#source` names the file(s) that implement them. Sections are treated as the analogue of class methods, needing a merge (in the static build) or virtual-lookup (in structural mode) mechanism.</fact></p>
      <p p="38"><fact id="merge-algorithm-lead" status="impl/done">Merge algorithm, per section (by matching `{#tag}`):</fact></p>
      <list ordered="true" p="39">
        <item><fact id="MERGE-CONTRACT-ONLY" status="impl/done">**In contract, absent in source** — structural: a full part of the spec, readable at will; static: compiled into the build whole.</fact></item>
        <item><fact id="MERGE-SOURCE-ONLY" status="impl/done">**In source, absent in contract** — always counted; structural: readable at will; static: compiled in whole. *(Calling a section that exists only in the implementation is poor taste, but permitted — we deliberately impose no `private`/`public` access control.)*</fact></item>
        <item><fact id="MERGE-BOTH" status="impl/done">**In both, same `{#tag}`** — merged by the tag's mode:</fact></item>
        <item><fact id="MERGE-REPLACE" status="impl/done">**`:replace`** — `# name {#tag} :replace` — the contract text is ignored; the source text is canonical (read by the agent / put in the static build; an already-read contract text is explicitly superseded).</fact></item>
        <item><fact id="MERGE-ADD" status="impl/done">**`:add`** — `# name {#tag} :add` — the result is the **sum**: contract text first, then source text. Static: compile the concatenation. Structural: the agent reads both and weights them equally.</fact></item>
        <item><fact id="MERGE-DEFAULT-ADD" status="impl/done" action="continue" actionstage="doc" audience="author">**Default is `:add`** (absent a `:`-suffix) — so the interface text need not be duplicated to appear in the result.</fact></item>
      </list>
      <p p="40"><fact id="fact-inheritance-lead" status="impl/done">**Fact inheritance** *(fact amendment, owner-ratified 2026-07-24 — closes F-022)*:</fact></p>
      <list ordered="true" p="41">
        <item><fact id="FACT-SECTION-FATE" status="impl/done">**Section fate by default.** Facts ride their section: `:add` carries both sides' facts into the sum; `:replace` supersedes the contract's facts — text and fact anchors together.</fact></item>
        <item><fact id="FACT-OVERRIDE" status="impl/done">**Per-fact override.** Within a merged `:add` section, a source fact redeclaring a contract fact's `##&lt;ID&gt;` **overrides** it: the contract fact's span is dropped from the merged output and the source's is canonical (last-wins in contract→source order). One id, one unit — redeclaration IS the override gesture, so refining a single statement never requires `:replace`-ing the whole section.</fact></item>
        <item><fact id="FACT-MERGED-UNIQUENESS" status="impl/done">**The merged view holds uniqueness.** After merging, the compiler re-runs the anchor-uniqueness check — fact and heading ids, one namespace — over the merged document; a surviving duplicate (a non-override collision across sections, or fact-vs-heading) is a **build error**, never a warning. Per-file cleanliness of the inputs does not exempt the merged output. *(Precision, from the implementation review 2026-07-24: the gate flags a repeat only when at least one occurrence is a fact leaf — a pure heading-vs-heading repeat is the `:add` concatenation's own artifact (both section versions legitimately carry the same `{#tag}`), not a collision.)*</fact></item>
      </list>
      <p p="42"><fact id="sequence-lead" status="impl/done">**Several sources, and the plugin form** *(B-056, owner-ruled 2026-08-04, built 2026-08-05)*:</fact></p>
      <list ordered="true" p="43">
        <item><fact id="SOURCE-SEQUENCE" status="impl/done">**A contract may declare more than one `#source`, and every one is honoured, in declaration order.** The algorithm above reads "the source" as that sequence: for an anchor `a`, let `S(a)` be the sub-sequence of sources carrying a section at `a`, in the order the directives were written (a glob contributing its members sorted). Before this the compiler took the FIRST `#source` and dropped the rest without a word — the silence B-055 (closed by `bc88e530`) recorded.</fact></item>
        <item><fact id="SOURCE-REPLACE-IS-A-FLAG" status="impl/done">**`:replace` from ANY source discards the contract text only; the sources still sum among themselves, in order.** Over a sequence `:replace` stops being "whose text is canonical" and becomes a flag, after which two sources both carrying it is not a conflict to adjudicate. With one source the result is byte-identical to ##MERGE-REPLACE, so the generalisation is backward compatible.</fact></item>
        <item><fact id="SOURCE-FACT-OVERRIDE-IS-A-UNION" status="impl/done">**Per-fact override widens to the union over `S(a)`.** A contract fact is dropped when ANY member redeclares its id — one id, one unit, and whoever redeclares it takes it. Two sources redeclaring one id is not a fold question: both survive into the merged text and @fact:FACT-MERGED-UNIQUENESS fails on the duplicate, loudly.</fact></item>
        <item><fact id="SOURCE-ONLY-IS-A-DEFINITION" status="impl/done">**A source-only section declared by two sources is an error, and the asymmetry is deliberate.** A source section matching a contract anchor is an *addition* to something already declared, so summing is right; a source-only section is a *new declaration*, and two of them are two definitions of one name — declaration is idempotent, definition is not (the ODR parallel §9 draws). **Where it is caught matters:** @fact:FACT-MERGED-UNIQUENESS sees a document whose provenance is already gone and deliberately tolerates a repeated heading (that shape is the legitimate `:add` artefact), so the collision is judged in the fold, which still knows which source brought what.</fact></item>
        <item><fact id="SOURCE-RECURSION" status="impl/done">**The fold follows `#source` recursively under §9's cycle law, and it carries an include guard.** A source that itself declares `#source` folds before it merges into its parent; a cycle among contracts is legal and its not-yet-folded member contributes nothing (the forward declaration); a cycle touching an implementation is a build error naming the path. This is @fact:NO-DEADLOCK-INVARIANT reaching the fold — the same walker, one more edge set, never a second traversal. **The guard is not bookkeeping:** visiting a shared node once does not make its TEXT appear once, because the fold is textual inclusion — without a guard a diamond carries the shared body in along both paths, and a shared source declaring a fact then fails the uniqueness check, turning an ordinary composition into an un-buildable error. A node's text therefore enters the composed document exactly once, by the first path in fold order.</fact></item>
        <item><fact id="SOURCE-GLOB" status="impl/done">**The plugin form.** A `#source` address may carry a `*` in the package-NAME half; it names every installed package whose name matches AND that carries the addressed document, expanded in sorted order — so the composed document is a pure function of (tree, lockfile). A glob matching nothing is a legal empty set, never a missing source; a pointed address still fails loudly when its target is absent. Both the fold and the cycle guard read a document's `#source` edges through one function, so the graph the guard judges is the graph the fold walks.</fact></item>
      </list>
    </section>
    <section id="in-place-use" title="7.4 In-place use — the `@spec://` sigil">
      <p p="44"><fact id="in-place-lead" status="impl/done">Implicit dependency without an explicit `#use`, made precise by a sigil:</fact></p>
      <list ordered="false" p="45">
        <item><fact id="AT-SPEC-MANDATORY" status="impl/done" action="continue" actionstage="doc" audience="author,agent">**`@spec://…`** (an `@` before `spec`) is an **in-place use**: the agent MUST read it (mandatory), exactly as if a `#use` had been declared at the top of the file. **Amendment (2026-08-24, the normal-flip ruling):** the obligation is the AGENT's, not the AOT compiler's — a `@spec` target is **never spliced** into a compiled lane; the address itself is the compiled artefact, and the §2 equivalence invariant is carried by the agent's read obligation. (Splicing every `@spec` realised ##OPEN-CLOSURE-EXPLOSION on the first normal-format host build: the lane grew 250 KB → 2.5 MB off prose pointers.) Only an explicit `#use` is a compiler splice edge.</fact></item>
        <item><fact id="BARE-SPEC-DISCRETIONARY" status="impl/done" action="continue" actionstage="doc" audience="author,agent">**Bare `spec://…`** (no `@`) is at the agent's discretion — read it if useful, skip it otherwise. (A future algorithmic agent narrows this further.)</fact></item>
        <item><fact id="READ-ONCE" status="impl/done" action="continue" actionstage="doc" audience="agent">**Read once.** An `@spec` target is read only on **first** encounter, never re-read blindly — see the read-set (§below).</fact></item>
        <item><fact id="IN-PLACE-RESOLUTION-ORDER" status="impl/done">**Resolution order.** Collect all explicit `#use` into a map, enrich it with the `@spec` in-place uses, then act on the combined map.</fact></item>
        <item><fact id="AT-BANG-IS-AN-ALIASED-IN-PLACE-USE" status="spec/work">**`@!&lt;Alias&gt;` (B-011, owner-approved 2026-08-04)** is the aliased twin of `@spec://…`: a **mandatory** in-place use of the address the file's `as`-declared alias binds to (§7.2), with identical read-once / read-set semantics. `@!X` where `X` is not declared in the file is a compile error naming the file's known aliases. In the compiled static lane every `@!X` is rewritten to the full `@spec://…` address it denotes — the compiled output is self-describing without the alias table and resolvable after any cleaning; structural mode reads the declaration and the sigil directly.</fact></item>
        <item><fact id="SHORT-LABEL-LOOKUP-IS-TWO-SCOPE" status="spec/work">**The short-reference lookup rule (B-011).** An *unqualified* label reference (an intra-document `(#x)` link) resolves against exactly two scopes, in order: (1) the anchor namespace of the containing document; (2) the file's declared aliases. Found in neither, or in both: a **compile error listing the candidates** — the resolver never widens the search and never picks silently.</fact></item>
      </list>
      <list ordered="false" p="46">
        <item><fact id="READ-SET" status="spec/done">**The read-set (surviving compaction).** To honour "read once" across an agent's context compaction, a persistent, file-based **read-set** (`.vibe/session/read-set.json` or equivalent) records `{ specpath, content_hash }` on each read; the `content_hash` is reused from specmap, so a *changed* section is re-read.</fact></item>
        <item><fact id="read-set-boot-instruction" status="spec/done">A first-loaded instruction (§13) tells the agent to consult the read-set before reading and append after — this survives compaction because the boot instructions are re-read.</fact></item>
        <item><fact id="read-set-records-existence" status="spec/done">Crucially the read-set records *what exists and where*, **not what is currently in context**: compaction evicts the *text* but not the *fact*, and reads are cheap (files sit in `vibedeps`).</fact></item>
        <item><fact id="READ-SET-RULE" status="spec/done">So the rule is: read an `@spec` target if (a) it is not in the read-set, **or** (b) it is, but its content is no longer in context.</fact></item>
        <item><fact id="read-set-floor" status="spec/done">A clean solution without a harness compaction signal is out of scope; the file-based read-set plus a boot instruction is the pragmatic floor, and the future algorithmic agent keeps the read-set rigorously. Mental model: a **linker symbol table, but for what has been read**.</fact></item>
      </list>
    </section>
  </section>
  <section id="pipeline" title="8. The compilation pipeline — the standard order">
    <p p="47"><fact id="pipeline-lead" status="impl/done">The single ordering standard both executors follow (the "procedure of macro-substitution" the owner asked to pin down):</fact></p>
    <list ordered="true" p="48">
      <item><fact id="PIPE-PARSE" status="impl/done">**Parse.** Build the IR tree (§5) of every participating file; collect all directives with their positions.</fact></item>
      <item><fact id="PIPE-USE-GRAPH" status="impl/done">**Build the use-graph and topologically sort.** Nodes = document sections (or packages, at the coarser tier); edges = explicit `#use` declarations only — an `@spec` in-place use is the agent's read edge, never a compiler splice (§7.4 amendment 2026-08-24). Topological order = every dependency before its dependent. **Absorbed nodes (READ-ONCE over overlapping spans, 2026-08-24):** two closure nodes of one doc may nest (a whole-doc node beside a section inside it); a node whose text is wholly contained in a same-doc sibling's is absorbed — emitted once with its ancestor, never twice.</fact></item>
      <item><fact id="PIPE-SOURCE-MERGE" status="impl/done">**Source-merge.** For every `contract` section, resolve `#source` (§7.3) into its effective (merged) body. This runs **before** embed because an embed may target a merged contract section (§7.1).</fact></item>
      <item><fact id="PIPE-EMBED-EXPAND" status="impl/done">**Embed-expand.** Apply `#embed` (§7.1) as textual substitution, **top-down within a file**, in **topological order over the embed-graph across files** (a package is fully compiled — its source-merge and its own embeds done — before it is embedded), **recursively to a fixed point**, with cycle guards (§9).</fact></item>
      <item><fact id="PIPE-QUALIFY" status="spec/work">**Qualify (B-011, owner-approved 2026-08-04; per-node refinement — the B-006 rider, owner-approved 2026-08-04).** For the static build only: rewrite label definitions — heading `{#x}` and fact `##X`, one namespace (§7.3) — to the qualified form `&lt;origin-slug&gt;--&lt;original&gt;` (the slug is the lowercased `&lt;group&gt;/&lt;name&gt;` with dots and the joiner mapped to `-`/`--`; the original tail keeps its case), **per node, each node under its own authoring origin**: a compiled closure that splices cross-origin nodes qualifies every node under the origin that authored it, never the carrying entry's — provenance is never re-attributed by splicing. An intra-closure `(#x)` link rewrites to the qualified name of the **defining** node (so a cross-origin link stays resolvable under the two-scope lookup); a `simple` contribution is one node, where this reduces to B-011's original whole-contribution rewrite. Full `spec://` addresses, `@spec` uses, directive lines, and fenced content are never touched. The qualified name is a pure function of `(origin, original label)` — independent of splice order and composition, which is what makes late lane additions append-only. `@!X` rewrites to its full address here (§7.4). **Multi-doc rider (2026-08-24):** a closure node whose doc-path lies OUTSIDE the package's contract homes (`boot/`, `contract/`) qualifies with its doc in the slug — `&lt;origin-slug&gt;--&lt;doc-seg-doc-seg…&gt;--&lt;original&gt;`, a pure function of `(origin, doc, label)` — so two docs of one package cannot collide on the near-universal anchors (`root`, `summary`); contract-home nodes keep the plain origin slug, so every existing boot-snippet unit is byte-stable. **Definition positions (2026-08-24):** the qualify pass recognises every position the fact frontends do — the lead of a paragraph or list item, a table CELL opening (a table bar followed by the `@fact` sigil and `:ID …`, the K6.5 cell grain), and a blockquote lead (`&gt; ` followed by the `@fact` sigil and `:ID …`, the `&lt;quote&gt;` projection) — one namespace, all renamed.</fact></item>
      <item><fact id="PIPE-EMIT" status="impl/done">**Emit.** Concatenate in topological order with open/close markers (§11), prefixed by the resolution preamble and the tombstone table (§11). For the static build: `STATIC.md`. For structural: the loader consults the same order lazily.</fact></item>
    </list>
    <p p="49"><fact id="PIPE-DETERMINISM" status="impl/done">Determinism: independent nodes are tie-broken by a stable key (category → boot-snippet slot → fully-qualified name), as PROP-034 §2.3 already specifies for the emission layer.</fact></p>
  </section>
  <section id="cycles" title="9. Cycles and guards">
    <p p="50"><fact id="cycles-intuition" status="impl/done">The owner's C++ intuition made precise. In C++ two distinct mechanisms are at work: an `#include` cycle is broken by **include guards** (idempotent re-inclusion becomes a no-op), and mutual recursion of *types* is resolved by **forward declaration** — a *declaration* needs no *definition*. "Including only interfaces never deadlocks" precisely because declarations can close a cycle without bodies. Mapped onto us:</fact></p>
    <list ordered="false" p="51">
      <item><fact id="EMBED-CYCLE-ERROR" status="impl/done">**`#embed` cycle → hard error.** `#embed` is `#include` without a guard, so a cycle is an infinite substitution. We **forbid** it: a guard keyed on the `specpath` currently on the expansion stack detects it, aborts compilation, and emits **debug info naming the full cycle path** (`A → B → A`). (Owner-required: the guard's firing is reported, not silent.)</fact></item>
      <item><fact id="USE-CYCLE-ALLOWED" status="impl/done">**`#use` cycle between contracts → allowed** (the forward-declaration case). Because a contract is small and self-contained, static mode breaks the cycle by **emitting the contracts before any source bodies**. Structural mode is "read when needed", so a contract-level cycle simply resolves lazily.</fact></item>
      <item><fact id="USE-BODY-CYCLE-ERROR" status="impl/done">**`#use` cycle that needs a source body to compile itself → error** (the "incomplete type where a complete type is required" case).</fact></item>
    </list>
    <p p="52"><fact id="NO-DEADLOCK-INVARIANT" status="impl/done" action="continue" actionstage="doc" audience="author">**Invariant.** The **contract layer is where cycles are legal; the source layer is where topological order is mandatory.** This is the theoretical no-deadlock guarantee: as long as the contract hierarchy is acyclic-under-`#embed` and no source body participates in a `#use` cycle, the build always terminates.</fact></p>
  </section>
  <section id="link-tables" title="10. Link tables — the vtable analogue *(provisional)*">
    <p p="53"><fact id="LINK-TABLE-ANALOGY" status="spec/work">The owner's C++-virtual-dispatch analogy, held for the implementation task. Inline mode ≈ a non-virtual / devirtualized call (bound statically, no runtime indirection); structural mode ≈ a virtual call (late-bound at runtime); a **link table ≈ a vtable** — a table the compiler builds once so the runtime dispatches cheaply instead of searching.</fact></p>
    <p p="54"><fact id="link-tables-build-lead" status="spec/work">Concretely: at **install-time** (or a dedicated compile phase) build, by code, the graph edges the structural executor otherwise lacks —</fact></p>
    <list ordered="false" p="55">
      <item><fact id="TABLE-ANCHOR-INDEX" status="spec/work">an **anchor-index** per document (the IR tree, addressable),</fact></item>
      <item><fact id="TABLE-CONTRACT-SOURCE" status="spec/work">a **contract→source map** (the real edges behind every `#source`),</fact></item>
      <item><fact id="TABLE-USE-GRAPH" status="spec/work">the **use-graph**,</fact></item>
    </list>
    <p p="56"><fact id="link-tables-persist" status="spec/work">and persist them to a file table (a sibling/extension of `specmap.json`). The structural agent then **consults a cheap on-disk table instead of building the graph in context** — which directly answers the objection that the structural executor "lacks global knowledge because the project is too big for the agent's context": the edges are built by the compiler, not the agent. A bonus: hand-drawn `#source` edges become **verifiable** — the table knows the real edges and can flag divergence. This reuses the specmap infrastructure rather than adding a parallel one. Kept provisional and folded into the implementation task per the owner.</fact></p>
  </section>
  <section id="markers" title="11. Markers in compiled output">
    <list ordered="false" p="57">
      <item><fact id="OPEN-CLOSE-MARKERS" status="impl/done">When a file's text is placed into a static file (e.g. `STATIC.md`), a path comment is added **both before and after** it (today only *before* — the after-comment is the closing tag). Around a package body (which contains several files) the same: a package-open comment, then many file open/close comments inside, then a package-close comment.</fact></item>
      <item><fact id="STATIC-REVERSIBLE" status="impl/done">This makes `STATIC.md` **reversible** — a compiled artifact can be decomposed back to its constituent files and packages, giving the same bidirectional traceability specmap already provides for code.</fact></item>
      <item><fact id="COMPILED-LABELS-ARE-QUALIFIED" status="spec/work">**Compiled labels are origin-qualified (B-011).** A compiled block's heading anchors and fact ids carry the §8 qualify phase's `&lt;origin-slug&gt;--` prefix, so the compiled document's label namespace is collision-free by construction; reversibility survives because the block's own marker key names the origin, and stripping that block's prefix restores the source labels.</fact></item>
      <item><fact id="STATIC-HEADER-RESOLUTION-PREAMBLE" status="spec/work">**The header carries the resolution preamble, first (B-011, owner addition 2026-08-04).** The compiled lane opens with a short generated preamble — the qualified-label convention, the alias semantics, the two-scope lookup rule, «unresolved short name → the tombstone table below», and «full addresses resolve against package sources, never against this file» — placed as the first lines of the first file a session reads, because boot files are re-read every session and after compaction, which is what makes the rules un-forgettable.</fact></item>
      <item><fact id="STATIC-TOMBSTONE-TABLE" status="spec/work">**The tombstone table sits directly under the header.** Every short name the qualify phase renamed is listed with its qualified heirs and their origins — a retired name never vanishes silently (the addressable-specs tombstone law applied to renames). A resolver that misses a short splice anchor answers with these candidates, never with emptiness.</fact></item>
      <item><fact id="COMPILED-LANE-IS-NOT-A-CITATION-TARGET" status="spec/work">**The compiled lane is not a citation target (B-011, §6.1 layer 1 of the design).** A `spec://` address whose document path names a generated `STATIC.md` is an illegal target for authored text — the lane is a cache; source-of-truth is the package source. The directive compiler rejects such an address; the gate lints the tree for them.</fact></item>
    </list>
  </section>
  <section id="transitive-inline" title="12. Transitive static — folding in PROP-034">
    <list ordered="false" p="58">
      <item><fact id="STATIC-TRANSITIVE-FOLD" status="impl/done">`static-transitive` may be set at the top of a package hierarchy; then every element below it in the dependency graph is pulled `static`, **regardless of what it declared before**. Since the visibility layer landed (2026-08-23, PROP-050 §3), «below it» means *below it within the effective set E(R)*: the fold walks visible edges only and never widens visibility (PROP-050 ##FORCING-NEVER-WIDENS).</fact></item>
      <item><fact id="transitive-safety" status="impl/done">This is safe precisely because the static build is algorithmic, not LLM-driven, and loses nothing. It is the path to large highly-optimized builds.</fact></item>
    </list>
    <list ordered="false" p="59">
      <item><fact id="EMISSION-LAYER" status="impl/done">This is PROP-034 §2.1/§2.3 (transitive links + dedup + topological order + cycle rejection), which becomes the **emission layer** of this compiler: after §8's pipeline resolves directives, PROP-034's linker deduplicates and dependency-orders the node list into `STATIC.md` / `INDEX.md`.</fact></item>
      <item><fact id="transitive-variants-reserved" status="spec/done">`transitive-static` / `transitive-dynamic` remain reserved (no use case yet), but the graph analyzer is built to operate at that level.</fact></item>
    </list>
  </section>
  <section id="loader-prompt" title="13. The structural loader — the &quot;first instructions&quot;">
    <list ordered="false" p="60">
      <item><fact id="LOADER-LLM-EXECUTED" status="spec/done">Until hard algorithmic agents exist (§14), structural mode is executed by an LLM following instructions.</fact></item>
      <item><fact id="LOADER-FIRST-EVERYWHERE" status="spec/done">Those instructions — how to honour `#use`, `#embed`, `#source`, `@spec`, and the read-set — MUST load **first, everywhere**: in every project, package, and library vibevm manages.</fact></item>
      <item><fact id="LOADER-BROKEN-WITHOUT" status="spec/done">A project or package **without** them is considered **broken**; the project- and package-creation tools MUST check for and inject them. This is one of the most critical loading mechanisms — nothing works without it.</fact></item>
      <item><fact id="LOADER-RESOLUTION-RULES" status="spec/work">**The resolution rules are part of the first instructions (B-011, owner addition 2026-08-04).** The first-loaded text includes the B-011 resolution rules: qualified-label convention and short↔qualified derivation, alias (`as` / `@!`) semantics, the two-scope lookup with fail-with-candidates, the tombstone table's role, and «full addresses resolve against package sources under `vibedeps/`, never against a compiled lane». B-011 wires this contract into a live boot for the first time — until it lands, the loader instructions remain the `structural-loader.xml` hold.</fact></item>
      <item><fact id="inline-tooling-note" status="spec/done">Inline compilation, by contrast, needs no LLM and can build the whole thing algorithmically today; its tooling is what remains to be built (the current `STATIC.md` machinery is naive by comparison).</fact></item>
    </list>
  </section>
  <section id="future-agents" title="14. Future algorithmic agents">
    <list ordered="false" p="61">
      <item><fact id="FUTURE-ALGORITHMIC-AGENTS" status="spec/done">We are preparing for purpose-built algorithmic agents that run alongside Claude Code (and in specific cases instead of it) and honour every directive (`#use`, `#embed`, `#source`) rigidly and unconditionally.</fact></item>
      <item><fact id="DESIGN-FOR-DETERMINISTIC" status="spec/done">The design must not assume only an LLM executor: the directive semantics (§7), the pipeline (§8), and the link tables (§10) are all specified so a deterministic agent can execute them. Remember this executor is coming.</fact></item>
    </list>
  </section>
  <section id="migration" title="15. Migration">
    <p p="62"><fact id="migration-lead" status="impl/done">Incremental, safety-first (owner-set):</fact></p>
    <list ordered="false" p="63">
      <item><fact id="MIG-DEMO-FIRST" status="impl/done">**Build and test on a demo fixture corpus first** — throwaway packages exercising `simple`/`normal`, `contract`/`source`, `#embed`/`#use`/`#source`, cycles, and `@spec`. These are **not** real packages, and experimenting on them must never break vibevm itself.</fact></item>
      <item><fact id="MIG-GRADUAL" status="spec/done">**Migrate real packages gradually**, improving them onto the new format one at a time.</fact></item>
      <item><fact id="MIG-VIBEVM-LAST" status="spec/done">**Convert vibevm itself last:** first the whole of `org.vibevm.world`, and only then (if at all) the core feature specs. With `simple` as the default (§3) there is **no blast radius** — an un-migrated package keeps loading as `simple` (whole), so conversion to `normal` is per-package and opt-in, never a flag-day.</fact></item>
    </list>
  </section>
  <section id="open" title="16. Open questions">
    <list ordered="true" p="64">
      <item><fact id="OPEN-EQUIVALENCE" status="spec/work">**Equivalence testing (§2).** Differential testing of the static vs structural executors — real, empirical, experiment-heavy; **planned separately**, meaningless before a working base exists. The static compiler is the reference semantics in the meantime.</fact></item>
      <item><fact id="OPEN-READ-SET-COMPACTION" status="spec/work">**`@spec` read-set across compaction (§7.4).** No clean solution without a harness compaction signal; the file-based read-set + boot instruction is the floor. Revisit if the harness exposes a compaction event.</fact></item>
      <item><fact id="OPEN-XML-FRONTEND" status="spec/work">**XML frontend (§5).** Timing and the exact IR mapping; the data structures are designed for it now, the frontend is built later.</fact></item>
      <item><fact id="OPEN-CLOSURE-EXPLOSION" status="impl/done">**Implicit-reference closure explosion (§7.4) — REALISED AND RESOLVED (2026-08-24).** The first normal-format host build spliced every `@spec` target and grew the lane tenfold (250 KB → 2.5 MB). Resolution: `@spec` is the agent's read edge, never a compiler splice (the §7.4 amendment); only explicit `#use` splices. The compiled lane returned to snippet size (+3% for the cell-fact tombstones).</fact></item>
      <item><fact id="OPEN-LINK-TABLES" status="spec/work">**Link tables (§10).** Whether they land at install-time, static-compile-time, or a separate phase — folded into the implementation task.</fact></item>
      <item><fact id="LINK-TABLES-ARE-DEFERRED-WITH-A-NAMED-TRIGGER" status="spec/done">**Deferred deliberately, by owner ruling 2026-07-29, and this records the reason so nobody re-derives it.** Built today: the graph and a deterministic dump (`crates/vibe-spec/src/link_table.rs`). Not built: the persisted on-disk format and the structural consumer. The tables are **the vtable of the §13 structural executor** — a prebuilt index so a late-bound reader dispatches instead of searching — and this project does not run that mode, so they are an optimisation of navigation cost, never a precondition of correctness. Meanwhile `#embed spec://…` resolves and splices at compile time (`render_static` → `expand_embeds`), and an `@spec://` pointer that costs a lookup is strictly better than the confidently wrong relative path it replaced. Building the layer mid-refactor would create code the refactor then has to refactor.</fact></item>
      <item><fact id="LINK-TABLES-PROMOTION-TRIGGER" status="spec/done">**What promotes it, so the deferral cannot quietly become permanent:** either `@spec://` pointers in the boot lane are MEASURED to cost a reader more than the lane saves, or the §13 structural loader is opened — whichever comes first. Either makes the searching real rather than hypothetical; until one fires, the cost being optimised away is a cost nobody has paid.</fact></item>
      <item><fact id="OPEN-NO-ACCESS-CONTROL" status="spec/work">**No access control (§7.3).** We deliberately omit `private`/`public`. Confirm this holds once real packages exercise cross-contract calls.</fact></item>
      <item><fact id="OPEN-DYNAMIC-TRANSITIVE" status="spec/work">**`dynamic-transitive` (§12).** Inherited from PROP-034 §5; still reserved.</fact></item>
    </list>
  </section>
  <section id="history" title="17. Version history">
    <list ordered="false" p="65">
      <item><fact id="HISTORY-DRAFTED" status="spec/done">**2026-07-14 — drafted (owner-requested), provisional.** Captures the "static-compiler vision" design dialogue: two build modes as AOT/JIT with the equivalence invariant (§2); `simple`/`normal` package formats (§3); the `contract`/`source` split (§4); the hierarchical document IR with MD and future-XML frontends (§5); the unified `spec://` grammar and the deterministic router (§6); the three directives `#embed` / `#use` / `#source` plus the `@spec` in-place-use sigil and the read-set (§7); the five-phase compilation pipeline and the embed-ordering standard (§8); the C++-derived cycle rules and the contract-layer no-deadlock invariant (§9); link tables as the vtable analogue (§10, provisional); reversible open/close markers (§11); `transitive-inline` folding in PROP-034 as the emission layer (§12); the first-loaded structural loader (§13); the future algorithmic executor (§14); and the demo-corpus-first, vibevm-last migration (§15). Implementation begins with the router (§6) under this contract.</fact></item>
      <item><fact id="HISTORY-IMPLEMENTED" status="spec/done">**2026-07-15 — implemented, and the default flipped to `simple`.** §5–§13 shipped as the `vibe-spec` crate and wired into `bootgen` (the payoff: `render_inline` runs `expand_embeds`, guarded); `transitive-inline` (§12) landed on `LinkType`. **§3's default changed from `normal` to `simple`** (owner decision): a forgotten `format` must fail *safe* (over-load, visibly working) rather than *silent* (a `normal` no-op), which also removes the §15 migration blast radius. Still open and under review: the `link` × `format` interaction (does a `normal` + `static` edge read eagerly or lazily?).</fact></item>
      <item><fact id="HISTORY-RENAME" status="spec/done">**2026-07-16 — link-type rename (owner decision), the `link` set shrinks to two.** `LinkType::Inline → Static` (the verbatim `STATIC.md` lane — "the static compiler"), `Static → Dynamic` (the default, a by-reference `INDEX.md` read with an optional `when`), and the old `Dynamic` removed — a conditional load is now just a `dynamic` entry carrying a `when`. `inline-transitive → static-transitive`; `INLINE.md → STATIC.md`; `render_inline → render_static`; `compile_inline → compile_static`. Pure terminology, aligning vibevm with the CS static/dynamic-linking standard so "the static compiler" reads naturally; shipped across `vibe-core`, `vibe-workspace`, `vibe-spec`, the package manifests, and these specs.</fact></item>
      <item><fact id="HISTORY-B011-ALIASING" status="spec/work">**2026-08-04 — deterministic loading: qualified splice, aliases, the lookup rule (B-011, owner-approved).** The owner's highest-priority build lands its contract: the §8 pipeline gains the **qualify** phase (labels become `&lt;origin-slug&gt;--&lt;original&gt;`, a pure function of origin — splice-order-independent, append-only under late dynamic lane additions); §7.2 gains the `as &lt;Alias&gt;` clause and §7.4 the `@!Alias` mandatory in-place use plus the two-scope short-reference lookup (fail with candidates, never a silent pick); §11 gains the qualified-label, resolution-preamble, tombstone-table, and lane-is-not-a-citation-target facts; §13's first instructions gain the resolution rules as named content (the owner's priority-placement addition). Design rationale and the fork record: `vibevm/vibespecs/design/deterministic-loading-aliasing.xml`; the commissioning entry: `BACKLOG.md` B-011. PROP-009 §2.3's «verbatim concatenation» becomes «anchor-qualified concatenation» in the same landing.</fact></item>
      <item><fact id="HISTORY-NORMAL-STATIC" status="spec/done">**2026-07-20 — `normal + static` compiled end to end; the `link × format` question resolved.** The `[package].format` field now **parses** (`PackageFormat` in `vibe-core`, default `simple`, `deny_unknown_fields`-clean), **threads** through the boot model (`DependencyBoot` / `UnitInput` → `BootEntry`, both emission paths), and **drives** the static renderer: a `normal`-format contribution pulled `static` is **compiled** to its `#use` / `#source`-resolved, tree-shaken, dependency-ordered closure (`vibe-workspace::boot_artifacts::normal::compile_normal_entry`, seeded at the contract's whole-document address and delegating to the shipped `vibe_spec::compile_static`), where a `simple` one stays a verbatim concatenation. This **resolves the open `link × format` question** raised in the 2026-07-15 entry ("does a `normal + static` edge read eagerly or lazily?"): it is **eager** — the tree-shaken, `#source`-merged closure is AOT-compiled into `STATIC.md`, which is the equivalence-invariant reading (§2), never the whole file. The default stays `simple`, so an un-migrated tree's static lane is byte-identical (§3/§15). `normal + dynamic` — the structural / JIT loader (§13) — is still pending; only the static (AOT) executor honours the format so far.</fact></item>
    </list>
  </section>
</spec>
