Research 034: the mesh in domains
The operator asked for one language per domain because the same concept keeps arriving under different words. Inventory the words in use, test a domain split, list the clashes with evidence, and describe how the glossary rule would be checked.
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
---
|
||||
status: active
|
||||
initiated: 2026-10-07
|
||||
touches:
|
||||
- 00-META/glossary.md
|
||||
- 00-META/checks/
|
||||
- 02-DECISIONS/0006-the-substrate-and-the-control-plane.md
|
||||
- 02-DECISIONS/0008-a-context-owns-its-store.md
|
||||
- 03-DESIGN/01-to-be/06-the-controller.md
|
||||
- the descriptions of every module's tools and every seat's verbs in the catalogue
|
||||
---
|
||||
|
||||
# 034 — The mesh in domains
|
||||
|
||||
## What is investigated
|
||||
|
||||
The operator, 2026-10-07: *"I wanted to develop our nox-mesh domain driven. Meaning every concept
|
||||
should fit into some domain and we try to come up with a common knowledge base/glossary/jargon for our
|
||||
application. We kind-of do this already I think, yet sometimes, you return different words for existing
|
||||
concepts."*
|
||||
|
||||
Two terms from domain-driven design are used throughout this effort, so they are explained once here.
|
||||
A **domain** (in the literature, a *bounded context*) is an area of the system inside which every word
|
||||
has exactly one meaning, and which owns the concepts that meaning describes. A **ubiquitous language** is
|
||||
the set of words a domain uses the same way in conversation, in documents and in code. The glossary
|
||||
([`00-META/glossary.md`](../../00-META/glossary.md)) is this repository's attempt at a ubiquitous
|
||||
language for the whole mesh, without domains.
|
||||
|
||||
The effort asks five questions:
|
||||
|
||||
1. **Which concepts are in use**, in the glossary, the decision records, the designs and the issue
|
||||
reports, and in the words the running mesh's tools use to describe themselves?
|
||||
2. **Into which domains do they fall?** Each domain gets a purpose, the concepts it owns, the one word
|
||||
for each, and its relation to the others. The operator's starting guess — building and delivering
|
||||
changes; running modules on machines; health and alerts; data and backups; people, conversation and
|
||||
approvals; the network — is tested, not assumed.
|
||||
3. **Where do the words clash?** Two or more words for one concept (a *synonym*), or one word for two
|
||||
concepts (a *homonym*), each with evidence and a proposed single word.
|
||||
4. **How is the glossary rule checked?** [`AGENTS.md`](../../AGENTS.md) says *a rule states how it is
|
||||
checked*, and "one name per thing" is checked by nothing today.
|
||||
5. **How should the glossary be organised by domain?** Described only; the glossary itself changes when
|
||||
this effort graduates, not before.
|
||||
|
||||
## Why
|
||||
|
||||
Because the drift is measurable, and it costs. The glossary retired *control plane* on 2026-09-16; three
|
||||
weeks later 29 occurrences stand in 12 to-be designs — the documents that tell somebody what to do — and
|
||||
73 files created after the retirement use it. It retired *host agent*, *the host* and `mesh-host` for the
|
||||
**node-engine** on 2026-10-05; the descriptions of four tools the running mesh serves still say *"the host
|
||||
will restore"*, and the glossary's own entry for node tools says *"a host-side process the host
|
||||
supervises"*. The glossary defines **node**, while the decisions and designs of the last week use
|
||||
*machine* twice as often as *node*, and the console's own tools are called `mesh_machine` and list
|
||||
"machines". A reader — person or agent — who meets two words assumes two things, and an agent answering
|
||||
from these documents repeats whichever word it read last. That is the operator's complaint, observed.
|
||||
|
||||
## What it touches
|
||||
|
||||
The glossary and how it is kept; the checks in [`00-META/checks/`](../../00-META/checks/); the seven
|
||||
contexts of the controller that [ADR 0006](../../02-DECISIONS/0006-the-substrate-and-the-control-plane.md)
|
||||
named and [ADR 0008](../../02-DECISIONS/0008-a-context-owns-its-store.md) gave each its own store, which
|
||||
are the nearest thing the mesh already has to domains; and the descriptions of the tools and seat verbs
|
||||
that the modules in the catalogue serve, which are where an agent meets the mesh's words most often.
|
||||
|
||||
## The documents
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| [01 — The concepts in use](01-the-concepts-in-use.md) | the inventory: what was read, how it was counted, what the glossary holds and what it lacks, and the words the running tools use |
|
||||
| [02 — The domains](02-the-domains.md) | the proposed split into ten domains plus the repository's own, each with purpose, concepts, words and relations; the operator's guess tested |
|
||||
| [03 — The clashes](03-the-clashes.md) | twenty clashes with evidence and a proposed word for each, the five most costly first |
|
||||
| [04 — How the glossary is checked](04-how-the-glossary-is-checked.md) | a proposed check over hq documents and over the catalogue's tool descriptions; described, not built |
|
||||
| [05 — A glossary by domain](05-a-glossary-by-domain.md) | how the glossary would be organised; described, not written |
|
||||
|
||||
## Findings so far
|
||||
|
||||
- **The mesh already has domains under another name.** ADR 0006 named seven *contexts* of the controller —
|
||||
inventory, config, connectivity, provisioning, delivery, observability, identity. Only three of them have
|
||||
a store today (`inventory`, `identity`, and `licences`, which is not one of the seven), and the words the
|
||||
mesh has grown since (seat, delivery, condition, ask, data class) are not organised by them. The
|
||||
proposed split in [02](02-the-domains.md) keeps five of the seven, renames one, and adds four.
|
||||
- **The operator's guess survives mostly intact.** Five of its six domains hold up. It lacks a domain for
|
||||
*identity and access* (credentials, grants, licences), one for *provisioning* (provider and consumer),
|
||||
the *core* the rest runs on (controller, bus, store, lease, genesis), and the *module* itself, whose
|
||||
manifest is the language every other domain reads. *Health and alerts* is better called *health and
|
||||
repair*: the mesh says *condition*, not *alert*.
|
||||
- **The glossary is short of the vocabulary in use, and contradicts itself twice.** It has 33 entries. At
|
||||
least 40 words used in more than ten decision records each — *module*, *manifest*, *assignment*,
|
||||
*machine*, *provider*, *condition*, *gate*, *tier*, *operator* among them — have no entry. It defines the
|
||||
console as a module and, further down, says node tools replaced that name; it says the deprecated broker
|
||||
holds no seat and, in the entry for *claim*, that it claims `mesh-broker`.
|
||||
- **Most drift is in two places**: governing designs written before a word was retired and never
|
||||
revisited, and tool descriptions, which nothing compares with the glossary at all.
|
||||
- **Homonyms cost more than synonyms**, and a word list cannot catch them. *Plan*, *push*, *release*,
|
||||
*gate*, *tier*, *ask*, *store* and *record* each mean two to four things today, several of them in the
|
||||
verbs of the same seat.
|
||||
|
||||
## Questions for graduation
|
||||
|
||||
- **Machine or node.** One concept, two words, both heavily used; [03](03-the-clashes.md) recommends
|
||||
*machine* in prose and keeps `node` only as an identifier (a scope's value and the `node-` prefix of seat
|
||||
names). This is the largest rename the effort proposes, and the operator's call.
|
||||
- **Domain or context.** The repository already says *context* (ADR 0006, ADR 0008) for an owner of
|
||||
records with its own store. Using *domain* for the vocabulary partition beside it would be the effort's
|
||||
own synonym. [02](02-the-domains.md) proposes that a domain is the vocabulary and ownership boundary and
|
||||
a context is one store inside it, and asks for that to be decided rather than left to usage.
|
||||
- **Which documents the check holds to the list**, and from which date ([04](04-how-the-glossary-is-checked.md)).
|
||||
- **Where the tool-description check runs**: in the catalogue repository's merge check, or as a probe of the
|
||||
running mesh, or both.
|
||||
@@ -0,0 +1,148 @@
|
||||
# 01 — The concepts in use
|
||||
|
||||
What was read, how words were counted, what the glossary holds, what it lacks, and which words the
|
||||
running mesh's tools use. The domains in [02](02-the-domains.md) and the clashes in
|
||||
[03](03-the-clashes.md) are drawn from this.
|
||||
|
||||
## What was read
|
||||
|
||||
| Source | Size on 2026-10-07 | How |
|
||||
|---|---|---|
|
||||
| the glossary | 33 entries | read whole |
|
||||
| decision records (`02-DECISIONS/`) | 225 records | counted; the seven-contexts record (0006), its store rule (0008) and the records from 0220 to 0240 read for their words |
|
||||
| to-be designs (`03-DESIGN/01-to-be/`) | 49 documents | counted; the controller (06), connectivity (08), and 45 to 48 read for their words |
|
||||
| as-is designs (`03-DESIGN/00-as-is/`) | 17 documents | counted |
|
||||
| issue reports (`04-ISSUES/`) | 291 issues | counted |
|
||||
| research (`01-RESEARCH/`) | 33 efforts | counted; research 005 (*which domains the catalogue groups into*) read whole, as prior art |
|
||||
| the running mesh's tools | 88 modules serving 535 tools, plus the verbs of 15 seats every machine holds and 5 seats held once for the mesh | listed through the console's read tools (overview, machine, search, describe); nothing was called that changes anything |
|
||||
|
||||
**How words were counted.** A case-insensitive, whole-word match per file; the number given is the number
|
||||
of *files* containing the word, not of occurrences, unless a statement says otherwise. Where a file's age
|
||||
matters, its age is the date git first records it. The tool descriptions are the first line each tool
|
||||
gives of itself in the console's listing, which is cut at about 160 characters, so a word that occurs only
|
||||
late in a long description is undercounted there.
|
||||
|
||||
## What the glossary holds
|
||||
|
||||
Thirty-three entries, in seven sections: the mesh and its machines; what runs the mesh; what the mesh
|
||||
stores and serves; how modules relate to the mesh; the surfaces; how a change reaches the machines; the
|
||||
operator's machine. Retired words are marked three ways — struck through (`~~flavor~~`), *"Replaces
|
||||
**x**"*, and *"Not x"* — so no program can read the list of retired words from it reliably today.
|
||||
|
||||
**It contradicts itself in two places.**
|
||||
|
||||
- **The console.** The surfaces section defines the console as *"the module (`mesh-console`) that puts the
|
||||
mesh's tools in front of whoever is on a machine"*. The operator's machine section, further down, defines
|
||||
node tools as the runtime whose *"serving mode on loopback is what was called **the console**"*, and
|
||||
says node tools *"replaces 'console' as the module's name; console remains the word for the person's end
|
||||
of it."* Both entries are current.
|
||||
- **The deprecated broker.** Its entry says it has *"no seat, not foundation"*. The entry for *claim*
|
||||
says *"the `mesh-controller`, `postgres` and `lavinmq` modules claim the `mesh-controller`, `mesh-store`
|
||||
and `mesh-broker` seats"*, and the entry for *bus* says the bus is held by the `mesh-broker` seat.
|
||||
|
||||
**It uses a word it retired.** The node tools entry says *"a host-side process the host supervises"*,
|
||||
eight lines after the node-engine entry retired *the host*.
|
||||
|
||||
## What the glossary lacks
|
||||
|
||||
Words used in more than ten decision records each, with no entry of their own (files containing each, of
|
||||
225 records):
|
||||
|
||||
| Word | Records | Word | Records | Word | Records |
|
||||
|---|---|---|---|---|---|
|
||||
| machine | 177 | operator | 125 | catalogue | 120 |
|
||||
| declaration | 106 | manifest | 102 | reach | 101 |
|
||||
| provider | 95 | person | 91 | adopted | 84 |
|
||||
| tool | 76 | holder | 75 | grant | 65 |
|
||||
| assignment | 60 | secret | 56 | scope | 55 |
|
||||
| apply | 54 | resolver | 51 | genesis | 46 |
|
||||
| verb | 45 | firewall | 43 | route | 42 |
|
||||
| converged | 40 | private network | 37 | connectivity | 34 |
|
||||
| the lab | 33 | proxy | 31 | overlay | 30 |
|
||||
| upgrade | 27 | gate | 25 | condition | 23 |
|
||||
| endpoint | 23 | reconcile | 22 | vault | 20 |
|
||||
| hub | 19 | finding | 19 | health | 19 |
|
||||
| licence | 16 | probe | 15 | tier | 14 |
|
||||
| membership | 14 | anchor | 14 | backup | 11 |
|
||||
|
||||
*Module* itself — the word the whole mesh is built on — has no entry. Nor do the words of the four
|
||||
designs written in the last week: *condition*, *healer*, *self-check*, *watchdog*, *hand-act*, *drill*,
|
||||
*lease*, *epoch* (to-be 45, *a core that cannot fail silently*); *data class*, *restore point* (to-be 43
|
||||
and ADR 0233); *converged* and *adopted* as the two states a machine is in (the controller's `nodes` verb
|
||||
answers with them).
|
||||
|
||||
## The seven contexts, as they stand
|
||||
|
||||
ADR 0006 split the controller into seven **contexts** — areas of record, each owning its own store
|
||||
(ADR 0008) — and to-be 06 tabulates them:
|
||||
|
||||
| Context | Owns, in ADR 0006's words | A store of its own today? |
|
||||
|---|---|---|
|
||||
| inventory | nodes, modules, assignments, versions | yes |
|
||||
| config | settings, secrets, and deriving them onto nodes | no |
|
||||
| connectivity | overlay, resolution, exposure, filtering, certificates | no |
|
||||
| provisioning | resource grants between modules | no |
|
||||
| delivery | source to artifact to node | no — deliveries are kept by the `mesh-delivery` module since ADR 0239 |
|
||||
| observability | health, logs, metrics, alerts | no |
|
||||
| identity | agents, humans, services, authorisation | yes |
|
||||
|
||||
The store has a third database the seven do not name, `licences` (ADR 0183). The seven are the nearest
|
||||
thing the mesh has to domains, and they were drawn from one question — *does answering this need more than
|
||||
one node?* — which is a test for what the controller owns, not for where a word belongs. Seat, claim,
|
||||
bench, delivery group, condition, ask, data class and every word of the operator's conversation arrived
|
||||
after them, and none of those records says which context its words belong to.
|
||||
|
||||
Research 005 asked a neighbouring question in August — which *modules* group into domains — measured which
|
||||
modules change together, and found that only the reachability modules do. Its conclusion, recorded in ADR
|
||||
0009, was that modules are not grouped into packages; it did not touch the vocabulary. This effort groups
|
||||
*concepts and words*, not modules: a module may serve several domains, and the domains are not folders in
|
||||
the catalogue.
|
||||
|
||||
## The words the running tools use
|
||||
|
||||
The console's listing gives each tool's first line. Over the 535 module tools (the seat verbs are counted
|
||||
separately below):
|
||||
|
||||
| Word | Tools | Modules | Note |
|
||||
|---|---|---|---|
|
||||
| machine | 39 | 25 | the word most modules use for where they run |
|
||||
| node | 27 | 5 | 21 of the 27 in the agent's configuration module; the others the vault, the bus server, the packet filter and a flow editor whose own objects are called nodes |
|
||||
| the host / host's | 6 | 2 | the container module's `start` and `stop` tools, meaning the node-engine; the remaining uses are a network's hosts |
|
||||
| operator | 28 | 23 | the person; consistent with the glossary |
|
||||
| user | 30 | 12 | almost all a wrapped program's own accounts (an identity provider's users, the forge's users, a database's users) |
|
||||
| install | 43 | 16 | a package installed on a machine, never the mesh's assignment |
|
||||
| condition | 0 | 0 | — while the controller's verb is `conditions` |
|
||||
| seat | 0 | 0 | the module tools never name a seat; only the console and the controller do |
|
||||
| deploy, rollout, pipeline, control plane | 1, 0, 0, 0 | — | the one *deploy* is a wrapped program's own (a flow editor's) |
|
||||
|
||||
The seat verbs say:
|
||||
|
||||
- `<machine>/node-service-manager.start` and `.stop`: *"the answer says **the host** will restore what its
|
||||
declaration says at its next apply"*.
|
||||
- the bus server module's `connections` tool: *"a machine's **host** `node.<machine>`, a machine's runtime
|
||||
`<machine>.node-tools`"* — three words (host, node, runtime) for two programs, in one line.
|
||||
- `mesh-controller.plan`: *"What one machine would run, and why: **the declaration** the mesh would send
|
||||
it"*; `mesh-controller.plans`: *"What the last merges produced … the tiers"*;
|
||||
`mesh-controller.delivery-plan`: *"The delivery plan of a diffset"*. Three meanings of *plan* on one
|
||||
seat.
|
||||
- `mesh-controller.queue`, `.cancel`, `.clear`: *"Every **ask** in the build queue"* — while the glossary's
|
||||
*ask* is a request for the operator's input.
|
||||
- `mesh-delivery.release`: *"A person's word that a held delivery goes on"*; and
|
||||
`anthropic-licence-manager.release`: *"Unbind a consumer"*.
|
||||
- `mesh-controller.doctor`: *"The **self-check** …"* — the verb and the concept named differently.
|
||||
- the nftables module's tool is called `firewall_rules`, and the seat it holds on every machine is
|
||||
`node-packet-filter`, whose verb is `rules`.
|
||||
- `mesh-controller.nodes`: *"Every **machine** the mesh knows"*; the verb is named for nodes and answers
|
||||
in machines.
|
||||
- `node-build-agent` is the name of a seat every machine holds, while the glossary avoids *agent*
|
||||
*"because the word already means two other things here, the build agent and the operator's coding
|
||||
agent"*, and ADR 0237 calls the same role *the build seat*.
|
||||
- `operator-channel` is a seat of the mesh, held by the conversation's router (ADR 0234); the glossary
|
||||
names the router and the `channel` bench but not the seat.
|
||||
|
||||
**Vendor words are not drift.** A module that wraps a program speaks that program's language where it
|
||||
describes the program's own objects: an identity provider has *users* and *realms*, a media manager has
|
||||
*releases*, a flow editor *deploys*. That is correct and must stay so; a check that flagged it would be
|
||||
wrong ([04](04-how-the-glossary-is-checked.md) scopes the list to the mesh's own words for that reason).
|
||||
The drift is where a tool describes **the mesh's** objects — its machines, its engine, its seats — in a
|
||||
word the glossary retired or never had.
|
||||
@@ -0,0 +1,292 @@
|
||||
# 02 — The domains
|
||||
|
||||
A proposed split of the mesh's concepts into domains, tested against the operator's starting guess and
|
||||
against the seven contexts of ADR 0006.
|
||||
|
||||
## What a domain is here, and how one was drawn
|
||||
|
||||
A **domain** is an area of the mesh that **owns** a set of concepts: inside it each concept has one
|
||||
word, and the domain decides what that word means. Another domain may use the word — that is what makes
|
||||
it a shared language — but may not change its meaning. Two relations between domains are named:
|
||||
|
||||
- **upstream / downstream.** Domain A is *upstream* of B when B depends on A's concepts and A does not
|
||||
depend on B's. A change of meaning upstream ripples down; never the other way.
|
||||
- **shared word.** A word two domains both use. It is safe when both mean the same thing and one of
|
||||
them owns it; it is a clash when they mean different things ([03](03-the-clashes.md)).
|
||||
|
||||
Three tests decided where a concept belongs, in this order:
|
||||
|
||||
1. **Who records it.** The context, module or seat that writes the record of it owns it (ADR 0008: *a
|
||||
context owns its store*). A condition is the controller's record; a delivery is `mesh-delivery`'s.
|
||||
2. **Whose decision records define it.** The records that introduced the word, and the to-be design that
|
||||
names those records in its frontmatter.
|
||||
3. **Which other words it is never used without.** *Walk* never appears without *delivery*, *tier* and
|
||||
*gate*; *healer* never without *condition* and *budget*.
|
||||
|
||||
**Domain and context.** ADR 0006's *context* is narrower than a domain: it is one owner of records, with
|
||||
one store, inside the controller. This effort proposes that a domain may hold zero, one or several
|
||||
contexts, and that the two words are kept apart: **domain** for the area of vocabulary and ownership,
|
||||
**context** for a store-owning part of the controller. Whether to adopt *domain* at all, or to widen
|
||||
*context* to mean it, is a question for graduation ([00](00-overview.md)); this document uses *domain*.
|
||||
|
||||
## The split
|
||||
|
||||
Ten domains of the mesh, and one of this repository. They are ordered from the most upstream to the most
|
||||
downstream; each lists its purpose, the concepts it owns with the proposed word for each, and its
|
||||
relations.
|
||||
|
||||
### 1. Module — what a module is and declares
|
||||
|
||||
**Purpose.** To say what one module is, in the one document every other domain reads: its manifest.
|
||||
|
||||
**Owns.** *module*; *manifest* (the file a module is defined by — not *module definition*, not
|
||||
*module.yml* in prose); *resource* (what a manifest declares a machine must have: a file, a service, a
|
||||
container, a package); *declares* (the verb for what a manifest states); *provides* / *requires* (as
|
||||
written in a manifest; their meaning is Provisioning's); *claim* (a manifest's request to hold a seat);
|
||||
*setting* (a value a manifest declares and an assignment gives); *kept region*; *bundle* and *tools
|
||||
bundle*; *tool* (what a module serves) and *verb* (what a seat carries); *invokes*; *upgrade policy*
|
||||
(`roll`, `together`, `record`); the declarations of *data* and *health* (their meaning is Data's and
|
||||
Health's).
|
||||
|
||||
**Relations.** The most upstream domain. Every other domain reads the manifest, which makes its words a
|
||||
**published language** — a vocabulary fixed in a schema that others conform to. It depends on nothing
|
||||
but the Core's notion of a scope.
|
||||
|
||||
**Against the seven contexts.** None; the seven describe the controller, and the manifest is not the
|
||||
controller's.
|
||||
|
||||
### 2. Core — the mesh's own machinery
|
||||
|
||||
**Purpose.** To keep the controller, the bus, the store and every machine's engine running and agreed,
|
||||
so that every other domain has something to run on.
|
||||
|
||||
**Owns.** *controller*; *control-node*; *node-engine*; *node tools* (the tool runtime on every machine);
|
||||
*foundation*; *store* (the one database server); *bus*; *broker seat*; *genesis* (raising the foundation
|
||||
on an empty mesh); *lease* and *epoch* (ADR 0229: which controller may send, and the order of what it
|
||||
sent); *context* (a part of the controller that owns a store).
|
||||
|
||||
**Relations.** Upstream of every domain but Module. Every other domain is a **conformist** to it — it
|
||||
uses the bus and the store as they are and has no say in their shape.
|
||||
|
||||
**Against the seven contexts.** Not one of them: ADR 0006 described what the controller owns, and the
|
||||
Core is the controller itself.
|
||||
|
||||
### 3. Placement — what runs on which machine
|
||||
|
||||
**Purpose.** To decide, send and apply what each machine runs, and to say why.
|
||||
|
||||
**Owns.** *machine* (or *node* — see clash 1); *operator account*; *assignment* (a module put on a
|
||||
machine); *seat*, *scope* (machine, site, mesh), *capacity*, *bench*, *kind*, *holder*, *holding*;
|
||||
*depends on a seat*; *declaration* (what the controller sends one machine — see clash 9); *send* (the
|
||||
controller giving a machine its declaration; `push` is the verb that asks for it — clash 4); *apply* (the
|
||||
node-engine making a machine match its declaration); *reconcile*; *converged* and *adopted* (a machine's
|
||||
two states, ADR 0100); *pin* is Provisioning's, not this domain's.
|
||||
|
||||
**Relations.** Downstream of Module and Core. Upstream of Provisioning, Connectivity, Data and Health,
|
||||
which all need to know what runs where. Shares *setting* with Module (a manifest declares it, an
|
||||
assignment gives it its value) and *declaration* with Module (clash 9).
|
||||
|
||||
**Against the seven contexts.** ADR 0006's *inventory* (nodes, modules, assignments, versions) and the
|
||||
derivation half of *config*.
|
||||
|
||||
The operator's guess called this *running modules on machines (seats, benches, claims)*, and it holds.
|
||||
*Claim* belongs to Module (a manifest claims) and *holding* to Placement (an assignment holds), which is
|
||||
the distinction the glossary already draws in *installed / holding*.
|
||||
|
||||
### 4. Provisioning — one module serving another
|
||||
|
||||
**Purpose.** To resolve which module serves a provision for which consumer, and to wire the two.
|
||||
|
||||
**Owns.** *provision*; *provider*; *consumer* (the module that requires); *pin* (a person's choice of
|
||||
provider); *endpoint* (where a consumer reaches its provider); *pair credential* (the two ends of one
|
||||
credential; the credential itself is Identity's); *retire* (a provider stops serving a consumer the mesh
|
||||
no longer asks for, ADR 0230).
|
||||
|
||||
**Relations.** Downstream of Module (requires/provides), Placement (what runs where) and Identity (the
|
||||
credential). Upstream of Data, which watches what a provider keeps for a consumer. Shares *consumer* with
|
||||
Identity's licences (a licence is bound to a consumer) — the same idea, safely shared.
|
||||
|
||||
**Against the seven contexts.** ADR 0006's *provisioning*, unchanged.
|
||||
|
||||
The operator's guess has no such domain; its words are spread across *running modules* and *data*. They
|
||||
are a language of their own: 95 decision records say *provider*, and four seat verbs (`pin`, `unpin`,
|
||||
`retire`, `cleanup`) are about nothing else.
|
||||
|
||||
### 5. Identity and access — who may do what
|
||||
|
||||
**Purpose.** To issue, hold, rotate and check the credentials and grants by which modules, machines,
|
||||
agents and the operator act.
|
||||
|
||||
**Owns.** *credential* (anything that proves an identity); *secret* (a credential or other value the vault
|
||||
keeps sealed); *vault*; *grant* (what an identity may call or reach); *bus account* and *membership*; *rotate*;
|
||||
*licence*, *binding* (a consumer bound to a licence), *adopt* (taking in a licence that existed before);
|
||||
*proof* (what an authorising answer carries: a verified sender, a one-time code, a key's touch);
|
||||
*operator identity* (the list the router checks a sender against).
|
||||
|
||||
**Relations.** Downstream of Core (the bus's accounts) and Placement (what is assigned where). Upstream of
|
||||
Provisioning, Operator and conversation, and Change and delivery (whose builds are signed and whose
|
||||
merges are approved).
|
||||
|
||||
**Against the seven contexts.** ADR 0006's *identity*, plus the secrets half of *config*, plus the
|
||||
`licences` store, which is a context the seven did not name.
|
||||
|
||||
The operator's guess has no such domain. It is not small: *credential* is in 78 decision records, *grant*
|
||||
in 65, *secret* in 56, and two of the three context stores that exist today (`identity`, `licences`) are
|
||||
its.
|
||||
|
||||
### 6. Change and delivery — a commit on its way to the machines
|
||||
|
||||
**Purpose.** To take one commit from its pull request to every machine that should run it, and to put it
|
||||
back when it fails.
|
||||
|
||||
**Owns.** *pull request*, *commit*, *trunk*; *merge check* (the two statuses a pull request carries, the
|
||||
*merge gate* and the *repository check*, ADR 0238); *build*, *build seat*, *build queue* and the entry in
|
||||
it (clash 7); *package* and *package-registry*; *artifact* and *artifact store*; *catalogue* (what the mesh
|
||||
holds of every module, at which commit); *delivery*, *delivery group*, *delivery plan* (its *build plan*
|
||||
and *deploy plan*); *walk*; *tier* in the sense of a step of a walk (clash 8); *first machine* and its
|
||||
*gate* (clash 6); *rollback*; *the lab*, *scenario*, *replay*.
|
||||
|
||||
**Relations.** Downstream of Module, Core, Health (the gate reads health) and Data (a module holding
|
||||
irreplaceable data is recorded, not rolled out, ADR 0236). Upstream of Placement in time — a walk asks
|
||||
the controller to send — and of Operator and conversation, which carries its held deliveries to a person.
|
||||
|
||||
**Against the seven contexts.** ADR 0006's *delivery*, now owned by the `mesh-delivery` module rather than
|
||||
by a context of the controller (ADR 0239).
|
||||
|
||||
The operator's guess called this *building and delivering changes*; it holds, with *change* kept for a
|
||||
diff (the glossary already says so) and *delivery* for the thing that travels.
|
||||
|
||||
### 7. Health and repair — what is wrong, and putting it right
|
||||
|
||||
**Purpose.** To notice what is wrong with the mesh, say it once, repair what may be repaired unattended,
|
||||
and record what was done by hand.
|
||||
|
||||
**Owns.** *health* (a module's or core component's statement of being well, ADR 0240); *probe*;
|
||||
*signal* and *watchdog*; *self-check* (clash 13); *condition* (one open fact about something wrong, with a
|
||||
key and a severity); *healer*, its *repair* and *budget*; *drill*; *hand-act*; *observation* (ADR 0231:
|
||||
only observation raises or clears a condition).
|
||||
|
||||
**Relations.** Downstream of everything it watches. Upstream of Change and delivery (the gate) and of
|
||||
Operator and conversation (a condition becomes a message).
|
||||
|
||||
**Against the seven contexts.** ADR 0006's *observability* — whose row says *"health, logs, metrics,
|
||||
alerts"*. The mesh never built *alerts*; it built conditions, and the word *alert* survives only in a
|
||||
wrapped dashboard program's tool. The domain is renamed accordingly: *observability* names the watching,
|
||||
and half of what this domain owns is repair.
|
||||
|
||||
The operator's guess called this *health and alerts*. It holds as a domain, under the word the mesh
|
||||
uses: *condition*, not *alert* (clash 14).
|
||||
|
||||
### 8. Data — what the mesh keeps, and getting it back
|
||||
|
||||
**Purpose.** To know every item of data a module holds, how precious it is, and to keep it recoverable.
|
||||
|
||||
**Owns.** *data* as a module declares it (ADR 0233); *data class* — *irreplaceable*, *rebuildable*,
|
||||
*cache*; *backup*; *restore point*; *restore* (beside the live data, never over it); the bus's *stream
|
||||
snapshot* (ADR 0235); *binding* of a consumer to its data moving only by a person (ADR 0232).
|
||||
|
||||
**Relations.** Downstream of Module (the declaration), Placement (where the data is) and Provisioning
|
||||
(data a provider keeps for a consumer). Upstream of Change and delivery (irreplaceable data holds a
|
||||
module back from rolling out) and of Health (data is watched).
|
||||
|
||||
**Against the seven contexts.** None. Data was not foreseen in ADR 0006; the self-check measures it today
|
||||
(`mesh-controller.data`), and every machine's `node-backup` seat keeps it.
|
||||
|
||||
The operator's guess called this *data and backups*, and it holds.
|
||||
|
||||
### 9. Connectivity — how machines and modules reach one another
|
||||
|
||||
**Purpose.** To make every machine and module reachable by name where it should be, and unreachable
|
||||
where it should not.
|
||||
|
||||
**Owns.** *private network* (clash 15); *resolver*; *uplink*; *hostname*; *zone*; *proxy* and *public
|
||||
name*; *packet filter* (clash 16); *intrusion prevention* and *ban*; *reach* (how far an
|
||||
assignment's endpoint may be reached from, ADR 0138); the roles a machine plays for the network (the anchor, a hub).
|
||||
|
||||
**Relations.** Downstream of Placement (what runs where) and Identity (who may reach). Upstream of
|
||||
Provisioning (an endpoint must be reachable) and of Health (an unreachable machine is a condition).
|
||||
|
||||
**Against the seven contexts.** ADR 0006's *connectivity*, unchanged — and the one domain research 005
|
||||
found real in the catalogue's history, where its modules are the only ones that change together.
|
||||
|
||||
The operator's guess called this *the network*, and it holds.
|
||||
|
||||
### 10. Operator and conversation — the person the mesh works for
|
||||
|
||||
**Purpose.** To let the mesh and its operator talk: tell, ask, answer, and act only on an answer it can
|
||||
trust.
|
||||
|
||||
**Owns.** *operator* (the person who runs the mesh; clash 17); *person* (any human, as against the mesh
|
||||
acting unattended); *console* (the person's or agent's end of node tools, clash 5); *channel* and *intake*
|
||||
benches; *router* and the `operator-channel` seat it holds; *responder*; *ask*, *authorising ask*,
|
||||
*answer*; *operator message* and *untrusted input*; *reference*; *notification* on a desktop.
|
||||
|
||||
**Relations.** Downstream of Health (conditions become messages), Change and delivery (a held delivery
|
||||
waits for a person's word) and Identity (proofs, the operator's identities). An authorising answer acts in
|
||||
whichever domain asked, through that domain's own verb; the conversation owns the asking, never the act.
|
||||
|
||||
**Against the seven contexts.** None. ADR 0006 named `api`, *"the one interface every surface speaks
|
||||
to"*, as an interface rather than a context; the console and the conversation are what it became.
|
||||
|
||||
The operator's guess called this *people, conversation and approvals*. It holds, with one adjustment:
|
||||
an **approval** is not this domain's concept. The approval of a merge is Change and delivery's (a human
|
||||
approves the pull request); the release of a held delivery is `mesh-delivery`'s verb; the conversation
|
||||
carries both as asks. *Approval* is in five decision records; *ask* in 58.
|
||||
|
||||
### 11. The record — how this repository works
|
||||
|
||||
Not a domain of the mesh but of the company's way of building it, and listed because its words collide
|
||||
with the mesh's. **Owns** *research effort*, *decision record* (and *supersede*, *progressive insight*),
|
||||
*design* (*as-is*, *to-be*), *issue*, *playbook*, *check* (one of `00-META/checks/`), *graduation*,
|
||||
*hand-off*. Its *record* and *check* collide with the mesh's (clashes 11 and 12).
|
||||
|
||||
## The operator's guess, scored
|
||||
|
||||
| Guess | Verdict |
|
||||
|---|---|
|
||||
| building and delivering changes | **holds** as *Change and delivery* |
|
||||
| running modules on machines (seats, benches, claims) | **holds** as *Placement*, with *claim* moved to Module |
|
||||
| health and alerts | **holds, renamed** *Health and repair*: the mesh's word is condition, and half the domain is repair |
|
||||
| data and backups | **holds** as *Data* |
|
||||
| people, conversation and approvals | **holds** as *Operator and conversation*, with *approval* owned by the domain whose act is approved |
|
||||
| the network | **holds** as *Connectivity* (ADR 0006's word) |
|
||||
| — | **added**: *Module* (the published language), *Core* (what the rest runs on), *Provisioning* (ADR 0006 had it), *Identity and access* (ADR 0006 had it) |
|
||||
|
||||
## A map
|
||||
|
||||
```
|
||||
Module (published language)
|
||||
|
|
||||
Core
|
||||
|
|
||||
+--------------------------+---------------------------+
|
||||
| | |
|
||||
Identity -------------> Placement |
|
||||
| / | \ |
|
||||
| / | \ |
|
||||
v v v v |
|
||||
Provisioning <------- Connectivity Data |
|
||||
| | |
|
||||
+-------------> Health and repair <------------------+
|
||||
| |
|
||||
v v
|
||||
Change and delivery Operator and conversation
|
||||
| ^
|
||||
+-------------------+
|
||||
(a held delivery waits for a person's word)
|
||||
```
|
||||
|
||||
Arrows point downstream. Change and delivery appears low because it reads health and data; in time it
|
||||
runs first, and asks Placement to send.
|
||||
|
||||
## What this split does not decide
|
||||
|
||||
- **Module ownership.** A module may serve several domains (the controller serves five). The domains
|
||||
are a partition of words and records, not of the catalogue — research 005 already found that grouping
|
||||
modules into folders records nothing.
|
||||
- **Whether every domain gets a context with its own store.** ADR 0008's rule applies where a domain's
|
||||
records live in the controller; *Change and delivery* has moved its records to a module instead, and
|
||||
that is equally sound.
|
||||
- **The operator's machine.** The desktop seats (display session, launcher, clipboard, notifier) are
|
||||
Placement's seats like any other, and their words are each program's own. Research 018 and 026 did not
|
||||
introduce a vocabulary that needs a domain.
|
||||
@@ -0,0 +1,306 @@
|
||||
# 03 — The clashes
|
||||
|
||||
Twenty places where the mesh's words disagree with each other. A **synonym clash** is two or more words
|
||||
for one concept; a **homonym clash** is one word for two or more concepts. Each entry gives the evidence
|
||||
— which documents and which tool descriptions say what — and a proposed single word, with the domain
|
||||
([02](02-the-domains.md)) that would own it. Counts are files containing the word, as in
|
||||
[01](01-the-concepts-in-use.md), unless they say *occurrences*.
|
||||
|
||||
The first five are ordered by cost: how often the clash appears where somebody is told what to do (a
|
||||
to-be design, `00-META`, a tool description), and how likely it is to make a reader act on the wrong
|
||||
thing. The other fifteen follow by domain.
|
||||
|
||||
A decision record keeps the words it was written with (its immutability rule), so a retired word found in
|
||||
a decision record is not a fault and is not counted as drift below unless the record was written after
|
||||
the word was retired.
|
||||
|
||||
## The five that cost most
|
||||
|
||||
### 1. *machine* and *node* — one concept, two words (synonym)
|
||||
|
||||
**Evidence.**
|
||||
|
||||
- The glossary defines **node**: *"a machine in the mesh"*, and has no entry for *machine*.
|
||||
- In the decisions and designs of the last week (ADRs 0220 to 0240, to-be 45 to 48), *machine* occurs 706
|
||||
times and *node* 349 times. Before ADR 0150, 6 record titles say *machine* and 9 say *node*; from ADR 0150
|
||||
on, 17 and 17.
|
||||
- In the tool descriptions, *machine* is in 39 tools of 25 modules; *node* in 27 tools of 5 modules, 21 of
|
||||
them one module's (the agent's configuration, where *node* is also a scope's value).
|
||||
- The console's own tools are `mesh_machine` and an overview that lists *"machines"*. The controller's verb
|
||||
is `nodes` and answers *"Every **machine** the mesh knows"*; `node` answers *"What one machine
|
||||
reported"*. Every seat a machine holds is named `node-…`.
|
||||
- The glossary itself switches inside one entry: *control-node* is *"the one node that also holds…"*, and
|
||||
the next sentence says it *"is not a separate kind of machine"*.
|
||||
|
||||
**Proposed word: _machine_** (Placement). It is what the operator, the tools and the newest records already
|
||||
say, and it needs no explaining. *Node* survives only as an **identifier**: the value of a scope
|
||||
(`scope: node`), the `node-` prefix of seat names, and *control-node* until it is renamed. The glossary
|
||||
would map the identifier to the word, as it does for `mesh-host` today. The alternative — *node* everywhere —
|
||||
is defensible and cheaper in code, and is what the glossary says; it is listed in
|
||||
[00](00-overview.md) as the operator's call because either choice renames something heavily used.
|
||||
|
||||
### 2. *node-engine*, *mesh-host*, *the host*, *node host*, *host agent* — one program (synonym)
|
||||
|
||||
**Evidence.**
|
||||
|
||||
- The glossary retired *host agent*, *the host* and `mesh-host` for **node-engine** on 2026-10-05, keeping
|
||||
`mesh-host` as the name of the repository, binary and service unit until they are renamed.
|
||||
- Its own node tools entry still says *"a host-side process **the host** supervises"*.
|
||||
- To-be 05 is titled *the node host*; *the host* is in 34 to-be designs and *node-engine* in 7.
|
||||
- Of the decision records written since the retirement, ADR 0222 says *the host* six times, ADR 0236 six
|
||||
times beside *node-engine* nine times, and ADR 0223 three of each.
|
||||
- Tool descriptions: `<machine>/node-service-manager.start` and `.stop`, and the container module's
|
||||
`start` and `stop`, say *"the answer says **the host** will restore …"*. The bus server's `connections`
|
||||
tool says *"a machine's **host** `node.<machine>`"* — naming the program *host* and its bus account
|
||||
*node*.
|
||||
- *Host* also keeps its ordinary meanings: a network host (the ssh client module's tools), *hosting* a
|
||||
service, and the *host's* network in a container runtime.
|
||||
|
||||
**Proposed word: _node-engine_** (Core), as the glossary already says; *the host* and *host agent* retired
|
||||
for the program. Because *host* also has ordinary networking meanings, the check in
|
||||
[04](04-how-the-glossary-is-checked.md) can retire only the phrases *the host* and *host agent* and the
|
||||
identifier `mesh-host` outside code spans, not the bare word. If clash 1 is decided for *machine*, the
|
||||
program's name reads more naturally as **machine engine**; this effort does not propose renaming it again.
|
||||
|
||||
### 3. *plan* — four things (homonym), and *change plan* / *release plan* / *delivery plan* (synonyms)
|
||||
|
||||
**Evidence.** On one seat, the controller's:
|
||||
|
||||
- `mesh-controller.plan` — *"What one machine would run, and why: the declaration the mesh would send it"*.
|
||||
A **machine's declaration**, previewed.
|
||||
- `mesh-controller.plans` — *"What the last merges produced and where each stands (ADR 0162): the
|
||||
tiers"*. ADR 0162 calls it *a tiered plan*; ADR 0218 and ADR 0236 call it the **release plan** (seven
|
||||
times in ADR 0236: *"Every release plan's first machine passes a gate"*).
|
||||
- `mesh-controller.delivery-plan` — *"The delivery plan of a diffset"*. The glossary: *"ADR 0238 called it the
|
||||
**change plan**; that word is retired"* — and the walk replaces the release plan: *"the controller's
|
||||
plan is now the walk of one delivery's trunk commit across machines"*.
|
||||
- `mesh-controller.bus` — *"The bus as a **planned step**"*.
|
||||
|
||||
*Release plan* appears in seven files created on or after 2026-10-06, the day ADR 0239 replaced it; *change
|
||||
plan* in four, including the title of ADR 0238.
|
||||
|
||||
**Proposed words** (Change and delivery, except the first):
|
||||
|
||||
| Concept | Word | Retire |
|
||||
|---|---|---|
|
||||
| what the controller would send one machine | **declaration** (Placement); the verb `plan` becomes `declaration` or `preview` | *plan* for this |
|
||||
| what a delivery would do to the mesh | **delivery plan** | *change plan*, *release plan* |
|
||||
| the controller's sending of one commit's builds across machines | **walk** | *release plan*, *plan* for this |
|
||||
| a step a person starts | **planned step**, or simply *step* | — |
|
||||
|
||||
Bare *plan* is then never a mesh concept on its own.
|
||||
|
||||
### 4. *push*, *send*, *roll out*, *release*, *deploy*, *upgrade* — moving a change (synonyms and homonyms)
|
||||
|
||||
**Evidence.**
|
||||
|
||||
- **push.** `mesh-controller.push`: *"Send one machine everything it should be. With no machine named it
|
||||
is a push of the WHOLE mesh"*. ADR 0221's title: *"a push sends no build a policy or a plan holds
|
||||
back"*. The same word is a git push (which, per the conventions, starts the build) and a phone
|
||||
notification (*"Matrix once its push is measured"*, to-be 46). *Push* is in 84 decision records and
|
||||
152 issues.
|
||||
- **send.** ADR 0236: *"that machine is sent it, by the ordinary send"*; the gate is judged *"from the
|
||||
moment it was sent the build"*. The controller's own description of `push` uses *send*.
|
||||
- **roll out.** ADR 0236's title says *rolls out unattended*; its person-facing verb is `upgrade <module>
|
||||
roll-out`, and the manifest's policy for the same thing is spelt `roll`. ADR 0218: *"code rolls out one
|
||||
machine first"*. *Roll out* is in 30 decision records and 36 issues.
|
||||
- **release.** `mesh-delivery.release` — *"A person's word that a held delivery goes on"*;
|
||||
`anthropic-licence-manager.release` — *"Unbind a consumer"*; and the retired *release plan* (clash 3).
|
||||
- **deploy.** The glossary: a delivery is *"not 'deployment' (one stage of it)"*; its *delivery plan* holds
|
||||
a *deploy plan*. The controller has no verb named deploy, and the only tool that says *deploy* is a
|
||||
wrapped flow editor's.
|
||||
- **upgrade.** `mesh-controller.upgrade` — *"How each module's new builds reach its machines … rolled out
|
||||
one machine first"*: a **policy**, not an act.
|
||||
|
||||
**Proposed words:**
|
||||
|
||||
| Concept | Word | Domain |
|
||||
|---|---|---|
|
||||
| the controller giving one machine its declaration | **send** (the verb `push` asks for one) | Placement |
|
||||
| one commit travelling to every machine | **delivery** | Change and delivery |
|
||||
| the per-machine part of a delivery plan | **deploy plan** (kept; the only use of *deploy*) | Change and delivery |
|
||||
| a build going to its first machine, judged, then the rest | **walk** (the act); **roll** (the policy, one spelling in the manifest and in the verb) | Change and delivery |
|
||||
| a person letting a held delivery go on | **release** — this sense only | Change and delivery |
|
||||
| unbinding a licence's consumer | **unbind** (rename the licence verb) | Identity |
|
||||
| how a module's builds reach its machines | **upgrade policy** | Module |
|
||||
|
||||
*Push* is kept for the controller's verb because it names what the operator does, but prose says *send*;
|
||||
*roll out* becomes the policy's value `roll` and is not a noun.
|
||||
|
||||
### 5. *console*, *node tools*, *mesh-console*, *the MCP server* — the operator's surface (synonym and homonym)
|
||||
|
||||
**Evidence.**
|
||||
|
||||
- The glossary's surfaces section: the console is *"the module (`mesh-console`)"*; not *"the tool bridge",
|
||||
"the brain" or "the MCP server"*.
|
||||
- The glossary's operator's machine section: node tools *"replaces 'console' as the module's name;
|
||||
console remains the word for the person's end of it"*. Both entries are current.
|
||||
- The live console introduces itself as *"The tools of a Novox mesh, reached as `<machine>.node-tools`"*,
|
||||
under an MCP server named `mesh`; the organisation's instructions to the agent call that server *"the
|
||||
console"*.
|
||||
- *Console* is in 28 decision records; `mesh-console` in 1; *node tools* in 10. A wrapped chat program's
|
||||
tool and the localisation module's tool use *console* in their own senses (a virtual terminal, a web
|
||||
console).
|
||||
|
||||
**Proposed words:** **node tools** (Core) for the runtime that serves every module's tools and every seat's
|
||||
verbs on a machine; **console** (Operator and conversation) for the end of it a person or agent uses — the
|
||||
MCP endpoint and its five tools. `mesh-console` retired. The glossary's surfaces entry is rewritten at
|
||||
graduation; the contradiction is removed, not annotated.
|
||||
|
||||
## Change and delivery
|
||||
|
||||
### 6. *gate* — three things (homonym)
|
||||
|
||||
ADR 0136 (*a step gates its module, not the machine*): a failing step of a module's apply stops that
|
||||
module's later steps. ADR 0236: the **gate** on a delivery's first machine — *"healthy three times"*.
|
||||
ADR 0237 and ADR 0238: the **merge gate**, a status a pull request carries (`mesh/merge-gate`). The
|
||||
controller's description of `upgrade` says *"judged there at the gate"*; a wrapped forge's tools say
|
||||
*branch protection*. **Proposed:** *first-machine gate* for ADR 0236's, *merge gate* for the status, and
|
||||
ADR 0136's becomes *a failed step holds its module* (no noun). Bare *the gate* is not used.
|
||||
|
||||
### 7. *ask* — the operator's question, and an entry in the build queue (homonym)
|
||||
|
||||
The glossary: *"**ask** — a request for the operator's input, of a declared kind"* (ADR 0234).
|
||||
`mesh-controller.queue`: *"Every **ask** in the build queue: waiting, in flight … and dead"*;
|
||||
`.cancel`: *"Drop one waiting or dead ask"*; `.clear`: *"Cancel every waiting ask"*. ADR 0234's ask is in
|
||||
58 decision records' worth of prose shared with the ordinary verb *to ask*. **Proposed:** *ask* stays the
|
||||
operator's (Operator and conversation); an entry in the build queue is a **build request** (Change and
|
||||
delivery), and the three verbs' descriptions say so.
|
||||
|
||||
### 8. *tier* — three things (homonym)
|
||||
|
||||
The `topic: the tiers` of 36 decision records, and `repos.md`'s *Tier 0 … 3*: the **layers** of the mesh
|
||||
(node-engine, foundation, controller, surfaces). ADR 0162 and to-be 47: the **steps of a walk**, a module
|
||||
and the modules built against it (*"its builds are asked and registered tier by tier"*). To-be 46: the
|
||||
**levels of authority** of an ask (*"a kind below the tier"*, *"no P2 tier before recovery codes"*).
|
||||
**Proposed:** *layer* for the first (Core); *tier* for the walk's steps (Change and delivery), which is how
|
||||
the tools use it; *assurance level* for the third (Identity and access).
|
||||
|
||||
### 9. *declaration* — what a manifest states, and what the controller sends (homonym)
|
||||
|
||||
The glossary: the node-engine *"receives the node's **declaration**"* — the controller's per-machine
|
||||
document. The glossary again: a module *"**declares** resources"*, and *depends on a seat* is *"derived from
|
||||
the resources it declares"* — the manifest. `mesh-controller.plan` returns *"the declaration the mesh would
|
||||
send"*; the container and service-manager tools say *"what its declaration says"*. *Declaration* is in 106
|
||||
decision records, in both senses. **Proposed:** a manifest **declares** (Module; the noun is *the
|
||||
manifest*), and what the controller sends one machine is that machine's **declaration** (Placement). The
|
||||
verb and the noun then never name the same thing, and *declaration* is not used for a manifest.
|
||||
|
||||
### 10. *control plane* and *controller* (synonym, drift)
|
||||
|
||||
Retired by the glossary on 2026-09-16. Since then: 29 occurrences in 12 to-be designs (`05`, `07`, `08`,
|
||||
`18`, `19`, `26`, `28`, `29`, `30`, `32`, `33`, `01`) and one as-is design; 73 files created after the
|
||||
retirement use it — 36 issue reports, 29 decision records, 6 designs — among them issue 156, titled *moving a consumer's delivery subject
|
||||
stops the control plane*. ADR 0006, the record the word came from, still has it in its
|
||||
title. **Proposed:** *controller* (Core), as decided; the to-be designs are corrected at graduation, which
|
||||
is a link-and-word fix the README's rules allow.
|
||||
|
||||
## The record and its checks
|
||||
|
||||
### 11. *record* — four things (homonym)
|
||||
|
||||
A **decision record** (this repository). **The record** of the mesh — the `records` module that agents
|
||||
search first (*"search the record with the literal text"*), and ADR 0006's *"where the record lives is
|
||||
deliberately open"*. An **upgrade policy** value: `record` means *register the build, send it nowhere*
|
||||
(ADR 0236). **On record**: a seat holder the controller has written down (ADR 0223's *"each on record"*).
|
||||
**Proposed:** *decision record* always qualified in hq; *the record* for the mesh's knowledge base (Operator
|
||||
and conversation, or a domain of its own if the records module grows one); the policy value renamed
|
||||
**hold** — which is also what *held* means for a delivery — and *on record* left as ordinary English.
|
||||
|
||||
### 12. *check* — at least six things (homonym)
|
||||
|
||||
The checks in `00-META/checks/`; a pull request's **merge check**, made of the **merge gate** and the
|
||||
**repository check** (`mesh/repo-check`, ADR 0238); a delivery group's **composed check**
|
||||
(`mesh-controller.delivery-check`); the state `checked` of a delivery; the **self-check** (clash 13); a
|
||||
module's tool named `…_check` (the ssh client's). *Check* is in 92 decision records. **Proposed:** never
|
||||
bare in a governing document; always one of *merge check*, *repository check*, *composed check*,
|
||||
*self-check*, *hq check*. The word is too ordinary to retire, so this one is a writing rule, not a list
|
||||
entry ([04](04-how-the-glossary-is-checked.md) says why it cannot be checked mechanically).
|
||||
|
||||
## Health and repair
|
||||
|
||||
### 13. *self-check* and *doctor* (synonym)
|
||||
|
||||
To-be 45 names the concept **self-check** (8 occurrences) and the verb `doctor` (14); the verb's own
|
||||
description begins *"The self-check (to-be 45 §4)"*. **Proposed:** *self-check* (Health and repair); the
|
||||
verb renamed `self-check`, or kept as `doctor` with the glossary mapping it — a verb name is an identifier.
|
||||
|
||||
### 14. *condition*, *alert*, *problem*, *incident*, *finding* (synonyms)
|
||||
|
||||
The controller's verb `conditions`: *"What is wrong with the mesh now: every open condition"*; to-be 45 says
|
||||
*condition* 72 times. ADR 0006's observability context owns *"health, logs, metrics, **alerts**"*. ADR
|
||||
0224's title: *"a provider that keeps failing a consumer is a **problem** the controller reports"*. The
|
||||
container module's tool is `docker_problems`. *Incident* is in 14 decision records, mostly as *the incident
|
||||
that earned a rule*. *Finding* is in 19, as what a check or a probe found. **Proposed:** *condition*
|
||||
(Health and repair) for an open fact about something wrong; *finding* for what one probe or check returned
|
||||
before it becomes a condition; *incident* kept for a past event that taught a rule (The record); *alert* and
|
||||
*problem* retired for the mesh's own notion. A wrapped dashboard's *alerts* are its own.
|
||||
|
||||
## Connectivity
|
||||
|
||||
### 15. *private network* and *overlay* (synonym)
|
||||
|
||||
The operator, quoted in ADR 0226 (2026-10-06): *"we simply have a private network"*; ADR 0226's title and
|
||||
the `mesh-wireguard` module's role: *the private network*, in 37 decision records. To-be 08 (connectivity)
|
||||
says *overlay* 24 times; *overlay* is in 30 decision records and 13 to-be designs. No tool says either.
|
||||
**Proposed:** *private network* (Connectivity), the operator's word.
|
||||
|
||||
### 16. *packet filter* and *firewall* (synonym)
|
||||
|
||||
The seat every machine holds is `node-packet-filter`, with the verb `rules` (*"The packet filter as this
|
||||
machine enforces it now"*). The nftables module's tool is `firewall_rules`. *Firewall* is in 33 decision
|
||||
records and 13 to-be designs; *packet filter* in 22 and 12. **Proposed:** *packet filter* (Connectivity),
|
||||
after the seat; the module's tool renamed `packet_filter_rules` or described in the seat's word.
|
||||
|
||||
## Operator and conversation
|
||||
|
||||
### 17. *operator*, *the user*, *person* (synonym, partly)
|
||||
|
||||
The glossary's *operator account* entry: *"Not 'the user' (ambiguous with a module's own account)"*. *The
|
||||
user* is in 10 to-be designs, several meaning a bus account (*"the user list"*, the bus server's word), and
|
||||
in 9 decision records. *Operator* is in 125 decision records and the tools of 23 modules; *person* in 91
|
||||
records, meaning a human as against the mesh acting unattended (*"a person's word"*). **Proposed:**
|
||||
*operator* for the person who runs the mesh; *person* for any human acting where the mesh could have; *the
|
||||
user* retired in the mesh's own prose; a bus account is a *bus account* (Identity). A wrapped program's
|
||||
*users* are its own.
|
||||
|
||||
### 18. *agent* — three things (homonym)
|
||||
|
||||
The glossary avoids *agent* for the node-engine because it *"already means two other things here, the build
|
||||
agent and the operator's coding agent"*. The seat every machine holds is `node-build-agent`, held by the
|
||||
`build-agent` module; ADR 0237 calls the role *the build seat*, ADR 0236 *the build machine* (14 decision
|
||||
records). The licence manager's verbs say *"a node's **agent**"* for the coding agent a licence is bound to.
|
||||
A wrapped memory server has *agents* of its own. **Proposed:** *agent* only for a coding agent (the
|
||||
operator's, or one the mesh runs); the build role is the **build seat**, its holder on a machine the
|
||||
**builder** — and the seat renamed when seats are next renamed. *Build machine* retired: any machine may
|
||||
hold the seat.
|
||||
|
||||
## Core
|
||||
|
||||
### 19. *store* — four things (homonym)
|
||||
|
||||
The glossary: **store** — *"the one postgres server"*. ADR 0189's title, *"The store keeps what the
|
||||
records name"*, is about the **artifact store**. Research 015 is about the **object store**. ADR 0006: *"a
|
||||
node reconciles from its own store"* — the machine's local copy of its declaration. **Proposed:** *store*
|
||||
alone means only the foundation's database server (Core); the others are always *artifact store*, *object
|
||||
store*, and the machine's *last declaration*.
|
||||
|
||||
### 20. The glossary's own contradictions
|
||||
|
||||
Recorded in [01](01-the-concepts-in-use.md) and listed here because the fix is the same kind: the console
|
||||
(clash 5); the deprecated broker, which has no seat in its own entry and claims `mesh-broker` in the entry
|
||||
for *claim*; and node tools described with the retired *the host*. **Proposed:** fixed at graduation,
|
||||
in the same change that reorganises the glossary ([05](05-a-glossary-by-domain.md)).
|
||||
|
||||
## Checked and found consistent
|
||||
|
||||
Worth saying, so nobody repeats the search:
|
||||
|
||||
- **catalogue / catalog.** Prose says *catalogue* everywhere (no bare *catalog* in any decision, design or
|
||||
`00-META` file); *catalog* appears only inside identifiers (`mesh-catalog`, `catalog_modules`). That is an
|
||||
identifier, not a clash.
|
||||
- **foundation / substrate.** Of the 10 files created since *substrate* was retired that still use it, 9
|
||||
are decision records and research (allowed to keep their words); the tenth is the glossary, naming it
|
||||
as retired.
|
||||
- **flavor.** Retired; two to-be designs (08, 16) still say it, both predating the retirement.
|
||||
- **operator** in the tools is used consistently for the person, in 28 tools of 23 modules.
|
||||
@@ -0,0 +1,140 @@
|
||||
# 04 — How the glossary is checked
|
||||
|
||||
[`AGENTS.md`](../../AGENTS.md): *"If a document states a rule about the mesh, it says how that rule is
|
||||
verified. An unenforced rule is indistinguishable from a wrong one."* The glossary states two rules — *one
|
||||
name per thing*, and *"a new name for an existing thing lands here first, in the same change that
|
||||
introduces it in code"* — and nothing verifies either. [03](03-the-clashes.md) is what that costs. This
|
||||
document describes a check; it does not build one. Building it follows graduation.
|
||||
|
||||
## What a word list can and cannot catch
|
||||
|
||||
A list of retired words catches **synonyms**: a word the glossary replaced, used again. It cannot catch
|
||||
**homonyms** — *plan*, *gate*, *tier*, *ask*, *store*, *record*, *check* — because the word is right in one
|
||||
sense and wrong in another, and telling them apart is reading, not matching. So the proposal has two
|
||||
parts: a mechanical check for synonyms, and a rule for homonyms that turns each one, once decided, into a
|
||||
synonym the list can hold (*release plan* → *walk*; *build machine* → *build seat*; `ask` in the build
|
||||
queue's verbs → *build request*). A homonym left undecided stays a reviewer's job, and the glossary says
|
||||
so next to the word.
|
||||
|
||||
## Part 1 — the list, kept in the glossary
|
||||
|
||||
The list of retired words lives **in the glossary, in one fixed form**, so there is one source and no
|
||||
second file to drift from it. Every entry that retires words ends with one line:
|
||||
|
||||
> *Not:* ~~control plane~~, ~~substrate~~
|
||||
|
||||
and nothing else in the glossary is struck through. Today the glossary marks retired words three ways
|
||||
(struck through, *"Replaces x"*, *"Not x"*); graduation moves all of them to this line.
|
||||
|
||||
Each struck word may carry a **scope**, in brackets after it, saying where it is retired:
|
||||
|
||||
- *(hq)* — in this repository's governing documents only;
|
||||
- *(tools)* — in the descriptions of the mesh's tools and seat verbs only;
|
||||
- no scope — both.
|
||||
|
||||
The scope exists because some words are wrong in one place and right in the other: *the user* is retired
|
||||
in hq prose, but a wrapped identity provider's tool must say *user*.
|
||||
|
||||
An entry may also carry an **identifier** line naming code that still has the old name, and the issue that
|
||||
tracks its rename:
|
||||
|
||||
> *Identifier until renamed:* `mesh-host` — the repository, binary and service unit (issue NNN)
|
||||
|
||||
An identifier is allowed inside a code span (`` `mesh-host` ``) and nowhere else; when the issue resolves,
|
||||
the line goes and so does the allowance.
|
||||
|
||||
## Part 2 — `00-META/checks/words.py`, over this repository
|
||||
|
||||
**Reads** the glossary's *Not:* lines and *Identifier* lines. **Scans** the documents that tell somebody
|
||||
what to do — the same set `records.py` calls *governing*: `00-META/` (the glossary's own *Not:* lines
|
||||
excluded), `03-DESIGN/01-to-be/`, `AGENTS.md` and `README.md` — plus `03-DESIGN/00-as-is/`, whose words
|
||||
should be today's even where its facts are yesterday's.
|
||||
|
||||
**Fails** on a retired word (of scope *hq* or none) in running prose. It **ignores**:
|
||||
|
||||
- code spans and code blocks, which hold identifiers;
|
||||
- block quotes and text in quotation marks, which quote somebody — the operator, a tool, an older
|
||||
record — and must quote them faithfully;
|
||||
- link targets, which are file names, and file names are immutable when they are a decision record's;
|
||||
- `02-DECISIONS/` entirely, and `01-RESEARCH/` and `04-ISSUES/` written before the check's start date
|
||||
— records keep their words, and research and issues observe.
|
||||
|
||||
**For research and issues written after the start date** the check applies the same rule. An issue report
|
||||
quoting a log or a tool keeps the quotation; its own prose uses today's words. This is a choice for
|
||||
graduation, listed in [00](00-overview.md); the reason to include them is that issue reports are the
|
||||
largest single source of drift found (36 of the 73 files that say *control plane* since its retirement).
|
||||
|
||||
**The reverse rule.** A to-be design that defines a word in the glossary's form — a bolded word followed by
|
||||
a dash at the start of a definition — must find that word as a head word in the glossary. This is how
|
||||
*"a new name lands here first"* gets checked, and it would have caught *condition*, *healer* and
|
||||
*data class* arriving in to-be 43 and 45 with no entry.
|
||||
|
||||
**The uniqueness rule.** No head word appears in two entries, and no head word is also struck through in
|
||||
another entry. This would have caught *release*: today a verb of `mesh-delivery`, and the retired *release
|
||||
plan*.
|
||||
|
||||
**What it would fail on today** — the check is proposed because these are real, and per
|
||||
[`00-META/checks/README.md`](../../00-META/checks/README.md) a check must fail on something real before
|
||||
it passes:
|
||||
|
||||
| Retired word | Where, today |
|
||||
|---|---|
|
||||
| control plane | 29 occurrences in 12 to-be designs; one as-is design |
|
||||
| the host (for the node-engine) | 34 to-be designs, and the glossary's own node tools entry |
|
||||
| release plan, change plan | to-be 45, 47 |
|
||||
| flavor | to-be 08, 16 |
|
||||
| the user | 10 to-be designs (several are a bus account) |
|
||||
|
||||
Each is either fixed at graduation or, where it is a quotation, put in quotation marks — which is the
|
||||
check doing its job, making a quotation look like one.
|
||||
|
||||
## Part 3 — the same list, over the catalogue's tool descriptions
|
||||
|
||||
An agent meets the mesh's words most often in tool descriptions: 535 module tools and the verbs of 20 seats
|
||||
today. Nothing compares them with the glossary, and four of them say *the host*.
|
||||
|
||||
**Where it runs.** In the catalogue repository's own repository check (`mesh/repo-check`, ADR 0238), which
|
||||
already reads every changed manifest. A changed manifest's tool descriptions and its seat's verb
|
||||
descriptions are matched against the *Not:* words of scope *tools* or none. A finding fails the check, as
|
||||
everything does on the mesh's repositories (a warning blocks a merge the same as a failure there, [issue
|
||||
293](../../04-ISSUES/293-a-warning-on-a-required-check-blocked-the-merge/00-report.md), so a warning-only mode
|
||||
is not available and is not proposed).
|
||||
|
||||
**Where the list comes from.** The catalogue cannot read this repository at build time without a new
|
||||
dependency. Two options, for graduation:
|
||||
|
||||
1. **A copy, checked.** The catalogue keeps a copy of the list, and `words.py` here fails when the copy in
|
||||
the catalogue's trunk differs from the glossary. Simple; two repositories change for one word, which is
|
||||
honest about what a retired word costs.
|
||||
2. **The list as an artifact.** This repository's merge publishes the list to the artifact store, and the
|
||||
catalogue's check reads the newest. One source; one more thing that must be up for a catalogue merge.
|
||||
|
||||
The first is recommended: it fails loudly in the right place, and adds no runtime dependency.
|
||||
|
||||
**Vendor words.** A module wrapping a program describes that program's objects in its own words — an
|
||||
identity provider's *users*, a media manager's *releases*, a flow editor's *deploy*. The list holds only
|
||||
the mesh's own retired words, and a word that is also a common vendor word (*user*, *release*, *deploy*)
|
||||
is never retired with scope *tools*. That keeps the check from crying wolf, which
|
||||
`00-META/checks/README.md` names as the way a check gets suppressed.
|
||||
|
||||
**On the running mesh, later.** The descriptions an agent actually sees are the ones served, which may lag
|
||||
the catalogue's trunk. A probe in the self-check could compare the controller's `tools` verb with the same
|
||||
list and raise a condition. That is a second place for the same rule and is not proposed until the first
|
||||
has run.
|
||||
|
||||
## Part 4 — homonyms, by rule
|
||||
|
||||
For a word the glossary marks *homonym* (*plan*, *gate*, *tier*, *store*, *record*, *check*, *ask*,
|
||||
*agent*), the entry lists each sense with its qualified form and its domain, and the writing rule is: **a
|
||||
homonym is never bare in a governing document; it is always the qualified form.** This is not
|
||||
machine-checked — a word list cannot tell *the gate* that means a first-machine gate from one that means
|
||||
the merge gate — and the glossary says so next to the rule, as AGENTS.md requires: *"checked by review;
|
||||
the reviewer looks for the bare word in the diff."* Where a homonym is resolved by renaming one sense, the
|
||||
old sense moves to the *Not:* line and becomes mechanical.
|
||||
|
||||
## What it costs
|
||||
|
||||
- One Python file of the size of `cycle.py`, run by `merge-check.sh`.
|
||||
- A one-time correction of the governing documents it fails on, made in the graduation change.
|
||||
- A copy of the list in the catalogue, and a few lines in its repository check.
|
||||
- One rule for writers: a retired word may be quoted, never used.
|
||||
@@ -0,0 +1,101 @@
|
||||
# 05 — A glossary by domain
|
||||
|
||||
How [`00-META/glossary.md`](../../00-META/glossary.md) would be organised once the domains in
|
||||
[02](02-the-domains.md) are decided. Described only: the glossary changes in the graduation change, with
|
||||
the decision record that adopts the domains, and not before.
|
||||
|
||||
## What is wrong with its shape today
|
||||
|
||||
- **Its sections are a history, not a map.** *The operator's machine* holds node tools, bundle, kept region
|
||||
and installed / holding because they arrived with research 018, not because they belong together; node
|
||||
tools is a Core concept and kept region a Module one.
|
||||
- **It has no home for a new word.** A writer adding *condition* would not know which section it goes in,
|
||||
and so it went in none.
|
||||
- **Retired words are marked three ways**, so no program can read them ([04](04-how-the-glossary-is-checked.md)).
|
||||
- **It is one page for 33 entries**; with the roughly 50 words [01](01-the-concepts-in-use.md) found
|
||||
missing, it is about 85, and one flat list of 85 is read by nobody.
|
||||
|
||||
## The proposed shape
|
||||
|
||||
One file, as now — it stays the single authority, and a reader searches one page. Its sections are the
|
||||
domains, in the order of [02](02-the-domains.md) (most upstream first), preceded by two short sections.
|
||||
|
||||
### 1. How to read this page
|
||||
|
||||
What a domain is, in two sentences; that a word is defined once, in the domain that owns it; that other
|
||||
domains may use it but not change it; and the forms of the *Not:* and *Identifier* lines the check reads.
|
||||
|
||||
### 2. Words every domain uses
|
||||
|
||||
A short **shared kernel** — the handful of words with one meaning everywhere, owned by no single domain
|
||||
and changed only by a decision record: *mesh*, *machine* (or *node*, clash 1), *module*, *seat*, *operator*,
|
||||
*person*. Each points to the domain where its detail lives. Kept deliberately short: a word that only one
|
||||
domain refines belongs to that domain.
|
||||
|
||||
### 3. One section per domain
|
||||
|
||||
Each section opens with a fixed header, then its entries:
|
||||
|
||||
- **Purpose** — one sentence, from [02](02-the-domains.md).
|
||||
- **Owned by** — the context, module or seat that records its concepts (*the controller's `inventory`
|
||||
context*; *the `mesh-delivery` module*; *every machine's `node-backup` seat*).
|
||||
- **Upstream of / downstream of** — the domains, by name.
|
||||
- **Decided by** — the decision records that define the domain's words, so a reader can go from a word
|
||||
to why.
|
||||
|
||||
Each **entry** keeps today's prose form and gains at most three fixed lines:
|
||||
|
||||
- the definition, in plain sentences, with its record cited (as now);
|
||||
- *Not:* ~~retired word~~, ~~another~~ *(scope)* — the words it replaced;
|
||||
- *Identifier until renamed:* `old-name` — what code still carries the old name, and the issue that
|
||||
tracks the rename.
|
||||
|
||||
A word a domain uses but does not own is not repeated there; the domain's section may list it under *Uses*
|
||||
with a link, so a reader of one section sees its whole vocabulary without the definition being copied.
|
||||
|
||||
### 4. Homonyms
|
||||
|
||||
One section at the end for the words that mean different things in different domains — *plan*, *gate*,
|
||||
*tier*, *store*, *record*, *check*, *ask*, *agent*, *release*. For each, a small table: the sense, its
|
||||
qualified form, the domain that owns it. This is the page a reader lands on from a search for a bare
|
||||
word, and it says the rule beside the table: never bare in a governing document; checked by review.
|
||||
|
||||
### 5. How this page is kept
|
||||
|
||||
Today's section, extended: a new word lands here first, in the domain that owns it; a word moves domain
|
||||
only with a decision record; a retired word goes on a *Not:* line and nowhere else; and `words.py`
|
||||
checks the three rules it can ([04](04-how-the-glossary-is-checked.md)).
|
||||
|
||||
## Where today's entries would go
|
||||
|
||||
| Today's entry | Domain |
|
||||
|---|---|
|
||||
| node, control-node, operator account | shared kernel (machine); Placement (operator account); Core (control-node) |
|
||||
| controller, mesh-controller, node-engine, foundation, store, bus, the deprecated broker | Core |
|
||||
| package, artifact | Change and delivery |
|
||||
| seat, depends on a seat, installed / holding | Placement |
|
||||
| claim, provision (as declared), invokes, bundle, kept region | Module |
|
||||
| provision (as resolved) | Provisioning |
|
||||
| channel / intake, ask, operator message / input, reference, console | Operator and conversation |
|
||||
| node tools | Core |
|
||||
| delivery, delivery group, delivery plan, mesh-delivery, walk | Change and delivery |
|
||||
| ~~master / slave~~, ~~hub / peer~~, ~~flavor~~ | *Not:* lines on *controller* and *setting* |
|
||||
|
||||
And the sections that are empty today and would be filled from the records that already define their
|
||||
words: **Identity and access** (credential, secret, vault, grant, bus account, licence, binding, proof —
|
||||
ADRs 0143, 0183, 0225, 0234); **Health and repair** (condition, probe, signal, watchdog, self-check, healer,
|
||||
drill, hand-act — to-be 45, ADRs 0227, 0231, 0240); **Data** (data class, backup, restore point, stream
|
||||
snapshot — to-be 43, ADRs 0233, 0235); **Connectivity** (private network, resolver, uplink, packet
|
||||
filter, reach — ADRs 0117, 0138, 0223, 0226).
|
||||
|
||||
## What derives from it
|
||||
|
||||
- **The decision index.** The records' `topic:` (*the mesh*, *the tiers*, *what runs on it*, *building
|
||||
it*, *checking it*, *how we work*) predates the domains and partly overlaps them. Whether a record also
|
||||
names its domain — a new frontmatter field, and so a schema change — is left for graduation. It would let
|
||||
`words.py` scope a word by domain, and `index.py` print the reading order per domain.
|
||||
- **The constitution page.** The mesh injects a page derived from `how-we-build.md` into design sessions
|
||||
(playbook 05). A derived glossary page per domain could be injected the same way, so an agent starts
|
||||
with the words; that is a separate decision, not proposed here.
|
||||
- **Tool descriptions.** Once a domain owns a word, a module describing that concept in a tool uses it; the
|
||||
check in [04](04-how-the-glossary-is-checked.md) holds them to the retired half, and review to the rest.
|
||||
Reference in New Issue
Block a user