| 1 | --- |
| 2 | title: Towncrier fragments + automated lockstep release PRs |
| 3 | date: 2026-07-24 |
| 4 | category: docs/solutions/workflow-issues |
| 5 | module: ci-release-engineering |
| 6 | problem_type: workflow_issue |
| 7 | component: release_workflow |
| 8 | severity: medium |
| 9 | applies_when: |
| 10 | - multiple PRs edit CHANGELOG.md ## [Unreleased] and conflict on merge |
| 11 | - a release must bump the same semver across skill, pyproject, and every plugin/marketplace manifest |
| 12 | - agents (not humans) author most feature PRs and need a clear changelog rule |
| 13 | symptoms: |
| 14 | - Unreleased section merge conflicts on every release train |
| 15 | - missed marketplace JSON version bumps when releasing by hand |
| 16 | - agents invent release steps that drift from test_plugin_contract lockstep |
| 17 | root_cause: missing_workflow_step |
| 18 | resolution_type: workflow_change |
| 19 | related_components: |
| 20 | - development_workflow |
| 21 | - documentation |
| 22 | - github_actions |
| 23 | tags: |
| 24 | - changelog |
| 25 | - towncrier |
| 26 | - release-engineering |
| 27 | - version-lockstep |
| 28 | - agents |
| 29 | - github-actions |
| 30 | --- |
| 31 | |
| 32 | # Towncrier fragments + automated lockstep release PRs |
| 33 | |
| 34 | ## Context |
| 35 | |
| 36 | Every feature PR used to edit `CHANGELOG.md` under `## [Unreleased]`, which produced constant merge conflicts. Separately, a correct release must bump the **same** semver across skill frontmatter + H1, `pyproject.toml`, `uv.lock`, Claude/Codex/Grok/Gemini plugin manifests, and both marketplace JSON files — enforced by `tests/test_plugin_contract.py`. Hand-rolled release PRs missed files; release-please would work only with a large `extra-files` surface and conventional-commit discipline that agent traffic does not reliably provide. |
| 37 | |
| 38 | ## Solution |
| 39 | |
| 40 | 1. **towncrier** — PRs add `changelog.d/<n>.<type>.md`; `CHANGELOG.md` is written only at release time. |
| 41 | 2. **`.github/scripts/prepare_release.py`** — runs `towncrier build` then bumps every lockstep path. |
| 42 | 3. **Actions → Prepare release** — opens the release PR; **Tag release** creates `vX.Y.Z` on merge; existing **Release** workflow attaches artifacts. |
| 43 | 4. **changelog-guard** — blocks non-release edits to `CHANGELOG.md` and version *strings*; requires a fragment (or `skip-changelog`) for engine/skill changes. |
| 44 | 5. **PR template** — changelog checklist, agent disclosure (AI review + security), and relationship disclosure for contributors tied to a vendor/product they are adding. |
| 45 | |
| 46 | ## Agent rules (short) |
| 47 | |
| 48 | - Write fragments, not `CHANGELOG.md`. |
| 49 | - Do not bump versions in feature PRs. |
| 50 | - Cut releases via Prepare release, not by editing ten files. |
| 51 | |
| 52 | ## See also |
| 53 | |
| 54 | - `AGENTS.md` § Changelog and releases |
| 55 | - `changelog.d/README.md` |
| 56 | - `tests/test_changelog_workflow.py` |
| 57 |