Terminology
Ground your docs' vocabulary — glossary-backed lexicon rules over the same source layer as every other grounded check.
A glossary is one instantiation of grounding, not a separate subsystem. The generic form already exists: any named entity can be checked for membership against any source —
<!-- mdv: document mentions.shape="<word|oneOf:[Captain, Ensign]> <name>" mentions.in=crewRoster? -->Every mention matching the shape must exist in the crewRoster source; the trailing ?
activates the check once the roster is wired. The lexicon.* family adds per-term
structure on top of that same source layer, for the checks plain membership cannot
express: which spelling is canonical, which are banned, what the casing law is.
The glossary artifact
The machine canon is JSON: an array of entry objects —
{"term": "...", "kind": ..., "casing": ..., "aliases": [...], "deprecated": [...], "compounds": [...]} — shape-validated against grammars/glossary.schema.json. It is the
only format the lexicon.* rules read; a wrong-shaped JSON glossary is a loud
invalid-glossary error, never a silent skip.
[
{
"term": "waypoint",
"kind": "domain-term",
"deprecated": ["node"],
"definition": "A charted position a transit plan may pass through. \"Node\" was retired because it collided with the compute-cluster noun."
}
]A Markdown glossary is optional, and is not read by the rules directly: keep it as a
governed view of the JSON canon instead — a human-readable GLOSSARY.md, validated
like any other document, with its own lexicon/lexicon.undefined binding pointed at
the JSON so every term it mentions is checked for the same canonical spelling and
casing as the rest of the repo's prose (forward direction: the view must stay faithful
to the canon; reverse completeness — flagging a JSON term the view never mentions — is
documented as a future primitive, not yet enforced). Definition quality on the canon is
a governance concern: put glossary.json in CODEOWNERS, and validate it against the
schema in CI if you want stub definitions rejected mechanically.
Binding
<!-- mdv: document lexicon=./glossary.json? lexicon.undefined=./glossary.json? -->Or bind once in config — usually alongside the rules: baseline so every contract in
the tree inherits the binding with no per-file line at all:
export default defineConfig({
rules: { lexicon: { value: "glossary?" }, "lexicon.undefined": { value: "glossary?" } },
sources: { declare: { glossary: "./.mediva/sources/glossary.json" } },
});The trailing ? keeps a fresh copy shape-only until the glossary exists. Fragment refs
(#/pointer) are rejected for lexicon — the glossary is always read whole.
The checks
deprecated-term— a banned spelling in prose, reported with the canonical term. Case-sensitive, protected against longer canonical phrases ("Mediva" inside "Mediva CI") and quoted mentions (the use–mention distinction:"ruleset"as a historical reference never fires).term-casing— a standalone prose occurrence whose casing differs from the entry's declaredcasing. Headings, code, links, filenames, and dotted/hyphenated identifiers are exempt by construction; sentence-case of an all-lowercase term is tolerated (brands that must stay lowercase even at sentence start list the capitalized form indeprecatedexplicitly).undefined-term(opt-in) — an entity-shaped mention (acronym, CamelCase, multi-word name) absent from the glossary. The diagnostic is a decision fork written for LLM authors: use the near-match's canonical form; add a genuinely new term with a real definition (the glossary's own contract rejects stubs); or, if the term changes the meaning of an existing entry, stop and flag it for human review instead of editing the glossary.
All three default to warnings — promote per code once precision is proven in your repo
(error=deprecated-term). The durable gate on glossary edits is structural, not copy:
put the glossary in CODEOWNERS so every vocabulary change gets a human reviewer.
Worked example
templates/repo-docs/example/ is a complete fictional project whose README and
CHANGELOG validate against these rules in CI — the generic catalogue check and the
glossary checks side by side, bound through one inert config.
Grounded templates
Bind logical source names to real data — files, commands, loaders, or in-memory values — so a contract checks claims against current truth, not just shape.
Editors & LSP
mdv lsp brings live diagnostics, hover docs, and completion for mdv directives into VS Code, Neovim, Helix, or any LSP-capable editor.