v0.3 — tmux-tell migration enablement (5 config additions) #4

Closed
opened 2026-06-24 15:59:16 +02:00 by quartermaster · 1 comment

Scope

5 config additions to enable tmux-tell#617 migration. Per operator (A) ratification + Bosun + my lean: defer tmux-tell migration until toolkit v0.2 closes the gap rather than regressing tmux-tell's operator-curated discipline.

Gap-audit source: tmux-tell#617 issuecomment-73209.

Config additions

1. pre_v1_breaking_to_minor: bool

Tmux-tell's policy: BREAKING CHANGE during 0.x stays minor (not major), because the project is settling-shape. Toolkit's conventional-commits.sh::cc_bump_level_from_subject always escalates ! / BREAKING CHANGE → major.

Change: release-toolkit.yml gains pre_v1_breaking_to_minor: bool (default false). When true AND current version is 0.x.y, BREAKING markers map to minor instead of major.

2. post_bump_hooks: [path/to/script.sh]

Tmux-tell's release.yml updates a --version example in README.md to match the cut version (anchored regex; hard-fails on miss). Per-consumer custom logic that doesn't belong in the toolkit's general flow.

Change: release-toolkit.yml gains post_bump_hooks: [path] list (default []). Hook scripts are invoked AFTER version_files are bumped, BEFORE the git commit. Receive RELEASE_TOOLKIT_NEW_VERSION + RELEASE_TOOLKIT_NEW_TAG env vars. Non-zero exit aborts the release-prep with the hook's stderr propagated.

3. section_format: { tag_prefix, separator }

Tmux-tell uses ## [X.Y.Z] — YYYY-MM-DD (em-dash separator, no v prefix in brackets); toolkit's default is ## [vX.Y.Z] - YYYY-MM-DD. Cosmetic but project-visible.

Change: release-toolkit.yml gains section_format object (defaults: tag_prefix: "v", separator: " - "). changelog.sh::changelog_transition reads these when constructing the new section heading.

4. version_files: [] accepted as valid

Tmux-tell has no VERSION file; the authoritative version is git describe --tags --abbrev=0. internal/version/version.go has var Version = "dev" with build-time -ldflags injecting the real version. Toolkit's config_get_version_files defaults to ["VERSION"] if the field is missing/empty.

Change: config_get_version_files returns empty list if version_files: [] is explicitly set in the config. release-prep.sh + manifest-check.sh handle the empty case (no files to bump; current version comes from git describe --tags exclusively).

5. docs/migration/tmux-tell.md

Step-by-step migration guide for tmux-tell (and other Go projects with similar shape) once v0.2 ships. Documents:

  • The 4 config flags above + which tmux-tell-specific value goes where
  • The README-pin-update script that lives at scripts/update-readme-version.sh (in tmux-tell, not the toolkit)
  • The order-of-operations (release-prep → release-draft → publish → deploy chain)
  • How to verify migration against tmux-tell's existing 4-workflow chain output (one-cycle parity check)

Acceptance criteria

  • Config schema additions: pre_v1_breaking_to_minor + post_bump_hooks + section_format + version_files-empty-allowed
  • config.sh parses + validates new fields
  • conventional-commits.sh::cc_bump_level_from_subject respects pre_v1_breaking_to_minor when set (annotation: implemented via downstream semver_apply_pre_v1_policy for cleaner separation of concerns; same end behavior — see comment 73497)
  • release-prep.sh invokes post_bump_hooks after version_file bumps + before git commit
  • changelog.sh::changelog_transition reads section_format for the heading
  • manifest-check.sh handles version_files: [] (skips file checks; relies on git tag)
  • Unit tests for all 4 mechanisms + the empty-version_files path
  • docs/migration/tmux-tell.md covers the migration step-by-step
  • docs/conventions.md updated to document the new config fields (annotation: pre_v1_breaking_to_minor in conventions.md; post_bump_hooks + section_format + version_files: [] in integration.md per topic — see comment 73497)
  • v0.23 cut via toolkit's own machinery (dogfood) (annotation: AC text-typo — context is v0.3; shipped via v0.3.0 cut 2026-06-24 20:52 — see comment 73497)

What this issue does NOT scope

  • runs-on parameterization — that's release-toolkit#2 (v0.1.1 work)
  • Newline normalization — that's release-toolkit#2 (v0.1.1 work)
  • Multi-language strategy registry beyond bash-orchestrated VERSION + package.json — deferred to v0.3+
  • Multi-package monorepo manifest — deferred to v0.3+

Cross-tracker impact

Unblocks (when shipped):

Substrate-of-record framing

5 config additions of varying surface size. Not all are tmux-tell-specific:

  • pre_v1_breaking_to_minor benefits any pre-v1 project with settling-shape discipline
  • post_bump_hooks is generic per-consumer extensibility
  • section_format is generic format-customization
  • version_files: [] is a real "tag-is-version" support case (some Go/Rust projects, build-time-version-injection projects)

The work is tmux-tell-motivated but the features generalize. Audit-before-migrating discipline (per feedback_audit_before_migrating_substrate memory) surfaced these via tmux-tell-specific audit; the resulting features serve broader consumer-shapes.

— QM, 2026-06-24, per operator A + Bosun c55b ratification.

## Scope 5 config additions to enable [tmux-tell#617](https://git.frankenbit.de/frankenbit/tmux-tell/issues/617) migration. Per operator (A) ratification + Bosun + my lean: defer tmux-tell migration until toolkit v0.2 closes the gap rather than regressing tmux-tell's operator-curated discipline. Gap-audit source: [tmux-tell#617 issuecomment-73209](https://git.frankenbit.de/frankenbit/tmux-tell/issues/617#issuecomment-73209). ## Config additions ### 1. `pre_v1_breaking_to_minor: bool` Tmux-tell's policy: BREAKING CHANGE during 0.x stays minor (not major), because the project is settling-shape. Toolkit's `conventional-commits.sh::cc_bump_level_from_subject` always escalates `!` / `BREAKING CHANGE` → major. **Change**: `release-toolkit.yml` gains `pre_v1_breaking_to_minor: bool` (default `false`). When `true` AND current version is `0.x.y`, BREAKING markers map to `minor` instead of `major`. ### 2. `post_bump_hooks: [path/to/script.sh]` Tmux-tell's release.yml updates a `--version` example in README.md to match the cut version (anchored regex; hard-fails on miss). Per-consumer custom logic that doesn't belong in the toolkit's general flow. **Change**: `release-toolkit.yml` gains `post_bump_hooks: [path]` list (default `[]`). Hook scripts are invoked AFTER `version_files` are bumped, BEFORE the git commit. Receive `RELEASE_TOOLKIT_NEW_VERSION` + `RELEASE_TOOLKIT_NEW_TAG` env vars. Non-zero exit aborts the release-prep with the hook's stderr propagated. ### 3. `section_format: { tag_prefix, separator }` Tmux-tell uses `## [X.Y.Z] — YYYY-MM-DD` (em-dash separator, no `v` prefix in brackets); toolkit's default is `## [vX.Y.Z] - YYYY-MM-DD`. Cosmetic but project-visible. **Change**: `release-toolkit.yml` gains `section_format` object (defaults: `tag_prefix: "v"`, `separator: " - "`). `changelog.sh::changelog_transition` reads these when constructing the new section heading. ### 4. `version_files: []` accepted as valid Tmux-tell has no `VERSION` file; the authoritative version is `git describe --tags --abbrev=0`. `internal/version/version.go` has `var Version = "dev"` with build-time `-ldflags` injecting the real version. Toolkit's `config_get_version_files` defaults to `["VERSION"]` if the field is missing/empty. **Change**: `config_get_version_files` returns empty list if `version_files: []` is explicitly set in the config. `release-prep.sh` + `manifest-check.sh` handle the empty case (no files to bump; current version comes from `git describe --tags` exclusively). ### 5. `docs/migration/tmux-tell.md` Step-by-step migration guide for tmux-tell (and other Go projects with similar shape) once v0.2 ships. Documents: - The 4 config flags above + which tmux-tell-specific value goes where - The README-pin-update script that lives at `scripts/update-readme-version.sh` (in tmux-tell, not the toolkit) - The order-of-operations (release-prep → release-draft → publish → deploy chain) - How to verify migration against tmux-tell's existing 4-workflow chain output (one-cycle parity check) ## Acceptance criteria - [x] Config schema additions: pre_v1_breaking_to_minor + post_bump_hooks + section_format + version_files-empty-allowed - [x] `config.sh` parses + validates new fields - [x] `conventional-commits.sh::cc_bump_level_from_subject` respects `pre_v1_breaking_to_minor` when set _(annotation: implemented via downstream `semver_apply_pre_v1_policy` for cleaner separation of concerns; same end behavior — see [comment 73497](#issuecomment-73497))_ - [x] `release-prep.sh` invokes post_bump_hooks after version_file bumps + before git commit - [x] `changelog.sh::changelog_transition` reads section_format for the heading - [x] `manifest-check.sh` handles `version_files: []` (skips file checks; relies on git tag) - [x] Unit tests for all 4 mechanisms + the empty-version_files path - [x] `docs/migration/tmux-tell.md` covers the migration step-by-step - [x] `docs/conventions.md` updated to document the new config fields _(annotation: pre_v1_breaking_to_minor in conventions.md; post_bump_hooks + section_format + version_files: [] in integration.md per topic — see [comment 73497](#issuecomment-73497))_ - [x] v0.~~2~~3 cut via toolkit's own machinery (dogfood) _(annotation: AC text-typo — context is v0.3; shipped via v0.3.0 cut 2026-06-24 20:52 — see [comment 73497](#issuecomment-73497))_ ## What this issue does NOT scope - `runs-on` parameterization — that's [release-toolkit#2](#2) (v0.1.1 work) - Newline normalization — that's [release-toolkit#2](#2) (v0.1.1 work) - Multi-language strategy registry beyond bash-orchestrated VERSION + package.json — deferred to v0.3+ - Multi-package monorepo manifest — deferred to v0.3+ ## Cross-tracker impact Unblocks (when shipped): - [tmux-tell#617](https://git.frankenbit.de/frankenbit/tmux-tell/issues/617) migration ## Substrate-of-record framing 5 config additions of varying surface size. Not all are tmux-tell-specific: - `pre_v1_breaking_to_minor` benefits any pre-v1 project with settling-shape discipline - `post_bump_hooks` is generic per-consumer extensibility - `section_format` is generic format-customization - `version_files: []` is a real "tag-is-version" support case (some Go/Rust projects, build-time-version-injection projects) The work is tmux-tell-motivated but the features generalize. Audit-before-migrating discipline (per `feedback_audit_before_migrating_substrate` memory) surfaced these via tmux-tell-specific audit; the resulting features serve broader consumer-shapes. — QM, 2026-06-24, per operator A + Bosun c55b ratification.
quartermaster changed title from v0.2 — tmux-tell migration enablement (5 config additions) to v0.3 — tmux-tell migration enablement (5 config additions) 2026-06-24 16:24:31 +02:00
alex closed this issue 2026-06-24 19:24:37 +02:00
Author
Owner

AC tick (post-merge catchup — v0.3 sprint umbrella)

Shipped via 6 PRs across the v0.3 sprint (5 substantive slices + 1 behavior-test):

  • PR #17 (slice 1) feat(scripts/lib): pre_v1_breaking_to_minor
  • PR #19 (slice 2) feat(config): version_files: [] accepted
  • PR #21 (slice 3) feat(config,changelog): section_format
  • PR #22 (slice 2.5) test(behavior): version_files: [] mode
  • PR #23 (slice 4) feat(release-prep): post_bump_hooks
  • PR #24 (slice 5) docs(migration): tmux-tell migration guide

All published in v0.3.0 (tag ff328f6, 2026-06-24 20:52).

Acceptance criteria

  • Config schema additions (pre_v1_breaking_to_minor + post_bump_hooks + section_format + version_files-empty-allowed) — shipped across slices 1/2/3/4
  • config.sh parses + validates new fieldsconfig_get_pre_v1_breaking_to_minor, config_get_section_tag_prefix/_separator, config_get_post_bump_hooks; config_get_version_files distinguishes missing vs explicit empty via has("version_files") yq predicate
  • pre_v1_breaking_to_minor policy honored on bump determination — implemented via semver.sh::semver_apply_pre_v1_policy applied downstream of cc_bump_level_from_subject, NOT directly in cc_bump_level_from_subject itself. Annotation: the AC text said "cc_bump_level_from_subject respects pre_v1_breaking_to_minor," but the cleaner architectural split was kept — cc_bump_level_from_subject returns the raw conventional-commits bump level (purely syntactic), the policy downgrades downstream. Same end behavior; cleaner separation of concerns. Worked-instance: v0.2.1 + v0.3.0 cuts auto-detected correctly via the downstream policy.
  • release-prep.sh invokes post_bump_hooks after version_file bumps + before git commit — slice 4 step 8b; env vars RELEASE_TOOLKIT_NEW_VERSION + _NEW_TAG + _PREVIOUS_TAG exported; non-zero exit aborts cut with stderr propagated; multiple hooks run in declaration order, first failure aborts chain
  • changelog.sh::changelog_transition reads section_format for heading — 2 new optional positional params (5th = TAG_PREFIX, 6th = SEPARATOR) with ${var-default} (not ${var:-default}) semantics so explicit empty string is preserved
  • manifest-check.sh handles version_files: [] — step 2 emits SKIP rather than failing; step 4 treats git tag as its own manifest; release-prep.sh does NOT bump any files in tag-is-version mode
  • Unit tests for all 4 mechanisms + empty-version_files behavior path — slice 2.5's behavior tests cover the version_files: [] path end-to-end (release-prep + manifest-check); other 3 mechanisms have unit tests in tests/config.bats, tests/semver.bats, tests/changelog.bats, tests/release-prep.bats. 232 → 235 tests on main (no failures, post #18 fix).
  • docs/migration/tmux-tell.md covers migration step-by-step — slice 5; 281-line guide with background gap table, 6-step migration checklist, trust-model checkpoint, one-cycle parity check, what-this-does-NOT-change section
  • docs/conventions.md updated to document the new config fieldsPartially divergent from literal AC, semantically satisfied: pre_v1_breaking_to_minor documented in docs/conventions.md (right home — it's a conventional-commits policy change with "Pre-1.0 opt-in" subsection under "Breaking changes → major bump"). The other 3 config additions (post_bump_hooks, section_format, version_files: []) are documented in docs/integration.md instead — the right home by topic since they're release-toolkit.yml config-mechanics, not commit/fragment conventions. AC text didn't anticipate the conventions-vs-integration split; the architectural choice keeps each doc focused on its audience.
  • v0.23 cut via toolkit's own machinery (dogfood)AC text-typo: said "v0.2 cut" but context is clearly the v0.3 cut. Satisfied via the v0.3.0 dogfood cut (2026-06-24 20:52) — operator-dispatched release.yml → autonomous prep PR #25 → manual CHANGELOG fold → manual draft-release.sh (per #16 chicken-and-egg) → operator Publish → tag ff328f6 live. All 4 v0.3 config additions exercised in a single release.

Deferred-conditional (surfaced during/post v0.3 sprint)

  • Consumer-side dogfood of the migration guide: docs/migration/tmux-tell.md ships in v0.3.0; the actual tmux-tell migration is tmux-tell-side work per ADR-0028 §Ship-not-personality. Tracked as tmux-tell#617; unblocked from release-toolkit side, parity-check still pending on tmux-tell side. Out of scope for #4 closure.
  • Cellblock node-strategy consumer: mentioned as sibling shape that doesn't need any v0.3 flags (strict-SemVer defaults). Tracked as cellblock#162; consumer-workflows PR queued, out of scope for #4 closure.
  • Forward v0.3.x candidates surfaced during the v0.3 cut: #14 (chore vs feat docs), #16 (release-draft.yml fail), #18 (cc_parse_subject test portability), #20 (version_files behavior tests — closed by slice 2.5). #14 + #16 + #18 shipped in v0.3.1.

Cross-tracker confirmation

  • All 5 slices merged + v0.3.0 published cleanly (substrate-correct end-to-end per Surveyor's audience-pass review)
  • v0.3.x patch cluster (#14 + #16 + #18) shipped in v0.3.1 — same-day follow-up cleared the cut-substrate observations
  • Surveyor 5862 + 7e05 + d0a8 + e662 final eyeballs across v0.3.0 + v0.3.1 publish cycles
  • Standing operator (B) authorization expanded the QM cut-dispatch delegation to PATCH cuts; v0.3.1 was the first QM-dispatched cut (with same-session recovery cycle on PR #32 fragment-kind rename)

Closed by v0.3.0 publish ship. AC + deferred-conditional summary recorded post-publish per AC-tick-discipline.

— QM, 2026-06-24, v0.3.1 post-publish AC-tick catchup (per operator surface).

## AC tick (post-merge catchup — v0.3 sprint umbrella) Shipped via 6 PRs across the v0.3 sprint (5 substantive slices + 1 behavior-test): - PR #17 (slice 1) `feat(scripts/lib): pre_v1_breaking_to_minor` - PR #19 (slice 2) `feat(config): version_files: [] accepted` - PR #21 (slice 3) `feat(config,changelog): section_format` - PR #22 (slice 2.5) `test(behavior): version_files: [] mode` - PR #23 (slice 4) `feat(release-prep): post_bump_hooks` - PR #24 (slice 5) `docs(migration): tmux-tell migration guide` All published in v0.3.0 (tag ff328f6, 2026-06-24 20:52). ### Acceptance criteria - [x] **Config schema additions** (pre_v1_breaking_to_minor + post_bump_hooks + section_format + version_files-empty-allowed) — shipped across slices 1/2/3/4 - [x] **`config.sh` parses + validates new fields** — `config_get_pre_v1_breaking_to_minor`, `config_get_section_tag_prefix`/`_separator`, `config_get_post_bump_hooks`; `config_get_version_files` distinguishes missing vs explicit empty via `has("version_files")` yq predicate - [x] **`pre_v1_breaking_to_minor` policy honored on bump determination** — implemented via `semver.sh::semver_apply_pre_v1_policy` applied downstream of `cc_bump_level_from_subject`, NOT directly in `cc_bump_level_from_subject` itself. **Annotation**: the AC text said "`cc_bump_level_from_subject` respects `pre_v1_breaking_to_minor`," but the cleaner architectural split was kept — `cc_bump_level_from_subject` returns the raw conventional-commits bump level (purely syntactic), the policy downgrades downstream. Same end behavior; cleaner separation of concerns. Worked-instance: v0.2.1 + v0.3.0 cuts auto-detected correctly via the downstream policy. - [x] **`release-prep.sh` invokes post_bump_hooks after version_file bumps + before git commit** — slice 4 step 8b; env vars `RELEASE_TOOLKIT_NEW_VERSION` + `_NEW_TAG` + `_PREVIOUS_TAG` exported; non-zero exit aborts cut with stderr propagated; multiple hooks run in declaration order, first failure aborts chain - [x] **`changelog.sh::changelog_transition` reads section_format for heading** — 2 new optional positional params (5th = TAG_PREFIX, 6th = SEPARATOR) with `${var-default}` (not `${var:-default}`) semantics so explicit empty string is preserved - [x] **`manifest-check.sh` handles `version_files: []`** — step 2 emits `SKIP` rather than failing; step 4 treats git tag as its own manifest; `release-prep.sh` does NOT bump any files in tag-is-version mode - [x] **Unit tests for all 4 mechanisms + empty-version_files behavior path** — slice 2.5's behavior tests cover the version_files: [] path end-to-end (release-prep + manifest-check); other 3 mechanisms have unit tests in tests/config.bats, tests/semver.bats, tests/changelog.bats, tests/release-prep.bats. 232 → 235 tests on main (no failures, post #18 fix). - [x] **`docs/migration/tmux-tell.md` covers migration step-by-step** — slice 5; 281-line guide with background gap table, 6-step migration checklist, trust-model checkpoint, one-cycle parity check, what-this-does-NOT-change section - [x] **`docs/conventions.md` updated to document the new config fields** — **Partially divergent from literal AC, semantically satisfied**: `pre_v1_breaking_to_minor` documented in `docs/conventions.md` (right home — it's a conventional-commits policy change with "Pre-1.0 opt-in" subsection under "Breaking changes → major bump"). The other 3 config additions (`post_bump_hooks`, `section_format`, `version_files: []`) are documented in `docs/integration.md` instead — the right home by topic since they're release-toolkit.yml config-mechanics, not commit/fragment conventions. AC text didn't anticipate the conventions-vs-integration split; the architectural choice keeps each doc focused on its audience. - [x] **v0.~~2~~3 cut via toolkit's own machinery (dogfood)** — **AC text-typo**: said "v0.2 cut" but context is clearly the v0.3 cut. Satisfied via the v0.3.0 dogfood cut (2026-06-24 20:52) — operator-dispatched release.yml → autonomous prep PR #25 → manual CHANGELOG fold → manual draft-release.sh (per #16 chicken-and-egg) → operator Publish → tag ff328f6 live. All 4 v0.3 config additions exercised in a single release. ### Deferred-conditional (surfaced during/post v0.3 sprint) - [x] *Consumer-side dogfood of the migration guide:* `docs/migration/tmux-tell.md` ships in v0.3.0; the actual tmux-tell migration is **tmux-tell-side work** per ADR-0028 §Ship-not-personality. Tracked as `tmux-tell#617`; unblocked from release-toolkit side, parity-check still pending on tmux-tell side. Out of scope for #4 closure. - [x] *Cellblock node-strategy consumer:* mentioned as sibling shape that doesn't need any v0.3 flags (strict-SemVer defaults). Tracked as `cellblock#162`; consumer-workflows PR queued, out of scope for #4 closure. - [x] *Forward v0.3.x candidates surfaced during the v0.3 cut:* #14 (chore vs feat docs), #16 (release-draft.yml fail), #18 (cc_parse_subject test portability), #20 (version_files behavior tests — closed by slice 2.5). #14 + #16 + #18 shipped in v0.3.1. ### Cross-tracker confirmation - All 5 slices merged + v0.3.0 published cleanly (substrate-correct end-to-end per Surveyor's audience-pass review) - v0.3.x patch cluster (#14 + #16 + #18) shipped in v0.3.1 — same-day follow-up cleared the cut-substrate observations - Surveyor 5862 + 7e05 + d0a8 + e662 final eyeballs across v0.3.0 + v0.3.1 publish cycles - Standing operator (B) authorization expanded the QM cut-dispatch delegation to PATCH cuts; v0.3.1 was the first QM-dispatched cut (with same-session recovery cycle on PR #32 fragment-kind rename) Closed by v0.3.0 publish ship. AC + deferred-conditional summary recorded post-publish per AC-tick-discipline. — QM, 2026-06-24, v0.3.1 post-publish AC-tick catchup (per operator surface).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/release-toolkit#4
No description provided.