Playbook 06 — one feature, one branch, one MR per repo #22

Merged
jschoubben merged 1 commits from feat/feature-branch-workflow into main 2026-09-05 01:47:26 +00:00
3 changed files with 66 additions and 2 deletions
+1
View File
@@ -49,6 +49,7 @@ the expensive half.
| [03](03-issues.md) | Issues | Something is wrong — often with the owner unknown | | [03](03-issues.md) | Issues | Something is wrong — often with the owner unknown |
| [04](04-build-handoff.md) | Build handoff | A design is ready to be built | | [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 | | [05](05-constitution-sync.md) | Constitution sync | `how-we-build.md` changed a rule the mesh enforces |
| [06](06-feature-branches.md) | Feature branches across repos | Code changes, in one repo or several, need branching and merging |
## Status lives in frontmatter ## Status lives in frontmatter
+57
View File
@@ -0,0 +1,57 @@
# Playbook 06 — Feature branches across repos
**Trigger.** Work that changes code — in one code repo or in several at once (`mesh-sdk`,
`mesh-control`, `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/<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.
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.
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 0042](../../02-DECISIONS/0042-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/<slug>` branch and no `.work/<slug>`
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/<slug>` and `git worktree list` return
nothing for it. A surviving branch or worktree means step 6 was skipped.
- 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.
+8 -2
View File
@@ -6,8 +6,8 @@ today almost entirely those of **Novox Mesh**, its first product ([ADR 0028](02-
Before changing anything here, read the playbooks in Before changing anything here, read the playbooks in
[`00-META/process/`](00-META/process/) — every workflow (research, graduation, design [`00-META/process/`](00-META/process/) — every workflow (research, graduation, design
amendment, issues, build handoff, constitution sync) is documented there, and agents operate amendment, issues, build handoff, constitution sync, feature branches) is documented there, and
through them. Thin skills in `.claude/skills/` wrap these playbooks for invocation agents operate through them. Thin skills in `.claude/skills/` wrap these playbooks for invocation
(`hq-new-research`, `hq-graduate`, `hq-new-issue`, `hq-diagnose`, `hq-amend-design`, (`hq-new-research`, `hq-graduate`, `hq-new-issue`, `hq-diagnose`, `hq-amend-design`,
`hq-handoff`, `hq-sync-constitution`, `hq-status`); each defers to its playbook as `hq-handoff`, `hq-sync-constitution`, `hq-status`); each defers to its playbook as
authoritative and adds only the mechanical scaffolding. authoritative and adds only the mechanical scaffolding.
@@ -31,6 +31,12 @@ authoritative and adds only the mechanical scaffolding.
constitution page is derived from it — see playbook constitution page is derived from it — see playbook
[`05-constitution-sync.md`](00-META/process/05-constitution-sync.md). Never edit the [`05-constitution-sync.md`](00-META/process/05-constitution-sync.md). Never edit the
derived page directly. derived page directly.
- **One feature, one branch, one MR per repo.** A code change spanning one or more repos uses a
single `feat/<slug>` shared across every repo it touches, isolated in `.work/<slug>/<repo>`
worktrees off `main`; push and open MRs only when the whole feature is done, then merge
promptly and delete the branch. Per-increment branches and MRs that pile up unmerged are the
failure this prevents — see playbook
[`06-feature-branches.md`](00-META/process/06-feature-branches.md).
## This repository is public ## This repository is public