Merge pull request 'ADR 0290 rewritten: a decision record lives whole in the knowledge base' (#307) from decisions/0290-records-whole-in-the-knowledge-base into main
This commit was merged in pull request #307.
This commit is contained in:
@@ -27,7 +27,7 @@ indistinguishable from one that cannot.
|
||||
| `live-citation` | a governing document citing a **superseded** record names its replacement in the same paragraph | `01-to-be/README.md` citing ADR 0022 as live guidance |
|
||||
| `supersession` | if A says it was superseded by B, B says it supersedes A | ADR 0012 never declared that it superseded 0011 |
|
||||
| `partial-supersession` | a record's `supersedes-in-part:` names records that exist, each carrying a dated *Superseded in part* note naming it under its heading; and every such note is named back by its superseder's field | 11 of 21 partial supersessions had no note on the record they change, and 6 more were said only in prose ([research 045](../../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/00-overview.md)) |
|
||||
| `clauses` | an accepted record dated from 2026-10-11 writes its `## Decision` section as numbered clauses with a bold lead ([ADR 0290](../../02-DECISIONS/0290-the-knowledge-base-holds-each-records-structure-and-clauses-and-hq-keeps-its-reasoning.md) rule 3) | 226 of 263 decision records wrote their decision as prose, so the knowledge base must draft their clauses |
|
||||
| `clauses` | an accepted record dated from 2026-10-11 writes its `## Decision` section as numbered clauses with a bold lead ([ADR 0290](../../02-DECISIONS/0290-a-decision-record-lives-whole-in-the-knowledge-base-made-of-clauses.md) rule 3) | 226 of 263 decision records wrote their decision as prose, so the knowledge base must draft their clauses |
|
||||
| `numbering` | the number in the filename is the number in the heading | — |
|
||||
| `topics` | every record names a topic of the reading order in `02-DECISIONS/README.md` | — |
|
||||
| *(index.py)* | the reading order is written, every record's topic is one of it, and the README stores no list of records ([ADR 0248](../../02-DECISIONS/0248-the-decision-index-is-generated-when-it-is-read-and-never-stored.md)) | a stored list made every two open decisions conflict ([issue 297](../../04-ISSUES/297-two-open-decisions-always-conflict/00-report.md)); it failed on the README of `main` before the list was removed |
|
||||
@@ -71,7 +71,10 @@ off — "until renamed", "left for later", "not decided here", "postponed", "fut
|
||||
change" — names the issue that tracks it, as tracking it ("tracked by issue N", or "issue N tracks"), in that
|
||||
paragraph or list item, or in a dated progressive insight that speaks about it: one in the same section, or one
|
||||
that quotes it. An issue cited for another reason tracks nothing, and one insight does not excuse every deferral
|
||||
in a record. A rejected option is not work put off and is not held, judged by its `##` section, so an option under a
|
||||
in a record. The tracking issue counts when it has a folder in `04-ISSUES/`, or when its number is above every
|
||||
folder's: since ADR 0275 an issue from 365 on lives only in the issue tracker, which a checkout cannot read, and the
|
||||
tracker hands out numbers in order (issue 436). A made-up number above the folders therefore passes; the reviewer
|
||||
checks that the issue exists, with `issue-tracker.get`. A rejected option is not work put off and is not held, judged by its `##` section, so an option under a
|
||||
`###` subheading of "Considered Options" is skipped too
|
||||
([issue 354](../../04-ISSUES/354-a-decided-rename-was-never-scheduled-and-the-operator-believed-it-live/00-report.md):
|
||||
ADR 0244 deferred the code renames with no issue, and two days later the operator believed them done). Held to
|
||||
|
||||
@@ -117,7 +117,14 @@ def covers(insight_section, insight_text, section, text):
|
||||
|
||||
|
||||
def issue_refs(text, issues):
|
||||
return {n for a, b in ISSUE_REF.findall(text) for n in (a, b) if n and n in issues}
|
||||
"""The issues a text names as tracking it: one with a folder here, or one numbered above every folder.
|
||||
|
||||
Since ADR 0275 an issue from 365 on lives only in the issue tracker, and ADR 0291 removes the folders; a
|
||||
checkout alone cannot see those, so a number above the highest folder counts as one the tracker holds
|
||||
(issue 436). The tracker hands out numbers in order, so such a number was issued after the last folder.
|
||||
"""
|
||||
top = max((int(k) for k in issues if k.isdigit()), default=0)
|
||||
return {n for a, b in ISSUE_REF.findall(text) for n in (a, b) if n and (n in issues or int(n) > top)}
|
||||
|
||||
|
||||
def rel(path):
|
||||
|
||||
+7
-6
@@ -577,12 +577,13 @@ Not a domain of the mesh but of the way it is built, listed because its words me
|
||||
*record* has other meanings (see [Homonyms](#homonyms)).
|
||||
- **clause** — one numbered statement a decision record makes, with its own status (`proposed`, `in force`,
|
||||
`changed`, `superseded`): a later record may change one clause and leave the rest
|
||||
([ADR 0290](../02-DECISIONS/0290-the-knowledge-base-holds-each-records-structure-and-clauses-and-hq-keeps-its-reasoning.md)). Not a *rule*, which is a line of
|
||||
([ADR 0290](../02-DECISIONS/0290-a-decision-record-lives-whole-in-the-knowledge-base-made-of-clauses.md)). Not a *rule*, which is a line of
|
||||
`00-META/how-we-build.md`.
|
||||
- **knowledge base** — the role that holds the structure of the decision records and research efforts (number,
|
||||
status, topic, typed links) and each decision's clauses, 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)). This
|
||||
repository keeps the reasoning. Not **the record**, the literal reader of this repository.
|
||||
- **knowledge base** — the role that holds the decision records and research efforts whole (number, status, topic,
|
||||
typed links, clauses and reasoning, with every version), takes them as proposals, has them reviewed and accepted,
|
||||
and answers what holds: the seat `knowledge-base`, held by the module `mesh-knowledge`
|
||||
([55 — The knowledge base](../03-DESIGN/01-to-be/55-the-knowledge-base.md)). Not **the record**, the literal reader
|
||||
of this repository.
|
||||
- **design** — a document in `03-DESIGN/`: **as-is** (what runs) or **to-be** (what is being built).
|
||||
- **issue** — a question about the mesh that someone must answer, numbered and tracked by the issue tracker, which
|
||||
holds it whole: its report, diagnosis and resolution included ([ADR 0291](../02-DECISIONS/0291-an-issue-lives-whole-in-the-issue-tracker.md));
|
||||
@@ -644,7 +645,7 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical.
|
||||
| record | a numbered decision | **decision record** | The record |
|
||||
| | the literal reader of this repository, searched first for a symptom | **the record** (the `records` module) | Operator and conversation |
|
||||
| | the upgrade policy that sends nowhere | `record` | Module |
|
||||
| knowledge base | the module holding records' structure and clauses | **knowledge base** | The record |
|
||||
| knowledge base | the module holding the decision records and research efforts whole | **knowledge base** | The record |
|
||||
| | the predecessor's operational memory, in older playbooks (issue 430) | none: it no longer exists | — |
|
||||
| check | a pull request's two statuses | **merge check**, **merge gate**, **repository check** | Change and delivery |
|
||||
| | a delivery group's verdict | **composed check** | Change and delivery |
|
||||
|
||||
@@ -14,7 +14,7 @@ touches:
|
||||
- 00-META/glossary.md
|
||||
- the records module's tools
|
||||
became:
|
||||
- 02-DECISIONS/0290-the-knowledge-base-holds-each-records-structure-and-clauses-and-hq-keeps-its-reasoning.md
|
||||
- 02-DECISIONS/0290-a-decision-record-lives-whole-in-the-knowledge-base-made-of-clauses.md
|
||||
- 02-DECISIONS/0291-an-issue-lives-whole-in-the-issue-tracker.md
|
||||
- 03-DESIGN/01-to-be/55-the-knowledge-base.md
|
||||
---
|
||||
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
---
|
||||
topic: how we work
|
||||
status: accepted
|
||||
date: 2026-10-11
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md
|
||||
---
|
||||
|
||||
# 290. A decision record lives whole in the knowledge base, made of clauses
|
||||
|
||||
> **Rewritten — 2026-10-11, on the operator's word.** This record was merged an hour earlier as *The knowledge base
|
||||
> holds each record's structure and clauses, and hq keeps its reasoning*: the store held the structure, and this
|
||||
> repository the reasoning, reviewed in pull requests. The operator asked why one record should live in two places,
|
||||
> and asked for this record to be updated in place rather than superseded. Nothing had been built on the earlier
|
||||
> version. It is in this repository's history at commit `08b1077b`.
|
||||
|
||||
## Context
|
||||
|
||||
[Research 045](../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/00-overview.md) measured, on 2026-10-11, how an
|
||||
agent learns what the mesh decided ([findings](../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/01-findings.md)).
|
||||
The operator gave the purpose the same day: the decisions and research 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.
|
||||
|
||||
**An answer costs too much.** "What holds about the merge window" took 26 search hits in 11 documents and about 85 KB
|
||||
of reading, some 21,000 tokens. The decision index, generated by the records module
|
||||
([ADR 0248](0248-the-decision-index-is-generated-when-it-is-read-and-never-stored.md)), is 77 KB, more than one
|
||||
tool answer may be. The records module matches a phrase literally and knows nothing of which record still holds
|
||||
([ADR 0153](0153-the-record-is-read-by-a-module-and-the-console-lists-it.md)).
|
||||
|
||||
**What a decision decided is not data.** 226 of 263 decision records write their `Decision` section as prose; 37
|
||||
write it as numbered statements with a bold lead (198 in all). A later record that changes one statement of an older
|
||||
one could say so only in prose or by naming the whole record: 21 `supersedes-in-part` links had no reverse, and 6
|
||||
more records said it in prose alone, until hq pull request 305 declared all of them in both records and added a check.
|
||||
|
||||
**The checks run after the fact.** Of the 33 rules the hq checks enforce, 25 judge one record and 4 judge its prose;
|
||||
all 29 could refuse a bad record when it is written. Only 4 need the whole record set.
|
||||
|
||||
**Numbers collide.** 16 decision numbers were taken twice by sessions working at once between 2026-09-25 and
|
||||
2026-10-10. [ADR 0275](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)
|
||||
rule 8 already decided that the issue tracker hands out decision and research numbers; issue 424 tracks building it.
|
||||
|
||||
### Against GENESIS
|
||||
|
||||
- **The mesh owns the truth** ([mission](../00-META/mission.md)): a record lives in one place, written through one
|
||||
module, not in a file every branch may edit.
|
||||
- **The mesh brokers everything the work needs, knowledge included**: an agent asks the mesh what holds, by
|
||||
capability, instead of knowing which folder to read.
|
||||
- **The mesh remembers** ([effect](../00-META/effect.md)): what was decided, and why, is available to whoever needs it
|
||||
next, on any node, in any folder, with every earlier version kept.
|
||||
- **Failure must be loud**: a write that would leave the records inconsistent is refused when it is made.
|
||||
|
||||
## Considered Options
|
||||
|
||||
### Where a record lives
|
||||
|
||||
1. **hq stays the truth; a module indexes it** (the research's option A). Rejected: a link about one statement of a
|
||||
decision stays prose, and every inconsistency is found after it is written.
|
||||
2. **Divided: the knowledge base holds a record's structure and clauses; hq keeps its reasoning.** Rejected by the
|
||||
operator on 2026-10-11: one record in two places, an agent sent to a file for the *why*, and the structure written
|
||||
twice until the frontmatter left hq.
|
||||
3. **The knowledge base holds a record whole: structure, clauses and reasoning, with every version.** Adopted. It is
|
||||
the division the operator made for issues ([ADR 0291](0291-an-issue-lives-whole-in-the-issue-tracker.md)), applied
|
||||
to decisions and research.
|
||||
|
||||
### The unit
|
||||
|
||||
1. **The record.** Rejected: a later record changes one statement of an older one far more often than the whole.
|
||||
2. **The clause: one numbered statement a decision makes, with its own status.** Adopted. The research called it a
|
||||
*rule*; *rule* already names a line of [how-we-build](../00-META/how-we-build.md), and one word names one thing
|
||||
([ADR 0244](0244-the-mesh-is-described-in-domains-and-one-word-names-one-thing.md)).
|
||||
|
||||
### How a record is reviewed, once it is not a pull request
|
||||
|
||||
1. **The operator approves every record.** Rejected: records are reviewed today by an independent agent, and the
|
||||
operator is asked only for real decisions; making every record wait for one person slows what works.
|
||||
2. **An independent agent reviews it, the write-time checks pass, and a record that needs the operator waits for the
|
||||
operator's Approve on a channel that proves who answered.** Adopted. It is how a pull request here is merged
|
||||
today, and the operator's Approve already reaches the mesh that way
|
||||
([ADR 0274](0274-an-agent-proposes-a-shared-instruction-section-and-every-node-takes-it-only-on-the-operators-warrant-which-it-proves-itself.md)).
|
||||
|
||||
### Who confirms the clauses drafted for the 226 prose decisions (the research's open question 1)
|
||||
|
||||
1. **The operator, topic by topic.** Rejected: 226 records is days of reading for one person, for statements already
|
||||
decided and reviewed once.
|
||||
2. **Nobody: drafted clauses are served as they are.** Rejected: a summary nobody checked would speak as the record's
|
||||
word, which is the work-that-reports-success-and-did-nothing fault.
|
||||
3. **A second judgement, independent of the one that drafted them, confirms each record's clauses against its text;
|
||||
the operator is told per topic and may send any record back.** Adopted, and confirmed by the operator on
|
||||
2026-10-11.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **The knowledge base is a Go module, `mesh-knowledge`, with one instance on the control-node.** It declares and
|
||||
claims one seat held once for the mesh, `knowledge-base`
|
||||
([ADR 0126](0126-a-module-declares-its-own-seats.md)). Its first kinds are the **decision record** and the
|
||||
**research effort**.
|
||||
2. **The knowledge base is the truth for a record whole**: its number, kind, title, topic, status, date, deciders, its
|
||||
typed links (held in both directions), its clauses, and its reasoning (context, options weighed, consequences,
|
||||
how it is checked; a research effort's documents). **Every version is kept**, with who wrote it and when, and any
|
||||
two versions can be compared. Once the import has run and been checked, no record is written in this repository.
|
||||
3. **A decision record is made of clauses.** A clause is one numbered statement of what was decided, with a status:
|
||||
`proposed`, `in force`, `changed` by a clause of a later record, or `superseded`. A link that is about a clause
|
||||
names the clause, not only the record. A record is written as clauses from the start. Until the knowledge base
|
||||
takes writes, a record written in this repository from 2026-10-11 on writes its `Decision` section as numbered
|
||||
clauses with a bold lead, and `records.py` refuses an accepted one that does not.
|
||||
4. **A record is proposed, reviewed and accepted in the knowledge base.** `propose` writes it with a number from
|
||||
`reserve`, and refuses it outright when one of the 29 rules that judge one record or its prose fails. An
|
||||
independent agent reviews it (`review`), and its approval moves the record and its clauses to `accepted` and
|
||||
`in force`, and every clause it changes or supersedes accordingly. A record that says it needs the operator waits
|
||||
for the operator's Approve, asked on a channel that proves who answered, and the warrant is kept with it
|
||||
([ADR 0259](0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md)).
|
||||
An accepted record changes only by a new record, or by a dated correction of a fact, written as a new version and marked as one;
|
||||
the 4 rules that judge the whole record set run over it after every acceptance and raise a condition when one
|
||||
fails.
|
||||
5. **Numbers come from the issue tracker's counters**, as ADR 0275 rule 8 decided: `reserve` asks the tracker for the
|
||||
next decision or research number, and a reserved number is spent whether or not its record is accepted. Until the
|
||||
tracker hands them out, tracked by issue 424, a session takes the highest number on `main` and on every open
|
||||
branch, plus one, as the shared instruction section *writing-decision-records* says.
|
||||
6. **An answer is the shape agents need, bounded.** The verbs are `ask` (records and clauses bearing on a question,
|
||||
ranked, each saying whether it holds or what changed it), `get` (one record: clauses, links both ways, what changed
|
||||
it since; its reasoning only when asked), `holds` (the clauses in force for a topic or a record), `links`,
|
||||
`history` (a record's versions and the difference between two), `reserve`, `propose`, `review`, `import` and
|
||||
`return` (send drafted clauses back to be drafted again). `ask`, `get` and `holds` stay under a size bound they
|
||||
state; the default is 4 KiB.
|
||||
7. **State is in a database in the store**, provided to the module, not in buckets: `ask` needs ranked full-text
|
||||
search, and a record's versions are a record set to search, not current state to watch
|
||||
([ADR 0201](0201-a-module-keeps-its-current-state-in-key-value-buckets-it-declares-and-reaches-through-the-runtime.md)
|
||||
is not narrowed). **Every change is an event the module declares**
|
||||
([ADR 0041](0041-events-are-a-relationship.md)), carrying what changed and who changed it.
|
||||
8. **The import reads this repository at a commit and can run again.** It writes every decision record and research
|
||||
effort whole, at its own number, with the commit as its first version's source; it creates what is absent, never
|
||||
overwrites, never advances a counter, and a second run changes nothing and says so. A record whose clauses are
|
||||
written as numbered statements gets them as `written`. A prose record gets them `drafted` by the agent's judgement
|
||||
([ADR 0278](0278-the-issue-tracker-checks-every-new-issue-for-a-duplicate-through-a-judgement-the-agent-makes-without-tools.md)),
|
||||
then `confirmed` by a second judgement that sees only the record and the drafts; the operator is told per topic and
|
||||
may send a record back. An answer marks a drafted or confirmed clause as such, and never serves a drafted clause as
|
||||
in force.
|
||||
9. **This repository stops holding decision records and research efforts** once the import is checked against it,
|
||||
record by record: one pull request removes them, rewrites the mentions of their paths to "ADR NNNN" and "research
|
||||
NNN", and changes playbooks 01 and 02, tracked by issue 426. Whether this repository then carries a generated,
|
||||
read-only public copy is not decided here, tracked by issue 435. The records module stays the literal reader of
|
||||
what this repository still holds.
|
||||
10. **It is built in slices, each tracked by an issue.** The first is the module for decisions and research: import,
|
||||
clauses, answers, and proposing and reviewing a record, tracked by issue 425. The records leave this repository
|
||||
under issue 426. Designs, playbooks and glossary entries follow the same way, tracked by issue 428. Meeting notes,
|
||||
drawings and blog posts come last and are not decided here, tracked by issue 429. The design is
|
||||
[to-be 55](../03-DESIGN/01-to-be/55-the-knowledge-base.md).
|
||||
|
||||
## Consequences
|
||||
|
||||
- An agent on any node asks what holds and why, and gets the clauses in force, the records they come from and what
|
||||
changed them, in one call, instead of reading several records whole. No session needs this repository's folder to
|
||||
read or write a decision.
|
||||
- A later record that changes one statement of an older one says which, and the older clause's status changes when
|
||||
the later record is accepted.
|
||||
- Review moves from a pull request to the knowledge base's `review`, and the forge's line comments and diff are
|
||||
replaced by the record's versions and `history`. A record is checked when it is written, not when it is merged.
|
||||
- Until the first slice takes writes, records are still written here as pull requests, with numbered clauses, and the
|
||||
import takes them in with the rest.
|
||||
- What got harder: one more module the mesh's own process depends on. Reading or writing a decision needs the mesh to
|
||||
be reachable; a node that cannot reach the control-node says so rather than guessing. The public repository stops
|
||||
showing decisions as they are made, until issue 435 decides on a public copy.
|
||||
|
||||
## How it is checked
|
||||
|
||||
- **Clauses in a record written here** (rule 3): `records.py`, check `clauses`, on every pull request of this
|
||||
repository, until the records leave it.
|
||||
- **What the module does** (rules 2, 4, 6, 7, 8): the module's tests and its live acceptance, listed in
|
||||
[to-be 55](../03-DESIGN/01-to-be/55-the-knowledge-base.md) §9, built under issue 425.
|
||||
- **Nothing lost when the records leave** (rule 9): every record compared with its file at the import's commit before
|
||||
the files are removed, the result written on issue 426.
|
||||
- **Numbers** (rule 5): the issue tracker's tests of its counters, built under issue 424; until then the
|
||||
`numbering` and duplicate checks of `records.py` and `cycle.py` find a collision on `main`.
|
||||
|
||||
## References
|
||||
|
||||
- [Research 045](../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/00-overview.md) and its
|
||||
[findings](../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/01-findings.md).
|
||||
- [To-be 55 — The knowledge base](../03-DESIGN/01-to-be/55-the-knowledge-base.md).
|
||||
- hq pull request 305: every partial supersession declared in both records, and the `partial-supersession` check.
|
||||
- Issues 424, 425, 426, 428, 429 and 435.
|
||||
-160
@@ -1,160 +0,0 @@
|
||||
---
|
||||
topic: how we work
|
||||
status: accepted
|
||||
date: 2026-10-11
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md
|
||||
---
|
||||
|
||||
# 290. The knowledge base holds each record's structure and clauses, and hq keeps its reasoning
|
||||
|
||||
## Context
|
||||
|
||||
[Research 045](../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/00-overview.md) measured, on 2026-10-11, how an
|
||||
agent learns what the mesh decided ([findings](../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/01-findings.md)).
|
||||
The operator gave the purpose the same day: the decisions and research 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.
|
||||
|
||||
**An answer costs too much.** "What holds about the merge window" took 26 search hits in 11 documents and about 85 KB
|
||||
of reading, some 21,000 tokens. The decision index, generated by the records module
|
||||
([ADR 0248](0248-the-decision-index-is-generated-when-it-is-read-and-never-stored.md)), is 77 KB, more than one
|
||||
tool answer may be. The records module matches a phrase literally and knows nothing of which record still holds
|
||||
([ADR 0153](0153-the-record-is-read-by-a-module-and-the-console-lists-it.md)).
|
||||
|
||||
**What a decision decided is not data.** 226 of 263 decision records write their `Decision` section as prose; 37
|
||||
write it as numbered statements with a bold lead (198 in all). A later record that changes one statement of an older
|
||||
one could say so only in prose or by naming the whole record: 21 `supersedes-in-part` links had no reverse, and 6
|
||||
more records said it in prose alone, until hq pull request 305 declared all of them in both records and added a check.
|
||||
The older record's status still reads `accepted`, and a reader must read both to know what holds.
|
||||
|
||||
**The records change after they are written, and that is reviewed.** 189 of 271 decision records were edited after
|
||||
the commit that created them, every edit through a pull request with a human approval and the repository's checks.
|
||||
|
||||
**Numbers collide.** 16 decision numbers were taken twice by sessions working at once between 2026-09-25 and
|
||||
2026-10-10. [ADR 0275](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)
|
||||
rule 8 already decided that the issue tracker hands out decision and research numbers; it is not built, and issue
|
||||
424 tracks it.
|
||||
|
||||
### Against GENESIS
|
||||
|
||||
- **The mesh brokers everything the work needs, knowledge included** ([mission](../00-META/mission.md)): an agent asks
|
||||
the mesh what holds, by capability, instead of knowing which folder to read.
|
||||
- **The mesh remembers** ([effect](../00-META/effect.md)): what was decided, and why, is available to whoever needs it
|
||||
next, on any node, in any folder.
|
||||
- **Failure must be loud**: a write that would leave the records inconsistent is refused when it is made, not found by
|
||||
a check afterwards.
|
||||
|
||||
## Considered Options
|
||||
|
||||
### Where the truth lives
|
||||
|
||||
1. **hq stays the truth; a module indexes it and opens pull requests for writes** (the research's option A).
|
||||
Rejected: it keeps review, but a link about one statement of a decision stays prose, and every inconsistency is
|
||||
found after it is written, which is the cause of what the research measured.
|
||||
2. **A store is the truth for everything, and hq is its export** (option B). Rejected: it would rebuild review, line
|
||||
comments, history and diff for prose, which git and the forge already give, for records that are edited after they
|
||||
are written as often as these are.
|
||||
3. **Divided by layer: the store holds each record's structure and its clauses; hq keeps its reasoning.** Adopted.
|
||||
It is what the research recommended when the operator asked on 2026-10-11 what a clean start would pick, and the operator chose it, and the division ADR 0275
|
||||
already made for issues, carried down to the statement a decision makes.
|
||||
|
||||
### The unit
|
||||
|
||||
1. **The record.** Rejected: a later record changes one statement of an older one far more often than the whole.
|
||||
2. **The clause: one numbered statement a decision makes, with its own status.** Adopted. The research called it a
|
||||
*rule*; *rule* already names a line of [how-we-build](../00-META/how-we-build.md), and one word names one thing
|
||||
([ADR 0244](0244-the-mesh-is-described-in-domains-and-one-word-names-one-thing.md)).
|
||||
|
||||
### Who confirms the clauses drafted for the 226 prose decisions (the research's open question 1)
|
||||
|
||||
1. **The operator, topic by topic.** Rejected: 226 records is days of reading for one person, for statements already
|
||||
decided and reviewed once.
|
||||
2. **Nobody: drafted clauses are served as they are.** Rejected: a summary nobody checked would speak as the record's
|
||||
word, which is the work-that-reports-success-and-did-nothing fault.
|
||||
3. **A second judgement, independent of the one that drafted them, confirms each record's clauses against its text;
|
||||
the operator is told per topic and may send any record back.** Adopted, and confirmed by the operator on 2026-10-11. A clause keeps its source, so an answer says
|
||||
whether a clause was written by the record's author or drafted and confirmed.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **The knowledge base is a Go module, `mesh-knowledge`, with one instance on the control-node.** It declares and
|
||||
claims one seat held once for the mesh, `knowledge-base`
|
||||
([ADR 0126](0126-a-module-declares-its-own-seats.md)). Its first kinds are the **decision record** and the
|
||||
**research effort**.
|
||||
2. **The knowledge base is the truth for each record's structure**: its number, kind, title, topic, status, date,
|
||||
deciders, and its typed links, each held in both directions. **hq is the truth for each record's reasoning**:
|
||||
context, options weighed, consequences, research documents, as markdown reviewed in pull requests. A record's file
|
||||
keeps its number in its name and heading.
|
||||
3. **A decision record is made of clauses.** A clause is one numbered statement of the `Decision` section, with a
|
||||
status: `in force`, `changed` by a clause of a later record, or `superseded`. A link that is about a clause names
|
||||
the clause, not only the record. A record written from 2026-10-11 on writes its `Decision` section as numbered
|
||||
clauses with a bold lead, and the knowledge base reads them from the merged text, so a clause's wording is always
|
||||
the reviewed one. `records.py` refuses an accepted record dated from 2026-10-11 whose `Decision` section has no
|
||||
numbered clause.
|
||||
4. **A record is accepted when its pull request merges.** The knowledge base hears the forge's merge on the bus,
|
||||
reads the merged record through the records module, and moves the record and its clauses to `accepted` and
|
||||
`in force`, and each clause it changes or supersedes accordingly. The merge, with its human approval and both
|
||||
required checks, is the warrant; there is no second approval beside it. A structural write that would change what
|
||||
an accepted record says, without a pull request, is refused.
|
||||
5. **Numbers come from the issue tracker's counters**, as ADR 0275 rule 8 decided: the knowledge base's `reserve`
|
||||
asks the tracker for the next decision or research number, and a reserved number is spent whether or not its
|
||||
record lands. Until the tracker hands them out, tracked by issue 424, a session takes the highest number on `main`
|
||||
and on every open branch, plus one, as the shared instruction section *writing-decision-records* says.
|
||||
6. **An answer is the shape agents need, bounded.** The verbs are `ask` (records and clauses bearing on a question,
|
||||
ranked, each saying whether it holds or what changed it), `get` (one record: clauses, links both ways, what changed
|
||||
it since, its reasoning only when asked), `holds` (the clauses in force for a topic or a record), `links`,
|
||||
`reserve`, `propose`, `import` and `return` (send a record's drafted clauses back to be drafted again). Every answer names the commit of this repository it was read at and stays under
|
||||
a size bound that `ask`, `get` and `holds` state; the default is 4 KiB.
|
||||
7. **State is in a database in the store**, provided to the module, not in buckets: `ask` needs ranked full-text
|
||||
search, which the store's server does and a bucket does not. This narrows nothing in
|
||||
[ADR 0201](0201-a-module-keeps-its-current-state-in-key-value-buckets-it-declares-and-reaches-through-the-runtime.md):
|
||||
what the module keeps is a record set to search, not current state to watch. **Every change is an event the
|
||||
module declares** ([ADR 0041](0041-events-are-a-relationship.md)), carrying what changed and who changed it.
|
||||
8. **The import reads this repository at a commit and can run again.** It creates what is absent, never overwrites,
|
||||
never advances a counter, and a second run changes nothing and says so. A record whose clauses are written as
|
||||
numbered statements gets them as `written`. A prose record gets them `drafted` by the agent's judgement
|
||||
([ADR 0278](0278-the-issue-tracker-checks-every-new-issue-for-a-duplicate-through-a-judgement-the-agent-makes-without-tools.md)),
|
||||
then `confirmed` by a second judgement that sees only the record and the drafts. The operator is told per topic and
|
||||
may send a record back. An answer marks a clause that is drafted or confirmed as such, and never serves a drafted
|
||||
clause as in force.
|
||||
9. **The records module stays the literal reader of this repository.** `records_search` for a symptom's literal text
|
||||
is unchanged; the knowledge base answers what holds. Both reach every session through the mesh MCP server, and a
|
||||
session needs this repository's folder only to write a record's reasoning.
|
||||
10. **It is built in slices, each tracked by an issue.** The first is the module for decisions and research, its
|
||||
import and its answers, tracked by issue 425. The structure's fields then leave hq's frontmatter, kind by kind,
|
||||
once the import is proven to hold the same values, tracked by issue 426. Designs, playbooks and glossary entries
|
||||
follow the same way, tracked by issue 428. Meeting notes, drawings and blog posts come last and are not decided
|
||||
here, tracked by issue 429. The design is
|
||||
[to-be 55](../03-DESIGN/01-to-be/55-the-knowledge-base.md).
|
||||
|
||||
## Consequences
|
||||
|
||||
- An agent on any node asks what holds and gets the clauses in force, the records they come from and what changed
|
||||
them, in one call, instead of reading several records whole.
|
||||
- A later record that changes one statement of an older one says which, and the older clause's status changes when
|
||||
the later record merges; the dated note under the older record's heading stays, for a reader who follows a citation.
|
||||
- Writing a decision changes in one way: its `Decision` section is numbered clauses, from this record on. This record
|
||||
and [ADR 0291](0291-an-issue-lives-whole-in-the-issue-tracker.md) are written that way.
|
||||
- Until issue 426 lands, a record's status and links are written in two places: hq's frontmatter, which the hq checks
|
||||
read, and the knowledge base, which reads them from hq at every merge. hq stays the source until then, so the two
|
||||
cannot disagree for longer than one merge.
|
||||
- What got harder: one more module the mesh's own process depends on, and a reader of a decision needs the mesh to be
|
||||
reachable to learn its clauses' status. The file in hq stays readable alone.
|
||||
|
||||
## How it is checked
|
||||
|
||||
- **Clauses in a new record** (rule 3): `records.py`, check `clauses`, on every pull request of this repository.
|
||||
- **What the module does** (rules 2, 4, 6, 7, 8): the module's tests and its live acceptance, listed in
|
||||
[to-be 55](../03-DESIGN/01-to-be/55-the-knowledge-base.md) §9, built under issue 425.
|
||||
- **Numbers** (rule 5): the issue tracker's tests of its counters, built under issue 424; until then the
|
||||
`numbering` and duplicate checks of `records.py` and `cycle.py` find a collision on `main`.
|
||||
|
||||
## References
|
||||
|
||||
- [Research 045](../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/00-overview.md) and its
|
||||
[findings](../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/01-findings.md).
|
||||
- [To-be 55 — The knowledge base](../03-DESIGN/01-to-be/55-the-knowledge-base.md).
|
||||
- hq pull request 305: every partial supersession declared in both records, and the `partial-supersession` check.
|
||||
- Issues 424, 425, 426, 428 and 429.
|
||||
@@ -33,10 +33,11 @@ tracker alone.
|
||||
story from a file, by a path the tracker gives. Since ADR 0275 an issue with a folder and one without are read
|
||||
differently, and which one has a folder is an author's judgement at the moment it was opened.
|
||||
|
||||
**What the public record keeps.** A design or governance question that matters ends in a decision record, and decision
|
||||
records stay here, public, with their reasoning
|
||||
([ADR 0290](0290-the-knowledge-base-holds-each-records-structure-and-clauses-and-hq-keeps-its-reasoning.md)). What
|
||||
the public repository loses is the story of how a question was found, not the answer.
|
||||
**What the record keeps.** A design or governance question that matters ends in a decision record, which the
|
||||
knowledge base holds whole, with its reasoning
|
||||
([ADR 0290](0290-a-decision-record-lives-whole-in-the-knowledge-base-made-of-clauses.md)). What an issue's
|
||||
content adds is the story of how a question was found, not the answer. Whether accepted decision records stay
|
||||
readable in this public repository is issue 435.
|
||||
|
||||
### Against GENESIS
|
||||
|
||||
@@ -52,7 +53,7 @@ the public repository loses is the story of how a question was found, not the an
|
||||
1. **Keep ADR 0275's split.** Rejected by the operator: one issue in two places, and a reader who must know which.
|
||||
2. **Everything in the tracker; hq keeps no issue content.** Adopted.
|
||||
3. **Everything in the tracker, and hq keeps a generated public copy of every resolved design or governance issue.**
|
||||
Rejected for now: it keeps a second copy, and the public reader who needs the outcome has the decision record. This
|
||||
Rejected for now: it keeps a second copy, and the reader who needs the outcome has the decision record. This
|
||||
was the research's open question 2; the operator confirmed no export on 2026-10-11. An export, if it is wanted
|
||||
later, is a decision of its own.
|
||||
|
||||
@@ -71,8 +72,8 @@ the public repository loses is the story of how a question was found, not the an
|
||||
4. **A mention of an issue is its number.** The 765 path mentions become "issue N" in the same pull request that
|
||||
removes the folders, and `records.py` then refuses a new path into `04-ISSUES/`. The knowledge base and the
|
||||
tracker resolve a number.
|
||||
5. **No issue content is exported to this repository.** The public record of a design question is the decision
|
||||
record it led to.
|
||||
5. **No issue content is exported to this repository.** The record of a design question is the decision record it
|
||||
led to.
|
||||
6. **The work is tracked by issue 427**: the documents in the tracker, the import, the mentions rewritten, the folders
|
||||
removed, and playbook 03 changed to match. Until it lands, every folder stays and playbook 03 is followed as it is
|
||||
written.
|
||||
@@ -80,8 +81,8 @@ the public repository loses is the story of how a question was found, not the an
|
||||
## Consequences
|
||||
|
||||
- One issue, one place: an agent reads an issue whole with `issue-tracker.get`.
|
||||
- The public repository no longer shows how a design question was found. The question's answer, the decision record,
|
||||
stays public.
|
||||
- The public repository no longer shows how a design question was found. Whether it still shows the answer, the
|
||||
decision record, is issue 435.
|
||||
- The tracker's values grow from a few hundred bytes to some kilobytes each; the largest measured fits 10 times over.
|
||||
- Reviewing an issue's diagnosis moves from a pull request to the tracker's history of that document. An issue's
|
||||
content was never a decision; what is decided still goes through a pull request.
|
||||
|
||||
@@ -4,28 +4,28 @@ status: designed
|
||||
code: []
|
||||
updated: 2026-10-11
|
||||
decisions:
|
||||
- 02-DECISIONS/0290-the-knowledge-base-holds-each-records-structure-and-clauses-and-hq-keeps-its-reasoning.md
|
||||
- 02-DECISIONS/0290-a-decision-record-lives-whole-in-the-knowledge-base-made-of-clauses.md
|
||||
---
|
||||
|
||||
# 55 — The knowledge base
|
||||
|
||||
**The mesh keeps the structure of its decision records and research efforts in a module of its own,
|
||||
`mesh-knowledge`, one instance on the control-node, holding the seat `knowledge-base`. It holds each record's number,
|
||||
status, topic and typed links, and each decision's clauses with their own status, and answers what holds in one
|
||||
bounded call. This repository keeps each record's reasoning, reviewed in pull requests; a record is accepted when its
|
||||
pull request merges.**
|
||||
([ADR 0290](../../02-DECISIONS/0290-the-knowledge-base-holds-each-records-structure-and-clauses-and-hq-keeps-its-reasoning.md),
|
||||
**The mesh keeps its decision records and research efforts whole in a module of its own, `mesh-knowledge`, one
|
||||
instance on the control-node, holding the seat `knowledge-base`: each record's number, status, topic, typed links,
|
||||
its clauses with their own status, and its reasoning, with every version kept. A record is proposed, checked when it
|
||||
is written, reviewed by an independent agent and accepted there; the operator's Approve is asked when a record needs
|
||||
it. Agents ask what holds, and why, in one bounded call.**
|
||||
([ADR 0290](../../02-DECISIONS/0290-a-decision-record-lives-whole-in-the-knowledge-base-made-of-clauses.md),
|
||||
from [research 045](../../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/00-overview.md).)
|
||||
|
||||
A **clause** is one numbered statement a decision record makes, with its own status. The **knowledge base** is the
|
||||
module that holds records' structure and clauses; the seat it holds is `knowledge-base`. The glossary holds both words.
|
||||
module that holds the records; the seat it holds is `knowledge-base`. The glossary holds both words.
|
||||
|
||||
**Acceptance.** A session started in any folder on any node asks "what holds about the merge window, and why" and
|
||||
gets, in one call under 4 KiB, the clauses in force, the records they come from, what changed them since, and the
|
||||
commit of this repository it was read at.
|
||||
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.
|
||||
|
||||
This document designs the first slice in detail, tracked by issue 425. The slices after it are in
|
||||
[§ 8](#8-the-slices-after-the-first).
|
||||
[§ 9](#9-the-slices-after-the-first).
|
||||
|
||||
## 1. The parts
|
||||
|
||||
@@ -34,30 +34,34 @@ This document designs the first slice in detail, tracked by issue 425. The slice
|
||||
|
||||
mesh-knowledge (seat knowledge-base, held once for the mesh)
|
||||
├ its process, launched by the node runtime
|
||||
├ a database in the store records, clauses, links, sources; ranked full-text search
|
||||
├ verbs ask, get, holds, links, reserve, propose, import, return
|
||||
├ a database in the store records, versions, clauses, links; ranked full-text search
|
||||
├ verbs ask, get, holds, links, history, reserve, propose, review, import, return
|
||||
│ served by the control-node's tool runner
|
||||
├ events imported, proposed, accepted, changed, drafted, confirmed, returned
|
||||
└ consumes the forge's merge event for hq: read the merged records (§ 4)
|
||||
├ events proposed, reviewed, accepted, changed, imported, drafted, confirmed, returned
|
||||
└ consumes the router's warrants: the operator's Approve for a record that needs it (§ 5)
|
||||
|
||||
records (any node) records_read at a commit: the text of a record
|
||||
mesh-issues (control-node) the counters for decision and research numbers (§ 5)
|
||||
claude-code (same node) claude_code_judge: draft and confirm clauses (§ 6)
|
||||
mesh-issues (control-node) the counters for decision and research numbers (§ 6)
|
||||
claude-code (same node) claude_code_judge: draft and confirm clauses (§ 7)
|
||||
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
|
||||
|
||||
any agent session, on any node
|
||||
mesh MCP server ── mesh_search, mesh_describe, mesh_call ──▶ the verbs, over the bus
|
||||
```
|
||||
|
||||
The module is written in Go against the SDK and holds no checkout: it reads this repository through the records
|
||||
module's `records_read` and `records_list` at the commit a merge names, as the issue tracker's import does.
|
||||
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.
|
||||
|
||||
## 2. What one record holds
|
||||
|
||||
- `number` and `kind` (decision or research), its key together; `title`, `topic`, `status`, `date`, `deciders`, and
|
||||
the `path` of its file in this repository;
|
||||
- `commit`: the commit of this repository the record was last read at;
|
||||
- `number` and `kind` (decision or research), its key together; `title`, `topic`, `status`, `date`, `deciders`;
|
||||
- its **reasoning**, in sections: for a decision, context, the options weighed, consequences, how it is checked,
|
||||
references; for a research effort, its overview and each of its documents by name; markdown, as written;
|
||||
- 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 change is a new version with who made it, when, and why in one line; `history` lists them
|
||||
and gives the difference between any two. A progressive insight is a version marked as one, dated, saying what stood
|
||||
before.
|
||||
|
||||
| Link | From → to |
|
||||
|---|---|
|
||||
@@ -65,12 +69,7 @@ module's `records_read` and `records_list` at the commit a merge names, as the i
|
||||
| `changes` | a clause or a record → a clause it replaces part of |
|
||||
| `extends` | a record → a record it builds on |
|
||||
| `became` | a research effort → a decision record or design |
|
||||
| `corrects` | a dated progressive insight → the record it stands in |
|
||||
| `cites` | any record → any record or issue it links in its text |
|
||||
|
||||
`changes` at the level of a clause is new. A merged record that declares `supersedes-in-part` gives a `changes` link
|
||||
to the older record; which of the older record's clauses it changes is read from the newer record's text by the
|
||||
judgement of § 6 and held as `drafted` until confirmed, like a drafted clause.
|
||||
| `cites` | any record → any record or issue it names |
|
||||
|
||||
## 3. Clauses
|
||||
|
||||
@@ -78,100 +77,107 @@ A clause holds its record's number and its own (`0276 §4`), its wording, a `sta
|
||||
|
||||
| Status | Meaning |
|
||||
|---|---|
|
||||
| `proposed` | its record is not accepted yet |
|
||||
| `in force` | holds, and nothing later changes it |
|
||||
| `changed` | a later clause replaces part of it; the `changes` link names which |
|
||||
| `superseded` | its record is superseded, or a later clause replaces it whole |
|
||||
| `proposed` | its record's pull request is not merged |
|
||||
|
||||
| Source | Meaning |
|
||||
|---|---|
|
||||
| `written` | read from a `Decision` section written as numbered clauses with a bold lead |
|
||||
| `drafted` | written by the judgement from a prose `Decision` section; never served as in force |
|
||||
| `confirmed` | drafted, then confirmed by a second, independent judgement (§ 6) |
|
||||
| `written` | written as a clause by the record's author |
|
||||
| `drafted` | written by the judgement from a prose `Decision` section at the import; never served as in force |
|
||||
| `confirmed` | drafted, then confirmed by a second, independent judgement (§ 7) |
|
||||
|
||||
From 2026-10-11 every accepted record writes its clauses (`records.py`, check `clauses`). The 226 records written
|
||||
before then in prose get theirs drafted and confirmed at the import.
|
||||
## 4. Writing a record
|
||||
|
||||
## 4. Acceptance follows the merge
|
||||
`reserve` gives a number (§ 6). `propose` takes the record whole: its fields, its clauses, its reasoning in sections,
|
||||
its links, and for each `changes` the clauses it changes. It is refused, with every reason at once, when one of the
|
||||
29 rules of the hq checks that judge one record or its prose fails, among them:
|
||||
|
||||
The knowledge base consumes the forge's merge event for this repository. For each decision record or research
|
||||
overview the merge adds or changes, it reads the file at the merge's commit through the records module and:
|
||||
- a link names a record or clause that does not exist;
|
||||
- a decision has no clause, or a clause has no bold lead;
|
||||
- a record it supersedes or changes is not accepted, or one it cites as live is superseded without naming the record
|
||||
that replaced it;
|
||||
- its topic is not one of the reading order's;
|
||||
- a research effort graduates without naming what it became;
|
||||
- its text uses a retired word of the glossary, or a daemon's command line.
|
||||
|
||||
1. writes or updates the record's structure from its frontmatter, and its clauses from its `Decision` section;
|
||||
2. moves a record from `proposed` to `accepted` when its frontmatter says `accepted`;
|
||||
3. for each `supersedes` and `supersedes-in-part` the record declares, moves the older record or the drafted target
|
||||
clauses to `superseded` or `changed`, and emits `changed` for each;
|
||||
4. emits `accepted`, naming the commit.
|
||||
A proposed record can be revised by its author as new versions until it is reviewed. Nothing proposed is ever served
|
||||
as in force.
|
||||
|
||||
A merge that changes nothing the knowledge base holds changes nothing. A record read that fails is retried, and a merge
|
||||
whose records could not be read after the retries raises a condition naming the commit: a merge the knowledge base did
|
||||
not take is loud, not silent.
|
||||
## 5. Review and acceptance
|
||||
|
||||
`propose` writes a new record's structure as `proposed` before its pull request exists, with the number `reserve`
|
||||
gave; nothing proposed is ever served as in force. A structural change to an accepted record without a merge is
|
||||
refused, with the reason that what an accepted record says changes only through a pull request.
|
||||
`review` is called by an agent that did not write the record, with a verdict, `approve` or `changes`, and its
|
||||
findings. The knowledge base refuses a review by the record's author. On `changes`, the record stays proposed and the
|
||||
findings are kept with it. On `approve`:
|
||||
|
||||
## 5. Numbers
|
||||
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
|
||||
channel that proves who answered ([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));
|
||||
the knowledge base accepts it only on the warrant for Approve, which it keeps with the record.
|
||||
|
||||
`reserve` takes a kind and asks the issue tracker for the next number of that sequence (issue 424, ADR 0275 rule 8),
|
||||
and answers it. The number is spent: a record that never lands leaves it as a gap, and the knowledge base keeps who
|
||||
reserved it and when, as `withdrawn` once its branch is closed unmerged. The knowledge base keeps no counter.
|
||||
On acceptance the record and its clauses move to `accepted` and `in force`, every clause its `changes` and
|
||||
`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 raises a
|
||||
condition naming the rule and the records, and does not undo the acceptance.
|
||||
|
||||
## 6. Drafting and confirming clauses
|
||||
An accepted record is changed only by a new record, or by a progressive insight: a new version marked as one, which
|
||||
goes through `review` like a proposal.
|
||||
|
||||
## 6. Numbers
|
||||
|
||||
`reserve` takes a kind and asks the issue tracker for the next number of that sequence (issue 424, ADR 0275 rule 8).
|
||||
The number is spent: a record that is never accepted keeps it as `withdrawn`, with who reserved it and when. The
|
||||
knowledge base keeps no counter.
|
||||
|
||||
## 7. Drafting and confirming clauses at the import
|
||||
|
||||
For a decision whose `Decision` section is prose, the import asks 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))
|
||||
for its clauses: the record's `Decision` section in, numbered statements out, each one sentence, each quoting nothing
|
||||
the section does not say. They are stored `drafted`.
|
||||
for its clauses: the section in, numbered statements out, each one sentence, each saying nothing the section does not.
|
||||
They are stored `drafted`. A second judgement, in a separate call that sees only the record and the drafts, answers
|
||||
per clause whether the record says exactly that; an accepted clause becomes `confirmed`, a rejected one stays
|
||||
`drafted` with the reason. Which clause of an older record a `supersedes-in-part` changes is judged and confirmed the
|
||||
same way. When every record of a topic has been through both, the operator is told once per topic, with the counts
|
||||
confirmed and still drafted. `return` with a record's number and a reason sends it back to be drafted again.
|
||||
|
||||
A second judgement, made in a separate call that sees only the record's text and the drafts, answers per clause
|
||||
whether the record says exactly that. A clause it accepts becomes `confirmed`; one it rejects stays `drafted` with
|
||||
the reason. When every record of a topic has been through both, the operator is told once per topic, with the count
|
||||
confirmed and the count still drafted, through the router. `return` with a record's number and a reason sends a
|
||||
record back to be drafted again.
|
||||
## 8. The import
|
||||
|
||||
## 7. Answers
|
||||
`import` takes a commit of this repository (and `dry-run`) and writes every decision record and research effort
|
||||
whole, at its own number, as its first version, naming the commit. It creates what is absent, never overwrites, never
|
||||
advances a counter; a second run changes nothing and says so. Records written in this repository after the import,
|
||||
while the first slice does not take writes yet, are taken in by running it again.
|
||||
|
||||
| Verb | Takes | Answers |
|
||||
|---|---|---|
|
||||
| `ask` | a question in words; optionally a kind, a topic, a size bound | records and clauses bearing on it, ranked by the store's full-text search: number, kind, status, title, and each clause with its status and what changed it |
|
||||
| `get` | a number and kind; optionally `reasoning` | one record: its clauses, its links both ways, what changed it since; the reasoning's text only with `reasoning` |
|
||||
| `holds` | a topic or a record | the clauses in force, each with its record and the `changes` that led to its present wording |
|
||||
| `links` | a number and kind | its typed links, both directions |
|
||||
| `reserve` | a kind | the next number (§ 5) |
|
||||
| `propose` | a kind, a number from `reserve`, a title, a topic, and its links | the structure written as `proposed` |
|
||||
| `import` | optionally `dry-run`, a commit | every decision and research effort at that commit, as § 4 reads one, with prose decisions drafted (§ 6); create-if-absent, never an overwrite; run again, changes nothing and says so |
|
||||
| `return` | a number and a reason | sends a record's drafted or confirmed clauses back to be drafted again |
|
||||
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.
|
||||
|
||||
Every answer names the commit it was read at. `ask`, `get` and `holds` answer at most 4 KiB unless a larger bound is
|
||||
given, and say when they cut and how to ask for the rest. A clause that is `drafted` is marked so in every answer and
|
||||
never listed under `holds`.
|
||||
|
||||
## 8. The slices after the first
|
||||
## 9. The slices after the first
|
||||
|
||||
| Slice | Delivers | Done when the operator sees | Tracked by |
|
||||
|---|---|---|---|
|
||||
| 1 | this document: the module, the import, the clauses, the answers, acceptance on merge | the acceptance sentence above, live | issue 425 |
|
||||
| 2 | the frontmatter fields the knowledge base holds leave this repository, kind by kind, and the per-record rules of `records.py` and `cycle.py` move into its write verbs | a decision record's file carries no status or links, and the hq checks still pass | issue 426 |
|
||||
| 1 | this document: the module, the import, clauses, answers, `propose`, `review` and acceptance | the acceptance sentence above, live, and a record proposed, reviewed and accepted without a pull request | issue 425 |
|
||||
| 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, playbooks and glossary entries as kinds | `holds` answers for a design's decisions and a glossary word | issue 428 |
|
||||
| 4 | meeting notes, drawings and blog posts | not decided; needs its own decision | issue 429 |
|
||||
|
||||
Numbers from the issue tracker, which slice 1 needs for `reserve`, are the tracker's own slice, tracked by issue 424.
|
||||
Numbers from the issue tracker, which `reserve` needs, are the tracker's own slice, tracked by issue 424. Whether this
|
||||
repository keeps a generated public copy of accepted records is issue 435.
|
||||
|
||||
## 9. How it is checked
|
||||
## 10. How it is checked
|
||||
|
||||
| Rule | Checked by |
|
||||
|---|---|
|
||||
| A record merged in hq is held, with its clauses, at the merge's commit | the module's test over a real bus and a fixture repository: a merge event, then `get` names that commit; and live, the first decision merged after the module is delivered |
|
||||
| A merge the knowledge base could not take is loud | the module's test: records unreadable after the retries raise a condition naming the commit |
|
||||
| The import changes nothing on a second run | the module's test: two imports at one commit, the second reports nothing created |
|
||||
| A proposal that breaks a per-record rule is refused, naming every reason | the module's table test, one case per rule of § 4 |
|
||||
| A record is accepted only after a review by someone else, and, when it needs the operator, only on the warrant | the module's tests: a review by the author refused; a `needs operator` record unaccepted without the warrant, accepted with it |
|
||||
| A whole-set rule that fails is loud | the module's test: an acceptance that leaves a decision cited by nothing raises the condition |
|
||||
| Every version is kept and comparable | the module's test: three versions, `history` lists them, the difference of the first and third is exact |
|
||||
| The import changes nothing on a second run, and loses nothing | the module's test over a fixture repository; and the comparison of § 8 on issue 426 |
|
||||
| A drafted clause is never served as in force | the module's test: `holds` over a record with only drafted clauses answers none, and `ask` marks them |
|
||||
| A structural change to an accepted record without a merge is refused | the module's test, one case per field |
|
||||
| An answer stays within its bound and names its commit | 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 new record writes its clauses | `records.py`, check `clauses`, on every hq pull request |
|
||||
| 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 |
|
||||
| Live | the acceptance sentence, asked from a session outside this repository |
|
||||
|
||||
## What it leaves out
|
||||
|
||||
Semantic or vector search; a browser view; writing a record's reasoning (that stays a pull request in this
|
||||
repository); and the rules of how-we-build, which are not decision records. Each needs a decision of its own.
|
||||
Semantic or vector search; a browser view; line comments on a proposal (a review'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.
|
||||
|
||||
@@ -54,7 +54,7 @@ document is written and this one's status becomes `implemented`.
|
||||
| [`52-shares-and-mounts.md`](52-shares-and-mounts.md) | **In progress.** A node shares one folder at a time through `nfs-server`, which provides it as a provision to the private network only, mapping every client to the folder's owner; a node that asks mounts it through `mounts`, a mount unit and an automount per share, so nothing mounts or fails at boot; a device that comes and goes is an occasional source whose absence is a state | [ADR 0263](../../02-DECISIONS/0263-a-share-is-a-provision-a-node-mounts-it-on-demand-and-only-nodes-that-ask-get-it.md), [ADR 0051](../../02-DECISIONS/0051-shared-data-is-the-operators.md), [ADR 0092](../../02-DECISIONS/0092-an-operator-delivers-a-pair-credential.md) |
|
||||
| [`53-the-issue-tracker.md`](53-the-issue-tracker.md) | **Designed.** The mesh keeps its issues in one module, `issues`, on the control-node: every number from one counter advanced by compare-and-set, the cycle's issue rules refused at the write, an event per change; an issue lives whole in the tracker, hq keeping no issue content ([ADR 0291](../../02-DECISIONS/0291-an-issue-lives-whole-in-the-issue-tracker.md)) | [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), [ADR 0291](../../02-DECISIONS/0291-an-issue-lives-whole-in-the-issue-tracker.md) |
|
||||
| [`54-the-controllers-records-on-the-bus.md`](54-the-controllers-records-on-the-bus.md) | **Designed.** The controller keeps five record mirrors on the bus (nodes, assignments, walks, builds, settings): each a bucket written from its store only when the record changed, with one event per write, and audited against the store every self-check run, a difference raised as `mirror-drifted` before the healer H6 repairs it | [ADR 0289](../../02-DECISIONS/0289-the-controller-mirrors-its-records-into-buckets-written-only-on-a-change-and-audited-against-its-store.md) |
|
||||
| [`55-the-knowledge-base.md`](55-the-knowledge-base.md) | **Designed.** The mesh keeps its decision records' and research efforts' structure in one module, `mesh-knowledge`, on the control-node: number, status, topic, typed links both ways, and each decision's clauses with their own status; a record is accepted when its pull request merges; agents ask what holds in one bounded call, and hq keeps the reasoning | [ADR 0290](../../02-DECISIONS/0290-the-knowledge-base-holds-each-records-structure-and-clauses-and-hq-keeps-its-reasoning.md) |
|
||||
| [`55-the-knowledge-base.md`](55-the-knowledge-base.md) | **Designed.** The mesh keeps its decision records and research efforts whole in one module, `mesh-knowledge`, on the control-node: number, status, topic, typed links both ways, each decision's clauses with their own status, and the reasoning, with every version; a record is proposed, checked at the write, reviewed by an independent agent and accepted there, with the operator's Approve when it needs it; agents ask what holds in one bounded call | [ADR 0290](../../02-DECISIONS/0290-a-decision-record-lives-whole-in-the-knowledge-base-made-of-clauses.md) |
|
||||
|
||||
## Not yet written
|
||||
|
||||
|
||||
Reference in New Issue
Block a user