Facet vocabularies and how they change
Normative for RUNBOOK.md §4. Data: vocabularies/. Implementation:
packages/lint/src/vocabulary.ts.
Why a facet needs a reason
A facet exists only if people filter by it, or if it affects execution safety. That is the whole defence against schema bloat, and without a process attached it is an opinion in a document.
A facet nobody can filter reliably fails the rule on its own terms. k8s and
kubernetes as two values split every list in half, and the reader who filtered by one
never learns the other half existed — so a controlled facet needs a synonym list as much
as it needs a vocabulary.
The vocabularies
| File | What | Closed? |
|---|---|---|
vocabularies/domains.json |
the eight second-level domains | closed, RFC only |
vocabularies/targets.json |
systems a runbook is about | controlled, additions by RFC |
vocabularies/capability-classes.json |
the class part of a capability URN | closed |
Each entry is { id, label, synonyms[], deprecated? }. A synonym resolves to a canonical
id and is never a value itself. A deprecated id still resolves — records that used it do
not break — and stops being suggested.
One dictionary. The deduplicator needs a vendor synonym list, and it uses this one. A second list beside the deduplicator would agree with this one until the first time somebody added a synonym to only one of them.
keywords[] is the pressure valve
Uncontrolled, unguaranteed, and not filterable. An author with a system we have never heard of is not stuck, and the catalog does not promise that searching a keyword finds everything that ought to match. This is deliberate: a vocabulary that rejected everything new would push people into writing prose in the fields that are supposed to be filterable, which is how a facet stops working while still appearing to.
Changing a closed vocabulary
- Who proposes. Anyone, as a PR to the vocabulary file, with the record or records that need it.
- What evidence. For a target: at least three records that would carry it, from more than one publisher — or one record plus a filter somebody actually asked for. For a domain: a set of runbooks that no existing domain describes without stretching. "It would be tidier" is not evidence.
- Who decides. The two-person rule applies (§15): a vocabulary change is a change to every URL that uses it.
- Deprecation path. An id is never deleted. It is marked
deprecatedwith a date and a replacement, and it keeps resolving — a removed id is a 404 on somebody's bookmark and a silent hole in an agent's filter.
Adding a facet, as a checklist
A PR proposing a new facet answers all four:
- Who filters by it? Name the surface. "A user might want it" is not a surface.
- Or what execution decision does it change? A facet that affects safety needs no filtering argument, but it needs to be one a supervisor or a reader acts on.
- What is the vocabulary? If the answer is "free text", the proposal is for
keywords[], which already exists. - What breaks if it is wrong? A facet whose wrong value costs nothing is a facet nobody will keep accurate.