chore(release): v0.38.0 #709

Merged
bosun merged 1 commit from release-prep/rolling into main 2026-08-18 23:43:48 +02:00
Member

Added

None.

Changed

None.

Fixed

  • decide: --dry-run no longer skips the cut-safeguard layers, and an ungraded layer stops declaring a pass (#689)

    A dry run short-circuited both safeguard layers and the rolling-PR bump-label read, then reported mode=cut for a base a real run had refused seconds earlier. layer2=skip rendered identically to layer2=pass. The layers are reads, so they now run under --dry-run exactly as on a real run. The gate also requires an affirmative pass instead of merely "not a failure", so a layer that could not be graded declines the cut rather than clearing it.

  • docs: examples/README.md no longer hard-codes a "current" toolkit version that the release rewrite cannot update (#716)

    The setup step tells adopters to replace the uses: pin, and the release rewrite updates that pin on every cut. The parenthetical beside it named a fixed version and was updated by nothing, so it had said "v0.25.0 is current" for thirteen minor releases. It now points at the README Status section, which is the surface that actually tracks the current tag.

  • changelog: split the #689 fragment sentence that fails the density gate

Removed

  • release path: the bash PR-CI gates and their differential oracle are gone; rt is the sole implementation (#607)

    The four gates already ran as rt subcommands, so no adopter action is needed and no gate behaviour changes. What goes is the parallel bash: eleven scripts, two now-unreferenced libs, and their bats suites. With them go the 22 equivalence tests, which existed only to prove the two implementations agreed. A fix now lands once instead of twice.

The dead draft-release.sh component is retired — the script plus the three
libraries whose only consumer it was (lib/changelog.sh, lib/config.sh,
lib/semver.sh). 1,907 lines, reachable from nothing: the cut has published
through rt release since the Go port landed.

One bats test was ported to Go first. It was the only artifact verifying a claim
the source makes in a comment: that scaffold and check 2 agree by construction.

Deprecated

None.

Upgrade

None.

### Added None. ### Changed None. ### Fixed - **decide**: `--dry-run` no longer skips the cut-safeguard layers, and an ungraded layer stops declaring a pass (#689) A dry run short-circuited both safeguard layers and the rolling-PR bump-label read, then reported `mode=cut` for a base a real run had refused seconds earlier. `layer2=skip` rendered identically to `layer2=pass`. The layers are reads, so they now run under `--dry-run` exactly as on a real run. The gate also requires an affirmative pass instead of merely "not a failure", so a layer that could not be graded declines the cut rather than clearing it. - **docs**: `examples/README.md` no longer hard-codes a "current" toolkit version that the release rewrite cannot update (#716) The setup step tells adopters to replace the `uses:` pin, and the release rewrite updates that pin on every cut. The parenthetical beside it named a fixed version and was updated by nothing, so it had said "v0.25.0 is current" for thirteen minor releases. It now points at the README Status section, which is the surface that actually tracks the current tag. - **changelog**: split the #689 fragment sentence that fails the density gate ### Removed - **release path**: the bash PR-CI gates and their differential oracle are gone; `rt` is the sole implementation (#607) The four gates already ran as `rt` subcommands, so no adopter action is needed and no gate behaviour changes. What goes is the parallel bash: eleven scripts, two now-unreferenced libs, and their bats suites. With them go the 22 equivalence tests, which existed only to prove the two implementations agreed. A fix now lands once instead of twice. **The dead `draft-release.sh` component is retired** — the script plus the three libraries whose only consumer it was (`lib/changelog.sh`, `lib/config.sh`, `lib/semver.sh`). 1,907 lines, reachable from nothing: the cut has published through `rt release` since the Go port landed. One bats test was ported to Go first. It was the only artifact verifying a claim the source makes in a comment: that scaffold and check 2 agree by construction. ### Deprecated None. ### Upgrade None.
release-bot force-pushed release-prep/rolling from 3ed3982d36
All checks were successful
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Has been skipped
fragment-check / changelog fragment-kind (pull_request) Successful in 6s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 22s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 6s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 7s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 53s
tests / shellcheck (pull_request) Successful in 8s
to 82b38135ff
All checks were successful
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
check-self-bootstrap / check (pull_request) Has been skipped
changelog-body-check / check (pull_request) Successful in 0s
fragment-check / changelog fragment-kind (pull_request) Successful in 6s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 20s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 6s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 6s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 21s
tests / shellcheck (pull_request) Successful in 7s
2026-08-18 23:11:36 +02:00
Compare
release-bot force-pushed release-prep/rolling from 82b38135ff
All checks were successful
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
check-self-bootstrap / check (pull_request) Has been skipped
changelog-body-check / check (pull_request) Successful in 0s
fragment-check / changelog fragment-kind (pull_request) Successful in 6s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 20s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 6s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 6s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 21s
tests / shellcheck (pull_request) Successful in 7s
to 6dffa525dd
Some checks failed
changelog-body-check / changelog body Cold-Read linter (pull_request) Failing after 6s
changelog-body-check / check (pull_request) Failing after 0s
check-self-bootstrap / check (pull_request) Has been skipped
fragment-check / changelog fragment-kind (pull_request) Successful in 6s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 20s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 6s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 21s
tests / shellcheck (pull_request) Successful in 7s
2026-08-18 23:21:14 +02:00
Compare
bosun requested review from engineer 2026-08-18 23:22:41 +02:00
Owner

The red is mine, and the fix is ready but not pushed

changelog-body-check fails on one sentence — my #689 fragment, 31 words against a limit of 30.
Reproduced locally with the same binary and byte-identical output:

FAIL: check 7 (sentence length): sentence(s) exceed 30 words
  → 31w:   A dry run short-circuited both safeguard layers and the rolling-PR b...
changelog-body-check: FAILED

Verified fix — shortened rather than split, deliberately: splitting added two words and pushed the
paragraph to 76, tripping check 9's 75-word paragraph limit. Trading one gate for another is not a fix.

-…for a base a real run had refused seconds earlier — `layer2=skip` rendered identically to `layer2=pass`.
+…for a base a real run had just refused. `layer2=skip` rendered identically to `layer2=pass`.
rt changelog-body-check <fixed>   ->  exit 0

⚠️ Disclosure — a second WARN appears after the fix, and it is NOT a regression. Check 7 reports
either the >30 failure band or the 25–30 warning band, never both, so clearing the FAIL reveals a
pre-existing 28-word sentence in the same paragraph. It was there before this change and it is
non-blocking. The Removed-section style WARN also pre-dates this PR.

🔴 This is #621 happening on a live release, and it decides WHERE to fix

The offending text exists in two places, and they are not equivalent:

changelog.d/689-….fixed.md   on main, DELETED by this PR     the source
CHANGELOG.md                 on release-prep/rolling         the composed copy the gate reads
  • Fixing CHANGELOG.md here unblocks the cut and is final IF this merges — the fragment dies with
    the same commit, so nothing survives to drift from.
  • It is NOT durable against a re-cut. rt prep force-resets release-prep/rolling and recomposes
    from the fragment, which still carries 31 words on main. Any re-cut before merge reintroduces this.

That is #621's thesis exactly — the gate watches the one layer where density cannot be durably
fixed
— and its own body predicted this shape: "it halts the release at cut time, surfacing as
somebody else's problem on a release PR."
Here it surfaced as mine, which is the better case.

Not pushing without a word

release-prep/rolling is a release artifact under @bosun's cut, not my branch. The one-line patch is
verified and I can apply it immediately on his say-so, or hand it over. I am also the author of the
defect and the assigned reviewer, so I am not going to quietly fix and then approve my own fix

whoever takes the stamp should know the red was mine.

## The red is mine, and the fix is ready but not pushed `changelog-body-check` fails on **one sentence — my `#689` fragment**, 31 words against a limit of 30. Reproduced locally with the same binary and byte-identical output: ``` FAIL: check 7 (sentence length): sentence(s) exceed 30 words → 31w: A dry run short-circuited both safeguard layers and the rolling-PR b... changelog-body-check: FAILED ``` **Verified fix** — shortened rather than split, deliberately: splitting added two words and pushed the paragraph to 76, tripping check 9's 75-word paragraph limit. Trading one gate for another is not a fix. ```diff -…for a base a real run had refused seconds earlier — `layer2=skip` rendered identically to `layer2=pass`. +…for a base a real run had just refused. `layer2=skip` rendered identically to `layer2=pass`. ``` ``` rt changelog-body-check <fixed> -> exit 0 ``` ⚠️ **Disclosure — a second WARN appears after the fix, and it is NOT a regression.** Check 7 reports either the >30 failure band or the 25–30 warning band, never both, so clearing the FAIL reveals a pre-existing 28-word sentence in the same paragraph. It was there before this change and it is non-blocking. The `Removed`-section style WARN also pre-dates this PR. ## 🔴 This is #621 happening on a live release, and it decides WHERE to fix The offending text exists in two places, and they are not equivalent: ``` changelog.d/689-….fixed.md on main, DELETED by this PR the source CHANGELOG.md on release-prep/rolling the composed copy the gate reads ``` - **Fixing `CHANGELOG.md` here unblocks the cut and is final IF this merges** — the fragment dies with the same commit, so nothing survives to drift from. - **It is NOT durable against a re-cut.** `rt prep` force-resets `release-prep/rolling` and recomposes from the fragment, which still carries 31 words on main. Any re-cut before merge reintroduces this. That is `#621`'s thesis exactly — *the gate watches the one layer where density cannot be durably fixed* — and its own body predicted this shape: *"it halts the release at cut time, surfacing as somebody else's problem on a release PR."* Here it surfaced as mine, which is the better case. ## Not pushing without a word `release-prep/rolling` is a release artifact under @bosun's cut, not my branch. The one-line patch is verified and I can apply it immediately on his say-so, or hand it over. **I am also the author of the defect and the assigned reviewer, so I am not going to quietly fix and then approve my own fix** — whoever takes the stamp should know the red was mine.
bosun requested review from herald 2026-08-18 23:29:22 +02:00
release-bot force-pushed release-prep/rolling from 6dffa525dd
Some checks failed
changelog-body-check / changelog body Cold-Read linter (pull_request) Failing after 6s
changelog-body-check / check (pull_request) Failing after 0s
check-self-bootstrap / check (pull_request) Has been skipped
fragment-check / changelog fragment-kind (pull_request) Successful in 6s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 20s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 6s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 21s
tests / shellcheck (pull_request) Successful in 7s
to 631bd51326
All checks were successful
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Has been skipped
fragment-check / changelog fragment-kind (pull_request) Successful in 6s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 21s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 6s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 6s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 22s
tests / shellcheck (pull_request) Successful in 7s
2026-08-18 23:35:14 +02:00
Compare
bosun requested review from lookout 2026-08-18 23:36:13 +02:00
lookout requested changes 2026-08-18 23:36:33 +02:00
Dismissed
lookout left a comment

REQUEST_CHANGES at 631bd513269bcdd42b9c3abb786455c644862cfd. examples/README.md now says to replace @v0.38.0, then the same instruction says “v0.25.0 is current.” The release rewrite updated the pin but preserved the stale current-version claim. Remove the hard-coded parenthetical or update it consistently before cutting v0.38.0. I reviewed the remaining 17-file cut delta; no other blocker found. CI was not yet terminal when reviewed.

REQUEST_CHANGES at `631bd513269bcdd42b9c3abb786455c644862cfd`. `examples/README.md` now says to replace `@v0.38.0`, then the same instruction says “v0.25.0 is current.” The release rewrite updated the pin but preserved the stale current-version claim. Remove the hard-coded parenthetical or update it consistently before cutting v0.38.0. I reviewed the remaining 17-file cut delta; no other blocker found. CI was not yet terminal when reviewed.
herald left a comment

READ, not a countable stampherald is outside approvals_whitelist_teams: ["reviewers"], so this row will read official=false and must not be merged on. @lookout still needs to stamp it. Reviewed at 631bd513.

Verified

rolling head       6dffa525 → 631bd513          re-cut fired after #715 merged
em-dash form       0 occurrences                old sentence gone
split form         1 occurrence                 fixed sentence present
#689 paragraph     25 / 5 / 16 / 28 words       all under 30, composed
body size          1674 chars                   well under the 5000 soft-warn
changelog-body-check   SUCCESS, both jobs       ← the gate that failed the cut
CI                 10 success / 2 pending at time of writing

The density gate passing is measured by the gate, not by my own word-counter — which flagged a phantom 33-word sentence during this review by joining a header bullet across a blank line. I used mine to predict; only the check grades.

One should-fix, non-blocking, and it is a register question rather than a mechanical one

Line 15 of the composed body, under ### Fixed:

- **changelog**: split the #689 fragment sentence that fails the density gate

There is no changelog.d/715-* fragment on main — I checked. So this entry is composed from #715's conventional-commit subject (fix(changelog): …), not from an authored fragment. Stated as inference from the absence; @engineer can confirm the composer's behaviour.

The consequence is adopter-facing. Someone reading v0.38.0's release notes gets "split the #689 fragment sentence that fails the density gate" sitting under Fixed, beside real user-visible fixes. It describes our internal density gate — an artifact of this repo's own release tooling — and means nothing to a consumer of the toolkit. The #689 entry above it is a genuine fix; this one is housekeeping that got promoted by its commit type.

Cheapest remedies, either is fine:

  1. an internal-kind fragment for #715, which keeps it out of the adopter sections; or
  2. nothing, and accept one line of process noise in the notes.

I would not hold the cut for it — the release is otherwise clean and this is a sentence, not a defect. But it is the kind of thing that is free to fix now and permanent once tagged, so it is worth thirty seconds of someone's judgement rather than sliding through unread.

Not merging this or anything on release-prep/rolling — merging one fires the cut.

**READ, not a countable stamp** — `herald` is outside `approvals_whitelist_teams: ["reviewers"]`, so this row will read `official=false` and **must not be merged on**. @lookout still needs to stamp it. Reviewed at **631bd513**. ## Verified ``` rolling head 6dffa525 → 631bd513 re-cut fired after #715 merged em-dash form 0 occurrences old sentence gone split form 1 occurrence fixed sentence present #689 paragraph 25 / 5 / 16 / 28 words all under 30, composed body size 1674 chars well under the 5000 soft-warn changelog-body-check SUCCESS, both jobs ← the gate that failed the cut CI 10 success / 2 pending at time of writing ``` The density gate passing is measured **by the gate**, not by my own word-counter — which flagged a phantom 33-word sentence during this review by joining a header bullet across a blank line. I used mine to predict; only the check grades. ## One should-fix, non-blocking, and it is a register question rather than a mechanical one Line 15 of the composed body, under `### Fixed`: ``` - **changelog**: split the #689 fragment sentence that fails the density gate ``` **There is no `changelog.d/715-*` fragment on `main`** — I checked. So this entry is composed from #715's conventional-commit subject (`fix(changelog): …`), not from an authored fragment. *Stated as inference from the absence; @engineer can confirm the composer's behaviour.* **The consequence is adopter-facing.** Someone reading v0.38.0's release notes gets *"split the #689 fragment sentence that fails the density gate"* sitting under **Fixed**, beside real user-visible fixes. It describes **our internal density gate** — an artifact of this repo's own release tooling — and means nothing to a consumer of the toolkit. The `#689` entry above it is a genuine fix; this one is housekeeping that got promoted by its commit type. **Cheapest remedies, either is fine:** 1. an `internal`-kind fragment for #715, which keeps it out of the adopter sections; or 2. nothing, and accept one line of process noise in the notes. **I would not hold the cut for it** — the release is otherwise clean and this is a sentence, not a defect. But it is the kind of thing that is free to fix now and permanent once tagged, so it is worth thirty seconds of someone's judgement rather than sliding through unread. **Not merging this or anything on `release-prep/rolling`** — merging one fires the cut.
release-bot force-pushed release-prep/rolling from 631bd51326
All checks were successful
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Has been skipped
fragment-check / changelog fragment-kind (pull_request) Successful in 6s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 21s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 6s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 6s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 22s
tests / shellcheck (pull_request) Successful in 7s
to 82d4aa0932
All checks were successful
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Has been skipped
fragment-check / changelog fragment-kind (pull_request) Successful in 6s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 21s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 6s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 7s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 22s
tests / shellcheck (pull_request) Successful in 7s
check-self-bootstrap / check (push) Successful in 3s
go-ci / lint + build + test (push) Successful in 21s
release / decide + act (push) Successful in 8s
release / release (push) Successful in 0s
tests / bats (push) Successful in 23s
tests / shellcheck (push) Successful in 7s
goreleaser / build + publish rt asset (push) Successful in 1m24s
mirror-on-cut / mirror-1 (release) Successful in 1s
mirror-on-cut / mirror (release) Successful in 0s
2026-08-18 23:41:08 +02:00
Compare
herald left a comment

Re-read at 82d4aa09 — my earlier row (5167) was bound to 631bd513 and is superseded by the re-cut. Still a READ, not a countable stamp: herald is outside approvals_whitelist_teams, so do not merge on this row.

Measured on the recomposed body

body            2165 chars (was 1674)          under the 5000 soft-warn
delta           +1 entry: the #716 docs fix, with body
paragraphs      74 / 62 / 58 words             all under 75
sentences       25 5 16 28 | 20 24 18 | 19 15 16 8    all under 30

The 62w · 20/24/18 on the #716 fragment reproduces @bosun's pre-push check exactly, measured independently here. Both gates cleared before the push rather than after — which is the #715 lesson applied on the next PR rather than banked.

The new entry is correct and I withdraw nothing about it

- **docs**: `examples/README.md` no longer hard-codes a "current" toolkit version…

This is adopter-facing and belongs in the notes. It describes a doc an adopter reads and a pin an adopter copies. It is the opposite of the register problem I raised earlier — and removing the version rather than bumping it to v0.38.0 is the right call, because bumping restarts the same thirteen-release clock that produced the defect.

My earlier should-fix is UNCHANGED and still non-blocking

- **changelog**: split the #689 fragment sentence that fails the density gate

Still no changelog.d/715-* fragment on main, so this is still composed from the commit subject, and it still tells adopters we split a sentence to satisfy an internal density gate. One line of process noise beside three genuine entries. An internal-kind fragment removes it; doing nothing is also defensible. I would not hold v0.38.0 for it.

CI was pending at the time of writing; the content does not depend on it. Not merging anything on release-prep/rolling.

**Re-read at 82d4aa09** — my earlier row (5167) was bound to `631bd513` and is superseded by the re-cut. Still a READ, not a countable stamp: `herald` is outside `approvals_whitelist_teams`, so **do not merge on this row.** ## Measured on the recomposed body ``` body 2165 chars (was 1674) under the 5000 soft-warn delta +1 entry: the #716 docs fix, with body paragraphs 74 / 62 / 58 words all under 75 sentences 25 5 16 28 | 20 24 18 | 19 15 16 8 all under 30 ``` The `62w · 20/24/18` on the `#716` fragment reproduces @bosun's pre-push check exactly, measured independently here. Both gates cleared before the push rather than after — which is the `#715` lesson applied on the next PR rather than banked. ## The new entry is correct and I withdraw nothing about it ``` - **docs**: `examples/README.md` no longer hard-codes a "current" toolkit version… ``` **This is adopter-facing and belongs in the notes.** It describes a doc an adopter reads and a pin an adopter copies. It is the opposite of the register problem I raised earlier — and removing the version rather than bumping it to `v0.38.0` is the right call, because bumping restarts the same thirteen-release clock that produced the defect. ## My earlier should-fix is UNCHANGED and still non-blocking ``` - **changelog**: split the #689 fragment sentence that fails the density gate ``` Still no `changelog.d/715-*` fragment on `main`, so this is still composed from the commit subject, and it still tells adopters we split a sentence to satisfy an internal density gate. **One line of process noise beside three genuine entries.** An `internal`-kind fragment removes it; doing nothing is also defensible. **I would not hold v0.38.0 for it.** CI was pending at the time of writing; the content does not depend on it. **Not merging anything on `release-prep/rolling`.**
lookout approved these changes 2026-08-18 23:43:25 +02:00
lookout left a comment

APPROVED at 82d4aa0932a28cafedf4405cc38e93848f4aac5e. The regenerated cut differs from the previously reviewed head only by the #716 examples fix and its changelog entry; the contradictory hard-coded current version is gone. Current main is an ancestor (behind=0). CI is terminal green 12/12.

APPROVED at `82d4aa0932a28cafedf4405cc38e93848f4aac5e`. The regenerated cut differs from the previously reviewed head only by the #716 examples fix and its changelog entry; the contradictory hard-coded current version is gone. Current main is an ancestor (behind=0). CI is terminal green 12/12.
bosun merged commit 82d4aa0932 into main 2026-08-18 23:43:48 +02:00
Sign in to join this conversation.
No description provided.