<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title id="root">Write specs an agent can cite</title>
  <status stage="doc" state="work" audience="author,agent"/>
  <p p="1">The text in a package is only useful to an agent if every rule in it has an address. This page shows the shape of such text: named sections, one idea per unit, a status on each, and an address that never changes once published.</p>
  <section id="two-processes" title="Why an address">
    <p p="2">A person and an agent share one repository and nothing else: no hallway, no shared memory, no tone of voice. The [specification](../glossary/index.xml#specification) tree is the only channel between them, and a channel works when a message can be pointed at. «Fix the retry count» sends the agent guessing; «fix `spec://org.acme/notes-flow/flows/notes/PROTOCOL#RETRY-COUNT`» sends it to one line. The second costs about twenty tokens; the first costs hundreds and may land on the wrong rule.</p>
    <rule ref="spec://org.vibevm.world/addressable-specs/flows/addressable-specs/ADDRESSABLE-SPECS-PROTOCOL#THE-SPEC-TREE-IS-THE-ONLY-CHANNEL" p="3"/>
    <rule ref="spec://org.vibevm.world/addressable-specs/flows/addressable-specs/ADDRESSABLE-SPECS-PROTOCOL#FOR-POINT-CORRECTIONS-THE-URI-WINS" p="4"/>
  </section>
  <section id="the-address" title="The address">
    <p p="5">`spec://&lt;group&gt;/&lt;name&gt;[@&lt;version&gt;]/&lt;path&gt;/&lt;document&gt;#&lt;anchor&gt;`: the package [coordinate](../glossary/index.xml#coordinate), an optional version, the document's path inside `vibevm/vibespecs/` without its extension, and an [anchor](../glossary/index.xml#anchor). The version is a feature, never an obligation: absent, the address resolves against the freshest installed version. Anchors are section ids and [fact](../glossary/index.xml#fact) ids in one address space, so a rule is cited the same way whether it is a section or one sentence.</p>
    <rule ref="spec://org.vibevm.world/addressable-specs/flows/addressable-specs/ADDRESSABLE-SPECS-PROTOCOL#URI-SCHEME-IS-THE-FULL-GRAMMAR" p="6"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#URI-VERSION-OPTIONAL" p="7"/>
    <example id="explain" fixture="host" p="8">
      <run>vibe explain "spec://org.vibevm.core/vibevm/common/PROP-000#KIND-SET"</run>
      <expect>spec unit spec://org.vibevm.core/vibevm/common/PROP-000#KIND-SET
  unmarked — `kind ∈ {flow, feat, stack, tool, mcp, lang, doc, app}` — eight kinds; `mcp` shipped with [PROP-027](../modules/vibe-mcp/PROP-027-mcp-packages.xml); `doc` and `app` admitted by [PROP-057](PROP-057-documentation-packages-and-site.xml) through the `VIBEVM-SPEC.md` §4.1 amendment of 2026-09-12 (pending the owner's ratification at the merge of the docs-2026-09 branch; the code learns the two kinds in that campaign's phase 2). (§Invariants `INV-VOCABULARY` in this file carries the same list.) &lt;status stage="spec" state="done" action="continue" actionstage="impl"/&gt; (vibevm/vibespecs/common/PROP-000.xml:75)
  hash sha256:1effee7da317e236ec9b0745d0e02f922cd93134fd731a758428dce62db2a81f
  edges in:
    documents ← `authoring::write-a-lang-package` (vibevm/vibepacks/org.vibevm.core/vibevm-docs/v1.0.0/vibevm/vibespecs/authoring/write-a-lang-package.xml:14)
    documents ← `glossary::index` (vibevm/vibepacks/org.vibevm.core/vibevm-docs/v1.0.0/vibevm/vibespecs/glossary/index.xml:107)
    documents ← `model::packages-and-kinds` (vibevm/vibepacks/org.vibevm.core/vibevm-docs/v1.0.0/vibevm/vibespecs/model/packages-and-kinds.xml:45)</expect>
    </example>
  </section>
  <section id="the-unit" title="The unit">
    <p p="9">A unit is one anchored heading and the text under it, up to the next heading; it carries one decision or one rule, makes sense on its own, and fits on a page. If a unit needs «and also», it is two units. Contract statements use MUST, SHOULD and MAY; a reader must never guess whether a sentence binds. Checkable claims stand outside code fences, because a fence carries no anchor and an instruction inside one is unverified by construction.</p>
    <rule ref="spec://org.vibevm.world/addressable-specs/flows/addressable-specs/authoring-rules#ONE-UNIT-CARRIES-ONE-DECISION" p="10"/>
    <rule ref="spec://org.vibevm.world/addressable-specs/flows/addressable-specs/authoring-rules#CONTRACT-STATEMENTS-USE-RFC-2119-VERBS" p="11"/>
    <rule ref="spec://org.vibevm.world/addressable-specs/flows/addressable-specs/authoring-rules#A-CHECKABLE-CLAIM-BELONGS-OUTSIDE-THE-FENCE" p="12"/>
  </section>
  <section id="the-dialect" title="Two serialisations, one model">
    <p p="13">A specification is written in Markdown or in the project's XML dialect, and both parse into one document model. In XML a section is an element named after its anchor, `&lt;retry-policy title="3. Retries"&gt;`. A rule is an element named after its id, with the attribute `fact="true"` and a status. In Markdown the same rule is a paragraph opening with `@fact:RETRY-COUNT` and closing with `@status:spec/done`. A tool that knows nothing of your vocabulary still finds every rule by one attribute test, and a converter turns one form into the other, reporting anything a round trip would not preserve.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-045#NAMED-FACT-ELEMENTS" p="14"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-045#XML-DIALECT-IS-THE-MD-SUBSET" p="15"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-045#NAMED-SECTION-ELEMENTS" p="16"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-045#FACTS-GROUP-ELEMENT" p="17"/>
    <p p="18">The status on each unit says where it stands: `spec/done` for a settled rule, `impl/done` once code implements it, `spec/work` for a draft. Two id registers carry the signal at no cost: an upper-case id marks a rule with binding weight, a lower-case one a lead-in or a note.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-facts/PROP-043#DECISION-TWO-REGISTERS" p="19"/>
    <example id="convert" fixture="package-spec" p="20">
      <run>vibe refactor convert-source --from md --to xml --dry-run vibevm/vibespecs</run>
      <expect>dry-run ir-stable-loss vibevm/vibespecs/NOTES-FLOW.md
--- source
+++ reverse-projection
@@ -3,2 +3,3 @@
 @fact:ONE-NOTE One note per review. @status:spec/done

+

dry-run ir-stable-loss vibevm/vibespecs/boot/10-tool-review-notes.md
--- source
+++ reverse-projection
@@ -1,6 +1,5 @@
-&lt;!-- vibe:static org.org.acme/review-notes — boot snippet --&gt;
-
 # review-notes

 A `tool` package.

+

summary converted=0 already=0 lossy-confirmed=0 refused=0 skipped-generated=0 skipped-foreign=0 skipped-harness=0 dry-run=2</expect>
    </example>
    <p p="21">`vibe refactor convert-source --to xml` or `--to markdown` converts files or whole folders, skipping the dependency tree and generated files. It writes the sibling form and deletes the original in one act, so the tree never holds both forms of one document. Before writing, it converts the result back and compares: a byte-identical round trip converts silently, and a loss of comments or layout is refused with a per-file description unless you confirm, or pass `--force`. A change of meaning is always refused, because that is a defect of the converter, not of your file. `--dry-run` reports every file and writes nothing.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-051#CONVERT-SOURCE-SURFACE" p="22"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-051#ONE-DOCUMENT-ONE-FORM-ON-CONVERT" p="23"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-051#HONESTY-BY-REVERSE" p="24"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-051#FORCE-AND-PROMPT" p="25"/>
  </section>
  <section id="directives" title="Directives: use, embed and read">
    <p p="26">A spec may pull another by address. `#use spec://…` pulls the whole top-level section that contains the addressed node, and not its siblings; `#embed` splices exactly the addressed node, no more. The default merge is `:add`, so interface text need not be repeated to appear in the result. Every file a directive names must be declared in the package's [manifest](../glossary/index.xml#manifest). Cycles are legal in the contract layer and forbidden among source bodies, which is what guarantees that a build always ends.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#USE-ANCESTOR-RULE" p="27"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#EMBED-EXACT-RULE" p="28"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#MERGE-DEFAULT-ADD" p="29"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#DIRECTIVE-MANIFEST-AGREE" p="30"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#NO-DEADLOCK-INVARIANT" p="31"/>
    <p p="32">In prose an agent reads, `@spec://…` with the at-sign is mandatory: the agent reads it in place, once, on first encounter, and the compiler never splices it. A bare `spec://…` is at the agent's discretion.</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#AT-SPEC-MANDATORY" p="33"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#READ-ONCE" p="34"/>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-035#BARE-SPEC-DISCRETIONARY" p="35"/>
  </section>
  <section id="immutable" title="An address never moves">
    <p p="36">Once published, an anchor is immutable. Renaming a section or a rule leaves a tombstone at the old anchor pointing at the new one, so a citation written last year still lands. Moving files does not change addresses either: the address is logical, the path is physics.</p>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-052#ADDRESSES-SURVIVE-THE-MOVE" p="37"/>
    <rule ref="spec://org.vibevm.core/vibevm/common/PROP-057#INV-ANCHORS-IMMUTABLE" p="38"/>
  </section>
  <section id="edge-cases" title="Edge cases and rules">
    <p p="39">A generated file is never a citation target: cite the source document, not the compiled [boot lane](../glossary/index.xml#boot-lane).</p>
    <rule ref="spec://org.vibevm.core/vibevm/modules/vibe-workspace/PROP-009#COMPILED-LANE-IS-NOT-A-CITATION-TARGET" p="40"/>
    <p p="41">`vibe facts check` validates the markup of a package's specifications; `vibe check` validates the package as a whole; both run before publishing.</p>
    <p p="42">Code may cite specifications too, with an attribute on the item that implements a rule, and a map then answers which code implements which rule in both directions; the architecture pages of this manual explain that map.</p>
  </section>
</spec>
