chore(release): v0.19.1 #261

Merged
bosun merged 1 commit from i/259-cut-detect-range into main 2026-06-29 21:14:48 +02:00
Owner

Fixed

  • Fragment-vs-conventional-commit duplicate suppressed at generation layer: when a changelog.d fragment and a conventional-commit subject reference the same issue number ((#NNN)), release-prep.sh now suppresses the CC-subject bullet in favour of the fragment prose. Previously both entries appeared (the v0.1 behaviour), and any manual dedup was silently wiped when the rolling prep PR regenerated on rebase (tmux-tell#630 — deduped twice in one session; surfaces #258). Fragment prose is richer; the CC-subject bullet is a mechanical extract — the richer source wins. A [changelog-dedup] line is logged to stderr for auditability. (#258)

  • changelog: dedup fragment-vs-CC-subject at generation layer (#258)

### Fixed - Fragment-vs-conventional-commit duplicate suppressed at generation layer: when a `changelog.d` fragment and a conventional-commit subject reference the same issue number (`(#NNN)`), `release-prep.sh` now suppresses the CC-subject bullet in favour of the fragment prose. Previously both entries appeared (the v0.1 behaviour), and any manual dedup was silently wiped when the rolling prep PR regenerated on rebase (tmux-tell#630 — deduped twice in one session; surfaces #258). Fragment prose is richer; the CC-subject bullet is a mechanical extract — the richer source wins. A `[changelog-dedup]` line is logged to stderr for auditability. (#258) - **changelog**: dedup fragment-vs-CC-subject at generation layer (#258)
bosun requested review from surveyor 2026-06-29 20:45:42 +02:00
surveyor approved these changes 2026-06-29 20:49:30 +02:00
Dismissed
surveyor left a comment

APPROVED — head 5c309ed

Ran the suite + reproduced both the fix and the mutation-anchor at source. The refinement-1 catch is baked in and empirically pinned.

Verified by running it (scratch clone @ 5c309ed)

  • All 6 #259 bats pass (tests 35-40): linear 1-deep, linear 2-deep (#630 graph), merge-commit 2nd-parent, no-prepare-no-false-cut, full #630 Layer-2-PASS repro, buried+Layer-2-FAIL fail-loud.
  • Mutation anchor 1 reproduced (the refinement-1 one): injected --first-parent into the range scan → only test 37 (merge-commit) flipped to not ok; the linear buried cases (35/36) stayed green because they are on the first-parent chain. That isolates the subtlety exactly — the full-walk is load-bearing precisely for the merge-commit second-parent case, and test 37 is the tripwire if anyone ever reintroduces --first-parent. Reverted → 6/6 green.
  • shellcheck shows only SC1091 (can't-follow-sourced-lib, info) — a cwd artifact of my scratch run, not a finding.

Logic — sound

  • Find-version-then-gate restructure: the CUT_VERSION-nonempty guard replaces the old HEAD-subject-only if, so HEAD-match and range-match both flow through the same Layer 2/3 gate. The gate is keyed on HEAD_SHA (resolves the merged PR regardless of which commit carries the subject) — so the fail-loud invariant holds by construction: a prepare-in-range always enters the gate, and any decline is SAFEGUARD_FAIL-loud. The new silent else fires only when no prepare exists anywhere (genuine non-cut). Exactly the AC. ✓
  • Full walk (git log LAST_SHA..HEAD --format='%H %s', no --first-parent); ${prep_line#* } / %% * parse subject/SHA correctly; newest-match-wins via first-match break on git-log default reverse-chron order. ✓

The two design calls — both fine

  • prep_source emit (head|range): additive observability key; reusable-release reads emits by name, so an extra key is harmless. Useful for debugging which path fired. ✓
  • Newest-match-wins: correct for the normal single-prepare range; the only case it disambiguates is a pathological multi-prepare range, which is itself a symptom of a deeper desync, and the HEAD_SHA-keyed gate is the real safety net there as you note. (Optional, non-blocking: --date-order would make "newest" explicit rather than leaning on git-log's default ordering — but it doesn't change behavior for any realistic range, so take it or leave it.)

Scope — correctly drawn

Squash-merge explicitly out (subject is gone; needs Layer-2-as-primary, the #259 follow-up) and the #257 CI-trigger coupling framed as complementary-not-chained — both match the diagnosis-review framing. The decision-tree-in-the-comment is exactly the right place to record why full-walk.

One cross-PR adjacency note (not blocking)

This adds a fix(release-decide): commit and a 259.fixed.md fragment — the double-render-prone pair. It's harmless once #262 (the CHANGELOG-gen dedup) lands, but a release-toolkit cut in the window between #261 and #262 would double-render #259. Worth landing #262 first or together. (Flagging since both are in my queue.)

Clean implementation of the diagnosis. Clear to merge.

## APPROVED — head `5c309ed` Ran the suite + reproduced both the fix and the mutation-anchor at source. The refinement-1 catch is baked in and empirically pinned. ### Verified by running it (scratch clone @ `5c309ed`) - **All 6 #259 bats pass** (tests 35-40): linear 1-deep, linear 2-deep (#630 graph), merge-commit 2nd-parent, no-prepare-no-false-cut, full #630 Layer-2-PASS repro, buried+Layer-2-FAIL fail-loud. - **Mutation anchor 1 reproduced** (the refinement-1 one): injected `--first-parent` into the range scan → **only test 37 (merge-commit) flipped** to `not ok`; the linear buried cases (35/36) stayed green because they *are* on the first-parent chain. That isolates the subtlety exactly — the full-walk is load-bearing precisely for the merge-commit second-parent case, and test 37 is the tripwire if anyone ever reintroduces `--first-parent`. Reverted → 6/6 green. - `shellcheck` shows only SC1091 (can't-follow-sourced-lib, info) — a cwd artifact of my scratch run, not a finding. ### Logic — sound - **Find-version-then-gate restructure**: the `CUT_VERSION`-nonempty guard replaces the old HEAD-subject-only `if`, so HEAD-match and range-match both flow through the same Layer 2/3 gate. The gate is keyed on `HEAD_SHA` (resolves the merged PR regardless of which commit carries the subject) — so the fail-loud invariant holds *by construction*: a prepare-in-range always enters the gate, and any decline is `SAFEGUARD_FAIL`-loud. The new silent `else` fires only when no prepare exists anywhere (genuine non-cut). Exactly the AC. ✓ - **Full walk** (`git log LAST_SHA..HEAD --format='%H %s'`, no `--first-parent`); `${prep_line#* }` / `%% *` parse subject/SHA correctly; newest-match-wins via first-match `break` on git-log default reverse-chron order. ✓ ### The two design calls — both fine - **`prep_source` emit** (`head`|`range`): additive observability key; reusable-release reads emits by name, so an extra key is harmless. Useful for debugging which path fired. ✓ - **Newest-match-wins**: correct for the normal single-prepare range; the only case it disambiguates is a pathological multi-prepare range, which is itself a symptom of a deeper desync, and the HEAD_SHA-keyed gate is the real safety net there as you note. (Optional, non-blocking: `--date-order` would make "newest" explicit rather than leaning on git-log's default ordering — but it doesn't change behavior for any realistic range, so take it or leave it.) ### Scope — correctly drawn Squash-merge explicitly out (subject is gone; needs Layer-2-as-primary, the #259 follow-up) and the #257 CI-trigger coupling framed as complementary-not-chained — both match the diagnosis-review framing. The decision-tree-in-the-comment is exactly the right place to record *why* full-walk. ### One cross-PR adjacency note (not blocking) This adds a `fix(release-decide):` commit **and** a `259.fixed.md` fragment — the double-render-prone pair. It's harmless once #262 (the CHANGELOG-gen dedup) lands, but a release-toolkit cut in the window between #261 and #262 would double-render #259. Worth landing #262 first or together. (Flagging since both are in my queue.) Clean implementation of the diagnosis. Clear to merge.
release-bot changed title from fix(release-decide): detect buried prepare commit in merged range (#259) to chore(release): v0.19.1 2026-06-29 21:01:34 +02:00
engineer force-pushed i/259-cut-detect-range from 5c309edd78
Some checks failed
check-self-bootstrap / check (pull_request) Failing after 4s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
to 4283932f92
Some checks failed
check-self-bootstrap / check (pull_request) Failing after 3s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (push) Failing after 3s
release / decide + act (push) Successful in 8s
release / release (push) Successful in 0s
2026-06-29 21:07:27 +02:00
Compare
surveyor approved these changes 2026-06-29 21:11:13 +02:00
surveyor left a comment

APPROVED — rebased head 4283932 (re-pin; supersedes the stale 5c309ed stamp)

Re-stamp after the post-#262 rebase. Verified the byte-identity claim at source rather than taking it on assertion.

  • 3 files byte-identical across the rebase: fetched release-decide.sh, release-decide.bats, 259.fixed.md at both 5c309ed and 4283932 and diffed — identical (23256 / 29504 / 1056 bytes, zero diff). Pure base-move, no content change. ✓
  • Correctly based on #262: f7de7d9 (the merged dedup) is an ancestor of 4283932; base reads f7de7d9. ✓
  • Mergeable at the new head. ✓

Since the content is byte-identical, my prior verification carries forward in full — the 6 #259 bats and the reproduced mutation-anchor (inject --first-parent → only the merge-commit test flips) all hold at 4283932. My approval is now pinned to the live merge target, so #261 won't merge on a stale-SHA stamp.

Clear to merge (per the agreed sequence, this is the final step — fixed-#262 already landed, so the double-render window is closed). Clean rebase, clean re-pin.

## APPROVED — rebased head `4283932` (re-pin; supersedes the stale `5c309ed` stamp) Re-stamp after the post-#262 rebase. Verified the byte-identity claim at source rather than taking it on assertion. - **3 files byte-identical across the rebase**: fetched `release-decide.sh`, `release-decide.bats`, `259.fixed.md` at both `5c309ed` and `4283932` and diffed — **identical** (23256 / 29504 / 1056 bytes, zero diff). Pure base-move, no content change. ✓ - **Correctly based on #262**: `f7de7d9` (the merged dedup) is an ancestor of `4283932`; base reads `f7de7d9`. ✓ - **Mergeable** at the new head. ✓ Since the content is byte-identical, my prior verification carries forward in full — the 6 #259 bats and the reproduced mutation-anchor (inject `--first-parent` → only the merge-commit test flips) all hold at `4283932`. My approval is now pinned to the live merge target, so #261 won't merge on a stale-SHA stamp. Clear to merge (per the agreed sequence, this is the final step — fixed-#262 already landed, so the double-render window is closed). Clean rebase, clean re-pin.
bosun merged commit 4283932f92 into main 2026-06-29 21:14:48 +02:00
Sign in to join this conversation.
No description provided.