Research 045 findings: serve the record as answers, keep review for what governs, and give light records a home
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request

This commit is contained in:
2026-10-11 00:30:13 +02:00
parent eac30272ee
commit fcf2fd0b46
2 changed files with 300 additions and 2 deletions
@@ -21,8 +21,13 @@ became: []
## What
Whether the mesh should **write** its own knowledge (decision records, guidelines, policies, designs and
playbooks) through a module's verbs, instead of only **reading** hand-written markdown. The effort
frames the questions below and answers none of them yet; the research itself is done separately.
playbooks) through a module's verbs, instead of only **reading** hand-written markdown, and whether it
should hold light content beside them: meeting notes, architectural drawings and blog posts.
The operator's purpose, given on 2026-10-11: the record becomes **shared knowledge that agents reach
through tools**, so that an agent gets what was decided as an answer instead of reading markdown files,
and a session no longer has to start in this repository's folder to know it. A session still starts here
for other work, such as writing a record.
Today the record is read-only. The `records` module reads this repository and serves it to sessions
([ADR 0153](../../02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md)).
@@ -38,6 +43,9 @@ Numbers collide, and the checks find a collision only after it happens. On 2026-
number for a different effort. On 2026-10-07 three decision numbers collided in one evening. A
record written by a verb could take its number from one counter, the way the issue tracker does.
Reading is costly too. Answering one question about what holds today means reading several records
whole, and the generated decision index is larger than one tool answer may be.
Some knowledge also has no home. This repository is public, so it may not name nodes or describe
operations; the mesh's knowledge about its own installation lives in agents' private notes, in no
shared and searchable place.
@@ -92,3 +100,8 @@ How this repository works (ADR 0019) and how the development cycle is checked (A
`records` module (ADR 0153) and the generated decision index (ADR 0248), the issue tracker and its
counters (ADR 0275, to-be 53), approval on a proving channel (ADR 0274), the playbooks in
`00-META/process/`, the hq checks in `00-META/checks/`, and the glossary.
## Documents
- [01 — Findings](01-findings.md): what exists, measured on 2026-10-11; an answer to each of the eight
questions; a first slice; and what needs the operator.
@@ -0,0 +1,285 @@
# 01 — Findings
Measured on 2026-10-11 against `main` of this repository, the records module and the issue tracker as they
answer through the mesh MCP server, and the hq checks in `00-META/checks/`. Section 0 is what exists; sections 1 to 8
answer the overview's eight questions in order; section 9 is the first slice this effort recommends; section 10
lists what needs the operator.
## The purpose, in the operator's words
The operator gave the purpose on 2026-10-11: the decisions and the rest of the record should become **shared
knowledge that agents reach through tools**, instead of reading markdown files, and a session should no longer
have to start in this repository's folder to know what was decided. A session still starts here for other work,
such as writing a record. On the same day the operator widened the scope: the knowledge base also holds **light
content**, such as meeting notes, architectural drawings and blog posts.
That purpose moves the weight of the overview's questions. Where the truth is stored (option A or B) matters
less than **what an answer looks like**: an agent needs the rule that holds now, with the records it rests on,
in one call and a few kilobytes.
An acceptance sentence for the whole effort: *a session started in any folder on any node asks "what holds
about the merge window, and why" and gets, in one call of under 4 KiB, the rules in force, the records they
come from, what changed them since, and the commit it was read at.*
## 0. What exists today, measured
| Fact | Measured |
|---|---|
| Records on `main` | 274 decision records, 44 research efforts (119 files), 55 to-be and 16 as-is designs, 8 playbooks, 361 issue narratives, the glossary: 951 files |
| Size | 6.9 MB of markdown, about 1.7 million tokens at four bytes a token; decision records alone 2.6 MB (about 650,000 tokens) |
| One question, today | "what holds about the merge window": `records_search` gives 26 places in 11 documents; reading the five records and the design they point to is 85 KB, about 21,000 tokens |
| The decision index | `records_decisions` answers 77 KB in one piece; the agent's tool-answer limit refused it inline, and it had to be read from a file in parts |
| What `records_search` does | a literal, case-insensitive phrase match giving document, line and heading; no ranking, no notion of which record is still in force |
| Frontmatter of a decision | `topic`, `status`, `date`, `deciders` on all 274; `extends` on 229 (182 with the folder prefix, 47 without); `supersedes-in-part` on 15 (21 links), `supersedes` on 8, `superseded-by` on 9, `rests-on` on 2, `amended` on 1 |
| Status of a decision | 265 `accepted`, 9 `superseded`; no record is marked as changed in part, though 21 links say so |
| Supersession said only in prose | 6 records say they supersede, amend or replace another and carry no field for it; 7 records carry a "superseded" marker in the body, of which only 1 has the field or the status |
| Progressive insights | 39 records carry the dated marker, 55 markers in all; 2 more use an older form |
| Change after writing | 189 of 271 traceable decision records were changed after the commit that created them; 34 paths were changed five times or more |
| Pace | commits touching decision records: 87 in the last ten days of August, 160 in September, 274 in the first eleven days of October |
| Number collisions | 16 decision numbers were taken twice by sessions working at once (2026-09-25 to 10-10), each repaired by a renumbering commit; 15 numbers on `main` are gaps; no research number collided |
| A decision's rules | 263 records have a `Decision` section; only 37 of them write it as numbered rules with a bold lead (198 rules in all); the rest write prose |
| Drawings | no file but markdown in the repository; no diagram source; 22 designs carry diagrams drawn in text characters |
| Knowledge with no home | the repository is public, and its README says what only makes sense to someone who knows this installation "is either a note in the wrong place or a disclosure"; one agent's private notes hold 89 files for one repository on one node, and issue 367 (a session's memory stays on the node where it was learned) is open |
| The hq checks | 33 rules: 25 judge one record, 4 the whole record, 4 the prose (section 6) |
Three things follow.
1. **The cost of an answer is the problem, not where the files are.** 85 KB for one question, and an index
too large for one tool answer, mean a session reads in parts or reads less than it should. Moving the
markdown into a store without changing the shape of the answer would keep that cost.
2. **The data that makes an answer cheap is missing or loose.** What a record decided is prose in 226 of 263
records. Which records changed which is half in fields, half in prose: 6 records say it only in prose, and
6 more carry a body marker that no field or status agrees with.
Status says `accepted` for records that 21 later links change in part.
3. **The records change after they are written, and that is reviewed.** 189 of 271 decision records were
edited after creation, every edit through a pull request with a human approval. Whatever is built must keep
that review for what governs the mesh.
## 1. Kinds and their lifecycles
Two families, which the operator's addition makes plain.
**Governing kinds** change how the mesh is built or run, and are reviewed before they hold:
| Kind | Lifecycle | Notes |
|---|---|---|
| decision | proposed → accepted → superseded; accepted records can be changed in part, and carry dated progressive insights | the 274 records |
| design | proposed → designed → in-progress → implemented, in one of two layers (to-be, as-is) | 71 documents |
| research | active → graduated or abandoned | 44 efforts |
| playbook | in force, or retired | 8, with no frontmatter today |
| glossary entry | in force, or retired with its replacement | one file today; an entry is the natural unit |
A **guideline** and a **policy**, which the overview named, have no record of their own today. What the
operator calls a policy is written as a decision; what an agent should do is a shared instruction section
(ADR 0274) or a personal rule ([ADR 0273](../../02-DECISIONS/0273-the-agents-home-is-the-modules-and-the-operators-personal-rules-and-lessons-are-registered-through-it.md)).
This effort recommends no new governing kind: rules for agents stay with the agent module's register, and the
knowledge base links to them instead of holding a second copy.
**Light kinds** are written, read and kept, but govern nothing:
| Kind | Lifecycle | Notes |
|---|---|---|
| note | written, then kept or archived | meeting notes, a brainstorm with one or more agents, a hand-over |
| post | draft → published, or withdrawn | a blog post, an explanation for readers outside the mesh |
| drawing | current, or replaced by a newer version | an architectural drawing: a file plus a text description |
A light record needs no review to exist, since nothing obeys it. It can link to the governing records it
discusses. A meeting's outcome that should hold becomes a proposed decision, which goes the governing way. The
operator's brief for the meshboard asks for a knowledge base with meetings where the operator brainstorms with
agents; a note is that meeting's record.
## 2. Numbering from one counter
The issue tracker already hands out numbers by compare-and-set on a counter key, and its design plans a
decision counter and a research counter as a later slice
([to-be 53](../../03-DESIGN/01-to-be/53-the-issue-tracker.md) §4). The 16 concurrent collisions all come from
reading the next number off a repository that many branches write at once; one counter removes them.
- **One sequence per governing kind**: decision, research, design. Numbers keep their meaning in conversation
("ADR 0276"), so they stay per kind.
- **A light record needs no number.** It gets a key, its date and its title; nobody says "note 1432".
- **A reserved number is spent.** A draft that is abandoned leaves its number as withdrawn, with who reserved
it and when. Gaps already exist (15 on `main`) and harm nothing; reusing a number would.
- **The counter starts above the highest number on `main` and on every open branch**, as the tracker's did.
Whether the counter lives in the tracker's `counters` bucket or in the knowledge base's own state is a design
choice. This effort recommends the knowledge base's own: a number is the knowledge base's to hand out, and the
tracker's design planned the extra counters only because nothing else would hold them.
## 3. Typed links
What frontmatter expresses today, and how reliably:
| Link | Today | Reliable |
|---|---|---|
| extends | `extends`, one target, two spellings | yes, after normalising the spelling |
| supersedes / superseded-by | both fields, mirrored | yes, 9 of 9 mirror |
| supersedes in part | one direction only; the target still reads `accepted` | no: 21 links have no reverse, and 6 more exist only in prose |
| rests on, amended | 2 and 1 records | too rare to trust |
| research became | `became` | yes |
| design names its decisions | `decisions` | yes |
| design names its code | `code`, free text | no |
| cites | prose links: 1,785 decision to decision, 716 to-be to decision, 469 decision to issue | readable, untyped |
The links an answer needs are **supersedes**, **changes in part**, **extends**, **became**, **decided by**
(design to decision), **cites**, and for light records **discusses**. The knowledge base stores each link in
both directions, so "what changed this record since" is one lookup. That is the question the merge window
example needs answered, and today it needs reading five records.
## 4. Approval
The overview asked whether accepting a decision should need the operator's warrant on a proving channel, as a
shared instruction section does.
- **Governing kinds already have an approval**: a pull request merged only with a human approval and both
required checks green. That is the warrant for a decision, and building a second one beside it would split
the evidence. A write verb for a governing kind therefore ends in a pull request (option A).
- **Light kinds need none to be written.** An agent may write a note or a draft post on its own; it is the
agent's record of what happened, and nothing obeys it.
- **Publishing needs the operator.** A post going out, or a light record exported into this public repository,
cannot be taken back once read. That act goes through an ask the operator answers on a proving channel
([ADR 0274](../../02-DECISIONS/0274-an-agent-proposes-a-shared-instruction-section-and-every-node-takes-it-only-on-the-operators-warrant-which-it-proves-itself.md)).
## 5. Public and private knowledge
This repository is public and must stay so. Knowledge about this installation has no shared home: it lives in
one agent's notes on one node (89 files), which no other session reads.
The knowledge base gives it one. **Every record carries a visibility, `public` or `private`.** Governing kinds
that come from this repository are public. A light record is private by default. A private record is served to
the mesh's own sessions through the mesh MCP server and never written into this repository; a record becomes public
only through the publishing act of section 4.
The check that nothing private leaks has to run where the export runs: the existing `words.py` rules for
identifiers, plus a list of the installation's own names held privately by the knowledge base and checked
against every record before it is exported. The words check cannot carry that list itself, since the list
would then be public.
Agents' notes to themselves are not this. A lesson or a personal rule belongs to the agent module's register
(ADR 0273), and carrying memory between nodes is issue 367's question. The knowledge base is for what the
operator and every agent should be able to look up, not for what an agent tells itself.
## 6. Checks as refusals at write
Of the 33 rules the hq checks enforce:
- **25 judge one record** and can become refusals of a write verb, given read access to the others: a link
resolves, a cited decision is accepted, supersession is symmetric, a design's layer matches its place, a
to-be design names a decision, a number is not taken twice, and the like. Two of them (a cited record that
becomes superseded later) can break without the citing record changing, so a write that supersedes must
check who cites the record it supersedes.
- **4 judge the whole record** (an accepted decision cited by nothing, an allowance nobody uses, two copies of
the retired words agreeing) and stay checks over the whole, run on every merge.
- **4 judge prose** (retired words, a daemon command line, the progressive-insight marker, a deferral naming its
issue) and stay checks on the text.
For governing kinds, the pull request keeps all 33 as they are. The write verb refuses early what 25 of them
would fail later, which saves a round trip but adds no new rule. For light kinds, the verb is the only gate:
it refuses a link to a record that does not exist, and an export with a private name in it.
## 7. Import
For governing kinds, **nothing is imported once**. The knowledge base reads this repository at every merge,
as the records module already does at the commit it names
([ADR 0153](../../02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md)), and rebuilds
its index from it: kinds, numbers, statuses, typed links in both directions, sections, and each decision's
rules. That is repeatable by construction, and the index can always be thrown away and rebuilt.
Two things a reading cannot recover alone:
- **Loose links.** The 6 supersessions said only in prose, the 7 body markers without a field, the 47 bare
`extends` targets and the 21 one-way partial supersessions are repaired in this repository by one pull
request, through progressive insights where a record's meaning is touched. The knowledge base does not guess
them.
- **What a decision decided, short.** 226 of 263 decision sections are prose. An answer needs each record's
rules as short statements. This effort recommends a `summary` per record: the rules it decides, one line
each, in the record's own frontmatter. For the 274 existing records, a first draft can be written by the
agent's judgement ([ADR 0278](../../02-DECISIONS/0278-the-issue-tracker-checks-every-new-issue-for-a-duplicate-through-a-judgement-the-agent-makes-without-tools.md))
and is reviewed in pull requests, a topic at a time. From then on, `records.py` refuses a decision without
one. A summary nobody reviewed is never served as the record's word.
For light kinds the knowledge base is the truth, so there is nothing to import, except the meeting notes and
other light material that exist today outside the mesh, if the operator wants them in.
## 8. What git gives, and what each option keeps
| What git and the forge give today | A: git stays the store | B: a store is the truth, hq its export |
|---|---|---|
| review on a pull request, line comments | kept | rebuilt or lost |
| history of every change with its author | kept | rebuilt per record |
| diff and revert | kept | rebuilt |
| the required checks on every change | kept | rebuilt as refusals, and the 4 whole-record rules need a new home |
| one number per record | the counter of section 2 | the counter of section 2 |
| an answer in one call | the index of section 7 | the store |
| a home for private and light records | no: the repository is public | yes |
Option A keeps everything review gives, for the kinds that need review. It cannot hold private or light
records. Option B holds those, but would rebuild review, history and the checks, for 189 records out of 271
that are edited after they are written.
**The recommendation is both, divided by kind**, the way the issue tracker already divided issues
([ADR 0275](../../02-DECISIONS/0275-the-mesh-numbers-and-tracks-its-issues-in-a-module-of-its-own-and-hq-keeps-only-the-narrative-of-a-design-or-governance-issue.md)):
- **Governing kinds**: this repository stays the truth for their text and frontmatter. The knowledge base
hands out their numbers, indexes them at every merge, and serves them as answers. Writing one stays a pull
request, which a write verb can open.
- **Light kinds**: the knowledge base is the truth. It stores them, private by default, and exports one to
this repository only on the operator's word.
## 9. The first slice
**A Go module serving one seat held once for the mesh, on the control-node, beside the issue tracker.** The
working name of the seat is `knowledge-base`; the glossary has no word for it yet (see *Words* below).
**Storage.** Light records and the index of governing records live in a database in the store, provided to
the module. The bus's key-value buckets are the wrong place here: the limits of
[ADR 0201](../../02-DECISIONS/0201-a-module-keeps-its-current-state-in-key-value-buckets-it-declares-and-reaches-through-the-runtime.md)
§6 (256 KiB a value, 64 MiB a bucket) are below the 6.9 MB the index holds, and an answer needs full-text
search ranked by relevance, which the store's server does and a bucket does not. The numbers' counter can
stay a bucket key with compare-and-set, as the tracker's is. A drawing's file goes into an object-store
bucket ([ADR 0288](../../02-DECISIONS/0288-the-object-store-stays-on-the-maintained-fork-and-garage-is-chosen-only-after-the-consumers-s3-features-are-counted.md));
its record holds the description an agent reads, and the link to the file.
**Verbs, shaped as answers.** Each answer is bounded in size and names the commit of this repository it was
read at.
| Verb | Answers |
|---|---|
| `ask` | the records that bear on a question, ranked: for each, its number, kind, status, title and summary, and whether it still holds or what changed it |
| `get` | one record: its summary, its rules, its links both ways, what changed it since; the full text only when asked for |
| `holds` | for a topic or a record, the rules in force now, after every supersession, partial change and progressive insight, each with the record it comes from |
| `links` | a record's typed links, both directions |
| `reserve` | the next number of a kind, spent whether or not the record lands |
| `write` | a light record (note, post, drawing): written, private unless said otherwise |
| `publish` | ask the operator to make a light record public, and export it on a yes |
The records module stays as it is: it is the literal reader of the repository, and `ask` and `get` do not
replace a search for a symptom's literal text.
**How a session reaches it.** The knowledge base's tools reach every session through the mesh MCP server, like every
module's. One shared instruction section, proposed and approved by ADR 0274's route, tells every session to ask
the knowledge base about decisions and designs before reading files. A session then needs this repository's
folder only to write a governing record.
**Proved by the acceptance sentence above**: the merge window question, asked from a session outside this
repository, answered in one call under 4 KiB, naming ADR 0276, the partial change ADR 0282 made to it, and the
commit.
## 10. What needs the operator
1. **Divided by kind (section 8)**: this repository stays the truth for decisions, designs, research and
playbooks, and the knowledge base is the truth only for light records. The alternative is option B for
everything.
2. **A summary per decision record (section 7)**, drafted by the agent's judgement for the existing 274 and
reviewed in pull requests, then required of every new record.
3. **Private by default for light records (section 5)**, with publishing on the operator's word.
4. **The store's database for the module (section 9)**, instead of the bus's buckets alone.
## Words
The glossary has **decision record**, **design**, **playbook** and **the record** (the records module). It has
no word for the whole this effort describes, for its seat, or for the light kinds. This effort proposes, for a
decision to settle through the glossary's own rules: **knowledge base** for the whole and its seat,
**governing record** for a kind that is reviewed before it holds, and **note**, **post** and **drawing** for
the light kinds. *Policy* stays the word for a module's upgrade policy, and *guideline* is not proposed, since
section 1 finds no record of that kind.