Files
hq/00-META/process/02-graduation.md
T
jschoubben a2da2a3e74
mesh/check checking a2da2a3e7451 on 87f2901f556b
mesh/delivery merged: source.main moved to novox/hq@87f2901f556b
Let the lead answer every design question against the principles
The operator replaced the instruction on implementing a design on
2026-11-11 about 21:48 CET: the lead answers each question met while
building in one line against the principles, and only one no principle
settles goes on, to the operator when it changes what they see or how
they work, removes data or needs their terminal, otherwise to the design
writer as a design line. Playbooks 02, 07 and 08, the glossary's design
question, AGENTS.md, the code reviewer and the drawn overview still said
only the operator or the design writer answers; they now say the rule.

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-11 23:53:03 +01:00

276 lines
21 KiB
Markdown

# Playbook 02 — Graduation and design change
**Trigger.** A research effort concludes, or an existing design must change.
**Who runs it.** Anyone, with the decision recorded before the design moves.
**Where a decision lives.** A decision record lives whole in the knowledge base, the seat `knowledge-base`,
reached through the mesh MCP server from any node and any folder (ADR 0290): its number, title, topic,
status, date, deciders, its clauses, its typed links, its reasoning and every version. This repository holds
none, and keeps no copy. What was decided is read with `knowledge-base.ask` (a question in plain words),
`knowledge-base.get` (one record by number; `reasoning: true` for its why) and `knowledge-base.holds` (the
clauses in force for a topic or a record).
## Graduating research
The effort's Direction, confirmed by the operator (playbook [01](01-research.md), step 7), is what
graduates. The lead writes the records and the design on the larger model; it is one sitting, bounded at
about an hour, and said to the operator if it runs past.
1. **Check it against GENESIS.** An effort graduates only if its conclusion is traceable to
[`mission.md`](../mission.md), [`context.md`](../context.md) and
[`effect.md`](../effect.md). If it conflicts, either the effort is wrong or GENESIS is —
say which, in writing, before proceeding.
2. **Record the decisions** (below, *Writing a decision record*): one record per question the effort
answers, holding that question, the options weighed and the one chosen. Most efforts answer one question
and graduate into one record; a second record is written only for a second question of its own, such as
how the change can be checked or delivered at all (the operator, 2026-11-06: an effort graduated into
eleven records where it answered two questions). The choices made while working out the design that
follows (a field, a tool, an event, a bound, the order of steps) are the design's: written in the design
with their reasons, under the record they follow from, never as records of their own. A clause of an
earlier record the decision changes is a `changes` link from the record, with one line saying in what.
How it is checked: the lead names, in the graduation's report to the operator, the question each record
answers; an effort graduating into more than two records is said to the operator with why, before the
records are proposed.
- **Write them together, not one after another.** Reserve every number first, then propose each record
as soon as it is written, without waiting for the review of the one before; the reviews run side by
side, and the operator's asks for the records that need them arrive together. A record that
`rests-on` or `extends` a sibling is proposed once that sibling is accepted.
- **Take the clauses from the confirmed direction** and cite the effort (`cites`, `"research NNN"`) for
the evidence instead of retyping its findings: a record's Context holds the few facts its decision
rests on, with the effort named for the rest.
- **Pre-check each record before proposing it**, as for research (playbook [01](01-research.md), step
5): every record, issue or design it names is in `links`; each deferral names its issue; each figure
is given as measured; no word on a glossary *Not:* line.
3. **Write the design.** **One design per thing** (the operator, 2026-10-16): when a to-be design already
covers what the decisions change, they rewrite that design, as *Amending an existing design* below says,
and no second design is written beside it that refers to it. Only for something no design covers, create
the document under `03-DESIGN/01-to-be/` with frontmatter:
```yaml
---
layer: to-be
status: designed
code: [] # owning code repo(s); set at build handoff, empty before
updated: YYYY-MM-DD
decisions:
- "ADR NNNN"
---
```
The design lists the direction's acceptance tests: what the build proves before it is done. Before it is
merged, the design is reviewed by architectural domain as playbook [01](01-research.md#review-by-architectural-domain) says, and
ends with its own *Reviewed by architectural domain* section; a design amended without an effort is reviewed the same way.
The words of the effort's Domains go into the glossary in the same change, each in its domain: a
word added gets its entry, a word whose meaning changed gets its entry rewritten, and a retired word moves to
its replacement's *Not:* line. A word that already means something else in another domain is named as a
homonym with the qualified form each domain uses.
4. **Hand it to the work breakdown.** The design goes on through playbook [04](04-build-handoff.md):
milestones, issues, and each milestone built as one feature step (playbook [07](07-feature-branches.md)).
5. **Close the effort.** `knowledge-base.close` the effort with `to: graduated`, a `became` link to each
decision record (`"NNNN"`) and the design document (its path), and a note of two or three sentences (what it
became, what carries it). The verb keeps the served text unchanged and adds a section *Graduated* with the note;
the knowledge base's review judges only the closing. Never close by proposing the effort again whole:
that is judged as a fresh proposal, so the approved reasoning is re-judged against the decisions that replace it
(on 2026-11-10 an effort closed that way met 5, then 11 findings on unchanged text; `close` was approved at once).
An effort that stops without a decision is closed `to: abandoned` with a `cites` link to what replaced it: the
knowledge base refuses `became` from a research effort to another research effort (its link-fits rule, design
55 § 2), so a replacing effort is cited, and `became` stays for the decision and the design an effort turned
into.
## Writing a decision record
**Before a number: what holds, and the mesh path, reviewed.** Ask the knowledge base what is already decided in
the record's area (`knowledge-base.ask`, `holds`), and name in the draft, for every interaction between modules the
record decides, the seat and verb, event, provision, state on the bus or manifest field that carries it. Then
`review-seams-and-tools` reviews the draft before it is proposed: a clause that has one module name another, read its
internals or be special-cased in another part, or puts a module's name into shared code, is a finding (the operator,
2026-11-03).
How it is checked: the record's References name the seams review's verdict; a record proposed without it is a breach
the lead names.
1. **Take a number.** `knowledge-base.reserve` with `kind: decision` and `for`: the record's title. The
number comes from the issue tracker's counter and is spent whether or not the record is accepted; one
never proposed is withdrawn after a week. Never pick a number by hand.
2. **Propose it.** `knowledge-base.propose` with the `number`, a one-line `title` in plain language, its
`topic` (one of the six of the reading order, [`02-DECISIONS/README.md`](../../02-DECISIONS/README.md)),
`date` (when the decision was taken, not when it was written down), `deciders`, and:
- `clauses`: what was decided, in order, each one statement opening with a bold lead
(`"**What is decided.** …"`);
- `sections`: the reasoning, in order: `Context` (what was true, with evidence), `Considered Options`
(numbered, each with why it was rejected), `Consequences` (what follows, including what got harder),
`How it is checked` (a rule states how it is checked), `References`;
- `links`: `extends` for a record it builds on, `rests-on` for a decision it stands on, `supersedes` for one it replaces whole, `changes` with
the clause it replaces part of (`"0276 §4"`, and `from` for the clause of this record that does it),
`cites` for any record, effort, issue or design it names;
- `homes`: the documents of this repository that cite it, such as the design's path;
- `needs-operator: true` when it holds only once the operator approves it.
State evidence, not assertion. *"Zero of 124 modules declare `brain` as a dependency"* outranks *"the
dependency rule is not followed"*. Record the options that were rejected — that is the half worth keeping.
3. **A record that puts work off** — a rename, a check, a case it does not handle — names the issue that
tracks it, in the sentence that defers it ("tracked by issue N"), or the deferral is not accepted: a
deferral nothing tracks reads as done
([issue 354](../../04-ISSUES/354-a-decided-rename-was-never-scheduled-and-the-operator-believed-it-live/00-report.md),
ADR 0244's code renames). `propose` refuses it (rule `deferral`).
4. **Review and acceptance.** `propose` refuses, naming every reason at once and writing nothing, a record
that breaks one of the rules that judge one record: a link to nothing, a clause without a bold lead, a
superseded record cited alone, an unknown topic, a retired word of the glossary, a daemon's line, a
deferral no issue tracks. The knowledge base then reviews the proposal itself, through a judgement that
sees only the record, the records it links and the rules, and answers `approve` or `changes`. On
`changes` the record stays proposed with the findings: revise it by proposing it again, whole, with `why`;
after three rounds the lead does not stop to ask, but fixes each further finding itself and proposes again
(the operator, 2026-10-18: ADR 0429 went past three rounds, each finding narrower than the last, and asking
first only added a wait). Only a finding that would change what was decided, rather than how the record
says it, goes to the operator, with a recommendation.
On `approve` it is accepted, or, when it says `needs-operator`, it waits for the operator's Approve on a
channel that proves who answered. Nothing proposed is in force. `knowledge-base.get` shows a record's
reviews and the operator's ask when it waits for one.
## Changing a decision
**A record's meaning is never rewritten.** A decision is changed by a new record, and a correction of fact
by a progressive insight.
- **Reversing a decision, changing its scope, rejecting an option it accepted, or making a consequence false
that a later record cites** is a new record that `supersedes` the old one whole, or `changes` the clauses
it replaces. On its acceptance the old record or clauses become `superseded` or `changed`, and every
answer says by what. The test is not how large the edit looks; it is whether a reader who acted on the
old text would now be wrong about *what was decided* rather than about *a detail the decision did not
rest on*.
- **A progressive insight** corrects a fact a record asserted that turned out wrong while the decision it
supports stays right: a count taken before anyone measured, a file named that does not exist. It is
`knowledge-base.propose` of the accepted record with `insight`: what was found, what the record said
before, and what it says instead. It is a new version, marked as one, dated, and reviewed like a
proposal; it adds and never quietly replaces; the decision, the options weighed and the consequences
stand untouched. If the correction changes what was decided, it is not an insight — write the new record.
- **Where a later record changes the mechanism an older one states** without reversing it, the later
record `changes` the older one's clause, so a reader who arrives at the older record by a citation sees
what changed it since.
## The shape of a design
A design is what its builders build from, and nothing else is (playbook [07](07-feature-branches.md)): decision
records and the mesh's principles are read when a design is written, amended or reviewed, and never again by the
prepare, the developers or the code review. So a design is written to be built without a choice of the builder's
own, and in pieces an agent can read whole. On 2026-11-10 one design of more than 400 KB was built in one
milestone: its agents read it by searching for pieces, filled what they did not find themselves, and an audit of
that day's 40 or so choices by the leads found seven against the records or the design and 29 questions the design
never answered, all found only in develop.
- **A main file and one milestone part per milestone.** The design's main file
(`03-DESIGN/01-to-be/NN-<slug>.md`) holds its frontmatter, its purpose, the whole shape (its parts, their seats,
events, provisions and state, drawn and in short prose), its acceptance tests and its *Milestones* section. Each
milestone not yet delivered has its **milestone part**, `03-DESIGN/01-to-be/NN-milestones/<milestone>.md`, which
holds every line that milestone builds and opens with frontmatter naming `layer: to-be`, the design, the
milestone and the `decisions:` its lines follow. A line lives in one place: a statement one milestone builds moves
from the main file into that part, never copied.
- **Bounds.** The main file at most 80 KB, a milestone part at most 60 KB. An agent reads both whole in under
40,000 tokens, under a fifth of what it can hold, and has the rest for the code. A milestone whose part would
pass 60 KB is two milestones (playbook [04](04-build-handoff.md)), each usable on its own.
- **Numbered design lines.** A milestone part's statements are numbered, each one thing to build with a bold
lead, like a decision's clauses, and cited as "design NN M §n"; a subtask, a commit and a review finding cite
them so. Each line names what its builder needs: the seat, verb or event, the field and its form, the key and
who deletes it, the bound, the caller, the tool that reads or steers it, and the fate of each thing that exists
today and changes. A line a builder would have to complete is a design question left open.
- **A delivered milestone's part stays.** It records what was intended, as a to-be design does once it ships
(the overview, *The two design layers*); no agent reads it again, so it costs no builder anything, and what runs is
written in the as-is design. The history of how a milestone was cut or why it waited is the issue tracker's and the
records', not the design's.
- **Design 47's next amendment is written in this shape**: the main file keeps the purpose, the whole shape, the
acceptance tests and the milestones, within 80 KB; every milestone gets its part with every line it builds or
built, moved from the main file, the one about to be built first; and the narrative of past milestones and their
prepare steps leaves the design for the issues it names. Every other design is put in this shape
at its next amendment, and a new design is written in it.
How it is checked: the reviewer of a design's pull request reads `wc -c` of the main file and of each milestone
part against the bounds, and that every statement of a milestone part is numbered; a check among hq's Go tests is to
be built (the cycle test reads only a design's main file today).
## Answering a design question
A design question (playbook [07](07-feature-branches.md), step 0) is first answered by the lead, in one line in the
milestone's lead-answers file, tested against the principles (`00-META/principles.md`) and naming the principle
that settles it, with no design batch and no review round (playbook 07, step 0, *Who answers a design question*; the
operator, 2026-11-11). The preparer, a developer and a reviewer answer none. Only a question no principle settles
comes to this section: the operator answers it when its answer changes what the operator sees or how they work,
removes data or needs the operator's terminal; every other one `hq-design-writer` answers as a design line of the
milestone part with its reason, under the record it follows from, read in item 3's round, and told to the operator in
one line. The lead asks the operator's as the instruction on asking says, one question per ask, with what the
milestone part says, what it leaves open, where it was met (file:line) and a recommendation. Then:
1. **Within a record's question** (a field, a bound, an owner, an order of steps, inside what a record decides), the
answer is the design's own choice: `hq-design-writer` writes it as a design line of the milestone part, citing
the operator's answer and its date and the record it follows from.
2. **Outside every record's question**, or **against a record** (the design contradicts a decision in force), the
answer is a decision: written first as *Writing a decision record* or *Changing a decision* above says, then as
design lines.
3. **The answers are reviewed together.** Before develop starts, the four reviewers by architectural domain read the
milestone part as amended, in one round (playbook [01](01-research.md#review-by-architectural-domain)); answers
met during develop are read by them in one round before the code review.
4. **They land on the milestone's branch.** The amendment is committed on hq's branch of the milestone
(`feat/<slug>`), so its pull request joins the milestone's delivery group, and the builders read the milestone
part at that branch's head.
How it is checked: every design question in the milestone file names the hq commit that answers it; a lead's answer
that names no principle, or a design line added during a milestone with no operator's answer or record behind it,
other than the writer's answer to one that changes nothing the operator sees or how they work, removes no data and
needs no terminal, is a finding of the review by architectural domain.
## Amending an existing design
A design changes only through a decision. A choice within what a decision decides (a field, a tool, an event,
a bound) is the design's own, written in it with its reason; it needs no record of its own. It is made when the
design is written or amended, never while it is built: a choice the design leaves to its builder is a design
question (above).
1. Write the decision record (above). If it reverses an earlier one, it `supersedes` it.
2. Edit the to-be design document, add the record to its `decisions:` as `"ADR NNNN"`, and set `updated:`
to today, keeping the design in the shape above (a line one milestone builds goes into that milestone's part).
A set of amendments across several designs (a milestone's findings, a graduation's) is written by the
agent `hq-design-writer` (`.claude/agents/`), started with a handover naming the designs, the records and the
branch. Review it by architectural domain before it is merged (playbook [01](01-research.md#review-by-architectural-domain)), and
rewrite its *Reviewed by architectural domain* section.
3. If the amendment came from an issue, give the issue the document path in the issue tracker:
`amended-design` on its `issue-tracker.move` to `resolved`, or `issue-tracker.link` with kind
`design` before then — never in the report's frontmatter
(ADR 0275).
## When something ships
Implementation state is a third axis, independent of both design and decision.
1. Write or update the matching document under `03-DESIGN/00-as-is/` so it describes what now
runs — including anything that shipped differently from the intent. A design that shipped
bent is an as-is fact, not a design amendment.
2. Set the to-be document's `status: implemented` and its `code:` to the owning repositories
from [`repos.md`](../repos.md).
3. `status: implemented` must be defensible from the owning repository's main branch, not from
intent. If it cannot be checked, it is `in-progress`.
## Do not
- Do not move a to-be document into `00-as-is/`. Write the as-is document; both stand.
- Do not edit an as-is document to describe an intention. That is what the to-be layer is for.
- Do not change a decision record's meaning. Supersede it. Correcting a fact it got wrong, while
the decision stands, is a progressive insight — marked and dated in the record, never silent.
- Do not write a decision record, or a copy of one, into this repository: the records test refuses a new path
under `02-DECISIONS/` other than its README.
## How it is checked
The rules on a record are the knowledge base's: `propose` refuses one that breaks a rule that judges one
record (its module's table test holds one case per rule), and the four rules that judge the whole record set
(an accepted decision cited by nothing, a supersession named by one side only, a changed clause nothing
changes, an accepted record extending a superseded one) run after every acceptance and raise a condition
when one fails. In this repository, the records test checks that a design's `decisions:` entries and every
"ADR NNNN" in the text are well formed, and that no record is written here; the index test checks the reading
order's six topics, which the knowledge base reads. A design's *Reviewed by architectural domain* section is read by the
reviewer of its pull request; nothing refuses a design without it yet. The three habits of graduating step 2 (side by side, clauses
from the direction, the pre-check) are the lead's, read by the reviewer; `propose` refuses a link to nothing,
a deferral no issue tracks and a retired word, and the review returns a record named but not linked.
The rounds are read in `knowledge-base.get` (its reviews, one per version): a question to the operator about a
record's wording after its third round is the failure of step 4 of *Writing a decision record*.