Files
hq/00-META/process/06-feature-branches.md
T
jschoubben cabe873503 Playbook 06 — one feature, one branch, one MR per repo
Records the branching-and-merging workflow for code changes across the mesh
repos, written against a failure it names: branches and MRs opened per unit of
thought, treated as done when opened not merged, and named differently per repo,
so they pile up unmerged — one session left sixteen to consolidate by hand. The
rule is one feat/<slug> shared across every repo a feature touches, isolated in
.work/<slug>/<repo> worktrees off main, pushed and opened as one MR per repo only
when the whole feature is done, then merged promptly. Adds the ground-rule
pointer in AGENTS.md and the row in the process overview.

Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
2026-09-05 03:40:39 +02:00

2.8 KiB

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); 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.