Merge pull request 'Playbook 07 as five bounded phases with reused context; playbook 08 for small fixes' (#364) from playbooks/07-08-fast-flow into main
This commit was merged in pull request #364.
This commit is contained in:
@@ -56,7 +56,8 @@ the expensive half.
|
||||
| [04](04-build-handoff.md) | Build handoff | A design is ready to be built |
|
||||
| [05](05-constitution-sync.md) | Constitution sync | `how-we-build.md` changed a rule the mesh enforces |
|
||||
| [06](06-writing-a-module.md) | Writing a module | Something that runs today must run on the mesh |
|
||||
| [07](07-feature-branches.md) | Feature branches across repos | Work that changes code, in one repo or several at once |
|
||||
| [07](07-feature-branches.md) | Features | Work that changes code across issues or repositories: prepared context, local development, one review, one check, one delivery |
|
||||
| [08](08-small-fixes.md) | Small fixes | One issue in one repository, about an hour of work: one review, one push, one delivery |
|
||||
|
||||
## The cycle is checked
|
||||
|
||||
|
||||
@@ -1,244 +1,213 @@
|
||||
# Playbook 07 — Feature branches across repos
|
||||
# Playbook 07 — Features
|
||||
|
||||
**Trigger.** Work that changes code — in one code repo or in several at once (`mesh-sdk`,
|
||||
`mesh-controller`, `mesh-catalog`, `mesh-host`, `mesh-lab`, and `hq` when a decision rides along).
|
||||
**Trigger.** A feature: work that changes code in one repository or several (`mesh-sdk`, `mesh-controller`,
|
||||
`mesh-catalog`, `mesh-host`, `mesh-lab`, and `hq` when a design rides along), too large to be one small fix.
|
||||
A small fix (one repository, one issue, about an hour of work) follows
|
||||
[playbook 08](08-small-fixes.md) instead.
|
||||
|
||||
**Who runs it.** Anyone who writes code, engineers and agents alike. Agents follow it exactly —
|
||||
it is the guard against the failure it was written for.
|
||||
**Who runs it.** Anyone who writes code, engineers and agents alike. Agents follow it exactly.
|
||||
|
||||
## The failure it prevents
|
||||
## The failures it prevents
|
||||
|
||||
A feature was worked as a branch-and-MR per *unit of thought* — one per decision, one per
|
||||
stacked increment — and each MR was treated as finished when it was *opened*, not when it was
|
||||
*merged*. Across repos the same feature took a different branch name in each. The MRs piled up
|
||||
unmerged: one session left **sixteen** stacked intermediate MRs that had to be consolidated and
|
||||
closed by hand. An MR is a review checkpoint, not a scratchpad.
|
||||
- **Pull requests as scratchpads.** A feature worked as one pull request per unit of thought left sixteen
|
||||
stacked pull requests unmerged, consolidated by hand afterwards. A pull request is the end of a feature,
|
||||
not a step in it.
|
||||
- **Waiting on checks mid-feature.** A feature worked as one pull request per issue into protected
|
||||
branches spent most of a day waiting for merge checks while the code was ready.
|
||||
- **Context bought again and again.** A fresh agent per small issue spends most of its run reading the
|
||||
playbook, the issue and the code before it writes a line. On 2026-10-14 an issue sized for five to ten
|
||||
minutes took forty-one.
|
||||
- **Finished work that never ships.** A feature that kept taking new issues held thirteen landed issues
|
||||
undelivered for a day: an issue done at 21:09 was still not on the machines at 15:00 the next day.
|
||||
- **Work that waits and nobody notices.** Most lost time was not work at all, but a check, a delivery plan
|
||||
or an agent waiting on something that had stopped, unseen.
|
||||
|
||||
It failed the other way too. A large feature was worked as one pull request per issue into protected
|
||||
integration branches, each waiting for the forge's merge check, again whenever another merge moved the
|
||||
branch, and for a review. Most of a day went to waiting on checks while the code itself was ready.
|
||||
## The shape
|
||||
|
||||
## The rule
|
||||
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:
|
||||
|
||||
One feature is **one branch name**, **one worktree per repo**, **one MR per repo**, opened
|
||||
**once, at the end**.
|
||||
| Phase | 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 | 1 to 2 hours |
|
||||
| 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 |
|
||||
|
||||
1. **Name the feature once.** `feat/<slug>`. The *same* branch name in every repo the feature
|
||||
touches — never a different name per repo, never a fresh branch per increment within the
|
||||
feature.
|
||||
A feature that cannot be developed in about two hours is split into **steps**. Each step runs all five
|
||||
phases on its own; the next step starts only when the previous step's delivery plan is done. A step is the
|
||||
unit that ships, so nothing finished waits for work that is not.
|
||||
|
||||
The feature branch is never protected and takes no pull request until step 4: a protected
|
||||
branch forces a merge check on every merge into it, which is the waiting this playbook avoids.
|
||||
**Scope is fixed at phase 0.** An issue found during a feature goes to the next step or the next feature,
|
||||
never into the running one, unless it blocks the running one.
|
||||
|
||||
2. **Isolate each repo.** One git worktree per touched repo under `.work/<slug>/<repo>`, branched
|
||||
off `main`:
|
||||
```
|
||||
git worktree add .work/<slug>/<repo> -b feat/<slug> origin/main
|
||||
```
|
||||
Parallel features never collide, and no shared checkout is edited.
|
||||
## Phase 0 — Prepare (the lead, larger model)
|
||||
|
||||
**Add the untouched siblings the lab reads.** The lab beds find the other repositories by
|
||||
sibling path from the lab checkout (`../mesh-tools/module.json`, `../mesh-sdk`, …), the way
|
||||
the main layout has them. A `.work/<slug>/` directory holding only the touched repos fails a
|
||||
bed at once with `no manifest for mesh-tools at …/.work/<slug>/mesh-tools/module.json`, after
|
||||
genesis has already passed. Give the directory those repos as **detached worktrees on `main`**
|
||||
— never symlinks:
|
||||
```
|
||||
git worktree add --detach .work/<slug>/mesh-tools main
|
||||
```
|
||||
3. **Commit as you go — locally.** Increments land on the one branch. Nothing is pushed and no
|
||||
MR is opened mid-feature.
|
||||
1. **Name the feature once:** `feat/<slug>`, the same branch name in every repository it touches. The
|
||||
branch is never protected.
|
||||
2. **Make the worktrees:** one per touched repository under `.work/<slug>/<repo>`, branched off `main`
|
||||
(`git worktree add .work/<slug>/<repo> -b feat/<slug> origin/main`). The lab beds find the other
|
||||
repositories by sibling path, so add the untouched siblings the lab reads as detached worktrees on
|
||||
`main` (`git worktree add --detach .work/<slug>/mesh-tools main`), never symlinks.
|
||||
3. **Settle every open question** in the feature's issues before any agent starts: on the issue, through
|
||||
the knowledge base, or by asking the operator. A fixing agent that meets an undecided design question
|
||||
stops, and its run is spent again.
|
||||
4. **Write one context file per repository**, `.work/<slug>/<repo>.context.md`. It is what a fixing agent
|
||||
reads instead of rediscovering the code, and it is reused by every agent and every round:
|
||||
- the issues it builds, in order, each with: the files and functions it changes, the decisions it builds
|
||||
with (quoted, with where each was decided), the test to write first, done-when in one sentence;
|
||||
- the repository's map for this feature: the packages and files involved, with one line each on what they
|
||||
hold, and the patterns to copy (file:line);
|
||||
- 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`), a throwaway database server if the store tests need one.
|
||||
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.
|
||||
|
||||
The unit of work is an **issue**. Each commit message names the issue it fixes, such as
|
||||
"Keep the assignments on the bus (issue 652)". No pull request, merge check, review or delivery
|
||||
per issue.
|
||||
## Phase 1 — Develop (one fixing agent per repository, smaller model)
|
||||
|
||||
4. **Finish, review, then publish.** When the whole feature is done — every repo, tests green —
|
||||
each repository's change gets one independent review **of the local commits, before anything
|
||||
is pushed**. A push starts the forge's checks (building the modules and running every test, up
|
||||
to a quarter of an hour), so a review finding fixed after a push costs another full run. The
|
||||
reviewer reads the feature worktree. Once the review approves, push every branch and open
|
||||
**one MR per touched repo**, together; the checks run once, on those MRs, and the feature is
|
||||
delivered as one delivery plan. MRs in two or more repositories that share the branch name are
|
||||
one delivery group (ADR 0239 §2); a feature in one repository is one delivery. A small change
|
||||
outside a feature (a playbook, a design) goes the same way: review the local commit, then push
|
||||
once.
|
||||
- **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.** 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
|
||||
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;
|
||||
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. Report back in under 150 words: commits, tests added and that they failed first, the
|
||||
check results, anything you stopped on.
|
||||
- **An agent that finds the code differs from its context file stops and reports** (file:line); the lead
|
||||
settles it, updates the context file, and continues the agent.
|
||||
- **Two repositories that depend on each other** keep their order in the context files: the reader before the
|
||||
writer, the controller's new manifest word before the catalogue manifest that uses it.
|
||||
- **Several agents in one repository** (only for a large repository with independent areas): each works on a
|
||||
local branch of its own from the feature branch's head and lands by fast-forward under a lock
|
||||
(`flock <feature worktree>.lock git -C <feature worktree> merge --ff-only <its branch>`), after its unit
|
||||
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`.
|
||||
|
||||
**One exception: a catalogue change that uses a new manifest word.** The catalogue's merge check
|
||||
reads manifests with the controller the mesh runs — the delivered one, not `main` and not the
|
||||
group's own branch — so such a feature is delivered in two steps, controller first: merge and
|
||||
deliver the controller's pull request, then ask `mesh-delivery.recheck` for the catalogue's, and
|
||||
merge it on the new verdict.
|
||||
## Phase 2 — Review (one reviewer, larger model; at most 3 rounds, about 15 minutes)
|
||||
|
||||
5. **Merge promptly, once approved.** Every merge into `main` is notified and approved
|
||||
(ADR 0023); once it is, merge —
|
||||
do not leave it sitting. The branch is deleted on merge.
|
||||
6. **Leave nothing behind.** After the MRs merge, no `feat/<slug>` branch and no `.work/<slug>`
|
||||
worktree survive.
|
||||
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. 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").
|
||||
3. **The report goes to the same fixing agents** that wrote the code, continued by their ids, so they fix
|
||||
with the context they already hold. Each answers the reviewer: what it changed, per finding, or why not.
|
||||
4. **The reviewer reads the answers and the new commits**, and approves or reports again. From round 2 it
|
||||
asks changes only for a finding that makes the feature wrong; smaller points become issues of their own.
|
||||
After round 3 the lead stops and brings the operator what is left, with a recommendation.
|
||||
|
||||
## Working one feature with several agents
|
||||
## Phase 3 — Check (no review)
|
||||
|
||||
A large feature (a design's whole work) is fixed by several agents at once. The **lead** is the
|
||||
session that runs the feature: it holds the feature branch, sends an agent per issue, and pushes,
|
||||
reviews and delivers at the end. The agents never push.
|
||||
1. **Push every feature branch and open one pull request per repository, together.** 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
|
||||
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 reviewer with the failure, for **one more cycle** of phase 2 with
|
||||
the same fixing agents; then push once again.
|
||||
4. **Mark each pull request ready** (`mesh/ready` and a comment `ready at <full sha>`) once the operator's word
|
||||
for the feature is given; mesh-delivery merges it when its checks pass (ADR 0364).
|
||||
|
||||
- **One feature worktree per repository, held by the lead.** Each agent works on a local branch of
|
||||
its own, in a worktree of its own, branched from the feature branch's current head.
|
||||
- **Land by fast-forward, under a lock.** An agent brings its branch up to the feature branch,
|
||||
runs the repository's tests and `merge-check.sh` in its own worktree, then fast-forwards the
|
||||
feature branch under a lock (`flock <feature worktree>.lock git -C <feature worktree> merge
|
||||
--ff-only <its branch>`). If another agent landed first, it merges again and repeats.
|
||||
- **The lead decides, a fixing agent builds.** Before an issue goes to an agent, the lead reads it and
|
||||
the code it touches, finds every open question and settles it: decided on the issue, through the
|
||||
knowledge base, or by the operator. An agent that meets an undecided design question stops, and its
|
||||
whole run is spent again when it restarts. The issue the agent gets then says, in its own text:
|
||||
- the repository and the files it changes: one repository and one change, sized so an agent finishes in
|
||||
five to ten minutes. The repository's own check is a floor under that: mesh-controller's, with its
|
||||
store, took 6 minutes 51 seconds on 2026-10-15 (the merge check of mesh-controller #342). A change that needs readers in one repository before a writer in another is two issues,
|
||||
the second depending on the first, not one agent through three repositories: each extra repository
|
||||
means merging the feature head and running every check again while other agents land;
|
||||
- the decisions it builds with, quoted, never "read notes 8 to 12";
|
||||
- the test to write first, which fails before the change;
|
||||
- its done-when, in one sentence;
|
||||
- what it must not touch, and what is landing beside it.
|
||||
An agent that finds the code differs from its issue stops and reports; it does not design around it.
|
||||
- **Spend the operator's allowance on judgement.** Every agent the mesh runs draws on one weekly
|
||||
allowance shared by every session, and the larger model (Opus) spends it many times faster than the
|
||||
smaller one (Sonnet). Fixing agents and read-only diagnosis agents run on Sonnet. The larger model is
|
||||
for the lead's own judgement, the independent review of each repository before the push, and
|
||||
decision records, and as few of its subagents as possible.
|
||||
- **Up to five Sonnet agents at once, at most two subagents on the larger model** (the lead not counted).
|
||||
What sets the limit is how many agents the lead can settle and follow, and their token cost, not the
|
||||
number of issues: an issue may take one agent or several, one after another. When one lands, the next ready
|
||||
issue starts at once; an issue is ready when every issue its `depends-on` links name has landed on the
|
||||
feature branch and the lead has settled its open questions. (Five agents on the larger model at once,
|
||||
with restarts, spent a week's allowance in a night.)
|
||||
- **An issue partly done goes back to `open`** with a note naming the commits that landed and what
|
||||
is left, linked `depends-on` to what it waits for. An issue is never left in `fixing` while
|
||||
nobody works on it. A finished issue's agent is gone, so the lead takes it over in `fixing` (its
|
||||
`by` names the lead) and keeps working it: for an agent that finished without committing, the lead
|
||||
commits, merges the feature head, runs the checks and lands it; for an agent that stopped on its
|
||||
stop rule, the lead settles the question first — then sends the issue again or lands it itself —
|
||||
or takes the question out of the feature as its own issue, saying on the issue which of the two it
|
||||
did. It is resolved, with `fixed-by` naming the feature's MRs, once the feature's delivery is done.
|
||||
- **Two issues in one file:** keep both sides' behaviour; where both added tests or list lines in
|
||||
one place, keep all of them. Never resolve code with a blind `git merge-file --union`: it can
|
||||
interleave two functions' braces. Build and test after every resolution.
|
||||
- **Fetch by name.** In a shared clone a plain `git fetch` may update only `main`. Fetch the
|
||||
feature branch with an explicit refspec before branching from it or comparing against it, or an
|
||||
agent merges a stale copy.
|
||||
- **Never land on a red check.** Run the checks, read the result, then land in a separate step; a
|
||||
command that checks and lands anyway is how a red branch lands. A manifest claiming a new seat or
|
||||
a new manifest word lands only after the controller change that understands it is delivered.
|
||||
- **Review the tree that is pushed.** Before the local review, bring each feature branch up to the
|
||||
current trunk (fetch by name, then merge or rebase), so the reviewed tree is the pushed tree.
|
||||
Where an agent session pushes through the forge tool `gitea_commit` (it puts one commit on a branch
|
||||
through the forge, as step 4's push), that commit is a new one on the forge's current base: the
|
||||
reviewer confirms the forge commit's tree equals the reviewed one before posting its verdict on the
|
||||
pull request.
|
||||
- **Three to five review rounds.** Tell every reviewer which round it is in ("round N of at most 5"): a
|
||||
reviewer that does not know keeps finding the next smaller thing. From round 3 it asks changes only for a
|
||||
finding that makes the change wrong, and lists smaller points as follow-ups that do not block. If it
|
||||
still asks changes at round 5, stop revising and bring the operator the findings with a recommendation:
|
||||
block, or follow as an issue of its own. The same holds for a decision record's review (issue 784).
|
||||
- **Report every ten minutes, and at once when something lands or needs the operator,** short, as a tree or a table: the issues done (of the total), each
|
||||
issue being fixed with its active time (minutes since its agent was sent, from a start time
|
||||
written down then, never guessed), the issues ready next, the ones waiting, and anything that
|
||||
needs the operator, and the allowance used (`anthropic-licence-manager.usage`: the week's and the
|
||||
session's share). Times are local and absolute.
|
||||
- **When this playbook meets a problem,** the lesson is added here, so the next feature avoids it.
|
||||
**One exception: a catalogue change that uses a new manifest word.** The catalogue's merge check reads
|
||||
manifests with the controller the mesh runs, so the controller's pull request is merged and delivered first;
|
||||
then `mesh-delivery.recheck` the catalogue's and merge it on the new verdict. Plan such a feature as two steps.
|
||||
|
||||
## The ready note
|
||||
## Phase 4 — Deliver
|
||||
|
||||
The form of what "The lead decides, a fixing agent builds" (above) asks the issue to say: a note on the issue
|
||||
headed exactly "Ready to build". If any line cannot be filled in, the issue is not ready.
|
||||
The merge starts the delivery plan: build, publish, send. The lead follows it to done
|
||||
(`mesh-controller.plans` with `wait` and `until: done`), then resolves the feature's issues with `fixed-by`
|
||||
naming its pull requests, and removes what is left: no `feat/<slug>` branch and no `.work/<slug>` worktree
|
||||
survive.
|
||||
|
||||
## Models
|
||||
|
||||
| Who | Model | Why |
|
||||
|---|---|---|
|
||||
| The lead (phase 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, and the extra cycle in phase 3) | 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
|
||||
spends it many times faster. Up to five agents on the smaller model at once, at most two subagents on the
|
||||
larger one (the lead not counted).
|
||||
|
||||
## Following and reporting
|
||||
|
||||
Most lost time is waiting nobody saw. The lead therefore keeps a **wait list**: everything the feature waits
|
||||
on, with when it started and its bound.
|
||||
|
||||
| Waiting on | Bound | Past the 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 the build queue (`mesh-controller.queue`) and the check's log |
|
||||
| a merge after ready | 5 minutes after the checks pass | 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` |
|
||||
|
||||
**Every ten minutes, and at once when something lands, stops or needs the operator,** the lead reports, in
|
||||
one of the two layouts below. Times are local and absolute; every number has its unit and its bound or
|
||||
baseline; an issue is named by its number and a few words, never by its number alone.
|
||||
|
||||
**The full layout** (in the session), the issues as a tree: grouped by repository, each issue under the one it
|
||||
waits for, marked ✓ landed, ▶ fixing, ⏸ waiting, ✗ stopped:
|
||||
|
||||
```
|
||||
Ready to build (<lead>, <time>).
|
||||
Repository: <one repository; an issue that needs another is split, the second depending on the first>.
|
||||
Files: <path:function or path, each>.
|
||||
Decisions it builds with: <quoted, one line each, with where each was decided>.
|
||||
First test: <name and what it asserts; it fails today because …>.
|
||||
Done when: <one sentence>.
|
||||
Do not touch: <files, behaviour, other issues' areas>; landing beside it: <issues>.
|
||||
Stop if: <the assumption the note rests on>.
|
||||
Feature <slug> · step <n> of <m> · phase <name>, <minutes used> of <bound> min
|
||||
Issues: <landed> of <total> landed · <fixing> fixing · <waiting> waiting
|
||||
|
||||
mesh-controller (agent: fixing, 2 of 3 landed)
|
||||
├── ✓ 652 assignments on the bus landed 14:02
|
||||
├── ▶ 736 placement words leave the layers fixing since 13:51, 23 of 30 min
|
||||
│ └── ⏸ 751 config keys named (mesh-catalog) waits for 736
|
||||
└── ✓ 654 a file names its template landed 13:20
|
||||
mesh-catalog (agent: waiting)
|
||||
└── ⏸ 751 (above, under 736)
|
||||
|
||||
Past its bound: <the wait, how long, what is being done> — or "none"
|
||||
Needs you: <one line per question, with my recommendation> — or "nothing"
|
||||
Allowance: week <n> % (<+d> since the last report), session <n> %
|
||||
Next: <the next action, one line>
|
||||
```
|
||||
|
||||
When the reading is large, a read-only agent on the smaller model reads the code and answers the lead's
|
||||
exact questions with file:line; the lead writes the note from its answers. The agent's prompt is then one
|
||||
paragraph: "Fix issue N of feature <name>. Follow playbook 07's agent brief; build exactly what the
|
||||
issue's ready note says." plus the feature's few local facts (below).
|
||||
**The short layout** (on a channel such as Telegram, or when nothing changed but time):
|
||||
|
||||
## The brief a fixing agent follows
|
||||
```
|
||||
<slug> step <n>/<m> · <phase> <used>/<bound> min · <landed>/<total> landed · past bound: <none | what> · needs you: <nothing | what> · week <n> %
|
||||
```
|
||||
|
||||
**Name your issue everywhere.** Begin every step, to-do item and message with the issue: "issue 805:
|
||||
landing in mesh-catalog", never "landing". The operator follows several agents at once.
|
||||
A report says what changed since the last one first; an unchanged table is not repeated, the short layout
|
||||
says it instead.
|
||||
|
||||
**Stop rule, the most important** ("The lead decides, a fixing agent builds", above): a decision the note
|
||||
does not give includes a new field, a new rule or a choice between two ways. Stop before writing code and
|
||||
report what and where (file:line). A stop costs minutes; building the wrong thing costs a review and a
|
||||
rebuild.
|
||||
## The context of the lead's own session
|
||||
|
||||
**Read the issue first,** its ready note first of all; read other notes, a design or a decision record only
|
||||
where the note points to them.
|
||||
|
||||
**Hard rules.** Reach the mesh only through the mesh MCP server; never ssh, never run `nox`. Never push,
|
||||
never open, merge or close a pull request: the lead does. Never write to a store's database by hand; a schema change
|
||||
is a numbered migration and the consolidated schema. Go only, unless the note says otherwise. Never move another issue; never edit files
|
||||
the mesh manages on a machine. Use the glossary's words; the unit of work is an issue.
|
||||
|
||||
**Steps.**
|
||||
1. Move the issue to `fixing` with `by` `<feature>-<issue>@<node>`. If it is refused, stop and report.
|
||||
2. Make your own worktree on a local branch `<feature>-<issue>` from the feature branch's head.
|
||||
3. Write the note's first test and see it fail. Make the change and see it pass; keep every other test
|
||||
passing.
|
||||
4. Commit: concise, imperative, about why, naming the issue.
|
||||
5. Merge the feature branch's head into yours. In a conflict keep both sides' behaviour and every test,
|
||||
then build again.
|
||||
6. Run the repository's checks in your worktree (`gofmt -l`, `go vet ./...`, `go test ./...`,
|
||||
`merge-check.sh`; where a test needs the store, a throwaway database server under the feature's
|
||||
scratchpad, stopped when done). Read the result. If anything is red, do not land.
|
||||
After every merge of the feature head, check again before landing.
|
||||
7. In a separate step, land by fast-forward under the feature worktree's lock. If it is not a
|
||||
fast-forward, go back to step 5.
|
||||
8. Note the issue: the commits and how its done-when is proven. Leave it in `fixing`.
|
||||
|
||||
**Fifteen minutes.** An agent still working after fifteen minutes tells the lead, in a few lines and
|
||||
without stopping, what has landed, what is left and whether part of it could be split off; the lead decides
|
||||
whether it goes on or is split.
|
||||
|
||||
**Report back,** in under 150 words: commits per repository, the tests added and that they failed first, the check
|
||||
results, and anything you stopped on or found that a later issue must know.
|
||||
|
||||
**The feature's local facts** (the lead gives them in the prompt or a short local file): the scratchpad and
|
||||
its worktrees, the feature branch's name, the lock files, and anything particular to the feature's
|
||||
repositories (a check that needs a gate built from another worktree, a test that is red at certain times).
|
||||
|
||||
**A shared machine's temporary directory can be filled by other sessions.** A test then fails with
|
||||
"disk quota exceeded", which is the machine, not the code: mesh-controller's `internal/builder` test
|
||||
`TestAGoProgramsBuildSourceIsItsImportClosure` fails when its temporary directory lies inside a git
|
||||
checkout such as the home. The local facts name a temporary directory for tests outside the home, and
|
||||
every check runs with `TMPDIR` set to it.
|
||||
|
||||
## What this is not
|
||||
|
||||
- **Not a licence to batch unbounded work.** A feature is a *bounded* unit; if it sprawls for
|
||||
days, end-of-feature bloat merely replaces per-increment bloat. Split it into features, each
|
||||
its own branch and MR.
|
||||
- **Not a second trunk.** Every repo branches off `main`. There is no longer an `initialization`
|
||||
trunk.
|
||||
At the end of each phase, 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
|
||||
next action; then the prompt the operator pastes. The context files make the feature resumable after a clear.
|
||||
|
||||
## How it is checked
|
||||
|
||||
The end state is visible, and its absence is the smell:
|
||||
- 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.
|
||||
- A context file exists per touched repository under `.work/<slug>/` while the feature runs.
|
||||
- After a feature's delivery, `git branch -r | grep feat/<slug>` and `git worktree list` return nothing for it.
|
||||
- More than one open pull request in a repository that share no feature name, or a feature step whose issues
|
||||
stay in `fixing` for more than a working day, is the smell: stop and bring it to the operator.
|
||||
- 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.
|
||||
|
||||
- After a feature merges, `git branch -r | grep feat/<slug>` and `git worktree list` return
|
||||
nothing for it. A surviving branch or worktree means step 6 was skipped.
|
||||
- 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.
|
||||
- A feature's issues show their commits on the feature branch (`git log --grep 'issue <n>'`), and no
|
||||
pull request into the feature branch exists. A pull request per issue, or an agent waiting on a
|
||||
merge check mid-feature, is the second failure above.
|
||||
- More than one open MR in a repo that share no feature name, or a stack of MRs none of which is
|
||||
merged, is the failure this playbook exists to prevent — stop and consolidate before opening
|
||||
more.
|
||||
When this playbook meets a problem, the lesson is added here, so the next feature avoids it.
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# Playbook 08 — Small fixes
|
||||
|
||||
**Trigger.** One issue in one repository, small enough to build in about an hour: a bug with a known cause,
|
||||
a missing check, a wording, a playbook or design edit. Anything larger, or anything that needs a change in a
|
||||
second repository first, is a feature and follows [playbook 07](07-feature-branches.md).
|
||||
|
||||
**Who runs it.** Anyone who writes code, engineers and agents alike.
|
||||
|
||||
## The aim
|
||||
|
||||
A small fix spends its time on the fix, and runs the long part once: **one review, one push, one check run,
|
||||
one delivery**. Everything before the push is local and fast.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Read the issue and the code it names** (the session's own model, or one read-only agent on the smaller
|
||||
model answering exact questions with file:line). If a design question is open, it is settled before any
|
||||
code is written: on the issue, through the knowledge base, or by the operator. A fix that turns out to
|
||||
need a decision or a second repository stops here and becomes a feature.
|
||||
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`. Write the
|
||||
test that fails today first; make the change; keep `gofmt`, `go vet` and the repository's unit tests green.
|
||||
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
|
||||
model; at most 2 rounds). The reviewer's findings go back to the same agent that wrote the fix, continued by
|
||||
its id, so the fix keeps its context. A playbook or design edit of a few lines may skip the reviewer: the
|
||||
operator's word on the pull request is its review.
|
||||
5. **Push once and open the pull request.** The forge's merge checks run the integration tests. A failed check
|
||||
goes back to the same agent with the failure, and the reviewer reads only the change it makes.
|
||||
6. **Mark it ready** (`mesh/ready` and `ready at <full sha>`) once the operator's word is given; mesh-delivery
|
||||
merges it when its checks pass.
|
||||
7. **Follow its delivery plan to done** (`mesh-controller.plans` with `wait` and `until: done`), prove the fix on
|
||||
the mesh (the symptom gone, measured), and resolve the issue with `located-in` and `fixed-by` the same hour.
|
||||
|
||||
## Bounds
|
||||
|
||||
| Waiting on | Bound | Past the bound |
|
||||
|---|---|---|
|
||||
| building the fix | 1 hour | it is a feature: stop and plan it under playbook 07 |
|
||||
| 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 after ready | 5 minutes after the checks pass | 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` |
|
||||
|
||||
A wait past its bound is said to the operator at once, with what is being done about it.
|
||||
|
||||
## Models
|
||||
|
||||
The fixing agent runs on the smaller model; the reviewer on the larger. A session fixing alone does the
|
||||
reading itself and uses one subagent only for the review.
|
||||
|
||||
## How it is checked
|
||||
|
||||
- A small fix has one pull request with one or few commits naming its issue, opened after its review: a pull
|
||||
request with many heads is a fix reviewed after its push.
|
||||
- Its issue moves to `resolved` within the hour its delivery plan ends.
|
||||
Reference in New Issue
Block a user