From bc40a65f65560ffff865b91588ff8028daee6703 Mon Sep 17 00:00:00 2001 From: Jakob Heuser Date: Wed, 29 Jul 2026 12:01:01 -0700 Subject: [PATCH] docs: require every OpenSpec proposal to declare its delivery shape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single PR, stacked merging forward, or stacked merging down — decided while writing the proposal rather than when the diff has already grown past reviewing. Prefer stacking, aiming under ~300 lines per diff. The forward/down distinction is one question: can each unit reach production alone without breaking anything? partition-rules-by-engine is the worked example — its first task group leaves 20 tests failing because the migration moves rules out from under readers that later groups update, so it can only merge down. Also drops "stacks are optional" from the opening, which now contradicts the preference stated below it. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CDv57zHq7abms3RReSQw6q --- CLAUDE.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index be85230f..4eb18065 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -68,7 +68,23 @@ The two rules that cause the most damage when missed: ## Stacked PRs -Committing a branch straight to `main` is the norm — stacks are optional. When PRs _do_ stack, the **stack-breadcrumb workflow** (`.github/workflows/stack-breadcrumb.yml`) keeps their cross-links and carried-forward bodies in sync automatically; there is no git-town or other stacking tool in the loop. Branch protection lives on `main` only (`Validate` required, `strict_up_to_date: true`, 0 required reviews); child branches are unprotected. When you do land a stack, follow these practices. +When PRs stack, the **stack-breadcrumb workflow** (`.github/workflows/stack-breadcrumb.yml`) keeps their cross-links and carried-forward bodies in sync automatically; there is no git-town or other stacking tool in the loop. Branch protection lives on `main` only (`Validate` required, `strict_up_to_date: true`, 0 required reviews); child branches are unprotected. When you do land a stack, follow these practices. + +### Every OpenSpec proposal declares its delivery shape + +The proposal states which of these the change is, and why. Decide it while writing the proposal, not when the diff has already grown too big to review. + +| Shape | When | How it lands | +| ---------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Single PR** | The whole change fits one reviewable diff. | Spec, implementation, and the archive land together. | +| **Stacked, merging forward** | Each unit is independently safe in production. | Each PR merges to `main` in turn; the last one archives the change. | +| **Stacked, merging down** | The units are only correct together — an intermediate state would ship a broken or half-migrated product. | Merge each PR **down** into its parent from the tip, then one protected merge of the bottom branch to `main`. The change reaches `main` atomically. | + +**Prefer stacking, and aim to keep an individual diff under ~300 lines.** A 900-line PR does not get reviewed, it gets approved. Tests count toward the total but never split from the code they cover — if a unit is oversized because of its tests, that is usually a sign the unit itself should be smaller. + +The deciding question between forward and down is only this: **can each unit reach production on its own without breaking anything?** If landing unit 1 alone would leave `check` broken, tests failing, or a migration half-applied, the answer is no and the stack merges down. Do not assume forward because it is tidier — verify it, since "each unit is safe" is a claim about behavior, not intent. + +Note how this interacts with the archive gate (see the OpenSpec archive check below): a change is archived exactly once, on whichever PR is the tip. Mid-stack PRs are expected to carry an unarchived change directory and the gate skips them. ### Landing a stack: merge _down_, then one merge to `main`