Add mesh-knowledge, the knowledge base's first slice (hq issue 425, ADR 0290)
mesh/merge-gate pass: builds new: modules/mesh-knowledge, sent nowhere; no bus step; every machine composes with the change as it did without (4 of 4 compo…
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate pass: builds new: modules/mesh-knowledge, sent nowhere; no bus step; every machine composes with the change as it did without (4 of 4 compo…
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
An agent learns what a decision says only by reading whole records. This module holds every decision record and research effort whole in a database in the store, with clauses that carry their own status and source, typed links read from both ends, and every version. It answers ask, get and holds within a stated bound, and takes a record through reserve, propose (refused on any of the 29 per-record rules), review by someone other than the author, and acceptance, on the operator's proven warrant when the record needs it. The 4 whole-set rules make the module unhealthy when they fail. The import reads hq at a commit through the records module, never overwrites, and changes nothing when run again. Prose decisions get drafted clauses that a second judgement must confirm before they are served.
This commit is contained in:
+86
@@ -0,0 +1,86 @@
|
||||
---
|
||||
status: graduated
|
||||
initiated: 2026-10-10
|
||||
touches:
|
||||
- 02-DECISIONS/0019-how-this-repository-works.md
|
||||
- 02-DECISIONS/0080-the-development-cycle-is-checked.md
|
||||
- 00-META/process/03-issues.md
|
||||
- 00-META/glossary.md
|
||||
- the runtime's state verbs and the SDK's state interface
|
||||
became:
|
||||
- 03-DESIGN/01-to-be/53-the-issue-tracker.md
|
||||
- 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
|
||||
---
|
||||
|
||||
# 042 — The mesh keeps its own issues
|
||||
|
||||
## What
|
||||
|
||||
Whether the mesh should keep its issues in a module of its own, on the bus, instead of only as
|
||||
numbered folders in this repository's `04-ISSUES/`, and what the smallest useful first version of
|
||||
that module is. The operator's ask of 2026-10-10: work on a ticketing system on the bus, consolidate
|
||||
every current issue into it, start small and extend the module along the way.
|
||||
|
||||
The effort answers six questions, in [01-findings.md](01-findings.md):
|
||||
|
||||
1. The smallest useful first slice: what the module holds, which tools it serves, which events it
|
||||
emits, and what it explicitly leaves out.
|
||||
2. Where the truth lives during and after the move: the folders here, the module, or a split
|
||||
between them, and what each choice does to the public-repository rule, playbook 03 and the hq
|
||||
checks.
|
||||
3. How the 357 issue folders are imported and consolidated (duplicates, still-open ones, grouping).
|
||||
4. How the controller's conditions, the router's asks and deliveries relate to issues.
|
||||
5. How the operator sees issues: through the mesh's tools first, through a view onto the bus later.
|
||||
6. The open questions for the operator, and the slices after the first.
|
||||
|
||||
The operator also named an existing project as inspiration: *hits*, a headless issue tracker built
|
||||
as NATS micro services on JetStream, with an MCP server for agents. Its model is studied in the
|
||||
findings, along with whether to reuse its code or build on its model.
|
||||
|
||||
## Why
|
||||
|
||||
Numbers collide. Playbook 03 tells an author to take the next free number across `main` and every
|
||||
open pull request, and [issue 155](../../04-ISSUES/155-two-records-may-share-a-number-and-nothing-says-so/00-report.md)
|
||||
records the second collision reaching `main` with every check passing. `cycle.py` now refuses two
|
||||
records sharing a number, which catches a collision after it happens and does not prevent one. On
|
||||
`main` at the time of writing, 31 commits mention a renumbering. On 2026-10-07 three decision numbers
|
||||
collided in one evening. On 2026-10-10 an open pull request still carries a branch named for issue
|
||||
349 and a title naming issue 350, because 349 was taken on `main` first. The operator's answer on
|
||||
2026-10-07 was that numbering belongs to the mesh's own issue tracker.
|
||||
|
||||
Status is also hard to see. Of 357 issue folders on `main`, 73 are not closed (27 `open`, 45
|
||||
`located`, 1 `diagnosing`). Finding them means reading frontmatter across the repository.
|
||||
Nothing connects a condition the controller raises to the issue that would fix it: on 2026-10-10 a
|
||||
condition was silenced with the words "hq issue to follow", and nothing records whether one followed.
|
||||
|
||||
## What it touches
|
||||
|
||||
- [ADR 0019](../../02-DECISIONS/0019-how-this-repository-works.md) (statuses live in frontmatter) and
|
||||
[ADR 0080](../../02-DECISIONS/0080-the-development-cycle-is-checked.md) (the cycle is checked), with
|
||||
playbook [03](../../00-META/process/03-issues.md) and `00-META/checks/cycle.py`.
|
||||
- [ADR 0201](../../02-DECISIONS/0201-a-module-keeps-its-current-state-in-key-value-buckets-it-declares-and-reaches-through-the-runtime.md)
|
||||
(a module keeps its state in key-value buckets it declares),
|
||||
[ADR 0197](../../02-DECISIONS/0197-every-tool-announces-itself-on-the-bus-in-the-nats-services-protocol.md)
|
||||
(tools announce themselves on the bus) and
|
||||
[ADR 0041](../../02-DECISIONS/0041-events-are-a-relationship.md) (events are declared).
|
||||
- The conditions of [ADR 0231](../../02-DECISIONS/0231-a-healer-acts-on-what-observation-raised-and-only-observation-says-it-worked.md)
|
||||
and the asks of [ADR 0259](../../02-DECISIONS/0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md).
|
||||
- The records module, which indexes this repository for agents.
|
||||
|
||||
**Graduated 2026-10-10** into [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)
|
||||
and [to-be 53](../../03-DESIGN/01-to-be/53-the-issue-tracker.md). The operator delegated the five open questions; each
|
||||
was decided as recommended. `touches:` names what the decision changes.
|
||||
|
||||
## Words
|
||||
|
||||
The glossary's word for one of these is **issue** (*The record*: "a report in `04-ISSUES/`"). This
|
||||
effort keeps that word for the thing the module holds, and proposes **issue tracker** for the module
|
||||
that holds them, with the module named `issues`. It does not use *ticket*, the operator's word in
|
||||
the ask, or *item*, the word hits uses. If the glossary entry is widened (an issue is then held by
|
||||
the issue tracker, and its narrative may live in `04-ISSUES/`), *ticket* would go on its *Not:* line.
|
||||
That change belongs to the decision this effort graduates into, not to the effort itself.
|
||||
|
||||
## Open questions for the operator
|
||||
|
||||
Listed in [01-findings.md § 7](01-findings.md#7-open-questions-for-the-operator), each with a
|
||||
recommendation.
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
# 01 — Findings
|
||||
|
||||
Measured on 2026-10-10 against `main` of this repository, the open pull requests on the forge, the
|
||||
controller's open conditions, the module SDK's source, and a clone of the hits repository at its
|
||||
release v0.7.0. Each section ends with what this effort recommends; section 7 lists what needs the
|
||||
operator.
|
||||
|
||||
## 0. What exists today, measured
|
||||
|
||||
| Fact | Measured |
|
||||
|---|---|
|
||||
| Issue folders on `main` | 357, numbered up to 362; numbers 283 and 284 were never used, and 338, 341 and 350 sit on open pull requests (363 too) |
|
||||
| Status in frontmatter | 283 `resolved`, 1 `wontfix`, 45 `located`, 27 `open`, 1 `diagnosing` |
|
||||
| Frontmatter keys | `status`, `opened`, `located-in` on all 357; `fixed-by` 356; `amended-design` 344; `replay` 22; `replay-none` 44 |
|
||||
| Size | 1.9 MiB of markdown in all; median folder 4.6 KiB, largest 25 KiB; 244 folders hold only a report, 111 also a diagnosis |
|
||||
| Links between issues | 168 folders link another issue's folder (265 links); 193 name another issue in prose |
|
||||
| `located-in` | free text: the controller is written `mesh-controller`, `cmd/mesh-controller`, `mesh-control` and as file paths; 17 issues name nothing |
|
||||
| Renumberings | 31 commits on `main` mention one; one open pull request still carries the old number in its branch name |
|
||||
| The forge's own issues | none in this repository or the controller's; [issue 178](../../04-ISSUES/178-a-routed-name-resolves-to-a-provider-merely-told-it/00-report.md) was filed there once and moved here, because "its numbers collide with hq's pull request numbers in conversation" |
|
||||
| Conditions | 10 open; 5 of kind `healer-wanted` (a hand repair repeated, "an automatic repair is wanted"); one silenced with "hq issue to follow" |
|
||||
|
||||
Two things follow. The collisions come from allocating a number by reading a repository that many
|
||||
branches write at once; nothing short of one allocator removes them. And the frontmatter is a small,
|
||||
regular data set (six keys, 1.9 MiB) that fits easily in the bus's key-value store under the limits
|
||||
[ADR 0201](../../02-DECISIONS/0201-a-module-keeps-its-current-state-in-key-value-buckets-it-declares-and-reaches-through-the-runtime.md)
|
||||
§6 sets (256 KiB a value, 64 MiB a bucket).
|
||||
|
||||
## 1. The first slice
|
||||
|
||||
**A Go module `issues`, one instance on the control-node, serving one seat held once for the mesh.**
|
||||
Its state is in buckets it declares (ADR 0201), its tools announce themselves on the bus
|
||||
([ADR 0197](../../02-DECISIONS/0197-every-tool-announces-itself-on-the-bus-in-the-nats-services-protocol.md)),
|
||||
and every change is an event it declares under `emits`
|
||||
([ADR 0041](../../02-DECISIONS/0041-events-are-a-relationship.md)). The module that delivers pull
|
||||
requests already has this shape: Go, one mesh seat, two state buckets, declared events.
|
||||
|
||||
**What one issue holds in v1**, the frontmatter of today plus what the folders carry in prose:
|
||||
|
||||
- `number` (the key), `title`, `status` (`open`, `diagnosing`, `located`, `resolved`, `wontfix`),
|
||||
`opened`, `closed`;
|
||||
- `located-in`, from a registered list of repositories and modules rather than free text;
|
||||
- `fixed-by` (pull requests or commits), `amended-design`, `replay` or `replay-none`;
|
||||
- `notes`, appended and never edited: who wrote, when, and the text;
|
||||
- `links`, typed: to another issue (`duplicates`, `relates-to`), to a pull request, a decision
|
||||
record, a design, a condition key or a delivery;
|
||||
- `record`: the path of the issue's folder in this repository, when it has one (section 2).
|
||||
|
||||
**Storage.** One bucket `issues` with one key per issue, keeping a short history per key, and a
|
||||
`counter` key for the next number. The events (`opened`, `changed`, `noted`, `linked`) carry what
|
||||
changed and who changed it, so they are the audit trail, and a view can watch the bucket. Section 6
|
||||
compares this with a stream as the source of record.
|
||||
|
||||
**Tools** (verbs of the seat, found with `mesh_search`):
|
||||
|
||||
| Tool | Does |
|
||||
|---|---|
|
||||
| `open` | takes the next number atomically and writes the issue; refuses a title or report that is empty |
|
||||
| `get` | one issue, whole |
|
||||
| `list` | by status, by `located-in`, by a phrase in title or notes; compact rows, newest first |
|
||||
| `move` | changes status, enforcing today's cycle rules at the write: `located` needs `located-in`; `resolved` needs `fixed-by`; a core issue needs `replay` or `replay-none`; `wontfix` needs a reason |
|
||||
| `note` | appends to the trail |
|
||||
| `link` / `unlink` | adds or removes a typed link |
|
||||
| `import` | reads this repository's issue folders and writes them as issues with their own numbers (section 3); idempotent, reporting what it would change before it does |
|
||||
|
||||
**The caller is the bus credential, not an argument.** The module records who acted from the
|
||||
identity the runtime gives it with each call, so an agent cannot write as someone else.
|
||||
|
||||
**Atomic numbering needs compare-and-set.** The SDK's state interface (v0.1.9) offers `get`, `put`,
|
||||
`delete`, `keys` and `watch`, and no write that is refused when the key changed since it was read.
|
||||
Whether the runtime's `mesh/state.put` takes an expected revision was not checked; the tool runner's
|
||||
code was not read for this effort. Two ways out: add `create` and an `update` that takes the revision
|
||||
read to the state interface (small, and every module with a counter gains it), or run exactly one
|
||||
instance and number inside it. **Recommended: the first.** One instance is also right for v1, but the
|
||||
counter should not depend on it.
|
||||
|
||||
> **Correction — 2026-10-10.** The finding above is wrong about the SDK. Version v0.1.9, the one read, had no
|
||||
> compare-and-set, but the SDK's Go state interface already had it from go/v0.1.10: `Create` (writes a key only if it
|
||||
> does not exist) and `Update` (writes only at the revision the caller read), with the runtime's matching state
|
||||
> verbs, both from [ADR 0259](../../02-DECISIONS/0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md).
|
||||
> What the tracker's counter needed and slice 1 added is `Increment`, in go/v0.1.12, which reads a counter and writes
|
||||
> the next number with `Create` or `Update` at the revision it read, retrying a bounded number of times. The
|
||||
> recommendation stands; the work it named was smaller than stated. ADR 0275 carries the same correction.
|
||||
|
||||
**Explicitly left out of v1:** decision and research numbers (slice 2), any change to playbook 03 or
|
||||
the hq checks (slice 2), duplicate finding beyond links (slice 3), opening an issue from a condition
|
||||
(slice 4), a web view (slice 5), full-text or semantic search, priorities, claims, notifications, and
|
||||
the forge's own issues.
|
||||
|
||||
## 2. Where the truth lives
|
||||
|
||||
| | (a) Split: the tracker holds the issue, hq holds the narrative | (b) Everything moves | (c) The tracker mirrors hq |
|
||||
|---|---|---|---|
|
||||
| Number | tracker | tracker | hq, so collisions stay |
|
||||
| Status, `located-in`, `fixed-by`, links | tracker | tracker | hq frontmatter, copied |
|
||||
| Report and diagnosis | hq folder for a design or governance question; notes in the tracker for the rest | tracker notes | hq |
|
||||
| Public-repository rule | holds: hq keeps only scrubbed narrative, the tracker is private and may name nodes | the public record of design questions is lost | holds |
|
||||
| Playbook 03 | changes: open in the tracker first, write a folder only for a design or governance question | replaced | unchanged |
|
||||
| `cycle.py` | its issue rules move into the tracker's `move`, refused at the write instead of at merge | same | unchanged, and a second copy to keep in step |
|
||||
| Records module | still finds the narrative; the tracker's `list` and `get` serve status | finds no issues | unchanged |
|
||||
|
||||
Option (c) keeps the collisions and adds a second copy that can drift, so it answers neither of the
|
||||
operator's problems. Option (b) loses the public record that hq exists to be
|
||||
([ADR 0019](../../02-DECISIONS/0019-how-this-repository-works.md)), and with it the
|
||||
symptom-to-component memory that playbook 03 says is never deleted.
|
||||
|
||||
**Recommended: (a).** Every issue gets a number from the tracker, including ones that never need a
|
||||
document here (a node's quirk, an operational follow-up, which playbook 03's table already sends
|
||||
elsewhere). A design or governance issue also gets a folder `04-ISSUES/NNN-slug/` with the tracker's
|
||||
number, whose frontmatter shrinks to a pointer (`issue: NNN`) and whose prose stays reviewed in pull
|
||||
requests. Status lives in one place, the tracker. This reverses ADR 0019's "statuses live only in
|
||||
frontmatter" for issues and moves part of ADR 0080's check, so it needs a decision record that
|
||||
supersedes those parts, written when this effort graduates.
|
||||
|
||||
**Numbering continues.** The tracker's counter starts above the highest number on `main` and on open
|
||||
branches at the moment of the switch (today 363, so the first new issue is 364). Numbers 283 and 284
|
||||
stay unused, and a number never moves again.
|
||||
|
||||
**During the move**, hq frontmatter stays authoritative until the import has run and been checked
|
||||
against it, and one pull request then removes the status keys from every report and changes playbook
|
||||
03 and `cycle.py` together. There is no period in which both are written.
|
||||
|
||||
## 3. Importing and consolidating the 357 issues
|
||||
|
||||
**Import.** `import` reads the folders through the records module (`records_list`, `records_read`),
|
||||
over the bus, rather than from a checkout. Each folder becomes an issue with its own number, its
|
||||
frontmatter as fields, its title from the heading, the commit it was read at, and its path as
|
||||
`record`. Folder-to-folder links (265) become `relates-to` links. The four open pull requests'
|
||||
issues (338, 341, 350, 363) are reserved as numbers and imported when they merge.
|
||||
|
||||
**Consolidating** means four concrete passes, each producing a list for the operator or an agent to
|
||||
confirm, never applying itself:
|
||||
|
||||
1. **Close what is fixed.** A `located` or `open` issue whose `located-in` repository has a merged
|
||||
pull request naming its number is a candidate for `resolved`. hits's auditor (section 6) checks
|
||||
exactly this against git and is the model.
|
||||
2. **Merge duplicates.** Candidates are pairs that link each other and share a `located-in`, and
|
||||
pairs whose titles share most words. A confirmed duplicate is closed `wontfix` with a
|
||||
`duplicates` link and the reason, keeping its number and folder.
|
||||
3. **Normalise `located-in`** onto the registered list (`mesh-controller`, `mesh-catalog`, the
|
||||
node-engine's repository, a module's name), keeping the file paths as a note.
|
||||
4. **Group the 73 not closed** by domain (the glossary's domains, ADR 0244) and by `located-in`, so
|
||||
the operator sees, for example, how many open issues the delivery domain carries.
|
||||
|
||||
## 4. Conditions, asks and deliveries
|
||||
|
||||
A condition is one open fact, raised and cleared only by observation (ADR 0231); an issue is a
|
||||
question someone must answer. They are different things, and a condition must not be closed by
|
||||
closing an issue. But a condition can say that a fix is owed: five of today's ten are `healer-wanted`,
|
||||
and one silence says "hq issue to follow".
|
||||
|
||||
Recommended for a later slice (slice 4): an issue links a condition by its key; the controller shows
|
||||
the link on the condition; and for `healer-wanted` the controller opens one issue per condition key
|
||||
when it first raises it, linked both ways, instead of an agent remembering to. A silence whose reason
|
||||
names an owed issue should carry its number. Asks
|
||||
([ADR 0259](../../02-DECISIONS/0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md))
|
||||
stay with the router: the tracker asks nothing in v1. Deliveries relate through pull requests: when
|
||||
the forge says a pull request merged, the tracker notes it on every issue the pull request names, and
|
||||
offers `resolved` (slice 4). Nothing in v1 depends on these.
|
||||
|
||||
## 5. How the operator sees issues
|
||||
|
||||
First through the mesh's tools: `list` returns rows short enough to read in a chat, `get` one issue
|
||||
whole, and every agent session reaches them through the mesh MCP server. The responder (`@mesh`,
|
||||
ADR 0234) answers from read verbs, so "what is open in delivery" works on a channel once the seat
|
||||
exists. Later a view onto the bus: the `issues` bucket watched over the bus (a browser reaches it through a WebSocket listener, which this effort did not check for),
|
||||
read-only, which the operator named as a future direction for every module's state. Nothing in v1
|
||||
blocks it, because the state is already a bucket and every change an event.
|
||||
|
||||
## 6. hits: what it is, and what to take from it
|
||||
|
||||
**What it is.** A headless issue tracker in Go (module `github.com/impire-io/hits`), with no web
|
||||
interface and no HTTP interface: NATS micro services on JetStream, a command line for people and a
|
||||
stdio MCP server for agents. One author, 81 commits between 2026-09-02 and 2026-09-14, release
|
||||
v0.7.0, about 9,700 lines of Go outside tests and 21 test files, tested against an embedded NATS
|
||||
server. Its model descends from a method like this repository's: a sibling `hits-hq` with numbered
|
||||
playbooks and decisions.
|
||||
|
||||
**Data model.** An *item* has a type (`bug`, `task`, `improvement`), a status (`open`, `diagnosing`,
|
||||
`located`, `blocked`, `resolved`, `wontfix`), a priority, `located-in` (from a registered list of
|
||||
*projects*), `fixed-by` (pull request, commit or action), `amended-design`, append-only notes, typed
|
||||
links (`duplicates`, `relates-to`), a claim, a block, and a tombstone for a filing mistake. Its
|
||||
statuses and fields are this repository's frontmatter almost key for key. Projects, *initiatives*
|
||||
(groups of projects that also scope the numbering) and *releases* are registered lists that are
|
||||
never reused once retired.
|
||||
|
||||
**How it stores.** The source of record is a stream `hits-ops` with subjects
|
||||
`hits.ops.item.<id>` (and `project`, `initiative`, `release`). Every write appends an operation,
|
||||
published with the per-subject expected last sequence, so two writers to one item cannot both win.
|
||||
A bucket `hits-state` holds the folded snapshot of each item, the registered lists and one counter
|
||||
per initiative. The counter is advanced by compare-and-set and an item is numbered only after it is
|
||||
validated, so a refused create spends no number. On start it rebuilds the bucket from the stream.
|
||||
|
||||
**Services and subjects.** One micro service `hits` with 23 endpoints under `hits.api.*` (`create`,
|
||||
`get`, `edit`, `transition`, `claim`, `release`, `block`, `unblock`, `link`, `unlink`, `note`,
|
||||
`tombstone`, and register, list and retire for projects, initiatives and releases); three index
|
||||
services, each a projection of the stream: full text (`hits.search.query`, a local index on disk),
|
||||
a graph (`hits.graph.neighbors`, `hits.graph.walk`) and an optional semantic search that needs an
|
||||
outside embedding provider.
|
||||
|
||||
**MCP tools.** 27, one per endpoint: `create_item`, `get_item`, `edit_item`, `transition_item`,
|
||||
`claim_item`, `release_item`, `block_item`, `unblock_item`, `link_items`, `unlink_items`,
|
||||
`note_item`, `tombstone_item`, the project, initiative and release tools, and `search_items`,
|
||||
`semantic_search`, `graph_neighbors`, `graph_walk`. One server serves one agent under one actor.
|
||||
Its command line also has an auditor that checks every item's `fixed-by` against git and finds
|
||||
merged pull requests whose items are still open.
|
||||
|
||||
| | Adopt as it is | Adapt to the mesh |
|
||||
|---|---|---|
|
||||
| Statuses, fields, append-only notes, typed links, tombstone | yes: they are already ours | — |
|
||||
| Stream of operations as the record, bucket as its projection | the pattern | the stream and bucket declared in the manifest and created by the controller (ADR 0201 §3), not created by the service on start |
|
||||
| Expected-sequence writes; compare-and-set counter; number only after validation | yes | needs compare-and-set in the state interface (section 1) |
|
||||
| The auditor | the idea, as a tool | reads the forge through the gitea module, not a local clone |
|
||||
| Subjects `hits.api.*`, its own MCP server | no | the seat's verbs, served by the tool runner and found with `mesh_search` |
|
||||
| Actor named by the caller | no | the caller is the bus credential the mesh issued |
|
||||
| Contexts, OAuth device flow, semantic search | no | the mesh issues credentials; no outside provider |
|
||||
| *item*, *project*, *initiative*, *release* | no | *issue*; a repository or module; no initiatives in v1; *release* is already a homonym here (glossary) |
|
||||
|
||||
**Reuse its code, or build on its model?** Its licence is the Sustainable Use License 1.0: use and
|
||||
modification are allowed for internal business, non-commercial or personal use, and distribution only
|
||||
free of charge and for non-commercial purposes. It is not an open-source licence. Running it on a
|
||||
personal mesh is allowed; vendoring it into the catalogue binds the catalogue to that licence for as
|
||||
long as the code is there. Its services create their own stream and bucket on start, which ADR 0201
|
||||
§3 forbids a module to do; its subjects carry no prefix and assume one tracker per bus account; its
|
||||
words clash with the glossary. Changing those means a fork of a two-week-old, single-author project.
|
||||
v1 here is the item store without the indexes: roughly the size of the module that delivers pull
|
||||
requests.
|
||||
|
||||
**Recommended: build our own module on hits's model,** and say so in the module's README. Do not
|
||||
depend on or vendor its code. Revisit only if its licence changes, or if its author agrees to a
|
||||
licence for this use.
|
||||
|
||||
## 7. Open questions for the operator
|
||||
|
||||
1. **Should the tracker hold every issue's number and status, while hq keeps a folder only for design
|
||||
and governance issues, pointing at the tracker by number (option (a) in section 2)?**
|
||||
Recommended: yes. It ends the collisions, keeps the public record, and moves the cycle rules into
|
||||
the write, where they refuse instead of report.
|
||||
2. **Should we build our own `issues` module on hits's model rather than run or vendor hits?**
|
||||
Recommended: build our own. hits's licence limits distribution, its services create their own bus
|
||||
resources (against ADR 0201), and its words clash with ours. Its model, its compare-and-set
|
||||
numbering and its auditor are worth copying.
|
||||
3. **Should the tracker also hand out decision and research numbers?** Recommended: yes, in slice 2.
|
||||
Decision numbers collided three times on 2026-10-07; the same counter mechanism serves any
|
||||
sequence, and the tracker then reserves the number when a branch starts.
|
||||
4. **Should the word stay *issue*, with the module named `issues` and *ticket* retired?**
|
||||
Recommended: yes. *Issue* is the glossary's word for this, and one word per thing (ADR 0244).
|
||||
5. **Should the controller open an issue by itself for a `healer-wanted` condition, or only link
|
||||
one an agent or the operator opened?** Recommended: link only, until slice 4 has run for a week;
|
||||
then open by itself for `healer-wanted`, one issue per condition key.
|
||||
|
||||
## 8. Slices after the first
|
||||
|
||||
| Slice | Delivers | Done when the operator sees |
|
||||
|---|---|---|
|
||||
| 1 | The `issues` module: open, get, list, move, note, link, import; compare-and-set in the state interface | the next issue number comes from the tracker and the 73 not closed are listed by one call |
|
||||
| 2 | Decision and research numbers from the tracker; playbook 03 and `cycle.py` changed; status keys removed from every report | two agents opening at once get two numbers, and no hq pull request is renumbered |
|
||||
| 3 | Consolidation: the four passes of section 3, and an audit tool for `fixed-by` against the forge | the not-closed list shrinks by what was already fixed or duplicated, each with its reason |
|
||||
| 4 | Conditions and pull requests linked; `healer-wanted` opens an issue | a condition shows its issue, and a merge notes the issues it names |
|
||||
| 5 | A read-only view onto the `issues` bucket | the operator reads issues in a browser without an agent |
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
---
|
||||
status: graduated
|
||||
initiated: 2026-10-10
|
||||
touches:
|
||||
- 02-DECISIONS/0019-how-this-repository-works.md
|
||||
- 02-DECISIONS/0080-the-development-cycle-is-checked.md
|
||||
- 02-DECISIONS/0153-the-record-is-read-by-a-module-and-the-console-lists-it.md
|
||||
- 02-DECISIONS/0248-the-decision-index-is-generated-when-it-is-read-and-never-stored.md
|
||||
- 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
|
||||
- 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
|
||||
- 03-DESIGN/01-to-be/53-the-issue-tracker.md
|
||||
- 00-META/process/
|
||||
- 00-META/checks/
|
||||
- 00-META/glossary.md
|
||||
- the records module's tools
|
||||
became:
|
||||
- 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
|
||||
---
|
||||
|
||||
# 045 — A knowledge base the mesh writes: decisions, guidelines, policies
|
||||
|
||||
## 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, 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. The operator later put the light content last, and decided that
|
||||
an issue's content belongs in the issue tracker rather than in this repository.
|
||||
|
||||
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)).
|
||||
Everything in it is written by hand as markdown and reaches `main` through a pull request; the hq checks
|
||||
in `00-META/checks/` judge it only after it is written. The issue tracker has already taken issues out
|
||||
of this path: it numbers and tracks them in a module of its own, and hq keeps only the narrative
|
||||
([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)).
|
||||
|
||||
## Why
|
||||
|
||||
Numbers collide, and the checks find a collision only after it happens. On 2026-10-10, research number
|
||||
043 was taken by one open pull request while a second session held an unpushed branch claiming the same
|
||||
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.
|
||||
|
||||
## The two options to weigh
|
||||
|
||||
- **A. Git stays the store.** The `records` module gains write verbs (propose, amend as a progressive
|
||||
insight, supersede, retire), each of which makes a branch and a pull request through the forge. Numbers
|
||||
come from the issue tracker's counters, as a further sequence beside `issue`
|
||||
([to-be 53](../../03-DESIGN/01-to-be/53-the-issue-tracker.md) §4).
|
||||
- **B. A store is the truth, and hq is its rendered public export**, as the issue tracker already is for
|
||||
issues (ADR 0275).
|
||||
|
||||
## The questions
|
||||
|
||||
1. **Types and lifecycles.** Which kinds of knowledge exist: decision, guideline, policy, design,
|
||||
playbook, and any others? What lifecycle does each have (proposed, accepted, superseded, retired;
|
||||
to-be and as-is for a design), and which transitions does each kind allow?
|
||||
2. **Numbering from one counter.** One sequence per kind, or one for all? How is a number reserved for
|
||||
a draft that is later abandoned, given that a number is never reused? How are today's collisions
|
||||
(043 is the latest example) resolved on import?
|
||||
3. **Typed links.** Which links between records are needed: supersedes, amends, implements, cites,
|
||||
decided-by, and others? Which of them does frontmatter express today (`became:`, `decisions:`,
|
||||
`fixed-by:`), and which exist only as prose links that no check reads?
|
||||
4. **Approval.** A decision or a policy changes how the mesh is run. Should accepting one require the
|
||||
operator's warrant on a channel that proves who answered, as a shared instruction section already
|
||||
does ([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))?
|
||||
Which kinds need it, and which may an agent write on its own?
|
||||
5. **Public and private knowledge.** Node names and operational knowledge have no home today. Does the
|
||||
knowledge base hold private records beside public ones, with a rule for which may be exported? How is
|
||||
a record checked so that nothing private reaches the public repository?
|
||||
6. **Checks as refusals at write.** `records.py`, `cycle.py`, `words.py` and `index.py` judge a pull
|
||||
request after it is written. Which of their rules can become refusals of the write verb itself, and
|
||||
which only make sense across the whole record?
|
||||
7. **Import.** How are the decision records (274 on `main` on 2026-10-11, numbered up to 0289), the designs and the playbooks imported without
|
||||
losing their history, their numbers or their links? Is the import repeatable, as the issue tracker's
|
||||
is?
|
||||
8. **What git gives today.** Review on a pull request, line comments, a history of every change with
|
||||
its author, a diff, a revert, and the forge's required checks. What of that would a store have to
|
||||
rebuild under option B, and what would option A lose by making every write a pull request?
|
||||
|
||||
## Words
|
||||
|
||||
The glossary has words for **decision record**, **design**, **playbook** and **the record** (the
|
||||
`records` module), but none for **guideline** or **policy** in this sense, and *policy* is already used
|
||||
for a module's **upgrade policy**. This effort uses "guideline" and "policy" as plain descriptions, and
|
||||
"knowledge base" for the whole, until a decision settles the words through the glossary's own rules.
|
||||
|
||||
## What it touches
|
||||
|
||||
How this repository works (ADR 0019) and how the development cycle is checked (ADR 0080), the
|
||||
`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; where the truth lives (the store
|
||||
for each record's structure and rules, this repository for its reasoning); issues whole in the issue
|
||||
tracker; the order of work; and what is still open.
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
# 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; section 1 is where the truth lives, which
|
||||
decides the rest; sections 2 to 9 answer the overview's questions and the operator's additions; section 10 is
|
||||
the order of work, and section 11 what is still open.
|
||||
|
||||
## 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. Later that day the operator widened the scope to **light records**
|
||||
(meeting notes, architectural drawings, blog posts) and then put them last; asked for a structured store of
|
||||
the decisions and research efforts; and decided that an issue's content belongs in the issue tracker, not in
|
||||
this repository.
|
||||
|
||||
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 (479 files): 951 files, and the glossary |
|
||||
| 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 on `main` (the 043 collision of the overview never reached it) |
|
||||
| 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 7) |
|
||||
|
||||
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. Where the truth lives: what a clean start would choose
|
||||
|
||||
The operator asked on 2026-10-11 which option this effort would choose with no prior setup. The answer
|
||||
decides the rest, so it comes first.
|
||||
|
||||
**The unit the mesh reasons about is a rule, not a file.** A decision is a handful of rules. A later decision
|
||||
changes one of them: ADR 0282 replaces one rule of ADR 0276 and leaves the others standing. Git and markdown
|
||||
know files only, so that change can be written only as prose. The earlier record keeps `accepted`, and every
|
||||
reader must read both records to learn what holds. Section 0's loose links all have this one cause: 21 partial
|
||||
supersessions with no reverse, 6 said only in prose, 6 markers no field agrees with.
|
||||
|
||||
**A store can hold what a repository cannot.** In a store, each rule is an entry with its own status and links
|
||||
("in force", "changed by rule 2 of 0282"). A write that leaves the record inconsistent is refused when it is
|
||||
made, not found by a check afterwards. Numbers come from one counter. "What holds now" is one query.
|
||||
|
||||
**What git does best is review of prose.** The reasoning behind a decision (its context, the options weighed,
|
||||
its consequences) is read and commented on by people. Agents rarely ask for it. They ask what holds.
|
||||
|
||||
So a clean start divides **by layer, not by kind**:
|
||||
|
||||
- **the store is the truth for the structure** of every governing record: its number, title, kind, topic,
|
||||
status, its rules one by one, and its typed links, at the level of the rule where a link is about a rule;
|
||||
- **this repository keeps the reasoning** as markdown under the store's number, reviewed in pull requests.
|
||||
|
||||
That is the division the issue tracker already made for 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)):
|
||||
the tracker holds number, status and links, and hq held the narrative. Section 9 takes issues one step further,
|
||||
on the operator's word: their narrative leaves this repository too.
|
||||
|
||||
Option A (git stays the truth, and a module's write verbs open pull requests, with numbers from a counter) was weighed and is not chosen. It keeps review, but it
|
||||
keeps the rule-level links in prose and the refusals after the fact, which is the cause of section 0's mess.
|
||||
Option B in full (the reasoning moves into the store too) is not chosen either: it would rebuild review, line
|
||||
comments, history and diff for prose, which git already gives.
|
||||
|
||||
## 2. Kinds and their lifecycles
|
||||
|
||||
| Kind | Lifecycle | Notes |
|
||||
|---|---|---|
|
||||
| decision | proposed → accepted → superseded; a rule can be changed or superseded on its own; a dated progressive insight corrects a fact | 274 records |
|
||||
| research | active → graduated or abandoned | 44 efforts |
|
||||
| design | proposed → designed → in-progress → implemented, in one of two layers (to-be, as-is) | 71 documents; a later slice (section 10) |
|
||||
| playbook | in force, or retired | 8, with no frontmatter today; a later slice |
|
||||
| glossary entry | in force, or retired with its replacement | one file today; a later slice |
|
||||
|
||||
The first slice holds decisions and research, the two the operator named.
|
||||
|
||||
A **guideline** or a **policy**, which the overview named, has no record of its 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)).
|
||||
No new kind is proposed for either.
|
||||
|
||||
**Light records** (meeting notes, drawings, blog posts) were added to the scope by the operator on 2026-10-11
|
||||
and put last by the operator the same day. They govern nothing, need no review to exist, and are private by
|
||||
default; a drawing's file belongs in 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))
|
||||
with a text description an agent reads. They are a later slice (section 10) and shape nothing in the first.
|
||||
|
||||
## 3. Numbering from one counter
|
||||
|
||||
The 16 concurrent collisions all come from reading the next number off a repository that many branches write
|
||||
at once. The issue tracker hands out numbers by compare-and-set on a counter key
|
||||
([to-be 53](../../03-DESIGN/01-to-be/53-the-issue-tracker.md) §4); the knowledge base asks it for every number.
|
||||
|
||||
- **One sequence per kind**: decision, research, and later design. Numbers keep their meaning in conversation
|
||||
("ADR 0276").
|
||||
- **A reserved number is spent.** A proposal that is abandoned keeps its number with status `withdrawn`, who
|
||||
reserved it and when. Gaps already exist (15 on `main`) and harm nothing; a reused number would.
|
||||
- **The counter starts above the highest number on `main` and on every open branch**, as the tracker's did.
|
||||
- **The counters stay where ADR 0275 put them.** Its rule 8 decided that the issue tracker hands out decision
|
||||
and research numbers too, in its second slice; to-be 53 §4 so far names only the issue counter. The knowledge
|
||||
base's `reserve` asks the tracker for the number, so one counter holds every sequence and no accepted record
|
||||
is superseded for it.
|
||||
|
||||
## 4. Rules and typed links
|
||||
|
||||
**A rule** is one short statement a decision makes, numbered within its record ("0276 rule 1"), with its own
|
||||
status: `in force`, `changed by` a rule of a later record, or `superseded`. 37 of 263 decision sections already
|
||||
write numbered rules with a bold lead (198 rules); the other 226 write prose, from which the import drafts the
|
||||
rules (section 7).
|
||||
|
||||
The links the first slice holds, each stored in both directions:
|
||||
|
||||
| Link | From → to | Today |
|
||||
|---|---|---|
|
||||
| supersedes | record → record | `supersedes` / `superseded-by`, 9 of 9 mirrored |
|
||||
| changes | rule or record → rule | `supersedes-in-part` on 15 records, one direction; 6 more only in prose |
|
||||
| extends | record → record | `extends` on 229, two spellings |
|
||||
| became | research → decision or design | `became` |
|
||||
| decided by | design → decision | `decisions` |
|
||||
| corrects | progressive insight → record | the dated marker, 55 in 39 records |
|
||||
| cites | any → any | prose links: 1,785 decision to decision, 469 decision to issue |
|
||||
|
||||
"What holds about X" is then: the rules matching X whose status is `in force`, each with its record and the
|
||||
changes that brought it to its present wording.
|
||||
|
||||
## 5. Approval
|
||||
|
||||
A decision governs how the mesh is built and run, so it needs a human approval before it holds.
|
||||
|
||||
- **Proposing** reserves a number and writes the structure with status `proposed`. Any agent may propose.
|
||||
- **Accepting** happens when the pull request carrying the record's reasoning merges with its human approval
|
||||
and both required checks. The knowledge base sees the merge on the bus and moves the record and its rules to
|
||||
`accepted` and `in force`, and every rule it changes to `changed by`. The merge is the warrant; a second
|
||||
approval beside it would split the evidence.
|
||||
- **A progressive insight** is a correction of fact and goes the same way: a pull request on the reasoning,
|
||||
and the structure recorded on merge.
|
||||
- A **structural write without a pull request** (a link added, a rule's wording fixed) is refused for an
|
||||
accepted record. Changing what an accepted record says is a new decision, as it is today.
|
||||
|
||||
## 6. Public and private
|
||||
|
||||
This repository is public and stays so. The reasoning of a decision or research effort stays here, public.
|
||||
The structure in the store is derived from public records and may be exported here as generated pages, like
|
||||
the decision index of [ADR 0248](../../02-DECISIONS/0248-the-decision-index-is-generated-when-it-is-read-and-never-stored.md),
|
||||
generated when read and never stored.
|
||||
|
||||
What changes is the issues' narrative (section 9): it moves into the tracker, which is the mesh's own and not
|
||||
public. The public repository loses those narratives. ADR 0275 kept them public on purpose, citing *the mesh
|
||||
remembers*; the tracker remembers them as well, but only for the mesh. Whether a resolved issue's narrative is
|
||||
ever exported publicly is a question for the decision that supersedes that part of ADR 0275.
|
||||
|
||||
Knowledge about this installation (one agent's 89 private notes, issue 367) stays out of scope. Agents' lessons
|
||||
and rules belong to the agent module's register (ADR 0273).
|
||||
|
||||
## 7. Checks as refusals at write, and the import
|
||||
|
||||
Of the 33 rules the hq checks enforce, **25 judge one record** and become refusals of the knowledge base's
|
||||
write verbs: a number taken twice, a supersession not mirrored, a cited record not accepted, a record without a
|
||||
topic, a research effort graduated without `became`. Two need a look beyond the record: a write that
|
||||
supersedes must check who cites what it supersedes. **4 judge the whole record** and **4 judge the prose**;
|
||||
those stay checks on this repository, run on every pull request. As frontmatter leaves this repository
|
||||
(section 8), the 25 leave `records.py` and `cycle.py` with it, and a check is added that a record's reasoning
|
||||
names a number the knowledge base holds.
|
||||
|
||||
**The import** reads this repository at a commit through the records module and writes each decision and
|
||||
research effort at its own number: status, topic, date, deciders, links, and its rules. Like the tracker's, it
|
||||
creates what is absent, never overwrites, never advances a counter, and a second run changes nothing and says
|
||||
so. Two things a reading cannot recover alone:
|
||||
|
||||
- **Loose links.** The 6 supersessions said only in prose, the 6 markers no field agrees with, the 47 bare
|
||||
`extends` targets and the 21 one-way partial supersessions are repaired in this repository first, by one
|
||||
pull request, so the import reads clean input.
|
||||
- **The rules of 226 decisions written as prose.** The import drafts them through 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 stores them as `drafted`, not `in force`. A topic's drafts are confirmed by the operator or a reviewer in
|
||||
one pass. An answer marks a drafted rule as drafted, and never presents it as the record's word.
|
||||
|
||||
## 8. What leaves this repository, and what stays
|
||||
|
||||
| | Today, in this repository | After |
|
||||
|---|---|---|
|
||||
| a decision's number, status, topic, links | frontmatter | the knowledge base; the file keeps the number in its name and heading |
|
||||
| a decision's rules | prose in the `Decision` section | the knowledge base; the section stays as prose for the reasoning |
|
||||
| a decision's context, options, consequences | markdown | unchanged |
|
||||
| a research effort's status and `became` | frontmatter | the knowledge base |
|
||||
| a research effort's documents | markdown | unchanged |
|
||||
| the decision index | generated from frontmatter when read | generated from the knowledge base when read |
|
||||
| an issue's report, diagnosis, resolution | `04-ISSUES/NNN-slug/` for 361 issues | the issue tracker (section 9) |
|
||||
|
||||
Frontmatter leaves a file only after the import has proven it holds the same values, one kind at a time, as
|
||||
ADR 0275 did for issues' status.
|
||||
|
||||
## 9. Issues live in the issue tracker, whole
|
||||
|
||||
The operator decided on 2026-10-11 that an issue's content belongs in the issue tracker, not in this
|
||||
repository. Measured on `main`: 361 issue folders, 1.9 MB; a folder's median is 4.4 KB and the largest
|
||||
25.9 KB, well under a tracker value's 256 KiB. Every folder has `00-report.md`; 107 have a diagnosis, 9 a
|
||||
resolution, 1 a progress file. Since ADR 0275, new issues live in the tracker already; the highest issue folder
|
||||
is 364.
|
||||
|
||||
What the tracker needs to hold it:
|
||||
|
||||
- **an issue's documents**: the report it already holds, plus a diagnosis and a resolution as named documents
|
||||
of the issue, each with its author and date, revised in place with history (notes stay append-only);
|
||||
- **an import** of the 361 folders, repeatable, keeping each issue's number and dates;
|
||||
- **links** from records: 250 files in this repository mention a path into `04-ISSUES/` 765 times, counted
|
||||
as every `04-ISSUES/NNN` path in the text (markdown links alone are fewer, about 660). Those mentions become
|
||||
plain "issue N" references that the knowledge base and the tracker resolve, rewritten in one pull request
|
||||
once the import is proven; the link check in `records.py` then refuses a new link into `04-ISSUES/`.
|
||||
|
||||
This supersedes part of ADR 0275 (hq keeps the narrative of a design or governance issue), so it needs its own
|
||||
decision record.
|
||||
|
||||
## 10. Slices
|
||||
|
||||
1. **Clean the input** (this repository, one pull request): repair the loose links of section 7, so the import
|
||||
reads clean records. In review as hq pull request 305, which declares every partial supersession in both
|
||||
records and adds the `partial-supersession` check. Beside it, a shared instruction section for every
|
||||
session: take a decision or research number above every one on `main` and on open branches until the
|
||||
counter exists, and name a partial supersession in a field, never only in prose.
|
||||
2. **The knowledge base, decisions and research**: a Go module serving one seat held once for the mesh, on
|
||||
the control-node beside the issue tracker. The import, the rules and links, and the answers; numbers come from the issue tracker (section 3):
|
||||
|
||||
| Verb | Answers |
|
||||
|---|---|
|
||||
| `ask` | the records and rules that bear on a question, ranked: number, kind, status, title, and whether each rule still holds or what changed it |
|
||||
| `get` | one record: its rules, its links both ways, what changed it since; its reasoning's text only when asked |
|
||||
| `holds` | for a topic or a record, the rules in force now, each with the record it comes from |
|
||||
| `reserve` | the next number of a kind, from the issue tracker's counter (section 3), spent whether or not the record lands |
|
||||
| `propose` | a new record's structure, status `proposed` |
|
||||
| `import` | this repository's decisions and research at a commit, repeatable |
|
||||
|
||||
Storage is a database in the store, provided to the module: the structure is small, but `ask` needs ranked
|
||||
full-text search, which the store's server does and a bucket does not. Every answer is bounded in size.
|
||||
3. **Frontmatter leaves this repository**, kind by kind, once the import is proven equal.
|
||||
4. **Issues whole in the tracker** (section 9): documents, import, links rewritten, folders removed.
|
||||
5. **Designs, playbooks and glossary entries** into the knowledge base the same way.
|
||||
6. **Light records**: notes, posts and drawings.
|
||||
|
||||
How a session reaches it: the knowledge base's tools reach every session through the mesh MCP server, and one
|
||||
shared instruction section, approved by ADR 0274's route, tells every session to ask the knowledge base what
|
||||
holds before reading files. A session needs this repository's folder only to write a record's reasoning.
|
||||
|
||||
Proved by the acceptance sentence at the top: the merge window question, asked from a session outside this
|
||||
repository, answered in one call under 4 KiB, naming ADR 0276's rules in force and the one ADR 0282 changed.
|
||||
|
||||
## 11. What needs the operator
|
||||
|
||||
Decided by the operator on 2026-10-11: the store is the truth for structure and this repository for reasoning
|
||||
(section 1); light records come last; issues live whole in the tracker (section 9).
|
||||
|
||||
Still open:
|
||||
|
||||
1. **Drafted rules (section 7)**: the 226 prose decisions get their rules drafted by the agent's judgement and
|
||||
confirmed a topic at a time. Who confirms: the operator, or an independent reviewing agent with the operator
|
||||
seeing a summary?
|
||||
2. **Issues' public narrative (section 6)**: once issues leave this repository, is a resolved design or
|
||||
governance issue ever exported here publicly, or does it stay the mesh's alone?
|
||||
|
||||
## Words
|
||||
|
||||
The glossary has **decision record**, **design**, **playbook** and **the record** (the records module). This
|
||||
effort proposes, for a decision to settle through the glossary's own rules: **knowledge base** for the module
|
||||
and its seat; **rule** for one statement a decision makes, with its own status; **governing record** for a kind
|
||||
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 2 finds no record of that kind.
|
||||
Reference in New Issue
Block a user