0005 — A release branch collects stories; progress is git ancestry, the CHANGELOG is fragments

Status: accepted (amends 0002); amended by 0006 (no longer opt-in: code level 1 and up) Date: 2026-10-17 Story: stories/021-release-branch-collects-stories-in-dependency.md

Context

ADR 0002 prepares the release in the story's own pull request, so one story is one release. Two ready stories (gobank-deploy #46, #47) meant two runs in a hand-picked order, a conflict on the shared [Unreleased], a .tp-release-comment that names one branch, and the version worked out by hand. A plain issue shipped on a story branch was never closed (#91).

Options

Option Complexity Testability Domain clarity Operational risk
A. Keep one story per release none as today a release is a story serial releases; CHANGELOG conflicts between parallel stories
B. Merge story PRs through the forge API into release, then check a merge call per forge; failures after the merge need reverting on the remote needs a forge that merges the forge's PR state is the record a story that breaks the build is already on the remote release
C. Merge locally into release, check, push; progress by ancestry; CHANGELOG lines as per-story fragment files a merge loop and a fragment package real git in a temp dir, fake forge for PRs only the batch is a list, the order is the fragments' after:, done is "tip reachable from release" only what passed check is pushed; a crash leaves nothing to reconcile

Decision

C, opt-in by fragments: true. The batch is the gitignored .tp-release.yml; nothing records "merged", so a manual merge or a crash cannot leave stale state. Fragments changes/<n>.<kind>.md replace the shared [Unreleased] and .tp-release-comment; their names give the issues the release closes, which absorbs #91. release is cut from the base per batch and deleted after the tag.

Consequences

Easier: stories are prepared in parallel without touching shared files; the version and comment follow from the fragments; a stopped batch resumes by running again.

Harder: tp merges the stories itself, so their review gate is the one pull request from release to the base, and a forge without "autodetect manual merge" leaves story PRs open for the human to close. release/* branches (story 005) cannot coexist with release, so they are refused.