VibeVM
Contents
On this page
en
Publisher
org.vibevm.core
Version
1.0.0latest
Audiences
author
Reading time
3 min
Rendered
Read aloud
never

Facts and their status markers

01A spec is a list of promises, and each promise has a state: proposed, being built, done, abandoned. vibe reads that state from a small marker written next to the promise, in Markdown or in the XML form, and one command tells you when a marker is malformed or in the wrong place. This page is the grammar of those markers.

02
vibe facts check
progress check: clean (2 files, 0 warning(s))

The marker

03A marker is one XML-shaped element, <status stage="…" state="…"/>, embedded in Markdown or native in the dialect. A point marker is self-closing; an unclosed one is not well-formed and is an error. The shorthand @status:spec/done means the same as the element, and @status:impl alone means impl/work, with one exception: @status:unknown means unknown/hold. The older spellings without status: are still read. Every vocabulary is closed: a value outside the tables is an error, with the nearest legal value as a hint.

04 One XML-shaped element, embedded in Markdown (and, later, native in XML documents — the frontend duality of PROP-035 §5):
05 A point marker MUST be self-closing (/>). An unclosed <status …> point form is not well-formed XML and is a check error.
06 @status:<stage>/<state> and @status:<stage> are macro-equivalents of a point marker. The legacy spellings @<stage>/<state> and @<stage> mean exactly the same and are still read, so a document written before the qualified form keeps parsing.
07 @status:impl<status stage="impl" state="work"/> — bare shorthand defaults to state="work", with exactly one exception: @status:unknownstate="hold". (@status:freezefreeze/work: "freezing now".)
08 Vocabularies are closed. Any value outside the tables is a check error with a nearest-legal-value hint (typos like rewrok die in CI, not in review).

Anchors

09A marked unit must have an address. In Markdown the anchor is @fact:ID as the first token of a paragraph or a list item. The id starts with a letter and continues with letters, digits, underscore and hyphen, and it shares one address space with the heading anchors, so a duplicate across the two forms is an error. A marker on a unit without an anchor is an error. The scanner ignores fenced code, inline code and addresses, so a marker quoted inside them is text, not a marker.

10 Fact anchors — the anchored-when-marked law (owner, 2026-07-24; spelling amended 2026-08-06). A stable fact address is written @fact:<ID> as the first token of a paragraph or list item. The legacy spelling ##<ID> means the same and is still read.
11 <ID> is [A-Za-z][A-Za-z0-9_-]*; the unit is then addressable as spec://…/<doc>#<ID>, sharing one address space with the heading {#anchor}s — a duplicate across both forms is a check error. The address is unchanged by the spelling: it names the id, never the opener.
12 Every unit that carries a status marker — paragraph or list item — MUST also carry a @fact:<ID> anchor; a marked, anchor-less unit is a check error.
13 Inside fenced code blocks, inline code spans, and URLs the element and the shorthand (§3.7) are not recognized — the scanner is fence-aware.

Where a marker goes

14There are four places. A document marker stands in the preamble, or right after the first heading when the document opens with one. A section marker stands alone on the line after its heading; that is the only legal standalone position in a body. A paragraph marker sits inside the paragraph's own text, as its first or its last token. Every list item is a unit of its own, at every nesting level, and its marker sits inside the item's text. A marker standing alone between two paragraphs is an error; there is no nearest-paragraph guess. A unit carries at most one status marker and any number of action markers.

15 Document — marker in the preamble, before the first heading. Pilot amendment (2026-07-24): a document that opens with its heading (the standard shape of this repo's specs) has no preamble; there, the standalone marker immediately after that first heading is the document marker, not a section marker.
16 Section — marker on its own line immediately after the heading line (for any heading other than a preamble-less file's first one, per the amendment above). This is the only legal standalone position inside a body.
17 Paragraph — marker inside the paragraph's own text: the first token (right after the newlines, or right after the paragraph's @fact:<ID> anchor) or the last token (right before them).
18 List item (fact amendment, 2026-07-24 — owner-directed) — every item of a bulleted or numbered list is a unit of its own, at every nesting level. Its marker — shorthand or XML form alike — sits inside the item's own text: the first or last token of the item (before any nested sub-items, which carry their own markers).
19 A standalone marker between two paragraphs is a check error — there is no "nearest paragraph" heuristic.
20 Multiple markers on one node: at most one status marker (stage/state), any number of action markers — a unit may legitimately need remove+actionstage="doc" and continue+actionstage="test" at once.

How a status rolls up and down

21A node's marker covers the descendants that carry none. An unmarked node's computed status is the worst of its children, and unknown wins the bottom.

22 Downward (defaulting): a node's marker covers unmarked descendants.
23 Upward (aggregation): an unmarked node's computed status is the worst-of its children per the §3.3 order (unknown wins the bottom).

Actions, stages and audiences

24Beside the status a marker may carry an action, what should happen next, and actionstage narrows it: action="remove" actionstage="doc" means the documentation of this is to be removed while stage still describes the unit itself. A doc action with an audience is an obligation of the documentation: a page written for that audience must cite the fact, and vibe doc check --coverage checks that one does.

25 actionstage narrows the target: action="remove" actionstage="doc" = "the documentation of this is to be removed", while stage keeps describing the unit itself.
26 Primary use: actionstage="doc" markers with an audience are the obligations of the documentation — the promises a page for that audience must cite. vibe progress report --view doc --audience user|author|dev|agent lists them; it is the source of the coverage gate vibe doc check --coverage (PROP-057 §14, the ratchet PROP-047 ##DOC-COVERAGE-RATCHET names), never a table of contents — navigation is derived from the page manifest (amended 2026-09-11; the earlier wording fed the two guides' tables of contents).

What closes a fact

27A fact may say what closes it: @requires:implementation,verification right before its final status in Markdown, or a requires attribute in the XML form. The kinds are a closed list, specification, implementation, verification, documentation, decision, research, plan, disposition and external. They name closure artifacts, not genres: a research note may require an implementation.

28 The Markdown form is exactly one qualified trailing annotation @requires:<kind>[,<kind>…], immediately before the fact's final status shorthand admitted by §3.7 (qualified full/bare or legacy full/bare), or final <status …/> point marker. @requires itself has no legacy bare spelling. The XML-dialect equivalent is a requires="<kind>[,<kind>…]" attribute on the named or generic fact element, beside status; it is never an attribute of the standalone document/section <status> element. Both forms lower to one fact-owned semantic set.
29 The closed vocabulary, in canonical order, is specification, implementation, verification, documentation, decision, research, plan, disposition, external. A new kind requires an amendment here before parser, IR or wire support. These are closure artifacts, not document genres: a research document may require an implementation, and a contract fact may itself be a decision artifact.

The tool

30vibe facts check is the lint, and --exhaustive demands a marker on every paragraph; vibe progress check is a transitional alias that prints the new spelling. The observed files are named by include globs in facts.toml at the package root: globs that say what is observed, never a list of exclusions.

31 The CLI follows the boundary. The markup lint is a facts operation: vibe facts check [--exhaustive] becomes its durable home, with vibe progress check kept as a transitional alias (printing the new spelling); the gate panel switches to the facts spelling. Campaign verbs (scan/mirror/seal/gate/baseline/rescan/resume/weave/report) stay under vibe progress. The same wave repairs B-100: a bare --campaign <id> resolves against campaigns/<id> instead of silently minting a cwd-relative state zone. Landed: vibe facts check carries the lint byte-identically (one implementation, two entries), the alias prints its stderr note (suppressed under --json), the shared campaign resolver fails loud on an unknown bare id with the existing zones listed and writes nothing, and the gate panel's markup line runs the facts spelling — proven live on the original B-100 scenario.
32 Optional dev-mode mechanics, configured by a facts.toml at the package root (the clippy.toml pattern — tool config, not manifest pollution); progress.toml is read as a silent legacy fallback for the transition (owner correction 2026-08-22: the observed tree is a facts-layer concern).
33 Include-style globs name what is observed (not gitignore-style excludes):

Edge cases and rules

34A document written before the qualified spelling keeps parsing: the legacy @spec/done and ##ID forms mean what the new ones mean. Converting a file between Markdown and XML keeps every marker, because the marker is part of the model, not of the syntax.

For an agent

This page has a machine mirror. The citation carries the version rather than latest, so what an agent quotes does not move under it.

spec://org.vibevm.core/vibevm-docs@1.0.0/authoring/facts-and-status-markers

.md.xmlllms.txt