Documentation governance
This page defines how Vox documentation is organized and how to keep it from drifting.
This page is the policy. The mechanism — sources, site build, generated pages, and which gate catches which drift at which stage — is How Vox documentation works.
Authority map
Section titled “Authority map”| Surface | Primary audience | Owns | Must not become |
|---|---|---|---|
README.md | evaluators, first-time visitors | short front door, quick start, tone, links into the book | a second FAQ or architecture dump |
docs-astro | site visitors | Starlight site entry + local preview (pnpm dev under docs-astro/) | a contributor policy page |
docs/src/explanation/faq.md | readers and evaluators | common product and architecture questions | a troubleshooting runbook |
docs/src/how-to/troubleshooting-faq.md | operators and contributors | operational fixes and environment troubleshooting | the main public FAQ |
AGENTS.md | contributors and agents | required cross-tool contributor policy, secret-management entry point, short architecture pointers | the general table of contents for the whole repo or a tool-specific troubleshooting log |
docs/src/reference/ | readers and contributors | lookup material, contracts mirrored in prose, stable operational references | speculative planning or marketing copy |
docs/src/architecture/ | contributors | current architecture, authority maps, research, and roadmaps | quick-start or beginner onboarding |
docs/src/contributors/ | contributors | contributor hub, documentation governance, contributor-facing process guidance | public product marketing |
docs/agents/ | contributors and automation | inventories, governance, machine-oriented support docs | duplicated public documentation |
docs/agents/*.json | contributors and automation | machine-readable IDE feature matrix, doc inventory, script registry | must not become hand-edited prose |
contracts/ | code and CI | machine-readable specs and schemas | long-form human explanation |
Taxonomy
Section titled “Taxonomy”Folder placement communicates ownership. Frontmatter communicates how a page should appear in the book.
Category vocabulary
Section titled “Category vocabulary”Use one of these category values in frontmatter:
category | Meaning |
|---|---|
Getting Started | first-stop pages and front-door onboarding |
Tutorials | guided learning |
How-To Guides | goal-oriented instructions |
Concepts | conceptual understanding |
Library | general (non-Vox) curated knowledge pages under docs/src/library/, indexed by the KB |
Language Reference | stable lookup information |
API Reference — Crates | per-crate API surface |
Examples | worked examples |
Architecture Decisions (ADRs) | architecture decisions |
Architecture SSOTs | current architecture, authority maps (research and roadmap pages appear under Internals — see below) |
CI & Quality | CI and quality-specific references |
Contributors | contributor-facing governance and process docs |
Operations | runbooks and operational catalogs |
archive | tombstoned pages (excluded from the sidebar) |
These display labels are the enforced vocabulary — VALID_CATEGORIES in
crates/vox-doc-pipeline/src/pipeline/lint.rs matches them exactly, with no
alias normalisation. They must stay in sync with the sections array in
contracts/documentation/docs-sidebar-section-order.v1.json.
Status vocabulary
Section titled “Status vocabulary”Use status when the distinction matters to readers:
status | Use for |
|---|---|
approved | accepted ADR or policy text that is normative but not yet reflected everywhere in code/docs |
current | documented behavior or process the repo actively relies on |
experimental | implemented but intentionally unstable or gated |
legacy | still present but not the preferred path |
research | investigation, findings, or synthesis not equivalent to shipped behavior |
roadmap | future-facing implementation plans |
deprecated | retained only for migration or compatibility notice |
Do not use status to make aspirational pages sound shipped.
Internals section
Section titled “Internals section”Pages with status: research or status: roadmap are grouped under a collapsed Internals sidebar section, shown last, instead of under their category. They render a status banner and a noindex robots tag, and they are omitted from the sitemap and from every published llms.txt variant. They stay searchable in the on-site search, labelled as Internals. Pages with status: deprecated or status: legacy keep their category but also get a banner and noindex.
The single source for this rule is docs-astro/src/utils/page-status.mjs; the sidebar, route metadata, sitemap filter and llms exclusion all read it. No category or frontmatter rewrite is needed — set status honestly and the page lands in the right place.
Frontmatter starter template
Section titled “Frontmatter starter template”Use this template for new pages so docs lint passes on first run:
---title: "Page title"description: "One specific sentence about what this page covers."category: "Architecture SSOTs"status: "current"topic: "doc-governance" # prefLabel from contracts/documentation/kb-taxonomy.v1.yamldomain: "documentation" # prefLabel from the same fileauthorship: "human" # human | llm-assisted | llm-generated (+ authorship_model for LLM)training_eligible: true# capabilities: [cli.secrets] # optional: capability ids this page explains---
# Page title
<!-- kb:summary -->40 to 120 words that say what the page is for and what it decides.<!-- /kb:summary -->New pages must also carry the KB facets and summary block shown above; see KB facets (taxonomy contract).
Note on temporal metadata: The “Last updated” date is the committer date of the newest commit touching the page’s source file, computed at build time by docs-astro/src/utils/git-dates.mjs. Commits listed in the repo-root .git-blame-ignore-revs, chore(ssot): auto-regenerate commits, formatting commits (style: and chore: fmt-style subjects) and bulk commits touching more than 100 files are skipped, and renames are followed. Frontmatter last_updated is ignored; do not add it. To keep a future mechanical sweep from resetting dates, add its commit SHA to .git-blame-ignore-revs.
Code Anchors & Freshness Governance
Section titled “Code Anchors & Freshness Governance”To support deterministic drift detection without LLM dependencies (DRIFT-02, DRIFT-03), authored frontmatter optionally accepts:
owner: owning team or contributor (e.g.team-infra)review_cadence: review period (e.g."90d","180d")code_anchors: list of code paths or symbol spans the document relies on (e.g.crates/vox-cli/src/main.rs,crates/vox-compiler/src/parser/mod.rs#Parser).
Forbidden Keys in Authored Frontmatter:
last_updated: derived automatically from Git history. Hand-authoring is a hard lint error (hand-authored-last-updated).last_verified/last_verified_commit: managed exclusively by the Freshness Ledger (contracts/reports/docs-freshness/ledger.v1.json). Hand-authoring is a hard lint error (hand-authored-last-verified).
Capability claims
Section titled “Capability claims”A page may declare which capabilities it explains with an optional capabilities: [<capability id>, …] frontmatter key (flow or block list). Ids come from contracts/capabilities/capability-index.v1.json, for example cli.secrets.get, mcp.vox_check, surface.mesh or crate.vox-secrets.
vox ci capability-indexvalidates every claimed id, so an unknown id failsvox ci ssot-driftwith the page path and the id.- A claim adds the page as a doc link on each claimed capability (after its page-level default), and gives the page its own
doc.<path>row. Pages that claim nothing get no row. - The doc lint is a line scanner: it does not parse YAML and does not check
capabilities. The index generator is the check: a page whosecapabilities:key it cannot read (for example a bare string instead of a list), or that has no closing---, failsvox ci capability-indexwith the page path. Other malformed frontmatter that makes no claim is skipped.docs/src/archive/is never read. - Regenerate with
vox ci capability-index --write; never edit the index by hand.
Fast local lint loop:
cargo run -p vox-doc-pipeline -- --lint-only --paths architecture/my-page.mdcargo run -p vox-doc-pipeline -- --lint-only --paths architecture/my-page.md --fix
Authoring guardrail:
- Do not start a line with a single backtick in prose (for example
`vox ...at line start). Use normal prose with inline code or a full triple-backtick fence.
KB facets (taxonomy contract)
Section titled “KB facets (taxonomy contract)”Every new or renamed page under docs/src/ (outside archive/ and *.generated.md) must carry KB facets so the knowledge base can filter, cite and gate training on it. The vocabulary is contracts/documentation/kb-taxonomy.v1.yaml; the typed schema is contracts/documentation/kb-facets.v1.schema.json (generated from vox_kb_facets::Facets).
Required facets:
topicanddomain: exactprefLabelvalues from the taxonomy. A synonym (altLabel) or a retired alias is a lint error that names the right label.authorship:human,llm-assistedorllm-generated. Addauthorship_modelwhenever the authorship is LLM. Never write a value you cannot vouch for.- A page-one summary directly under the H1, independent of
descriptionand stripped from MENS training (shape below).
# Page title
<!-- kb:summary -->40 to 120 words that say what the page is for and what it decides.<!-- /kb:summary -->Training eligibility is forced to false for origin: web-promoted pages and for LLM authorship unless human_attested_by names the human reviewer. Only a human sets human_attested_by; agents must never write it.
Promoted (origin: web-promoted) pages need sources[], each with url, date (YYYY-MM-DD) and hash (blake3: plus 64 hex characters). Quotes are capped at 50 words each and 200 words per page.
Optional facets: kb_tier, trust_tier, scope, review_by, verified_at, supersedes, superseded_by, sensitivity.
Facet lint rule ids
Section titled “Facet lint rule ids”| Rule id | Fix |
|---|---|
facet-missing-topic, facet-missing-domain | add the facet with a taxonomy prefLabel |
facet-unknown-topic, facet-unknown-domain, facet-deprecated-label | use the prefLabel the message suggests |
facet-domain-mismatch | pick a topic that belongs to the page’s domain, or fix the domain |
facet-missing-summary, facet-summary-placement | put the kb:summary block directly under the H1 |
facet-summary-word-count | keep the summary between 40 and 120 words |
facet-missing-authorship, facet-missing-authorship-model | add authorship (and authorship_model for LLM authorship) |
facet-training-eligible-contradiction | drop training_eligible: true, or add human_attested_by after human review |
facet-missing-sources, facet-source-field | give every source a url, date and blake3 hash |
facet-quote-over-cap | shorten or paraphrase the quote |
facet-invalid-date | use YYYY-MM-DD |
facet-unknown-key | rename the misspelled frontmatter key (for example training_eligble) to the facet the message names |
facet-invalid-attestation | name the human reviewer in human_attested_by (not a placeholder such as false, none, todo or an AI name), or remove the key |
facet-parse-error | fix the facet value named in the message |
facet-backlog-stale (warning) | run --tighten-facet-backlog |
facet-contract-unreadable | restore the taxonomy and backlog under contracts/documentation/ |
Backlog ratchet
Section titled “Backlog ratchet”Docs that predate the contract are listed, with the rule ids they still violate, in contracts/documentation/kb-facet-backlog.v1.yaml. A listed doc is excused only for its listed rule ids; editing it does not force compliance, but fixing it should be followed by:
cargo run -p vox-doc-pipeline -- --tighten-facet-backlogThe backlog only shrinks. Adding a row or rule id is USER-AUTHORIZED-ONLY: it needs a re-seed (--seed-facet-backlog --epoch-note "<why>"), which bumps the epoch, and the fast-tier gate rejects any growth that lacks one. Even a re-seed cannot list a doc that does not exist at the base ref: a new or renamed doc is never excused. Never hand-edit the file.
Documentation Reality Audit
Section titled “Documentation Reality Audit”For a sustained doc vs code vs contract triage loop (aspiration vs fulfillment, historicity, and prioritized backlog), use the Documentation Reality Audit Program. Machine-readable claims and findings live under contracts/reports/docs-reality-audit/; CI validates them via vox ci docs-reality-audit verify (also included in vox ci ssot-drift).
Authority tiers (A-D)
Section titled “Authority tiers (A-D)”Use one authority tier per documentation domain. The canonical registry is
contracts/documentation/canonical-map.v1.yaml.
| Tier | Meaning | Typical location | CI expectation |
|---|---|---|---|
A-spec | normative machine-readable contract | contracts/, schema-backed registries | contract validator must pass |
B-canon | one canonical human page for the domain | usually docs/src/reference/ (or one ADR) | no second canon for same domain id |
C-generated | code-derived docs | *.generated.md and include fragments | generation verify command must pass |
D-index | navigation, index, compatibility stubs, research maps; Starlight sidebar is the D-index — do not maintain a committed research catalog | architecture/ci pointers and index pages | must link to canon, not restate canonical behavior |
Rules:
- Do not label a page as “SSOT” unless it is the sole
B-canonpage for its domain id in the canonical map. D-indexpages should summarize links only. If behavior text duplicates aB-canonpage, remove it.
Placement guide
Section titled “Placement guide”When adding or moving a page:
- If the source of truth is machine-readable, put the contract in
contracts/and link to it fromdocs/src/reference/. - Register the domain in
contracts/documentation/canonical-map.v1.yamlwithspec_paths, onecanon_doc, and any alias stubs. - If the subject is a communication protocol or transport boundary, make the machine-readable artifact discoverable from
contracts/index.yamland mirror it from one canonicaldocs/src/reference/page. - If the page teaches or explains the user-facing language, keep it in
docs/src/. - If the page is mainly for contributors or automation, prefer
docs/src/contributors/ordocs/agents/. - If the page is research or planning, keep it under
docs/src/architecture/and label it clearly withstatus: researchorstatus: roadmap. - If a page exists only as a compatibility stub, make it a short redirect and avoid duplicating the canonical content.
Claim policy
Section titled “Claim policy”Forward-facing docs should describe the architecture that exists now.
Prefer:
- “Vox documents a compiler pipeline that generates Rust and TypeScript artifacts.”
- “Mens currently defaults to code-oriented training lanes.”
- “This page is research, not a claim that the capability is fully shipped.”
Avoid:
- “Vox already does everything in this section automatically” unless the code path is current and documented.
- “Mens answers architecture questions” unless that retrieval or QA path is explicitly wired and tested.
- “SSOT” in titles when the page is only a convenience summary, pointer, or index.
Maintenance protocol
Section titled “Maintenance protocol”Use this lightweight review matrix for high-drift surfaces:
| If you change | Also review |
|---|---|
| authority ownership, stubs, or canonical pathing | contracts/documentation/canonical-map.v1.yaml, vox ci check-docs-ssot, and affected alias pages |
crates/vox-cli/src/** command surface | docs/src/reference/cli.md, command-compliance docs, contributor references that mention the command |
| secret or env handling | AGENTS.md, Secrets SSOT |
| agent instruction layering or shell-discipline policy | AGENTS.md, Agent instruction architecture, and relevant tool-specific overlays such as GEMINI.md |
| doc structure, nav, or new pages | this page, docs/src/adr/002-diataxis-doc-architecture.md, docs-astro sidebar |
| architecture claims | Doc-to-code acceptance checklist, relevant explanation/reference pages |
| contracts or schema-backed behavior | matching contracts/ files and the mirrored reference pages |
| communication protocols, transport routes, or streaming semantics | contracts/communication/protocol-catalog.yaml, Communication protocols reference, and the owning protocol page such as MCP / Populi / runtime docs |
| Mens training or corpus behavior | Mens native training SSOT, Mens training data contract |
Codex research_metrics, mesh/cost telemetry env knobs, or telemetry trust boundaries | Telemetry and research_metrics contract, env-vars, Telemetry trust SSOT |
apps/editor/vox-vscode/ (extension host, webview UI, Oratio/MCP wiring) | apps/editor/vox-vscode/README.md, VS Code to MCP compatibility; speech capture / Oratio pages when capture or tool surfaces change |
Review cadence
Section titled “Review cadence”- Front door surfaces: review on every material product-language or contributor-experience change.
- Architecture and reference pages: review when the owning code path changes.
- Research and roadmap pages: keep their status current even if the implementation does not move.
- Contributor and governance pages: review whenever CI, inventory rules, or workflow expectations change.
Related
Section titled “Related”- Contributor hub
- Doc-to-code acceptance checklist
- Architectural governance (TOESTUB)
- Doc inventory verifier
Documentation Update Checklist
Section titled “Documentation Update Checklist”Before committing documentation to the repository, verify the following constraints:
- Syntax correctness: All code snippets must parse and type-check cleanly. You must write raw, inline ````vox``` code blocks within the document. The
vox-doc-pipelinewill dynamically extract and validate all inline Vox blocks. Only use{{#include}}for legacy files, or use// vox:skipinside the block to explicitly disable dynamic validation for pseudo-code. - Authority registration: New canonical pages must be reflected in
contracts/documentation/canonical-map.v1.yaml; aliases must remain link-only. - Status marker: Use
statusonly when needed (current,experimental,legacy,research,roadmap,deprecated). - Terminology: Use established nomenclature (Codex vs Arca, Mens vs Populi, Islands vs Components).
- Navigation integrity: If creating a user-facing document, update Starlight nav metadata (frontmatter
title/category/sort_order) and runvox-doc-pipeline --lint-onlyorpnpm --dir docs-astro buildas appropriate.