# Playbook 07 — Feature branches across repos **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). **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. ## The failure 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. ## The rule One feature is **one branch name**, **one worktree per repo**, **one MR per repo**, opened **once, at the end**. 1. **Name the feature once.** `feat/`. 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. 2. **Isolate each repo.** One git worktree per touched repo under `.work//`, branched off `main`: ``` git worktree add .work// -b feat/ origin/main ``` Parallel features never collide, and no shared checkout is edited. **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//` directory holding only the touched repos fails a bed at once with `no manifest for mesh-tools at …/.work//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//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. 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. 5. **Merge promptly, once approved.** Every merge into `main` is notified and approved ([ADR 0023](../../02-DECISIONS/0023-approval-is-the-checkpoint.md)); 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/` branch and no `.work/` worktree survive. ## 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. ## How it is checked The end state is visible, and its absence is the smell: - After a feature merges, `git branch -r | grep feat/` and `git worktree list` return nothing for it. A surviving branch or worktree means step 6 was skipped. - A bed run from `.work//mesh-lab` that fails naming a `.work///…` path it cannot find is a missing sibling worktree, not a mesh fault. - 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.