From 8eb58dbdbc98befba60522b5f5a80f802ca5d9a4 Mon Sep 17 00:00:00 2001 From: Emi Griffith Date: Sun, 2 Aug 2026 00:15:42 +0000 Subject: [PATCH] flow: squash into dev, fast-forward the promotions (#165) --- .claude/BRANCHING.md | 10 ++++++++-- .forgejo/workflows/pr-build.yml | 2 +- CLAUDE.md | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/.claude/BRANCHING.md b/.claude/BRANCHING.md index e602fbc..bef5ba2 100644 --- a/.claude/BRANCHING.md +++ b/.claude/BRANCHING.md @@ -71,8 +71,14 @@ correct" rather than erroring. is a divergence to reconcile deliberately, not to overwrite. 2. **`dev` is the default branch.** `forge_repo_settings(apply_flow_defaults=true)` — sets the default branch and - permits every merge style the chain uses, including `fast-forward-only`, plus - rebase-updates (without which the merge queue's core primitive 403s). + permits the merge styles the chain uses, plus rebase-updates (without which + the merge queue's core primitive 403s). + + The chain uses exactly two: **squash** for `feat/*` → `dev`, and + **fast-forward-only** for both promotions. Merge commits and rebase merges + are disabled deliberately — see the merge-style table in the root + `CLAUDE.md`. If `apply_flow_defaults` re-enables them, that is the tool + disagreeing with the policy, not permission to use them. 3. **Protection.** `forge_branch_protection(branch="dev", apply=true)`, then `main`, then `release`. diff --git a/.forgejo/workflows/pr-build.yml b/.forgejo/workflows/pr-build.yml index 578aa9d..8ac368d 100644 --- a/.forgejo/workflows/pr-build.yml +++ b/.forgejo/workflows/pr-build.yml @@ -19,7 +19,7 @@ name: PR build (required check) on: pull_request: - branches: [dev, main] + branches: [dev, main, release] concurrency: group: pr-build-${{ github.event.pull_request.number }} diff --git a/CLAUDE.md b/CLAUDE.md index f81e631..afa51e8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -22,6 +22,21 @@ every change, so a stale one is a correctness bug, not a documentation bug. `dev`, `main` and `release` are protected: **everything is a PR**, for humans and agents alike. Promotion is one PR per hop, `dev` → `main` → `release`. +**Merge style is part of the contract**, and Forgejo enforces it repo-wide — +it cannot scope styles per branch, so these are the only two enabled: + +| Hop | Style | +|---|---| +| `feat/*` → `dev` | **squash** | +| `dev` → `main`, `main` → `release` | **fast-forward only** | + +Merge commits and rebase merges are disabled. A promotion therefore never +creates a commit, which keeps `release ⊆ main ⊆ dev` true permanently: the +three branches hold identical history, never merely identical trees. Squashing +into `main` instead would strand `merge-base(dev, main)` and make every later +promotion re-apply work already there. Rebase-*updates* stay enabled — the +merge queue 403s without them. + `.claude/BRANCHING.md` is the orchestrator's runbook for that flow — the serialised merge queue, promotions, hotfix down-merges — and `.claude/ownership.md` is the module map saying which tasks may run