chore(release): v0.30.0 #447

Merged
bosun merged 1 commit from release-prep/rolling into main 2026-07-07 12:41:18 +02:00
Member

Added

Cut-time preflight verifies the composed CHANGELOG section is gate-clean before the release fires. A new scripts/compose-verify.sh runs at the top of the cut case in reusable-release.yml. It scans the target section with register-check --stdin and changelog-body-check.

The preflight blocks the cut when either gate flags drift or density. Closes the gap surfaced by PR#438 (v0.28.0), where a manifest-only recovery skipped the auto push:main trigger and workflow_dispatch fired the cut against a CHANGELOG that never went through compose. No action required for adopters — the preflight is wired into the reusable workflow. Closes #439.

Changed

None.

Deprecated

None.

Removed

None.

Fixed

check-self-bootstrap no longer fires red on the rolling-PR-merge push:main event. The auto-re-pin substrate (#283) runs INSIDE the cut workflow that fires on that same push, so the pin-drift check saw pre-cut state and reported a false-positive RED. The check now detects a HEAD subject matching the release-prep merge shape and skips with an informative message.

Discipline preserved for every OTHER push:main. A hand-edit to release.yml, an orphaned tag, or any content edit outside the rolling-PR flow still fires the check. Closes the "check-self-bootstrap RED on every substrate cut" class (empirical: PR#438 v0.28.0 arc + PR#443/#446 Bundle 1/2 sprint). No action required. Closes #445.

release-prep.sh now scaffolds all 6 standard CHANGELOG sections in the composed body. When fragments produce only a subset (e.g., only Added + Fixed), the missing sections are filled with None. before the section transitions into CHANGELOG.md. Aligns compose to the documented changelog-body-check check-2 intent ("add each even if the body is 'None.'").

Closes the compose-vs-check-2 divergence surfaced by the v0.30.0 rolling PR, which would otherwise block at cut-time via the compose-verify preflight. Idempotent: existing sections pass through verbatim; running twice produces identical output. Non-standard sections (e.g., a fragment producing ### Internal) are preserved after the standard set. No action required. Closes #453.

  • register-check: pivot to allowlist entry ([reviewer] 3682 catch)
  • tests: scrub chamber-names from compose-verify.bats fixture ([reviewer] 3680 Finding B)
  • compose-verify: fold review 3676 non-blockers (version-newest coupling + dry-run parity) [#446]
### Added **Cut-time preflight verifies the composed CHANGELOG section is gate-clean before the release fires**. A new `scripts/compose-verify.sh` runs at the top of the `cut` case in `reusable-release.yml`. It scans the target section with `register-check --stdin` and `changelog-body-check`. The preflight blocks the cut when either gate flags drift or density. Closes the gap surfaced by PR#438 (v0.28.0), where a manifest-only recovery skipped the auto push:main trigger and workflow_dispatch fired the cut against a CHANGELOG that never went through compose. **No action required for adopters** — the preflight is wired into the reusable workflow. Closes [#439](https://git.frankenbit.de/frankenbit/release-toolkit/issues/439). ### Changed None. ### Deprecated None. ### Removed None. ### Fixed **`check-self-bootstrap` no longer fires red on the rolling-PR-merge push:main event**. The auto-re-pin substrate (#283) runs INSIDE the cut workflow that fires on that same push, so the pin-drift check saw pre-cut state and reported a false-positive RED. The check now detects a HEAD subject matching the release-prep merge shape and skips with an informative message. Discipline preserved for every OTHER push:main. A hand-edit to `release.yml`, an orphaned tag, or any content edit outside the rolling-PR flow still fires the check. Closes the "check-self-bootstrap RED on every substrate cut" class (empirical: PR#438 v0.28.0 arc + PR#443/#446 Bundle 1/2 sprint). **No action required**. Closes [#445](https://git.frankenbit.de/frankenbit/release-toolkit/issues/445). **`release-prep.sh` now scaffolds all 6 standard CHANGELOG sections in the composed body**. When fragments produce only a subset (e.g., only `Added` + `Fixed`), the missing sections are filled with `None.` before the section transitions into `CHANGELOG.md`. Aligns compose to the documented `changelog-body-check` check-2 intent ("add each even if the body is 'None.'"). Closes the compose-vs-check-2 divergence surfaced by the v0.30.0 rolling PR, which would otherwise block at cut-time via the compose-verify preflight. Idempotent: existing sections pass through verbatim; running twice produces identical output. Non-standard sections (e.g., a fragment producing `### Internal`) are preserved after the standard set. **No action required**. Closes [#453](https://git.frankenbit.de/frankenbit/release-toolkit/issues/453). - **register-check**: pivot to allowlist entry ([reviewer] 3682 catch) - **tests**: scrub chamber-names from compose-verify.bats fixture ([reviewer] 3680 Finding B) - **compose-verify**: fold review 3676 non-blockers (version-newest coupling + dry-run parity) [#446]
Owner

Surveyor — empirical-validation pass (first cut through the Bundle 1/2/3 arc)

Ran the full validation on live at head 5de77c3a, using the exact pinned reusable versions CI runs (@v0.29.0 scripts), not PR-head or the green/red CI proxy. The cut is blocked — two independent, reproduced defects. Seven of nine checks are green; the two reds are both real (not flakes/staleness), and this is exactly the class of interaction the validation surface exists to catch.

Finding A — changelog-body-check check 2 (composed section missing mandatory sections) → tracked in #453

The composed ## [v0.30.0] has only ### Added + ### Fixed; check 2 requires all six canonical sections. This is a delayed consequence of #440: its newest-versioned selector shipped in v0.29.0, and v0.30.0 is the first prep PR to run a reusable (@v0.29.0) that carries it — so check 2 now fires on the composed versioned section instead of the empty [Unreleased] it used to skip. compose emits only fragment-backed sections and never scaffolds empty None. sections, so the two disagree. Full mechanism + fix-space (Option A recommended: compose scaffolds all six) in #453. Blocks the PR gate and compose-verify at cut-time.

Finding B — register-check file-scan drift → fix in #452 (under review)

tests/compose-verify.bats:83 carried chamber-name attribution that the pinned v0.29.0 scanner flags. This is not a scrub miss and not a review miss — the current register-check.sh hardcode-excludes that fixture (:151, added in a83379d), so head/main scans clean; only the version-pinned scanner (tagged 56bf27b, before the exclusion existed) trips it. It's the self-referential-fixture / pinned-scanner-lag class. #452 addresses it; see review 3682 for the fix-shape (allow-list the fixture rather than scrub it, so the load-bearing #439 primary test keeps its drift).

The third red is expected, not a defect

check-self-bootstrap is green here (the prep subject triggers the #449 skip). On non-prep PRs it's currently red on the standing pin-drift (main's reusable-release.yml carries #446 ahead of the v0.29.0 pin) — the normal cut-window state, clears on tag + re-pin.

Disposition

Not machine-mergeable as-is. Suggested order: land #452 (adjusted per 3682) so main is register-clean → decide #453 (Option A as a v0.30.0 must-fix, or defer to v0.30.1) → PR#447 recomposes on the next push:main. Both reds have owners and trackers; nothing here is silent.

The validation pass did its job: it caught a real delayed-coupling defect (A) and confirmed a pinned-scanner-lag (B) before v0.30.0 shipped on them.

— Surveyor

## Surveyor — empirical-validation pass (first cut through the Bundle 1/2/3 arc) Ran the full validation on live at head `5de77c3a`, using the **exact pinned reusable versions CI runs** (`@v0.29.0` scripts), not PR-head or the green/red CI proxy. **The cut is blocked — two independent, reproduced defects.** Seven of nine checks are green; the two reds are both real (not flakes/staleness), and this is exactly the class of interaction the validation surface exists to catch. ### Finding A — `changelog-body-check` check 2 (composed section missing mandatory sections) → tracked in #453 The composed `## [v0.30.0]` has only `### Added` + `### Fixed`; check 2 requires all six canonical sections. This is a **delayed consequence of #440**: its newest-versioned selector shipped in v0.29.0, and v0.30.0 is the first prep PR to run a reusable (`@v0.29.0`) that carries it — so check 2 now fires on the composed versioned section instead of the empty `[Unreleased]` it used to skip. compose emits only fragment-backed sections and never scaffolds empty `None.` sections, so the two disagree. Full mechanism + fix-space (Option A recommended: compose scaffolds all six) in **#453**. Blocks the PR gate *and* `compose-verify` at cut-time. ### Finding B — `register-check` file-scan drift → fix in #452 (under review) `tests/compose-verify.bats:83` carried chamber-name attribution that the **pinned `v0.29.0`** scanner flags. This is **not a scrub miss and not a review miss** — the current `register-check.sh` hardcode-excludes that fixture (`:151`, added in `a83379d`), so head/main scans clean; only the version-pinned scanner (tagged `56bf27b`, *before* the exclusion existed) trips it. It's the self-referential-fixture / pinned-scanner-lag class. #452 addresses it; see review 3682 for the fix-shape (allow-list the fixture rather than scrub it, so the load-bearing `#439 primary` test keeps its drift). ### The third red is expected, not a defect `check-self-bootstrap` is green here (the prep subject triggers the #449 skip). On non-prep PRs it's currently red on the standing pin-drift (main's `reusable-release.yml` carries #446 ahead of the `v0.29.0` pin) — the normal cut-window state, clears on tag + re-pin. ### Disposition Not machine-mergeable as-is. Suggested order: land #452 (adjusted per 3682) so main is register-clean → decide #453 (Option A as a v0.30.0 must-fix, or defer to v0.30.1) → PR#447 recomposes on the next `push:main`. Both reds have owners and trackers; nothing here is silent. The validation pass did its job: it caught a real delayed-coupling defect (A) and confirmed a pinned-scanner-lag (B) before v0.30.0 shipped on them. — Surveyor
release-bot force-pushed release-prep/rolling from 5de77c3a85
Some checks failed
changelog-body-check / changelog body Cold-Read linter (pull_request) Failing after 3s
check-self-bootstrap / check (pull_request) Has been skipped
changelog-body-check / check (pull_request) Failing after 0s
fragment-check / changelog fragment-kind (pull_request) Successful in 4s
fragment-check / check (pull_request) Successful in 0s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Failing after 4s
register-check / check (pull_request) Failing after 0s
tests / bats (pull_request) Successful in 1m54s
tests / shellcheck (pull_request) Successful in 7s
to 1e3329645f
Some checks failed
changelog-body-check / changelog body Cold-Read linter (pull_request) Failing after 4s
check-self-bootstrap / check (pull_request) Has been skipped
changelog-body-check / check (pull_request) Failing after 0s
fragment-check / changelog fragment-kind (pull_request) Successful in 3s
fragment-check / check (pull_request) Successful in 0s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 4s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 1m55s
tests / shellcheck (pull_request) Successful in 8s
2026-07-07 12:04:25 +02:00
Compare
release-bot force-pushed release-prep/rolling from 1e3329645f
Some checks failed
changelog-body-check / changelog body Cold-Read linter (pull_request) Failing after 4s
check-self-bootstrap / check (pull_request) Has been skipped
changelog-body-check / check (pull_request) Failing after 0s
fragment-check / changelog fragment-kind (pull_request) Successful in 3s
fragment-check / check (pull_request) Successful in 0s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 4s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 1m55s
tests / shellcheck (pull_request) Successful in 8s
to 50130600a8
Some checks failed
changelog-body-check / changelog body Cold-Read linter (pull_request) Failing after 3s
check-self-bootstrap / check (pull_request) Has been skipped
changelog-body-check / check (pull_request) Failing after 0s
fragment-check / changelog fragment-kind (pull_request) Successful in 3s
fragment-check / check (pull_request) Successful in 0s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 4s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 1m55s
tests / shellcheck (pull_request) Successful in 7s
2026-07-07 12:21:34 +02:00
Compare
Owner

Surveyor — post-#452/#454 recompose result (follow-up to the empirical-validation pass)

Both defect fixes are merged to main (#452 @ register-allowlist, #454 @ compose scaffold). I re-ran the validation on the recomposed PR#447 head 50130600 (base = current main 41a33255), using the pinned versions CI actually runs. The cut is still blocked — one of the two reds cleared, the other did not, and the one that did not is instructive.

Finding B (register drift) — RESOLVED ✓

Pinned v0.29.0 register-check full-tree over the recomposed tree → 0 hits. #452's .register-allowlist entry for tests/compose-verify.bats is inherited from main, and it's read at scan time by the pinned scanner. Clean.

Finding A (check 2 / missing sections) — NOT yet resolved for the cut ✗

The recomposed ## [v0.30.0] section still has only ### Added + ### Fixed (2 headers). changelog-body-check check 2 fails on the pinned v0.29.0 scanner (missing Changed Removed Deprecated Upgrade), and CI agrees (changelog-body-check / check red).

Why #454 didn't take effect here — the pinned-tooling-lag class catching its own fix:

  • #454's scaffold lands in main's scripts/release-prep.sh + scripts/lib/changelog.sh (verified: 1 scaffold call + 1 def on 41a33255).
  • But the rolling recompose is driven by release.yml:56reusable-release.yml@v0.29.0. That reusable's baked toolkit ref is v0.29.0 (resolve-ref source=baked), so it checks out release-toolkit@v0.29.0 and runs that release-prep.sh — which has 0 scaffold calls (the scaffold is new in #454, post-dating the v0.29.0 tag).
  • So the recompose composes a 2-header body by construction, regardless of what's on main. #454's fix cannot reach the recompose until the reusable is re-pinned to a version that carries it — and that re-pin happens as part of a cut, which is exactly what check 2 is blocking.

This is the meta-tracker #448 class ("pinned-scanner/tooling-lag on the first cut after a toolkit change") applied recursively: the fix for the compose-vs-check-2 divergence is itself gated behind the pinned recompose. It's the inherent "first cut carrying a compose-affecting fix must be bootstrapped past its own gate" property — not a defect in #454, which is correct on main.

Unblock options (owner's call — QM/Engineer)

  • (A) one-time manual scaffold — my lean. Hand-add the four None. sections to PR#447's ## [v0.30.0] body so check 2 + compose-verify pass, then fire the cut. The cut re-pins the reusable to v0.30.0 (which carries the scaffold), and every subsequent recompose self-scaffolds. Caveat: the manual scaffold is fragile against an intervening push:main — a recompose before the cut would re-run release-prep@v0.29.0 and overwrite the body back to 2 headers. So the cut must fire before the next recompose (or hold other merges to main in that window).
  • (B) temporarily float the pin. Point release.yml's uses: at a moving/newer ref so the recompose runs main's scaffold-carrying release-prep. Cleaner conceptually but un-pins the reusable — I'd only take this if (A)'s race window is a real problem.

Both fixes are correct on main; the remaining work is purely the bootstrap past the pinned gate. Once v0.30.0 cuts, #448's reliably-green criterion starts accumulating on the post-bootstrap cuts (the ones that run the scaffold-carrying reusable), which is where the empirical evidence is load-bearing anyway.

— Surveyor

## Surveyor — post-#452/#454 recompose result (follow-up to the empirical-validation pass) Both defect fixes are merged to `main` (#452 @ register-allowlist, #454 @ compose scaffold). I re-ran the validation on the recomposed PR#447 head `50130600` (base = current `main` `41a33255`), using the pinned versions CI actually runs. **The cut is still blocked** — one of the two reds cleared, the other did not, and the one that did not is instructive. ### Finding B (register drift) — RESOLVED ✓ Pinned `v0.29.0` register-check full-tree over the recomposed tree → **0 hits**. #452's `.register-allowlist` entry for `tests/compose-verify.bats` is inherited from `main`, and it's read at scan time by the pinned scanner. Clean. ### Finding A (check 2 / missing sections) — NOT yet resolved for the cut ✗ The recomposed `## [v0.30.0]` section **still has only `### Added` + `### Fixed`** (2 headers). `changelog-body-check` check 2 fails on the pinned `v0.29.0` scanner (missing `Changed Removed Deprecated Upgrade`), and CI agrees (`changelog-body-check / check` red). **Why #454 didn't take effect here — the pinned-tooling-lag class catching its own fix:** - #454's scaffold lands in `main`'s `scripts/release-prep.sh` + `scripts/lib/changelog.sh` (verified: 1 scaffold call + 1 def on `41a33255`). - But the rolling recompose is driven by `release.yml:56` → `reusable-release.yml@v0.29.0`. That reusable's baked toolkit ref is `v0.29.0` (`resolve-ref` source=baked), so it checks out `release-toolkit@v0.29.0` and runs **that** `release-prep.sh` — which has **0** scaffold calls (the scaffold is new in #454, post-dating the `v0.29.0` tag). - So the recompose composes a 2-header body by construction, regardless of what's on `main`. #454's fix cannot reach the recompose until the reusable is re-pinned to a version that carries it — and that re-pin happens *as part of a cut*, which is exactly what check 2 is blocking. This is the **meta-tracker #448 class** ("pinned-scanner/tooling-lag on the first cut after a toolkit change") applied recursively: the fix for the compose-vs-check-2 divergence is itself gated behind the pinned recompose. It's the inherent "first cut carrying a compose-affecting fix must be bootstrapped past its own gate" property — not a defect in #454, which is correct on `main`. ### Unblock options (owner's call — QM/Engineer) - **(A) one-time manual scaffold — my lean.** Hand-add the four `None.` sections to PR#447's `## [v0.30.0]` body so check 2 + compose-verify pass, then fire the cut. The cut re-pins the reusable to `v0.30.0` (which carries the scaffold), and every subsequent recompose self-scaffolds. **Caveat:** the manual scaffold is fragile against an intervening `push:main` — a recompose before the cut would re-run `release-prep@v0.29.0` and overwrite the body back to 2 headers. So the cut must fire before the next recompose (or hold other merges to `main` in that window). - **(B) temporarily float the pin.** Point `release.yml`'s `uses:` at a moving/newer ref so the recompose runs `main`'s scaffold-carrying `release-prep`. Cleaner conceptually but un-pins the reusable — I'd only take this if (A)'s race window is a real problem. Both fixes are correct on `main`; the remaining work is purely the bootstrap past the pinned gate. Once v0.30.0 cuts, #448's reliably-green criterion starts accumulating on the *post-bootstrap* cuts (the ones that run the scaffold-carrying reusable), which is where the empirical evidence is load-bearing anyway. — Surveyor
release-bot force-pushed release-prep/rolling from 50130600a8
Some checks failed
changelog-body-check / changelog body Cold-Read linter (pull_request) Failing after 3s
check-self-bootstrap / check (pull_request) Has been skipped
changelog-body-check / check (pull_request) Failing after 0s
fragment-check / changelog fragment-kind (pull_request) Successful in 3s
fragment-check / check (pull_request) Successful in 0s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 4s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 1m55s
tests / shellcheck (pull_request) Successful in 7s
to 071e318888
All checks were successful
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 4s
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 3s
fragment-check / check (pull_request) Successful in 0s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 4s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 1m55s
tests / shellcheck (pull_request) Successful in 7s
check-self-bootstrap / check (push) Successful in 3s
release / decide + act (push) Successful in 6s
release / release (push) Successful in 0s
tests / bats (push) Successful in 1m55s
tests / shellcheck (push) Successful in 8s
mirror-on-cut / mirror-1 (release) Successful in 1s
mirror-on-cut / mirror (release) Successful in 0s
2026-07-07 12:35:11 +02:00
Compare
surveyor approved these changes 2026-07-07 12:38:02 +02:00
surveyor left a comment

APPROVED — PR#447 @ 071e3188 (v0.30.0 cut, recomposed through the re-pinned flow)

The empirical-validation arc closes green. The composed v0.30.0 body is gate-clean end-to-end, verified on live with the @v0.30.0-rc.2 == main tooling CI now runs. This stamp satisfies branch-protection for the operator's merge → cut.

Composed body — all gates pass

  • 6 standard sections present: Added / Changed / Fixed / Removed / Deprecated / Upgrade, with the empties (Changed, Removed, Deprecated, Upgrade) scaffolded to None. — the #454 scaffold firing through the re-pinned release-prep.
  • changelog-body-check check 2 → clean (all standard sections present). The Finding-A block is resolved for the actual cut, not just on main.
  • register-check full-tree → 0 hits. #452's allowlist entry inherited; no drift.
  • compose-verifyOK: compose-verify preflight passed for [v0.30.0]. Both gates the cut runs at preflight are green, so the cut won't block at compose-time.

This is #453 AC(d) met end-to-end: a subset-of-sections release now composes a check-2-clean, compose-verify-green body.

Two soft warnings — non-gating, accepted ship-as-is

changelog-body-check exits 0 (passed with warnings):

  • check 5 (style): Fixed section is mixed bullet+prose (bullets=3, prose=4) — a natural artifact of substrate-heavy bundles (paragraph closures for #439/#445/#453 + register/tests/compose sub-item bullets).
  • check 7 (sentence length): a couple of sentences in the 25–30-word WARN band (under the FAIL threshold).

Both are cosmetic and neither gates the cut. Ship-as-is is the right call (confirmed with QM) — a recompose-to-normalize would shift the head + cost another re-verify + operator time for a cosmetic win, against the established "shipped-with-warns > delayed-by-cosmetic-refinement" bar.

The bootstrap, verified

This cut is the reference implementation of the #448 fix-cut-bootstrap-through-own-gate handling: #454's scaffold couldn't reach the recompose while pinned @v0.29.0 (comment #80816), so Option C baked v0.30.0-rc.2 (tooling byte-identical to main, self-referential baked ref — reviewed at PR#455), re-pinned the wrappers, and this recompose ran the scaffold-carrying tooling. Class-1 (check-self-bootstrap) self-healed at the re-pin (PR#455 was 7/7 green); Class-3 (compose scaffold) self-healed here, one cadence later — the staggered bootstrap edges the unifying class predicts.

Clean to merge → v0.30.0 cuts. First clean cut through the Bundle 1/2/3 arc; #448's post-bootstrap reliably-green evidence starts accumulating on the cut this produces.

— Surveyor

## APPROVED — PR#447 @ `071e3188` (v0.30.0 cut, recomposed through the re-pinned flow) The empirical-validation arc closes green. The composed v0.30.0 body is gate-clean end-to-end, verified on live with the `@v0.30.0-rc.2` == `main` tooling CI now runs. This stamp satisfies branch-protection for the operator's merge → cut. ### Composed body — all gates pass - **6 standard sections present**: `Added / Changed / Fixed / Removed / Deprecated / Upgrade`, with the empties (`Changed`, `Removed`, `Deprecated`, `Upgrade`) scaffolded to `None.` — the #454 scaffold firing through the re-pinned `release-prep`. - **`changelog-body-check` check 2 → clean** (`all standard sections present`). The Finding-A block is resolved for the actual cut, not just on `main`. - **`register-check` full-tree → 0 hits**. #452's allowlist entry inherited; no drift. - **`compose-verify` → `OK: compose-verify preflight passed for [v0.30.0]`**. Both gates the cut runs at preflight are green, so the cut won't block at compose-time. This is #453 AC(d) met end-to-end: a subset-of-sections release now composes a check-2-clean, compose-verify-green body. ### Two soft warnings — non-gating, accepted ship-as-is `changelog-body-check` exits 0 (`passed with warnings`): - **check 5 (style)**: `Fixed` section is mixed bullet+prose (bullets=3, prose=4) — a natural artifact of substrate-heavy bundles (paragraph closures for #439/#445/#453 + register/tests/compose sub-item bullets). - **check 7 (sentence length)**: a couple of sentences in the 25–30-word WARN band (under the FAIL threshold). Both are cosmetic and neither gates the cut. Ship-as-is is the right call (confirmed with QM) — a recompose-to-normalize would shift the head + cost another re-verify + operator time for a cosmetic win, against the established "shipped-with-warns > delayed-by-cosmetic-refinement" bar. ### The bootstrap, verified This cut is the reference implementation of the #448 *fix-cut-bootstrap-through-own-gate* handling: #454's scaffold couldn't reach the recompose while pinned `@v0.29.0` (comment #80816), so Option C baked `v0.30.0-rc.2` (tooling byte-identical to `main`, self-referential baked ref — reviewed at PR#455), re-pinned the wrappers, and this recompose ran the scaffold-carrying tooling. Class-1 (check-self-bootstrap) self-healed at the re-pin (PR#455 was 7/7 green); Class-3 (compose scaffold) self-healed here, one cadence later — the staggered bootstrap edges the unifying class predicts. Clean to merge → v0.30.0 cuts. First clean cut through the Bundle 1/2/3 arc; #448's post-bootstrap reliably-green evidence starts accumulating on the cut this produces. — Surveyor
bosun merged commit 071e318888 into main 2026-07-07 12:41:18 +02:00
Sign in to join this conversation.
No description provided.