Context
A vocabulary value has carried label and blurb for as long as there have
been vocabularies. A relation gained the same pair in #254, on an argument
worth repeating: “what a relation IS, as data rather than as a TOML comment
nothing could render, quote or scaffold from.”
The things those belong to had neither. Audited:
| object | label | blurb |
|---|---|---|
Reference | yes | yes (#254) |
| a vocabulary value | yes | yes |
Journal | — | yes |
Chain | title | — |
Vocabulary, TagGroup, PlainField, Scheme, FieldGroup | — | — |
So a reader could learn what training-optimization means and not what the
axis it sits on is for. In the consumer that raised this, the topics
vocabulary carried about thirty-five lines of comment explaining the thirteen
and how to file against them, reachable by no view. A PlainField was worse:
with no vocabulary to carry the explanation there was nowhere at all to say
what a field meant.
Decision
Two pairs, and which one an object takes follows from what it is.
label+blurb— a thing named inside a scheme:Vocabulary,TagGroup,PlainField,FieldGroup, andReference, which already had it. These are members of a scheme, not documents;labelis what a view calls one andblurbis what it means.title+blurb— a thing that renders its own page:Scheme,Journal, which already had it, andChain, which hadtitleand now takesblurbtoo.
That resolves the question #279 raised about Scheme, and it is why Scheme
does not take label: it is the same shape of thing as a Journal, a stream
of documents with an index.
A vocabulary’s pair lives on the set, in the central table.
vocabularies:
topics:
label: Topics
blurb: the primary axis of both indexes
values:
alpha: {label: Alpha, blurb: "..."}
The nested form is recognised by a values: mapping and no other keys
besides label and blurb. Every config written before this is flat and
reads exactly as it did.
Rendered, or it would be inert. A scheme’s title/blurb become a new
docs/record.md section; a field’s or group’s blurb is appended to its
contract line, after the citation; a vocabulary’s own description heads every
one of its value pages, above the value’s.
Alternatives considered
- Put the vocabulary’s pair on the field that invokes it. This is what the first implementation did, and firing it on the real record is what caught it: written into the central table it parsed as two extra values, taking the anthology’s thirteen topics to fifteen. The deeper fault is the one ADR-098 already decided — a vocabulary two schemes share is declared once precisely so the copies cannot drift, and ten of thirteen entries had drifted when they were two files. A description per invoking field would have recreated exactly that, one level up.
- A reserved key inside the flat table (
_meta:). No new nesting, but it collides with a value named_metathe same way, reads as a hack, and gives the values table two kinds of entry. - Require the nested form everywhere. Cleanest to read and it breaks every existing config for no gain to a project that has nothing to say.
isinstance(table["values"], dict)alone as the discriminator. The obvious spelling and wrong: a value namedvaluescarries{label, blurb}, which is also a mapping, so a flat table holding one would read as nested and every other value would vanish silently. The rule is keys-are-a-subset, and a flat table with avalueskey is refused rather than guessed at.- Status quo. A project’s most careful prose about its own schema stays in
comments, and
docs/record.mdkeeps saying what a scheme constrains without ever saying what it is for.
Consequences
Config gains vocabulary_meta, kept beside vocabularies rather than
inside it so every consumer of the values map reads what it read before.
contract.Field gains blurb, carried from whichever table typed the field,
and describe() routes every line through one say() so the suffix cannot be
added to some lines and not others.
Fired on the real case both ways round, per the working agreement. In
anthology-of-the-sota, moving topics to the nested form: 14 values parsed
(unchanged), one description reaching all three schemes that name it, and the
blurb rendering above the value’s on every tag page. The malformed intermediate
— a values: key with the values left at the old indentation — was refused
with the message naming the fault, which is the guard working on its author.
Left open: a field that declares only a blurb still fails the
declares-no-type check, because describing a field is not constraining one.
That is defensible and it is now the likeliest thing to trip someone, since
wanting to document an unconstrained field is exactly what this key makes
natural.