Playbooks 07, 08 and the overview name what runs: the checker's try and status, hq's Go tests, the stream backlog, and the way to deliver without the builder (issue 1888)

This commit is contained in:
2026-10-23 15:17:30 +02:00
parent 99fa8f0f09
commit c8ccbfe35f
4 changed files with 55 additions and 27 deletions
+1 -1
View File
@@ -71,7 +71,7 @@ The flow above is a rule, and a rule states how it is checked:
decision, an `in-progress`/`implemented` design that names no owning code, two issue folders
sharing a number or an issue report carrying a status key; a `graduated` research effort that
does not say what it became is refused by the knowledge base's `propose` (ADR 0290). Run it with `records.py`, `index.py` and
`words.py` before any HQ merge (`sh merge-check.sh` runs all four). The issue rules the check
`words.py` before any HQ merge (`go test ./...` at the root runs all four as Go tests, and `sh merge-check.sh` runs the Python ones until the delivery of R4g is done: ADR 0527). The issue rules the check
once held — `located` with an owner, `resolved` with a fix, a core issue with its replay — are
refused at the write by the issue tracker's `move`
(ADR 0275). What the checks cannot see — that code work actually started from a
+44 -16
View File
@@ -111,7 +111,7 @@ issue whether it is being fixed in between, after the delivery, or waits, and on
- what not to touch, and what lands beside it in other repositories;
- the local facts: the worktree, the branch, the check commands, a temporary directory for tests outside
the home (`TMPDIR`), and the unit tests to run (never a database server: tests that need one are
integration tests, which `mesh-controller.try` and the forge's checks run).
integration tests, which the try (`mesh-controller.try`) and the checker's merge check run).
When the reading is large, a read-only agent on the smaller model answers the lead's exact questions with
file:line, and the lead writes the file from its answers.
5. **Write the findings into the issues** (the operator, 2026-10-17: the better the content of the issues, the
@@ -173,7 +173,7 @@ issue whether it is being fixed in between, after the delivery, or waits, and on
acceptance criteria**: one test or more per criterion at the level it names, each test's comment citing
the criterion it proves by its label (`// 1118/AC2`), and no criterion left without its test; an integration criterion is a test
that compiles and waits for the try at this step's end. The integration tests (those that start a store, a bus
or a process) are run first by that try, and again by the forge's merge check.
or a process) are run first by that try, and again by the checker's merge check.
- **No pull request is opened in this step. When every issue is committed, the lead brings each feature branch up
to the current trunk (fetch by name, then merge), pushes it and tries it** (`mesh-controller.try`, as step 3 item 1 says), so the review reads the integration tests' real
results and judges none by reasoning (2026-10-19: a reviewer reasoned that a warning goes out at once, the
@@ -184,7 +184,7 @@ issue whether it is being fixed in between, after the delivery, or waits, and on
message ("issue 805: landing in mesh-catalog"); reach the mesh only through the mesh MCP server, never ssh;
never push, open, merge or close a pull request; never write to a store's database by hand, a schema change
is a numbered migration and the consolidated schema; Go only unless the context file says otherwise; never
move another issue; **never run an integration test on the machine** (no `go test -tags integration`, no `merge-check.sh`,
move another issue; **never run an integration test on the machine** (no `go test -tags integration`,
no store or bus started by hand): compile them with `go vet -tags integration ./...` and leave the running to
the lead's try at the end of this step, where `mesh-controller.try` runs them on the pushed branch. On 2026-10-17 three fixing agents ran them anyway, one for minutes on end, because the
brief only said they wait for the check (the operator). Report back in under 150 words: commits, tests added and that they failed first, the
@@ -236,11 +236,13 @@ issue whether it is being fixed in between, after the delivery, or waits, and on
1. **Push the reviewed heads, try again a head the review changed, then open one pull request per repository,
together.** **The integration tests run before the pull requests are opened**, first before the review (step 1)
and again for a head the review changed since its try: `mesh-controller.try` with the
repository and the pushed branch runs the repository's `merge-check.sh` (main's version) on the merge, in the
toolchain containers and against the throwaway store and bus a merge check gets, and answers with an id to
read back. A try that fails goes to step 3 item 3 as a failed check does; the pull requests are opened only
repository and the pushed branch is a check ask of the checker (ADR 0501 §5): the checker runs the repository's tests on the
merge with the trunk's head, at the unit and the integration level, through the build module of the repository's language and by
that language's convention, as the merge check does, and answers with an id to read back. The try is an ask on the language's check
stream (ADR 0525 §1), so it waits behind the asks before it until a build node has a free slot; no script of the repository decides
it (ADR 0445, ADR 0529). A try that fails goes to step 3 item 3 as a failed check does; the pull requests are opened only
when every head's last try passed (the operator, 2026-10-18: three pushes in a row failed their first merge check on
faults a try finds in minutes). Never `merge-check.sh`, `go test -tags integration` or a store or bus started
faults a try finds in minutes). Never `go test -tags integration` or a store or bus started
by hand on the machine (the operator, 2026-10-18). Pull requests in two or
more repositories that share the branch name are one delivery group (ADR 0239 §2).
Where a session pushes through the forge tool `gitea_commit` (one commit on the forge's current base), the
@@ -271,20 +273,21 @@ issue whether it is being fixed in between, after the delivery, or waits, and on
(also in a delivery group that holds the catalogue's pull request); the lead runs mesh-controller's unit
suite with `MESH_CHECK_BESIDE` naming a directory that holds the catalogue's branch, as mesh-controller's
`internal/beside` says.
2. **The forge's merge checks run the integration tests again, as the gate** (`mesh/merge-gate`, `mesh/repo-check`). No
2. **The checker's merge check runs the integration tests again, as the gate** (its one status, `mesh/check`). No
second review: step 2 reviewed this tree.
3. **A check that fails** goes back to the same reviewer, continued by its id, with the failure, for **one more cycle** of step 2 with
the same fixing agents; then push once again. **The failure is read from the check's whole log**, never
reasoned from its summary: `mesh-delivery.show` names the check's build id, and `mesh-controller.builds` with
`log` set to that id prints everything the builder said. A check's summary picks only some failing lines;
on 2026-10-17 it showed a store test's `FAIL` without its cause, and a fix was first guessed from the code.
**A change to `merge-check.sh` is judged by main's version of it**, so a test the change adds must pass under
either version: one that runs the new script's behaviour runs a file of its own, never `merge-check.sh` itself.
**So a change that needs the new script to judge it ships the script first, as a small fix of its own**, and the
rest waits for its delivery: on 2026-10-17 milestone 3 of design 47 moved its integration tests behind a build
tag in the same pull request as the script that runs that tag, and main's script would have skipped every
tagged test, its acceptance tests among them. The prepare step looks for this: a change to `merge-check.sh` or to
what it selects (build tags, the store-tests list) is cut ahead of the milestone.
**A change to the Go build module's recipe is judged by the build module the nodes run**, not by the changed one, so a
test the change adds must pass under either version. **A change that needs the new recipe to judge it ships the recipe
first, as a small fix of its own**, and the rest waits for its delivery: on 2026-10-17 milestone 3 of design 47 moved its
integration tests behind a build tag in the same pull request as the script that ran that tag, and main's script would
have skipped every tagged test, its acceptance tests among them. Since R4g no repository holds such a script (ADR 0529):
which tests run at which level is the build tag's (ADR 0445 §2), and hq's checks are Go tests like any repository's
(ADR 0527). The prepare step looks for this: a change to what the checker's build module selects (its recipe, a build
tag convention) is cut ahead of the milestone.
4. **The milestone's acceptance is proven by its check.** A milestone that adds or changes a module
carries an integration test that starts the module whole, its process against the real bus and store, and
shows the milestone's acceptance sentence; the forge's checks run it (ADR 0391 §1, §6). Unit tests alone are not
@@ -348,6 +351,31 @@ to one machine first, its plan read before the push and its apply read after it
answer, and `status` for a failed resource), and taken back at once when that machine cannot compose or apply, so
the machine keeps applying everything else; the other machines follow once it runs there.
## Deliver the controller, the builder or a build module without the builder
The builder delivers its own module, the build modules and the controller from its keys, and nothing falls back to another builder
(ADR 0524 §7). When the builder or a build module cannot write references, or a controller cannot take its own fix (issue 1886: the
controller's plan could never finish, and no plan it made could deliver its own fix), the way is ADR 0526's, in this order, each
step recorded in the hand-act log with its reason:
1. **Revert, with no build.** Revert the change that broke the builder or the build module: the earlier source's fingerprint has a done key naming
references, so the revert's delivery builds nothing. Read first that the artifact store still holds the earlier artifact
(`mesh-controller.artifacts`): it keeps a recorded build while it is among its module's five newest or a definition names it.
2. **A build by a session's call.** Call the build module's fetch and build tools on one named build node (for Go, `build_go_fetch` and then
`build_go_build` with `publish: true`); the build module pushes the artifact and answers its reference. `mesh-pack` in mesh-sdk gives a
hand build the build module's form; write the Go version of each hand build down, since another version gives another digest.
3. **Register by reference, at the controller's terminal only.** The operator names the module, its repository, its path and each artifact's
reference there; no verb reaches it. Say before you ask that this is a terminal step, and which notifications it raises; check that the
command exists on the node before you hand it over.
4. **A controller that cannot take its own fix** is put on the control-node by hand: register its hand build as in step 3, read the control-node's
plan, then `mesh-controller.push`. Only in the worst case does the operator send a declaration by hand at the terminal (its source and
digest the hand build's) and register it as in step 3 so the next push keeps it.
5. **Before a switch that moves the controller, the builder or a build module,** the lead keeps the running versions' artifacts outside the
artifact store, by digest on two nodes, with module, artifact, commit, Go version and the steps that put each back; the store's nightly
collection removes a blob the controller did not record.
Nothing here is a work-around for a delivery that can run normally: while the builder delivers, no hand act replaces it.
## Models
| Who | Model | Why |
@@ -371,7 +399,7 @@ on, with when it started and its bound.
|---|---|---|
| a fixing agent's issue | 30 minutes | ask it where it stands; split or take over |
| the review | 15 minutes a round | ask the reviewer; stop at round 3 |
| a merge check | 15 minutes | read `mesh-delivery.show` (its state and verdict), then the check's log; the build queue (`mesh-controller.queue`) never lists a running check |
| a merge check | 15 minutes | read `mesh-delivery.show` (its state and verdict), then the check's log; the check stream's backlog and the age of its oldest ask are in the delivery view (ADR 0525 §9) |
| the Approve's ask | 5 minutes after both checks pass | read `mesh-delivery.show`: an ask not raised is a fault, said to the operator |
| a merge after the Approve | 5 minutes | read `mesh-delivery.show` for the delivery |
| a delivery plan | its class's budget (`mesh-delivery.times`), at most 30 minutes | read `mesh-controller.plans`, then `mesh-delivery.stalled` |
+6 -6
View File
@@ -38,7 +38,7 @@ one delivery**. Everything before the try is local and fast.
decision stays a small fix. **The session's own model (the larger) then writes the issue's acceptance
criteria** as playbook [07](07-feature-branches.md) step 0 item 5 says: each one sentence, given, when, then,
naming the level of the test that proves it, as an `issue-tracker.note` headed `Acceptance criteria`. A
playbook or design edit has none: its check is `sh merge-check.sh`.
playbook or design edit has none: its check is `go test ./...` at hq's root, which runs the four checks (ADR 0527).
2. **Move the issue to `fixing`** with `by` as who@node.
3. **Build on a local branch** `fix/<issue>-<slug>`, in a worktree of its own branched from `main`, never in
the repository's own clone, which stays on `main` (playbook [07](07-feature-branches.md), step 0, item 2). Write the
@@ -50,7 +50,7 @@ one delivery**. Everything before the try is local and fast.
caught only by the review); read `git show --stat` before pushing.
The tests are written from the acceptance criteria, at least one per criterion at its level, each citing the
criterion it proves by its label (`<issue>/AC<n>`, playbook 07 step 0 item 5). Commit, naming the issue. For a playbook or design edit, run the repository's own checks (in hq,
`sh merge-check.sh`). Then push the branch and run `mesh-controller.try` on it, so the review reads the
`go test ./...` at the root). Then push the branch and run `mesh-controller.try` on it, so the review reads the
integration tests' real results; a failed try goes back to the same agent before the review.
4. **One review of the commit and its try** (a reviewer that did not write it, larger
model; at most 3 rounds, as playbook 07; from round 2 only what is wrong; it reads each acceptance criterion
@@ -60,13 +60,13 @@ one delivery**. Everything before the try is local and fast.
operator's Approve of its merge is its review, and the review record says so.
5. **Push the reviewed head, try it again if the review changed it, and open the pull request.** The trunk is what runs and nothing holds merged work back
(ADR 0401), so a fix waits for no other change's delivery. `mesh-controller.try` on the pushed branch runs
the integration tests, and the pull request is opened only when the head's last try passed; the forge's merge check runs
the integration tests, and the pull request is opened only when the head's last try passed; the checker's merge check runs
them again as the gate (playbook [07](07-feature-branches.md) step 3). They are never run on the machine. A
failed try or check goes back to the same agent with the failure, and the reviewer reads only the change it makes.
6. **The pull request's description carries the review record** (`Reviewed-by: <who@node> at <full sha>`,
playbook [07](07-feature-branches.md) step 3) and the session that pushed it (`Pushed-by: <who@node>`, ADR 0505 §5), and mesh-delivery asks the operator's Approve as soon as its
checks pass and merges the approved head (ADR 0421); nobody marks, labels, comments or rechecks. A fix to a module that changes how it runs carries an
integration test starting the module whole against the real bus and store, run by `mesh-controller.try` and the forge's checks
integration test starting the module whole against the real bus and store, run by `mesh-controller.try` and the checker's merge check
(ADR 0391 §1, §6); unit tests alone are not that proof, and the lab is not used. The operator's word is waited for only when the fix changes what the operator sees, removes data,
or needs the operator's terminal.
7. **Follow its delivery plan to done** (`mesh-controller.plans` with `wait` and `until: done`), prove the fix on
@@ -99,9 +99,9 @@ code.
| Waiting on | Bound | Past the bound |
|---|---|---|
| building the fix | 1 hour | it is a feature: stop and plan it under playbook 07 |
| a slot for the try | 30 minutes | `mesh-controller.try` holds at most four tries and refuses a fifth without queueing it: a watcher asks again every minute; past the bound, read `mesh-controller.queue` |
| the try | 30 minutes | a try is a check ask on the language's check stream and waits behind the asks before it for a build node's free slot (ADR 0525); past the bound, read the stream's backlog and the age of its oldest ask in the delivery view |
| the review | 15 minutes | ask the reviewer where it stands |
| the merge check | 15 minutes | read `mesh-controller.queue` and the check's log |
| the merge check | 15 minutes | read `mesh-delivery.show`, the check's log and the check stream's backlog in the delivery view |
| the Approve's ask | 5 minutes after both checks pass | read `mesh-delivery.show`: an ask not raised is a fault, said to the operator |
| the merge after the Approve | 5 minutes | read `mesh-delivery.show` for the delivery |
| the delivery plan | its class's budget (`mesh-delivery.times`), at most 30 minutes | read `mesh-controller.plans`, then `mesh-delivery.stalled` |
+4 -4
View File
@@ -302,7 +302,7 @@ code{font:12.5px ui-monospace,monospace;background:var(--soft);padding:1px 5px;b
<!-- ============ TESTS ============ -->
<h2 id="tests">When tests run</h2>
<p class="lead">Two levels. Unit tests run all the time on the machine; integration tests (a bus, a store or a process started) never run there: <code>mesh-controller.try</code> runs them on the pushed branch, and the forge's merge check runs them again as the gate.</p>
<p class="lead">Two levels. Unit tests run all the time on the machine; integration tests (a bus, a store or a process started) never run there: <code>mesh-controller.try</code> runs them on the pushed branch (a check ask on the language's stream), and the checker's merge check runs them again as the gate.</p>
<div class="box scroll">
<svg viewBox="0 0 1080 170" role="img" aria-label="Test levels over a feature's timeline">
<defs><marker id="ar3" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0L10,5L0,10z" fill="var(--mute)"/></marker></defs>
@@ -465,11 +465,11 @@ const P = [
{n:"07",name:"Features",kind:"build",c:"--build",
trig:"Work that changes code across issues or repositories, too large for a small fix.",
who:"A lead (larger model), one fixing agent per repository (smaller), one reviewer (larger).",
steps:["Prepare: name the branch, make the worktrees, settle every question.","Write one context file per repository.","Write the findings and acceptance criteria into each issue.","Survey every other reader and writer of each changed value. (new)","List every part the change reaches; copy fixtures from the real writer.","Develop: one agent per repository, one commit per issue.","A test fails first on behaviour, not on compiling. (new)","Bring each branch up to the trunk, push, and try it. (new)","Review all of it with the tries' results; at most 3 rounds.","Push the reviewed heads; try again only what changed.","Open one pull request per repository, together, with Reviewed-by and Pushed-by.","The operator's Approve on Telegram; the group merges in one pass.","Follow the delivery plan to done; resolve the issues; clean up."],
steps:["Prepare: name the branch, make the worktrees, settle every question.","Write one context file per repository.","Write the findings and acceptance criteria into each issue.","Survey every other reader and writer of each changed value. (new)","List every part the change reaches; copy fixtures from the real writer.","Develop: one agent per repository, one commit per issue.","A test fails first on behaviour, not on compiling. (new)","Bring each branch up to the trunk, push, and try it. (new)","Review all of it with the tries' results; at most 3 rounds.","Push the reviewed heads; try again only what changed.","Open one pull request per repository, together, with Reviewed-by and Pushed-by.","The operator's Approve on Telegram; the group merges in one pass.","Follow the delivery plan to done; resolve the issues; clean up.","When the builder cannot deliver its own fix: revert, a build by a session's call, a registration at the terminal, copies kept outside the store. (new)"],
prod:"One pull request per repository, one delivery plan, resolved issues, no branch or worktree left.",
next:"02 (when it ships)",bounds:"Prepare 15 min · 30 min per issue · review 15 min, ≤ 3 rounds · one try and one check",
prev:["Pull requests as scratchpads","Context bought again and again","Review rounds spent on what a run would show"],
check:"The forge's merge-gate and repo-check; the review record; the tracker's move."},
check:"The checker's one status, mesh/check; the review record; the tracker's move."},
{n:"08",name:"Small fixes",kind:"build",c:"--build",
trig:"One issue in one repository, about an hour of work.",
who:"The session, with one reviewer on the larger model.",
@@ -477,7 +477,7 @@ const P = [
prod:"One pull request, one delivery, a resolved issue.",
next:"—",bounds:"About an hour · one try before the review, one review, one check",
prev:["A fix reviewed after its pull request opened","A long part run twice","A fix waiting on someone else's delivery","Ten SDK merges and eight controller merges in a day, one per fix"],
check:"The forge's checks; the review record; the tracker's move; one delivery group and one delivery plan per milestone."},
check:"The checker's status; the review record; the tracker's move; one delivery group and one delivery plan per milestone."},
{n:"09",name:"Cleanup",kind:"side",c:"--side",
trig:"The operator asks, or merged branches, stale pull requests and old worktrees pile up.",
who:"A session on the operator's word; the operator decides every deletion.",