Say how several agents work one feature on one branch
mesh/merge-gate head c2d5323dea5a merged into trunk 21b79a04a283 — pass: the change touches no module of the mesh's graph
mesh/repo-check head c2d5323dea5a merged into trunk 21b79a04a283 — pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate head c2d5323dea5a merged into trunk 21b79a04a283 — pass: the change touches no module of the mesh's graph
mesh/repo-check head c2d5323dea5a merged into trunk 21b79a04a283 — pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
Feature 57 was first worked as a pull request per issue into protected branches and lost most of a day waiting on merge checks. Record the issue as the unit, a review and checks once at the end, landing by fast-forward under a lock, and the lessons met on the way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,10 @@ stacked increment — and each MR was treated as finished when it was *opened*,
|
||||
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.
|
||||
|
||||
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 rule
|
||||
|
||||
One feature is **one branch name**, **one worktree per repo**, **one MR per repo**, opened
|
||||
@@ -22,6 +26,9 @@ One feature is **one branch name**, **one worktree per repo**, **one MR per repo
|
||||
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.
|
||||
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.
|
||||
|
||||
2. **Isolate each repo.** One git worktree per touched repo under `.work/<slug>/<repo>`, branched
|
||||
off `main`:
|
||||
```
|
||||
@@ -40,14 +47,51 @@ One feature is **one branch name**, **one worktree per repo**, **one MR per repo
|
||||
```
|
||||
3. **Commit as you go — locally.** Increments land on the one branch. Nothing is pushed and no
|
||||
MR is opened mid-feature.
|
||||
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.
|
||||
|
||||
4. **Finish, then publish.** When the whole feature is done — every repo, tests green — push
|
||||
every branch and open **one MR per touched repo**, together.
|
||||
Each repository's change gets one independent review before its MR opens; the checks run once,
|
||||
on those MRs, and the feature is delivered as one delivery plan (the MRs share the branch name,
|
||||
so they are one delivery group, ADR 0239).
|
||||
|
||||
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.
|
||||
|
||||
## Working one feature with several agents
|
||||
|
||||
A large feature (a design's whole work) is fixed by several agents at once. The lead holds the
|
||||
feature branch; the agents never push.
|
||||
|
||||
- **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.
|
||||
- **At most five issues are being fixed at once.** When one lands, the next ready issue starts at
|
||||
once; the design's table of what waits for what says which are ready.
|
||||
- **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 stays in `fixing` until the feature's delivery, then is
|
||||
resolved.
|
||||
- **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.
|
||||
- **Report every ten minutes,** 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. Times are local and absolute.
|
||||
- **When this playbook meets a problem,** the lesson is added here, so the next feature avoids it.
|
||||
|
||||
## What this is not
|
||||
|
||||
- **Not a licence to batch unbounded work.** A feature is a *bounded* unit; if it sprawls for
|
||||
@@ -64,6 +108,9 @@ The end state is visible, and its absence is the smell:
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user