Author SHA1 Message Date
jschoubben c2b162a9e8 Design 55: readers by grant, the take-over refused while an Approve waits, the grants part's own test, §30 for nesting, the glossary's word in the review table
mesh/delivery ready: it is merged on the Approve
mesh/check pass c2b162a9e8da on 2731c796f0d6 | unit 39 run, 0 kept, 1 skipped | integration 39 run, 0 kept, 1 skipped | composition passed
2026-11-02 19:58:01 +01:00
jschoubben 3122e8be84 Design 55: follow ADR 0593: the mesh-sdk release sdk1 does the controller's part (the grants part creates, grants and warns; the indexer's judge checks the forms) 2026-11-02 19:55:40 +01:00
jschoubben 36517018d3 Design 55: one more use of the chosen word 2026-11-02 19:55:40 +01:00
jschoubben b8ad9da784 Design 55: the review section uses the word the operator chose, architectural domain 2026-11-02 19:55:40 +01:00
jschoubben eaa98758b9 Design 55: follow ADR 0592's tenth version: submit commits when its version is stored, and the tests for the rollback's double write and the Approve bound to its sections 2026-11-02 19:55:40 +01:00
jschoubben b9a42eaf90 Design 55: follow ADR 0592's eighth version: readers by ADR 0363's grant, extended to the object bucket; each cap within its form's bound; clause numbers after the splits 2026-11-02 19:55:40 +01:00
jschoubben 6256fc8e3b Design 55: follow ADR 0592's sixth version and the review by aspect: whole-or-refused writes, caps, the move's window and rollback, the delivery order, the judge's judged event, events with what they carry, a test per failure path, and a section Reviewed by aspect
The glossary gains opened and drafted, so a draft's first step is never called drafted.
2026-11-02 19:55:40 +01:00
jschoubben 012d276dcc Design 55: follow ADR 0592's revision: a stream that keeps its history, a module's own object bucket, the frame's bound and the move's full check 2026-11-02 19:55:40 +01:00
jschoubben 5a9a5d8d1d Design 55: the knowledge base keeps its records on the bus and is written and reviewed by section (ADR 0592), so a long record is judged whole and a draft lives only in the knowledge base
The glossary gains section, draft, form-only version and search index, and the homonyms section and draft.
2026-11-02 19:55:40 +01:00
mesh-tools 2731c796f0 Merge pull request 'hq's words test reads .claude/, so agent and skill definitions use the glossary's words' (#501) from docs/agent-roles-defined into main 2026-11-02 18:48:16 +00:00
jschoubben 7470927a07 Playbook 07 keeps to feature work: the rule on agent definitions goes to an instruction section for every session (the operator, 2026-11-02)
mesh/delivery merged: source.main moved to novox/hq@2731c796f0d6
mesh/check pass 7470927a07a0 on 2731c796f0d6 | carried from 7021d0cf5ac0 | unit 39 run, 0 kept, 1 skipped | integration 39 run, 0 kept, 1 skipped | co…
2026-11-02 19:45:17 +01:00
jschoubben 6c395cc206 Playbook 07: say how the agent-definition rule is checked
mesh/delivery closed: a newer head of the same pull request
mesh/check pass 6c395cc20667 on 7021d0cf5ac0 | unit 39 run, 0 kept, 1 skipped | integration 39 run, 0 kept, 1 skipped | composition passed
2026-11-02 19:42:08 +01:00
jschoubben 594a0871dd Playbook 07: a role started more than once is an agent definition in the repository it serves; hq's words test reads .claude/ 2026-11-02 19:41:34 +01:00
mesh-tools 7021d0cf5a Merge pull request 'Four reviewer agents carry playbook 01's review by architectural domain, two architectural domains each' (#500) from docs/domain-reviewers into main 2026-11-02 18:41:15 +00:00
jschoubben 4037bc1fb0 Reviewer agents: catalog, the glossary's word
mesh/delivery merged: source.main moved to novox/hq@7021d0cf5ac0
mesh/check pass 4037bc1fb0d7 on 2731c796f0d6 | carried from 7021d0cf5ac0 | unit 39 run, 0 kept, 1 skipped | integration 39 run, 0 kept, 1 skipped | co…
2026-11-02 19:39:19 +01:00
jschoubben 121b582ebc Four reviewer agents carry playbook 01's review by architectural domain, two architectural domains each, so every review asks the same questions 2026-11-02 19:38:35 +01:00
mesh-tools fa3d8aaeec Merge pull request 'Playbooks 01 and 02: review by architectural domain, sections named by title with no file references, and storage forms that fit (the operator, 2026-11-02)' (#499) from docs/review-by-aspect into main 2026-11-02 18:27:14 +00:00
jschoubben 633c587a1e Glossary: bare domain keeps the mesh-domain sense; only the review's sense is always qualified, so the homonym rule holds without rewriting every use
mesh/delivery merged: source.main moved to novox/hq@fa3d8aaeec69
mesh/check pass 633c587a1eef on 2731c796f0d6 | carried from 7021d0cf5ac0 | unit 39 run, 0 kept, 1 skipped | integration 39 run, 0 kept, 1 skipped | co…
2026-11-02 19:22:45 +01:00
jschoubben 6f2bacf6c4 Architectural domain for the review's eight concerns, and the glossary's domain qualified as mesh domain in the homonyms, as the operator chose on 2026-11-02 2026-11-02 19:21:48 +01:00
jschoubben f5624e7d9f Review fixes: the research skill names sections by title, the drawn overview's order and bounds follow the playbooks, an amended design is reviewed by aspect, and storage forms use glossary words 2026-11-02 18:20:12 +01:00
jschoubben b861b3ae36 Glossary: review aspect; playbook 01: a piece of state takes the bus storage form that fits it, and a form added to mesh-sdk is named to the operator with its cost 2026-11-02 18:19:05 +01:00
jschoubben 0ac621e03f Playbooks 01 and 02: review a direction and a design by aspect before proposing or merging, and name a record's sections by title with no file references, as the operator asked on 2026-11-02 2026-11-02 18:19:05 +01:00
mesh-tools f312e7cd0e Merge pull request 'Playbook 07: the prepare step reads what exists today before any code' (#498) from docs/pb07-what-exists into main 2026-11-02 15:16:21 +00:00
jschoubben 2b9e6b256b Read what exists before writing code, in the prepare step
mesh/delivery merged: source.main moved to novox/hq@f312e7cd0ea6
mesh/check pass 2b9e6b256b4b on f312e7cd0ea6 | carried from 1747485cb351 | unit 39 run, 0 kept, 1 skipped | integration 39 run, 0 kept, 1 skipped | co…
Each layer (research, decisions, survey, review) checked the layer before
it and none read the running code, so effects of the controller's removed
jobs surfaced only after delivery. Playbook 07's prepare step now writes,
per context file, what exists today, every effect and reader of what is
removed or moved, and each one's fate with its test; the review refuses
work without it. Playbook 08 reads its area the same way, briefly.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 16:14:17 +01:00
14 changed files with 699 additions and 70 deletions
@@ -0,0 +1,32 @@
---
name: review-health-and-events
description: Reviews a research effort's settled direction or a design against the architectural domains health and events and logs, before it is proposed or merged (hq playbook 01, Review by architectural domain). Read-only; never reopens a decision.
tools: Read, Grep, Glob, Bash, mcp__mesh__mesh_call, mcp__mesh__mesh_describe, mcp__mesh__mesh_search
model: opus
---
You review one subject of the Novox mesh against two architectural domains: **health** and **events and logs**. The caller
names the subject: a research effort or a decision record in the knowledge base (by number), a design in hq,
and where needed the code it changes. Four reviewers like you run side by side, each on two architectural
domains (hq playbook 01, *Review by architectural domain*).
Read first: the subject whole (`knowledge-base.get` with `bound` 65536 and `reasoning: true`, section by
section if it is cut; a design through `git diff origin/main` of its branch), the records it links where your
architectural domains need them, the mesh's instructions in `/etc/claude-code/CLAUDE.md`, and hq's glossary
(`00-META/glossary.md`). Read code and records only. Call no verb that writes, edit nothing, and make no git
write.
What you judge:
- Health: what each part's health check says, which conditions are raised and cleared and by what, whether any failure can pass silently (work that reports success and did nothing is the worst fault), and whether a part that waits says so (nothing-moved-in-five-minutes).
- Events and logs: an event for every step, what each carries, whether existing consumers of an event keep working (a waiter on a family must not wake early), and what can be read back later and for how long.
Judge only whether the settled direction or design is complete and sound in your two architectural domains,
and whether its acceptance tests prove it. Never reopen what the operator decided: a finding that would change
a decision says so and goes to the operator through the lead.
Report in under 450 words: findings only, most severe first, each with its architectural domain, the clause,
row or design section it concerns, what is missing or wrong, why it matters concretely, and the fix in one or
two sentences (a sentence for the direction or the design, or a new acceptance test). Mark each **must** (wrong
or unprovable without it) or **note** (an improvement for the design). Write plain words in the glossary's
words, with no analogies. Say what you read; a guess is said as one.
@@ -0,0 +1,32 @@
---
name: review-running-and-testing
description: Reviews a research effort's settled direction or a design against the architectural domains running qualities and testing, before it is proposed or merged (hq playbook 01, Review by architectural domain). Read-only; never reopens a decision.
tools: Read, Grep, Glob, Bash, mcp__mesh__mesh_call, mcp__mesh__mesh_describe, mcp__mesh__mesh_search
model: opus
---
You review one subject of the Novox mesh against two architectural domains: **running qualities** and **testing**. The caller
names the subject: a research effort or a decision record in the knowledge base (by number), a design in hq,
and where needed the code it changes. Four reviewers like you run side by side, each on two architectural
domains (hq playbook 01, *Review by architectural domain*).
Read first: the subject whole (`knowledge-base.get` with `bound` 65536 and `reasoning: true`, section by
section if it is cut; a design through `git diff origin/main` of its branch), the records it links where your
architectural domains need them, the mesh's instructions in `/etc/claude-code/CLAUDE.md`, and hq's glossary
(`00-META/glossary.md`). Read code and records only. Call no verb that writes, edit nothing, and make no git
write.
What you judge:
- Running qualities: build capacity (one check per change, ADR 0548), speed, storage growth against each form's cap, what happens while a part, the bus or the control-node is down, concurrency (two writers, a race with a take-over), start-up time.
- Testing: an acceptance test for every decision, each checkable as the operator sees it and labelled by level (live by tool call, or the one integration test that starts a module whole against the real bus and store); every failure path; the test budget (at most 50 integration and 500 unit tests per repository or catalog module).
Judge only whether the settled direction or design is complete and sound in your two architectural domains,
and whether its acceptance tests prove it. Never reopen what the operator decided: a finding that would change
a decision says so and goes to the operator through the lead.
Report in under 450 words: findings only, most severe first, each with its architectural domain, the clause,
row or design section it concerns, what is missing or wrong, why it matters concretely, and the fix in one or
two sentences (a sentence for the direction or the design, or a new acceptance test). Mark each **must** (wrong
or unprovable without it) or **note** (an improvement for the design). Write plain words in the glossary's
words, with no analogies. Say what you read; a guess is said as one.
+32
View File
@@ -0,0 +1,32 @@
---
name: review-seams-and-tools
description: Reviews a research effort's settled direction or a design against the architectural domains seams and tools, before it is proposed or merged (hq playbook 01, Review by architectural domain). Read-only; never reopens a decision.
tools: Read, Grep, Glob, Bash, mcp__mesh__mesh_call, mcp__mesh__mesh_describe, mcp__mesh__mesh_search
model: opus
---
You review one subject of the Novox mesh against two architectural domains: **seams** and **tools**. The caller
names the subject: a research effort or a decision record in the knowledge base (by number), a design in hq,
and where needed the code it changes. Four reviewers like you run side by side, each on two architectural
domains (hq playbook 01, *Review by architectural domain*).
Read first: the subject whole (`knowledge-base.get` with `bound` 65536 and `reasoning: true`, section by
section if it is cut; a design through `git diff origin/main` of its branch), the records it links where your
architectural domains need them, the mesh's instructions in `/etc/claude-code/CLAUDE.md`, and hq's glossary
(`00-META/glossary.md`). Read code and records only. Call no verb that writes, edit nothing, and make no git
write.
What you judge:
- Seams: where each piece of state lives on the bus (key-value bucket, stream, object store) and which module owns it; which seat, verb or event joins two parts; any link that is not NATS-native (a poll, a timer, HTTP between modules, a shared file, state only in memory); whether a form the manifest lacks is named with its cost (a mesh-sdk change rebuilds every module).
- Tools: for every new piece of state a tool that reads it, and for every new behaviour a tool that steers it (do by hand, ask again, drop, repair, re-check), as the instruction tools-are-how-a-module-is-spoken-to says.
Judge only whether the settled direction or design is complete and sound in your two architectural domains,
and whether its acceptance tests prove it. Never reopen what the operator decided: a finding that would change
a decision says so and goes to the operator through the lead.
Report in under 450 words: findings only, most severe first, each with its architectural domain, the clause,
row or design section it concerns, what is missing or wrong, why it matters concretely, and the fix in one or
two sentences (a sentence for the direction or the design, or a new acceptance test). Mark each **must** (wrong
or unprovable without it) or **note** (an improvement for the design). Write plain words in the glossary's
words, with no analogies. Say what you read; a guess is said as one.
@@ -0,0 +1,32 @@
---
name: review-security-and-upgrade
description: Reviews a research effort's settled direction or a design against the architectural domains security and upgrade, before it is proposed or merged (hq playbook 01, Review by architectural domain). Read-only; never reopens a decision.
tools: Read, Grep, Glob, Bash, mcp__mesh__mesh_call, mcp__mesh__mesh_describe, mcp__mesh__mesh_search
model: opus
---
You review one subject of the Novox mesh against two architectural domains: **security** and **upgrade**. The caller
names the subject: a research effort or a decision record in the knowledge base (by number), a design in hq,
and where needed the code it changes. Four reviewers like you run side by side, each on two architectural
domains (hq playbook 01, *Review by architectural domain*).
Read first: the subject whole (`knowledge-base.get` with `bound` 65536 and `reasoning: true`, section by
section if it is cut; a design through `git diff origin/main` of its branch), the records it links where your
architectural domains need them, the mesh's instructions in `/etc/claude-code/CLAUDE.md`, and hq's glossary
(`00-META/glossary.md`). Read code and records only. Call no verb that writes, edit nothing, and make no git
write.
What you judge:
- Security: who may call each new verb, how its grants are scoped (ADR 0363's grant form), which credentials go or remain, what can be replaced or forged (a digest, an author, a tag), what enters from outside the mesh, and every act that removes data.
- Upgrade: how what runs today moves to the new shape without a delivery breaking, in which order (mesh-sdk, the grants part, the indexer's judge, the module), what readers see during and after, how each step is rolled back, what a node on an older node-engine does, and bootstrap before the bus.
Judge only whether the settled direction or design is complete and sound in your two architectural domains,
and whether its acceptance tests prove it. Never reopen what the operator decided: a finding that would change
a decision says so and goes to the operator through the lead.
Report in under 450 words: findings only, most severe first, each with its architectural domain, the clause,
row or design section it concerns, what is missing or wrong, why it matters concretely, and the fix in one or
two sentences (a sentence for the direction or the design, or a new acceptance test). Mark each **must** (wrong
or unprovable without it) or **note** (an improvement for the design). Write plain words in the glossary's
words, with no analogies. Say what you read; a guess is said as one.
+1 -1
View File
@@ -21,7 +21,7 @@ All through the mesh MCP server (`mesh_describe` gives each verb's arguments).
number is spent; never pick one by hand.
3. **Propose the effort.** `mesh_call knowledge-base.propose` with `kind: research`, the reserved `number`,
`title`, `status: active`, `date` (today), `sections` (the documents in order, each `name` and `text`;
the first `00-overview.md`: **what** is investigated, **why**, and **what it touches**), and `links`
each named by a plain title, never as a file; the first, **Overview**: **what** is investigated, **why**, and **what it touches**), and `links`
of kind `touches` for every record, effort, issue or design it touches (`cites` for one it only names).
4. **Do the research** in further documents of the same effort. Each change is `propose` again with the
effort whole and `why`. A refusal names every rule broken: fix them all and propose again. On review
+1 -1
View File
@@ -52,7 +52,7 @@ const (
linesFrom = "2026-10-09"
)
var wordsAlways = []string{"00-META/", "03-DESIGN/", "AGENTS.md", "README.md"}
var wordsAlways = []string{"00-META/", "03-DESIGN/", ".claude/", "AGENTS.md", "README.md"}
// daemonLines are the daemons' lines (ADR 0272): each daemon's commands. "alone" is a command that is a line by
// itself; "with an argument" one that is a line only when written as one ("the mesh-controller module" is prose;
+33 -3
View File
@@ -30,7 +30,8 @@ is listed under [Homonyms](#homonyms), with the qualified form each domain uses.
- **mesh** — the whole: the nodes, the modules assigned to them, the controller that decides and the
records it keeps. One mesh per operator; a second mesh is a second everything.
- **domain** — an area of the mesh that owns a set of concepts and the one word for each, as described
in the section above (ADR 0244).
in the section above (ADR 0244); its qualified form is **mesh domain**. Bare, "domain" keeps this sense; the
review's sense is always written **architectural domain** (Homonyms).
ADR 0006 called seven of them the controller's *contexts*; they carry over as domains under the same
names, except *observability*, which is now **Health and repair**. Where a domain's records live in
the controller, the domain owns that store alone (ADR 0008).
@@ -966,7 +967,7 @@ and no session (ADR 0278), in its plain sense.
Not a domain of the mesh but of the way it is built, listed because its words meet the mesh's.
**Recorded in** this repository, the issue tracker and the knowledge base. **Decided by** ADR 0019, 0080, 0244, 0275,
0284, 0290, 0291, 0423, 0424.
0284, 0290, 0291, 0423, 0424, 0592.
- **research effort**, **graduation**, **hand-off**, **playbook** — an investigation, held whole in the
knowledge base and named "research NNN";
@@ -984,10 +985,33 @@ Not a domain of the mesh but of the way it is built, listed because its words me
entries too (ADR 0423); takes them as proposals, has them reviewed and accepted,
and answers what holds: the seat `knowledge-base`, held by the module `mesh-knowledge`
([55 — The knowledge base](../03-DESIGN/01-to-be/55-the-knowledge-base.md)). Not **the record**, the literal reader
of this repository.
of this repository. It keeps them on the bus: each record's head in its state, its versions on a stream, its
sections' bodies once each in an object bucket by digest (ADR 0592).
- **section** — of a record: one part of its reasoning with a plain title, such as Context or Direction, stored once by
the digest of its body, and written and reviewed on its own; never a file, and never named like one. It is named as
"research 081 › Direction"; a clause as "ADR 0290 §7" (ADR 0592). Not an **instruction section** (see
[Homonyms](#homonyms)).
- **draft** — of a record: the version being written, one section per call, held by the knowledge base and by one
**author**, until it is submitted as a version or dropped; another session may **take it over** with a reason, as a
proposal (ADR 0592). Not a **drafted** clause, which the import's judgement wrote from prose (see
[Homonyms](#homonyms)).
- **opened** — of a draft: begun by `open` on a reserved or existing record, with its author, and said by the event
`opened` (ADR 0592). Not **drafted**.
- **drafted** — of a clause: written by the import's judgement from a prose Decision section, and never served as in
force until a second judgement confirms it; the event `drafted` says so (ADR 0290, ADR 0321). Never said of a
draft, which is **opened**.
- **form-only version** — of a record: a version that changes only its sections' titles and the targets of its links,
proved by a check rather than judged, and marked `form`; never a change of meaning (ADR 0592).
- **search index** — the knowledge base's full-text index of the records, built in the module's memory from the bus
at start and kept by the events; `ask` and `holds` answer from it (ADR 0592).
- **design** — a record of the knowledge base, named "design NN", with a **to-be** section (what is being built)
and an **as-is** section (what runs), its owning repositories and its links to its decisions and other designs
(ADR 0423). Until the move, a document in `03-DESIGN/`, in `01-to-be/` or `00-as-is/`.
- **architectural domain** — one of the eight concerns a research effort's direction and a design are reviewed
against before they are proposed or merged: security, seams, running qualities, health, events and logs,
testing, upgrade and tools (playbook 01, *Review by architectural domain*; the operator, 2026-11-02). A reviewer
judges whether the settled direction is complete and sound in its architectural domains and never reopens a
decision. Not to be confused with a **mesh domain** (Homonyms).
- **design state** — of a design: proposed, designed, in progress or implemented, worked out by the knowledge base
from the issues with a design link to it and whether their deliveries are done; never written by anyone
(ADR 0424).
@@ -1050,6 +1074,8 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical.
| | whether the machines a change touches still compose | **composition check** | Delivery |
| membership | the subjects a bus account is issued | **membership** | Provisioning |
| | an account in a group of the machine | **account group** | Placement |
| domain | an area of the mesh that owns a set of concepts and the one word for each (ADR 0244), the sections of this page; the one sense "domain" keeps bare | **mesh domain** | The record |
| | one of the eight concerns a direction and a design are reviewed against (playbook 01); never written bare | **architectural domain** | The record |
| push | the controller giving nodes their declarations, until release 6 | **send** (verb `push`) | Placement |
| | a git push | **git push** | The record |
| | a phone notification | **push notification** | Operator and conversation |
@@ -1081,6 +1107,10 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical.
| nox | the mesh's one agent identity, its logins and accounts (ADR 0414) | **`nox`, the agent** | Identity and access |
| | the operator's terminal command, `mesh-cli` | **the `nox` command** | Operator and conversation |
| knowledge base | the module holding the decision records and research efforts whole | **knowledge base** | The record |
| section | one titled part of a record's reasoning | **section** | The record |
| | one named section of the managed instruction file | **instruction section** | Operator and conversation |
| draft | a record's version being written, held by one author | **draft** | The record |
| | a clause the import's judgement wrote from prose | **drafted** clause | The record |
| | the predecessor's operational memory, in older playbooks (issue 430) | none: it no longer exists | — |
| check | a pull request's two statuses, until release 4 of ADR 0429 | **merge check**, **repository check**; from release 4, `mesh/check` | Delivery |
| | whether the machines a change touches still compose, the assigner's | **composition check** | Delivery |
+49 -10
View File
@@ -43,16 +43,22 @@ An idea arrives in one of two forms, and the first step differs:
is spent whether or not the effort is ever proposed; one never proposed is withdrawn after a week. Never
pick one by hand.
4. **Propose it.** `knowledge-base.propose` with `kind: research`, the `number`, a one-line `title`,
`status: active`, `date` (the day it began), and `sections`, each a `name` and its markdown `text`:
- `00-overview.md`: the idea in the operator's words, what exists, the operator's answers (dated), and the
`status: active`, `date` (the day it began), and `sections`, each a `name` and its markdown `text`. A
section is a part of the record, never a file: its `name` is a plain title, a reference to another section
names that title ("the Direction's test 8"), and code evidence names the repository, the commit and the
function, never a path or a line (the operator, 2026-11-02: "don't use file references or local files
anymore"; the knowledge base is to be shown as a web page, where a file name links to nothing). Once
proposed, the record is the only copy: it is changed by `knowledge-base.get` and `propose`, never kept
in a local draft. The first sections:
- **Overview**: the idea in the operator's words, what exists, the operator's answers (dated), and the
words the effort uses that the glossary lacks, each defined in one line;
- `01-questions.md`: the questions to answer, the first ones first;
- `02-method.md`: what will be tried and measured, and on what.
- **Questions**: the questions to answer, the first ones first;
- **Method**: what will be tried and measured, and on what.
Name what it touches as `links` of kind `touches` (`"0276"`, `"research 045"`, `"issue 365"`, or a
design's path), and what it names for another reason as `cites`.
5. **Do the research.** Try, measure and read, smallest question first. Each finding goes into
`04-findings.md`: what was tried, what it showed (with numbers), what it means. Each change of the effort
the section **Findings**: what was tried, what it showed (with numbers), what it means. Each change of the effort
is `knowledge-base.propose` again, whole, with `why`; every version is kept, and `knowledge-base.history`
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
@@ -69,20 +75,51 @@ An idea arrives in one of two forms, and the first step differs:
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. **Place it in the domains.** Before the direction, write `03-domains.md`: the domain or domains the idea
6. **Place it in the domains.** Before the direction, write the section **Domains**: the domain or domains the idea
belongs to (the glossary's sections, ADR 0244); the modules and seats it lands in, each new, changed or
retired; what it does to each domain's words, each word added (with its domain and a one-line meaning),
changed or retired, and none on a *Not:* line or already meaning something else (the glossary's homonyms);
and whether a domain grows or shrinks, a concept moving between domains included. The direction names its
decisions in those words. Asked when the idea is set up, too: an option that lands a concept in the wrong
domain is offered with that cost named, like one that breaks a rule.
7. **Settle the direction with the operator.** When the questions are answered, write `05-direction.md`:
7. **Settle the direction with the operator.** When the questions are answered, write the section **Direction**:
the proposed decisions in a few lines each, the options rejected and why, and the build's acceptance
tests: what the build must prove before it is done, carried by its milestones (playbook
[04](04-build-handoff.md)). Nothing else is left open: each question closes by a test, by a decision the
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).
operator to confirm or change the direction, one point at a time. Then review it by architectural domain (below) and
propose it once. Then the effort graduates through playbook [02](02-graduation.md).
## Review by architectural domain
A direction the operator settled can still be wrong where nobody looked. Before it is proposed, and again
before a design is merged (playbook [02](02-graduation.md)), it is reviewed against each **architectural domain**
(the operator, 2026-11-02), by reviewers on the larger model, about two architectural domains each, side by side:
the four reviewer agents in `.claude/agents/` (`review-security-and-upgrade`, `review-seams-and-tools`,
`review-running-and-testing`, `review-health-and-events`), each given the subject by number or path:
- **security**: who may call each new verb, how its grants are scoped, which credentials go or remain, what
can be replaced or forged, and what enters from outside the mesh;
- **seams**: where each piece of state lives on the bus, which seat, verb or event joins two parts, and any
link that is not NATS-native. Each piece of state is kept in the bus storage form that fits it (a key-value
bucket, a stream, an object store); a form the manifest lacks is added to mesh-sdk, and the review names that change
and its cost (a mesh-sdk change rebuilds every module) to the operator, never folds it in silently (the
operator, 2026-11-02);
- **running qualities**: build capacity, speed, storage growth, and what happens while a part, the bus or the
control-node is down;
- **health**: what each part's health check says, which conditions are raised and cleared, and whether any
failure can pass silently;
- **events and logs**: what each step says on the bus, and what can be read back later;
- **testing**: an acceptance test for every decision, each one checkable and within the test budget, and the
failure paths;
- **upgrade**: how what runs today moves to the new shape without a delivery breaking, in which order, and
how it is rolled back;
- **tools**: which tool reads each new piece of state and which one steers each new behaviour.
A reviewer judges only whether the settled direction is complete and sound in its architectural domains; it never reopens
a decision. Each finding is a sentence for the direction or a new acceptance test; a finding that changes a
decision goes to the operator. The direction ends with a section *Reviewed by architectural domain*: per architectural domain, what was
found and how it was answered, or that nothing was found.
## Bounds and models
@@ -93,6 +130,7 @@ An idea arrives in one of two forms, and the first step differs:
| each experiment or reading task (5) | 30 minutes | smaller, one agent at a time unless the operator allows more |
| placing it in the domains (6) | 15 minutes | larger |
| the direction (7) | 30 minutes | larger |
| the review by architectural domain | 20 minutes | larger, about two architectural domains per reviewer |
A step past its bound is said to the operator at once, with what is being done about it. The lead reports
as playbook 07 does: every ten minutes and at once when something is found, stops or needs the operator,
@@ -134,7 +172,8 @@ The rules on an effort are the knowledge base's: `propose` refuses one that brea
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, 6 and 7 (options checked
against the rules, one version per settled set, the cheapest level, nothing left open) are the lead's, read by
the reviewer; of the pre-check, `propose` refuses a link to nothing and a retired word, and the review returns
the reviewer; the review by architectural domain is read in the direction's *Reviewed by architectural domain* section (nothing refuses a direction
without it yet: the lead and the reviewer hold it); of the pre-check, `propose` refuses a link to nothing and a retired word, and the review returns
a record named but not linked, an untracked deferral and a figure not as measured. That this repository holds
no effort is the records test'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.
+9 -5
View File
@@ -13,7 +13,7 @@ clauses in force for a topic or a record).
## Graduating research
The effort's `05-direction.md`, confirmed by the operator (playbook [01](01-research.md), step 7), is what
The effort's Direction, confirmed by the operator (playbook [01](01-research.md), step 7), is what
graduates. The lead writes the records and the design on the larger model; it is one sitting, bounded at
about an hour, and said to the operator if it runs past.
@@ -49,9 +49,11 @@ 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.
The design lists the direction's acceptance tests: what the build proves before it is done. Before it is
merged, the design is reviewed by architectural domain as playbook [01](01-research.md#review-by-architectural-domain) says, and
ends with its own *Reviewed by architectural domain* section; a design amended without an effort is reviewed the same way.
The words of the effort's `03-domains.md` go into the glossary in the same change, each in its domain: a
The words of the effort's Domains go into the glossary in the same change, each in its domain: a
word added gets its entry, a word whose meaning changed gets its entry rewritten, and a retired word moves to
its replacement's *Not:* line. A word that already means something else in another domain is named as a
homonym with the qualified form each domain uses.
@@ -129,7 +131,8 @@ A design changes only through a decision.
1. Write the decision record (above). If it reverses an earlier one, it `supersedes` it.
2. Edit the to-be design document, add the record to its `decisions:` as `"ADR NNNN"`, and set `updated:`
to today.
to today. Review it by architectural domain before it is merged (playbook [01](01-research.md#review-by-architectural-domain)), and
rewrite its *Reviewed by architectural domain* section.
3. If the amendment came from an issue, give the issue the document path in the issue tracker:
`amended-design` on its `issue-tracker.move` to `resolved`, or `issue-tracker.link` with kind
`design` before then — never in the report's frontmatter
@@ -164,7 +167,8 @@ 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
when one fails. In this repository, the records test checks that a design's `decisions:` entries and every
"ADR NNNN" in the text are well formed, and that no record is written here; the index test 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. A design's *Reviewed by architectural domain* section is read by the
reviewer of its pull request; nothing refuses a design without it yet. The three habits of graduating step 2 (side by side, clauses
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.
The rounds are read in `knowledge-base.get` (its reviews, one per version): a question to the operator about a
+42 -1
View File
@@ -44,6 +44,10 @@ A small fix (one repository, one issue, about an hour of work) follows
on the bus; two reviews read the code, no test ran it under a node's real permissions, and once it was live every
node's agent was refused that read and stopped composing (issue 1126). How-we-build's rule "A bus permission is
proven under the real permission" (ADR 0560) is what the review now asks for.
- **A change built on what was remembered, not on what runs.** In the days up to 2026-11-02 a release took the
controller's jobs apart from the records and the survey alone. Jobs nobody had named surfaced only after the
delivery, a moved module's wiring and a changed failure label's readers were never read, and every check found one
more fault. Each layer had checked the layer before it; none had read the running code. Step 0 item 3a is the answer.
- **A module proven only after it reached the machines.** The mail modules were delivered with unit tests
only, then failed live three times (issues 859, 865, 868) and took five more hours of fixes.
@@ -55,7 +59,7 @@ opened **once**, after the review, and **one check** (ADR 0548). It runs in five
| Step | What happens | Bound |
|---|---|---|
| 0. Prepare | the lead settles the open questions and writes one context file per repository | 15 minutes |
| 0. Prepare | the lead reads what exists today in the code and on the live mesh, settles the open questions and writes one context file per repository, opening with what exists, what relies on it and what happens to each | 15 minutes, longer when what exists is large: code never starts on an incomplete answer |
| 1. Develop | one fixing agent per repository builds every issue locally, the whole unit suite before every commit, the integration tests compiled (those that exercise the change are run by name before the push, step 3); nothing is pushed | the milestone's issues, 30 minutes each |
| 2. Review | one reviewer reads all of it, the local commits, judging the integration tests by reading them against the code; reports go both ways; at most 3 rounds | 15 minutes |
| 3. Check | push the reviewed heads once and open the pull requests together; the checker's one check runs the integration tests; no further review unless the check fails | one check run |
@@ -114,8 +118,33 @@ issue whether it is being fixed in between, after the delivery, or waits, and on
2026-10-26: "that is simply our delivery plan and milestones, we've already researched it"); propose new research
only for what no record decides. A fixing agent that meets an undecided design question
stops, and its run is spent again.
3a. **Read what exists today, and write it down before any code** (the operator, 2026-11-02: "if i ask to implement
feature A, you'd better first check what exists today with regards to feature A"). Research, decisions, the survey
and the review each check the layer before them; this is the step that checks the running code. Each repository's
context file (item 4) opens with a section `What exists today` that answers three questions, in writing:
1. **What exists today for this feature**, read from the code (file:line) and from the live mesh through the mesh
MCP server's tools (the seats, the modules on each machine, their state on the bus, their tools' answers), never
from memory and never from a record alone. Where the code or the mesh contradicts a record, the answer says so,
and the lead settles it as item 3 says.
2. **Everything the change touches, replaces or removes, and what relies on each today.** For a part that is removed
or moved (a module, a seat, a job of a module, a file, a value's form, a label others read), every effect it has
is listed, found mechanically from its code and not recalled: each bus write (bucket key, stream subject, event),
each file it writes, each credential or grant it issues or rotates, each plan or record it makes, each process or
container it starts, each verb, tool or request it answers, and each timer it runs. Then, for each effect, every
reader that relies on it (a search across every repository and the live bus, file:line or address). The search is
written down as run (the pattern and where), so the review can run it again.
3. **For each item of the second answer, what happens to it after the change** (kept as it is, moved to a named seat,
module or verb, replaced by a named part, or dropped and why nothing needs it), **and the test that proves it**: an
acceptance criterion (item 5) at its level, or, for a dropped effect, the search showing no reader is left.
Code starts only when the three answers are complete for every repository: no fixing agent starts on a context file
without them, and an effect found later is the prepare step missed, written into the answer and its issue before the
fix. In the days up to 2026-11-02 the controller was taken apart without this answer: jobs nobody had named (making
a provision's credentials for a new consumer, planning a module's next build) surfaced only after the delivery; a
module was moved without reading how its pieces were wired; a failure label was changed without reading what relied
on it; and each check found one more fault the preparation should have known.
4. **Write one context file per repository**, `.work/<slug>/<repo>.context.md`. It is what a fixing agent
reads instead of rediscovering the code, and it is reused by every agent and every round:
- first, the section `What exists today` with item 3a's three answers;
- the issues it builds, in order, each with: the files and functions it changes, the decisions it builds
with (quoted, with where each was decided), and its acceptance criteria (item 5), each with the test that
proves it;
@@ -271,6 +300,12 @@ issue whether it is being fixed in between, after the delivery, or waits, and on
key and stream the diff creates or writes (search the diff for the bucket and stream names) and finds each in the
lifetime answer with a deleter and event, or a time to live; it reads the switch-over answer and checks it was done as
written or that the operator's choice is recorded; it reads the integration-level answer against the check the pull requests will ask. A missing answer, or a key or stream the diff creates that the answer omits, is a change asked.
6b. **The reviewer holds the change to each context file's `What exists today`** (step 0, item 3a). It refuses to
review a repository whose context file lacks the section or leaves one of its three answers open: that is the
prepare step undone, sent back to the lead, and not a round. For every part the diff removes, moves or changes the
form of, it runs the recorded search again on the reviewed tree and finds each effect and each reader in the second
answer; for each, it reads in the diff that the third answer's fate happened and that its test exists. An effect or a
reader the search finds and the answer omits, or a fate the diff does not carry out, makes the change wrong.
7. **A finding outside the issues' done-when and their acceptance criteria is never a change asked, in any round.** More hardening, a
further case, a nicer form: the reviewer opens it with `issue-tracker.open` and names the number in its
report, and the round does not wait for it. What a round asks is only what makes the change wrong against
@@ -632,6 +667,12 @@ issues in `fixing` that nobody works on reads to the operator as stuck work.
request into a feature branch exists. A pull request per issue, or an agent waiting on a merge check in
step 1, is the failure this playbook prevents.
- A context file exists per touched repository under `.work/<slug>/` while the feature runs.
- Every context file opens with `What exists today` holding step 0 item 3a's three answers, each search written as run
(`grep -n -A3 'What exists today' .work/<slug>/*.context.md`), and its time (the file's commit or the lead's note) is
older than the repository's first commit of the feature; the review report says it ran the searches again (step 2,
item 6b). A fixing agent started on a file without the section, or an effect of a removed or moved part met only
after the delivery, is the prepare step skipped, named in the next detailed report and written into the playbook's
lessons here.
- No issue of a running milestone is sized over an hour in its prepare note; an issue whose fixing agent passes
twice its bound was not split.
- Every issue of a running milestone has a note from the prepare step naming its files and tests (file:line), how
+10 -2
View File
@@ -33,7 +33,12 @@ processing power"). Everything before the push is local and fast, and no try is
## Steps
1. **Read the issue and the code it names** (the session's own model, or one read-only agent on the smaller
model answering exact questions with file:line). If a design question is open, it is settled before any
model answering exact questions with file:line). **Read what exists in the fix's area today, briefly, before any
code** (playbook [07](07-feature-branches.md) step 0 item 3a, at a small fix's size): what the code and the live mesh
(through the mesh MCP server's tools) do there now, and for each value, label, file or job the fix changes or removes,
every reader that relies on it, found by a search across the repositories (written down as run) and not from memory,
with what happens to each after the fix. It is a few lines in the issue's note, under `What exists today`, and the
review runs the search again; a reader it finds that the note omits makes the fix wrong. If a design question is open, it is settled before any
code is written: on the issue, through the knowledge base (`knowledge-base.ask` first: what is decided is read before anything is designed), or by the operator. A fix that turns out to
need a second repository, or more than about an hour, stops here and becomes a feature; one that needs a
decision stays a small fix. **The session's own model (the larger) then writes the issue's acceptance
@@ -59,7 +64,7 @@ processing power"). Everything before the push is local and fast, and no try is
writer writes it; the review asks it.
4. **One review of the local commit** (a reviewer that did not write it, larger
model; at most 3 rounds, as playbook 07; from round 2 only what is wrong; it reads each acceptance criterion
against its test, as playbook 07 step 2 item 6; a finding outside the issue's done-when and its acceptance
against its test, as playbook 07 step 2 item 6; it runs the `What exists today` search again, as playbook 07 step 2 item 6b; a finding outside the issue's done-when and its acceptance
criteria is opened as an issue of its own, never asked as a change; it judges the integration tests by reading them against the code, as playbook 07 step 2 item 4 says; it answers playbook 07 step 2 item 10's two questions, on state and seams and on mesh-agnostic repositories, in its report). 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
operator's Approve of its merge is its review, and the review record says so.
@@ -146,6 +151,9 @@ reading itself and uses one subagent only for the review.
- A pull request with no review record at its head (the Approve's ask says so first), a fix to a module's
running pushed with no integration test of the module whole, or a review report
asking a change outside the issue's done-when and acceptance criteria, is the failure of steps 4 to 6.
- A fixed code issue shows a note with `What exists today` (`issue-tracker.get`) older than its first commit, its
search written as run; one without is step 1 skipped, and a reader of a changed value met only after the delivery
is that note left short.
- A fixed code issue shows a note headed `Acceptance criteria` (`issue-tracker.get`) older than its first
commit, and each criterion's label is cited by a test in the pushed tree
(`git grep -n '<issue>/AC<n>'`); one without is step 1 skipped.
+9 -8
View File
@@ -221,8 +221,8 @@ code{font:12.5px ui-monospace,monospace;background:var(--soft);padding:1px 5px;b
</g>
<!-- lead -->
<rect x="110" y="56" width="160" height="52" rx="8" fill="var(--card)" stroke="var(--dec)" stroke-width="2"/>
<text x="190" y="78" text-anchor="middle" class="t">Survey · criteria</text>
<text x="190" y="96" text-anchor="middle" class="mute">context file per repo</text>
<text x="190" y="78" text-anchor="middle" class="t">What exists · survey</text>
<text x="190" y="96" text-anchor="middle" class="mute">criteria · context file per repo</text>
<rect x="340" y="56" width="140" height="52" rx="8" fill="var(--card)" stroke="var(--dec)" stroke-width="2"/>
<text x="410" y="78" text-anchor="middle" class="t">Up to trunk</text>
<text x="410" y="96" text-anchor="middle" class="mute">each branch, local</text>
@@ -275,6 +275,7 @@ code{font:12.5px ui-monospace,monospace;background:var(--soft);padding:1px 5px;b
<div class="box">
<h3>Step 0 · what the lead writes before any agent starts</h3>
<ul style="margin:6px 0;padding-left:20px;font-size:14px">
<li><span class="tag new">new</span>What exists today, read from the code and the live mesh, never from memory: every effect of a part removed or moved (bus writes, files, credentials, plans, processes, calls answered), every reader relying on each, what happens to each after the change and its test. It opens each context file; no code before it is complete, and the review refuses work without it.</li>
<li>Every open question settled: on the issue, in the knowledge base, or by the operator.</li>
<li>Into each issue: every file and test it touches (file:line), how it is checked and delivered, a group's merge order.</li>
<li><span class="tag new">new</span>Every other reader and writer of each value the change touches, each with a criterion.</li>
@@ -415,15 +416,15 @@ const P = [
{n:"01",name:"Research",kind:"idea",c:"--idea",
trig:"An idea worth investigating before it is committed to design. A symptom is not research.",
who:"The session that heard the idea leads.",
steps:["Read what is known: ask, get, the tracker's list.","Ask 3 to 5 setup questions, one at a time, each with a recommendation.","Check every option against the mission and how-we-build first.","Reserve a number (kind research), never pick one by hand.","Propose the effort: overview, questions, method, with links.","Research; findings in 04-findings, one version per settled set.","Try at the cheapest level that answers the question.","Write 03-domains: modules, seats, glossary words added or retired.","Write 05-direction: decisions, rejected options, acceptance tests.","Ask the operator to confirm the direction, one point at a time.","If the review asks changes: propose again, at most three times."],
steps:["Read what is known: ask, get, the tracker's list.","Ask 3 to 5 setup questions, one at a time, each with a recommendation.","Check every option against the mission and how-we-build first.","Reserve a number (kind research), never pick one by hand.","Propose the effort: Overview, Questions, Method, sections named by title, no file references.","Research; findings in the section Findings, one version per settled set.","Try at the cheapest level that answers the question.","Write the Domains: modules, seats, glossary words added or retired.","Write the Direction: decisions, rejected options, acceptance tests.","Ask the operator to confirm the direction, one point at a time.","Review the direction by architectural domain: security, seams, running qualities, health, events and logs, testing, upgrade, tools.","If the review asks changes: propose again, at most three times."],
prod:"A research effort in the knowledge base, status active, every version kept. Nothing in hq.",
next:"02",bounds:"Setup 30 min · proposing 15 min · each experiment 30 min · direction 30 min · report every 10 min",
next:"02",bounds:"Setup 30 min · proposing 15 min · each experiment 30 min · direction 30 min · review by architectural domain 20 min · report every 10 min",
prev:["Research that measured nothing","A recommendation the operator must argue back","Efforts copied into hq"],
check:"propose refuses rule breaks; the knowledge base reviews; the records test on every PR."},
{n:"02",name:"Graduation & design change",kind:"idea",c:"--dec",
trig:"A research effort concludes, or an existing design must change.",
who:"The lead, on the larger model; the decision is recorded before the design moves.",
steps:["Check the conclusion against mission, context and effect.","Reserve a number per decision.","Propose one record per choice that can be reversed on its own.","Pre-check, then propose siblings together.","On changes: revise whole; after three rounds fix findings yourself.","A finding that would change what was decided: ask the operator.","needs-operator: wait for the operator's Approve.","Amend the design, or create a to-be design with status designed.","Add the decisions, updated:, and the effort's glossary words.","Hand the design to the breakdown (04).","Close the effort: graduated with became links, or abandoned.","When it ships: write the as-is, set the to-be implemented."],
steps:["Check the conclusion against mission, context and effect.","Reserve a number per decision.","Propose one record per choice that can be reversed on its own.","Pre-check, then propose siblings together.","On changes: revise whole; after three rounds fix findings yourself.","A finding that would change what was decided: ask the operator.","needs-operator: wait for the operator's Approve.","Amend the design, or create a to-be design with status designed.","Add the decisions, updated:, and the effort's glossary words.","Review the design by architectural domain before it is merged.","Hand the design to the breakdown (04).","Close the effort: graduated with became links, or abandoned.","When it ships: write the as-is, set the to-be implemented."],
prod:"Decision records; a to-be design with frontmatter; glossary entries; later the as-is.",
next:"04",bounds:"One sitting of about an hour",
prev:["A decision rewritten silently","A deferral nothing tracks","A design amended without a decision"],
@@ -463,15 +464,15 @@ const P = [
{n:"07",name:"Features",kind:"build",c:"--build",
trig:"Work that changes code across issues or repositories, too large for a small fix.",
who:"A lead (larger model), one fixing agent per repository (smaller), one reviewer (larger).",
steps:["Prepare: name the branch, make the worktrees, settle every question.","Write one context file per repository.","Write the findings and acceptance criteria into each issue.","Survey every other reader and writer of each changed value. (new)","Answer three questions in the milestone file: who deletes each new key and stream, how the switch-over is tried on one node first, what the one check does not cover. The review checks them. (new)","List every part the change reaches; copy fixtures from the real writer.","Develop: one agent per repository, one commit per issue.","A test fails first on behaviour, not on compiling. (new)","Bring each branch up to the trunk; nothing is pushed, no try runs. (new)","Review all of it, reading the integration tests against the code; at most 3 rounds; the report answers the state-and-seams and mesh-agnostic questions. (new)","A group pins the group's own mesh-sdk head in every member. (new)","Push the reviewed heads once and read each forge head against the reviewed commit; no draft pull request, no fix round on an open one. (new)","Open one pull request per repository, together, with Reviewed-by and Pushed-by; the one check runs. A failed check is read, fixed, reviewed, pushed once more. (new)","The operator's Approve on Telegram; the group merges in one pass.","Follow the delivery in the status view (moving, settled, stuck, delivered) to done; resolve the issues; clean up. (new)","When the builder cannot deliver its own fix: revert, a build by a session's call, a registration at the terminal, copies kept outside the store; a broken controller is put back by a want the operator writes, a hand build by mesh-hand-compose and a want. (new)"],
steps:["Prepare: name the branch, make the worktrees, settle every question.","Read what exists today from the code and the live mesh: every effect of what is removed or moved, every reader of each, what happens to each and its test. No code before it is complete; the review refuses work without it. (new)","Write one context file per repository, opening with what exists today.","Write the findings and acceptance criteria into each issue.","Survey every other reader and writer of each changed value. (new)","Answer three questions in the milestone file: who deletes each new key and stream, how the switch-over is tried on one node first, what the one check does not cover. The review checks them. (new)","List every part the change reaches; copy fixtures from the real writer.","Develop: one agent per repository, one commit per issue.","A test fails first on behaviour, not on compiling. (new)","Bring each branch up to the trunk; nothing is pushed, no try runs. (new)","Review all of it, reading the integration tests against the code; at most 3 rounds; the report answers the state-and-seams and mesh-agnostic questions. (new)","A group pins the group's own mesh-sdk head in every member. (new)","Push the reviewed heads once and read each forge head against the reviewed commit; no draft pull request, no fix round on an open one. (new)","Open one pull request per repository, together, with Reviewed-by and Pushed-by; the one check runs. A failed check is read, fixed, reviewed, pushed once more. (new)","The operator's Approve on Telegram; the group merges in one pass.","Follow the delivery in the status view (moving, settled, stuck, delivered) to done; resolve the issues; clean up. (new)","When the builder cannot deliver its own fix: revert, a build by a session's call, a registration at the terminal, copies kept outside the store; a broken controller is put back by a want the operator writes, a hand build by mesh-hand-compose and a want. (new)"],
prod:"One pull request per repository, one source revision delivered, resolved issues, no branch or worktree left.",
next:"02 (when it ships)",bounds:"Prepare 15 min · 30 min per issue · review 15 min, ≤ 3 rounds · one check, pushed once",
prev:["Pull requests as scratchpads","Context bought again and again","Review rounds spent on what a run would show","A node agent's bus reads, proven only by review"],
prev:["Pull requests as scratchpads","Context bought again and again","A change built on what was remembered, not on what runs","Review rounds spent on what a run would show","A node agent's bus reads, proven only by review"],
check:"The checker's one status, mesh/check; the review record; the tracker's move."},
{n:"08",name:"Small fixes",kind:"build",c:"--build",
trig:"One issue in one repository, about an hour of work.",
who:"The session, with one reviewer on the larger model.",
steps:["Read the issue and the code; settle any open question.","Write the acceptance criteria.","Move the issue to fixing.","Build on fix/<issue>-<slug> in its own worktree.","A test that fails today first, on behaviour. (new)","Nothing is pushed and no try runs before the review. (new)","One review of the local commit.","Push the reviewed head once; only then open the pull request. (new)","The operator's Approve; the merge; the delivery, followed in the status view. (new)","Prove the fix live and resolve the same hour.","During a milestone: ride in its delivery group, unless broken for the operator now. (new)"],
steps:["Read the issue and the code; settle any open question.","Read what exists in the fix's area today, briefly: every reader of what the fix changes. (new)","Write the acceptance criteria.","Move the issue to fixing.","Build on fix/<issue>-<slug> in its own worktree.","A test that fails today first, on behaviour. (new)","Nothing is pushed and no try runs before the review. (new)","One review of the local commit.","Push the reviewed head once; only then open the pull request. (new)","The operator's Approve; the merge; the delivery, followed in the status view. (new)","Prove the fix live and resolve the same hour.","During a milestone: ride in its delivery group, unless broken for the operator now. (new)"],
prod:"One pull request, one delivery, a resolved issue.",
next:"—",bounds:"About an hour · one review, one push, one check",
prev:["A fix reviewed after its pull request opened","A long part run twice","A fix waiting on someone else's delivery","Ten SDK merges and eight controller merges in a day, one per fix"],
+413 -38
View File
@@ -2,34 +2,47 @@
layer: to-be
status: in-progress
code: [mesh-catalog, hq]
updated: 2026-10-18
updated: 2026-11-02
decisions:
- "ADR 0290"
- "ADR 0321"
- "ADR 0423"
- "ADR 0424"
- "ADR 0592"
- "ADR 0593"
---
# 55 — The knowledge base
**Where it stands, 2026-10-17** (the records cleanup, issue 1072; playbook 07, "The design's state is written back"). Built and live since 2026-10-11: the knowledge base is the module mesh-knowledge in mesh-catalog, holding every decision record and research effort (issues 425 and 426, resolved and delivered). Left: the later slices, issues 428 and 429.
**Amended, 2026-11-02** (ADR 0592, on the operator's word: "our knowledge base must be nats-native"; "don't use
file references or local files anymore"). The records leave the store for the bus: each record's head in the
module's state, its versions on a stream, its sections' bodies once each in an object bucket by digest. A record is
written one section at a time in a draft, and reviewed one section at a time. A section is a part with a title,
never a file. § 1, § 2, § 4, § 5, § 8.1 and the fifth slice of § 9 say how; until it is built, the module keeps its
records in the store as before.
**The mesh keeps its decision records and research efforts whole in a module of its own, `mesh-knowledge`, one
instance on the control-node, holding the seat `knowledge-base`: each record's number, status, topic, typed links,
its clauses with their own status, and its reasoning, with every version kept. A record is proposed, checked when it
is written, reviewed by the knowledge base's own judgement and accepted there; the operator's Approve is asked when a record needs
it. Agents ask what holds, and why, in one bounded call.**
(ADR 0290,
its clauses with their own status, and its reasoning in titled sections, with every version kept, all of it on the
bus. A record is written section by section, checked when it is submitted, reviewed section by section by the
knowledge base's own judgement and accepted there; the operator's Approve is asked when a record needs it. Agents
ask what holds, and why, in one bounded call.**
(ADR 0290 and ADR 0592,
from research 045.)
A **clause** is one numbered statement a decision record makes, with its own status. The **knowledge base** is the
module that holds the records; the seat it holds is `knowledge-base`. The glossary holds both words.
A **clause** is one numbered statement a decision record makes, with its own status. A **section** is one titled
part of a record's reasoning. The **knowledge base** is the module that holds the records; the seat it holds is
`knowledge-base`. The glossary holds these words.
**Acceptance.** A session started in any folder on any node asks "what holds about the merge window, and why" and
gets, in one call under 4 KiB, the clauses in force, the records they come from, what changed them since, and how to
read the reasoning behind each.
read the reasoning behind each. A session writes a research effort of more than 100 KiB one section at a time, a
session on another node takes the draft over and submits it, and every section is judged.
This document designs the first slice in detail, tracked by issue 425. The slices after it are in
This document designs the first slice in detail, tracked by issue 425, and the fifth, the records on the bus
(ADR 0592). The slices after the first are in
[§ 9](#9-the-slices-after-the-first), which also designs the third: designs and the glossary's entries become records,
and the knowledge base works out each design's state (ADR 0423, ADR 0424).
@@ -40,17 +53,32 @@ and the knowledge base works out each design's state (ADR 0423, ADR 0424).
mesh-knowledge (seat knowledge-base, held once for the mesh)
├ its process, launched by the node runtime
├ a database in the store records, versions, clauses, links; ranked full-text search
├ verbs ask, get, holds, links, history, reserve, propose, import, return
├ on the bus, written by it alone (§ 2)
│ state heads one key per record: its fields, clauses, links, sections as title and digest
│ state drafts one key per record being written: its author and its sections as title and digest
│ state asked one key per part asked of the judge and not yet answered: ticket, node, when
│ state names per digest: how many versions and drafts name it, and since when none has
│ state findings the whole-set findings standing now, and the told marks (told.<topic>)
│ stream versions one message per version: who, when, why, its mark, the head as it stood
│ stream reviews one message per part reviewed: the digest judged, the verdict, the findings
│ objects sections every section's body, once, named by its sha256 digest
├ in its memory the search index, built from the bus at start and kept by watching heads
├ verbs ask, get, list, holds, links, history, findings, progress,
│ reserve, open, write, remove, order, submit, drop, take-over, propose,
│ withdraw, retract, import, return
│ served by the control-node's tool runner
├ events proposed, reviewed, accepted, changed, imported, drafted, confirmed, returned
├ events reserved, opened, written, removed, ordered, submitted, dropped, taken-over, proposed,
│ part-reviewed, reviewed, accepted, changed, swept, moved, checked, formed,
│ imported, drafted, confirmed, returned
├ consumes the router's warrants: the operator's Approve for a record that needs it (§ 5)
├ consumes claude-code's judged: the judge's answer to a part (§ 5)
└ consumes the delivery module's delivery-done announcement: a design's state (§ 9)
mesh-issues (control-node) the counters for decision and research numbers (§ 6);
the issues' design links, read for a design's state (§ 9)
mesh-delivery (its seat) announces each delivery done, on the bus (§ 9)
claude-code (same node) claude_code_judge: review a proposal (§ 5), draft and confirm clauses (§ 7)
claude-code (same node) claude_code_judge: review a section or a head (§ 5), draft and confirm clauses (§ 7);
emits judged with the answer of each ticket (§ 5, a dependency of the fifth slice)
records (any node) records_read at a commit: the import's source (§ 8)
messenger (control-node) the router: the operator's ask and its warrant
@@ -59,20 +87,86 @@ and the knowledge base works out each design's state (ADR 0423, ADR 0424).
```
The module is written in Go against the SDK. It holds no checkout of this repository; the import reads it through
the records module, as the issue tracker's import does.
the records module, as the issue tracker's import does. Until the move of § 8.1, its records are in a database in
the store; from the move on, it requires no database (ADR 0592 §1, changing ADR 0290 §7).
**A write is whole or refused, and `submit` commits when its version is stored** (ADR 0592 §10). Every change to
`heads`, `drafts`, `asked`, `names` and `findings` is a compare-and-set on the key's revision, retried at most three
times and then refused with the reason. The commit point of `submit` is the version message stored on `versions`: a
failure before it is stored refuses the call, and nothing is taken. Once it is stored, the call answers that the
version is taken; the head's update against its revision and the event are then completed at once, retried, and at
the next start for any head behind its last stored version. So nothing an author was told was refused takes effect
later. A reservation is a head created only if the key is absent, so two sessions reserving at once get two numbers
or one refusal.
**The search index** is a full-text index in the module's own memory, written with the pure Go library bleve. At
start the module reads every head and the bodies of every current version into it, then keeps it current by watching
`heads`, noting the last revision of `heads` it took in. `ask` and `holds` answer from it, ranked by title, clauses
and sections as before, and refuse with "index not built" while it is built; `get`, `list` and `propose` answer from
`heads` at once (ADR 0592 §11). The integration test measures the start; the estimate is 20 to 40 seconds and about
100 MB of memory for today's 736 records. Nothing but the module writes it, and nothing outside it reads it.
### 1.1 Its tools, health and events
Every piece of state has a tool that reads it, and every act the module does by itself can be done by hand
(ADR 0592 §32):
| Tool | Reads or does |
|---|---|
| read a head | one key of `heads`, whole |
| read a version | one message of `versions`, with its sections' titles, digests and authors |
| read a section | one object of `sections`, by its digest, checked against it |
| read a draft | one key of `drafts`, with its author and since when |
| read a review | the part verdicts of one version, from `reviews` |
| in-flight parts | the keys of `asked`: each part waiting on the judge, its ticket and since when; ask one again |
| told marks | the `told.<topic>` keys; clear one, so it is told again |
| fill | each bucket's and stream's size and count against its cap |
| rebuild the index | the search index, built again from the bus |
| review again | asks one part's review again, for a version still proposed |
| sweep | lists the objects no version or draft names and since when; sweeps them now; dry run |
| integrity | checks every named digest has its object; restores a body from given text once its digest matches |
| form-only | lists, dry-runs and runs the form-only versions of § 2.2 |
| move, and check the move | § 8.1, each with a dry run |
**Health** (ADR 0592 §33) is unhealthy, naming the cause, when a bucket or stream does not answer, when the index is
behind the latest revision of `heads`, when a digest some version names has no object (counted, each named), and
when a bucket or stream is at its cap. It names the source it serves from (the database or the bus) and the result
of the move's last check, and counts drafts idle more than a week, records the form-only check refused, and parts
waiting more than 30 minutes. A part waiting more than 30 minutes is asked of the operator once through the operator
channel, and the ask clears when the part is judged; the module stays healthy meanwhile, because a record waiting on
its review is not the module failing (issue 508). The condition at 75 percent of a cap is the grants part's (§ 2.1).
**Events** (ADR 0592 §34) are kept 30 days; what a later reader needs is also in the version message. Each carries:
| Event | Carries |
|---|---|
| `opened` | the record, the version it starts from, the author |
| `written`, `removed` | the record, the section's title and digest, the author |
| `ordered` | the record, the titles in order, the author |
| `submitted` | the record, the new version, its section digests, the author |
| `dropped` | the record, the author, the reason (asked, or idle 14 days) |
| `taken-over` | the record, the previous author, the new author, the reason |
| `part-reviewed` | the record, the version, the part, its digest, the verdict |
| `reviewed` | the record, the version, every part's verdict: one event per version, as before |
| `swept` | the digest removed, since when nothing named it |
| `moved` | the record, its counts on the bus |
| `checked` | the move's check: records compared, every difference |
| `formed` | the record, the version, the names changed |
None is named `drafted`, which stays the event of a clause the import's judgement wrote.
## 2. What one record holds
- `number` and `kind` (decision or research; with the third slice also design and glossary entry, § 9), its key
together; `title`, `topic`, `status`, `date`, `deciders`;
- its **reasoning**, in sections: for a decision, context, the options weighed, consequences, how it is checked,
references; for a research effort, its overview and each of its documents by name; for a design, its `to-be`
section and, where something of it runs, its `as-is` section (§ 9); markdown, as written;
- its **reasoning**, in **sections**, each a plain title and its text in markdown: for a decision, Context,
Considered Options, Consequences, How it is checked, References; for a research effort, its overview and each of its
parts by title; for a design, its `to-be` section and, where something of it runs, its `as-is` section (§ 9);
- for a decision, its **clauses** (§ 3);
- its **links**, typed, each stored once and read from both ends;
- its **versions**: every change is a new version with who made it, when, and why in one line; `history` lists them
and gives the difference between any two. A progressive insight is a version marked as one, dated, saying what stood
before.
before. A form-only version (§ 2.2) is marked `form`.
| Link | From → to |
|---|---|
@@ -84,6 +178,90 @@ the records module, as the issue tracker's import does.
| `touches` | a research effort → a record, issue or design it bears on (by link), or an area (as text) |
| `cites` | any record → any record or issue it names |
### 2.1 Where it is kept
A record is kept in three of the bus's own forms, so that a new version costs only what changed (ADR 0592 §1 to §9):
```
heads (state) versions (stream) sections (object bucket)
┌─────────────────────┐ ┌──────────────────────────┐ ┌────────────────────────┐
│ decision.0290 │ │ decision.0290 version 7 │ │ 3f9a… "Context" text │
│ title, status, … │ │ who, when, why, mark │ │ 81c2… "Options" text │
│ clauses, links │ │ the head as it stood: │──────▶ │ 0d77… "Context" text, │
│ current: 8 │ │ Context 3f9a… │ │ as changed in 8 │
│ sections: │ ├──────────────────────────┤ │ … │
│ Context 0d77… │──────▶│ decision.0290 version 8 │──────▶ └────────────────────────┘
│ Options 81c2… │ │ Context 0d77… │ each body once, named by
└─────────────────────┘ │ Options 81c2… │ its sha256 digest
└──────────────────────────┘
```
- **The head** is one key in the state `heads`, `<kind>.<number>`: the record's fields, its clauses with their status
and source, its links, the operator's ask and warrant, its current and pending version, the latest verdict of each
part's review (§ 5), and its sections in order, each a title and a digest. A key's value stays under 256 KiB
(ADR 0201). A reserved number is a head at `reserved`, with who reserved it, when, for what and when it expires.
- **A version** is one message on the stream `versions`: who wrote it (the caller the bus proved), when, why, its
mark, who wrote each section, the reason of any take-over since the version before, and the head as it stood. It never copies a section's body. The stream keeps its history: every message,
with no age limit, and when it reaches its cap it refuses a new message rather than dropping its oldest, with a
condition raised at 75 percent of the cap. A module's stream may declare that retention; before, a stream was kept at
most 30 days (ADR 0592 §6, changing ADR 0363 §1). The stream `reviews` keeps its history the same way. The
condition at 75 percent is raised by the grants part (mesh-grants), in one place, for every history stream and
object bucket of every module (ADR 0593 §10, changing ADR 0592 §16).
- **A section's body** is one object in the bucket `sections`, named by the sha256 digest of the body: a section
unchanged in a new version costs nothing. The module checks that a body hashes to its name each time it reads one.
The state `names` keeps, per digest, how many versions and drafts name it and since when none has; an object no
version and no draft names is removed a day after the last stopped naming it, each removal the event `swept`. The bucket is storage of the bus, as the object bucket of ADR 0486 is. Any module
may declare an object bucket of its own in its manifest, with a local name and a cap, created as its state buckets
are, kept with no age limit and refusing a new object when full (ADR 0592 §5).
- **A draft** is a key in the state `drafts` (§ 4). **A part's verdict** is a message on the stream `reviews`, and a
part asked of the judge and not yet answered a key in the state `asked` (§ 5). **The whole-set findings** standing
now are keys in the state `findings`, and what was told to the operator once is a key `told.<topic>` there.
**Caps** (ADR 0592 §25). Each is set from the move's dry run, within its form's bound: a stream at most 8192 MiB
(ADR 0363), a state at most 64 MiB (ADR 0201), an object bucket at most 8192 MiB (ADR 0592 §5). The starting figures, from
today's 83 MB for 736 records with every version copying every section, are:
| Bucket or stream | Cap |
|---|---|
| `versions` (stream) | 1 GiB |
| `reviews` (stream) | 512 MiB |
| `sections` (object bucket) | 1 GiB |
| `drafts` (state) | 64 MiB |
| `heads`, `asked`, `names`, `findings` (state) | 64 MiB, ADR 0201's bound |
A write refused at a cap names the cap, and the module's health turns unhealthy naming it.
**Who may read each** follows the mesh's own forms, read-only (ADR 0592 §8, §9). `versions` and `reviews` are
restricted streams (ADR 0363): a module hears them only through its own `consumes` and a `grant` in mesh-knowledge's
trusted config value `readers`, which names the web page that shows records once it exists and nothing today. The
object bucket `sections` is read the same way, through a `reads` entry and a `grant` of `readers`: ADR 0592 extends
ADR 0363's grant to a module's object bucket, and the grants part composes a read-only grant on that one bucket
(ADR 0593 §10).
`heads` is read by a module that names it in `reads`; `drafts`, `asked`, `names` and `findings` by mesh-knowledge
alone. No secret is kept in any of them. A grant cannot limit a reader to some objects of a bucket
(ADR 0488), which is why reading is announced per bucket and never per record.
### 2.2 A section is a part with a title
A section's name is a plain title, unique in its record: "Context", "Direction", "The move". It is never a file's
name: a name with an extension, a number prefix such as `00-`, or a slash is refused, and so is a text that holds a
local path (in a person's home folder or the temporary folder), a reference to a file and line, or a link whose
target is a relative path or a file (ADR 0592 §29).
**A reference has one form** (ADR 0592 §30): the record, a section's title, then a row or clause inside that
section's text, joined by ›, such as "research 081 › Direction › D3"; a clause as its record and number,
"ADR 0290 §7". Sections never nest: `get` resolves a record and a section's title, and the row is an anchor in the
section's text, which a web page links.
**The records imported with file-named sections** (the research efforts' `00-overview.md` and the like) get titles in
one form-only version per record, written after the move by the move's tool alone; no verb writes one. It changes only section names and the
targets of links, each link to a record's file becoming a reference in the form above. It is marked `form`, lists the
names it changed, and is accepted without a judgement because a check proves only form changed: each section's text,
with every link replaced by its label, is the same before and after, and each new link target resolves to the record
the old name named. `get` accepts the old section names as aliases, recorded in that version. A part's review carries
over to it, its meaning being unchanged. It is not a change of meaning; `history` shows it as a change of form
(ADR 0592 §31).
## 3. Clauses
A clause holds its record's number and its own (`0276 §4`), its wording, a `status` and a `source`:
@@ -103,9 +281,47 @@ A clause holds its record's number and its own (`0276 §4`), its wording, a `sta
## 4. Writing a record
`reserve` gives a number (§ 6). `propose` takes the record whole: its fields, its clauses, its reasoning in sections,
its links, and for each `changes` the clauses it changes. It is refused, with every reason at once, when one of the
29 rules of the hq checks that judge one record or its prose fails, among them:
`reserve` gives a number (§ 6). A record is then written in a **draft**, one section per call, and submitted as a
version (ADR 0592 §17):
| Verb | Does |
|---|---|
| `open` | opens a draft of a reserved or existing record, with its fields, clauses and links; called again by its author, changes them |
| `write` | writes one section: its title and its text; one call per section |
| `remove` | removes one section from the draft |
| `order` | sets the sections' order |
| `submit` | makes the draft a version: every rule below is checked, every reason of a refusal named at once, and the review asked (§ 5) |
| `drop` | discards the draft |
| `take-over` | makes the caller the author of a draft or a proposal, with a reason |
| `propose` | `open`, a `write` of each section and `submit` in one call, for a record that fits one bus message |
```
open ──▶ write ──▶ write ──▶ … ──▶ submit ──▶ proposed, reviewed by part (§ 5)
▲ │ │
└─ remove, order └── refused: every reason named, the draft kept as it was
drop: the draft is gone take-over: another session becomes its author, with a reason
```
A draft is a key in the state `drafts`: its author, when it was opened, the version it starts from, the record's
fields and clauses, and its sections in order as title and digest. Each `write` stores the section's body in the
object bucket `sections` and its digest in the draft, so the knowledge base holds the only copy of a draft and a
session on any node can read it. A draft holds at most 64 sections and 1 MiB; one untouched for a week is counted in
the health, and one idle for 14 days is dropped and its author told by `dropped`.
**A draft and a proposal have one author** (ADR 0592 §19). Only the author writes a draft or revises a proposal;
another caller is refused, naming the author. `take-over` makes the caller the author, keeps the reason on the
record, and tells the previous author by the event `taken-over`. It answers a proposal that only the machine that
wrote it could revise (issue 1102) and one left proposed for ever by a version from an unproven writer (issue 465).
A proposal waiting for the operator's Approve cannot be taken over: its author withdraws it first. The reason of a
take-over is carried in the next version's message.
**Only a proven caller writes** (ADR 0592 §20, §21): `open`, `write`, `submit`, `propose` and `take-over` refuse a caller
the runtime could not prove. The operator's Approve binds the section digests of the version shown; a version with
any other section is asked again.
`submit` and `propose` are refused, with every reason at once, when one of the rules that judge one record or its
prose fails, among them:
- a link names a record or clause that does not exist;
- a decision has no clause, or a clause has no bold lead;
@@ -113,21 +329,62 @@ its links, and for each `changes` the clauses it changes. It is refused, with ev
that replaced it;
- its topic is not one of the reading order's;
- a research effort graduates without naming what it became;
- its text uses a retired word of the glossary, or a daemon's command line.
- its text uses a retired word of the glossary, or a daemon's command line;
- a section is over 40 KiB (it says: split it), or the clauses together are;
- a section's name looks like a file, or its text holds a local path, a file and line, or a link to a file (§ 2.2).
`write` refuses a section over 40 KiB, or one whose name or text breaks § 2.2, at once, so a session learns it on the
section it just wrote.
A proposed record can be revised by its author as new versions until it is accepted. Nothing proposed is ever served
as in force.
## 5. Review and acceptance
When `propose` takes a record (or a new version of a proposed one), the knowledge base reviews it itself: it asks for
a judgement in a separate call, with no tools, that sees only the record, the records it links and the rules, and
answers `approve` or `changes` with its findings, the way the issue tracker's triage judges an issue. The judgement
goes through the agent module's judge (`claude_code_judge`) today, and through the mesh's inference layer once one
exists; nothing in this design depends on which. On `changes`, the record stays proposed, the findings are kept with
that version, and its author revises it with a new version, which is reviewed again. A judgement that cannot be had
(the judge unreachable, or its answer unreadable) leaves the record proposed and says so; it is never taken as an
approval. On `approve`:
When a version is submitted (by `submit` or `propose`, a new version of a proposed record included), the knowledge
base reviews it itself, **in parts** (ADR 0592 §22 to §28, changing ADR 0290 §4): one judgement per part, each in a
separate call, with no tools, that answers `approve` or `changes` with its findings, the way the issue tracker's
triage judges an issue. The judgement goes through the agent module's judge (`claude_code_judge`) today, and through
the mesh's inference layer once one exists; nothing in this design depends on which.
- **The head** is one part: the title, the brief, the clauses (at most 40 KiB together) and the links, judged
against the clauses of the records it links, in what room is left, those not shown named.
- **Each changed section** is a part of its own, judged with **the frame** of at most 16 KiB: the title, the links,
and only what the section names (rows of other sections, clauses, the clauses of linked records), with the digest
of the Context section (the Overview, for a research effort) it is read beside. What does not fit is cut, and the
question says what was cut. A section is at most 40 KiB, so each question stays under the judge's 60 KiB.
- **What is judged again.** A section is judged again only when its own text or what it names changes; the Context
only when it changes. So a usual revision judges only the sections it changed.
- **At most two judge calls of one version run at once.** A revision of eight sections takes a few minutes, and
about four times the tokens of one whole judgement.
- **The rules on the whole record** (§ 4) stay code, run at `submit`; no judgement is asked to find a link to nothing.
```
version 3 of research 081
├ head title, brief, clauses, links ── judged ──▶ approve
├ Overview unchanged since version 2, same frame ── kept ──▶ approve (version 2's)
├ Direction changed ── judged ──▶ changes: "D3 contradicts ADR 0290 §7"
└ Findings changed ── judged ──▶ approve
version 3 stays proposed, with the findings of Direction
```
**The parts wait on the bus** (ADR 0592 §23). Each part asked of the judge is a key in the state `asked` (the part,
the judge's ticket, the node, when it was asked), collected again at start, so a restart loses no review. The judge's
answer comes as the event `judged`, which the claude-code module emits for each ticket and the knowledge base
consumes; until claude-code emits it, the knowledge base polls the ticket, which is not NATS-native and is tracked by
issue 1956. The judge is a tool of the claude-code module, not a seat's verb: a seat for judgements (held by the
mesh's inference layer once one exists) is a note on that issue. A part waiting more than 30 minutes asks the
operator once through the operator channel, and the ask clears when the part is judged.
**A part's verdict** is the event `part-reviewed` and a message on the stream `reviews`: the record, its version, the
part, the digest judged, the verdict, the findings, who judged and when; the head keeps the latest verdict of each
part. **`reviewed` keeps its meaning**: one event per version, once every part is judged, carrying each part's
verdict, so every wait on it keeps working. A part's review is kept for a new version when what it was judged with is
unchanged, and for a form-only version (§ 2.2); any other part is judged again. **A version is accepted when every
part's review approves.** On `changes`, the record stays proposed, the findings are kept with that version and the
part they name, and its author revises it with a new version. A part that cannot be judged (the judge unreachable,
or its answer unreadable) leaves the version proposed and says which; it is never taken as an approval. When every
part approves:
1. a record that does not need the operator is accepted at once;
2. a record whose author marked it `needs operator` gets an ask on the router with Approve and Decline, shown on a
@@ -138,18 +395,18 @@ On acceptance the record and its clauses move to `accepted` and `in force`, ever
`supersedes` name moves to `changed` or `superseded`, and `accepted` and `changed` events are emitted. Then the 4
rules that judge the whole record set run (an accepted decision cited by nothing, and the like). A failure does not
undo the acceptance. It is a fault of the records, which their authors repair, not of the module: it is told to the
operator once, as a warning naming the rule and the records, and cleared once the rule holds again. The module's
health names it and stays healthy, because health says only whether the module works, and a finding never holds a
rollout at the module's first-node gate (the operator's decision of 2026-10-12 on issue 504, as issue 508 decided for a proposal never
reviewed).
operator once, as a warning naming the rule and the records, kept in the state `findings`, and cleared once the rule
holds again. The module's health names it and stays healthy, because health says only whether the module works, and
a finding never holds a rollout at the module's first-node gate (the operator's decision of 2026-10-12 on issue 504,
as issue 508 decided for a proposal never reviewed).
The rule `cited` is also judged ahead, in the review, before the judgement: a decision that names no home and that no
accepted record links is not accepted. Its review, by the knowledge base itself, asks changes naming the rule (issue
504). It is not refused at `propose`, because no record can link a number only reserved: a record that cites a new
504). It is not refused at `submit`, because no record can link a number only reserved: a record that cites a new
decision is proposed after it and accepted, and the new decision is proposed again.
An accepted record is changed only by a new record, or by a progressive insight: a new version marked as one, which
is reviewed like a proposal.
An accepted record is changed only by a new record, by a progressive insight (a new version marked as one, which is
reviewed like a proposal), or by a form-only version of § 2.2, which a check, not a judgement, accepts.
## 6. Numbers
@@ -194,6 +451,41 @@ reporting nothing created (issue 488).
Before the records leave this repository (issue 426), every record is compared with its file at the import's commit,
field by field and section by section, and the result is written on issue 426.
### 8.1 The move off the store
The records leave the store once, and the database is dropped only after a check and the operator's yes
(ADR 0592 §12 to §16):
1. **Order.** Two deliveries, in order (ADR 0593 §10, changing ADR 0592 §16): first the mesh-sdk release sdk1
(issue 1585), which carries the manifest's field types for `objects` and `retention: history`, their checks in
the indexer's judge, and in the grants part the creation of the object buckets and history streams, the
read-only grants of `readers` on them and the condition at 75 percent for every such bucket and stream in one
place; then mesh-knowledge. An indexer whose judge predates these keys refuses a manifest that has them, so
mesh-knowledge cannot be delivered before the release. The claude-code module's `judged` event is
delivered beside, and is not needed for the move (§ 5).
2. **Copy.** The move copies everything the database holds onto the bus, every record, version, clause, link,
review, finding, ask with its warrant, reservation and told mark: each version's sections into `sections` by
digest, each version as a message on `versions`, each record's head into `heads`, each standing finding into
`findings`, each told mark as `told.<topic>`. A clause keeps its number, status and source as the database holds
them (ADR 0321). It emits `moved` per record, writes nothing twice, and a second run changes nothing and says so.
A dry run lists what it would write and the size each bucket and stream will need, from which the caps are set.
3. **The window.** From the move's final copy through the check to the switch, every writing verb is refused with
its reason ("the knowledge base is moving"). Reading verbs answer throughout.
4. **Check.** A tool compares the database and the bus record by record: for each record the count of each of
those, the digest of every section of every version, computed from the database's text and read from the bus,
that each body hashes to its name, and a digest of every review's, finding's and ask's content. It emits
`checked` with every difference, and the health shows its last result.
5. **Switch.** Only once the check shows no difference, the module answers from the bus. The switch is a key on the
bus, so a restart never falls back to the database. A difference is told to the operator, and the module stays on
the database.
6. **Rollback.** Until the database is dropped, the module writes each change to the database too, so a rollback of
the delivery reads a current database. A rollback is safe only until the drop.
7. **Tell and ask.** Once the check is clean, the operator is told its result and asked, once, whether the database
may be dropped, because dropping it removes data.
8. **Drop.** On the operator's yes, the delivery after it removes the module's requirement of a database, and the
database is dropped by the store's module, through its tool for it, which is built there first if it has none.
9. **Titles.** The move's tool then writes the form-only versions of § 2.2, one per record with file-named sections.
## 9. The slices after the first
| Slice | Delivers | Done when the operator sees | Tracked by |
@@ -202,6 +494,7 @@ field by field and section by section, and the result is written on issue 426.
| 2 | the decision records and research efforts leave this repository; path mentions become "ADR NNNN" and "research NNN"; playbooks 01 and 02 changed | this repository holds no decision record, and `get` answers every one | issue 426 |
| 3 | designs and the glossary's entries as records, moved in one delivery, and each design's state worked out by the knowledge base (§ 9.1 to § 9.3; ADR 0423, ADR 0424) | `get` answers design 47 with its sections and links, a word's entry answers from the knowledge base, and a design's state follows its issues' deliveries without anyone writing it | issue 428 |
| 4 | meeting notes, drawings and blog posts | not decided; needs its own decision | issue 429 |
| 5 | the records on the bus, written and reviewed by section, the move off the store and the titles (§ 1, § 2, § 4, § 5, § 8.1; ADR 0592), delivered as the mesh-sdk release sdk1, then mesh-knowledge, with claude-code's `judged` event beside | the acceptance tests of the fifth slice in § 10, live; the knowledge base requires no database | the issues its hand-off opens (playbook 04) |
Numbers from the issue tracker, which `reserve` needs, are the tracker's own slice, tracked by issue 424. This
repository keeps no copy of the records, generated or otherwise (issue 435, answered by the operator). Playbooks
@@ -299,6 +592,45 @@ milestones and nothing of how a delivery runs; it only listens for the announcem
| An answer stays within its bound | the module's test over the full import of `main` at a recorded commit: every `ask`, `get` and `holds` of a fixed question list |
| A record written in this repository meanwhile writes its clauses | `records.py`, check `clauses`, on every hq pull request, until the records left this repository (issue 426); since then `records.py`, check `no-records`, refuses any record written here |
| Live | the acceptance sentence, asked from a session outside this repository |
| A record is kept in the bus's forms, a section once by its digest, and read only as announced | one integration test that starts the module whole against a real bus server: a record of three sections and a second version changing one give one head, two version messages and four objects; a module with no `grant` in `readers` is refused the streams and the object bucket |
| Search answers from the index as it did from the store | a unit test over a fixed set of records and a fixed question list; the integration test restarts the module and asks again |
| A draft is written by section and has one author, and a take-over tells the previous one | unit tests of each verb of § 4, of a refusal naming the author, and of `take-over` emitting `taken-over`; a take-over refused while the operator's Approve is waited for |
| A stream that keeps its history, and an object bucket of a module's own | in the integration test: a history stream at its cap refuses a new message and keeps its oldest; an object no version or draft names is removed after a day, one still named is kept; unit tests of registration refusing a name already taken |
| A long record is judged whole, one part at a time | unit tests: the frame never passes 16 KiB and says what it cut, with twenty clauses of 2000 bytes and a 40 KiB Context; every question stays under 60 KiB with a 40 KiB section and that frame, and the head part with 40 KiB of clauses; a section over 40 KiB is refused saying split it; an unchanged section keeps its review, a changed frame asks it again |
**The fifth slice's tests, one per failure path** (ADR 0592; the review by architectural domain's testing ruling). Unit tests are
table-driven; one integration test starts the module whole against the real bus server. The module's count today is
1 integration and 104 unit tests; these add about 20 table cases and stay within the budget of 50 and 500.
| Failure path | Test |
|---|---|
| two writes race on one draft | unit: the second compare-and-set loses, is retried, and is refused with the reason past its tries |
| `submit` races `take-over` | unit: one wins; the other is refused naming the new author or the new version |
| two reservations race | unit: two numbers, or one refused; never one number twice |
| a write cut between the stream and the head | unit: the call answered that the version is taken; a start completes the head from the stored version and sends the event once |
| a failure before the version is stored | unit: the call is refused, and no head, event or version follows later |
| a change through the bus during the move | unit: read back from the database, so a rollback of the delivery reads a current database (ADR 0592 §14) |
| a section changed after the operator's Approve | unit: the record is asked again; a version with every section unchanged is not (ADR 0592 §21) |
| a named digest has no object | unit: health unhealthy, naming it; the integrity tool restores it from given text |
| a body does not hash to its name | unit: the read refuses it, naming the digest |
| a full object bucket | integration: a write refused naming the cap; health unhealthy |
| a full history stream | integration: `submit` refused with the head unchanged |
| a judge timeout for one part | unit: that part stays asked and the version proposed, saying which; the others keep their verdicts |
| a restart with parts asked | integration: the parts in `asked` are collected again and judged |
| `reviewed` once per version | unit: one `reviewed` after the last `part-reviewed`, carrying every verdict |
| told once | unit: a whole-set finding told once across a restart, again only after its mark is cleared |
| a second run of the move | unit: changes nothing and says so |
| the move's check | unit: a changed review, a missing finding and a missing ask, each named |
| writes during the switch | unit: every writing verb refused with its reason; reading verbs answer |
| an older judge | the indexer's judge test (release sdk1): a manifest with `objects` or `retention: history` refused by a judge that does not know them, accepted by one that does |
| the grants part's forms | the grants part's test (release sdk1), against a real bus server: an object bucket and a history stream created for their module; a read-only grant on that one bucket for a module named in `readers`, removed at the next composition once withdrawn; the condition at 75 percent raised and cleared below |
| a reference | unit: "record › title › row" resolves to the section; a nested title is refused |
| a form-only version | unit: accepted when only names and links changed and each target resolves; refused otherwise |
| an unproven caller | unit: `open`, `write`, `submit`, `propose` and `take-over` refuse it |
| the index behind | unit: health unhealthy while the index's revision is behind `heads`; `ask` refuses "index not built" |
| the start | integration: the time to a built index measured and reported |
| A section is a part with a title | a table test, one case per refused name and text of § 2.2; a form-only version whose text changed beyond its links is refused |
| Every bucket has a tool, and health says the index | the manifest test compares tools and events with the code; a unit test of the health before and after the index is built |
**The third slice's acceptance tests** (§ 9.1 to § 9.3; research 062's direction), what its build proves before it
is done:
@@ -320,7 +652,50 @@ is done:
9. Tests 1 to 8 pass together after the one delivery, run against main and the live knowledge base, with nothing
in this repository, the catalog or the instruction text pointing at a removed path.
**The fifth slice's acceptance tests** (§ 1, § 2, § 4, § 5, § 8.1; ADR 0592), what its build proves before it is
done:
1. The move's check, run live, names no difference between the database and the bus: 656 decision records and 80
research efforts (the counts of 2026-11-02, or the counts on the day), every version, clause and link, and the
digest of every section of every version.
2. The operator is told that result and asked before the database is dropped; after the yes and the delivery, the
module's manifest requires no database and the store holds none for it.
3. A session writes a research effort of more than 100 KiB one section at a time from one node; a session on another
node takes the draft over with a reason, the first session hears `taken-over`, and the second submits it.
4. Every changed section of that effort is judged on its own, each question under 60 KiB, and the effort is
accepted once every part approves.
5. A section named like a file, a text holding a local path, and a section over 40 KiB are each refused, the last
saying split it.
6. After the titles' form-only versions, no record holds a section named like a file, `history` shows each as a
change of form, and `get` of "research 062 › Direction" answers that section.
7. The fill tool shows each bucket and stream against its cap; the second version of a record with one changed
section adds one object, not one per section.
8. During the move's window a `write` is refused saying the knowledge base is moving; after the switch a restart
still serves from the bus; the health names the source and the check's result.
9. A part's review waiting on the judge survives a restart of the module, and one past 30 minutes reaches the
operator once.
10. Every test of the table above passes in the one check of the pull requests, within the test budget.
## What it leaves out
Semantic or vector search; a browser view; line comments on a proposal (the judgement's findings name the section and
Semantic or vector search; a browser view (its reading of the buckets is announced, ADR 0592); line comments on a proposal (the judgement's findings name the section and
clause instead); and the rules of how-we-build, which are not decision records. Each needs a decision of its own.
## Reviewed by architectural domain
The fifth slice was reviewed by architectural domain on 2026-11-02 (four reviewers, two architectural domains each; the knowledge base's own
review of ADR 0592's fourth version beside), and the lead ruled on every finding. What was found, and what answers it:
| Architectural domain | Found | Answered by |
|---|---|---|
| security | unproven callers could write or take over; an Approve did not bind the sections shown; readers were named outside ADR 0363's grant (the knowledge base's review of version 6); a proposal waiting on the operator could be taken over; readers' grants and a body's match with its name were unsaid; a draft had no bound | ADR 0592 §4, §8, §9, §17, §19, §20, §21; § 2.1, § 4 |
| seams | asked parts lived only in memory; told marks and reservations had no form on the bus; the judge's ticket is polled; who creates buckets and grants was unsaid; the judge is a module's tool, not a seat | ADR 0592 §2, §7, §16, §23; § 1, § 5 (the judge's seat a note on issue 1956), § 8.1 |
| running qualities | three writes could stop halfway; caps had no figures; a usual revision judged every section again, with no limit on parallel calls; start time unknown | ADR 0592 §10, §22, §25; § 1, § 2.1 (caps), § 5 |
| health | a stale index, a missing body, a full bucket and the move's state were not visible; waiting reviews and idle drafts were not counted | ADR 0592 §25, §33; § 1.1 |
| events and logs | per-part verdicts would have broken every wait on `reviewed`; events did not say what they touched; a take-over's reason and each section's author were lost after 30 days | ADR 0592 §3, §27, §34; § 1.1 (the events table) |
| testing | each failure path lacked a test; the budget was not counted | ADR 0592's How it is checked; § 10 (the failure-path table) |
| upgrade | writes during the switch, a rollback after it, and the order of the three deliveries were unsaid; the form-only check did not prove new link targets | ADR 0592 §13 to §16, §31; § 8.1, § 2.2 |
| tools | unnamed objects, missing bodies, form-only versions, asked parts and told marks had no tool | ADR 0592 §32; § 1.1 (the tools table) |
The knowledge base's review of the fourth version found that the reference form read as nested sections: ADR 0592
§30 and § 2.2 say sections never nest.
+4 -1
View File
@@ -11,7 +11,10 @@ amendment, issues, build handoff, constitution sync) is documented there, and ag
through them. Thin skills in `.claude/skills/` wrap these playbooks for invocation
(`hq-new-research`, `hq-graduate`, `hq-new-issue`, `hq-diagnose`, `hq-amend-design`,
`hq-handoff`, `hq-sync-constitution`, `hq-status`, `hq-cleanup`); each defers to its playbook as
authoritative and adds only the mechanical scaffolding.
authoritative and adds only the mechanical scaffolding. Four reviewer agents in `.claude/agents/` carry
playbook 01's *Review by architectural domain*, two architectural domains each:
`review-security-and-upgrade`, `review-seams-and-tools`, `review-running-and-testing` and
`review-health-and-events`; the lead starts all four side by side and rules on their findings.
## The development cycle