Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba7c9e7f17 |
+25
-99
@@ -69,8 +69,7 @@ is listed under [Homonyms](#homonyms), with the qualified form each domain uses.
|
|||||||
**Recorded in** the catalogue, one manifest per module. **Upstream of** every other domain; its words
|
**Recorded in** the catalogue, one manifest per module. **Upstream of** every other domain; its words
|
||||||
are a published vocabulary, fixed by the manifest's schema. **Decided by** ADR 0040, 0126, 0174, 0188,
|
are a published vocabulary, fixed by the manifest's schema. **Decided by** ADR 0040, 0126, 0174, 0188,
|
||||||
0207, 0236, 0262.
|
0207, 0236, 0262.
|
||||||
**Uses:** module, seat, config value (Config), provision (Provisioning), data class (Data), health (Health
|
**Uses:** module, seat, provision (Provisioning), data class (Data), health (Health and repair).
|
||||||
and repair).
|
|
||||||
|
|
||||||
- **manifest** — the file a module is defined by (`module.json`): what it is, what it provides and
|
- **manifest** — the file a module is defined by (`module.json`): what it is, what it provides and
|
||||||
requires, the seats it claims, the resources it declares, its tools, its data and its health. Say
|
requires, the seats it claims, the resources it declares, its tools, its data and its health. Say
|
||||||
@@ -84,9 +83,18 @@ and repair).
|
|||||||
it guards: the `mesh-controller`, `postgres` and `nats` modules claim the `mesh-controller`,
|
it guards: the `mesh-controller`, `postgres` and `nats` modules claim the `mesh-controller`,
|
||||||
`mesh-store` and `mesh-broker` seats (ADR 0079,
|
`mesh-store` and `mesh-broker` seats (ADR 0079,
|
||||||
ADR 0116).
|
ADR 0116).
|
||||||
|
- **setting** — a value a manifest declares and an assignment gives, one of the two ways a node varies
|
||||||
|
a module (ADR 0174).
|
||||||
|
What a "flavor" once varied is a setting or a separate module.
|
||||||
|
*Not:* ~~flavor~~
|
||||||
|
- **preference** — a setting whose manifest gives it a default, because its value is true of the
|
||||||
|
software and only tuned per node: a font size, a width
|
||||||
|
(ADR 0262).
|
||||||
|
A setting with no default is the operator's own value: a domain, an identity.
|
||||||
|
*Not:* ~~tunable~~ (hq)
|
||||||
- **kept region** — a marked block in a managed file the mesh writes *into*, where the operator's own
|
- **kept region** — a marked block in a managed file the mesh writes *into*, where the operator's own
|
||||||
lines survive every send and are given back when the module goes (ADR 0174). The other way a node
|
lines survive every send and are given back when the module goes (ADR 0174). The other way a node
|
||||||
varies a module, besides a config value; a **managed** file's marked block is one (Provisioning).
|
varies a module.
|
||||||
- **bundle** — the artifact a module's own code is built into — its tools, a seat's implementation, a
|
- **bundle** — the artifact a module's own code is built into — its tools, a seat's implementation, a
|
||||||
daemon — in any language the mesh has a toolchain for; never an image. A **tools bundle** speaks MCP to
|
daemon — in any language the mesh has a toolchain for; never an image. A **tools bundle** speaks MCP to
|
||||||
the tool runner. One module may declare several
|
the tool runner. One module may declare several
|
||||||
@@ -103,55 +111,6 @@ and repair).
|
|||||||
(ADR 0236).
|
(ADR 0236).
|
||||||
The controller's verb `upgrade` shows it.
|
The controller's verb `upgrade` shows it.
|
||||||
|
|
||||||
## Config — the values someone may change
|
|
||||||
|
|
||||||
**Purpose.** To hold, check and resolve every value a module reads that someone may change, and to say
|
|
||||||
where each resolved value came from. **Recorded by** the `mesh-config` module, in its buckets on the bus,
|
|
||||||
with its store as the history behind them. **Upstream of** Provisioning, which places the values;
|
|
||||||
downstream of Module and Placement. **Decided by** ADR 0262, 0277, 0348.
|
|
||||||
**Uses:** module, node, manifest (Module), assignment (Placement), provision (Provisioning), proposal
|
|
||||||
(Operator and conversation).
|
|
||||||
|
|
||||||
- **config value** — anything a module reads that someone may change: a font size, a domain, an address.
|
|
||||||
A module declares every one it reads under `config` in its manifest, with a type, a description,
|
|
||||||
validation, whether it is trusted, optionally the predefined key it falls back to, and a default or
|
|
||||||
`required`; it lands in a template file as `${config:<key>}` or is read by the module's code at runtime.
|
|
||||||
It resolves from four sources, the most specific winning: the default in the manifest; **mesh config**,
|
|
||||||
the value of the predefined key it falls back to for the whole mesh; **node config**, that key's value
|
|
||||||
on one node; and **module-assignment config**, the module's own value on one node. There is no module
|
|
||||||
value for the whole mesh. *Config* is the concept, the verb (`config`) and the manifest field
|
|
||||||
(ADR 0348). Mesh config is a source level, the value set for the whole mesh; `mesh-config` is the module
|
|
||||||
that keeps every level. The controller holds, mirrors and resolves no config value (ADR 0348 §9).
|
|
||||||
Older records and documents say "setting" for a config value and "settings" for the concept; new writing
|
|
||||||
says config value and config. The word goes on this entry's *Not:* line once the documents in force that
|
|
||||||
still use it in running prose are reworded, which is issue 683; until then it is checked by review. The
|
|
||||||
manifest field and the verb "settings" are kept as aliases until every module has moved (ADR 0348 §1,
|
|
||||||
issue 630), and are named on the line below with the rest once issue 683 is done.
|
|
||||||
*Identifier until renamed:* `takes-settings`, `${setting:}` — manifest forms kept as aliases until every
|
|
||||||
module has moved to their config names (ADR 0348 §1, issue 630).
|
|
||||||
What a "flavor" once varied is a config value or a separate module.
|
|
||||||
*Not:* ~~flavor~~
|
|
||||||
- **predefined key** — a key of the catalogue's `predefined.json`, the fixed list of keys for which mesh
|
|
||||||
config and node config hold values, each with its type, description, validation and whether it is
|
|
||||||
trusted, such as `font-size`. A config value may name the predefined key it falls back to, of its own
|
|
||||||
type; one that names none resolves from its default and the module's own value only. The list is the
|
|
||||||
catalogue build's: a change to it is validated with every manifest naming a key, and removing a key still
|
|
||||||
named or still holding a value is refused (ADR 0348).
|
|
||||||
- **trusted** — said of a config value that decides what runs or who can reach what. At every level it is
|
|
||||||
set only at the controller's terminal or through `config` with propose, on the operator's Approve; a
|
|
||||||
module value that falls back to a trusted predefined key is itself trusted (ADR 0277, ADR 0348 §8). Not
|
|
||||||
the trusted sender of an operator message (see [Homonyms](#homonyms)).
|
|
||||||
- **preference** — a config value whose manifest gives it a default, because its value is true of the
|
|
||||||
software and only tuned per node: a font size, a width
|
|
||||||
(ADR 0262).
|
|
||||||
A config value with no default is `required`: the operator's own value, such as a domain or an
|
|
||||||
identity, and while nothing sets it the module's files are not written (ADR 0348).
|
|
||||||
*Not:* ~~tunable~~ (hq)
|
|
||||||
- **`mesh-config`** — the module that owns every config value, and not the source level mesh config: it
|
|
||||||
holds the seat `mesh-config` once for the mesh, validates, takes a trusted value only from the
|
|
||||||
controller's terminal or the operator's Approve, keeps the history with who set it and why, and resolves
|
|
||||||
the four sources (ADR 0348).
|
|
||||||
|
|
||||||
## Core — the mesh's own machinery
|
## Core — the mesh's own machinery
|
||||||
|
|
||||||
**Purpose.** To keep the controller, the bus, the store and every node's engine running and agreed, so
|
**Purpose.** To keep the controller, the bus, the store and every node's engine running and agreed, so
|
||||||
@@ -231,10 +190,9 @@ every other domain has something to run on. **Recorded by** the controller and t
|
|||||||
**Purpose.** To decide, send and apply what each node runs, and to say why.
|
**Purpose.** To decide, send and apply what each node runs, and to say why.
|
||||||
**Recorded by** the controller's `inventory` database. **Upstream of** Provisioning, Connectivity, Data
|
**Recorded by** the controller's `inventory` database. **Upstream of** Provisioning, Connectivity, Data
|
||||||
and Health and repair. **Decided by** ADR 0100, 0126, 0176, 0181, 0207, 0221, 0252, 0261.
|
and Health and repair. **Decided by** ADR 0100, 0126, 0176, 0181, 0207, 0221, 0252, 0261.
|
||||||
**Uses:** node, machine, module, seat, manifest (Module), config value (Config).
|
**Uses:** node, machine, module, seat, setting (Module), manifest (Module).
|
||||||
|
|
||||||
- **assignment** — a module put on a node. Its config values on that node (module-assignment config,
|
- **assignment** — a module put on a node, with the settings that node gives it.
|
||||||
Config) are `mesh-config`'s, never part of what the controller records (ADR 0348 §9).
|
|
||||||
- **pending assignment** — an assignment of a module whose build is still running, kept, and made by the
|
- **pending assignment** — an assignment of a module whose build is still running, kept, and made by the
|
||||||
controller when that build registers the module, or ended with why when it does not
|
controller when that build registers the module, or ended with why when it does not
|
||||||
(ADR 0261).
|
(ADR 0261).
|
||||||
@@ -269,7 +227,7 @@ and Health and repair. **Decided by** ADR 0100, 0126, 0176, 0181, 0207, 0221, 02
|
|||||||
(ADR 0181).
|
(ADR 0181).
|
||||||
Not a name a manifest carries.
|
Not a name a manifest carries.
|
||||||
- **agent account** — the login every coding agent on a node runs as, when the node names one of its own;
|
- **agent account** — the login every coding agent on a node runs as, when the node names one of its own;
|
||||||
stated on the node record at the controller's terminal, never by a verb or a config value. Empty means agents
|
stated on the node record at the controller's terminal, never by a verb or a setting. Empty means agents
|
||||||
run as the operator account. It cannot become root without a person, and the node-engine judges that on
|
run as the operator account. It cannot become root without a person, and the node-engine judges that on
|
||||||
every look (ADR 0266).
|
every look (ADR 0266).
|
||||||
- **account group** — a group of the machine's group database that a module puts an account in, by
|
- **account group** — a group of the machine's group database that a module puts an account in, by
|
||||||
@@ -280,21 +238,15 @@ and Health and repair. **Decided by** ADR 0100, 0126, 0176, 0181, 0207, 0221, 02
|
|||||||
|
|
||||||
## Provisioning — one module serving another
|
## Provisioning — one module serving another
|
||||||
|
|
||||||
**Purpose.** To resolve which module serves a provision for which consumer, to wire the two, and to
|
**Purpose.** To resolve which module serves a provision for which consumer, and to wire the two.
|
||||||
place every value a module needs into its files on its node. **Recorded by** the controller and
|
**Recorded by** the controller. **Upstream of** Data; downstream of Module, Placement and Identity.
|
||||||
`mesh-provisioner`. **Upstream of** Data; downstream of Module, Placement, Config and Identity.
|
**Decided by** ADR 0027, 0084, 0138, 0225, 0230, 0263.
|
||||||
**Decided by** ADR 0027, 0084, 0138, 0225, 0230, 0263, 0349.
|
**Uses:** module, seat, credential (Identity and access).
|
||||||
**Uses:** module, seat, node-engine (Core), declaration (Placement), config value (Config), credential
|
|
||||||
and vault (Identity and access).
|
|
||||||
|
|
||||||
- **provision** — a service one module `provides` and others `require`; the mesh resolves a provider
|
- **provision** — a service one module `provides` and others `require`; the mesh resolves a provider
|
||||||
and wires the two with an endpoint and a credential. A provision is a service you offer, a seat is a
|
and wires the two with an endpoint and a credential. A provision is a service you offer, a seat is a
|
||||||
role you occupy, and the two meet where a seat delivers a provision: occupying the seat is what makes
|
role you occupy, and the two meet where a seat delivers a provision: occupying the seat is what makes
|
||||||
a module *the* provider of it.
|
a module *the* provider of it.
|
||||||
Every value a module needs is a provision from the domain that owns it: placement from the controller,
|
|
||||||
config values from `mesh-config`, shared secrets from the vault, a consumer's values from the module
|
|
||||||
providing it, an item of a collection from its contributor. A module says only what it needs and where
|
|
||||||
it lands (ADR 0349).
|
|
||||||
- **provider** and **consumer** — the module that provides a provision, and the module that requires
|
- **provider** and **consumer** — the module that provides a provision, and the module that requires
|
||||||
it. Which of several providers serves a consumer is resolved
|
it. Which of several providers serves a consumer is resolved
|
||||||
(ADR 0084).
|
(ADR 0084).
|
||||||
@@ -312,28 +264,6 @@ and vault (Identity and access).
|
|||||||
node seat `node-mounts`, as a mount unit and an automount unit, mounted on access (ADR 0263).
|
node seat `node-mounts`, as a mount unit and an automount unit, mounted on access (ADR 0263).
|
||||||
- **occasional source** — a share on a device that is not a node and comes and goes, such as a USB disk;
|
- **occasional source** — a share on a device that is not a node and comes and goes, such as a USB disk;
|
||||||
its absence is a state, *not present*, never a fault (ADR 0263).
|
its absence is a state, *not present*, never a fault (ADR 0263).
|
||||||
- **mesh-provisioner** — the module that places provisions on the nodes: it holds the seat
|
|
||||||
`mesh-provisioner` once for the mesh, keeping which domain answers which kind of placeholder, what each
|
|
||||||
module on each node needs, what is applied where and the items of every collection, and the seat
|
|
||||||
`node-provisioner` on every node, which its provisioner client serves (ADR 0349).
|
|
||||||
- **provisioner client** — mesh-provisioner's part on one node. For each module there it reads the
|
|
||||||
placeholders of its template files, records the needs, watches each owner's values for the node, fills a
|
|
||||||
template only once every value is there, has the node-engine write the file through a narrow local verb,
|
|
||||||
makes the program take the change as the file declares (`restart-on`, `reload-on`, `read-on-use`), and
|
|
||||||
reports `prov.applied`. It runs as a service with a bus account of its own, never in the tool runner
|
|
||||||
(ADR 0349).
|
|
||||||
- **collection** — a provision with many providers. The **collector**, a module that takes additions from
|
|
||||||
others (a shell's snippets, a bar's blocks), requires it; each **contributor** ships its **item** as a
|
|
||||||
template in its own repository and provides it. The provisioner client fills the collector's template
|
|
||||||
from the items of the contributors placed on its node, and an item goes when its contributor leaves the
|
|
||||||
node (ADR 0349).
|
|
||||||
- **owned** — a placed file that is the mesh's whole: the provisioner writes it back whenever it differs.
|
|
||||||
It is one of three answers a manifest gives for each file it places (`owner-at-runtime`): **owned**,
|
|
||||||
**seed** or **managed**. Whichever it is, the file has one writer: the node-engine writes it only on the
|
|
||||||
provisioner client's word (ADR 0349).
|
|
||||||
- **seed** — a placed file the provisioner writes once; from then on it is the program's.
|
|
||||||
- **managed** — a placed file of which only its named keys or a marked block (a kept region, Module) are
|
|
||||||
the mesh's; the program keeps the rest.
|
|
||||||
|
|
||||||
## Identity and access — who may do what
|
## Identity and access — who may do what
|
||||||
|
|
||||||
@@ -348,7 +278,7 @@ and the operator act. **Recorded by** the controller's `identity` and `licences`
|
|||||||
- **secret** — a credential or other value the vault keeps sealed and the node-engine unseals into a
|
- **secret** — a credential or other value the vault keeps sealed and the node-engine unseals into a
|
||||||
file at apply (ADR 0085).
|
file at apply (ADR 0085).
|
||||||
- **secret family** — a module's own secrets declared as one name ending in `-*`; each member is the prefix
|
- **secret family** — a module's own secrets declared as one name ending in `-*`; each member is the prefix
|
||||||
and a name (`smb-password-<source>`, one per source the module's config values name), given by its full name
|
and a name (`smb-password-<source>`, one per source the module's settings name), given by its full name
|
||||||
and never made by the mesh
|
and never made by the mesh
|
||||||
(ADR 0283).
|
(ADR 0283).
|
||||||
- **vault** — the module that owns every secret (`mesh-vault`,
|
- **vault** — the module that owns every secret (`mesh-vault`,
|
||||||
@@ -492,7 +422,7 @@ becomes a message). **Decided by** ADR 0227, 0231, 0240, 0252, 0283.
|
|||||||
running session, started before, does not have that group yet. Said by the node-engine as the module's
|
running session, started before, does not have that group yet. Said by the node-engine as the module's
|
||||||
resource of kind `account`; it clears at the first look after a new login (ADR 0252).
|
resource of kind `account`; it clears at the first look after a new login (ADR 0252).
|
||||||
- **waiting** — a resource's health when its module's tool check says it waits for the operator: a named own
|
- **waiting** — a resource's health when its module's tool check says it waits for the operator: a named own
|
||||||
secret or config value of the module, not given yet, without which a part cannot work. Not a fault: the
|
secret or setting of the module, not given yet, without which a part cannot work. Not a fault: the
|
||||||
controller checks it and says it as the condition `needs-operator`, naming the act, and the first-node gate
|
controller checks it and says it as the condition `needs-operator`, naming the act, and the first-node gate
|
||||||
reads it as *waits for a person*
|
reads it as *waits for a person*
|
||||||
(ADR 0283).
|
(ADR 0283).
|
||||||
@@ -616,7 +546,7 @@ asking, never the act. **Decided by** ADR 0152, 0175, 0234, 0259, 0272.
|
|||||||
published for that asker alone. The only thing an asker acts on (ADR 0259).
|
published for that asker alone. The only thing an asker acts on (ADR 0259).
|
||||||
- **proposal** — a change an agent, or anyone the bus admits, puts forward through a verb and that takes
|
- **proposal** — a change an agent, or anyone the bus admits, puts forward through a verb and that takes
|
||||||
effect only on the operator's warrant, bound to the exact thing shown: a shared instruction section (ADR
|
effect only on the operator's warrant, bound to the exact thing shown: a shared instruction section (ADR
|
||||||
0274), a trusted config value (ADR 0277, ADR 0348).
|
0274), a trusted setting's layer (ADR 0277).
|
||||||
A proposal changes nothing by itself; declined, expired or refused, it is discarded.
|
A proposal changes nothing by itself; declined, expired or refused, it is discarded.
|
||||||
- **approval mark** — a tool's or verb's declaration in its manifest (`needs-approval`) that each call to it runs
|
- **approval mark** — a tool's or verb's declaration in its manifest (`needs-approval`) that each call to it runs
|
||||||
only on the operator's warrant for that one call, with its exact arguments; the tool runner that serves it, or
|
only on the operator's warrant for that one call, with its exact arguments; the tool runner that serves it, or
|
||||||
@@ -633,7 +563,7 @@ asking, never the act. **Decided by** ADR 0152, 0175, 0234, 0259, 0272.
|
|||||||
build seat's holder, whose seat name `node-build-agent` is an identifier to rename.
|
build seat's holder, whose seat name `node-build-agent` is an identifier to rename.
|
||||||
- **instruction section** — one named section of the managed instruction file, which every agent session on the
|
- **instruction section** — one named section of the managed instruction file, which every agent session on the
|
||||||
nodes it is for reads first, as the mesh's word: set at the controller's terminal in the agent module's
|
nodes it is for reads first, as the mesh's word: set at the controller's terminal in the agent module's
|
||||||
config, or **proposed** by an agent and made active on each node only by the operator's warrant, which that node
|
settings, or **proposed** by an agent and made active on each node only by the operator's warrant, which that node
|
||||||
proves itself (ADR 0274). A hand-over between sessions is one.
|
proves itself (ADR 0274). A hand-over between sessions is one.
|
||||||
- **personal rule** — one short text in the operator's own words about how the operator wants their agent
|
- **personal rule** — one short text in the operator's own words about how the operator wants their agent
|
||||||
to work with them, registered for the operator (the **operator scope** of the agent module) and rendered
|
to work with them, registered for the operator (the **operator scope** of the agent module) and rendered
|
||||||
@@ -648,10 +578,10 @@ asking, never the act. **Decided by** ADR 0152, 0175, 0234, 0259, 0272.
|
|||||||
## Media — what a person watches, listens to and reads
|
## Media — what a person watches, listens to and reads
|
||||||
|
|
||||||
**Purpose.** To find, fetch and file copies of the works a person watches, listens to and reads, each in
|
**Purpose.** To find, fetch and file copies of the works a person watches, listens to and reads, each in
|
||||||
the library its kind names. **Recorded by** the `media-importer` module's config values and its memory of what
|
the library its kind names. **Recorded by** the `media-importer` module's settings and its memory of what
|
||||||
it was told, and the servarr apps' own libraries. **Upstream of** nothing. **Decided by** ADR 0295, 0296,
|
it was told, and the servarr apps' own libraries. **Upstream of** nothing. **Decided by** ADR 0295, 0296,
|
||||||
0302.
|
0302.
|
||||||
**Uses:** module, seat, config value (Config).
|
**Uses:** module, seat, setting (Module).
|
||||||
|
|
||||||
- **content** — a work a person watches, listens to or reads: a film, an album and its tracks, an
|
- **content** — a work a person watches, listens to or reads: a film, an album and its tracks, an
|
||||||
episode, a book, a session of a sport event. It is known by an identity from a catalogue outside the
|
episode, a book, a session of a sport event. It is known by an identity from a catalogue outside the
|
||||||
@@ -662,7 +592,7 @@ it was told, and the servarr apps' own libraries. **Upstream of** nothing. **Dec
|
|||||||
- **media release** — one copy of a work an engine can fetch, such as an NZB or a video. Downloaded, it
|
- **media release** — one copy of a work an engine can fetch, such as an NZB or a video. Downloaded, it
|
||||||
sits in the downloads folder, not yet filed. ADR 0302 says *release*.
|
sits in the downloads folder, not yet filed. ADR 0302 says *release*.
|
||||||
- **library** — one folder of one kind, filed by one importer: the media-importer's, named in its
|
- **library** — one folder of one kind, filed by one importer: the media-importer's, named in its
|
||||||
config, or a servarr app's. Several libraries may hold one kind, as TV Shows and Anime both hold
|
settings, or a servarr app's. Several libraries may hold one kind, as TV Shows and Anime both hold
|
||||||
series.
|
series.
|
||||||
- **media file** — a file on disk together with its metadata: its kind, the fields that identify the
|
- **media file** — a file on disk together with its metadata: its kind, the fields that identify the
|
||||||
work, and what part of the work the file is. It is what the media-importer takes.
|
work, and what part of the work the file is. It is what the media-importer takes.
|
||||||
@@ -782,10 +712,6 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical.
|
|||||||
| | a question someone must answer | **issue** | The record |
|
| | a question someone must answer | **issue** | The record |
|
||||||
| deploy | the per-node part of a delivery plan | **deploy plan** | Change and delivery |
|
| deploy | the per-node part of a delivery plan | **deploy plan** | Change and delivery |
|
||||||
| | a wrapped program's own deploy | its own word | — |
|
| | a wrapped program's own deploy | its own word | — |
|
||||||
| managed | a placed file of which only named keys or a marked block are the mesh's | **managed** (`owner-at-runtime`) | Provisioning |
|
|
||||||
| | a file the mesh writes, such as the agent's instruction file or `managed_settings` | the file's own name, or *a file the mesh places* | — |
|
|
||||||
| trusted | a config value that decides what runs or who can reach what | **trusted** config value | Config |
|
|
||||||
| | a sender on the operator's own list | **trusted** sender, its message an **operator message** | Operator and conversation |
|
|
||||||
|
|
||||||
## How this page is kept
|
## How this page is kept
|
||||||
|
|
||||||
|
|||||||
+1
-26
@@ -1,10 +1,9 @@
|
|||||||
---
|
---
|
||||||
status: canonical
|
status: canonical
|
||||||
updated: 2026-10-16
|
updated: 2026-10-11
|
||||||
derives: the constitution page
|
derives: the constitution page
|
||||||
decisions:
|
decisions:
|
||||||
- "ADR 0020"
|
- "ADR 0020"
|
||||||
- "ADR 0391"
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# How we build
|
# How we build
|
||||||
@@ -173,30 +172,6 @@ quietly stop being true, and nobody will learn that from a document.
|
|||||||
Not test-driven development as a blanket rule — a test written first against undiscovered
|
Not test-driven development as a blanket rule — a test written first against undiscovered
|
||||||
behaviour asserts a guess. The obligation is that every decision has a defender.
|
behaviour asserts a guess. The obligation is that every decision has a defender.
|
||||||
|
|
||||||
### Tests run at the lowest level that proves them, within a time budget
|
|
||||||
|
|
||||||
Three levels, by how much real system a test uses (ADR 0391):
|
|
||||||
|
|
||||||
| Level | Uses | Budget | Runs |
|
|
||||||
|---|---|---|---|
|
|
||||||
| **Unit** | one piece of logic alone: no database, network, bus, running service or other process | well under a second per test | locally, the tests of what changed, while working; and in the forge's checks |
|
|
||||||
| **Integration** | the real thing beside it: a database, the bus, a catalogue tree | the repository's whole suite in seconds, never over sixty | only in the forge's checks, once per push |
|
|
||||||
| **End to end** | the whole mesh, or a lab mesh, from the outside | — | only when the operator asks |
|
|
||||||
|
|
||||||
- **Test each behaviour at the lowest level that can prove it.** A defect found higher up gets a test at the
|
|
||||||
lowest level that reproduces it, before its fix.
|
|
||||||
- **A test that needs longer than a second, or a database, the network or a service, is not a unit test.**
|
|
||||||
- **A suite over sixty seconds is a defect with its own issue**: it is made faster or split, not accepted.
|
|
||||||
- **Never run a merge check, a throwaway database or an integration suite locally.** The forge's checks do,
|
|
||||||
on the builder.
|
|
||||||
- **A report names its tests and how long they took**, so a test over its budget is seen when it is added.
|
|
||||||
|
|
||||||
### Tests within a time budget — how it was earned
|
|
||||||
|
|
||||||
On 2026-10-16 a feature's fixing agents ran the catalogue's whole merge check (about ten minutes), a
|
|
||||||
throwaway database and a locally built gate during local development. Each round cost tens of minutes and
|
|
||||||
caught neither real failure; the forge's checks found both.
|
|
||||||
|
|
||||||
### A report is read from the system, never from what asked for it
|
### A report is read from the system, never from what asked for it
|
||||||
|
|
||||||
The same rule as the two above, pointed at reporting rather than at verification. **Anything
|
The same rule as the two above, pointed at reporting rather than at verification. **Anything
|
||||||
|
|||||||
@@ -30,15 +30,6 @@ An idea arrives in one of two forms, and the first step differs:
|
|||||||
2. **Ask the operator to set it up.** A few questions, one at a time, each answerable with a choice and
|
2. **Ask the operator to set it up.** A few questions, one at a time, each answerable with a choice and
|
||||||
carrying a recommendation: what comes first, what is out of scope, which options must be tried, what
|
carrying a recommendation: what comes first, what is out of scope, which options must be tried, what
|
||||||
done looks like. Three to five questions is usual; the answers are the effort's first findings.
|
done looks like. Three to five questions is usual; the answers are the effort's first findings.
|
||||||
- **Check every option against the mesh's own rules before offering it.** An option that breaks one
|
|
||||||
(the core values in [`mission.md`](../mission.md), among them *the mesh owns the truth* and
|
|
||||||
*sovereignty: external dependencies are deliberate and few*; the rules in
|
|
||||||
[`how-we-build.md`](../how-we-build.md); and everything between modules over the bus, research 036) is
|
|
||||||
dropped, or offered only with the rule it breaks named. A recommendation the operator has to argue back
|
|
||||||
costs a version.
|
|
||||||
- **Explain each question with a concrete picture** in the operator's words: what they would see, do or
|
|
||||||
lose under each option. No internal names (a record number, a verb, a word the glossary lacks) without
|
|
||||||
what it is beside it.
|
|
||||||
3. **Take a number.** `knowledge-base.reserve` with `kind: research` and `for`: the effort's title. The number
|
3. **Take a number.** `knowledge-base.reserve` with `kind: research` and `for`: the effort's title. The number
|
||||||
is spent whether or not the effort is ever proposed; one never proposed is withdrawn after a week. Never
|
is spent whether or not the effort is ever proposed; one never proposed is withdrawn after a week. Never
|
||||||
pick one by hand.
|
pick one by hand.
|
||||||
@@ -57,25 +48,10 @@ An idea arrives in one of two forms, and the first step differs:
|
|||||||
lists them and gives the difference between two. Until issue 844 is delivered, the knowledge base
|
lists them and gives the difference between two. Until issue 844 is delivered, the knowledge base
|
||||||
takes a new version of an accepted, active effort only as a progressive insight: give `insight`, saying
|
takes a new version of an accepted, active effort only as a progressive insight: give `insight`, saying
|
||||||
what the effort held before the new finding, and mark the finding in the text with its date.
|
what the effort held before the new finding, and mark the finding in the text with its date.
|
||||||
- **Propose a version per settled set, not per answer.** While the operator answers a run of questions,
|
|
||||||
or while experiments run, keep the answers and findings in the session's save point and propose once
|
|
||||||
when the set is settled. Each version is reviewed and resent whole, so a version per answer multiplies
|
|
||||||
the reviews.
|
|
||||||
- **Pre-check before proposing**, against what the review sends back most: every record, issue or design
|
|
||||||
the text names is in `links`; work put off names the issue that tracks it (an acceptance test is not
|
|
||||||
put-off work: it is what the build proves, step 6); each figure is given as measured (a range, not a
|
|
||||||
rounded claim); no word on a glossary *Not:* line.
|
|
||||||
- **Try at the cheapest level that answers the question.** A program's own behaviour (a library, a
|
|
||||||
server, a protocol) is tried in process, on the machine's loopback, in minutes. Lab runs (about 12 to
|
|
||||||
16 minutes fresh) are for the mesh's own code; before that code exists, a lab run tests nothing an
|
|
||||||
in-process test does not, and its lab scenario is written as the build's acceptance test instead.
|
|
||||||
6. **Settle the direction with the operator.** When the questions are answered, write `05-direction.md`:
|
6. **Settle the direction with the operator.** When the questions are answered, write `05-direction.md`:
|
||||||
the proposed decisions in a few lines each, the options rejected and why, and the build's acceptance
|
the proposed decisions in a few lines each, the options rejected and why, what is left open. Ask the
|
||||||
tests: what the build must prove before it is done, carried by its milestones (playbook
|
operator to confirm or change it, one point at a time. Then the effort graduates through playbook
|
||||||
[04](04-build-handoff.md)). Nothing else is left open: each question closes by a test, by a decision the
|
[02](02-graduation.md).
|
||||||
effort records with its reason (a small design limit is the lead's), or by the operator. Ask the
|
|
||||||
operator to confirm or change the direction, one point at a time, then propose it once. Then the effort
|
|
||||||
graduates through playbook [02](02-graduation.md).
|
|
||||||
|
|
||||||
## Bounds and models
|
## Bounds and models
|
||||||
|
|
||||||
@@ -124,9 +100,6 @@ and why, is the more expensive half to rediscover.
|
|||||||
|
|
||||||
The rules on an effort are the knowledge base's: `propose` refuses one that breaks a rule that judges one
|
The rules on an effort are the knowledge base's: `propose` refuses one that breaks a rule that judges one
|
||||||
record (the module's table test holds one case per rule), and the rules that judge the whole record set run
|
record (the module's table test holds one case per rule), and the rules that judge the whole record set run
|
||||||
after every acceptance and raise a condition when one fails. The habits of steps 2, 5 and 6 (options checked
|
after every acceptance and raise a condition when one fails. That this repository holds no effort is
|
||||||
against the rules, one version per settled set, the cheapest level, nothing left open) are the lead's, read by
|
`records.py`'s `no-records` check, on every pull request. An active effort with no new version for seven
|
||||||
the reviewer; of the pre-check, `propose` refuses a link to nothing and a retired word, and the review returns
|
days is the smell of research left behind: its lead closes or continues it.
|
||||||
a record named but not linked, an untracked deferral and a figure not as measured. That this repository holds
|
|
||||||
no effort is `records.py`'s `no-records` check, on every pull request. An active effort with no new version
|
|
||||||
for seven days is the smell of research left behind: its lead closes or continues it.
|
|
||||||
|
|||||||
@@ -23,16 +23,6 @@ about an hour, and said to the operator if it runs past.
|
|||||||
say which, in writing, before proceeding.
|
say which, in writing, before proceeding.
|
||||||
2. **Record the decisions** (below, *Writing a decision record*): one record per choice that could be
|
2. **Record the decisions** (below, *Writing a decision record*): one record per choice that could be
|
||||||
reversed on its own, not one record for the whole effort.
|
reversed on its own, not one record for the whole effort.
|
||||||
- **Write them together, not one after another.** Reserve every number first, then propose each record
|
|
||||||
as soon as it is written, without waiting for the review of the one before; the reviews run side by
|
|
||||||
side, and the operator's asks for the records that need them arrive together. A record that
|
|
||||||
`rests-on` or `extends` a sibling is proposed once that sibling is accepted.
|
|
||||||
- **Take the clauses from the confirmed direction** and cite the effort (`cites`, `"research NNN"`) for
|
|
||||||
the evidence instead of retyping its findings: a record's Context holds the few facts its decision
|
|
||||||
rests on, with the effort named for the rest.
|
|
||||||
- **Pre-check each record before proposing it**, as for research (playbook [01](01-research.md), step
|
|
||||||
5): every record, issue or design it names is in `links`; each deferral names its issue; each figure
|
|
||||||
is given as measured; no word on a glossary *Not:* line.
|
|
||||||
3. **Write the design.** Create the document under `03-DESIGN/01-to-be/` with frontmatter:
|
3. **Write the design.** Create the document under `03-DESIGN/01-to-be/` with frontmatter:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -46,8 +36,6 @@ about an hour, and said to the operator if it runs past.
|
|||||||
---
|
---
|
||||||
```
|
```
|
||||||
|
|
||||||
The design lists the direction's acceptance tests: what the build proves before it is done.
|
|
||||||
|
|
||||||
4. **Hand it to the work breakdown.** The design goes on through playbook [04](04-build-handoff.md):
|
4. **Hand it to the work breakdown.** The design goes on through playbook [04](04-build-handoff.md):
|
||||||
milestones, issues, and each milestone built as one feature step (playbook [07](07-feature-branches.md)).
|
milestones, issues, and each milestone built as one feature step (playbook [07](07-feature-branches.md)).
|
||||||
5. **Close the effort.** `knowledge-base.propose` the effort again, whole, with `status: graduated` and a
|
5. **Close the effort.** `knowledge-base.propose` the effort again, whole, with `status: graduated` and a
|
||||||
@@ -153,6 +141,4 @@ record (its module's table test holds one case per rule), and the four rules tha
|
|||||||
changes, an accepted record extending a superseded one) run after every acceptance and raise a condition
|
changes, an accepted record extending a superseded one) run after every acceptance and raise a condition
|
||||||
when one fails. In this repository, `records.py` checks that a design's `decisions:` entries and every
|
when one fails. In this repository, `records.py` checks that a design's `decisions:` entries and every
|
||||||
"ADR NNNN" in the text are well formed, and that no record is written here; `index.py` checks the reading
|
"ADR NNNN" in the text are well formed, and that no record is written here; `index.py` checks the reading
|
||||||
order's six topics, which the knowledge base reads. The three habits of graduating step 2 (side by side, clauses
|
order's six topics, which the knowledge base reads.
|
||||||
from the direction, the pre-check) are the lead's, read by the reviewer; `propose` refuses a link to nothing,
|
|
||||||
a deferral no issue tracks and a retired word, and the review returns a record named but not linked.
|
|
||||||
|
|||||||
@@ -28,11 +28,10 @@ A design becomes **milestones**, and each milestone becomes **issues**:
|
|||||||
there; if it is not, write it before changing it. Building against an undocumented as-is is how a shipped
|
there; if it is not, write it before changing it. Building against an undocumented as-is is how a shipped
|
||||||
behaviour gets lost.
|
behaviour gets lost.
|
||||||
4. **Break it into milestones.** Write them into the design, in a section *Milestones*: for each, its number,
|
4. **Break it into milestones.** Write them into the design, in a section *Milestones*: for each, its number,
|
||||||
its one-sentence outcome, the acceptance tests of the design it proves, the repositories it touches, and
|
its one-sentence outcome, the repositories it touches, and what it depends on. Order them so each is
|
||||||
what it depends on. Order them so each is usable as soon as it is delivered, the smallest useful one
|
usable as soon as it is delivered, the smallest useful one first.
|
||||||
first.
|
5. **Ask the operator to confirm the milestones**, in a short table: number, outcome, repositories, the
|
||||||
5. **Ask the operator to confirm the milestones**, in a short table: number, outcome, the acceptance tests it
|
parts each repository builds. Change what they change.
|
||||||
proves, repositories, the parts each repository builds. Change what they change.
|
|
||||||
6. **Open the issues.** For each confirmed milestone, `issue-tracker.open` one issue per repository part, its
|
6. **Open the issues.** For each confirmed milestone, `issue-tracker.open` one issue per repository part, its
|
||||||
title the symptom or capability in plain words, its report naming the design, the milestone and the
|
title the symptom or capability in plain words, its report naming the design, the milestone and the
|
||||||
decisions it builds with; link the order with `depends-on`. Write the issue numbers into the milestone's
|
decisions it builds with; link the order with `depends-on`. Write the issue numbers into the milestone's
|
||||||
@@ -62,5 +61,5 @@ Read by the lead and the reviewer today; a check in hq's merge-check is tracked
|
|||||||
issues; an in-progress design without one is the smell of building without a breakdown.
|
issues; an in-progress design without one is the smell of building without a breakdown.
|
||||||
- Every issue a milestone names exists in the tracker (`issue-tracker.get`), and an issue in `fixing` names
|
- Every issue a milestone names exists in the tracker (`issue-tracker.get`), and an issue in `fixing` names
|
||||||
its milestone in its report.
|
its milestone in its report.
|
||||||
- A milestone whose issues are all `resolved` has had its delivery plan done; its outcome sentence and
|
- A milestone whose issues are all `resolved` has had its delivery plan done; its outcome sentence is proven on
|
||||||
acceptance tests are proven on the mesh before the next milestone starts.
|
the mesh before the next milestone starts.
|
||||||
|
|||||||
@@ -61,8 +61,7 @@ never into the running one, unless it blocks the running one.
|
|||||||
hold, and the patterns to copy (file:line);
|
hold, and the patterns to copy (file:line);
|
||||||
- what not to touch, and what lands beside it in other repositories;
|
- what not to touch, and what lands beside it in other repositories;
|
||||||
- the local facts: the worktree, the branch, the check commands, a temporary directory for tests outside
|
- the local facts: the worktree, the branch, the check commands, a temporary directory for tests outside
|
||||||
the home (`TMPDIR`), and the unit tests to run (never a database server: tests that need one are
|
the home (`TMPDIR`), a throwaway database server if the store tests need one.
|
||||||
integration tests, which the forge's checks run).
|
|
||||||
When the reading is large, a read-only agent on the smaller model answers the lead's exact questions with
|
When the reading is large, a read-only agent on the smaller model answers the lead's exact questions with
|
||||||
file:line, and the lead writes the file from its answers.
|
file:line, and the lead writes the file from its answers.
|
||||||
5. **Move the issues to `fixing`**, `by` naming the feature's agent for that repository.
|
5. **Move the issues to `fixing`**, `by` naming the feature's agent for that repository.
|
||||||
@@ -73,8 +72,7 @@ never into the running one, unless it blocks the running one.
|
|||||||
issues one after another, committing each locally with a message naming the issue ("Keep the assignments
|
issues one after another, committing each locally with a message naming the issue ("Keep the assignments
|
||||||
on the bus (issue 652)"). It is not replaced per issue: the lead continues the same agent (by its id) with
|
on the bus (issue 652)"). It is not replaced per issue: the lead continues the same agent (by its id) with
|
||||||
the next instruction, so its context is paid for once.
|
the next instruction, so its context is paid for once.
|
||||||
- **Unit tests only, of what changed, each well under a second** (how-we-build §5, ADR 0391). Each issue's
|
- **Unit tests only.** Each issue's first test fails before its change and passes after; `gofmt`, `go vet`
|
||||||
first test fails before its change and passes after; `gofmt`, `go vet`
|
|
||||||
and the repository's unit tests stay green. The integration tests (`merge-check.sh` with the store and the
|
and the repository's unit tests stay green. The integration tests (`merge-check.sh` with the store and the
|
||||||
bus) wait for phase 3.
|
bus) wait for phase 3.
|
||||||
- **Nothing is pushed** and no pull request is opened in this phase. Never land on a red check: run the
|
- **Nothing is pushed** and no pull request is opened in this phase. Never land on a red check: run the
|
||||||
|
|||||||
@@ -26,15 +26,18 @@ one delivery**. Everything before the push is local and fast.
|
|||||||
need a decision or a second repository stops here and becomes a feature.
|
need a decision or a second repository stops here and becomes a feature.
|
||||||
2. **Move the issue to `fixing`** with `by` as who@node.
|
2. **Move the issue to `fixing`** with `by` as who@node.
|
||||||
3. **Build on a local branch** `fix/<issue>-<slug>`, in a worktree of its own branched from `main`. Write the
|
3. **Build on a local branch** `fix/<issue>-<slug>`, in a worktree of its own branched from `main`. Write the
|
||||||
test that fails today first; make the change; keep `gofmt`, `go vet` and the unit tests of what changed green
|
test that fails today first; make the change; keep `gofmt`, `go vet` and the repository's unit tests green.
|
||||||
(each well under a second; never a merge check or a database locally: how-we-build §5, ADR 0391).
|
|
||||||
Commit, naming the issue. For a playbook or design edit, run the repository's own checks (in hq,
|
Commit, naming the issue. For a playbook or design edit, run the repository's own checks (in hq,
|
||||||
`sh merge-check.sh`).
|
`sh merge-check.sh`).
|
||||||
4. **One review of the local commit, before anything is pushed** (a reviewer that did not write it, larger
|
4. **One review of the local commit, before anything is pushed** (a reviewer that did not write it, larger
|
||||||
model; at most 3 rounds, as playbook 07; from round 2 only what is wrong). The reviewer's findings go back to the same agent that wrote the fix, continued by
|
model; at most 3 rounds, as playbook 07; from round 2 only what is wrong). The reviewer's findings go back to the same agent that wrote the fix, continued by
|
||||||
its id, so the fix keeps its context. A playbook or design edit of a few lines may skip the reviewer: the
|
its id, so the fix keeps its context. A playbook or design edit of a few lines may skip the reviewer: the
|
||||||
operator's word on the pull request is its review.
|
operator's word on the pull request is its review.
|
||||||
5. **Push once and open the pull request.** The forge's merge checks run the integration tests. A failed check
|
5. **Push the branch, try it, then open the pull request.** `mesh-controller.try` with the repository and the
|
||||||
|
branch runs the merge check in the check's own toolchain before any status is set; open the pull request
|
||||||
|
only once it passes. A local run never stands in for it: the check's containers carry other tools than the
|
||||||
|
nodes (a test that called util-linux `flock -E` passed on a node and failed on BusyBox's in the check). The
|
||||||
|
forge's merge checks run the integration tests. A failed check
|
||||||
goes back to the same agent with the failure, and the reviewer reads only the change it makes.
|
goes back to the same agent with the failure, and the reviewer reads only the change it makes.
|
||||||
6. **Mark it ready** (`mesh/ready` and `ready at <full sha>`) once the operator's word is given; mesh-delivery
|
6. **Mark it ready** (`mesh/ready` and `ready at <full sha>`) once the operator's word is given; mesh-delivery
|
||||||
merges it when its checks pass.
|
merges it when its checks pass.
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
layer: to-be
|
layer: to-be
|
||||||
status: in-progress
|
status: in-progress
|
||||||
code: [mesh-controller, mesh-catalog modules/mesh-delivery]
|
code: [mesh-controller, mesh-catalog modules/mesh-delivery]
|
||||||
updated: 2026-10-16
|
updated: 2026-10-13
|
||||||
decisions:
|
decisions:
|
||||||
- "ADR 0382"
|
|
||||||
- "ADR 0350"
|
- "ADR 0350"
|
||||||
- "ADR 0335"
|
- "ADR 0335"
|
||||||
- "ADR 0323"
|
- "ADR 0323"
|
||||||
@@ -372,12 +371,6 @@ only once it is built.
|
|||||||
group's members puts the composed check out of date: the group reads `checking` with the reason, and the
|
group's members puts the composed check out of date: the group reads `checking` with the reason, and the
|
||||||
composed check runs again once a member is judged again. Checked by mesh-delivery's
|
composed check runs again once a member is judged again. Checked by mesh-delivery's
|
||||||
`TestAGroupsComposedCheckGoesOutOfDateOnAMergeThatIsNotItsMember` and `TestARebasedMemberIsComposedAgainNotHeld`.
|
`TestAGroupsComposedCheckGoesOutOfDateOnAMergeThatIsNotItsMember` and `TestARebasedMemberIsComposedAgainNotHeld`.
|
||||||
- **Each member's own check reads its siblings** (ADR 0382): the group's other open members into a base of
|
|
||||||
the same name are read beside a member's own check at their head merged onto their base, and a mesh-controller
|
|
||||||
sibling's merge judges it, so changes that are only consistent together pass their own checks. The controller
|
|
||||||
learns the siblings from mesh-delivery's `groups`; the verdict names each one. A sibling's new head, close or
|
|
||||||
base move puts that verdict out of date, and the merge tool merges such a member only when
|
|
||||||
`mesh/delivery-group` passed at the heads read and every sibling head read is reviewed.
|
|
||||||
- **Delivering**: in order. A member waits in `published` until the one before is `delivered` or `covered`.
|
- **Delivering**: in order. A member waits in `published` until the one before is `delivered` or `covered`.
|
||||||
A member published while its group's composed check is asked and not answered waits there for the answer;
|
A member published while its group's composed check is asked and not answered waits there for the answer;
|
||||||
one held because that check had not passed is *lifted* back to `published` once it passes or warns for the
|
one held because that check had not passed is *lifted* back to `published` once it passes or warns for the
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
# Release 57: config and provisioning
|
|
||||||
|
|
||||||
This branch carries the work of design 57 (ADR 0348, ADR 0349) in this repository. Each package
|
|
||||||
merges here through its own reviewed pull request; the branch reaches main as one pull request, in one
|
|
||||||
delivery group with the branch of the same name in mesh-controller, mesh-host, mesh-sdk, mesh-catalog
|
|
||||||
and hq, after a rehearsal in the lab. This file is deleted by the last commit before that pull request.
|
|
||||||
Reference in New Issue
Block a user