Playbook 07: a milestone has steps, runs the whole unit suite, writes its findings into its issues and watches on the smaller model; design 47 names milestone 2b and takes 895 into milestone 3 (issue 1053)
This commit is contained in:
@@ -35,12 +35,13 @@ A small fix (one repository, one issue, about an hour of work) follows
|
||||
## The shape
|
||||
|
||||
One feature is **one branch name**, **one worktree per repository**, **one pull request per repository**,
|
||||
opened **once**, after the review. It runs in five phases, and its time is bounded:
|
||||
opened **once**, after the review. It runs in five steps, and its time is bounded. A milestone has no phases
|
||||
(the operator, 2026-10-17): these are its steps, and a report names the step it is in:
|
||||
|
||||
| Phase | What happens | Bound |
|
||||
| Step | What happens | Bound |
|
||||
|---|---|---|
|
||||
| 0. Prepare | the lead settles the open questions and writes one context file per repository | 15 minutes |
|
||||
| 1. Develop | one fixing agent per repository builds every issue locally, unit tests only | the milestone's issues, 30 minutes each |
|
||||
| 1. Develop | one fixing agent per repository builds every issue locally, the whole unit suite before every commit | the milestone's issues, 30 minutes each |
|
||||
| 2. Review | one reviewer reads all of it; reports go both ways; at most 3 rounds | 15 minutes |
|
||||
| 3. Check | push; the forge's merge checks run the integration tests; no further review | one check run |
|
||||
| 4. Deliver | merge; the delivery plan builds, publishes and sends the whole feature | its delivery plan |
|
||||
@@ -57,10 +58,10 @@ built, no milestone of another design starts: its issues stay `open`, and nobody
|
||||
lead who finds another design's milestone already in `fixing` asks its owner before starting its own. A small
|
||||
fix ([playbook 08](08-small-fixes.md)) and an issue that is in no design's milestones are not held by this rule.
|
||||
|
||||
**Scope is fixed at phase 0.** An issue found during a feature goes to the next milestone or the next feature,
|
||||
**Scope is fixed at the prepare step.** An issue found during a feature goes to the next milestone or the next feature,
|
||||
never into the running one, unless it blocks the running one.
|
||||
|
||||
## Phase 0 — Prepare (the lead, larger model)
|
||||
## Step 0 — Prepare (the lead, larger model)
|
||||
|
||||
1. **Name the feature once:** `feat/<slug>`, the same branch name in every repository it touches. The
|
||||
branch is never protected. **One milestone is one branch per repository** (the operator, 2026-10-17), with one
|
||||
@@ -86,19 +87,27 @@ never into the running one, unless it blocks the running one.
|
||||
integration tests, which the forge's checks 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. **Move the issues to `fixing`**, `by` naming the feature's agent for that repository.
|
||||
5. **Write the findings into the issues** (the operator, 2026-10-17: the better the content of the issues, the
|
||||
better work the agents do, and the less review is needed). Before any agent starts, each issue carries, with
|
||||
`issue-tracker.note`: every file and test that touches the change, found by search and not from memory
|
||||
(file:line); how the change is checked and delivered end to end (which test proves its done-when, which
|
||||
modules its delivery plan moves, to which machines); and for a group, its merge order. The context file
|
||||
points to these notes; an issue reread by another session or a later agent then holds what was found.
|
||||
When the reading is large, it starts with a read-only survey agent on the smaller model.
|
||||
6. **Move the issues to `fixing`**, `by` naming the feature's agent for that repository.
|
||||
|
||||
## Phase 1 — Develop (one fixing agent per repository, smaller model)
|
||||
## Step 1 — Develop (one fixing agent per repository, smaller model)
|
||||
|
||||
- **One agent per repository, kept for the whole feature.** It reads its context file once and builds the
|
||||
issues one after another, committing each locally with a message naming the issue ("Keep the assignments
|
||||
on the bus (issue 652)"). It is not replaced per issue: the lead continues the same agent (by its id) with
|
||||
the next instruction, so its context is paid for once.
|
||||
- **Unit tests only, of what changed, each well under a second** (how-we-build §5, ADR 0391). Each issue's
|
||||
first test fails before its change and passes after; `gofmt`, `go vet`
|
||||
and the repository's unit tests stay green. The integration tests (`merge-check.sh` with the store and the
|
||||
bus) wait for phase 3.
|
||||
- **Nothing is pushed** and no pull request is opened in this phase. Never land on a red check: run the
|
||||
- **Unit tests only, each well under a second** (how-we-build §5, ADR 0391). **The whole unit suite runs before
|
||||
every commit** (the operator, 2026-10-17), not only the tests of what changed: it takes under a second, and a
|
||||
change breaks tests in packages it never touched. Each issue's first test fails before its change and passes
|
||||
after; `gofmt`, `go vet` and the whole unit suite stay green. The integration tests (`merge-check.sh` with the store and the
|
||||
bus) wait for the check step.
|
||||
- **Nothing is pushed** and no pull request is opened in this step. Never land on a red check: run the
|
||||
checks, read the result, then land in a separate step.
|
||||
- **The fixing agent's brief** (the lead gives it with the context file): name your issue in every step and
|
||||
message ("issue 805: landing in mesh-catalog"); reach the mesh only through the mesh MCP server, never ssh;
|
||||
@@ -116,13 +125,13 @@ never into the running one, unless it blocks the running one.
|
||||
tests pass; if another landed first, it merges again and repeats. In a shared clone, fetch the feature
|
||||
branch by name before branching from it. Never resolve a conflict with a blind `git merge-file --union`.
|
||||
|
||||
## Phase 2 — Review (one reviewer, larger model; at most 3 rounds, about 15 minutes)
|
||||
## Step 2 — Review (one reviewer, larger model; at most 3 rounds, about 15 minutes)
|
||||
|
||||
1. **Bring every feature branch up to the current trunk** (fetch by name, then merge), so the reviewed tree is
|
||||
the tree that is pushed.
|
||||
2. **One reviewer reads every repository's local commits** together, against the context files and the
|
||||
decisions. **It is one agent, kept for the whole release** like the fixing agents: the lead continues it by
|
||||
its id for every later round, for the extra cycle after a failed check (phase 3) and for the ready mark, so it
|
||||
its id for every later round, for the extra cycle after a failed check (step 3) and for the ready mark, so it
|
||||
reads the decisions, the issues, the context files and the commits once (issue 1042). A fresh reviewer per
|
||||
round or per mark pays for all of that again. Its report is per repository: each finding as file:line, the failure it causes, and the fix.
|
||||
It says which round it is in ("round 1 of at most 3").
|
||||
@@ -135,7 +144,7 @@ never into the running one, unless it blocks the running one.
|
||||
report, and the round does not wait for it. What a round asks is only what makes the change wrong against
|
||||
its issues and its decisions.
|
||||
|
||||
## Phase 3 — Check (no review)
|
||||
## Step 3 — Check (no review)
|
||||
|
||||
1. **Push every feature branch and open one pull request per repository, together.**
|
||||
The integration tests
|
||||
@@ -144,8 +153,8 @@ never into the running one, unless it blocks the running one.
|
||||
Where a session pushes through the forge tool `gitea_commit` (one commit on the forge's current base), the
|
||||
reviewer first confirms that commit's tree equals the reviewed one.
|
||||
2. **The forge's merge checks run the integration tests once** (`mesh/merge-gate`, `mesh/repo-check`). No
|
||||
second review: phase 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 phase 2 with
|
||||
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;
|
||||
@@ -172,7 +181,7 @@ then `mesh-delivery.recheck` the catalogue's and merge it on the new verdict. Su
|
||||
The exception ends when milestone 3 of design 47 is delivered (issue 977, ADR 0402, ADR 0403): the group's composed
|
||||
check, judged by the group's controller, is then each member's gate, and the feature is one group.
|
||||
|
||||
## Phase 4 — Deliver
|
||||
## Step 4 — Deliver
|
||||
|
||||
The merge starts the delivery plan: build, publish, send. A merge into a branch other than `main` is not a
|
||||
delivery: no machine receives it (issue 889 while it still starts one). The lead follows it to done
|
||||
@@ -184,10 +193,10 @@ survive.
|
||||
|
||||
| Who | Model | Why |
|
||||
|---|---|---|
|
||||
| The lead (phase 0 decisions, the context files, following and reporting) | larger | judgement |
|
||||
| The lead (step 0 decisions, the context files, following and reporting) | larger | judgement |
|
||||
| Read-only questions about the code for the context files | smaller | reading, answered with file:line |
|
||||
| Fixing agents (phase 1, and the fixing in phases 2 and 3) | smaller | building to a written context |
|
||||
| The reviewer (phase 2, the extra cycle in phase 3 and the ready mark; one agent, continued by its id) | larger | judgement, once per round |
|
||||
| Fixing agents (step 1, and the fixing in steps 2 and 3) | smaller | building to a written context |
|
||||
| The reviewer (step 2, the extra cycle in step 3 and the ready mark; one agent, continued by its id) | larger | judgement, once per round |
|
||||
| Decision records | larger | judgement |
|
||||
|
||||
Every agent the mesh runs draws on one weekly allowance shared by every session, and the larger model
|
||||
@@ -211,7 +220,8 @@ on, with when it started and its bound.
|
||||
**Every wait on the list has a watcher** (the operator, 2026-10-17). A session runs only when a message reaches
|
||||
it, so a check, a merge, a delivery plan, a record's review or the operator's Approve on a channel that lands
|
||||
while the lead's turn has ended wakes nobody: on 2026-10-17 an approved group sat half merged for 14 minutes
|
||||
unseen (issue 1032). For each wait the lead starts a watcher, an agent on the smallest model that changes nothing.
|
||||
unseen (issue 1032). For each wait the lead starts a watcher, an agent on the smaller model that changes nothing,
|
||||
never the smallest (the operator, 2026-10-17).
|
||||
It loops `mesh_wait` on the event families of what it watches (`mesh-delivery.transition` and
|
||||
`mesh-delivery.group` for a delivery, for example) with a timeout under 60 seconds, since the call itself ends near
|
||||
a minute. After every answer or timeout it reads the state from the verb that owns it (`mesh-delivery.show`,
|
||||
@@ -228,7 +238,7 @@ overview): every milestone of the design with its state, and under the running m
|
||||
their issues, each issue under the one it waits for, marked ✓ landed or delivered, ▶ fixing, ⏸ waiting, ✗ stopped:
|
||||
|
||||
```
|
||||
Feature <slug> · milestone <n> of <m> · phase <name>, <minutes used> of <bound> min
|
||||
Feature <slug> · milestone <n> of <m> · step <name>, <minutes used> of <bound> min
|
||||
Issues: <landed> of <total> landed · <fixing> fixing · <waiting> waiting
|
||||
|
||||
Design <nn> · <its title>
|
||||
@@ -253,7 +263,7 @@ Next: <the next actions up to the delivery, in order>
|
||||
**The short layout** (on a channel such as Telegram, or when nothing changed but time):
|
||||
|
||||
```
|
||||
<slug> milestone <n>/<m> · <phase> <used>/<bound> min · <landed>/<total> landed · past bound: <none | what> · needs you: <nothing | what> · week <n> %
|
||||
<slug> milestone <n>/<m> · <step> <used>/<bound> min · <landed>/<total> landed · past bound: <none | what> · needs you: <nothing | what> · week <n> %
|
||||
```
|
||||
|
||||
A report says what changed since the last one first. In the session every report is the full layout, the whole
|
||||
@@ -262,9 +272,9 @@ asking. The short layout is for a channel.
|
||||
|
||||
## The context of the lead's own session
|
||||
|
||||
At the end of each phase, and whenever the session's context grows large or spread over unrelated work, the
|
||||
At the end of each step, and whenever the session's context grows large or spread over unrelated work, the
|
||||
lead prepares a `/clear` as the mesh's instruction "prepare before clear" says: a save point with the
|
||||
feature's phase, its branches and heads, the context files' paths, the agents' ids, the wait list and the
|
||||
feature's step, its branches and heads, the context files' paths, the agents' ids, the wait list and the
|
||||
next action; then the prompt the operator pastes. The context files make the feature resumable after a clear.
|
||||
|
||||
## The design's state is written back
|
||||
@@ -277,7 +287,7 @@ moments, the same hour, an hq change going through [playbook 08](08-small-fixes.
|
||||
|
||||
- **The first milestone starts:** the design's `status: in-progress` ([playbook 04](04-build-handoff.md) step 7),
|
||||
if it is not already.
|
||||
- **A milestone's delivery plan is done:** its issues are resolved (phase 4), with `fixed-by` naming its pull
|
||||
- **A milestone's delivery plan is done:** its issues are resolved (step 4), with `fixed-by` naming its pull
|
||||
requests. The design's milestone entry is not changed: it names the milestone's issues, and whether they are
|
||||
delivered, when and by what is read from the issue tracker when it is asked, never copied into the design
|
||||
(issue 1038; AGENTS.md: cross-cutting views are generated when they are read).
|
||||
@@ -299,8 +309,16 @@ issues in `fixing` that nobody works on reads to the operator as stuck work.
|
||||
|
||||
- A feature's issues show their commits on the feature branch (`git log --grep 'issue <n>'`), and no pull
|
||||
request into a feature branch exists. A pull request per issue, or an agent waiting on a merge check in
|
||||
phase 1, is the failure this playbook prevents.
|
||||
step 1, is the failure this playbook prevents.
|
||||
- A context file exists per touched repository under `.work/<slug>/` while the feature runs.
|
||||
- Every issue of a running milestone has a note from the prepare step naming its files and tests (file:line), how
|
||||
it is checked and delivered, and for a group its merge order (`issue-tracker.get`); an issue moved to `fixing`
|
||||
without one is a prepare step skipped.
|
||||
- Every fixing agent's report gives the whole unit suite's result and time; a report naming only some packages'
|
||||
tests is the whole-suite rule not kept.
|
||||
- The lead's save point names each watcher with its model; a watcher on the smallest model is the failure of
|
||||
"Following and reporting".
|
||||
- A report or a save point that names a "phase" of a milestone is the old wording: a milestone has steps.
|
||||
- Every repository's own clone says `main` (`git -C <clone> branch --show-current`); another branch there is
|
||||
work done outside a worktree (issue 1010).
|
||||
- After a feature's delivery, `git branch -r | grep feat/<slug>` and `git worktree list` return nothing for it.
|
||||
@@ -323,7 +341,7 @@ issues in `fixing` that nobody works on reads to the operator as stuck work.
|
||||
- Every ready mark of a release names one reviewer (`mesh-delivery.show`, `ready.by`), and the lead's save point
|
||||
names one reviewer id per release; a second reviewer within one release is a reviewer not kept (issue 1042).
|
||||
- A milestone that adds or changes a module marked ready with no integration test that starts the module whole is
|
||||
the failure of phase 3's fourth step.
|
||||
the failure of the check step's fourth item.
|
||||
- A bed run from `.work/<slug>/mesh-lab` that fails naming a `.work/<slug>/<repo>/…` path it cannot find is a
|
||||
missing sibling worktree, not a mesh fault.
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ one delivery**. Everything before the push is local and fast.
|
||||
decision stays a small fix.
|
||||
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), phase 0 step 2). Write the
|
||||
test that fails today first; make the change; keep `gofmt`, `go vet` and the unit tests of what changed green
|
||||
(each well under a second; never a merge check or a database locally: how-we-build §5, ADR 0391).
|
||||
the repository's own clone, which stays on `main` (playbook [07](07-feature-branches.md), step 0, item 2). Write the
|
||||
test that fails today first; make the change; keep `gofmt`, `go vet` and the repository's whole unit suite green
|
||||
before every commit (each test well under a second; never a merge check or a database locally: how-we-build §5, ADR 0391).
|
||||
Commit, naming the issue. For a playbook or design edit, run the repository's own checks (in hq,
|
||||
`sh merge-check.sh`).
|
||||
4. **One review of the local commit, before anything is pushed** (a reviewer that did not write it, larger
|
||||
|
||||
Reference in New Issue
Block a user