Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0ac729070 |
@@ -1,31 +0,0 @@
|
|||||||
---
|
|
||||||
name: mesh-code-reviewer
|
|
||||||
description: Reviews one change of the Novox mesh before it is pushed (hq playbook 07, the review; at most three rounds): against what the knowledge base decides and the mesh's paths, and whether its tests prove it. Read-only; reports findings, never fixes.
|
|
||||||
tools: Read, Grep, Glob, Bash, mcp__mesh__mesh_call, mcp__mesh__mesh_describe, mcp__mesh__mesh_search
|
|
||||||
model: opus
|
|
||||||
---
|
|
||||||
|
|
||||||
You review one change of the Novox mesh for the lead who started you, independently of who built it. The
|
|
||||||
caller's handover names the issue, the decision records, the branch, the worktrees and their commits, and the
|
|
||||||
round.
|
|
||||||
|
|
||||||
**First, what the mesh already knows.** Ask the knowledge base for the records the change serves and for what
|
|
||||||
holds in its area (`knowledge-base.ask`, `knowledge-base.holds`, `knowledge-base.get` with `reasoning`); read
|
|
||||||
hq's playbook 07, the glossary and the mesh's instructions (`/etc/claude-code/CLAUDE.md`). You judge the change
|
|
||||||
against those, not only against its own prepare.
|
|
||||||
|
|
||||||
**What makes it wrong** (a finding):
|
|
||||||
- it contradicts a decision in force, or does not do what its record's clause says;
|
|
||||||
- an interaction that is not a mesh path: one module naming another, reading another's internals or being
|
|
||||||
special-cased in another part; a module's name in shared code; state only in memory; a poll or a timer where
|
|
||||||
an event exists; a new state without a tool that reads it or a new behaviour without a tool that steers it;
|
|
||||||
- a test that does not fail without its change (check it by taking the change out in a copy), a new test
|
|
||||||
function where the repository is over budget, real sleeping;
|
|
||||||
- vet or tests that fail: run `go vet ./...`, `go vet -tags integration ./...` and `go test ./...` in every
|
|
||||||
touched module, as the running checker places siblings.
|
|
||||||
|
|
||||||
Anything else (hardening, a further case, a nicer form) is a note, never a round. Read only: no edits, no git
|
|
||||||
write, no verb that writes, never ssh. Use a temporary directory under `/var/tmp`.
|
|
||||||
|
|
||||||
Answer **APPROVED at** the full commit ids, or numbered findings each with file:line, what is wrong, and the
|
|
||||||
fix; notes apart. Under 25 lines, glossary words only.
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
---
|
|
||||||
name: mesh-developer
|
|
||||||
description: Builds one prepared change of the Novox mesh in local worktrees on a feature branch (hq playbook 07, develop; playbook 08): code and tests, committed locally, never pushed. Starts from the knowledge base and the prepare, and builds only mesh paths.
|
|
||||||
tools: Read, Grep, Glob, Bash, Edit, Write, mcp__mesh__mesh_call, mcp__mesh__mesh_describe, mcp__mesh__mesh_search
|
|
||||||
model: sonnet
|
|
||||||
---
|
|
||||||
|
|
||||||
You build one change of the Novox mesh for the lead who started you. The caller's handover names the issue, the
|
|
||||||
decision records, the prepare file, the branch name and the worktrees.
|
|
||||||
|
|
||||||
**First, what the mesh already knows.** Read the prepare file, then ask the knowledge base for every record it
|
|
||||||
names and anything it missed (`knowledge-base.ask`, `knowledge-base.get` with `reasoning`). Read hq's playbook
|
|
||||||
07 (`00-META/process/07-feature-branches.md`), the glossary and the mesh's instructions
|
|
||||||
(`/etc/claude-code/CLAUDE.md`). Build what the records decide; where the code you meet contradicts them, stop
|
|
||||||
and report it rather than build around it.
|
|
||||||
|
|
||||||
**Build only mesh paths.** Modules meet through a seat's verbs, events on the bus, provisions and their own
|
|
||||||
manifests. Never make one module name another, read another's internals, or special-case one module in another
|
|
||||||
part; never put a module's name into shared code (mesh-sdk). Keep state on the bus (a key-value bucket, a stream,
|
|
||||||
the object store), never only in memory, and react to events, not timers. For every new state add a tool that
|
|
||||||
reads it, for every new behaviour a tool that steers it. If the change cannot be built without one of these,
|
|
||||||
stop and report it.
|
|
||||||
|
|
||||||
**How you work.** Worktrees from `origin/main` on the branch the handover names; commit per subtask, locally
|
|
||||||
only: never push, never open a pull request, never call a verb that writes on the mesh (reads are fine). Never
|
|
||||||
ssh, never a shell helper for the mesh. Tests: every change carries a test that fails without it (check it);
|
|
||||||
rows or subtests in existing tests where the repository is over the test budget the instructions set; no real
|
|
||||||
sleeping. Run `go vet ./...`, `go vet -tags integration ./...` and `go test ./...` in every touched module as
|
|
||||||
the running checker places siblings (playbook 07). Use a temporary directory under `/var/tmp` (TMPDIR).
|
|
||||||
|
|
||||||
Report in under 20 lines: per clause or subtask the change (file:line) and its test, that each test failed
|
|
||||||
first, the full commit ids, anything the prepare got wrong, and what is left. Glossary words only.
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
---
|
|
||||||
name: mesh-preparer
|
|
||||||
description: Prepares one milestone or small fix of the Novox mesh before any code is written (hq playbook 07, the prepare step; playbook 08): what the knowledge base already decides, the mesh path of every interaction the change adds, every file and test it touches, the subtasks and the release order. Read-only but for its prepare file.
|
|
||||||
tools: Read, Grep, Glob, Bash, Write, mcp__mesh__mesh_call, mcp__mesh__mesh_describe, mcp__mesh__mesh_search
|
|
||||||
model: opus
|
|
||||||
---
|
|
||||||
|
|
||||||
You prepare one change of the Novox mesh for the lead who started you. The caller's handover names the issue,
|
|
||||||
the decision records and the design it serves, and where your prepare file goes. You write that one file and
|
|
||||||
nothing else; you call no verb that writes and make no git write.
|
|
||||||
|
|
||||||
**First, what the mesh already knows.** Before you read any code, ask the knowledge base (`knowledge-base.ask`
|
|
||||||
with the change in plain words, `knowledge-base.holds` for its topic, `knowledge-base.get` with `reasoning` for
|
|
||||||
each record it names) and the issue tracker (`issue-tracker.get`, `issue-tracker.list` with `search`). List the
|
|
||||||
decisions and principles that hold for this change, each by number and clause. Read the design it serves in hq
|
|
||||||
(`03-DESIGN/`), hq's glossary (`00-META/glossary.md`) and the mesh's instructions (`/etc/claude-code/CLAUDE.md`).
|
|
||||||
Code shows what exists, not what was decided: where the code and the records disagree, say so.
|
|
||||||
|
|
||||||
**Then map every interaction the change adds onto a mesh path**, before any file: which seat and verb, which
|
|
||||||
event, which provision (requires and provides), which state on the bus (key-value bucket, stream, object store)
|
|
||||||
and which module owns it, which field of a module's own manifest. A module that names another module, reads
|
|
||||||
another's internals, or is special-cased in another part is not a mesh path: name it as a finding and give the
|
|
||||||
mesh-shaped alternative. Shared code (mesh-sdk) holds only seat contracts and what every module shares, never a
|
|
||||||
module's name.
|
|
||||||
|
|
||||||
**Then the work**, as playbook 07's prepare step says: per repository every file and test the change touches,
|
|
||||||
by clause of the record; subtasks of about thirty minutes, one change each, with their acceptance; the test
|
|
||||||
budget (rows in existing tests where a repository is over budget); which parts judge the change (indexer, judge,
|
|
||||||
checker, builders, grants part, node-engine) and what the running ones accept; for every new state a tool that
|
|
||||||
reads it and for every new behaviour a tool that steers it. Code: read the repositories at `origin/main`
|
|
||||||
(`git fetch`, `git show`, `git grep`), never a working tree.
|
|
||||||
|
|
||||||
Report to the caller in under 30 lines: the records that hold, the mesh path of each interaction, the findings
|
|
||||||
where the change or its records are not mesh-shaped, the release order, and the open questions with your
|
|
||||||
recommendation. Glossary words only; a guess is said as one.
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
---
|
|
||||||
name: mesh-watcher
|
|
||||||
description: Follows one thing the lead waits on in the Novox mesh (a pull request's check, a merge, a delivery, a decision's Approve, an answer on Telegram) and reports when it lands, fails, or stands still. Read-only; never acts.
|
|
||||||
tools: mcp__mesh__mesh_call, mcp__mesh__mesh_wait, mcp__mesh__mesh_describe, mcp__mesh__mesh_search
|
|
||||||
model: sonnet
|
|
||||||
---
|
|
||||||
|
|
||||||
You watch one thing for the lead who started you. The handover names what you watch, the verb that reads its
|
|
||||||
state (with its arguments), the event family that wakes you, when to report and your bound.
|
|
||||||
|
|
||||||
**First, the owner's event.** Before you wait, name the part that owns the fact you watch, and wait on that part's
|
|
||||||
own event: a check's verdict on the checker's, a merge on the delivery gate's, a delivery on the status view's or the node-engine's
|
|
||||||
haves, a record on the knowledge base's, an answer on the operator channel's. Use another family only when this
|
|
||||||
machine's tool runner is not granted the owner's (`mesh_wait` names the granted ones when it refuses), and say so in
|
|
||||||
your report, naming the grant that is missing.
|
|
||||||
|
|
||||||
Loop: wait with `mesh_wait` on the event family (its answer only wakes you), then read the state from the verb
|
|
||||||
the handover names; never report a state you did not read in that round. Report and end at the first of: the
|
|
||||||
thing reached its end (passed, merged, delivered, accepted, chosen, declined), it failed (quote every failure
|
|
||||||
line word for word), five minutes passed with no change while something should be moving (say what you last
|
|
||||||
read and when), the bound passed, or a call failed twice (quote it).
|
|
||||||
|
|
||||||
You only read: no verb that writes, never ssh, never a shell helper. Report in a few lines, with times in UTC as
|
|
||||||
the tools give them; the lead says them to the operator in local time.
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
---
|
|
||||||
name: research-reader
|
|
||||||
description: Carries one reading task of a research effort's step 5 (hq playbook 01, Do the research) - reads the code on main, counts from the manifests, or tries a program's behaviour in process, and reports facts with their repository, commit and function. Read-only on the mesh and every working copy.
|
|
||||||
tools: Read, Grep, Glob, Bash, mcp__mesh__mesh_call, mcp__mesh__mesh_describe, mcp__mesh__mesh_search
|
|
||||||
model: sonnet
|
|
||||||
---
|
|
||||||
|
|
||||||
You carry one reading task of a research effort of the Novox mesh (hq playbook 01, step 5, *Do the research*).
|
|
||||||
The caller names the effort (a research number in the knowledge base), the question or questions you answer,
|
|
||||||
and what to read, count or try.
|
|
||||||
|
|
||||||
Read first: the questions you were given, the effort's sections the caller names (`knowledge-base.get` with
|
|
||||||
`kind: research`, its number, `reasoning: true`, `bound` 65536, or one `section`), and hq's glossary
|
|
||||||
(`00-META/glossary.md`). Then the code.
|
|
||||||
|
|
||||||
How you read:
|
|
||||||
|
|
||||||
- **Code on main only, never a working copy's checkout.** Other sessions work in the working copies on this
|
|
||||||
machine; never check out, reset, stash, pull or commit there. Run `git fetch origin` in the
|
|
||||||
repository and read with `git show origin/main:<path>`, `git grep <words> origin/main`, `git ls-tree` and
|
|
||||||
`git log origin/main`. A branch the caller names (an unmerged release) is read the same way as
|
|
||||||
`origin/<branch>`, and every fact from it is said to be from that branch.
|
|
||||||
- **Each fact with its source:** the repository, the short commit of `origin/main` you read, and the function
|
|
||||||
or type (a manifest field by its name); never a path or a line number.
|
|
||||||
- **Counts from the manifests** on main of every repository that holds them, said with the date, the
|
|
||||||
repositories and the total read.
|
|
||||||
- **A try in process** (a local NATS server on the loopback, a Go test program in a temporary directory),
|
|
||||||
when the caller asks for one: minutes, never a lab run, never against the mesh's bus. Say what you ran and
|
|
||||||
what it printed.
|
|
||||||
- Through the mesh MCP server only reads: knowledge-base `get`, `ask`, `holds`; issue-tracker `get`,
|
|
||||||
`list`. Call no verb that writes.
|
|
||||||
|
|
||||||
Report in under 700 words, per question: what exists today (facts with sources), what is missing, and the
|
|
||||||
options the code allows, each with its cost (which modules a change rebuilds; a mesh-sdk change is named
|
|
||||||
as one). Separate fact from guess: a guess is said as one, with how to check it. Write plain words in the
|
|
||||||
glossary's words. Say what you read and what you could not.
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
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*).
|
|
||||||
|
|
||||||
**First, what the mesh already knows.** Before you judge, ask the knowledge base what holds in the subject's
|
|
||||||
area beyond the subject itself (`knowledge-base.ask` with its topic in plain words, `knowledge-base.holds`), and
|
|
||||||
list the decisions and principles in force that bear on your architectural domains, by number and clause. Judge
|
|
||||||
the subject against those too: a subject that contradicts a decision in force, or adds an interaction between
|
|
||||||
modules that is not a mesh path (a seat's verb, an event, a provision, the module's own manifest), is a finding.
|
|
||||||
|
|
||||||
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.
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
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*).
|
|
||||||
|
|
||||||
**First, what the mesh already knows.** Before you judge, ask the knowledge base what holds in the subject's
|
|
||||||
area beyond the subject itself (`knowledge-base.ask` with its topic in plain words, `knowledge-base.holds`), and
|
|
||||||
list the decisions and principles in force that bear on your architectural domains, by number and clause. Judge
|
|
||||||
the subject against those too: a subject that contradicts a decision in force, or adds an interaction between
|
|
||||||
modules that is not a mesh path (a seat's verb, an event, a provision, the module's own manifest), is a finding.
|
|
||||||
|
|
||||||
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.
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
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*).
|
|
||||||
|
|
||||||
**First, what the mesh already knows.** Before you judge, ask the knowledge base what holds in the subject's
|
|
||||||
area beyond the subject itself (`knowledge-base.ask` with its topic in plain words, `knowledge-base.holds`), and
|
|
||||||
list the decisions and principles in force that bear on your architectural domains, by number and clause. Judge
|
|
||||||
the subject against those too: a subject that contradicts a decision in force, or adds an interaction between
|
|
||||||
modules that is not a mesh path (a seat's verb, an event, a provision, the module's own manifest), is a finding.
|
|
||||||
|
|
||||||
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.
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
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*).
|
|
||||||
|
|
||||||
**First, what the mesh already knows.** Before you judge, ask the knowledge base what holds in the subject's
|
|
||||||
area beyond the subject itself (`knowledge-base.ask` with its topic in plain words, `knowledge-base.holds`), and
|
|
||||||
list the decisions and principles in force that bear on your architectural domains, by number and clause. Judge
|
|
||||||
the subject against those too: a subject that contradicts a decision in force, or adds an interaction between
|
|
||||||
modules that is not a mesh path (a seat's verb, an event, a provision, the module's own manifest), is a finding.
|
|
||||||
|
|
||||||
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.
|
|
||||||
@@ -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.
|
number is spent; never pick one by hand.
|
||||||
3. **Propose the effort.** `mesh_call knowledge-base.propose` with `kind: research`, the reserved `number`,
|
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`;
|
`title`, `status: active`, `date` (today), `sections` (the documents in order, each `name` and `text`;
|
||||||
each named by a plain title, never as a file; the first, **Overview**: **what** is investigated, **why**, and **what it touches**), and `links`
|
the first `00-overview.md`: **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).
|
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
|
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
|
effort whole and `why`. A refusal names every rule broken: fix them all and propose again. On review
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
.work/
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const (
|
|||||||
linesFrom = "2026-10-09"
|
linesFrom = "2026-10-09"
|
||||||
)
|
)
|
||||||
|
|
||||||
var wordsAlways = []string{"00-META/", "03-DESIGN/", ".claude/", "AGENTS.md", "README.md"}
|
var wordsAlways = []string{"00-META/", "03-DESIGN/", "AGENTS.md", "README.md"}
|
||||||
|
|
||||||
// daemonLines are the daemons' lines (ADR 0272): each daemon's commands. "alone" is a command that is a line by
|
// 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;
|
// itself; "with an argument" one that is a line only when written as one ("the mesh-controller module" is prose;
|
||||||
|
|||||||
+6
-68
@@ -30,8 +30,7 @@ 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
|
- **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.
|
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
|
- **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); its qualified form is **mesh domain**. Bare, "domain" keeps this sense; the
|
in the section above (ADR 0244).
|
||||||
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
|
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
|
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).
|
the controller, the domain owns that store alone (ADR 0008).
|
||||||
@@ -117,8 +116,6 @@ downstream of Module and Placement. **Decided by** ADR 0262, 0277, 0348.
|
|||||||
**Uses:** module, node, manifest (Module), assignment (Placement), provision (Provisioning), proposal
|
**Uses:** module, node, manifest (Module), assignment (Placement), provision (Provisioning), proposal
|
||||||
(Operator and conversation).
|
(Operator and conversation).
|
||||||
|
|
||||||
- **template file** — a file a module ships with placeholders, such as `${config:<key>}`, which the provisioner
|
|
||||||
client fills on each node (ADR 0349). Never a template of bus state (see [Homonyms](#homonyms)).
|
|
||||||
- **config value** — anything a module reads that someone may change: a font size, a domain, an address.
|
- **config value** — anything a module reads that someone may change: a font size, a domain, an address.
|
||||||
A module declares every one it reads under `config` in its manifest, with a type, a description,
|
A module declares every one it reads under `config` in its manifest, with a type, a description,
|
||||||
validation, whether it is trusted, optionally the predefined key it falls back to, and a default or
|
validation, whether it is trusted, optionally the predefined key it falls back to, and a default or
|
||||||
@@ -215,8 +212,7 @@ every other domain has something to run on. **Recorded by** the controller and t
|
|||||||
A module reaches it by requiring `mesh-bus` (ADR 0128);
|
A module reaches it by requiring `mesh-bus` (ADR 0128);
|
||||||
one that does not require it has no account on it. Held by the `mesh-broker` seat, which is named
|
one that does not require it has no account on it. Held by the `mesh-broker` seat, which is named
|
||||||
after the role rather than the server, so the server can change without the seat doing so. The `nats`
|
after the role rather than the server, so the server can change without the seat doing so. The `nats`
|
||||||
module holds it. The **bus module** is the module holding `mesh-broker`; it also provides bus state (Data,
|
module holds it.
|
||||||
ADR 0595).
|
|
||||||
- **the deprecated broker** — the lavinmq module. It was the mesh's bus and is not any more. It keeps
|
- **the deprecated broker** — the lavinmq module. It was the mesh's bus and is not any more. It keeps
|
||||||
running as an **ordinary provider** of the `amqp` provision, for modules that need a message broker
|
running as an **ordinary provider** of the `amqp` provision, for modules that need a message broker
|
||||||
of their own the way something needs a database
|
of their own the way something needs a database
|
||||||
@@ -727,8 +723,8 @@ becomes a message). **Decided by** ADR 0227, 0231, 0240, 0252, 0283, 0564.
|
|||||||
|
|
||||||
**Purpose.** To know every item of data a module holds, how precious it is, and to keep it recoverable.
|
**Purpose.** To know every item of data a module holds, how precious it is, and to keep it recoverable.
|
||||||
**Recorded by** the manifests' `data` declarations and every node's `node-backup` seat.
|
**Recorded by** the manifests' `data` declarations and every node's `node-backup` seat.
|
||||||
**Upstream of** Delivery and Health and repair. **Decided by** ADR 0232, 0233, 0235, 0571, 0595, 0596, 0597.
|
**Upstream of** Delivery and Health and repair. **Decided by** ADR 0232, 0233, 0235, 0571.
|
||||||
**Uses:** module, node, provider and consumer (Provisioning), person, bus module (Core), tool runner (Core).
|
**Uses:** module, node, provider and consumer (Provisioning), person.
|
||||||
|
|
||||||
- **data class** — how precious an item of data is, ranked by the operator: `irreplaceable`,
|
- **data class** — how precious an item of data is, ranked by the operator: `irreplaceable`,
|
||||||
`valuable`, `rebuildable`, `cache`; and `none` for a provision that keeps nothing of anybody's
|
`valuable`, `rebuildable`, `cache`; and `none` for a provision that keeps nothing of anybody's
|
||||||
@@ -743,25 +739,6 @@ becomes a message). **Decided by** ADR 0227, 0231, 0240, 0252, 0283, 0564.
|
|||||||
self-check read them there, never the controller (ADR 0571 §5).
|
self-check read them there, never the controller (ADR 0571 §5).
|
||||||
- **sticky binding** — a consumer's tie to the data a provider keeps for it, which moves only by a
|
- **sticky binding** — a consumer's tie to the data a provider keeps for it, which moves only by a
|
||||||
person (ADR 0232).
|
person (ADR 0232).
|
||||||
- **bus state** — what a module keeps on the bus, asked for in `requires` as a provision of the bus module, by a
|
|
||||||
template and its options; created by the bus module and reached by the owner's account alone. Another module
|
|
||||||
asks the owner's tools for its data, or hears its declared events (ADR 0595, ADR 0596).
|
|
||||||
- **storage type** — how the bus keeps bus state: the **stream**, the base, or one built on it, the **key-value
|
|
||||||
bucket**, the **object store** or the **ledger**, each with calls of its own (ADR 0595 §2).
|
|
||||||
*Not:* ~~data type~~
|
|
||||||
- **configuration** of a storage type — the settings it is given: what is kept, for how long, how much, and what
|
|
||||||
happens when full. Never bare where it could be read as a config value (see [Homonyms](#homonyms)).
|
|
||||||
- **template** — a storage type with a configuration, predefined and named: **state**, **events**, **work
|
|
||||||
queue**, **log**, **objects** and **ledger** (ADR 0595 §2). What keeps its data safe, "when full" among it, is
|
|
||||||
fixed by the template. *Template of bus state* where it could be read as a template file (see
|
|
||||||
[Homonyms](#homonyms)). The template log is the module log of ADR 0297.
|
|
||||||
- **option** of a template — one setting a module may change, within its bound, such as state's past values (1 to
|
|
||||||
64) (ADR 0595 §3).
|
|
||||||
- **ledger** — a storage type keeping, per instance of a type, a history of every **operation** (one change, kept
|
|
||||||
in order) and a state derived from that history by each operation's **ledger effect** (one of a fixed set: set
|
|
||||||
fields, set an entry of a map, append to a list, remove), through the tool runner's `apply` (ADR 0597).
|
|
||||||
- **snapshot** of a ledger's state — the latest state of one instance, on a subject of its own, never expiring,
|
|
||||||
from which a rebuild starts; distinct from the stream snapshot.
|
|
||||||
|
|
||||||
## Connectivity — how nodes and modules reach one another
|
## Connectivity — how nodes and modules reach one another
|
||||||
|
|
||||||
@@ -989,7 +966,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.
|
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,
|
**Recorded in** this repository, the issue tracker and the knowledge base. **Decided by** ADR 0019, 0080, 0244, 0275,
|
||||||
0284, 0290, 0291, 0423, 0424, 0592.
|
0284, 0290, 0291, 0423, 0424.
|
||||||
|
|
||||||
- **research effort**, **graduation**, **hand-off**, **playbook** — an investigation, held whole in the
|
- **research effort**, **graduation**, **hand-off**, **playbook** — an investigation, held whole in the
|
||||||
knowledge base and named "research NNN";
|
knowledge base and named "research NNN";
|
||||||
@@ -1007,33 +984,10 @@ 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,
|
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`
|
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
|
([55 — The knowledge base](../03-DESIGN/01-to-be/55-the-knowledge-base.md)). Not **the record**, the literal reader
|
||||||
of this repository. It keeps them on the bus: each record's head in its state, its versions on a stream, its
|
of this repository.
|
||||||
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)
|
- **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
|
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/`.
|
(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
|
- **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
|
from the issues with a design link to it and whether their deliveries are done; never written by anyone
|
||||||
(ADR 0424).
|
(ADR 0424).
|
||||||
@@ -1096,18 +1050,6 @@ 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 |
|
| | whether the machines a change touches still compose | **composition check** | Delivery |
|
||||||
| membership | the subjects a bus account is issued | **membership** | Provisioning |
|
| membership | the subjects a bus account is issued | **membership** | Provisioning |
|
||||||
| | an account in a group of the machine | **account group** | Placement |
|
| | 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 |
|
|
||||||
| configuration | the settings of a storage type, which a template fixes or a module gives | **configuration** of a storage type | Data |
|
|
||||||
| | anything a module reads that someone may change | **config value** | Config |
|
|
||||||
| snapshot | the latest state of one ledger instance, from which a rebuild starts | **snapshot** of a ledger's state | Data |
|
|
||||||
| | the bus's own backup of each stream | **stream snapshot** | Data |
|
|
||||||
| template | a storage type with a configuration, asked for in `requires` | **template** of bus state | Data |
|
|
||||||
| | a file with placeholders a provisioner fills | **template file** | Config |
|
|
||||||
| option | a setting of a template a module may change | **option** of a template | Data |
|
|
||||||
| | one choice of an ask to a person | an ask's **option** | Operator and conversation |
|
|
||||||
| effect | what an operation does to a ledger's state | **ledger effect** | Data |
|
|
||||||
| | a tool's mark: reads, acts or dangerous | a tool's **effect** | Identity and access |
|
|
||||||
| push | the controller giving nodes their declarations, until release 6 | **send** (verb `push`) | Placement |
|
| push | the controller giving nodes their declarations, until release 6 | **send** (verb `push`) | Placement |
|
||||||
| | a git push | **git push** | The record |
|
| | a git push | **git push** | The record |
|
||||||
| | a phone notification | **push notification** | Operator and conversation |
|
| | a phone notification | **push notification** | Operator and conversation |
|
||||||
@@ -1139,10 +1081,6 @@ 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 |
|
| 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 |
|
| | 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 |
|
| 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 | — |
|
| | 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 |
|
| 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 |
|
| | whether the machines a change touches still compose, the assigner's | **composition check** | Delivery |
|
||||||
|
|||||||
@@ -43,22 +43,16 @@ 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
|
is spent whether or not the effort is ever proposed; one never proposed is withdrawn after a week. Never
|
||||||
pick one by hand.
|
pick one by hand.
|
||||||
4. **Propose it.** `knowledge-base.propose` with `kind: research`, the `number`, a one-line `title`,
|
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`. A
|
`status: active`, `date` (the day it began), and `sections`, each a `name` and its markdown `text`:
|
||||||
section is a part of the record, never a file: its `name` is a plain title, a reference to another section
|
- `00-overview.md`: the idea in the operator's words, what exists, the operator's answers (dated), and the
|
||||||
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;
|
words the effort uses that the glossary lacks, each defined in one line;
|
||||||
- **Questions**: the questions to answer, the first ones first;
|
- `01-questions.md`: the questions to answer, the first ones first;
|
||||||
- **Method**: what will be tried and measured, and on what.
|
- `02-method.md`: 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
|
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`.
|
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
|
5. **Do the research.** Try, measure and read, smallest question first. Each finding goes into
|
||||||
the section **Findings**: what was tried, what it showed (with numbers), what it means. Each change of the effort
|
`04-findings.md`: 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`
|
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
|
lists them and gives the difference between two. Until issue 844 is delivered, the knowledge base
|
||||||
takes a new version of an accepted, active effort only as a progressive insight: give `insight`, saying
|
takes a new version of an accepted, active effort only as a progressive insight: give `insight`, saying
|
||||||
@@ -75,51 +69,20 @@ 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
|
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
|
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.
|
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 the section **Domains**: the domain or domains the idea
|
6. **Place it in the domains.** Before the direction, write `03-domains.md`: 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
|
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),
|
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);
|
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
|
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
|
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.
|
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 the section **Direction**:
|
7. **Settle the direction with the operator.** When the questions are answered, write `05-direction.md`:
|
||||||
the proposed decisions in a few lines each, the options rejected and why, and the build's acceptance
|
the proposed decisions in a few lines each, the options rejected and why, and the build's acceptance
|
||||||
tests: what the build must prove before it is done, carried by its milestones (playbook
|
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
|
[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
|
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 review it by architectural domain (below) and
|
operator to confirm or change the direction, one point at a time, then propose it once. Then the effort
|
||||||
propose it once. Then the effort graduates through playbook [02](02-graduation.md).
|
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
|
## Bounds and models
|
||||||
|
|
||||||
@@ -127,10 +90,9 @@ found and how it was answered, or that nothing was found.
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| reading and the setup questions (1, 2) | 30 minutes | the session's own, larger |
|
| reading and the setup questions (1, 2) | 30 minutes | the session's own, larger |
|
||||||
| proposing (3, 4) | 15 minutes | larger |
|
| proposing (3, 4) | 15 minutes | larger |
|
||||||
| each experiment or reading task (5) | 30 minutes | smaller, one agent at a time unless the operator allows more: the agent `research-reader` |
|
| 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 |
|
| placing it in the domains (6) | 15 minutes | larger |
|
||||||
| the direction (7) | 30 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
|
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,
|
as playbook 07 does: every ten minutes and at once when something is found, stops or needs the operator,
|
||||||
@@ -172,8 +134,7 @@ 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
|
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
|
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
|
against the rules, one version per settled set, the cheapest level, nothing left open) are the lead's, read by
|
||||||
the reviewer; the review by architectural domain is read in the direction's *Reviewed by architectural domain* section (nothing refuses a direction
|
the reviewer; of the pre-check, `propose` refuses a link to nothing and a retired word, and the review returns
|
||||||
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
|
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
|
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.
|
for seven days is the smell of research left behind: its lead closes or continues it.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ clauses in force for a topic or a record).
|
|||||||
|
|
||||||
## Graduating research
|
## Graduating research
|
||||||
|
|
||||||
The effort's Direction, confirmed by the operator (playbook [01](01-research.md), step 7), is what
|
The effort's `05-direction.md`, 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
|
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.
|
about an hour, and said to the operator if it runs past.
|
||||||
|
|
||||||
@@ -49,11 +49,9 @@ 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. Before it is
|
The design lists the direction's acceptance tests: what the build proves before it is done.
|
||||||
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 Domains go into the glossary in the same change, each in its domain: a
|
The words of the effort's `03-domains.md` 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
|
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
|
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.
|
homonym with the qualified form each domain uses.
|
||||||
@@ -66,15 +64,6 @@ about an hour, and said to the operator if it runs past.
|
|||||||
|
|
||||||
## Writing a decision record
|
## Writing a decision record
|
||||||
|
|
||||||
**Before a number: what holds, and the mesh path, reviewed.** Ask the knowledge base what is already decided in
|
|
||||||
the record's area (`knowledge-base.ask`, `holds`), and name in the draft, for every interaction between modules the
|
|
||||||
record decides, the seat and verb, event, provision, state on the bus or manifest field that carries it. Then
|
|
||||||
`review-seams-and-tools` reviews the draft before it is proposed: a clause that has one module name another, read its
|
|
||||||
internals or be special-cased in another part, or puts a module's name into shared code, is a finding (the operator,
|
|
||||||
2026-11-03).
|
|
||||||
How it is checked: the record's References name the seams review's verdict; a record proposed without it is a breach
|
|
||||||
the lead names.
|
|
||||||
|
|
||||||
1. **Take a number.** `knowledge-base.reserve` with `kind: decision` and `for`: the record's title. The
|
1. **Take a number.** `knowledge-base.reserve` with `kind: decision` and `for`: the record's title. The
|
||||||
number comes from the issue tracker's counter and is spent whether or not the record is accepted; one
|
number comes from the issue tracker's counter and is spent whether or not the record is accepted; one
|
||||||
never proposed is withdrawn after a week. Never pick a number by hand.
|
never proposed is withdrawn after a week. Never pick a number by hand.
|
||||||
@@ -140,8 +129,7 @@ A design changes only through a decision.
|
|||||||
|
|
||||||
1. Write the decision record (above). If it reverses an earlier one, it `supersedes` it.
|
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:`
|
2. Edit the to-be design document, add the record to its `decisions:` as `"ADR NNNN"`, and set `updated:`
|
||||||
to today. Review it by architectural domain before it is merged (playbook [01](01-research.md#review-by-architectural-domain)), and
|
to today.
|
||||||
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:
|
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
|
`amended-design` on its `issue-tracker.move` to `resolved`, or `issue-tracker.link` with kind
|
||||||
`design` before then — never in the report's frontmatter
|
`design` before then — never in the report's frontmatter
|
||||||
@@ -176,8 +164,7 @@ record (its module's table test holds one case per rule), and the four rules tha
|
|||||||
changes, an accepted record extending a superseded one) run after every acceptance and raise a condition
|
changes, an accepted record extending a superseded one) run after every acceptance and raise a condition
|
||||||
when one fails. In this repository, the records test checks that a design's `decisions:` entries and every
|
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
|
"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. A design's *Reviewed by architectural domain* section is read by the
|
order's six topics, which the knowledge base reads. The three habits of graduating step 2 (side by side, clauses
|
||||||
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,
|
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.
|
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
|
The rounds are read in `knowledge-base.get` (its reviews, one per version): a question to the operator about a
|
||||||
|
|||||||
@@ -44,10 +44,6 @@ 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
|
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
|
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.
|
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
|
- **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.
|
only, then failed live three times (issues 859, 865, 868) and took five more hours of fixes.
|
||||||
|
|
||||||
@@ -59,7 +55,7 @@ opened **once**, after the review, and **one check** (ADR 0548). It runs in five
|
|||||||
|
|
||||||
| Step | What happens | Bound |
|
| Step | What happens | Bound |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 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 |
|
| 0. Prepare | the lead settles the open questions and writes one context file per repository | 15 minutes |
|
||||||
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
||||||
@@ -100,27 +96,7 @@ the running milestone, so the scope above holds. Only an issue in another design
|
|||||||
a time), or one that needs a decision or the operator first, waits, and the report says which and why. Each detailed report's line "Opened along the way" says for every
|
a time), or one that needs a decision or the operator first, waits, and the report says which and why. Each detailed report's line "Opened along the way" says for every
|
||||||
issue whether it is being fixed in between, after the delivery, or waits, and on what.
|
issue whether it is being fixed in between, after the delivery, or waits, and on what.
|
||||||
|
|
||||||
## Step 0 — Prepare (the lead with mesh-preparer, larger model)
|
## Step 0 — Prepare (the lead, larger model)
|
||||||
|
|
||||||
**Agents work from hq's definitions, never from a prompt written by hand.** Every agent the lead starts is one of
|
|
||||||
`.claude/agents/`: `mesh-preparer` for this step, `mesh-developer` for step 1, `mesh-code-reviewer` for step 2,
|
|
||||||
`mesh-watcher` for every wait, and the four reviewers by architectural domain and `research-reader` of playbook 01.
|
|
||||||
The lead writes only the handover: what the agent works on (issue, records, branch, worktrees, commits) and where it
|
|
||||||
reports. A subagent runs in the session that started it, from hq: its way of working comes from its definition and hq's playbooks, its knowledge from the knowledge base; one given a coding task works in a worktree under hq's `.work/` and also reads the conventions of the repository it changes, and where those contradict hq, hq wins and the agent says so. How it works, what it reads first and what it judges come from its definition, and so does its model: a
|
|
||||||
`mesh-developer` runs on the smaller model, and the lead starts one on the larger model only for work whose parts meet
|
|
||||||
at an interface still being designed, written with its reason in the milestone file; a lesson about how an agent
|
|
||||||
works goes into its definition by an hq pull request (the operator, 2026-11-03: "please don't write prompts by hand,
|
|
||||||
only the handover prompt"). How it is checked: the lead's report names each agent by its definition; an agent started
|
|
||||||
from a prompt written by hand is a breach the lead names at the next report.
|
|
||||||
|
|
||||||
**Every prepare starts from the knowledge base and maps every interaction onto a mesh path, and the seams review
|
|
||||||
judges it before code starts.** The preparer lists the decisions in force for the change and the seat, verb, event,
|
|
||||||
provision, state on the bus or manifest field that carries each interaction the change adds; then
|
|
||||||
`review-seams-and-tools` reviews the prepare (and any decision record written for the change) before step 1. A module
|
|
||||||
that names another, reads its internals or is special-cased in another part, or a module's name in shared code, is a
|
|
||||||
finding of that review (the operator, 2026-11-03: "you never follow the mesh paths for inter-module communication").
|
|
||||||
How it is checked: the milestone file carries the seams review's verdict on the prepare; a step 1 started without it
|
|
||||||
is a breach the lead names.
|
|
||||||
|
|
||||||
1. **Name the feature once:** `feat/<slug>`, the same branch name in every repository it touches (but see the
|
1. **Name the feature once:** `feat/<slug>`, the same branch name in every repository it touches (but see the
|
||||||
exception for a new manifest word in phase 3: a release that must merge first has a name of its own). The
|
exception for a new manifest word in phase 3: a release that must merge first has a name of its own). The
|
||||||
@@ -138,33 +114,8 @@ is a breach the lead names.
|
|||||||
2026-10-26: "that is simply our delivery plan and milestones, we've already researched it"); propose new research
|
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
|
only for what no record decides. A fixing agent that meets an undecided design question
|
||||||
stops, and its run is spent again.
|
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
|
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:
|
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
|
- 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
|
with (quoted, with where each was decided), and its acceptance criteria (item 5), each with the test that
|
||||||
proves it;
|
proves it;
|
||||||
@@ -203,9 +154,11 @@ is a breach the lead names.
|
|||||||
hours; it ran past its 30-minute bound for over an hour, and the reports could only say "still on part D".
|
hours; it ran past its 30-minute bound for over an hour, and the reports could only say "still on part D".
|
||||||
6. **List every part the change reaches, before any agent starts**, so each is an issue of the milestone and
|
6. **List every part the change reaches, before any agent starts**, so each is an issue of the milestone and
|
||||||
nothing is found on the way. Read, for each repository of the milestone, what it takes from the others and how:
|
nothing is found on the way. Read, for each repository of the milestone, what it takes from the others and how:
|
||||||
the SDK's users (they pin an SDK commit, and a pin to a commit no branch holds is a download that fails later,
|
the users of every package the change alters, mesh-sdk and each seat's package (a seat's contract is a package its
|
||||||
issue 1148); every program that parses a manifest strictly (search `ParseManifest` across every repository, with
|
holder's repository publishes, and a user takes it as a package, never as another repository's source; each user
|
||||||
the SDK commit each pins), which must take an SDK that knows a new manifest word (2026-10-21: design 60's
|
builds against the latest published version, and in the group's check against the group's head, so nobody writes a
|
||||||
|
version or a commit for them: ADR 0573); every program that parses a manifest strictly (search `ParseManifest`
|
||||||
|
across every repository), which must take an SDK that knows a new manifest word (2026-10-21: design 60's
|
||||||
catalog milestone found mesh-build-go and the delivery's indexer reading manifests with an SDK from before the
|
catalog milestone found mesh-build-go and the delivery's indexer reading manifests with an SDK from before the
|
||||||
word); the SDK's list of a defined seat's verbs, which must name a verb a module adds (2026-10-21: node-files' two
|
word); the SDK's list of a defined seat's verbs, which must name a verb a module adds (2026-10-21: node-files' two
|
||||||
new verbs were refused on the claim); the node-engine's decoder for a new key on the wire; the route by which a
|
new verbs were refused on the claim); the node-engine's decoder for a new key on the wire; the route by which a
|
||||||
@@ -320,12 +273,6 @@ is a breach the lead names.
|
|||||||
key and stream the diff creates or writes (search the diff for the bucket and stream names) and finds each in the
|
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
|
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.
|
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
|
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
|
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
|
report, and the round does not wait for it. What a round asks is only what makes the change wrong against
|
||||||
@@ -377,8 +324,9 @@ is a breach the lead names.
|
|||||||
**While a group is being checked, nothing else is merged or pushed into a repository that is one of its members:**
|
**While a group is being checked, nothing else is merged or pushed into a repository that is one of its members:**
|
||||||
a moved main asks the group's check again. How it is checked: the lead's wait list names the group's members, and
|
a moved main asks the group's check again. How it is checked: the lead's wait list names the group's members, and
|
||||||
`mesh-delivery.show` shows one check per head.
|
`mesh-delivery.show` shows one check per head.
|
||||||
**A group is one check.** Before the push, every member pins the group's own mesh-sdk head exactly (the checker refuses an
|
**A group is one check.** No member names the group's mesh-sdk head, or any package's version, by hand: the group's
|
||||||
older commit of the same branch), then all members are pushed and opened together, so the group's check runs once. A head the review replaces
|
check builds every member against the group's own package heads (ADR 0573 §4). All members are pushed and opened
|
||||||
|
together, so the group's check runs once. A head the review replaces
|
||||||
counts for nothing against a running check; say so, and ask no other until the new head is reviewed.
|
counts for nothing against a running check; say so, and ask no other until the new head is reviewed.
|
||||||
**Before a session trusts an agent's "pushed", it reads the forge branch's head** (`git ls-remote origin refs/heads/<branch>`) and compares it with the commit reviewed; an agent may commit on a detached HEAD and report a push that never happened (2026-10-26: the first check of a reviewed fix failed "not our ref"). The pull request is opened only on that read head. Pull requests in two or
|
**Before a session trusts an agent's "pushed", it reads the forge branch's head** (`git ls-remote origin refs/heads/<branch>`) and compares it with the commit reviewed; an agent may commit on a detached HEAD and report a push that never happened (2026-10-26: the first check of a reviewed fix failed "not our ref"). The pull request is opened only on that read head. Pull requests in two or
|
||||||
more repositories that share the branch name are one delivery group (ADR 0239 §2).
|
more repositories that share the branch name are one delivery group (ADR 0239 §2).
|
||||||
@@ -413,20 +361,13 @@ is a breach the lead names.
|
|||||||
(also in a delivery group that holds the catalog's pull request); the lead runs mesh-controller's unit
|
(also in a delivery group that holds the catalog's pull request); the lead runs mesh-controller's unit
|
||||||
suite with `MESH_CHECK_BESIDE` naming a directory that holds the catalog's branch, as mesh-controller's
|
suite with `MESH_CHECK_BESIDE` naming a directory that holds the catalog's branch, as mesh-controller's
|
||||||
`internal/beside` says.
|
`internal/beside` says.
|
||||||
**Before the push, every member's suites run as the running checker runs them**: each sibling repository placed
|
|
||||||
beside it by main's beside rules, the node-engine at the commit the machines run, and the running indexer's judge
|
|
||||||
over every manifest the change touches. On 2026-11-02 release sdk1 failed four checks one fault at a time (test
|
|
||||||
globals left set, a sibling placed otherwise, the checker's manifest archive, a composition step the old checker could not
|
|
||||||
build), each of which a run as the checker places things would have shown before the first push. How it is
|
|
||||||
checked: the pull request's description names the placement, the node-engine commit and the judge run used
|
|
||||||
locally; a check that fails on a placement the local run did not use is named by the lead at the next report.
|
|
||||||
2. **The checker's merge check runs the integration tests once, as the gate** (its one status, `mesh/check`). No
|
2. **The checker's merge check runs the integration tests once, as the gate** (its one status, `mesh/check`). No
|
||||||
second review: step 2 reviewed this tree.
|
second review: step 2 reviewed this tree.
|
||||||
3. **A check that fails** goes back to the same reviewer, continued by its id, with the failure, for **one more cycle** of step 2 with
|
3. **A check that fails** goes back to the same reviewer, continued by its id, with the failure, for **one more cycle** of step 2 with
|
||||||
the same fixing agents; then push **once** again (the one more push of ADR 0548). The check is **read, never re-asked to see if it passes**: a
|
the same fixing agents; then push **once** again (the one more push of ADR 0548). The check is **read, never re-asked to see if it passes**: a
|
||||||
check asked again without a new, reviewed head spends the build capacity for nothing. **The failure is read from the check's whole log**, never
|
check asked again without a new, reviewed head spends the build capacity for nothing. **The failure is read from the check's whole log**, never
|
||||||
reasoned from its summary: `mesh-delivery-checker.checker_pull` names every failure the verdict holds, one line each, and the full report
|
reasoned from its summary: `mesh-delivery.show` names the check's build id, and `mesh-controller.builds` with
|
||||||
of the check. A check's summary picks only some failing lines;
|
`log` set to that id prints everything the builder said. A check's summary picks only some failing lines;
|
||||||
on 2026-10-17 it showed a store test's `FAIL` without its cause, and a fix was first guessed from the code.
|
on 2026-10-17 it showed a store test's `FAIL` without its cause, and a fix was first guessed from the code.
|
||||||
**A failure the check hides or loses** (a verdict naming only the first failed test, a log not kept) is a fault of the
|
**A failure the check hides or loses** (a verdict naming only the first failed test, a log not kept) is a fault of the
|
||||||
checking tool: it is fixed there, the same turn (instruction fix-a-bug-met-twice), not asked around.
|
checking tool: it is fixed there, the same turn (instruction fix-a-bug-met-twice), not asked around.
|
||||||
@@ -438,13 +379,6 @@ is a breach the lead names.
|
|||||||
which tests run at which level is the build tag's (ADR 0445 §2), and hq's checks are Go tests like any repository's
|
which tests run at which level is the build tag's (ADR 0445 §2), and hq's checks are Go tests like any repository's
|
||||||
(ADR 0527). The prepare step looks for this: a change to what the checker's build module selects (its recipe, a build
|
(ADR 0527). The prepare step looks for this: a change to what the checker's build module selects (its recipe, a build
|
||||||
tag convention) is cut ahead of the milestone.
|
tag convention) is cut ahead of the milestone.
|
||||||
**The same holds for every part that judges a change**: the checker, the indexer and its judge, the grants part and
|
|
||||||
the build modules. A release that changes one of them is judged by the version that runs, so whatever the running
|
|
||||||
version cannot judge is delivered first as a change of its own, or left out and added back once the new part runs.
|
|
||||||
On 2026-11-02 release sdk1 delivered the build module's relative replaces first, and took the checker's new
|
|
||||||
composition call out of the release, adding it back in the next pull request once the new node-engines answered it. How it is checked: the prepare step's
|
|
||||||
milestone file lists every judging part the release changes and how each is delivered first or left out; the review
|
|
||||||
refuses a group that holds one without that line.
|
|
||||||
4. **The milestone's acceptance is proven by its check.** A milestone that adds or changes a module
|
4. **The milestone's acceptance is proven by its check.** A milestone that adds or changes a module
|
||||||
carries an integration test that starts the module whole, its process against the real bus and store, and
|
carries an integration test that starts the module whole, its process against the real bus and store, and
|
||||||
shows the milestone's acceptance sentence; the forge's checks run it (ADR 0391 §1, §6). Unit tests alone are not
|
shows the milestone's acceptance sentence; the forge's checks run it (ADR 0391 §1, §6). Unit tests alone are not
|
||||||
@@ -472,20 +406,29 @@ is a breach the lead names.
|
|||||||
moved to include it): one Approve, one delivery. The old Approve ask closes itself on the new head and the new
|
moved to include it): one Approve, one delivery. The old Approve ask closes itself on the new head and the new
|
||||||
head is asked once its checks pass. How it is checked: a follow-up that sits in a second pull request while the
|
head is asked once its checks pass. How it is checked: a follow-up that sits in a second pull request while the
|
||||||
first still waits shows in `gitea.gitea_list_pull_requests` as two open pull requests of one lead.
|
first still waits shows in `gitea.gitea_list_pull_requests` as two open pull requests of one lead.
|
||||||
6. **A member pins mesh-sdk only at a commit that is a pull request's head**, merged or open (2026-10-28: the check
|
6. **Nobody pins a package** (ADR 0573 §2, §4). No commit writes a mesh package's version or commit into `go.mod`,
|
||||||
refused a pin to a merge commit on main as "on no pull request", though its tree equalled the head's). How it is
|
`go.sum` or `package-lock.json` to choose what a module builds against: every module builds against the latest
|
||||||
checked: the check's pin step; a refusal "on no pull request" is this rule skipped.
|
published version of each package it uses, a publish rebuilds every dependent (ADR 0573 §3, along ADR 0267 §3's
|
||||||
7. **Two groups that pin the same module's mesh-sdk conflict in `go.mod` and `go.sum`.** The group that merges
|
edges), and a group's check builds its members against the group's own heads. This replaces the pin rules learned on
|
||||||
second merges main in and re-pins once, to a pull request head that holds both changes, after the first group
|
2026-10-28 (a pin only at a pull request's head; two groups pinning one module's mesh-sdk re-pin after the first
|
||||||
is merged and not before (a re-pin before makes the first group conflict). How it is checked: the check's merge
|
merges): each was a step the developer ordered by hand, which the operator ruled out (2026-10-21, 2026-10-31). A
|
||||||
step; a group that conflicts after the first one merged is this rule skipped.
|
check that refuses a member for the version it names, an older head, a merge commit or a commit on no pull request
|
||||||
8. **A group that adds a seat, a verb or a manifest field in mesh-sdk and uses it in a module's manifest in the
|
is a fault of the check: say it to the operator and fix the check under issue 1585, never
|
||||||
same group cannot pass its check** until the running assigner pins a mesh-sdk that defines it, because the
|
re-pin around it. How it is checked: the review refuses a hand-written version or commit of a mesh package; a check
|
||||||
check composes with the running assigner's mesh-sdk (issue 1585). The assigner's pin ships first, as its own
|
of the checker that refuses one is to be built (issue 1585).
|
||||||
release. How it is checked: the check's composition step; a composition refusing the new word in such a group
|
7. **A seat's contract is its holder's package, and a module takes another repository's code only as a package**
|
||||||
is this rule skipped.
|
(ADR 0573 §1). A new or changed seat's records, keys, events, verbs and message schemas go into a package its
|
||||||
|
holder's repository publishes (a Go module or a node package), never into mesh-sdk, which keeps only what every
|
||||||
|
seat shares; a user imports that package, never a path into, a copy of or a `replace` to another repository's
|
||||||
|
source. A change that alters a seat whose contract mesh-sdk still holds moves it to the holder's package in the same
|
||||||
|
change (issue 167). How it is checked: the review refuses a seat-specific type, key or verb added to mesh-sdk and an
|
||||||
|
import of another repository's source; no check refuses them yet (issue 1585).
|
||||||
|
8. **A group that adds a seat, a verb or a manifest field and uses it in a module's manifest in the same group is
|
||||||
|
composed with the group's own mesh-sdk head** (ADR 0482 §3), so it passes in one group, with no release ahead of
|
||||||
|
it. How it is checked: the check's composition step; a composition that refuses the new word in such a group is a
|
||||||
|
fault of the check (issue 1585).
|
||||||
9. **A new head on an open pull request needs its `Reviewed-by` line at that head before the Approve is asked,
|
9. **A new head on an open pull request needs its `Reviewed-by` line at that head before the Approve is asked,
|
||||||
even for a pin-only commit.** How it is checked: the Approve's ask names the review record;
|
even for a one-line commit.** How it is checked: the Approve's ask names the review record;
|
||||||
an ask whose line names another commit is this rule skipped.
|
an ask whose line names another commit is this rule skipped.
|
||||||
|
|
||||||
**One exception: a catalog change that uses a new manifest word.** The catalog's merge check reads
|
**One exception: a catalog change that uses a new manifest word.** The catalog's merge check reads
|
||||||
@@ -701,12 +644,6 @@ 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
|
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.
|
step 1, is the failure this playbook prevents.
|
||||||
- A context file exists per touched repository under `.work/<slug>/` while the feature runs.
|
- 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
|
- 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.
|
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
|
- Every issue of a running milestone has a note from the prepare step naming its files and tests (file:line), how
|
||||||
|
|||||||
@@ -33,12 +33,7 @@ processing power"). Everything before the push is local and fast, and no try is
|
|||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
1. **Read the issue and the code it names** (the session's own model, or one read-only agent on the smaller
|
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). **Read what exists in the fix's area today, briefly, before any
|
model answering exact questions with file:line). If a design question is open, it is settled 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
|
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
|
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
|
decision stays a small fix. **The session's own model (the larger) then writes the issue's acceptance
|
||||||
@@ -64,7 +59,7 @@ processing power"). Everything before the push is local and fast, and no try is
|
|||||||
writer writes it; the review asks it.
|
writer writes it; the review asks it.
|
||||||
4. **One review of the local commit** (a reviewer that did not write it, larger
|
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
|
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; 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
|
against its test, as playbook 07 step 2 item 6; 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
|
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
|
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.
|
operator's Approve of its merge is its review, and the review record says so.
|
||||||
@@ -151,9 +146,6 @@ 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
|
- 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
|
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.
|
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
|
- 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
|
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.
|
(`git grep -n '<issue>/AC<n>'`); one without is step 1 skipped.
|
||||||
|
|||||||
@@ -221,8 +221,8 @@ code{font:12.5px ui-monospace,monospace;background:var(--soft);padding:1px 5px;b
|
|||||||
</g>
|
</g>
|
||||||
<!-- lead -->
|
<!-- lead -->
|
||||||
<rect x="110" y="56" width="160" height="52" rx="8" fill="var(--card)" stroke="var(--dec)" stroke-width="2"/>
|
<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">What exists · survey</text>
|
<text x="190" y="78" text-anchor="middle" class="t">Survey · criteria</text>
|
||||||
<text x="190" y="96" text-anchor="middle" class="mute">criteria · context file per repo</text>
|
<text x="190" y="96" text-anchor="middle" class="mute">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"/>
|
<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="78" text-anchor="middle" class="t">Up to trunk</text>
|
||||||
<text x="410" y="96" text-anchor="middle" class="mute">each branch, local</text>
|
<text x="410" y="96" text-anchor="middle" class="mute">each branch, local</text>
|
||||||
@@ -275,7 +275,6 @@ code{font:12.5px ui-monospace,monospace;background:var(--soft);padding:1px 5px;b
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<h3>Step 0 · what the lead writes before any agent starts</h3>
|
<h3>Step 0 · what the lead writes before any agent starts</h3>
|
||||||
<ul style="margin:6px 0;padding-left:20px;font-size:14px">
|
<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>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>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>
|
<li><span class="tag new">new</span>Every other reader and writer of each value the change touches, each with a criterion.</li>
|
||||||
@@ -416,15 +415,15 @@ const P = [
|
|||||||
{n:"01",name:"Research",kind:"idea",c:"--idea",
|
{n:"01",name:"Research",kind:"idea",c:"--idea",
|
||||||
trig:"An idea worth investigating before it is committed to design. A symptom is not research.",
|
trig:"An idea worth investigating before it is committed to design. A symptom is not research.",
|
||||||
who:"The session that heard the idea leads.",
|
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, 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."],
|
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."],
|
||||||
prod:"A research effort in the knowledge base, status active, every version kept. Nothing in hq.",
|
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 · review by architectural domain 20 min · report every 10 min",
|
next:"02",bounds:"Setup 30 min · proposing 15 min · each experiment 30 min · direction 30 min · report every 10 min",
|
||||||
prev:["Research that measured nothing","A recommendation the operator must argue back","Efforts copied into hq"],
|
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."},
|
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",
|
{n:"02",name:"Graduation & design change",kind:"idea",c:"--dec",
|
||||||
trig:"A research effort concludes, or an existing design must change.",
|
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.",
|
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.","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."],
|
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."],
|
||||||
prod:"Decision records; a to-be design with frontmatter; glossary entries; later the as-is.",
|
prod:"Decision records; a to-be design with frontmatter; glossary entries; later the as-is.",
|
||||||
next:"04",bounds:"One sitting of about an hour",
|
next:"04",bounds:"One sitting of about an hour",
|
||||||
prev:["A decision rewritten silently","A deferral nothing tracks","A design amended without a decision"],
|
prev:["A decision rewritten silently","A deferral nothing tracks","A design amended without a decision"],
|
||||||
@@ -464,15 +463,15 @@ const P = [
|
|||||||
{n:"07",name:"Features",kind:"build",c:"--build",
|
{n:"07",name:"Features",kind:"build",c:"--build",
|
||||||
trig:"Work that changes code across issues or repositories, too large for a small fix.",
|
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).",
|
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.","Every agent is one of hq's definitions (mesh-preparer, mesh-developer, mesh-code-reviewer, mesh-watcher); the lead writes only the handover. (new)","The prepare starts from the knowledge base and names the mesh path of every interaction; the seams review judges it before code. (new)","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)"],
|
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)","No member pins a package: the group's check builds every member against the group's own heads (ADR 0573). (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.",
|
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",
|
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","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"],
|
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"],
|
||||||
check:"The checker's one status, mesh/check; the review record; the tracker's move."},
|
check:"The checker's one status, mesh/check; the review record; the tracker's move."},
|
||||||
{n:"08",name:"Small fixes",kind:"build",c:"--build",
|
{n:"08",name:"Small fixes",kind:"build",c:"--build",
|
||||||
trig:"One issue in one repository, about an hour of work.",
|
trig:"One issue in one repository, about an hour of work.",
|
||||||
who:"The session, with one reviewer on the larger model.",
|
who:"The session, with one reviewer on the larger model.",
|
||||||
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)"],
|
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)"],
|
||||||
prod:"One pull request, one delivery, a resolved issue.",
|
prod:"One pull request, one delivery, a resolved issue.",
|
||||||
next:"—",bounds:"About an hour · one review, one push, one check",
|
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"],
|
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"],
|
||||||
|
|||||||
@@ -7,14 +7,9 @@ code:
|
|||||||
- mesh-tools src/broker-amqp.ts (to be replaced)
|
- mesh-tools src/broker-amqp.ts (to be replaced)
|
||||||
- mesh-catalog modules/nats (to be written)
|
- mesh-catalog modules/nats (to be written)
|
||||||
- mesh-sdk src (the protocol's NATS binding, step 3)
|
- mesh-sdk src (the protocol's NATS binding, step 3)
|
||||||
- mesh-tools node-tools/internal/bus (a module's state, ADR 0201; the new calls and apply, ADR 0595, ADR 0597)
|
- mesh-tools node-tools/internal/bus (a module's state, ADR 0201)
|
||||||
- mesh-sdk (the typed bus-state entry, its binding and the new calls' package, ADR 0595)
|
updated: 2026-10-10
|
||||||
- mesh-delivery (the judge's rules and the grants part's binding, ADR 0595)
|
|
||||||
updated: 2026-11-03
|
|
||||||
decisions:
|
decisions:
|
||||||
- "ADR 0595"
|
|
||||||
- "ADR 0596"
|
|
||||||
- "ADR 0597"
|
|
||||||
- "ADR 0289"
|
- "ADR 0289"
|
||||||
- "ADR 0264"
|
- "ADR 0264"
|
||||||
- "ADR 0235"
|
- "ADR 0235"
|
||||||
@@ -43,11 +38,6 @@ under which subject, with which guarantee, under whose account; how a node joins
|
|||||||
reaches a tool; how the mesh moves from the bus it has to this one; and how each claim is checked.
|
reaches a tool; how the mesh moves from the bus it has to this one; and how each claim is checked.
|
||||||
Prose and diagrams only; no configuration is pasted.
|
Prose and diagrams only; no configuration is pasted.
|
||||||
|
|
||||||
**Amended, 2026-11-03** (ADR 0595, ADR 0596, ADR 0597): what a module keeps on the bus is its **bus state**, a
|
|
||||||
provision of the bus module asked for by template, created by the bus module, read by its owner alone; and the
|
|
||||||
**ledger** is a storage type of its own. § 12 is the design; the `KV_<module>_<name>` row of § 3 and the module's
|
|
||||||
state in § 4 hold for a module still on the old sections.
|
|
||||||
|
|
||||||
## 1. What the bus is for
|
## 1. What the bus is for
|
||||||
|
|
||||||
**The bus is where the mesh happens.** Not a transport the mesh sends things over — the place a
|
**The bus is where the mesh happens.** Not a transport the mesh sends things over — the place a
|
||||||
@@ -189,7 +179,7 @@ Core NATS is at-most-once. Everything the mesh must not lose lives in a JetStrea
|
|||||||
| EVENTS | `mesh.mod.*.event.>` and `mesh.seat.*.event.>`; and `mesh.again.>` (ADR 0264) | limits (age, size), durable consumer per subscribing module | a subscriber that was down catches up; after `max-deliver` attempts the advisory feeds `mesh.events.dead` (its own small stream). *2026-10-08, ADR 0264:* that stream is DEAD_LETTERS, below; each consumer also filters `mesh.again.<consumer>.>`, where a message it gave up on is delivered again to it alone. *2026-10-01:* a build's whole log is here too, as the build seat's `log.<build id>` events (ADR 0157) — one subject per build, a week of retention, read back by `builds --log <id>` with a consumer that is gone when the reading is done |
|
| EVENTS | `mesh.mod.*.event.>` and `mesh.seat.*.event.>`; and `mesh.again.>` (ADR 0264) | limits (age, size), durable consumer per subscribing module | a subscriber that was down catches up; after `max-deliver` attempts the advisory feeds `mesh.events.dead` (its own small stream). *2026-10-08, ADR 0264:* that stream is DEAD_LETTERS, below; each consumer also filters `mesh.again.<consumer>.>`, where a message it gave up on is delivered again to it alone. *2026-10-01:* a build's whole log is here too, as the build seat's `log.<build id>` events (ADR 0157) — one subject per build, a week of retention, read back by `builds --log <id>` with a consumer that is gone when the reading is done |
|
||||||
| DEAD_LETTER_NOTICES | the server's maximum-deliveries advisory | work queue, a week; one consumer (the controller), no `max-deliver` | the server's word that a consumer gave up on a message, kept whether or not a controller is listening, until the controller has copied the message (ADR 0264) |
|
| DEAD_LETTER_NOTICES | the server's maximum-deliveries advisory | work queue, a week; one consumer (the controller), no `max-deliver` | the server's word that a consumer gave up on a message, kept whether or not a controller is listening, until the controller has copied the message (ADR 0264) |
|
||||||
| DEAD_LETTERS | `mesh.events.dead.<stream>.<consumer>` | limits: no age, 256 MiB, refuses new when full; a day's de-duplication | every message a consumer gave up on, with its consumer, subject, deliveries and when, until a person delivers it again or drops it with why (ADR 0264); a `max-deliveries` condition is open per consumer while it holds any |
|
| DEAD_LETTERS | `mesh.events.dead.<stream>.<consumer>` | limits: no age, 256 MiB, refuses new when full; a day's de-duplication | every message a consumer gave up on, with its consumer, subject, deliveries and when, until a person delivers it again or drops it with why (ADR 0264); a `max-deliveries` condition is open per consumer while it holds any |
|
||||||
| `KV_<module>_<name>` | `$KV.<module>_<name>.>` | the newest value per key — as many past values as the owner declared — no age unless the owner declared one; a value at most 256 KiB, a bucket at most 64 MiB | a module's state (ADR 0201): one per name in a manifest's `state`, created from the catalog on every raise, so it exists before its owner runs anywhere; kept when the module is unassigned, because what it holds is data. *2026-11-03, ADR 0595:* a module's kept data in the new form is created by the bus module from `requires`, by template (§ 12) |
|
| `KV_<module>_<name>` | `$KV.<module>_<name>.>` | the newest value per key — as many past values as the owner declared — no age unless the owner declared one; a value at most 256 KiB, a bucket at most 64 MiB | a module's state (ADR 0201): one per name in a manifest's `state`, created from the catalog on every raise, so it exists before its owner runs anywhere; kept when the module is unassigned, because what it holds is data |
|
||||||
|
|
||||||
Tool calls and heartbeats stay on core NATS: a lost heartbeat is the next heartbeat; a lost tool
|
Tool calls and heartbeats stay on core NATS: a lost heartbeat is the next heartbeat; a lost tool
|
||||||
call is a timeout the caller already handles.
|
call is a timeout the caller already handles.
|
||||||
@@ -276,7 +266,7 @@ expresses this exactly, per subject, and better than a vhost could:
|
|||||||
permissions for each consumed event's subject, its tool subjects, and that same inbox prefix.
|
permissions for each consumed event's subject, its tool subjects, and that same inbox prefix.
|
||||||
Nothing else. A module that tries to publish outside its emits is refused by the server, not by
|
Nothing else. A module that tries to publish outside its emits is refused by the server, not by
|
||||||
convention.
|
convention.
|
||||||
- **A module's state** (ADR 0201; for the new form, § 12.2: the owner's account alone, no reader, ADR 0596), for whichever principal carries the module — today the machine's
|
- **A module's state** (ADR 0201), for whichever principal carries the module — today the machine's
|
||||||
runtime, whose grant is the union of its modules': binding to the bucket, reading a key directly,
|
runtime, whose grant is the union of its modules': binding to the bucket, reading a key directly,
|
||||||
and an ordered consumer for listing and watching, created and deleted on the bucket's own stream
|
and an ordered consumer for listing and watching, created and deleted on the bucket's own stream
|
||||||
and nothing else's; and, for the owner's instances only, publishing under the bucket's own
|
and nothing else's; and, for the owner's instances only, publishing under the bucket's own
|
||||||
@@ -627,275 +617,3 @@ find what changed and why.
|
|||||||
that needs it? ADR 0039's test —
|
that needs it? ADR 0039's test —
|
||||||
*does editing it recompile unrelated modules, and does it change often* — probably says no for
|
*does editing it recompile unrelated modules, and does it change often* — probably says no for
|
||||||
one instance; worth asking again if a second module needs the same shape.
|
one instance; worth asking again if a second module needs the same shape.
|
||||||
|
|
||||||
## 12. Bus state: what a module keeps on the bus, and the bus module that provides it
|
|
||||||
|
|
||||||
*Added 2026-11-03* (ADR 0595, ADR 0596, ADR 0597, from research 082; the operator, 2026-11-02 20:45: "The names
|
|
||||||
simply represent named configurations or templates"). Until now a manifest declared what a module keeps on the bus
|
|
||||||
in four sections with four vocabularies (`state`, `logs`, `streams`, `objects`), the grants part created each
|
|
||||||
entry once and never changed it, and nothing compared what the bus holds with what was asked. This section is the
|
|
||||||
design of the one form that replaces them; [design 32](32-what-a-module-declares.md) § 4 says how a manifest asks
|
|
||||||
for it, and [design 55](55-the-knowledge-base.md) § 2.1 is its first ledger.
|
|
||||||
|
|
||||||
**Bus state is a provision of the bus module** (ADR 0595 §1). The **bus module** is the module holding the seat
|
|
||||||
`mesh-broker` (today `nats`). A module asks it for each piece of its **bus state** the way it asks postgres for a
|
|
||||||
database: an entry in `requires`, by its local name, its storage type, its template and the template's options.
|
|
||||||
The bus module creates it; the module receives the names on the bus in its membership; nothing else creates it.
|
|
||||||
|
|
||||||
### 12.1 Three layers
|
|
||||||
|
|
||||||
```
|
|
||||||
layer 3 templates state events work queue log objects ledger
|
|
||||||
│ │ │ │ │ │
|
|
||||||
layer 2 storage types key-value │ │ │ object store ledger
|
|
||||||
built on the bucket │ │ │ │ (a stream and
|
|
||||||
stream │ │ │ │ │ key-value buckets)
|
|
||||||
└──────────┴───────────┴──────────┴──────────┴────────────┘
|
|
||||||
layer 1 base type stream
|
|
||||||
```
|
|
||||||
|
|
||||||
A **storage type** is how the bus keeps the data: the **stream** is the base, and the **key-value bucket**, the
|
|
||||||
**object store** and the **ledger** are built on it, each with calls of its own (ADR 0595 §2). A **configuration**
|
|
||||||
is the settings a storage type is given. A **template** is a storage type with a configuration, predefined and
|
|
||||||
named: six exist, from the uses counted on main (158 state entries, 6 event streams, 4 logs, 3 work queues). An
|
|
||||||
**option** is one setting of a template a module may change, within its bound. A module gives a configuration of
|
|
||||||
its own only where no template fits: the bare stream, or a ledger whose history expires.
|
|
||||||
|
|
||||||
**What keeps the data safe is fixed, never an option** (ADR 0595 §3). Each template fixes what happens when it is
|
|
||||||
full, and the judge refuses a manifest that gives it:
|
|
||||||
|
|
||||||
| Template | On | Fixed | Options, their bounds (default) |
|
|
||||||
|---|---|---|---|
|
|
||||||
| state | key-value | refuses when full; a value at most 256 KiB; the bucket at most 64 MiB; one copy, on disk | past values 1 to 64 (1), 0 refused; time to live (none); a lifetime per key; one bucket per machine |
|
|
||||||
| events | stream | drops the oldest when full; the module's own subjects | age 1 to 30 days (7); cap 1 to 8192 MiB (1024); a grant (ADR 0363 §4) |
|
|
||||||
| work queue | stream | removed once taken; refuses when full; one taker; no grant | deliveries 1 to 10; duplicate detection up to its age; cap; age |
|
|
||||||
| log | stream | refuses when full; never rewritten; an entry at most 256 KiB; one subject per key | cap 1 to 8192 MiB (1024); age 1 to 3650 days (none) |
|
|
||||||
| objects | object store | refuses when full; kept for good | cap 1 to 8192 MiB, required; a grant |
|
|
||||||
| ledger | ledger | as log, plus its type and a snapshot per instance; its state and index buckets as state | cap; keeping days only in a ledger's own configuration |
|
|
||||||
| (none: a bare stream) | stream | the module's own subjects; within the mesh's bounds | its own configuration, which must give "when full" (refuse or drop the oldest), a cap of 1 to 8192 MiB and an age of 1 to 3650 days or none, and may give a grant; the judge refuses one missing any of the three |
|
|
||||||
|
|
||||||
The template log is the **module log** of ADR 0297. The mesh, never the module, names the bus objects and their
|
|
||||||
subjects (ADR 0201 §4): `<module>_<local name>`, and a local name holding the separator is refused so no two
|
|
||||||
modules' names meet.
|
|
||||||
|
|
||||||
### 12.2 Who creates it, and how a module receives it
|
|
||||||
|
|
||||||
```
|
|
||||||
indexer's judge ──verdict: accepted, with the module's bus-state entries whole──▶ bus module
|
|
||||||
│ creates each entry
|
|
||||||
▼
|
|
||||||
grants part ◀──────────────── created (module, local name, bus name, template, settings)
|
|
||||||
│ writes the binding into the module's membership
|
|
||||||
▼
|
|
||||||
the tool runner reads the membership ──▶ the module's calls reach its own entries, and only those
|
|
||||||
```
|
|
||||||
|
|
||||||
- **The trigger is the judge's verdict** (ADR 0595 §4), heard as an event that carries the module's entries whole,
|
|
||||||
so the bus module never reads the indexer's state and never polls. It hears the verdicts on a durable consumer, so
|
|
||||||
one given while it was down is heard when it is back, and at start it runs `check` over every accepted manifest,
|
|
||||||
creating what is missing. The judge checks every entry once, at the merge
|
|
||||||
check and at take-in (ADR 0578; ADR 0595 §8).
|
|
||||||
- **The bus module has a process of its own** beside its tool bundle, with a declared health check. Its credential
|
|
||||||
creates streams and buckets under modules' names only, and deletes only through `drop` and `recreate`. Its health
|
|
||||||
turns unhealthy, naming the cause, when an accepted verdict has waited on its durable consumer, unanswered, for
|
|
||||||
more than three minutes, or when its last pass over fill, which runs every minute, is more than three minutes old, so the only guard against a store filling never stops without a sound; another module's entry at 75 percent
|
|
||||||
raises that module's condition and leaves the bus module healthy.
|
|
||||||
- **The binding travels on `created`** (ADR 0595 §1, §7). The grants part, which issues every membership, hears it
|
|
||||||
on a durable consumer and writes the binding (the names on the bus) into the module's membership, kept in its own
|
|
||||||
state `memberships`, so no part writes another's state and a binding outlives the 30 days its event is kept.
|
|
||||||
A module whose binding is missing at start fails loudly, naming the entry; it never starts blind. A `refused`
|
|
||||||
create hands no binding. **A refused or overdue creation is loud**: overdue means no `created` or `refused` within
|
|
||||||
five minutes of an accepted verdict that asks for the entry. The condition is raised by the watchman, which today raises the judge's
|
|
||||||
refusals as findings and gains, through its `consumes`, the accepted verdicts and the seat `mesh-broker`'s `created`
|
|
||||||
and `refused`; never by the bus module, which cannot raise it while it is down; it names the module
|
|
||||||
and the entry; a later `created` clears it, and so does a later accepted verdict of that module that no longer asks
|
|
||||||
for the entry.
|
|
||||||
- **Only the owner reaches it** (ADR 0596 §2). The membership grants the owner's account its own entries and no
|
|
||||||
other module's: the new form has no readers. What another module needs of that data it asks through the owner's
|
|
||||||
tools or seat verbs, and what the owner lets others hear is its declared events, subscribed to through
|
|
||||||
`consumes` (ADR 0363, unchanged). A part watches only its own state, and hears another's events (ADR 0596 §4).
|
|
||||||
|
|
||||||
### 12.3 The seat's verbs, events and fill
|
|
||||||
|
|
||||||
The seat `mesh-broker`, until now a seat with no verbs, gains these (ADR 0595 §5, §6). Where the seat's definition
|
|
||||||
lives, and so the exact form of each verb's arguments, waits for the research effort on how seats are defined,
|
|
||||||
tracked on issue 1966; the build's third step does not start before it.
|
|
||||||
|
|
||||||
| Verb | Does | Who may call it |
|
|
||||||
|---|---|---|
|
|
||||||
| `list` | every entry, its template, its settings, its fill against its cap | any caller whose role grants it (ADR 0386) |
|
|
||||||
| `show` | one entry, the same | the same |
|
|
||||||
| `check` | compares what the bus holds with what was asked, entry by entry | the same |
|
|
||||||
| `orphans` | entries the bus holds that no manifest asks for; never one whose manifest the judge refused or outgrew, nor one of the foundation's old sections | the same |
|
|
||||||
| `create` | creates one entry now | the bus module's own process only |
|
|
||||||
| `apply` | applies a difference that only grows: a larger cap, a longer age | the bus module's own process only |
|
|
||||||
| `recreate` | rebuilds an entry whose settings differ in a way that cannot grow, from its data where the storage type allows | the bus module's process, on the operator's warrant |
|
|
||||||
| `drop` | removes one orphan | the bus module's process, on the operator's warrant |
|
|
||||||
|
|
||||||
`create`, `apply`, `recreate` and `drop` are granted to the bus module's own credential alone, so a module calling
|
|
||||||
them is refused by the bus. A person asks for them through the bus module's tools, and `recreate` and `drop` act
|
|
||||||
only on the operator's warrant (ADR 0259 §6), asked through the operator channel. Before `recreate` or `drop` acts,
|
|
||||||
the bus module takes a stream snapshot of the entry. A drifted entry is said, never quietly fixed: only a difference
|
|
||||||
that grows is applied without a person.
|
|
||||||
|
|
||||||
**Events**: `created`, `refused` (with why), `drifted` and `drift-cleared`, `full` and `full-cleared`, `orphaned`
|
|
||||||
(cleared by a `drop`, or by a manifest asking for the entry again, which emits `created` for it);
|
|
||||||
each carries the module, the local name, the bus name, the template, and the settings asked against those held. The
|
|
||||||
bus module's own kept data stays on the old sections (ADR 0595 §10), because it cannot wait for its own process to
|
|
||||||
create it: it declares this stream in its `streams` section, kept 30 days (ADR 0363's bound), created by the grants
|
|
||||||
part as today, with a cap of 256 MiB; it drops its oldest when full, which loses no live state, because every drift,
|
|
||||||
orphan and fill stands as a condition until it clears. Thirty days, because a drift or an orphan is read back days later by a person; the conditions hold the
|
|
||||||
live state. The tool `history` of one entry reads them back: every event the bus module said of it, in order. This
|
|
||||||
settles where they are kept, which ADR 0595 §12 left to the design.
|
|
||||||
|
|
||||||
**Fill is the bus module's one periodic read** (ADR 0595 §6): every minute, for every entry that refuses when full,
|
|
||||||
because the bus says nothing as a store fills. The condition `full` is raised from 75 percent of the cap and cleared
|
|
||||||
below it. The grants part's `mesh-grants.history-full` moves to it: the new condition is raised first, then the old
|
|
||||||
key cleared. A bare stream that refuses when full is read the same way. **The conditions**, each naming the module
|
|
||||||
and the entry: `full` (cleared below 75 percent), `drifted` (cleared by `drift-cleared`), `orphaned` (cleared by a
|
|
||||||
`drop` or by a manifest asking for it again) and a refused create (cleared by a later `created`).
|
|
||||||
|
|
||||||
**Its tools** (tools-are-how-a-module-is-spoken-to): the four reading verbs, marked reads, answer every entry the
|
|
||||||
bus module created and its fill, and `history` its events for one entry; `create` and `apply`, marked acts, and
|
|
||||||
`recreate` and `drop`, marked dangerous and so granted only by name (ADR 0386 §6, ADR 0387), are its tools for a
|
|
||||||
person. Such a tool, in the bus module's bundle, holds no grant of those verbs' subjects, and neither does the tool
|
|
||||||
runner's account: it hands the request to the process on the process's own tool subject, carrying the caller as
|
|
||||||
the token the identity seat signed (ADR 0386 §8), whose signature the process checks, so no account granted that
|
|
||||||
subject can name another caller; the process acts only for a caller whose role grants that tool, for `recreate` and `drop` only once
|
|
||||||
the operator's warrant is held, and answers what it did. The bus seat's `apply` (a difference that grows) and the
|
|
||||||
ledger's `apply` (§ 12.4) are two verbs on two subjects, granted apart; this design writes them qualified. Its health
|
|
||||||
names the process's last pass, the entries it could not create, and the entries over 75 percent.
|
|
||||||
|
|
||||||
### 12.4 The ledger
|
|
||||||
|
|
||||||
A **ledger** is a storage type whose state is derived from its history (ADR 0597). It is built on a stream and
|
|
||||||
key-value buckets, and asked for with the template ledger.
|
|
||||||
|
|
||||||
```
|
|
||||||
module ──apply(instance, operation)──▶ tool runner on its own machine
|
|
||||||
│ 1 checks the operation against the type
|
|
||||||
│ 2 reads the history's last sequence for the instance; replays if the state is behind
|
|
||||||
│ 3 appends to the history, that sequence expected ──▶ history (stream, a subject per instance)
|
|
||||||
│ 4 derives the state by the operation's effect ──▶ state (key-value, updated at the revision read)
|
|
||||||
│ 5 writes the instance's snapshot ──▶ snapshot subject (latest only, never expires)
|
|
||||||
▼
|
|
||||||
answers: taken, with its sequence (and "state behind" when the state bucket is full)
|
|
||||||
module's process: a watcher keeps each declared index (a second key-value bucket) from the history
|
|
||||||
```
|
|
||||||
|
|
||||||
- **A type** is a schema and the operations allowed on it; an **instance** of a type is named by a path
|
|
||||||
(`listing/a17`, `decision/0290`); every change is an **operation**, kept in the instance's history.
|
|
||||||
- **A ledger effect** is what an operation does to the state, one of a fixed set: set fields, set an entry of a
|
|
||||||
map, append to a list, remove (ADR 0597 §2). An effect copies only the fields its type names, and may add the
|
|
||||||
operation's sequence and author. Where a type pairs a text field with its digest, `apply` refuses an operation
|
|
||||||
whose digest does not match. A module's own rules are checked by the module before it calls `apply`, never by the
|
|
||||||
effects. Only the owning module calls `apply` on its ledger, for every effect, remove among them; a person
|
|
||||||
removes through the owner's tools. This settles who may call the remove effect, which ADR 0597 §13 left to the
|
|
||||||
design.
|
|
||||||
- **One writer wins, and the state never goes back** (§5): the expected sequence makes the bus refuse a racing
|
|
||||||
writer; the state is written as an update of the revision read, never a plain put; when that update loses to
|
|
||||||
another writer, `apply` answers success with its operation's sequence and re-reads, never appending again.
|
|
||||||
- **A full state bucket loses no operation** (§6): `apply` answers that the operation is taken, with its sequence,
|
|
||||||
and that the state is behind because the bucket is full; the next `apply` after room is made catches it up.
|
|
||||||
- **The author is proven** (§7): `apply` stamps the owning module's authenticated account and the account that
|
|
||||||
called the owner's tool. The owner passes that author on by naming the tool call it serves: the tool runner, which
|
|
||||||
served that call and proved its caller, stamps the caller it proved, so the module cannot set the author to words of
|
|
||||||
its own; an `apply` naming no call in flight carries the owner's account alone, and one naming another module's
|
|
||||||
call is refused. A copy of old records (design 55 § 8.1) is stamped with the owner's account and keeps the old
|
|
||||||
author as a separate field marked imported, never as the proven author.
|
|
||||||
- **Every instance has a snapshot** (§8): the latest state on a subject of its own, never expiring, written by every
|
|
||||||
`apply`. It makes a kept ledger's rebuild fast and an expiring ledger's possible; a repair that finds it behind
|
|
||||||
the state rewrites it.
|
|
||||||
- **Only the tool runner's ledger credential publishes on a ledger's history** (§9): one per module, held by the
|
|
||||||
tool runner and never by the module's own code, whose account may read its ledger and not publish on it. The grants
|
|
||||||
part issues it with the module's membership on that machine, scoped to the subjects of that module's ledger
|
|
||||||
histories and snapshots, and removes it when the module is unassigned from the machine. Only the
|
|
||||||
owner's account reads the history, the snapshot and the state.
|
|
||||||
- **An index** is a second key-value bucket kept by a watcher in the owning module's process, rebuildable from the
|
|
||||||
history; it raises a condition when it lags behind (§4).
|
|
||||||
|
|
||||||
### 12.5 The calls, and where they live
|
|
||||||
|
|
||||||
The new calls live in a small mesh-sdk package of their own, served by the tool runner and imported only by the
|
|
||||||
modules that use them; the module library, which 112 modules import, does not change (ADR 0595 §9). They are the
|
|
||||||
object store's (put, get, list, delete, info, watch); a stream's read-back and fill; a work queue's size and dead
|
|
||||||
letters; and the ledger's: `apply`, `get`, `history`, `watch`, `query`, and its repairs `rebuild` (the state from
|
|
||||||
the history or the snapshot), `reindex`, `snapshot` and `lag` (ADR 0597 §10). The tool runner serves the repairs as
|
|
||||||
tools of every module that owns a ledger, limited to its own ledgers, so no owner declares them and the next ledger's
|
|
||||||
owner has them on its first day. mesh-sdk's catalog and membership
|
|
||||||
packages change once for the typed `requires` entry and the binding, rebuilding about 30 modules.
|
|
||||||
|
|
||||||
### 12.6 The move, and the order of the build
|
|
||||||
|
|
||||||
**The build, each step undoable on its own** (ADR 0595 §10): (1) mesh-sdk's typed `requires`, binding and calls
|
|
||||||
package; (2) the judge's rules; (3) the bus module's process, verbs and events, creating only for the new form, with the grants part's writing of
|
|
||||||
the binding on `created`; (4) the tool runner's calls, the ledger's `apply` and its ledger credential among them; (5)
|
|
||||||
modules move, each owner first. Each undo: undoing step 2 refuses the new form again, which no module uses before
|
|
||||||
step 5; undoing step 3 leaves what it created in place, and a module moved after it fails loudly on its missing
|
|
||||||
binding; undoing step 4 leaves a moved module without its calls, which the placement holds off that machine. The
|
|
||||||
placement holds a moved module off a machine whose tool runner does not serve the typed binding and the calls the
|
|
||||||
module asks for (a ledger's `apply` among them), and says so; where the placement reads what a tool runner serves is
|
|
||||||
left to the build of step 4 and tracked on issue 1966.
|
|
||||||
|
|
||||||
**A module moves when it is next touched** (ADR 0595 §11), keeping its local names and carrying its old settings
|
|
||||||
as options, so its bus objects and data stay and no drift is raised. It asks for each entry once: an old section
|
|
||||||
and the new form are never both used for one local name. During the move the grants part keeps creating the old
|
|
||||||
sections' entries, so each entry has one creator. The indexer counts the modules on each old section, a tool reads
|
|
||||||
the count, and the judge refuses a section once its count is 0. The foundation's own kept data (the bus module's,
|
|
||||||
the grants part's and the indexer's) stays on the old sections for good and is not counted: those modules cannot
|
|
||||||
wait for a process that needs them first.
|
|
||||||
|
|
||||||
**Readers move after their owners** (ADR 0596 §3). Today 195 `reads` entries in 37 modules read another module's
|
|
||||||
bus state, the indexer's 36 times and the assigner's 30. An owner declares the events and gains the tools its
|
|
||||||
readers need before any reader moves: the judge refuses a moved module's subscription to an event its owner does
|
|
||||||
not declare, and the review of a reader's move reads that the owner's tool is on main and delivered. These moves
|
|
||||||
are tracked by issue 1966.
|
|
||||||
|
|
||||||
### 12.7 How it is checked
|
|
||||||
|
|
||||||
| Rule | Checked by |
|
|
||||||
|---|---|
|
|
||||||
| A manifest's bus state is valid, once | the judge's unit tests, each refusal naming the field: an unknown template, an option outside its bound, past values 0, "when full" given, a fixed setting given, a name used twice across storage types, two modules' bus names alike, a `reads` in the new form, an effect outside the fixed set (ADR 0595 §8, ADR 0596 §2, ADR 0597 §2) |
|
|
||||||
| The bus module creates, and the binding follows | live, by tool call: a module asking for a state, a log, objects and a ledger in `requires` receives each binding in its membership, written after `created`, never before; `show` gives each entry's template, settings and fill; a module calling `create` is refused |
|
|
||||||
| The bus module runs whole | one integration test in the nats module's repository that starts the bus module whole against the real bus server: a verdict, then `created`, then the binding in the membership; a restart that catches up a verdict given while it was down; a bucket whose settings differ raises `drifted`, the seat's `apply` of a larger cap clears it with `drift-cleared`; a refused create raises its condition and hands no binding; `recreate` and `drop` without the operator's warrant are refused, and with it act after a stream snapshot; an orphan is listed, raises `orphaned`, and goes only by `drop`; each template at a small cap refuses, events drop the oldest, and `full` is raised at 75 percent and cleared below |
|
|
||||||
| Drift and orphans, live | live, made only by a manifest change: a manifest that shrinks a setting raises `drifted`; the conditions clear as above. Nothing is filled on the live bus, and no orphan is made there |
|
|
||||||
| Overdue and stopped are loud | live, carried by the change of the first module that moves in step 5, never by a merge made for the test alone: with the bus module's process stopped, an accepted manifest asking for an entry raises the overdue condition within five minutes, from the watchman, and a later `created` clears it; the bus module's health turns unhealthy when its pass is more than three minutes old |
|
|
||||||
| A person's tools reach the process, and only by role | live: a role without the dangerous grant is refused `drop`'s tool; the tool runner's account holds no grant of `create`, the seat's `apply`, `recreate` or `drop` |
|
|
||||||
| The author is the proven caller | the ledger's integration test: an `apply` naming another module's tool call is refused; the author stamped is the caller the tool runner proved, whatever the module passed |
|
|
||||||
| Only the owner reaches its data | live: another module's account reading an entry in the new form, a ledger's history, snapshot or state among them, is refused; a raw publish on a ledger's history is refused |
|
|
||||||
| The ledger keeps its promises | one integration test against the real bus (ADR 0597's How it is checked): two writers race and one is refused; two interleaved applies leave the state at the higher sequence; a write cut between history and state is repaired; a full state bucket answers taken with its sequence and catches up; an idle instance whose operations expired rebuilds from its snapshot; `rebuild`, `reindex` and `lag` repair by hand; a forged author is refused; every `apply` leaves the snapshot equal to the state; an index behind raises its condition and `reindex` clears it |
|
|
||||||
| Only the owner applies | the ledger's integration test: another module's ledger `apply` on the knowledge base's ledger is refused |
|
|
||||||
| A bare stream is complete | the judge's unit test: a bare stream missing "when full", a cap or an age is refused, naming the field |
|
|
||||||
| The calls rebuild only their users | a read of the delivery plan: only the importers of the calls package rebuild when it changes |
|
|
||||||
| The move keeps data | live: a module moved from `state` keeps its bucket and data and raises no drift; a new entry in an old section is still created by the grants part; the count falls by one; at 0 a manifest using the section is refused and the foundation's are still accepted; a moved module is held off a machine whose tool runner does not read the typed binding |
|
|
||||||
|
|
||||||
**The test budget** (50 integration and 500 unit tests per repository): the design adds one integration test in the
|
|
||||||
nats module's repository and one in mesh-tools (the ledger), and table cases, not new functions, to the judge's unit
|
|
||||||
tests in mesh-delivery and to mesh-sdk's decoding tests. Each repository's count against the budget is read in the
|
|
||||||
prepare step of issue 1966, and a repository over it merges tests to stay within it.
|
|
||||||
|
|
||||||
**Acceptance.** The operator asks the bus module's `list` and sees every module's kept data with its template, its
|
|
||||||
settings and its fill; a module that moved keeps its data; a drift or an orphan reaches the operator as a condition
|
|
||||||
and is changed only on their word; and the knowledge base keeps its records as a ledger (design 55 § 10).
|
|
||||||
|
|
||||||
## Reviewed by architectural domain
|
|
||||||
|
|
||||||
The amendment of 2026-11-03 to ADR 0595, ADR 0596 and ADR 0597 (designs 25 § 12, 32 § 4 and 55 together) was
|
|
||||||
reviewed by the four reviewers by architectural domain side by side (playbook 01), over three rounds, and the lead
|
|
||||||
ruled on every finding. What was found, and what answers it:
|
|
||||||
|
|
||||||
| Domain | Found | Answered by |
|
|
||||||
|---|---|---|
|
|
||||||
| security | the author could be words the module chose; a person's dangerous tools had no role, mark or path to the process; the caller travelled as a plain field | design 25 § 12.3 (marks, the process's own tool subject, the identity seat's signed token), § 12.4 (the tool runner stamps the caller it proved; the move's authors marked imported) |
|
|
||||||
| seams | the bus module asked for its own events in the new form, which it would have to create itself (ADR 0595 §10); a person's tool had no join to the process; a verdict was written twice with no order | design 25 § 12.3 (its events on its old `streams` section; the process's own tool subject); design 55 § 2.1 (the `review` operation first, `reviews` caught up from it) |
|
|
||||||
| running qualities | overdue creation was undefined and raised by nobody; the database's rollback write lived in memory; a forward delivery after a rollback could miss acceptances and verdicts; no size estimate of the heads | design 25 § 12.2 (five minutes, the watchman, durable consumers, `check` at start); design 55 § 8.1 step 6 (`database.sequence`, the check at every start before the drop), § 2.1 (the heads' estimate) |
|
|
||||||
| health | the bus module's health would have fired on a quiet mesh; conditions had no clearing; `database-behind` had no clearing | design 25 § 12.2 and § 12.3 (each condition with what clears it); design 55 § 8.1 step 6 |
|
|
||||||
| events and logs | an event lost when the module stopped after `apply`; the bus module's events had no reader | design 55 § 1 (each event sent with its operation's sequence as id, the state `sent`); design 25 § 12.3 (`history` of one entry) |
|
|
||||||
| testing | the bus module had no test that starts it whole; live tests would have filled the live bus; the budget was not counted | design 25 § 12.7 (the nats module's integration test, live drift only by a manifest change, the budget paragraph); design 55 § 10 |
|
|
||||||
| upgrade | the build order lacked the grants part's binding and two undo steps | design 25 § 12.6 |
|
|
||||||
| tools | the ledger's repairs had no tool for the next owner; the bus module's events had no read tool | design 25 § 12.5 (served for every ledger owner), § 12.3 |
|
|
||||||
|
|
||||||
**Left to the operator**, because each changes an accepted record: a margin between raising and clearing the
|
|
||||||
condition `full` (ADR 0595 §6 raises and clears it at 75 percent, so an entry sitting there flaps), and an event of
|
|
||||||
its own for `drop` and `recreate`. **A correction of fact** for ADR 0595 §4: the bus module deletes through `recreate`
|
|
||||||
as well as `drop`. Each is noted on issue 1966.
|
|
||||||
|
|||||||
@@ -12,11 +12,8 @@ code:
|
|||||||
- mesh-tools src/main.ts
|
- mesh-tools src/main.ts
|
||||||
- mesh-catalog modules/mesh-catalog
|
- mesh-catalog modules/mesh-catalog
|
||||||
- mesh-tools node-tools/internal/runtime (a module's state, ADR 0201)
|
- mesh-tools node-tools/internal/runtime (a module's state, ADR 0201)
|
||||||
- mesh-sdk (the typed bus-state entry in `requires` and its binding, ADR 0595)
|
updated: 2026-10-12
|
||||||
updated: 2026-11-03
|
|
||||||
decisions:
|
decisions:
|
||||||
- "ADR 0595"
|
|
||||||
- "ADR 0596"
|
|
||||||
- "ADR 0307"
|
- "ADR 0307"
|
||||||
- "ADR 0240"
|
- "ADR 0240"
|
||||||
- "ADR 0233"
|
- "ADR 0233"
|
||||||
@@ -230,7 +227,7 @@ service" versus "one worker per machine".
|
|||||||
| credential | sealed, per consumer | none | none | none | none |
|
| credential | sealed, per consumer | none | none | none | none |
|
||||||
| reply | — | none | none, or an event later | a report | awaited |
|
| reply | — | none | none, or an event later | a report | awaited |
|
||||||
| retention | — | age and size | work queue, explicit ack | **last per subject** | none |
|
| retention | — | age and size | work queue, explicit ack | **last per subject** | none |
|
||||||
| declared | `provides`/`requires` | `emits`/`consumes` | seat `accepts` / `uses` | the mesh's own; a module's bus state in `requires` (ADR 0595), the old `state` / `reads` until it moves | `serves` |
|
| declared | `provides`/`requires` | `emits`/`consumes` | seat `accepts` / `uses` | the mesh's own; a module's `state` / `reads` | `serves` |
|
||||||
|
|
||||||
**Job** is the one ADR 0041 had no room
|
**Job** is the one ADR 0041 had no room
|
||||||
for. Its table has events at 1:many and provisions at 1:1; a module submitting work to a service
|
for. Its table has events at 1:many and provisions at 1:1; a module submitting work to a service
|
||||||
@@ -281,36 +278,6 @@ module's assignment** — what a module stored is data
|
|||||||
(ADR 0030) — and one whose
|
(ADR 0030) — and one whose
|
||||||
declaration is gone is reported, never removed by the mesh.
|
declaration is gone is reported, never removed by the mesh.
|
||||||
|
|
||||||
**A module asks for its bus state in `requires`, and reads no other module's.** *Amended 2026-11-03, ADR 0595
|
|
||||||
and ADR 0596, from research 082.* The `state` and `reads` of the two paragraphs above, and the sections `logs`,
|
|
||||||
`streams` and `objects` beside them, are four vocabularies for one need: what a module keeps on the bus. They are
|
|
||||||
replaced by one form, a **provision** of the bus module, as a database is postgres's:
|
|
||||||
|
|
||||||
- **An entry of `requires`, in its typed long form** (ADR 0595 §1): the local name, the storage type, the template
|
|
||||||
(state, events, work queue, log, objects, ledger) and the template's options, within their bounds; a ledger also
|
|
||||||
names its type (its schema, its operations each with its ledger effect, its indexes). The templates, their fixed
|
|
||||||
settings and their options are [design 25](25-the-bus-on-nats.md) § 12.1. mesh-sdk's catalog package carries the
|
|
||||||
entry's type and its strict decoding; every rule that judges it lives in the indexer's judge (ADR 0595 §8).
|
|
||||||
- **The binding is what the module receives**: the names on the bus for each local name, written into its
|
|
||||||
membership by the grants part once the bus module says `created` (design 25 § 12.2). The module still names only
|
|
||||||
locally (§ 1). A module whose binding is missing at start fails loudly, naming the entry.
|
|
||||||
- **One name, one form.** A module asks for each entry once: an old section and the new form are never both used for
|
|
||||||
one local name, and one name serves one storage type only.
|
|
||||||
- **No readers.** The new form has no `reads`, and the judge refuses one (ADR 0596 §2). Only the owner's account
|
|
||||||
reaches its bus state. **A module's events are subscribed to; its data is asked for**: what another module needs
|
|
||||||
of a module's kept data it asks through that module's tools or seat verbs (§ 4's tool relationship, `serves`),
|
|
||||||
and what a module lets others hear is its declared events, heard through `consumes` (ADR 0363, unchanged; ADR 0596
|
|
||||||
§1). A bucket's layout is never a contract another module depends on; a tool or a declared event is.
|
|
||||||
- **The move is a module at a time** (ADR 0595 §11, ADR 0596 §3), each when it is next touched, keeping its local
|
|
||||||
names and its old settings as options so its data stays. A reader moves after its owner: the owner declares the
|
|
||||||
event or gains the tool its readers need first, and the judge refuses a moved module's subscription to an event
|
|
||||||
its owner does not declare. An old section is refused once no module but the foundation's uses it.
|
|
||||||
|
|
||||||
What follows for the paragraphs above: for a module that has moved, ADR 0201 §2 (another module's state read by
|
|
||||||
naming it in `reads`) no longer holds, and the bucket "every instance of the owner writes; a reader reads and
|
|
||||||
watches" becomes "every instance of the owner writes and reads". The runtime's `get`, `put`, `delete`, `keys`,
|
|
||||||
`watch` and `history` stay the calls of the template state.
|
|
||||||
|
|
||||||
**A module declares the data it holds.** *Added 2026-10-06,
|
**A module declares the data it holds.** *Added 2026-10-06,
|
||||||
ADR 0233.*
|
ADR 0233.*
|
||||||
State on the bus is one kind of data; the rest lives on a machine's disks or with a provider, and the
|
State on the bus is one kind of data; the rest lives on a machine's disks or with a provider, and the
|
||||||
@@ -635,34 +602,6 @@ billing existing under that name.
|
|||||||
- **A module reaches only the state it declared.** The composer's test: an owner's runtime may write
|
- **A module reaches only the state it declared.** The composer's test: an owner's runtime may write
|
||||||
its buckets, a reader's may only read, and nothing else is granted; the runtime's test over a real
|
its buckets, a reader's may only read, and nothing else is granted; the runtime's test over a real
|
||||||
bus: a name not issued and a reader's write are refused with the reason.
|
bus: a name not issued and a reader's write are refused with the reason.
|
||||||
- **Bus state is asked for once, in one form, and read by its owner alone** (ADR 0595 §8, ADR 0596). The judge's
|
|
||||||
unit tests: a `reads` in the new form, a local name used twice across storage types or in an old section and the
|
|
||||||
new form, an unknown template and an option outside its bound are each refused, naming the field. Live: a moved
|
|
||||||
module receives its binding after `created`; another module's account reading its entries is refused; a moved
|
|
||||||
reader hears its owner's declared event and asks its owner's tool. The rest is [design 25](25-the-bus-on-nats.md)
|
|
||||||
§ 12.7.
|
|
||||||
- **State is current at once.** The runtime's test over a real bus: a watch hands the current values
|
- **State is current at once.** The runtime's test over a real bus: a watch hands the current values
|
||||||
without deletions, then an end-of-current marker, then changes. Live: a machine assigned after a put
|
without deletions, then an end-of-current marker, then changes. Live: a machine assigned after a put
|
||||||
reads it at start.
|
reads it at start.
|
||||||
|
|
||||||
## Reviewed by architectural domain
|
|
||||||
|
|
||||||
The amendment of 2026-11-03 to ADR 0595, ADR 0596 and ADR 0597 (designs 25 § 12, 32 § 4 and 55 together) was
|
|
||||||
reviewed by the four reviewers by architectural domain side by side (playbook 01), over three rounds, and the lead
|
|
||||||
ruled on every finding. What was found, and what answers it:
|
|
||||||
|
|
||||||
| Domain | Found | Answered by |
|
|
||||||
|---|---|---|
|
|
||||||
| security | the author could be words the module chose; a person's dangerous tools had no role, mark or path to the process; the caller travelled as a plain field | design 25 § 12.3 (marks, the process's own tool subject, the identity seat's signed token), § 12.4 (the tool runner stamps the caller it proved; the move's authors marked imported) |
|
|
||||||
| seams | the bus module asked for its own events in the new form, which it would have to create itself (ADR 0595 §10); a person's tool had no join to the process; a verdict was written twice with no order | design 25 § 12.3 (its events on its old `streams` section; the process's own tool subject); design 55 § 2.1 (the `review` operation first, `reviews` caught up from it) |
|
|
||||||
| running qualities | overdue creation was undefined and raised by nobody; the database's rollback write lived in memory; a forward delivery after a rollback could miss acceptances and verdicts; no size estimate of the heads | design 25 § 12.2 (five minutes, the watchman, durable consumers, `check` at start); design 55 § 8.1 step 6 (`database.sequence`, the check at every start before the drop), § 2.1 (the heads' estimate) |
|
|
||||||
| health | the bus module's health would have fired on a quiet mesh; conditions had no clearing; `database-behind` had no clearing | design 25 § 12.2 and § 12.3 (each condition with what clears it); design 55 § 8.1 step 6 |
|
|
||||||
| events and logs | an event lost when the module stopped after `apply`; the bus module's events had no reader | design 55 § 1 (each event sent with its operation's sequence as id, the state `sent`); design 25 § 12.3 (`history` of one entry) |
|
|
||||||
| testing | the bus module had no test that starts it whole; live tests would have filled the live bus; the budget was not counted | design 25 § 12.7 (the nats module's integration test, live drift only by a manifest change, the budget paragraph); design 55 § 10 |
|
|
||||||
| upgrade | the build order lacked the grants part's binding and two undo steps | design 25 § 12.6 |
|
|
||||||
| tools | the ledger's repairs had no tool for the next owner; the bus module's events had no read tool | design 25 § 12.5 (served for every ledger owner), § 12.3 |
|
|
||||||
|
|
||||||
**Left to the operator**, because each changes an accepted record: a margin between raising and clearing the
|
|
||||||
condition `full` (ADR 0595 §6 raises and clears it at 75 percent, so an entry sitting there flaps), and an event of
|
|
||||||
its own for `drop` and `recreate`. **A correction of fact** for ADR 0595 §4: the bus module deletes through `recreate`
|
|
||||||
as well as `drop`. Each is noted on issue 1966.
|
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
layer: to-be
|
layer: to-be
|
||||||
status: in-progress
|
status: in-progress
|
||||||
code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-delivery, mesh-host, mesh-sdk, mesh-vault, hq 00-META/checks]
|
code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-delivery, mesh-host, mesh-sdk, mesh-vault, hq 00-META/checks]
|
||||||
updated: 2026-11-03
|
updated: 2026-10-29
|
||||||
decisions:
|
decisions:
|
||||||
- "ADR 0594"
|
|
||||||
- "ADR 0572"
|
- "ADR 0572"
|
||||||
- "ADR 0571"
|
- "ADR 0571"
|
||||||
- "ADR 0570"
|
- "ADR 0570"
|
||||||
@@ -846,21 +845,6 @@ backup holder backs up nothing, and the have says so.
|
|||||||
fingerprint, the digest, the phase and the health after the module's start window. A failed apply is loud,
|
fingerprint, the digest, the phase and the health after the module's start window. A failed apply is loud,
|
||||||
retried by the next change of the want or the composition, never by a clock, and fixed forward (ADR 0360 §8,
|
retried by the next change of the want or the composition, never by a clock, and fixed forward (ADR 0360 §8,
|
||||||
ADR 0539 §9).
|
ADR 0539 §9).
|
||||||
- **The bus module is wanted like any module; only a warranted want replaces its server** (ADR 0594, changing
|
|
||||||
ADR 0539 §14 and §15, ADR 0546 §8 and ADR 0565 §7 for the bus module). The assigner writes the bus module's want by
|
|
||||||
the same rules as every module's, and the node agent applies what that want brings (its files, its processes' bus
|
|
||||||
accounts and secrets, its tools) while it keeps the server's container as it runs, with no record ask. Only a want
|
|
||||||
that carries the operator's warrant (a put after the streams' snapshot, or the operator's hand write) replaces the
|
|
||||||
server; until then the bus module's have names the fingerprint applied and the one the server runs, and the view
|
|
||||||
says the server waits. mesh-sdk names the resources the bus's
|
|
||||||
server holds, so the assigner and the node agent read one list; the assigner writes the bus module's want only to a
|
|
||||||
node agent whose have says it keeps the server (the version it reports), so the node agent's keeping of the server
|
|
||||||
is delivered before the assigner's change. Until
|
|
||||||
then nothing writes the bus module's process accounts, and its tools that write to the bus fail (issue 774, the
|
|
||||||
operator, 2026-11-03). How it is checked: a node agent unit test applies a bus module's new want and shows the
|
|
||||||
server's container untouched and the tools' account written; an assigner unit test writes the bus module's want
|
|
||||||
by the rules, holds the server's replacement for a put, and writes none to a node agent whose have does not say it
|
|
||||||
keeps the server.
|
|
||||||
- **Every want is owed.** The watchman mirrors every want as a pulse owed by that node's agent until its have
|
- **Every want is owed.** The watchman mirrors every want as a pulse owed by that node's agent until its have
|
||||||
names the want's fingerprint, so a node that does not move is a stall (ADR 0539 §19).
|
names the want's fingerprint, so a node that does not move is a stall (ADR 0539 §19).
|
||||||
- **A move a person must allow is judged by the node and asked by the assigner.** The node agent applies ADR 0377
|
- **A move a person must allow is judged by the node and asked by the assigner.** The node agent applies ADR 0377
|
||||||
@@ -1270,8 +1254,8 @@ release reports the controller's code lines against research 063's baseline (acc
|
|||||||
| R4g | The last milestone of release 4 and release 5 as one, with one switch-over and no rehearsal (ADR 0524 §1): builds and checks are asks on streams that each build node pulls when it has a free slot, deliveries first, with nothing holding checks and no controller queue (ADR 0525); the assigner is made with its composition check, writes each node's wants compared with what the controller sends and every difference, and the view answers the asks that need no proof of who answered (ADR 0528, ADR 0437 §10); no module's fingerprint takes the builder (ADR 0530); the scripts of the repositories a module is built from, build-agent with its socket and Dockerfile code, the toolchain images and the controller's build code go, and the builder delivers its own module, the build modules and the controller from its keys (ADR 0453 clauses 5, 8, 10; ADR 0524 §5, §7); the ways to deliver without the builder are recorded (ADR 0526); hq's four checks are Go tests (ADR 0527); each repository's script goes (ADR 0529); the word for the composition check's predecessor is struck. Its pull requests are opened only after five readings, the revert path read, not shown on a test merge (ADR 0524 §3) | 4 (from R4g mesh-build-image, rootless, is the only part that builds an image: ADR 0487 §7), 17, 24 (no `merge-check.sh` in a repository a module is built from) | mesh-sdk, mesh-controller (build-agent removed), mesh-delivery, mesh-catalog, mesh-tools, mesh-tools-go, the node-engine (`mesh-host`), mesh-media-catalog, okioki, hq | 1887 (the flow), 1297 (the assigner), 1295 (`merge-check.sh` goes), 979 (closed with the toolchain images), 1296 and 1303 (hq's check, the old word struck), 1299, 1305, 1294, 1318 (the controller's deletions) |
|
| R4g | The last milestone of release 4 and release 5 as one, with one switch-over and no rehearsal (ADR 0524 §1): builds and checks are asks on streams that each build node pulls when it has a free slot, deliveries first, with nothing holding checks and no controller queue (ADR 0525); the assigner is made with its composition check, writes each node's wants compared with what the controller sends and every difference, and the view answers the asks that need no proof of who answered (ADR 0528, ADR 0437 §10); no module's fingerprint takes the builder (ADR 0530); the scripts of the repositories a module is built from, build-agent with its socket and Dockerfile code, the toolchain images and the controller's build code go, and the builder delivers its own module, the build modules and the controller from its keys (ADR 0453 clauses 5, 8, 10; ADR 0524 §5, §7); the ways to deliver without the builder are recorded (ADR 0526); hq's four checks are Go tests (ADR 0527); each repository's script goes (ADR 0529); the word for the composition check's predecessor is struck. Its pull requests are opened only after five readings, the revert path read, not shown on a test merge (ADR 0524 §3) | 4 (from R4g mesh-build-image, rootless, is the only part that builds an image: ADR 0487 §7), 17, 24 (no `merge-check.sh` in a repository a module is built from) | mesh-sdk, mesh-controller (build-agent removed), mesh-delivery, mesh-catalog, mesh-tools, mesh-tools-go, the node-engine (`mesh-host`), mesh-media-catalog, okioki, hq | 1887 (the flow), 1297 (the assigner), 1295 (`merge-check.sh` goes), 979 (closed with the toolchain images), 1296 and 1303 (hq's check, the old word struck), 1299, 1305, 1294, 1318 (the controller's deletions) |
|
||||||
| R6 | Each node applies from its wants the compositions its own node agent composes (ADR 0547 §2; as released it applied the controller's signed ones), a new version reaches the module's canary first and the rest once it is healthy there, a move a person must allow is asked before its want, the view says what is moving, settled, stuck and delivered, and the plans are deleted from the code; switched over by release 5's last plan (ADR 0539) | 18, 19, 20 | mesh-sdk, the node-engine (`mesh-host`: the node agent), mesh-controller (plans deleted; as released also compositions and credentials, which ADR 0547 moves to the node agents, the grants part and the vault), mesh-delivery (assigner, watchman, view), mesh-catalog (the gate, the messenger, the issue tracker, the backup holder), hq | 1942 (the planner puts the node-engine and the controller in one tier for the switch; delivered first), the bus's user list granting what release 6 uses (delivered first, under L1's issue), 1943 (mesh-sdk: the composition's layout and signature, the want's digest, `mesh-hand-compose`, the verb tables without the plan verbs), 1944 (the node agent), 1946 (the gate keeps the merge's states; the messenger and the issue tracker hear the view), 1906 (the assigner's seventh rule and its asks, the watchman's pulses for wants, the view's wants and events), 1130 (hq) |
|
| R6 | Each node applies from its wants the compositions its own node agent composes (ADR 0547 §2; as released it applied the controller's signed ones), a new version reaches the module's canary first and the rest once it is healthy there, a move a person must allow is asked before its want, the view says what is moving, settled, stuck and delivered, and the plans are deleted from the code; switched over by release 5's last plan (ADR 0539) | 18, 19, 20 | mesh-sdk, the node-engine (`mesh-host`: the node agent), mesh-controller (plans deleted; as released also compositions and credentials, which ADR 0547 moves to the node agents, the grants part and the vault), mesh-delivery (assigner, watchman, view), mesh-catalog (the gate, the messenger, the issue tracker, the backup holder), hq | 1942 (the planner puts the node-engine and the controller in one tier for the switch; delivered first), the bus's user list granting what release 6 uses (delivered first, under L1's issue), 1943 (mesh-sdk: the composition's layout and signature, the want's digest, `mesh-hand-compose`, the verb tables without the plan verbs), 1944 (the node agent), 1946 (the gate keeps the merge's states; the messenger and the issue tracker hear the view), 1906 (the assigner's seventh rule and its asks, the watchman's pulses for wants, the view's wants and events), 1130 (hq) |
|
||||||
| L1 | The controller leaves build and delivery, first milestone: the bus node follows the user list alone, the grants part composes in shadow and the vault holds the bus accounts' hashes, so the operator's take-over can make the grants part's list the one loaded (ADR 0547 §8, §11; ADR 0550 §4) | — | mesh-controller, mesh-delivery, mesh-catalog (the vault, the grants part), the node-engine (`mesh-host`), mesh-sdk | 1945 |
|
| L1 | The controller leaves build and delivery, first milestone: the bus node follows the user list alone, the grants part composes in shadow and the vault holds the bus accounts' hashes, so the operator's take-over can make the grants part's list the one loaded (ADR 0547 §8, §11; ADR 0550 §4) | — | mesh-controller, mesh-delivery, mesh-catalog (the vault, the grants part), the node-engine (`mesh-host`), mesh-sdk | 1945 |
|
||||||
| L2 | Nodes compose: each node agent composes its own modules, and no node applies a composition made elsewhere but the bus's user list (ADR 0547 §11); where modules run is bus state held by the seat `mesh-placement` on the assigner, changed by a proposal the nodes answer and the operator approves, and no repository names a node or holds what one installation decides (ADR 0567). Built as release sdk1 (ADR 0593) and delivered to every machine on 2026-11-02, the controller's code emptied (mesh-controller #491) and its repository archived; done once a check has composed a candidate on every machine | — | the node-engine (`mesh-host`), mesh-sdk, mesh-delivery (the assigner as the seat's holder), mesh-catalog, mesh-controller (its pin only) | 1126 |
|
| L2 | Nodes compose: each node agent composes its own modules, and no node applies a composition made elsewhere but the bus's user list (ADR 0547 §11); where modules run is bus state held by the seat `mesh-placement` on the assigner, changed by a proposal the nodes answer and the operator approves, and no repository names a node or holds what one installation decides (ADR 0567) | — | the node-engine (`mesh-host`), mesh-sdk, mesh-delivery (the assigner as the seat's holder), mesh-catalog, mesh-controller (its pin only) | 1126 |
|
||||||
| L3 | Nothing is left with the controller: the vault mints bus accounts and signs, the grants part writes grants, the try is the checker's own verb, placement is read from the seat `mesh-placement` alone, each node-engine holds the node seat `node-engine`, judges `root-free` for its node and asks the operator itself for a hand-over or an access act, acting on the warrant with nothing signed (ADR 0563), and, once L4 to L7 are delivered, the lease write passes the lease to a holder that is no controller, made right after the delivery that drops every listed read of the controller but the three ADR 0571 §13 keeps to the write itself (ADR 0547 §11, ADR 0549 §5, §6, ADR 0550 §2, ADR 0571 §13); the rest of the controller's code lines is the issue of L2. Since the controller left (2026-11-02), nothing writes the bus module's own process accounts while the bus module has no want on the broker node, so its tools that write the bus fail (issue 774) | — | mesh-controller, mesh-sdk, the node-engine (`mesh-host`), mesh-catalog (the vault, the grants part, the messenger), mesh-delivery | 774 |
|
| L3 | Nothing is left with the controller: the vault mints bus accounts and signs, the grants part writes grants, the try is the checker's own verb, placement is read from the seat `mesh-placement` alone, each node-engine holds the node seat `node-engine`, judges `root-free` for its node and asks the operator itself for a hand-over or an access act, acting on the warrant with nothing signed (ADR 0563), and, once L4 to L7 are delivered, the lease write passes the lease to a holder that is no controller, made right after the delivery that drops every listed read of the controller but the three ADR 0571 §13 keeps to the write itself (ADR 0547 §11, ADR 0549 §5, §6, ADR 0550 §2, ADR 0571 §13); the rest of the controller's code lines is the issue of L2 | — | mesh-controller, mesh-sdk, the node-engine (`mesh-host`), mesh-catalog (the vault, the grants part, the messenger), mesh-delivery | 774 |
|
||||||
| M1 | A milestone is a record of the issue tracker: each row of a design's milestone table is a milestone record its issues are linked to by `issue-tracker.link`, an issue to at most one, and pull requests and commits to issues the same way; the knowledge base's `progress` reads the milestones from the tracker, not from this table (ADR 0493 §1 to §4) | — (ADR 0493 §13 in part) | hq, mesh-catalog (mesh-issues, mesh-knowledge) | 1781 |
|
| M1 | A milestone is a record of the issue tracker: each row of a design's milestone table is a milestone record its issues are linked to by `issue-tracker.link`, an issue to at most one, and pull requests and commits to issues the same way; the knowledge base's `progress` reads the milestones from the tracker, not from this table (ADR 0493 §1 to §4) | — (ADR 0493 §13 in part) | hq, mesh-catalog (mesh-issues, mesh-knowledge) | 1781 |
|
||||||
| L4 | Health leaves the controller (ADR 0564): the condition keeper holds the seat `mesh-conditions` and keeps every open condition from the observers' findings, saying today's condition events; the watchman holds `mesh-watchdogs`, its watchdogs pulses, reads each node-engine's node health report, and keeps the dead letters from the lease write; `mesh-self-check` runs the probes, `root-free` among them from L7 (ADR 0571 §11), and says `checked`; of the probes still deferred, D13, D8, D-fill and DA are built and the rest are not, their kinds ending with the controller at the lease write (ADR 0572); `mesh-healers` heals on events and acts only once the lease names no controller; `status` is the view's derivation; built dark, compared, then switched by the operator's take-over; the bus module gains a tool that removes one named consumer, which the lease write uses (ADR 0547 §11) | — | mesh-sdk, mesh-catalog (mesh-conditions, mesh-self-check, mesh-healers, the router, mesh-watcher, nats), mesh-delivery (watchman, view, the grants part) | 1952 |
|
| L4 | Health leaves the controller (ADR 0564): the condition keeper holds the seat `mesh-conditions` and keeps every open condition from the observers' findings, saying today's condition events; the watchman holds `mesh-watchdogs`, its watchdogs pulses, reads each node-engine's node health report, and keeps the dead letters from the lease write; `mesh-self-check` runs the probes, `root-free` among them from L7 (ADR 0571 §11), and says `checked`; of the probes still deferred, D13, D8, D-fill and DA are built and the rest are not, their kinds ending with the controller at the lease write (ADR 0572); `mesh-healers` heals on events and acts only once the lease names no controller; `status` is the view's derivation; built dark, compared, then switched by the operator's take-over; the bus module gains a tool that removes one named consumer, which the lease write uses (ADR 0547 §11) | — | mesh-sdk, mesh-catalog (mesh-conditions, mesh-self-check, mesh-healers, the router, mesh-watcher, nats), mesh-delivery (watchman, view, the grants part) | 1952 |
|
||||||
| L5 | Control records leave the controller, and the controller is not changed (ADR 0565): mesh-config keeps each module's declared config in its state `declared` and publishes the predefined keys, which the indexer reads from the forge bridge's messages with each open pull request's config candidate; config switches to that source only on the operator's take-over, refused while `compare` shows a difference; each node agent writes its node's declared packages (the node seat `node-engine`, verb `packages`); the assigner holds the new seat `mesh-wants` with the upgrade policy a person chose and the bus step; the hand-act log (`hand-act`, `hand-acts`, `warranted`) is the stream of the new seat `mesh-hand-acts`, held by a new module in mesh-catalog, which every recorder calls from this delivery with no switch; the checker and the assigner's composition check read the held values of their pull requests from mesh-config's state `kept`; from the lease write a trusted config value is set only on the operator's Approve; `settings`, `move-config` and `move-placement` end with the lease and nothing replaces them. each person's six policy choices are set through `mesh-wants.upgrade` and recorded as hand acts, `upgrade compare` and the assigner's finding `policy-split` show any split, and the lease write waits for `compare` to be empty (ADR 0565 §8). One delivery group, built before the lease write of L3, which waits for the group delivered, the six choices set, mesh-config's `compare` empty and its take-over done, `mesh-wants.upgrade compare` empty, and the readings of ADR 0565 §12 (ADR 0565 §14; ADR 0348 §9, ADR 0502 §2, ADR 0539 §14, §15, ADR 0547 §11) | — | mesh-sdk, mesh-catalog (mesh-config, mesh-hand-acts, pacman, the forge module, claude-code, mesh-knowledge, mesh-conditions, mesh-healers), mesh-delivery (indexer, assigner, checker, grants part, forge bridge), the node-engine (`mesh-host`); mesh-controller is not a member | 1953 |
|
| L5 | Control records leave the controller, and the controller is not changed (ADR 0565): mesh-config keeps each module's declared config in its state `declared` and publishes the predefined keys, which the indexer reads from the forge bridge's messages with each open pull request's config candidate; config switches to that source only on the operator's take-over, refused while `compare` shows a difference; each node agent writes its node's declared packages (the node seat `node-engine`, verb `packages`); the assigner holds the new seat `mesh-wants` with the upgrade policy a person chose and the bus step; the hand-act log (`hand-act`, `hand-acts`, `warranted`) is the stream of the new seat `mesh-hand-acts`, held by a new module in mesh-catalog, which every recorder calls from this delivery with no switch; the checker and the assigner's composition check read the held values of their pull requests from mesh-config's state `kept`; from the lease write a trusted config value is set only on the operator's Approve; `settings`, `move-config` and `move-placement` end with the lease and nothing replaces them. each person's six policy choices are set through `mesh-wants.upgrade` and recorded as hand acts, `upgrade compare` and the assigner's finding `policy-split` show any split, and the lease write waits for `compare` to be empty (ADR 0565 §8). One delivery group, built before the lease write of L3, which waits for the group delivered, the six choices set, mesh-config's `compare` empty and its take-over done, `mesh-wants.upgrade compare` empty, and the readings of ADR 0565 §12 (ADR 0565 §14; ADR 0348 §9, ADR 0502 §2, ADR 0539 §14, §15, ADR 0547 §11) | — | mesh-sdk, mesh-catalog (mesh-config, mesh-hand-acts, pacman, the forge module, claude-code, mesh-knowledge, mesh-conditions, mesh-healers), mesh-delivery (indexer, assigner, checker, grants part, forge bridge), the node-engine (`mesh-host`); mesh-controller is not a member | 1953 |
|
||||||
|
|||||||
@@ -2,62 +2,34 @@
|
|||||||
layer: to-be
|
layer: to-be
|
||||||
status: in-progress
|
status: in-progress
|
||||||
code: [mesh-catalog, hq]
|
code: [mesh-catalog, hq]
|
||||||
updated: 2026-11-03
|
updated: 2026-10-18
|
||||||
decisions:
|
decisions:
|
||||||
- "ADR 0290"
|
- "ADR 0290"
|
||||||
- "ADR 0321"
|
- "ADR 0321"
|
||||||
- "ADR 0423"
|
- "ADR 0423"
|
||||||
- "ADR 0424"
|
- "ADR 0424"
|
||||||
- "ADR 0592"
|
|
||||||
- "ADR 0593"
|
|
||||||
- "ADR 0595"
|
|
||||||
- "ADR 0596"
|
|
||||||
- "ADR 0597"
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# 55 — The knowledge base
|
# 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.
|
**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.
|
|
||||||
|
|
||||||
**Amended, 2026-11-03** (ADR 0597, ADR 0595 and ADR 0596, from research 082; the operator, 2026-11-02 21:53: "the
|
|
||||||
writes are the record"). The knowledge base is the first **ledger**: a record is an instance of a ledger type, every
|
|
||||||
change to it is an operation kept in the ledger's history, and its head is the ledger's state, derived from those
|
|
||||||
operations by the tool runner's `apply` and never written by the module. A section's text lives only in the
|
|
||||||
`write-section` operation that wrote it, with its digest; the head names each section by its title, digest and that
|
|
||||||
operation's sequence. So the object bucket `sections`, the state `names`, the stream `versions` and the module's own
|
|
||||||
commit rule fall away (ADR 0597 §12, changing ADR 0592 §1 to §12, §17, §25, §32, §33). Its kept data is asked for in
|
|
||||||
`requires` by template (ADR 0595), and no other module reads it: another module asks the knowledge base's tools or
|
|
||||||
hears its events (ADR 0596). The ledger itself, the same for every module, is designed in
|
|
||||||
[design 25](25-the-bus-on-nats.md) § 12; how a module asks for it, in [design 32](32-what-a-module-declares.md) § 4.
|
|
||||||
§ 1, § 1.1, § 2.1, § 4, § 8.1, § 9 and § 10 say what changes here.
|
|
||||||
|
|
||||||
**The mesh keeps its decision records and research efforts whole in a module of its own, `mesh-knowledge`, one
|
**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,
|
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 in titled sections, with every version kept, all of it on the
|
its clauses with their own status, and its reasoning, with every version kept. A record is proposed, checked when it
|
||||||
bus. A record is written section by section, checked when it is submitted, reviewed section by section by the
|
is written, reviewed by the knowledge base's own judgement and accepted there; the operator's Approve is asked when a record needs
|
||||||
knowledge base's own judgement and accepted there; the operator's Approve is asked when a record needs it. Agents
|
it. Agents ask what holds, and why, in one bounded call.**
|
||||||
ask what holds, and why, in one bounded call.**
|
(ADR 0290,
|
||||||
(ADR 0290, ADR 0592 and ADR 0597,
|
from research 045.)
|
||||||
from research 045 and research 082.)
|
|
||||||
|
|
||||||
A **clause** is one numbered statement a decision record makes, with its own status. A **section** is one titled
|
A **clause** is one numbered statement a decision record makes, with its own status. The **knowledge base** is the
|
||||||
part of a record's reasoning. The **knowledge base** is the module that holds the records; the seat it holds is
|
module that holds the records; the seat it holds is `knowledge-base`. The glossary holds both words.
|
||||||
`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
|
**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
|
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. A session writes a research effort of more than 100 KiB one section at a time, a
|
read the reasoning behind each.
|
||||||
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, and the fifth, the records on the bus
|
This document designs the first slice in detail, tracked by issue 425. The slices after it are in
|
||||||
(ADR 0592), kept as a ledger (ADR 0597). 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,
|
[§ 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).
|
and the knowledge base works out each design's state (ADR 0423, ADR 0424).
|
||||||
|
|
||||||
@@ -68,38 +40,17 @@ and the knowledge base works out each design's state (ADR 0423, ADR 0424).
|
|||||||
|
|
||||||
mesh-knowledge (seat knowledge-base, held once for the mesh)
|
mesh-knowledge (seat knowledge-base, held once for the mesh)
|
||||||
├ its process, launched by the node runtime
|
├ its process, launched by the node runtime
|
||||||
├ on the bus, asked for in requires by template (ADR 0595), read by it alone (§ 2)
|
├ a database in the store records, versions, clauses, links; ranked full-text search
|
||||||
│ ledger records one instance per record (decision/0290, research/082):
|
├ verbs ask, get, holds, links, history, reserve, propose, import, return
|
||||||
│ history every operation, in order, each section's text in its write-section
|
|
||||||
│ state the head, derived by apply: fields, clauses, links, sections as
|
|
||||||
│ title, digest and sequence
|
|
||||||
│ snapshot the latest head per record, never expiring
|
|
||||||
│ state drafts one key per record being written: its author and its sections as title,
|
|
||||||
│ digest and the sequence of their write-section
|
|
||||||
│ state asked one key per part asked of the judge and not yet answered: ticket, node, when
|
|
||||||
│ state findings the whole-set findings standing now, and the told marks (told.<topic>)
|
|
||||||
│ state sent per record, the last operation whose event was sent
|
|
||||||
│ stream reviews one message per part reviewed: the digest judged, the verdict, the findings
|
|
||||||
├ written through the tool runner's apply on the control-node, the only publisher on the
|
|
||||||
│ ledger's history (ADR 0597 §3, §9)
|
|
||||||
├ in its memory the search index, built from the bus at start and kept by watching the
|
|
||||||
│ ledger's state
|
|
||||||
├ 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
|
│ served by the control-node's tool runner
|
||||||
├ events reserved, opened, written, removed, ordered, submitted, dropped, taken-over, proposed,
|
├ events proposed, reviewed, accepted, changed, imported, drafted, confirmed, returned
|
||||||
│ part-reviewed, reviewed, accepted, changed, moved, checked, formed,
|
|
||||||
│ imported, drafted, confirmed, returned
|
|
||||||
├ consumes the router's warrants: the operator's Approve for a record that needs it (§ 5)
|
├ 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)
|
└ 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);
|
mesh-issues (control-node) the counters for decision and research numbers (§ 6);
|
||||||
the issues' design links, read for a design's state (§ 9)
|
the issues' design links, read for a design's state (§ 9)
|
||||||
mesh-delivery (its seat) announces each delivery done, on the bus (§ 9)
|
mesh-delivery (its seat) announces each delivery done, on the bus (§ 9)
|
||||||
claude-code (same node) claude_code_judge: review a section or a head (§ 5), draft and confirm clauses (§ 7);
|
claude-code (same node) claude_code_judge: review a proposal (§ 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)
|
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
|
messenger (control-node) the router: the operator's ask and its warrant
|
||||||
|
|
||||||
@@ -108,109 +59,20 @@ 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 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. Until the move of § 8.1, its records are in a database in
|
the records module, as the issue tracker's import does.
|
||||||
the store; from the move on, it requires no database (ADR 0592 §1, changing ADR 0290 §7).
|
|
||||||
|
|
||||||
**A record is changed by an operation, and the head follows from it** (ADR 0597 §1 to §8). Every change to a record
|
|
||||||
is one operation the module hands to `apply`: among them `reserve`, `propose`, `write-section`, `submit`,
|
|
||||||
`take-over`, `review` (a part's verdict), `ask` and `warrant` (the operator's ask and answer), `accept` and
|
|
||||||
`withdraw`. The module checks its own rules first (an `accept` needs the operator's Approve where the record needs
|
|
||||||
it, § 5; only the author writes a draft, § 4), then calls `apply`, which checks the operation against the record's
|
|
||||||
type, appends it to the instance's history with the sequence it expects, derives the head by the operation's effect,
|
|
||||||
and writes the head and its snapshot. The author is the account the bus proved for the caller of the module's verb:
|
|
||||||
the module names the tool call it serves, and the tool runner stamps the caller it proved for it, never a name the
|
|
||||||
caller or the module gave (ADR 0597 §7; [design 25](25-the-bus-on-nats.md) § 12.4).
|
|
||||||
|
|
||||||
**Every operation's event is sent once, after a restart too.** `apply` emits nothing; the module sends the event of
|
|
||||||
each operation it applied (`submitted`, `reviewed` and the rest) with the operation's sequence as the message's
|
|
||||||
id, so the bus drops a second send within its duplicate window, and keeps the last sequence it sent per record in a
|
|
||||||
state of its own, `sent` (one key `<kind>.<number>`). The duplicate window of its event stream and of `reviews` is
|
|
||||||
one day, far longer than a start (40 seconds at most, § 10); a module stopped between a send and its `sent` key for
|
|
||||||
longer than a day sends that one event again, which a consumer already takes as a bus delivered at least once. A
|
|
||||||
missed send is never chosen over a second one. At start it sends the events of every later operation in each record's history, so a
|
|
||||||
module stopped between `apply` and its event loses none, and a consumer of `mesh-knowledge.reviewed` never waits for
|
|
||||||
one that was never sent.
|
|
||||||
|
|
||||||
**A write is whole or refused, and an operation commits when its history takes it** (ADR 0597 §5, §6, changing
|
|
||||||
ADR 0592 §10). The commit point of every change to a record is the operation appended to the ledger's history: a
|
|
||||||
failure before it is appended refuses the call, and nothing is taken; a racing writer is refused by the bus, which
|
|
||||||
expects the history's last sequence for the instance. Once it is appended, the call answers that it is taken, with
|
|
||||||
its sequence; the head is derived by `apply` as an update of the revision it read, and a head behind its history is
|
|
||||||
caught up by the next `apply` (ADR 0597 §6). A full state bucket answers that the operation is taken and the head behind,
|
|
||||||
never that it was refused. So nothing an author was told was refused takes effect later. A reservation is an
|
|
||||||
operation `reserve` on an instance with no history, so two sessions reserving at once get two numbers or one
|
|
||||||
refusal. The module's other state (`drafts`, `asked`, `findings`) keeps the compare-and-set on the key's revision,
|
|
||||||
retried at most three times and then refused with the reason (ADR 0597 §12).
|
|
||||||
|
|
||||||
**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 from the ledger's state and the bodies of every current version from their
|
|
||||||
`write-section` operations into it, then keeps it current by watching the ledger's state, noting the last sequence it
|
|
||||||
took in (ADR 0597 §12, changing ADR 0592 §11). The index is the module's own, in its memory; the ledger's declared
|
|
||||||
index (ADR 0597 §4) is not used for it, because a full-text index is not a key-value bucket. `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
|
|
||||||
the ledger's state 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, changed by ADR 0597 §12: the sweep and the digest check become the ledger's repairs):
|
|
||||||
|
|
||||||
| Tool | Reads or does |
|
|
||||||
|---|---|
|
|
||||||
| read a head | one instance's state in the ledger, whole, with the sequence of the last operation it holds |
|
|
||||||
| read a record's history | the instance's operations in order, each with its sequence, author and when; a version is its `submit` |
|
|
||||||
| read a section | one `write-section` operation, by its sequence, its text checked against its digest |
|
|
||||||
| 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 |
|
|
||||||
| the ledger's repairs | the tool runner's `rebuild` (a head from the history or the snapshot), `snapshot` and `lag` (how far each head is behind its history), served for the module's own ledger (ADR 0597 §10) |
|
|
||||||
| integrity | checks every section a head or draft names resolves to a `write-section` whose text hashes to its digest |
|
|
||||||
| 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 ledger's state, when a head lags behind its history (the ledger's lag, ADR 0597 §12, changing
|
|
||||||
ADR 0592 §33), 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 bus module's (ADR 0595 §6; [design 25](25-the-bus-on-nats.md) § 12).
|
|
||||||
|
|
||||||
**Events** (ADR 0592 §34) are kept 30 days; what a later reader needs is also in the `submit` operation, in the ledger's history. 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 |
|
|
||||||
| `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
|
## 2. What one record holds
|
||||||
|
|
||||||
- `number` and `kind` (decision or research; with the third slice also design and glossary entry, § 9), its key
|
- `number` and `kind` (decision or research; with the third slice also design and glossary entry, § 9), its key
|
||||||
together; `title`, `topic`, `status`, `date`, `deciders`;
|
together; `title`, `topic`, `status`, `date`, `deciders`;
|
||||||
- its **reasoning**, in **sections**, each a plain title and its text in markdown: for a decision, Context,
|
- its **reasoning**, in sections: for a decision, context, the options weighed, consequences, how it is checked,
|
||||||
Considered Options, Consequences, How it is checked, References; for a research effort, its overview and each of its
|
references; for a research effort, its overview and each of its documents by name; for a design, its `to-be`
|
||||||
parts by title; for a design, its `to-be` section and, where something of it runs, its `as-is` section (§ 9);
|
section and, where something of it runs, its `as-is` section (§ 9); markdown, as written;
|
||||||
- for a decision, its **clauses** (§ 3);
|
- for a decision, its **clauses** (§ 3);
|
||||||
- its **links**, typed, each stored once and read from both ends;
|
- its **links**, typed, each stored once and read from both ends;
|
||||||
- its **versions**: every `submit` is a new version with who made it, when, and why in one line; `history` lists them
|
- 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
|
and gives the difference between any two. A progressive insight is a version marked as one, dated, saying what stood
|
||||||
before. A form-only version (§ 2.2) is marked `form`.
|
before.
|
||||||
|
|
||||||
| Link | From → to |
|
| Link | From → to |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -222,105 +84,6 @@ None is named `drafted`, which stays the event of a clause the import's judgemen
|
|||||||
| `touches` | a research effort → a record, issue or design it bears on (by link), or an area (as text) |
|
| `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 |
|
| `cites` | any record → any record or issue it names |
|
||||||
|
|
||||||
### 2.1 Where it is kept
|
|
||||||
|
|
||||||
A record is kept as one instance of the knowledge base's ledger `records` (ADR 0597 §11), so that a new version
|
|
||||||
costs only the sections it changes; the forms of ADR 0592 §1 to §9 that it replaces are named in its §12.
|
|
||||||
|
|
||||||
```
|
|
||||||
records: history (stream, one subject per instance) records: state (key-value, derived)
|
|
||||||
┌───────────────────────────────────────────────┐ ┌─────────────────────────────────┐
|
|
||||||
│ 101 decision/0290 propose fields, … │ │ decision/0290 │
|
|
||||||
│ 102 decision/0290 write-section "Context" │ │ title, status, clauses, links │
|
|
||||||
│ text, digest 3f9a… │ apply │ current sections: │
|
|
||||||
│ 103 decision/0290 write-section "Options" │ ───────▶ │ Context 3f9a… 102 │
|
|
||||||
│ text, digest 81c2… │ │ Options 81c2… 103 │
|
|
||||||
│ 104 decision/0290 submit sections 102, 103 │ │ pending sections: none │
|
|
||||||
│ 230 decision/0290 write-section "Context" │ │ after operation 231 │
|
|
||||||
│ text, digest 0d77… │ └─────────────────────────────────┘
|
|
||||||
│ 231 decision/0290 submit sections 230, 103 │ records: snapshot (one per instance,
|
|
||||||
└───────────────────────────────────────────────┘ the latest head, never expiring)
|
|
||||||
```
|
|
||||||
|
|
||||||
- **The head** is the instance's state, `<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, a digest and the sequence of the `write-section`
|
|
||||||
that wrote it, never the text. A section's title is held to 200 bytes, so an entry is at most about 300 bytes,
|
|
||||||
and a head with 64 pending and 64 current sections holds at most about 40 KiB of them, within a state value's
|
|
||||||
256 KiB (ADR 0597 §11). A reserved number is a head at `reserved`, with who reserved it, when, for what and when it
|
|
||||||
expires. It is derived by `apply` and never written by the module.
|
|
||||||
- **A version** is the operation `submit`: who wrote it (the caller the bus proved), when, why, its mark, the
|
|
||||||
reason of any take-over since the version before, and the version's sections (title, digest and sequence each),
|
|
||||||
which its effect sets as the head's current sections. It never copies a section's text. Who wrote each section is
|
|
||||||
the author of its `write-section`.
|
|
||||||
- **A section's text** is in the `write-section` operation that wrote it, with its digest, at most 40 KiB within a
|
|
||||||
history entry's 256 KiB: a section unchanged in a new version costs nothing, since no operation is written for it.
|
|
||||||
`apply` refuses a `write-section` whose digest does not match its text, and the module checks the text against
|
|
||||||
the digest each time it reads one. A dropped draft's operations stay in the history, named by no version
|
|
||||||
(ADR 0597 §11).
|
|
||||||
- **The history** is kept for good: the ledger template's history refuses a new operation when full, rather than
|
|
||||||
dropping its oldest, and the bus module raises its condition at 75 percent of the cap (ADR 0595 §3, §6). Each
|
|
||||||
instance's snapshot, the latest head on a subject of its own, makes a rebuild fast (ADR 0597 §8).
|
|
||||||
- **A draft** is a key in the state `drafts` (§ 4). **A part's verdict** is the operation `review` on the record's
|
|
||||||
history first, then a message on the stream `reviews`; a `review` with no message on `reviews` is sent at start
|
|
||||||
with the operation's sequence as its id, so the consumers of `reviews` miss none and hear none twice. 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. These
|
|
||||||
keep their own forms (ADR 0597 §12), asked for in `requires`: the states by the template state; `reviews`, kept for
|
|
||||||
good and heard only where granted (ADR 0592 §6, §8), as a bare stream with its own configuration (kept for good,
|
|
||||||
refusing when full, a grant), because no template both keeps for good and takes a grant (ADR 0595 §2); the bus module's read of fill every minute
|
|
||||||
covers it like any entry that refuses when full.
|
|
||||||
|
|
||||||
**Caps** (ADR 0592 §25, its object bucket's cap lapsing by ADR 0597 §12). Each is set from the move's dry run, within
|
|
||||||
its template's bound (ADR 0595 §3): a history at most 8192 MiB, a state or a ledger's state at most 64 MiB. The
|
|
||||||
starting figures, from today's 83 MB for 736 records with every version copying every section, are:
|
|
||||||
|
|
||||||
| Kept data | Template | Cap |
|
|
||||||
|---|---|---|
|
|
||||||
| `records` (history) | ledger | 1 GiB |
|
|
||||||
| `records` (state) | ledger | 64 MiB |
|
|
||||||
| `reviews` | a bare stream, its own configuration | 512 MiB |
|
|
||||||
| `drafts` | state | 64 MiB |
|
|
||||||
| `asked`, `findings`, `sent` | state | 64 MiB, the template's bound |
|
|
||||||
|
|
||||||
A write refused at a cap names the cap, and the module's health turns unhealthy naming it.
|
|
||||||
|
|
||||||
**The ledger's state is the tightest cap.** 64 MiB is already the template's top. A head holds no text, only fields,
|
|
||||||
clauses, links and its sections' titles and digests; estimated at most 8 KiB for a usual record, the 736 heads of
|
|
||||||
today need about 6 MiB, and about 1000 once designs and glossary entries become records (slice 3, § 9) about 8 MiB.
|
|
||||||
Those are estimates; the move's dry run measures the real total, and a total above 32 MiB is told to the operator
|
|
||||||
before the move.
|
|
||||||
|
|
||||||
**Nobody else reads any of it** (ADR 0596 §2, ADR 0597 §9, changing ADR 0592 §8 and §9). Only the knowledge base's
|
|
||||||
own account reads its ledger's history, snapshot and state and its other kept data; the ledger's history is published
|
|
||||||
on only by the tool runner's ledger credential. Another module asks the knowledge base's verbs (`get`, `history`,
|
|
||||||
`ask`) or hears its events (`reviewed`, `accepted` and the rest); the reads of `heads` and `sections` that ADR 0592
|
|
||||||
let another module declare lapse once those verbs answer what each reader needed. `reviews` stays a restricted event
|
|
||||||
family (ADR 0363 §4), heard only by a module granted it in mesh-knowledge's trusted config value `readers`, which
|
|
||||||
names nothing today. A draft is answered by the verbs to its author only, and a version's bodies as `get` answers
|
|
||||||
them, so the text in the history is no more open than ADR 0592 kept it. No secret is kept in any of it.
|
|
||||||
|
|
||||||
### 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
|
## 3. Clauses
|
||||||
|
|
||||||
A clause holds its record's number and its own (`0276 §4`), its wording, a `status` and a `source`:
|
A clause holds its record's number and its own (`0276 §4`), its wording, a `status` and a `source`:
|
||||||
@@ -340,49 +103,9 @@ A clause holds its record's number and its own (`0276 §4`), its wording, a `sta
|
|||||||
|
|
||||||
## 4. Writing a record
|
## 4. Writing a record
|
||||||
|
|
||||||
`reserve` gives a number (§ 6). A record is then written in a **draft**, one section per call, and submitted as a
|
`reserve` gives a number (§ 6). `propose` takes the record whole: its fields, its clauses, its reasoning in sections,
|
||||||
version (ADR 0592 §17):
|
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:
|
||||||
| 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, digest and the sequence of the `write-section` that wrote
|
|
||||||
each. Each `write` appends a `write-section` operation with the section's title, text and digest to the record's
|
|
||||||
history at once, through `apply`, and names its sequence in the draft (ADR 0597 §11, changing ADR 0592 §17), so an
|
|
||||||
unsubmitted draft's text is already in the history, the knowledge base holds the only copy of a draft, and a
|
|
||||||
session on any node can read it through the verbs; `submit` carries the draft's sections into the version. 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 link names a record or clause that does not exist;
|
||||||
- a decision has no clause, or a clause has no bold lead;
|
- a decision has no clause, or a clause has no bold lead;
|
||||||
@@ -390,62 +113,21 @@ prose fails, among them:
|
|||||||
that replaced it;
|
that replaced it;
|
||||||
- its topic is not one of the reading order's;
|
- its topic is not one of the reading order's;
|
||||||
- a research effort graduates without naming what it became;
|
- 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
|
A proposed record can be revised by its author as new versions until it is accepted. Nothing proposed is ever served
|
||||||
as in force.
|
as in force.
|
||||||
|
|
||||||
## 5. Review and acceptance
|
## 5. Review and acceptance
|
||||||
|
|
||||||
When a version is submitted (by `submit` or `propose`, a new version of a proposed record included), the knowledge
|
When `propose` takes a record (or a new version of a proposed one), the knowledge base reviews it itself: it asks for
|
||||||
base reviews it itself, **in parts** (ADR 0592 §22 to §28, changing ADR 0290 §4): one judgement per part, each in a
|
a judgement in a separate call, with no tools, that sees only the record, the records it links and the rules, and
|
||||||
separate call, with no tools, that answers `approve` or `changes` with its findings, the way the issue tracker's
|
answers `approve` or `changes` with its findings, the way the issue tracker's triage judges an issue. The judgement
|
||||||
triage judges an issue. The judgement goes through the agent module's judge (`claude_code_judge`) today, and through
|
goes through the agent module's judge (`claude_code_judge`) today, and through the mesh's inference layer once one
|
||||||
the mesh's inference layer once one exists; nothing in this design depends on which.
|
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 head** is one part: the title, the brief, the clauses (at most 40 KiB together) and the links, judged
|
(the judge unreachable, or its answer unreadable) leaves the record proposed and says so; it is never taken as an
|
||||||
against the clauses of the records it links, in what room is left, those not shown named.
|
approval. On `approve`:
|
||||||
- **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;
|
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
|
2. a record whose author marked it `needs operator` gets an ask on the router with Approve and Decline, shown on a
|
||||||
@@ -456,18 +138,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
|
`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
|
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
|
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, kept in the state `findings`, and cleared once the rule
|
operator once, as a warning naming the rule and the records, and cleared once the rule holds again. The module's
|
||||||
holds again. The module's health names it and stays healthy, because health says only whether the module works, and
|
health names it and stays healthy, because health says only whether the module works, and a finding never holds a
|
||||||
a finding never holds a rollout at the module's first-node gate (the operator's decision of 2026-10-12 on issue 504,
|
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
|
||||||
as issue 508 decided for a proposal never reviewed).
|
reviewed).
|
||||||
|
|
||||||
The rule `cited` is also judged ahead, in the review, before the judgement: a decision that names no home and that no
|
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
|
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 `submit`, because no record can link a number only reserved: a record that cites a new
|
504). It is not refused at `propose`, 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.
|
decision is proposed after it and accepted, and the new decision is proposed again.
|
||||||
|
|
||||||
An accepted record is changed only by a new record, by a progressive insight (a new version marked as one, which is
|
An accepted record is changed only by a new record, or by a progressive insight: a new version marked as one, which
|
||||||
reviewed like a proposal), or by a form-only version of § 2.2, which a check, not a judgement, accepts.
|
is reviewed like a proposal.
|
||||||
|
|
||||||
## 6. Numbers
|
## 6. Numbers
|
||||||
|
|
||||||
@@ -512,62 +194,6 @@ 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,
|
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.
|
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; the forms the records are copied into are those of ADR 0597 §12):
|
|
||||||
|
|
||||||
1. **Order.** The ledger is built first, in the order of ADR 0595 §10: mesh-sdk's typed `requires`, binding and
|
|
||||||
package of the new calls; the indexer's judge's rules; the bus module's process, verbs and events; the tool
|
|
||||||
runner's calls, `apply` among them, with its ledger credential per module; then mesh-knowledge moves, asking for
|
|
||||||
its ledger, states and stream in `requires`. An indexer whose judge predates the new form refuses a manifest
|
|
||||||
that uses it, and the placement holds the module off a machine whose tool runner does not read the typed
|
|
||||||
binding, so mesh-knowledge cannot be delivered before them. The release sdk1 (issue 1585, ADR 0593 §10), which
|
|
||||||
created object buckets and history streams through the grants part, is no longer needed by the move: the
|
|
||||||
knowledge base asks for no object bucket and no stream `versions`. 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 record's versions as operations on its
|
|
||||||
instance in the ledger, in order (a `write-section` for each section a version changed, then its `submit`, then
|
|
||||||
the record's review, ask, warrant and acceptance), through `apply`, so each head is derived and never copied; each operation is stamped with the knowledge base's own
|
|
||||||
account and keeps the database's author as a separate field marked imported, which `history` shows as the author
|
|
||||||
of an imported version;
|
|
||||||
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 its
|
|
||||||
`write-section` on the bus, that each text hashes to its digest, that each head derived equals the head the
|
|
||||||
database holds, 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, after `apply`
|
|
||||||
has taken its operation, so a rollback of the delivery reads a current database. What the database holds is
|
|
||||||
kept as a key in the state `findings`, `database.sequence`: the last history sequence written to it. At start,
|
|
||||||
and after a write the database refused, the module catches the database up from the history from that sequence
|
|
||||||
on, so a restart between `apply` and the database write loses nothing. A database still behind after three tries
|
|
||||||
raises the condition `database-behind`, naming each record it lacks and saying that a rollback now would lose
|
|
||||||
them, and never answers the author that the write was refused; the module's health is unhealthy while it stands,
|
|
||||||
the drop (step 8) is refused while it stands, and the catch-up tool copies the records again from the ledger and
|
|
||||||
clears it. A rollback is a person's act, and the condition is what tells them it is unsafe. **After a rollback**,
|
|
||||||
the older module wrote to the database alone, and not only versions: acceptances, verdicts, asks, warrants,
|
|
||||||
reservations and changed clauses too. So until the drop, every start of the module refuses every writing verb
|
|
||||||
and runs the check of step 4 before it serves writes; a difference it finds is copied from the database onto the
|
|
||||||
ledger as operations, and the check runs again, so writes are served only once it is clean. A record changed on
|
|
||||||
both sides (an operation the database never took, and a change the older module made) never checks clean: it is
|
|
||||||
told to the operator at once, naming the record and both changes, so the refused writes read as a decision
|
|
||||||
waiting and not as a stall. A rollback is safe
|
|
||||||
only until the drop. This settles the rollback ADR 0597 §13 left to the design.
|
|
||||||
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
|
## 9. The slices after the first
|
||||||
|
|
||||||
| Slice | Delivers | Done when the operator sees | Tracked by |
|
| Slice | Delivers | Done when the operator sees | Tracked by |
|
||||||
@@ -576,7 +202,6 @@ The records leave the store once, and the database is dropped only after a check
|
|||||||
| 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 |
|
| 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 |
|
| 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 |
|
| 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), kept as the first ledger (ADR 0597), delivered after the ledger's build (ADR 0595 §10), 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
|
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
|
repository keeps no copy of the records, generated or otherwise (issue 435, answered by the operator). Playbooks
|
||||||
@@ -674,50 +299,6 @@ 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 |
|
| 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 |
|
| 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 |
|
| Live | the acceptance sentence, asked from a session outside this repository |
|
||||||
| A record is kept as a ledger instance, a section's text once in its operation, and read by no other module | 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 `submit` operations and four `write-section` operations, the changed section's text found only in its operation; another module's account reading the ledger's history, snapshot or state, the head among them, is refused (ADR 0597 How it is checked, clauses 9, 11, 12) |
|
|
||||||
| 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 ledger that keeps its history | in the integration test: the history at its cap refuses a new operation and keeps its oldest; a draft's written section is in the history before `submit` and named by no version after `drop`; a section title over 200 bytes is refused |
|
|
||||||
| 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 history and the head | the ledger's integration test (design 25 § 12.7): the call answered that the operation is taken; the next `apply` derives the head. The module's own integration test: stopped after `apply`, restarted, it sends the event once |
|
|
||||||
| a failure before the operation is appended | 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 head behind its history | unit: health unhealthy naming the lag; the ledger's `rebuild` clears it |
|
|
||||||
| a text does not hash to its digest | unit: `apply` refuses the `write-section`, and a read refuses it, naming the digest |
|
|
||||||
| a full ledger state | integration: `submit` answers taken with the head behind; health unhealthy naming the cap |
|
|
||||||
| a full ledger history | 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 (ADR 0595 §8): a manifest asking for a ledger in `requires` refused by a judge that does not know the template, accepted by one that does |
|
|
||||||
| the bus module's forms | the bus module's test (design 25 § 12), against a real bus server: the ledger, states and stream created for their module, `reviews` heard by a module granted it in `readers` and by no other; 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 sequence is behind the ledger's state; `ask` refuses "index not built" |
|
|
||||||
| a forward delivery after a rollback | unit: an acceptance and a verdict made by the older module are found by the check at start, the writing verbs refused meanwhile, the changes copied and checked, then writes served; a record changed on both sides is told to the operator |
|
|
||||||
| a restart between `apply` and the database write | unit: the module is stopped after `apply` and before the database write, restarted, and the database matches the history; health showed it behind meanwhile |
|
|
||||||
| the database refuses past its tries | unit: `database-behind` names the record; the drop is refused while it stands; the catch-up tool clears it |
|
|
||||||
| a restart between `apply` and its event | unit: the module is stopped after `apply` of a `review`, restarted, and sends one `reviewed`; a second start sends none |
|
|
||||||
| the move as operations | unit: each record's versions copied as `write-section` and `submit` operations in order; the derived head equals the database's; a second run appends nothing |
|
|
||||||
| the start | integration: the time to a built index measured and reported, failing above 40 seconds, the estimate's top |
|
|
||||||
| 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
|
**The third slice's acceptance tests** (§ 9.1 to § 9.3; research 062's direction), what its build proves before it
|
||||||
is done:
|
is done:
|
||||||
@@ -739,77 +320,7 @@ is done:
|
|||||||
9. Tests 1 to 8 pass together after the one delivery, run against main and the live knowledge base, with nothing
|
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.
|
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 `write-section` and one `submit`, not one operation 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.
|
|
||||||
11. As a ledger (ADR 0597 How it is checked, clauses 11 and 12): `get` answers the same digest for every record
|
|
||||||
before and after the move; `ask` answers from bodies read from their operations; `mesh-knowledge.reviewed` is
|
|
||||||
emitted once per review; the module's manifest asks for no stream `versions`, no object bucket `sections` and
|
|
||||||
no state `names`, and the bus holds none for it once the move's check is clean; its tools and health name the
|
|
||||||
ledger's repairs and lag, and no digest store; the consumers of `reviews` still hear it.
|
|
||||||
|
|
||||||
## What it leaves out
|
## What it leaves out
|
||||||
|
|
||||||
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
|
Semantic or vector search; a browser view; 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.
|
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.
|
|
||||||
|
|
||||||
### The amendment of 2026-11-03
|
|
||||||
|
|
||||||
The amendment of 2026-11-03 to ADR 0595, ADR 0596 and ADR 0597 (designs 25 § 12, 32 § 4 and 55 together) was
|
|
||||||
reviewed by the four reviewers by architectural domain side by side (playbook 01), over three rounds, and the lead
|
|
||||||
ruled on every finding. What was found, and what answers it:
|
|
||||||
|
|
||||||
| Domain | Found | Answered by |
|
|
||||||
|---|---|---|
|
|
||||||
| security | the author could be words the module chose; a person's dangerous tools had no role, mark or path to the process; the caller travelled as a plain field | design 25 § 12.3 (marks, the process's own tool subject, the identity seat's signed token), § 12.4 (the tool runner stamps the caller it proved; the move's authors marked imported) |
|
|
||||||
| seams | the bus module asked for its own events in the new form, which it would have to create itself (ADR 0595 §10); a person's tool had no join to the process; a verdict was written twice with no order | design 25 § 12.3 (its events on its old `streams` section; the process's own tool subject); design 55 § 2.1 (the `review` operation first, `reviews` caught up from it) |
|
|
||||||
| running qualities | overdue creation was undefined and raised by nobody; the database's rollback write lived in memory; a forward delivery after a rollback could miss acceptances and verdicts; no size estimate of the heads | design 25 § 12.2 (five minutes, the watchman, durable consumers, `check` at start); design 55 § 8.1 step 6 (`database.sequence`, the check at every start before the drop), § 2.1 (the heads' estimate) |
|
|
||||||
| health | the bus module's health would have fired on a quiet mesh; conditions had no clearing; `database-behind` had no clearing | design 25 § 12.2 and § 12.3 (each condition with what clears it); design 55 § 8.1 step 6 |
|
|
||||||
| events and logs | an event lost when the module stopped after `apply`; the bus module's events had no reader | design 55 § 1 (each event sent with its operation's sequence as id, the state `sent`); design 25 § 12.3 (`history` of one entry) |
|
|
||||||
| testing | the bus module had no test that starts it whole; live tests would have filled the live bus; the budget was not counted | design 25 § 12.7 (the nats module's integration test, live drift only by a manifest change, the budget paragraph); design 55 § 10 |
|
|
||||||
| upgrade | the build order lacked the grants part's binding and two undo steps | design 25 § 12.6 |
|
|
||||||
| tools | the ledger's repairs had no tool for the next owner; the bus module's events had no read tool | design 25 § 12.5 (served for every ledger owner), § 12.3 |
|
|
||||||
|
|
||||||
**Left to the operator**, because each changes an accepted record: a margin between raising and clearing the
|
|
||||||
condition `full` (ADR 0595 §6 raises and clears it at 75 percent, so an entry sitting there flaps), and an event of
|
|
||||||
its own for `drop` and `recreate`. **A correction of fact** for ADR 0595 §4: the bus module deletes through `recreate`
|
|
||||||
as well as `drop`. Each is noted on issue 1966.
|
|
||||||
|
|||||||
@@ -11,14 +11,7 @@ amendment, issues, build handoff, constitution sync) is documented there, and ag
|
|||||||
through them. Thin skills in `.claude/skills/` wrap these playbooks for invocation
|
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-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
|
`hq-handoff`, `hq-sync-constitution`, `hq-status`, `hq-cleanup`); each defers to its playbook as
|
||||||
authoritative and adds only the mechanical scaffolding. Four reviewer agents in `.claude/agents/` carry
|
authoritative and adds only the mechanical scaffolding.
|
||||||
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. A fifth,
|
|
||||||
`research-reader`, carries one reading task of playbook 01's step 5: code on main, counts from the manifests, a
|
|
||||||
try in process. Four more carry playbook 07: `mesh-preparer` (the prepare step), `mesh-developer` (develop),
|
|
||||||
`mesh-code-reviewer` (the review) and `mesh-watcher` (every wait). Every agent starts from the knowledge base and maps
|
|
||||||
each interaction onto a mesh path; the lead writes only the handover, never an agent's way of working. A subagent runs in the session that started it, from hq: its way of working comes from its definition and hq's playbooks, its knowledge from the knowledge base; one given a coding task works in a worktree under hq's `.work/` and also reads the conventions of the repository it changes, and where those contradict hq, hq wins and the agent says so.
|
|
||||||
|
|
||||||
## The development cycle
|
## The development cycle
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user