%unimsg 0 design/terminology-and-infrastructure/v0 -- The words the project uses for its own parts, the name it goes by, and the -- arrangement of the things that have grown up around the format — written -- down because until now every one of them was decided at the moment it was -- first needed, by whoever needed it, and the third "profile" did not mean -- what the first one meant. -- -- Written against @vocab/design/v0. It is a proposal, and its tables are the -- part that binds once it stops being one. terminology-and-infrastructure @design/terminology-and-infrastructure/v0 { conforms -> @vocab/design/v0 title "Terminology, branding and organisation: one word per kind of thing, and a registry that lists all of them" status :proposal about -> @unimsg/v0 at 2026-09-02 -- =================================================================== -- THE ASK -- =================================================================== the-ask "Open the terminology around unimsg, its branding and the organisation of the infrastructure that has accumulated around the format, and standardise it. In particular: define a register of vocabularies, and decide what a profile within a vocabulary is called — staying with linguistic nomenclature, and considering `lect`, a variety of a language, for that second thing." what-is-ad-hoc-today "The survey behind this document read every header line in the repository — the `kind/name/vN` after `%unimsg 0` — and the block keyword that opens each document. Sixty-odd documents use twenty kinds, and the kinds were coined one at a time. THREE UNRELATED THINGS ARE CALLED A PROFILE. `@unimsg/v0` in profiles/ is a conformance profile of the ENCODING: which key types are allowed, that determinism is required, a depth limit. `@rd/profile/prose/v0` in the same directory is a declared subset of a VOCABULARY that a document promises to stay inside. `@ui/target/web/v0`, also there, describes a RENDERER — what a build has and what it resolves tokens to — and vocab/README.md already had to spend a paragraph warning that the last two are easy to confuse. One directory, three kinds, one word. IDENTIFIERS DO NOT SHARE A GRAMMAR. A vocabulary is `@vocab//v0`, which is regular. A library is `@ui/lib/v0`; a target is `@ui/target/web/v0`; a lect is `@rd/profile/prose/v0`; a mapping is `mapping/encyclopaedia/infobox-planet/v0` with no `@` at all. Two of these abbreviate the vocabulary they serve (`ui`, `rd`) and the rest do not, so a reader cannot tell from an identifier what kind of thing it names or which vocabulary it belongs to without opening the file. ONLY ONE DIRECTORY HAS AN INDEX. vocab/vocabularies.umsg lists the vocabularies and renders to vocab/README.md, and it is the nearest thing to a registry the project has. Profiles, lects, targets, libraries and mappings appear in no index at all; a tool that wants the target for a toolkit finds it by knowing the path. THE NAME IS WRITTEN THREE WAYS. Prose in this repository writes `unimsg` lowercase 263 times and `UMSG` once; the ask that produced this document writes `UniMSG`. The domain had the same history in miniature: docs/18's first draft assumed unimsg.org, and the .org survived in docs/README.md and a tool comment after docs/18 itself had settled on .net." -- =================================================================== -- THE NAME -- =================================================================== the-name-is-one-lowercase-word "`unimsg`. Lowercase, one word, in prose and in code, because that is what the header line, the file extension, the identifiers and 263 occurrences in the design record already say. A word that is spelt the same in a sentence, a URL, a header and a namespace costs nothing to remember and never needs a style rule quoted at anyone. `UniMSG` IS A DISPLAY FORM, NOT A SECOND NAME. It may appear as a wordmark — a logo, a page banner, a store listing that would otherwise lowercase the first letter of a title — and nowhere a reader might copy it into a search box or a document. `UMSG` and `Unimsg` are not used. THE ABBREVIATIONS ARE FIXED: `.umsg` is the file extension for the text form; `%unimsg` is the header keyword; `@unimsg/v0` is the conformance profile. None of these is a name for the format." the-domain-is-unimsg-net "Decided on 2026-09-02: the canonical address is unimsg.net. docs/18 already records it as a decision rather than a typo; the two stale .org references — the docs/README.md row for doc 18 and the comment at the top of tools/site — were corrected with this document. unimsg.org is not a redirect and is not referred to." -- =================================================================== -- THE LINGUISTIC NOMENCLATURE -- =================================================================== why-linguistic-terms-fit "The project already speaks this way. A VOCABULARY says what a document's fields mean. A QUALIFIER is a word written in front of a value. The text form has a LEXER and the design record compares DIALECTS of syntax. The terms were not chosen for effect; they were chosen because a format that makes meaning addressable has the same parts a language does, and borrowing the words a linguist would use keeps the analogy honest. Extending that analogy is cheaper than inventing a parallel set, provided each borrowed word is given exactly one job." the-kinds [ | kind "a variety of" holds "today's example" | "vocabulary" "meaning" "what a document's fields mean; the shape a gate checks" "@vocab/rich-document/v0" | "lect" "a vocabulary" "a declared variety of one vocabulary: fixed values, refused keys, no new ones" "@rd/profile/prose/v0 — the prose subset of rich-document" | "target" "a renderer" "what one build of one consumer has, and what it resolves tokens to" "@ui/target/web/v0" | "library" "a kernel" "element types derived over a vocabulary's kernel; adds nothing to implement" "@ui/lib/v0" | "mapping" "another format" "how an external format's constructs land in a vocabulary" "mapping/encyclopaedia/infobox-planet/v0" | "profile" "the encoding" "what the format itself restricts: key types, determinism, limits" "@unimsg/v0" | "registry" "the whole" "the one list of every named thing above, with its kind, hash and status" "vocab/vocabularies.umsg, for vocabularies only" ] lect-is-the-right-word "A lect, in linguistics, is any variety of a language distinguished by SOMETHING — region gives a dialect, social group a sociolect, situation a register — and the word exists precisely because the general notion needed a name that presumed none of the specific ones. That is the situation here. `@rd/profile/prose/v0` is rich-document as written by an author with no opinion about type; a future one might be rich-document as written for a screen reader, or encyclopaedia as written for a gazetteer. They vary a vocabulary along an axis the lect itself declares, and the axis is different every time. A LECT IS A VARIETY AND NOT ONLY A SUBSET. The prose lect refuses keys, which is a subset, and FIXES five values, which is not — a document in it resolves to formatting a plain rich-document reader would have had to be told. So `subset` or `restriction` would have been wrong words, and `profile` was a wrong word for a different reason: it was already taken. WHAT A LECT MAY NOT DO IS ADD. A lect that introduced a key its vocabulary does not have would be a new vocabulary wearing a disguise, and a gate for the parent would refuse its documents. That is the rule that keeps a lect cheap: every document in a lect is a valid document of the vocabulary, and a reader that knows only the vocabulary reads it correctly, if less efficiently." the-words-not-taken [ | word "why not" | "dialect" "presumes a geographic axis, and docs/05 already uses it for the candidate human syntaxes — which are notations of one data model, not varieties of one vocabulary. That use is retired below in favour of `syntax`" | "register" "the linguistic sense is an axis of variation by situation, and docs/09 already uses it that way as a declared DIMENSION in the Arabic plural data. It cannot also be the name of the list of vocabularies" | "subset" "true of the refusals and false of the fixed values; a lect changes what a document means by default, and a subset does not" | "variant" "no linguistic weight, and already the ordinary English word for anything slightly different from anything else" | "profile" "three meanings in one directory today. It keeps the one with prior art outside this project — RFC 8949 calls a set of encoding restrictions a profile, and @unimsg/v0 cites that section by name" ] registry-not-register "The list of everything is a REGISTRY, and the act of adding to it is to REGISTER. This is what docs/00 through docs/07 already say, fifteen times, when they talk about the IANA tag registry and the `registry governance` the format inherits; it is what the promotion ladder in the glossary means by `register publicly`. `Register` as a noun is reserved for the linguistic dimension, where docs/09 put it, and the two are not confused because one is a noun in the data and the other a verb about the repository." syntax-not-dialect "The six candidate human forms in docs/05 were called dialects when there was one data model and six ways to write it. There is now one text SYNTAX, specified in docs/15 and the specification, and a binary encoding. Neither is a dialect of anything. The term is retired; the documents that used it are historical and are not rewritten." -- =================================================================== -- ONE GRAMMAR FOR IDENTIFIERS -- =================================================================== the-identifier-grammar "Every named thing in the registry is identified as @//v for a vocabulary, profile or registry @///v for a lect, target, library or mapping where is one of the seven words in the-kinds, is the bare name of the vocabulary served (`rich-document`, never `rd`), and is the thing's own name. A vocabulary keeps `@vocab//vN` because eleven of them exist under that form in documents outside this repository, and `vocab` is the kind word abbreviated once, everywhere, rather than a second convention. THE KIND IS THE FIRST SEGMENT SO A READER CAN SORT BY IT. The vocabulary is the second so a reader can find everything that serves one. The header line carries the same path without the `@`, as it does today, and the block keyword is the kind word." renamed-under-the-grammar [ | today "under the grammar" kind | "@vocab/rich-document/v0" "@vocab/rich-document/v0" "vocabulary — unchanged" | "@rd/profile/prose/v0" "@lect/rich-document/prose/v0" "lect" | "@ui/target/web/v0" "@target/ui/web/v0" "target" | "@rd/target/print/v0" "@target/rich-document/print/v0" "target" | "@ui/lib/v0" "@library/ui/v0" "library — DONE 2026-09-02, the first rename applied; see the-library-went-first" | "mapping/encyclopaedia/infobox-planet/v0" "@mapping/encyclopaedia/infobox-planet/v0" "mapping" | "@unimsg/v0" "@profile/core/v0" "profile — decided 2026-09-02, applied when the tree is quiet; see the-profile-shares-the-spec-name" | "@vocab/vocabularies/v0" "@registry/unimsg/v0" "registry" ] the-library-went-first "The library was renamed on 2026-09-02, ahead of the rest, because it was the smallest case and settled the one objection the grammar invited: that `library @library/ui/v0 {` says the kind twice. It does, and so does `vocabulary @vocab/ui/v0 {`, which nobody had minded. The envelope keyword is the kind and the first segment of the identifier is the kind, and they agree because they are the same fact written for two readers — the parser and the sort order. Six files changed: the header and envelope, the showcase's `uses`, two prose mentions, the registry's ancestor and its generated README. uigen resolved the renamed library without a change, which confirms that the tool finds it through `uses` and not by name." the-profile-shares-the-spec-name "The first draft of this document said `@unimsg/v0` was written into every implementation's profile checker and recommended leaving it as a documented exception. That was checked and it is false: the identifier appears in two comments across eleven implementations, and the checker takes a profile by path. The cost that justified the exception does not exist. WHAT THE CHECK FOUND INSTEAD IS A COLLISION. spec/unimsg-v0.umsg opens `spec @unimsg/v0` and profiles/v0.umsg opens `profile @unimsg/v0`: two documents, one identifier. A registry cannot hold that row twice, so one moves, and it is the profile — a restriction is subordinate to the thing it restricts, and the bare name belongs to the specification. DECIDED 2026-09-02. The profile becomes `@profile/core/v0`: the baseline every v0 document meets, a name that stays true when a second profile arrives and says nothing a new rule could make false. `interchange` was the runner-up, and was not taken because it names the reason the current rules were chosen rather than what the profile is. The specification keeps `@unimsg/v0` and its header line changes from `spec/unimsg/v0` to `unimsg/v0` so the header and the envelope say the same thing. NOT YET APPLIED, DELIBERATELY. Other work is in flight in this tree and references these names. The rename is done once that work has landed and before any new work begins, in one commit, with the library rename above as the pattern: header, envelope, every `->` reference, the registry's ancestor, the generated README, and a run of every checker that reads a renamed file." now-is-the-time-to-rename "Every identifier above is at v0 and every document carrying one is :draft. The repository's own rule for drafts is that they are amended in place — an identifier is a name and not a counter, and nothing has been released that a rename would break. That window closes at the first public release, after which a renamed identifier is a successor with a predecessor and the old name must be resolvable forever. The rename is cheap this month and never again." -- =================================================================== -- THE REGISTRY -- =================================================================== what-the-registry-is "ONE document, `registry/unimsg-v0.umsg`, identifier `@registry/unimsg/v0`, in a vocabulary of its own shape, listing every named thing of the seven kinds. vocab/vocabularies.umsg is its ancestor and is folded into it: the prose there about why shapes differ from qualifiers and why a library is not a vocabulary survives as sections, and the tables become rows of the registry. vocab/README.md continues to be generated, from the registry, filtered to one kind. IT LISTS; IT DOES NOT DEFINE. A row names a thing, says what kind it is, which vocabulary it serves, where its document lives, what it hashes to, what status it carries, and what it succeeds. The definition is the document at the path. A registry that carried definitions would be a second copy of every vocabulary and would drift from the first." registry-row [ | column holds | :id "the identifier, under the grammar" | :kind "one of the seven" | :serves "the vocabulary a lect, target, library or mapping is for; absent for a vocabulary, profile or the registry itself" | :path "where the document is, relative to the repository root — for people; the identifier is the name" | :hash "what the document hashes to, so a consumer can verify it has the thing the registry means" | :status "the document's own status, copied, so a directory can be scanned without opening sixty files" | :succeeds "the identifier this one replaces, if any" | :holds "one sentence, as the vocab/README tables have today" ] the-registry-is-checked-not-trusted "A tool, `tools/registry`, reads the registry and every document it names, and refuses the build when a row's hash does not match its file, a row's status does not match the document's, a document of one of the seven kinds exists with no row, or a row's identifier does not parse under the grammar. That is the same arrangement the corpus has with the implementations and the gates have with the vocabularies: the list is the arbiter only because something checks it." -- =================================================================== -- THE INFRASTRUCTURE -- =================================================================== the-repository-by-kind [ | directory holds "changes proposed" | "spec/" "the specification" "none" | "profiles/" "encoding profiles — @unimsg/v0 and any successor" "loses the lects and targets that were put here for want of a directory" | "vocab/" "vocabularies, in shapes/, qualifiers/ and subjects/" "loses libraries/ and its index; keeps the generated README" | "lects/" "lects, one file per lect, named --v" "new; receives rd-profile-prose-v0" | "targets/" "targets, named the same way" "new; receives the eight *-target-* files" | "libraries/" "libraries" "new; receives vocab/libraries/ui-lib-v0" | "mappings/" "mappings, one subdirectory per vocabulary served" "none" | "registry/" "the registry and its shape vocabulary" "new" | "corpus/" "the conformance corpus" "none" | "vectors/" "test vectors" "none" | "descriptors/" "the bootstrap descriptors" "none" | "implementations/" "the independent implementations and their guide" "none" | "tools/" "the tools, one directory each" "gains registry/" | "docs/" "the design record — design, findings, guide, method" "none" | "issues/" "issues, in @vocab/issue/v0" "none" | "site/" "the built site" "regenerated once the domain is decided" ] a-directory-is-for-people "Nothing above changes a name. vocab/README.md says it in capitals — a vocabulary is named by its identifier and not by its path — and the same holds for every other kind. Moving the targets into targets/ touches no document that references one, because no document references a path. The directories are the reading order for a person opening the repository, and the registry is the reading order for a tool." the-document-kinds-are-already-fine "docs/ carries four kinds — design, findings, guide, method — and issues/ carries one. All five are document shapes, not registry kinds: a design is not a variety of anything, and it is listed in docs/README.md rather than the registry. They are named here only so that nobody reaches for `profile` or `lect` to describe a document about the format rather than a part of it." -- =================================================================== -- WHAT TO DO, IN ORDER -- =================================================================== the-steps [ | step does "cheap while" | 1 "settle this vocabulary of kinds — argue with the-kinds table before anything moves" "nothing has moved" | 2 "write @vocab/registry-shape/v0 and registry/unimsg-v0.umsg from vocab/vocabularies.umsg" "the vocabulary list is short enough to retype" | 3 "rename the lect, targets, profile and mappings under the grammar, once in-flight work has landed" "everything is v0 and no other work is open" | 4 "move files into lects/, targets/, libraries/, registry/; regenerate vocab/README.md" "no external path references exist" | 5 "write tools/registry and run it in implementations/check.sh" "the registry is small enough to check by eye against the tool" | 6 "regenerate site/ so its copy of docs/README carries unimsg.net" "the site has no inbound links" | 7 "add the seven kinds and the branding rule to docs/glossary.md" "this document is the only source" ] -- =================================================================== -- SCRUTINY -- =================================================================== scrutiny { load-bearing "That the three things called `profile` today are three different kinds and not one kind at three altitudes. If a lect and a target are the same kind of thing, `lect` is a rename and not a distinction, and the registry needs one word fewer." to-falsify "Find a document that has to be BOTH: a variety of a vocabulary that also describes a renderer's capabilities. The nearest candidate is a target that fixes authoring defaults for its own toolkit — a web target that says, in the same document, which rich-document keys its authors should not use. Cheapest to look for before step 3, by reading the eight targets and asking whether any of them fixes a value a document could have set." would-change "If a fourth kind arrives that the seven cannot hold — a transform between vocabularies, say, which is neither a mapping from an external format nor a lect of either — the grammar gains a word before the registry gains a row, and the-kinds table is amended rather than the new thing squeezed under `mapping`." already-rejected "Calling the format a LANGUAGE and everything else a variety of it. Tempting, because the analogy runs all the way down — but @vocab/language/v0 is a vocabulary for describing human languages, and `language` would then mean the format in one sentence and Akkadian in the next. The format is a format; the linguistic words are used one level down, for the things written in it." } }