Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37b46d5349 |
@@ -72,6 +72,12 @@ answers from it. Nothing flows back: this repository is public, the mesh is not,
|
||||
would be how installation-specific detail arrives into documents that must not carry it
|
||||
([`README.md`](../README.md)).
|
||||
|
||||
> **The mechanism changed — 2026-09-30, by ADR 0153.** What stands: read where it is written, no copy,
|
||||
> one-way. What moved: the reader is a module the mesh assigns (`records`, a checkout at a commit every
|
||||
> answer names) rather than the agent session of design 15, which is not built; and "the search consults
|
||||
> the agent" has no store to consult since the cut-over — the console's tool list is where the record
|
||||
> appears beside everything else. [ADR 0153](0153-the-record-is-read-by-a-module-and-the-console-lists-it.md).
|
||||
|
||||
## Consequences
|
||||
|
||||
**This repository stops being a fourth knowledge system, properly.** The original objection was
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
---
|
||||
topic: how we work
|
||||
status: accepted
|
||||
date: 2026-09-30
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 02-DECISIONS/0025-the-design-record-is-read-not-copied.md
|
||||
---
|
||||
|
||||
# 153. The record is read by a module the mesh assigns, and the console lists it
|
||||
|
||||
## Context
|
||||
|
||||
[ADR 0025](0025-the-design-record-is-read-not-copied.md) decided that this repository is **read where
|
||||
it is written, never copied to be found**: an agent reads it directly, and a search of the mesh's
|
||||
memory consults that agent so its answers appear beside ordinary results. It named the check that
|
||||
closes [issue 006](../04-ISSUES/006-hq-is-not-indexed-into-the-knowledge-base/00-report.md): search
|
||||
for a phrase that appears only in a design document here, and get it back. It gated the build on an
|
||||
agent that did not exist — the mesh session of
|
||||
[15 — The agent session](../03-DESIGN/01-to-be/15-the-agent-session.md) — and on a search that
|
||||
does not exist either, now: the knowledge base 0025 meant was the predecessor's, and since the
|
||||
cut-over nothing reaches it ([issue 147](../04-ISSUES/147-the-operators-tools-still-dial-the-bus-that-was-removed/00-report.md)).
|
||||
|
||||
**So the two halves of 0025 have no home.** There is no store to be "beside", and no session to be
|
||||
the reader. What the mesh has instead, since today: a tool model in which every module answers what
|
||||
it serves, and a console on the machine a person sits at that lists every tool the running modules
|
||||
answer ([ADR 0152](0152-the-operators-surface-is-a-module-the-console.md)). An agent holding the
|
||||
console does not search a store; it reads a tool list and calls what fits the question.
|
||||
|
||||
**What 0025 could not tolerate was a derived copy** — the enforced copy winning while the reasoned one
|
||||
quietly stops being true. It rejected a sync for that reason and for no other. A git checkout is not a
|
||||
derived copy: it is the same bytes at a commit the answer names, and the only way it can differ from
|
||||
the source is by lagging behind it, which is measurable and stated. 0025's own words allow it —
|
||||
*retrieval is an agent reading this repository, not a copy living in a second store* — and the
|
||||
transformation that makes a copy dangerous is exactly what a checkout does not do.
|
||||
|
||||
## Considered Options
|
||||
|
||||
**1. Wait for the mesh session.** Rejected. Design 15 is `designed` with nothing built, its model
|
||||
access is a provisions question with no consumer identity yet, and 006 has waited since 2026-08-23.
|
||||
A record whose check cannot run is a rule enforced by nothing.
|
||||
|
||||
**2. The console reads the repository itself.** Rejected. The console holds nothing and decides
|
||||
nothing (ADR 0152, ADR 0035); a reader inside it would be a second implementation of a thing that
|
||||
should be one module, unavailable to a person's client and to any other module.
|
||||
|
||||
**3. A module that keeps a checkout of the repository and answers questions about it, listed by the
|
||||
console like any tool.** Chosen.
|
||||
|
||||
## Decision
|
||||
|
||||
**The reader is a module: `records`.** It requires the `git` provision — the forge — clones the
|
||||
repository its settings name, keeps the checkout current on every merge the forge announces and on a
|
||||
timer, and answers over the bus: where a phrase appears as written (document, line, nearest heading),
|
||||
one document whole, what a folder holds, and where the checkout stands — always with the commit it
|
||||
read. Nothing is indexed, ranked or summarised: a design record is found by its own words, and a
|
||||
reader deciding which words matter would be a second opinion about somebody else's document.
|
||||
|
||||
**The repository is a setting, not a manifest field.** The module names no mesh
|
||||
([ADR 0112](0112-a-module-definition-names-no-node-mesh-or-path.md)): which repository it reads is
|
||||
the assignment's business, and an installation that keeps its record elsewhere sets that. Until a
|
||||
repository is set it serves no tools and says why. Public repositories only; it asks for no
|
||||
credential, because a secret it did not need would be one more thing to seal.
|
||||
|
||||
**"Beside everything else" is the console's tool list.** 0025's second half — the search consults the
|
||||
agent — has no store to consult and needs none: the console lists `records_search` beside the forge's
|
||||
tools and the mesh's own verbs, with a description that says when to call it, and an agent choosing
|
||||
tools for a symptom is the search. That is surfacing, not merely reaching: nobody has to know this
|
||||
repository exists to be offered it.
|
||||
|
||||
**Reading stays one-way.** The module reads the forge and answers; nothing flows back into the
|
||||
repository. It holds no credential that could write.
|
||||
|
||||
**The mesh session, when it exists, is a caller of this module, not a replacement for it.** Design 15's
|
||||
*it holds the design record by reading it* is satisfied by asking `records`; the session brings
|
||||
judgement, this brings the text.
|
||||
|
||||
## Consequences
|
||||
|
||||
- **Issue 006 closes on 0025's own check**, run through the console: `records_search` for a phrase
|
||||
that appears in one design document here returns that document. The module's test does the same
|
||||
against a repository it makes.
|
||||
- **The as-is knowledge document is rewritten.** [`07-knowledge.md`](../03-DESIGN/00-as-is/07-knowledge.md)
|
||||
described the predecessor's two stores; neither is reachable from the mesh, and what the mesh knows
|
||||
is now what its modules answer. Saying otherwise is the failure this repository exists to name.
|
||||
- **A checkout lags.** Between a merge and the next sync — seconds when the forge announces it,
|
||||
minutes when it does not — an answer is the previous commit's, and says which. That is the cost of
|
||||
no copy, and it is a number rather than a silence.
|
||||
- **The reader depends on the forge module's event, by name.** `consumes: gitea.pull.merged` names a
|
||||
module rather than the `git` seat, because the seat declares no events. A forge that is not gitea
|
||||
leaves the timer as the only refresh, which still works.
|
||||
- **What got harder:** the record is now reachable from every machine holding a console, which is what
|
||||
was wanted, and a reader must remember that this repository is public and the mesh is not — the
|
||||
module reads the public repository and nothing about the installation.
|
||||
|
||||
## How this is checked
|
||||
|
||||
| Rule | Checked by |
|
||||
|---|---|
|
||||
| A phrase in one document comes back from where it is written, with the commit | the module's test against a repository it makes; and live, through the console |
|
||||
| A merge on the origin is pulled and the next answer names the new commit | the same test |
|
||||
| A path outside the checkout is refused, not resolved | a test per shape |
|
||||
| A failed sync leaves the checkout standing and is said | a test against an unreachable origin |
|
||||
| Without a repository set, no tools are served and the log says why | the module's own start |
|
||||
| The console lists `records_search` beside every other tool | the console's listing, live |
|
||||
|
||||
## References
|
||||
|
||||
- [ADR 0025](0025-the-design-record-is-read-not-copied.md) — extended: the reader is a module, the search is the console's list
|
||||
- [ADR 0152](0152-the-operators-surface-is-a-module-the-console.md) — what lists it
|
||||
- [issue 006](../04-ISSUES/006-hq-is-not-indexed-into-the-knowledge-base/00-report.md) — what closes
|
||||
- [35 — Reading the record](../03-DESIGN/01-to-be/35-reading-the-record.md) — the design
|
||||
- mesh-catalog `modules/records` — the module (PR 183)
|
||||
@@ -0,0 +1,133 @@
|
||||
---
|
||||
topic: the mesh
|
||||
status: accepted
|
||||
date: 2026-09-30
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 02-DECISIONS/0132-a-seat-carries-the-tools-its-holder-must-serve.md
|
||||
---
|
||||
|
||||
# 154. The mesh's own verbs are the mesh-controller seat's tools, and which verbs those are
|
||||
|
||||
## Context
|
||||
|
||||
[ADR 0132](0132-a-seat-carries-the-tools-its-holder-must-serve.md) decided that a seat's protocol
|
||||
carries its tools in full, that holding a seat means serving them, and that the mesh's own verbs are
|
||||
the `mesh-controller` seat's. It named three prerequisites, none in place: the protocol in the store
|
||||
rather than in compiled defaults; a protocol richer than a list of verbs; a node-scoped seat's subject
|
||||
carrying the node. And it left one thing to a decision per seat: **which verbs each seat serves**,
|
||||
because a seat's tools bind every future holder.
|
||||
|
||||
The console shipped the same day ([ADR 0152](0152-the-operators-surface-is-a-module-the-console.md))
|
||||
and made the gap visible from the operator's chair: a person on a workstation could call every tool a
|
||||
*module* serves and none of the mesh's own. What a node runs, what is assigned, whether a push
|
||||
applied — the questions issue 147 opened with — still meant a shell on the control node. The console's
|
||||
own handshake said so.
|
||||
|
||||
The control plane already answers every one of those questions, as commands: `status --json`,
|
||||
`node show`, `plan --json`, `assign`, `push`. [ADR 0035](0035-one-implementation-several-surfaces.md)
|
||||
says a surface is an adapter over those with no decisions in it, and the `api` verb proves the shape:
|
||||
every route calls the function the command line calls.
|
||||
|
||||
## Considered Options
|
||||
|
||||
**1. Leave the mesh's verbs to the shell until an identity provider authenticates the HTTP API.**
|
||||
Rejected. The authenticated network surface is for a browser on another machine; the console is
|
||||
already behind the machine's login (0152), and the bus already carries every other tool call under an
|
||||
account whose permission list says what it may ask. Waiting would keep the one surface the mesh has
|
||||
from answering the mesh's own questions, for a reason that does not apply to it.
|
||||
|
||||
**2. Serve the verbs as the mesh-controller *module's* tools, `mesh.mod.mesh-controller.tool.<verb>`.**
|
||||
Rejected; 0132 rejected it already. The controller holds a seat, and the verbs must keep their address
|
||||
while the control plane is being replaced, which is the moment they are most needed. A module's name
|
||||
would change with the implementation; the seat's does not.
|
||||
|
||||
**3. Call each command's function inside the serving process.** Rejected on two facts: the commands
|
||||
print, to the process's standard output, and two calls answered at once would read each other's
|
||||
words; and each command opens and closes its own stores, which the serving process holds open. Making
|
||||
every command return a value is the larger refactor, and it would give the tools a second code path to
|
||||
keep in step with the command line — the thing ADR 0035 forbids.
|
||||
|
||||
**4. The holder of the seat runs the command it names, in its own binary, and answers what it
|
||||
printed.** Chosen.
|
||||
|
||||
## Decision
|
||||
|
||||
**The `mesh-controller` seat serves twelve verbs**, and these are its interface, additive within a
|
||||
version ([33 — The tools the mesh answers](../03-DESIGN/01-to-be/33-the-tools-the-mesh-answers.md) §7):
|
||||
|
||||
| verb | answers with | takes |
|
||||
|---|---|---|
|
||||
| `tools` | every seat's tools, from the mesh's records | nothing |
|
||||
| `status` | what is wrong, quiet, behind, waiting — `status --json` | nothing |
|
||||
| `nodes` | every machine and its mode | nothing |
|
||||
| `node` | what one machine reported, what it is assigned, why | `node` |
|
||||
| `modules` | every module, its version, commit and machines | nothing |
|
||||
| `seats` | every seat, what it delivers, who holds it — `seats --json` | nothing |
|
||||
| `builds` | what was built lately and what came of it | `module` (optional) |
|
||||
| `plan` | the declaration a machine would be sent — `plan --json` | `node` |
|
||||
| `assign`, `unassign` | the mesh's own words, refusal included | `node`, `module` |
|
||||
| `push` | that it was sent; `status` says what the machine did | `node` (optional: every machine behind) |
|
||||
| `build` | that the build machine was asked; `builds` says what came of it | `repository`, `path`, `ref` |
|
||||
|
||||
**Each verb runs the command it names, in the controller's own binary, and answers what the command
|
||||
printed** — the output, whether it succeeded, and, where the command speaks JSON, the same as data. A
|
||||
refusal is the command's refusal in the command's words, because it is the same output. A verb takes
|
||||
only the arguments its schema names; nothing reaches a flag the schema did not declare. `push` and
|
||||
`build` are sent and not waited for: a call that blocked for a whole apply would time out on every
|
||||
machine that takes a minute and say nothing about the others.
|
||||
|
||||
**The three prerequisites are built.** A seat's protocol is three columns on its row, seeded from the
|
||||
compiled defaults where a row had none and additively thereafter, so a verb a release adds joins the
|
||||
row and nothing an operator wrote is taken away. A served verb is its name, what it does, and the
|
||||
schema of its arguments and answer; a manifest may still write a bare name. A node-scoped seat's tool
|
||||
carries the node it is asked of, as the last token of its subject; a mesh-scoped seat's stays flat.
|
||||
|
||||
**Holding a mesh seat requires serving its verbs**, judged where the store's set is loaded, and the
|
||||
refusal names the missing verbs. The controller's own manifest lists the twelve under `tools`.
|
||||
|
||||
**Discovery reads the records, through the seat.** `tools` is one of the twelve because the console
|
||||
cannot read the store and should not: the mesh answers for its own records through the role that owns
|
||||
them, and the answer is true while any *other* holder restarts. It is not true while the control plane
|
||||
itself restarts, and the console says so rather than hiding the modules' tools with it.
|
||||
|
||||
**A grant of `*` reaches a role's tools; `seat:<seat>.<verb>` grants one.** The console's `*` needed no
|
||||
change to reach the mesh's verbs, which is what a grant meaning *every tool* should mean.
|
||||
|
||||
## Consequences
|
||||
|
||||
- **The console answers the mesh's own questions.** Issue 147's first paragraph closes: what a node
|
||||
runs, what is assigned, whether a push applied, from the machine the person sits at, over the bus,
|
||||
under an account whose permission list says so.
|
||||
- **Whoever may call `mesh-controller.push` may change the mesh.** That is the console's `*` on a
|
||||
machine whose login owns the mesh (0152), and a person's account only if `operator issue` says so.
|
||||
A grant reviewer reads `*` and `seat:mesh-controller.` with the same care.
|
||||
- **A verb here binds every future controller.** Twelve is deliberate: what an operator asks weekly,
|
||||
and nothing that is still finding its shape (`take`, `converge`, `settings`, `secret` stay commands).
|
||||
- **A command's text is the answer**, and text changes. The three verbs that speak JSON carry it as
|
||||
data; the rest are read by a person or an agent, not parsed. Anything that needs a shape asks for
|
||||
`--json` to be added to the command first, which is the right order.
|
||||
- **What got harder:** the mesh-controller seat's row now carries a protocol an operator could edit, and
|
||||
a verb removed from the row is a verb the controller stops serving without a build. That is
|
||||
ADR 0122's arrangement applied to tools, and `seats` shows the row.
|
||||
|
||||
## How this is checked
|
||||
|
||||
| Rule | Checked by |
|
||||
|---|---|
|
||||
| Every declared verb is one the binary can run, with the arguments its schema names | a test walks the table and derives a command line for each |
|
||||
| A verb missing a required argument is refused in its own words, before anything runs | a test per shape |
|
||||
| A holder that does not serve a mesh seat's verbs cannot hold it, and the refusal names them | a catalogue test against a seat with two verbs and a holder with one |
|
||||
| A node-scoped seat's tool carries the node; a mesh seat's does not | the bus composition test: two nodes derive two addresses |
|
||||
| The controller subscribes its seat's tools and may answer | the composition test, and the golden user list |
|
||||
| `*` reaches a role's tools; `seat:` grants one and refuses a name with no verb | the composition test |
|
||||
| The protocol is seeded into the row and widened additively | the store-backed seat test |
|
||||
| Live: the console lists `mesh-controller.status` and a call answers what `status --json` prints | the rollout of this record |
|
||||
|
||||
## References
|
||||
|
||||
- [ADR 0132](0132-a-seat-carries-the-tools-its-holder-must-serve.md) — extended: the prerequisites built, the verbs decided
|
||||
- [ADR 0152](0152-the-operators-surface-is-a-module-the-console.md) — the surface that lists them
|
||||
- [ADR 0035](0035-one-implementation-several-surfaces.md) — a surface is an adapter with no decisions in it
|
||||
- [ADR 0122](0122-a-seat-is-data-a-rename-is-a-database-update.md) — the row is the mesh's, and now carries the protocol
|
||||
- [33 — The tools the mesh answers](../03-DESIGN/01-to-be/33-the-tools-the-mesh-answers.md) — the design this completes
|
||||
@@ -168,6 +168,7 @@ python3 00-META/checks/index.py fail if stale
|
||||
- **0132** — [A seat carries the tools its holder must serve](0132-a-seat-carries-the-tools-its-holder-must-serve.md)
|
||||
- **0134** — [The mesh says what it applied](0134-the-mesh-says-what-it-applied.md)
|
||||
- **0142** — [The mesh delivers its own components as binaries, not as container images](0142-the-mesh-delivers-its-own-components-as-binaries.md)
|
||||
- **0154** — [The mesh's own verbs are the mesh-controller seat's tools, and which verbs those are](0154-the-meshs-own-verbs-are-the-controller-seats-tools.md)
|
||||
|
||||
### Its tiers, from the bottom up
|
||||
|
||||
@@ -298,5 +299,6 @@ python3 00-META/checks/index.py fail if stale
|
||||
- **0034** — [The local account owns the mesh, and a web application's login is not that](0034-the-local-account-owns-the-mesh.md)
|
||||
- **0080** — [The development cycle is checked, not trusted](0080-the-development-cycle-is-checked.md)
|
||||
- **0081** — [A decision nothing cites is not yet in the chain](0081-a-decision-nothing-cites-is-not-yet-in-the-chain.md)
|
||||
- **0153** — [The record is read by a module the mesh assigns, and the console lists it](0153-the-record-is-read-by-a-module-and-the-console-lists-it.md)
|
||||
|
||||
<!-- index:end -->
|
||||
|
||||
@@ -1,78 +1,58 @@
|
||||
---
|
||||
layer: as-is
|
||||
status: implemented
|
||||
code: [hal]
|
||||
updated: 2026-08-23
|
||||
decisions: []
|
||||
code: [mesh-catalog modules/records, mesh-catalog modules/mesh-console]
|
||||
updated: 2026-09-30
|
||||
decisions:
|
||||
- 02-DECISIONS/0025-the-design-record-is-read-not-copied.md
|
||||
- 02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md
|
||||
- 02-DECISIONS/0152-the-operators-surface-is-a-module-the-console.md
|
||||
---
|
||||
|
||||
# Knowledge
|
||||
|
||||
The mesh keeps two knowledge stores. They are not redundant, and knowing which is which is the
|
||||
difference between finding an answer in one search and rediscovering it over several hours.
|
||||
**The mesh keeps no knowledge store.** What it knows is what its modules answer, and the way a person
|
||||
or an agent asks is the console's tool list on the machine they sit at
|
||||
([13 — The console](13-the-console.md)). This document used to describe two stores; it is rewritten
|
||||
because neither exists from the mesh's side, and an as-is document that describes what is gone is a
|
||||
brochure.
|
||||
|
||||
## The operational memory
|
||||
## What was here, and where it went
|
||||
|
||||
A store of operational notes, written and read by whoever — human or agent — is working. Each
|
||||
note is a slug and a body: how something works, what went wrong, what the fix was, what
|
||||
assumption turned out to be false.
|
||||
Until the cut-over of 2026-09-28 the predecessor ran two stores: an operational memory of notes
|
||||
indexed on symptoms, and a structured archive of governed documents with a librarian approving
|
||||
promotion. Both were reached through the predecessor's tool server over the bus the mesh removed
|
||||
([issue 147](../../04-ISSUES/147-the-operators-tools-still-dial-the-bus-that-was-removed/00-report.md)).
|
||||
Nothing in the mesh reaches them now, and nothing in the mesh has replaced them: there is no note
|
||||
store, no archive, no librarian, and the lessons of the last days were written into this repository by
|
||||
hand. That is a gap, and it is stated here rather than papered over. What replaces a symptom-indexed
|
||||
memory, if anything does, is undecided.
|
||||
|
||||
It is indexed on **symptoms**. The entry someone needs is usually titled after the error they
|
||||
are staring at, which is why the standing instruction is to search the literal error text
|
||||
before forming a hypothesis rather than after one fails.
|
||||
## The record
|
||||
|
||||
Its content is overwhelmingly the record of previous debugging: a large body of
|
||||
troubleshooting entries, module conventions, and standing notes about work that is open. It is
|
||||
the mesh's institutional memory of *what has already gone wrong*.
|
||||
**The design record is read where it is written.** Since 2026-09-30 a module, `records`, keeps a
|
||||
checkout of this repository from the forge — cloned from the `git` seat, reset to the origin on every
|
||||
merge the forge announces and every ten minutes — and answers over the bus: where a phrase appears as
|
||||
written, one document whole, what a folder holds, and where the checkout stands, each naming the
|
||||
commit it read. Which repository it reads is a setting on its assignment; the module names no mesh.
|
||||
|
||||
The cost of skipping it is documented in the mesh's own record: entries have been rediscovered
|
||||
from scratch, over hours, in sessions where the search was skipped because the trail felt
|
||||
confident. It fires hardest on familiar ground, not unfamiliar ground.
|
||||
It is listed by the console beside every other tool, with a description that says to search the
|
||||
literal words of a symptom before forming a hypothesis. That is what
|
||||
[ADR 0025](../../02-DECISIONS/0025-the-design-record-is-read-not-copied.md) meant by *beside
|
||||
everything else*, in a mesh with no store to be beside
|
||||
([ADR 0153](../../02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md)).
|
||||
|
||||
## The structured archive
|
||||
Nothing is copied. A checkout lags the source by seconds after an announced merge and by minutes
|
||||
otherwise, and says so.
|
||||
|
||||
A second store, structured rather than flat: spaces, pages, revisions, tiers, and full-text
|
||||
search. Where the operational memory is a note, this is a document with an owner and a
|
||||
lifecycle.
|
||||
## The constitution
|
||||
|
||||
Content is promoted through tiers — private, then team, then platform — with a librarian agent
|
||||
owning approval and promotion at the boundary. Proposals to edit are reviewed rather than
|
||||
applied.
|
||||
|
||||
This is where the mesh's **governed** documents live, including the constitution injected into
|
||||
design sessions ([ADR 0020](../../02-DECISIONS/0020-the-mesh-is-governed-by-a-constitution.md)).
|
||||
|
||||
## Why both
|
||||
|
||||
The distinction is by lifecycle, not by subject.
|
||||
|
||||
| Operational memory | Structured archive |
|
||||
|---|---|
|
||||
| Written the moment something is learned | Written deliberately, reviewed |
|
||||
| Flat, symptom-indexed | Structured, tiered, owned |
|
||||
| Anyone writes; nothing approves | Promotion is approved |
|
||||
| Truth is "this happened" | Truth is "this is agreed" |
|
||||
|
||||
Collapsing them would cost one of the two properties: either every hard-won note waits for
|
||||
review, or governed documents can be changed by anyone mid-incident.
|
||||
[`00-META/how-we-build.md`](../../00-META/how-we-build.md) is the source of the mesh constitution
|
||||
([ADR 0021](../../02-DECISIONS/0021-hq-is-the-source-of-the-constitution.md)). The page it used to be
|
||||
synchronised into lived in the predecessor's archive and is unreachable; the constitution today is
|
||||
read from this repository, through the same module, and playbook 05's sync has nothing to write to.
|
||||
|
||||
## Where this repository sits
|
||||
|
||||
This repository is a third thing, and the objection was raised when it was created: a fourth
|
||||
knowledge system repeats the mistake the split was made to fix.
|
||||
|
||||
The answer given was **indexing, not location** — that these documents are indexed into the
|
||||
knowledge base so that a symptom search returns them alongside everything else. One source,
|
||||
many surfaces.
|
||||
|
||||
**That indexing does not currently exist.** A search for this repository's content returns
|
||||
nothing. The claim is load-bearing for the decision to separate the repository at all, and
|
||||
until it is true, this repository is exactly the fourth knowledge system the objection
|
||||
described. Recorded here because it is a statement about how the mesh's knowledge actually
|
||||
works today, and as [`04-ISSUES/006`](../../04-ISSUES/006-hq-is-not-indexed-into-the-knowledge-base/00-report.md).
|
||||
|
||||
## The librarian
|
||||
|
||||
A single agent owns the archive's approvals and promotions. Its approval capabilities have at
|
||||
times not been reachable as tools, which does not affect the operational memory but does mean
|
||||
promotion stops silently — the store keeps accepting proposals that nothing can approve.
|
||||
A third thing beside two that are gone, which makes it the first: the one governed record the mesh
|
||||
has, public, read by a module the mesh assigns, and edited nowhere else.
|
||||
|
||||
@@ -82,6 +82,22 @@ to clone.
|
||||
The schema column added for this defaults to empty rather than null, because "not on a seat" is a
|
||||
real answer, so every row recorded before the change keeps exactly the meaning it had.
|
||||
|
||||
## A seat's protocol is on its row, and the controller serves its own
|
||||
|
||||
*Since 2026-09-30 ([ADR 0154](../../02-DECISIONS/0154-the-meshs-own-verbs-are-the-controller-seats-tools.md)).*
|
||||
The `seat` table carries `accepts`, `emits` and `serves`; `serves` holds each verb with its description
|
||||
and input schema. The rows were seeded from the compiled defaults the first time a controller with the
|
||||
columns migrated, and each later migration adds any verb the defaults name that a row lacks, never
|
||||
removing one. `UseSeats` still falls back to the compiled protocol for a row with none, which after the
|
||||
first seeding is no row.
|
||||
|
||||
The `mesh-controller` seat serves twelve verbs — `tools`, `status`, `nodes`, `node`, `modules`, `seats`,
|
||||
`builds`, `plan`, `assign`, `unassign`, `push`, `build` — on `mesh.seat.mesh-controller.tool.<verb>`,
|
||||
each answered by the controller running that command in its own binary and returning what it printed.
|
||||
A module claiming a mesh seat with verbs must list them under `tools` or registration refuses it by
|
||||
name. A node-scoped seat's tool is `mesh.seat.<seat>.tool.<verb>.<node>`; no node-scoped seat declares
|
||||
one yet.
|
||||
|
||||
## Where this differs from the design
|
||||
|
||||
**Capacity is not implemented.** The design's vocabulary has a seat with a capacity, and a
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
---
|
||||
layer: as-is
|
||||
status: implemented
|
||||
code: [mesh-catalog modules/mesh-console, mesh-tools src/mesh.ts, mesh-tools src/http.ts, mesh-tools src/runtime.ts, mesh-controller internal/broker, mesh-controller cmd/mesh-controller/check.go]
|
||||
code: [mesh-catalog modules/mesh-console, mesh-tools src/mesh.ts, mesh-tools src/http.ts, mesh-tools src/runtime.ts, mesh-controller internal/broker, mesh-controller cmd/mesh-controller/check.go, mesh-controller cmd/mesh-controller/seatverbs.go]
|
||||
updated: 2026-09-30
|
||||
decisions:
|
||||
- 02-DECISIONS/0152-the-operators-surface-is-a-module-the-console.md
|
||||
- 02-DECISIONS/0095-the-control-plane-is-the-way-to-ask-a-module.md
|
||||
- 02-DECISIONS/0037-where-a-module-lives.md
|
||||
- 02-DECISIONS/0154-the-meshs-own-verbs-are-the-controller-seats-tools.md
|
||||
---
|
||||
|
||||
# The console, as it runs
|
||||
@@ -30,11 +31,14 @@ mesh records rather than rolls out — and 62 tools from the rest.
|
||||
`tools/call` reaches any tool by `<module>.<tool>`, listed or not. The console's grant is `*`, so what it
|
||||
may call is every tool on the mesh; its account may publish nothing else and subscribes nothing.
|
||||
|
||||
## What it does not answer
|
||||
## The mesh's own verbs
|
||||
|
||||
The mesh's own verbs. `status`, `push`, `assign` and the rest are not served on the bus — they are the
|
||||
`mesh-controller` seat's tools under ADR 0132, whose three prerequisites are not built — so a person
|
||||
still opens a shell on the control node for them. The console's handshake says so.
|
||||
*Since 2026-09-30 evening ([ADR 0154](../../02-DECISIONS/0154-the-meshs-own-verbs-are-the-controller-seats-tools.md)).*
|
||||
The console asks the `mesh-controller` seat's `tools` verb beside the modules and lists every role's
|
||||
tools as `<seat>.<verb>` — `mesh-controller.status`, `mesh-controller.push` and the other ten. A call
|
||||
to `<prefix>.<name>` reaches the seat when the prefix is a seat declaring that verb, and the module
|
||||
otherwise; `seat:<seat>.<verb>` says so outright. When the control plane does not answer, the list
|
||||
names `mesh-controller (seat)` as not answering and carries the modules' tools regardless.
|
||||
|
||||
## Around it
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ Where the two disagree, the implementation wins and the disagreement is stated.
|
||||
| [`04-delivery.md`](04-delivery.md) | Push to running: the three silos, levels, and what a green pipeline proves |
|
||||
| [`05-runtime-and-installation.md`](05-runtime-and-installation.md) | The node runtime, its modes, and how a node comes into being |
|
||||
| [`06-configuration-and-secrets.md`](06-configuration-and-secrets.md) | Managed files, value resolution, and where secrets live |
|
||||
| [`07-knowledge.md`](07-knowledge.md) | The two knowledge stores, and what each is for |
|
||||
| [`07-knowledge.md`](07-knowledge.md) | The mesh keeps no store: what it knows is what modules answer, and the record is read by one |
|
||||
| [`08-agents-and-work.md`](08-agents-and-work.md) | Agents as employees, tasks, workflows, and the meeting model |
|
||||
| [`09-interfaces-and-observability.md`](09-interfaces-and-observability.md) | How the mesh is reached and watched — tools, board, proxy, health, thoughts |
|
||||
| [`10-module-catalogue.md`](10-module-catalogue.md) | The catalogue's shape, and what its shape says |
|
||||
|
||||
@@ -148,6 +148,10 @@ than reproduced from a declaration — because there is nothing to reproduce it
|
||||
([ADR 0025](../../02-DECISIONS/0025-the-design-record-is-read-not-copied.md)), not by holding a
|
||||
copy. It is that reader; there is not a second agent for it.
|
||||
|
||||
*2026-09-30:* the reading is a module's — `records`, [35 — Reading the record](35-reading-the-record.md),
|
||||
[ADR 0153](../../02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md). The
|
||||
session, when built, asks it rather than reading for itself; what it adds is judgement, not text.
|
||||
|
||||
**It answers into a symptom search**, so what it knows appears beside ordinary results rather than
|
||||
only when it is asked. **And when it cannot be reached, the search says so.** A result set that
|
||||
silently omits this material looks identical to one where nothing matched — the same rule as the
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
---
|
||||
layer: to-be
|
||||
status: designed
|
||||
code: []
|
||||
updated: 2026-09-28
|
||||
status: in-progress
|
||||
code: [mesh-controller, mesh-tools]
|
||||
updated: 2026-09-30
|
||||
decisions:
|
||||
- 02-DECISIONS/0154-the-meshs-own-verbs-are-the-controller-seats-tools.md
|
||||
- 02-DECISIONS/0132-a-seat-carries-the-tools-its-holder-must-serve.md
|
||||
- 02-DECISIONS/0129-a-seat-carries-the-protocol-of-its-role.md
|
||||
- 02-DECISIONS/0095-the-control-plane-is-the-way-to-ask-a-module.md
|
||||
@@ -126,6 +127,18 @@ by side until nothing is bound to the old one.
|
||||
- **Two nodes holding one node-scoped seat derive two addresses.** Checked by the same test as the rest
|
||||
of the subject table.
|
||||
|
||||
## What is built, 2026-09-30
|
||||
|
||||
Under [ADR 0154](../../02-DECISIONS/0154-the-meshs-own-verbs-are-the-controller-seats-tools.md): §2's
|
||||
two constraints (the protocol in the store's row, seeded additively; a verb with description and
|
||||
schema, a bare name still accepted), §3 for the mesh's seats (holding refused by naming the missing
|
||||
verbs), §4 (a node-scoped seat's tool carries the node as its last subject token; a user publishes
|
||||
`*`), and the third family — twelve verbs on the `mesh-controller` seat, each running the command it
|
||||
names in the controller's own binary. §5's first half is served rather than read: the seat's `tools`
|
||||
verb answers every seat's tools from the records, because the console cannot read the store; the
|
||||
console lists a role's tools beside the modules' own and resolves `<seat>.<verb>` to the seat when the
|
||||
seat declares that verb. Which verbs each *other* seat serves stays a decision per seat, still untaken.
|
||||
|
||||
## What this does not settle
|
||||
|
||||
- Which verbs each seat should serve. That is a decision per seat, and the reason to do it slowly: a
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
---
|
||||
layer: to-be
|
||||
status: in-progress
|
||||
code: [mesh-catalog modules/records]
|
||||
updated: 2026-09-30
|
||||
decisions:
|
||||
- 02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md
|
||||
- 02-DECISIONS/0025-the-design-record-is-read-not-copied.md
|
||||
- 02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md
|
||||
---
|
||||
|
||||
# 35 — Reading the record
|
||||
|
||||
**The design record, answered from a checkout the mesh keeps, at the commit it read.** A module,
|
||||
`records`, holds a working copy of a repository of markdown — this one, for this mesh — and answers
|
||||
where a phrase appears, what a document says, what a folder holds and where the copy stands. The
|
||||
console lists those answers beside every other tool
|
||||
([ADR 0153](../../02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md)).
|
||||
|
||||
## 1. What it keeps, and why that is not a copy
|
||||
|
||||
A git checkout, cloned from the forge that holds the `git` seat, brought up to date on every merge the
|
||||
forge announces and every ten minutes besides. The bytes are the repository's; nothing is derived
|
||||
from them and stored. What [ADR 0025](../../02-DECISIONS/0025-the-design-record-is-read-not-copied.md)
|
||||
refused was a second store that is *searched* while the first is *edited*, drifting silently. A
|
||||
checkout cannot drift; it can lag, and the lag is in every answer as the commit it was read at and
|
||||
in `records_status` as when it was last brought up to date.
|
||||
|
||||
The checkout is reset to the origin on every sync, never merged: it is the mesh's, so a local change
|
||||
is nobody's.
|
||||
|
||||
## 2. What it answers
|
||||
|
||||
| tool | answers |
|
||||
|---|---|
|
||||
| `records_search` | every place a phrase appears, as written and case-insensitively: document, line, the nearest heading above it; bounded, and says when it was |
|
||||
| `records_read` | one document, whole, or its first part with a note when very long |
|
||||
| `records_list` | what a folder holds: sub-folders and documents |
|
||||
| `records_status` | repository, forge, commit and its date, last sync, document count, last error |
|
||||
| `records_sync` | bring the checkout up to date now |
|
||||
|
||||
No ranking and no summary, on purpose: a record is found by its own words, and the reasoning is in
|
||||
the document, not in the tool.
|
||||
|
||||
## 3. What it is told, and what it refuses to guess
|
||||
|
||||
Three things, none from a manifest ([ADR 0112](../../02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md)):
|
||||
the directory its checkout lives in (a resource the mesh gives it), the forge's address (the `git`
|
||||
provision's binding, written into a file as `scheme://host:port`), and the repository's path on the
|
||||
forge (a **setting**, `{"repository": "<owner>/<name>"}`). Without the third it serves no tools and its
|
||||
log says so. Public repositories only; it holds no credential.
|
||||
|
||||
## 4. How it is found
|
||||
|
||||
The console asks every module what it serves and lists `records_search` with a description that says
|
||||
when to call it — *search the literal words of a symptom or a term before forming a hypothesis*. That
|
||||
is 0025's second half in today's mesh: there is no store to be beside, and an agent choosing from a
|
||||
tool list is the search.
|
||||
|
||||
## 5. Where it runs
|
||||
|
||||
Anywhere a node has the forge in reach; one assignment is enough, and a second on another machine is
|
||||
harmless. The mesh session of design 15, when it exists, calls this rather than reading for itself.
|
||||
|
||||
## How it is checked
|
||||
|
||||
| Check | Defends |
|
||||
|---|---|
|
||||
| a phrase in one document of a repository the test makes comes back from that document, with the commit; a second commit on the origin is pulled and the next answer names it | ADR 0025's check, ADR 0153 |
|
||||
| a path outside the checkout is refused; an empty search is refused | the reader reads the repository and nothing else |
|
||||
| a sync against an unreachable origin leaves the checkout standing and says why | silence and success never look alike |
|
||||
| live: through the console, `records_search` for a phrase that appears only in a design document here returns it | issue 006's closing check |
|
||||
|
||||
## What this does not settle
|
||||
|
||||
- Ranking or meaning. A search that understands a question is the session's job, not the reader's.
|
||||
- A private repository. That is a credential the module would have to hold, and a decision about
|
||||
what may read what.
|
||||
|
||||
## References
|
||||
|
||||
- [ADR 0153](../../02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md)
|
||||
- [ADR 0025](../../02-DECISIONS/0025-the-design-record-is-read-not-copied.md)
|
||||
- [34 — The console](34-the-console.md) — what lists it
|
||||
- [issue 006](../../04-ISSUES/006-hq-is-not-indexed-into-the-knowledge-base/00-report.md)
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
status: located
|
||||
opened: 2026-08-23
|
||||
located-in: [hq README.md, and the agent ADR 0025 names — not built]
|
||||
located-in: [mesh-catalog modules/records, mesh-catalog modules/mesh-console]
|
||||
fixed-by:
|
||||
amended-design: 02-DECISIONS/0025-the-design-record-is-read-not-copied.md
|
||||
---
|
||||
@@ -182,3 +182,14 @@ a module ([ADR 0152](../../02-DECISIONS/0152-the-operators-surface-is-a-module-t
|
||||
reader ADR 0025 describes is the mesh session of design 15, which would answer through that surface
|
||||
like any tool. What closes this is still the check 0025 names: search for a phrase that appears only in
|
||||
a design document here, and get it back.
|
||||
|
||||
## Built, 2026-09-30
|
||||
|
||||
[ADR 0153](../../02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md): the
|
||||
reader is a module, `records` (mesh-catalog PR 183), keeping a checkout of this repository from the
|
||||
forge and answering `records_search`, `records_read`, `records_list`, `records_status` and
|
||||
`records_sync` at the commit it read; the console lists them beside every other tool, which is where
|
||||
"beside everything else" lives in a mesh with no store. Design
|
||||
[35 — Reading the record](../../03-DESIGN/01-to-be/35-reading-the-record.md). The module's test runs
|
||||
0025's check against a repository it makes; this record closes when the same check passes through the
|
||||
console on the live mesh, and says so below.
|
||||
|
||||
Reference in New Issue
Block a user