fix(release-prep): Bundle 1 v0.28.1 must-fix — target section + dedup + register-scrub [#440 #441 #442] #443

Merged
alex merged 2 commits from i/440-441-442-bundle-1 into main 2026-07-06 23:06:33 +02:00

Summary

v0.28.1 must-fix Bundle 1 — three size/S register-check / machinery fixes surfaced by review 3668 on PR#438 (v0.28.0 rolling cut). All three collaborated to allow chamber-name attributions, duplicate CC bullets, and vacuous density-check passes to ship in v0.28.0's composed CHANGELOG.

  • #440changelog-body-check now targets the newest ## [vX.Y.Z] section instead of the first ## [ (which on a composed CHANGELOG is the empty [Unreleased] placeholder above the transitioned section). Falls back to [Unreleased] only when no versioned section exists. Final fallback to any ## [ preserves check-1 FAIL semantic for malformed headers (CI reads "content invalid", not exit-2 "script broken").

  • #441changelog_dedup_cc_by_fragment_refs catches (closes #NNN) / (fixes #NNN) / Closes #NNN. / closes #123, #456 bullet formats via a bare #NNN ref + word-boundary regex guard ((^|[^0-9])#NNN([^0-9]|$)). One unified pattern replaces the pre-fix trailer + bolded-scope shapes and holds against false-positive prefix matches (#4380 does NOT match #438).

  • #442cc_categorize_commits_since scrubs REGISTER_PATTERNS matches from CC bullet descriptions at emission time, replacing each with [reviewer] (option (b) scrub-emission per review 3668 fix-path). Extracts REGISTER_PATTERNS + register_build_regex into new scripts/lib/register-patterns.sh so register-check.sh (PR-time gate) and conventional-commits.sh (compose-time filter) share one source of truth. The register-check --stdin FATAL in release-prep.sh stays wired as defense-in-depth for fragment-side drift the emission scrub does not cover.

Why bundled

All three sit on the same substrate (register-check + CHANGELOG composition) and were surfaced together by the PR#438 empirical anchor. Single Surveyor review cycle per Bosun bus c977 dispatch. Bundle 2 (#439 workflow_dispatch + push:main compose-path unification) follows in a separate solo PR.

What this PR does NOT do

  • Does NOT touch the compose-path divergence between workflow_dispatch and push:main — that is Bundle 2 (#439).
  • Does NOT add adopter-overridable REGISTER_PATTERNS — that is deferred to #435. The extraction into register-patterns.sh is a natural extension point when #435 lands, but no adopter-visible override surface here.
  • Does NOT rewrite v0.28.0's shipped CHANGELOG — historical record stays as-shipped. The .register-allowlist entry for CHANGELOG.md (per feedback_ac_deferral_discipline principle) preserves the frozen release history.

Test coverage

  • Bats: 13 new fixtures across changelog-body-check.bats / changelog.bats / conventional-commits.bats. Full suite 717/717 green.
  • Empirical PR#438-shape reproduction:
    • [Unreleased] above [v0.28.0] composed shape → density check fires on the real body (was PASS vacuously before).
    • (closes #438) / (fixes #440) / Closes #440, #438 bullets all deduped when matching fragments exist.
    • fold Surveyor 3664 non-blocking nits subject → - **cli**: fold [reviewer] 3664 non-blocking nits bullet.
  • Register-check: file-scan + PR-time --git-log both green after genericizing 3 "Surveyor 3668" comment anchors to "review 3668" + narrow exclusions for register-patterns.sh (pattern source-of-truth) + conventional-commits.bats (compose-time scrub tests).

Follow-ups

  • Bundle 2 (#439) — workflow_dispatch + push:main compose path unification (size/M solo PR, post-Bundle-1 merge).
  • v0.28.1 patch cut after Bundle 2 lands → re-pin → #338 memorial-chore fold → v1.0.0 tag.
  • #435 — adopter-overridable REGISTER_PATTERNS extension (non-blocking; consumer opt-out surface for the extracted lib).

Closes #440, closes #441, closes #442.

## Summary **v0.28.1 must-fix Bundle 1** — three size/S register-check / machinery fixes surfaced by review 3668 on PR#438 (v0.28.0 rolling cut). All three collaborated to allow chamber-name attributions, duplicate CC bullets, and vacuous density-check passes to ship in v0.28.0's composed CHANGELOG. - **[#440](https://git.frankenbit.de/frankenbit/release-toolkit/issues/440)** — `changelog-body-check` now targets the newest `## [vX.Y.Z]` section instead of the first `## [` (which on a composed CHANGELOG is the empty `[Unreleased]` placeholder above the transitioned section). Falls back to `[Unreleased]` only when no versioned section exists. Final fallback to any `## [` preserves check-1 FAIL semantic for malformed headers (CI reads "content invalid", not exit-2 "script broken"). - **[#441](https://git.frankenbit.de/frankenbit/release-toolkit/issues/441)** — `changelog_dedup_cc_by_fragment_refs` catches `(closes #NNN)` / `(fixes #NNN)` / `Closes #NNN.` / `closes #123, #456` bullet formats via a bare `#NNN` ref + word-boundary regex guard (`(^|[^0-9])#NNN([^0-9]|$)`). One unified pattern replaces the pre-fix trailer + bolded-scope shapes and holds against false-positive prefix matches (`#4380` does NOT match `#438`). - **[#442](https://git.frankenbit.de/frankenbit/release-toolkit/issues/442)** — `cc_categorize_commits_since` scrubs `REGISTER_PATTERNS` matches from CC bullet descriptions at emission time, replacing each with `[reviewer]` (option (b) scrub-emission per review 3668 fix-path). Extracts `REGISTER_PATTERNS` + `register_build_regex` into new `scripts/lib/register-patterns.sh` so `register-check.sh` (PR-time gate) and `conventional-commits.sh` (compose-time filter) share one source of truth. The `register-check --stdin` FATAL in `release-prep.sh` stays wired as defense-in-depth for fragment-side drift the emission scrub does not cover. ## Why bundled All three sit on the same substrate (register-check + CHANGELOG composition) and were surfaced together by the PR#438 empirical anchor. Single Surveyor review cycle per Bosun bus c977 dispatch. Bundle 2 (#439 workflow_dispatch + push:main compose-path unification) follows in a separate solo PR. ## What this PR does NOT do - **Does NOT** touch the compose-path divergence between `workflow_dispatch` and `push:main` — that is Bundle 2 (#439). - **Does NOT** add adopter-overridable `REGISTER_PATTERNS` — that is deferred to [#435](https://git.frankenbit.de/frankenbit/release-toolkit/issues/435). The extraction into `register-patterns.sh` is a natural extension point when #435 lands, but no adopter-visible override surface here. - **Does NOT** rewrite v0.28.0's shipped CHANGELOG — historical record stays as-shipped. The `.register-allowlist` entry for `CHANGELOG.md` (per `feedback_ac_deferral_discipline` principle) preserves the frozen release history. ## Test coverage - **Bats:** 13 new fixtures across `changelog-body-check.bats` / `changelog.bats` / `conventional-commits.bats`. Full suite **717/717 green**. - **Empirical PR#438-shape reproduction:** - `[Unreleased]` above `[v0.28.0]` composed shape → density check fires on the real body (was PASS vacuously before). - `(closes #438)` / `(fixes #440)` / `Closes #440, #438` bullets all deduped when matching fragments exist. - `fold Surveyor 3664 non-blocking nits` subject → `- **cli**: fold [reviewer] 3664 non-blocking nits` bullet. - **Register-check:** file-scan + PR-time `--git-log` both green after genericizing 3 "Surveyor 3668" comment anchors to "review 3668" + narrow exclusions for `register-patterns.sh` (pattern source-of-truth) + `conventional-commits.bats` (compose-time scrub tests). ## Follow-ups - **Bundle 2 (#439)** — workflow_dispatch + push:main compose path unification (size/M solo PR, post-Bundle-1 merge). - **v0.28.1 patch cut** after Bundle 2 lands → re-pin → #338 memorial-chore fold → v1.0.0 tag. - **#435** — adopter-overridable `REGISTER_PATTERNS` extension (non-blocking; consumer opt-out surface for the extracted lib). Closes #440, closes #441, closes #442.
fix(release-prep): Bundle 1 v0.28.1 must-fix — target section + dedup + register-scrub [#440 #441 #442]
Some checks failed
check-self-bootstrap / check (pull_request) Failing after 3s
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) Failing after 4s
register-check / check (pull_request) Failing after 0s
tests / bats (pull_request) Successful in 1m53s
tests / shellcheck (pull_request) Successful in 8s
b469d1121a
Three size/S register-check/machinery fixes surfaced by review 3668 on
PR#438 (v0.28.0 rolling cut). All three collaborated to allow chamber-
name attributions + duplicate CC bullets + vacuous density-check passes
to ship in v0.28.0's composed CHANGELOG. Fixes:

* **#440** changelog-body-check now targets the newest versioned
  section (`## [vX.Y.Z]`) instead of the first `## [`, which on a
  composed CHANGELOG is the still-empty `[Unreleased]` placeholder
  above the newly-transitioned section. Falls back to `[Unreleased]`
  only when no versioned section exists (pre-transition state). Final
  fallback to any `## [` preserves check-1 FAIL semantic for malformed
  headers so CI still sees "content invalid" instead of exit-2
  "script broken".

* **#441** changelog_dedup_cc_by_fragment_refs now catches
  `(closes #NNN)` / `(fixes #NNN)` / `Closes #NNN.` / `closes #123, #456`
  bullet formats via a bare `#NNN` ref + word-boundary regex guard
  (`(^|[^0-9])#NNN([^0-9]|$)`). Replaces the pre-fix trailer-only +
  bolded-scope shapes with a single unified pattern that also holds
  against false-positive prefix matches (`#4380` does NOT match `#438`).

* **#442** cc_categorize_commits_since scrubs REGISTER_PATTERNS matches
  from CC bullet descriptions at emission time, replacing each with
  `[reviewer]` (option (b) scrub-emission per review 3668 fix-path).
  Extracts REGISTER_PATTERNS + register_build_regex into new
  scripts/lib/register-patterns.sh so both register-check.sh (PR-time
  gate) and conventional-commits.sh (compose-time filter) share the
  same list. release-prep.sh's `--stdin` FATAL stays wired as defense-
  in-depth for fragment-side drift the scrub doesn't cover.

Coverage:

* Bats: 13 new fixtures across changelog-body-check.bats /
  changelog.bats / conventional-commits.bats. Full suite 717/717
  green.
* Empirical: verified against PR#438-shape composed CHANGELOG (Unreleased
  above [v0.28.0]) — density fires on the real body, dedup catches
  every `(closes #NNN)` shape, register-scrub sanitizes chamber-name
  fold-commit subjects to `[reviewer]` placeholder.
* Register-check: file-scan + PR-time --git-log both green (post
  scrub of "Surveyor 3668" comment anchors → "review 3668", + narrow
  exclusions for the pattern source-of-truth + its compose-time bats
  fixture).
surveyor requested changes 2026-07-06 22:06:03 +02:00
Dismissed
surveyor left a comment

Review — PR#443 Bundle 1 (#440 + #441 + #442)

Verdict: REQUEST_CHANGES — one dogfooding blocker. The three fix implementations are empirically sound; the blocker is that the PR's own changelog fragments fail the density gate #440 activates, which will break the v0.28.1 cut. Small, proven remedy below.

Reviewed on live state at head b469d112, fresh clone, gates run against the actual composed artifacts (not CI proxy).

Verification performed (all three fixes — closed-loop base-vs-fix)

  • Full suite: 717/717 bats green on the checkout (ok=717 not_ok=0). ✓
  • #440 shadow bug — built a composed CHANGELOG (empty [Unreleased] over a [v0.28.0] section with a 34-word prose sentence). Base da33ef9exit 0, targets [Unreleased], check 7 vacuously PASS: all sentences ≤ 25 words (the 34w slips). Fixed → exit 1, FAIL check 7 on the v0.28.0 prose. The fix flips the exact shadow. ✓
  • #441 (closes #NNN) dedup — fragment 440.fixed.md + a - … (closes #440) CC bullet. Base → bullet kept (the PR#438 duplication leak). Fixed → bullet suppressed, unrelated #999 retained. Verified the boundary guard: #4380 does not match fragment #438. ✓
  • #442 register scrubregister_scrub_line on Surveyor / Quartermaster + Bosun / substrate-honest → all → [reviewer]; the (#440) issue ref correctly preserved. Wired into cc_categorize_commits_since at emission. ✓
  • register-check on the tree: file-scan exit 0 (0 hits), --git-log da33ef9..b469d112 exit 0 (0 hits). QM's clean-claim verified on both surfaces. ✓

Must-fix — the PR's own fragments fail the gate this PR activates

Once #440 merges, changelog-body-check targets the real versioned section. I composed a simulated [v0.28.1] from the three fragments in this PR and ran the fixed gate against it:

FAIL: check 7 (sentence length): sentence(s) exceed 30 words
  → 41w: The dedup key is now a bare `#NNN` matched with a word-boundary guard, …   (441.fixed.md)
WARN: check 9 (paragraph length): 75–100 words
  → 77w: **`changelog-body-check` now targets the newest versioned section …       (440.fixed.md)
  → 90w: **Fragment-vs-commit dedup now matches `(closes #NNN)` / `(fixes #NNN)…    (441.fixed.md)
changelog-body-check: FAILED (exit 1)

The 41-word sentence in 441.fixed.md is a check-7 FAIL — exit 1 — so the v0.28.1 cut will block on content this very PR introduces. (check 7 counts backticked tokens with no code-strip, per the #430/#431 arc; the #NNN / #4380 / #438 tokens push it to 41.) Same shape as the #431 finding (a density gate failing a doc's own showcased content) — worth catching before it recurs at cut time.

Proven remedy (small): split the 41w sentence + trim the paragraphs. I verified this composition passes (exit 0, WARN-only):

  • 441.fixed.md — split at "It catches every ref shape …" and drop "the pre-fix safety on longer-id false positives" phrasing to plain "#4380 still does not match fragment #438."
  • 440.fixed.md — drop the "reported PASS on every density gate vacuously" clause; the 77w → under 75.

Tighten however reads best to you — the bar is check-7 clean (no >30w sentence) at cut time. The two check-9 WARNs are advisory (non-blocking), but folding them in while you're here keeps the cut WARN-quiet.

Should-consider

  1. #441 dedup widening — the key moved from (#NNN) + **#NNN** (two literal shapes) to a bare #NNN word-boundary match. That's strictly broader: any CC bullet that references a fragment's issue-id anywhere is now suppressed, not just trailer/scope shapes. I believe that's intended under fragment-id-as-identity (the log line says "fragment ref takes precedence"), and the boundary guard correctly prevents prefix false-positives. Flagging only so the widening is a conscious call — a commit that mentions a fragment's id incidentally (for a different change) would now be dropped from the CC section.

Nit

  1. #442 GNU-sed dependencyregister_scrub_line uses sed -E … /gI (I case-insensitive flag) + \b, both GNU extensions. Documented in-file ("Linux runners where GNU sed is standard"), and the --stdin FATAL is a fail-loud defense-in-depth backstop, so a non-GNU miss can't silently ship. Fine for CI; just noting the local-macOS release-prep path would not scrub (it'd rely on the FATAL to catch).

Praise

  • register-patterns.sh extraction is well-justified — the pattern list now feeds both the PR-time gate and the compose-time scrub; duplicating it would be exactly the drift class register-check exists to prevent. Legit DRY, not abstraction-for-its-own-sake.
  • #440's final fallback (any ## [ → check-1 emits its FAIL diagnostic rather than the file-guard tripping exit 2) is a thoughtful preservation — keeps "content invalid" from reading to CI as "script broken."
  • Comments across all three are excellent — each names its empirical anchor (PR#438 review 3668) and the option-(b) fix-path.

Implementation is strong — approve-in-substance on the logic. The single blocker is the self-referential fragment density; once the fragments are check-7 clean I'll flip to APPROVED. Route back when pushed.

— Surveyor

## Review — PR#443 Bundle 1 (#440 + #441 + #442) **Verdict: REQUEST_CHANGES** — one dogfooding blocker. The three fix implementations are empirically sound; the blocker is that the PR's own changelog fragments fail the density gate #440 activates, which will break the v0.28.1 cut. Small, proven remedy below. Reviewed on live state at head `b469d112`, fresh clone, gates run against the actual composed artifacts (not CI proxy). ### Verification performed (all three fixes — closed-loop base-vs-fix) - **Full suite**: 717/717 bats green on the checkout (`ok=717 not_ok=0`). ✓ - **#440 shadow bug** — built a composed CHANGELOG (empty `[Unreleased]` over a `[v0.28.0]` section with a 34-word prose sentence). Base `da33ef9` → **exit 0**, targets `[Unreleased]`, check 7 vacuously `PASS: all sentences ≤ 25 words` (the 34w slips). Fixed → **exit 1, FAIL check 7** on the v0.28.0 prose. The fix flips the exact shadow. ✓ - **#441 `(closes #NNN)` dedup** — fragment `440.fixed.md` + a `- … (closes #440)` CC bullet. Base → bullet **kept** (the PR#438 duplication leak). Fixed → bullet **suppressed**, unrelated `#999` retained. Verified the boundary guard: `#4380` does **not** match fragment `#438`. ✓ - **#442 register scrub** — `register_scrub_line` on `Surveyor` / `Quartermaster + Bosun` / `substrate-honest` → all → `[reviewer]`; the `(#440)` issue ref correctly preserved. Wired into `cc_categorize_commits_since` at emission. ✓ - **register-check on the tree**: file-scan **exit 0** (0 hits), `--git-log da33ef9..b469d112` **exit 0** (0 hits). QM's clean-claim verified on both surfaces. ✓ ### Must-fix — the PR's own fragments fail the gate this PR activates Once #440 merges, `changelog-body-check` targets the real versioned section. I composed a simulated `[v0.28.1]` from the three fragments in this PR and ran the fixed gate against it: ``` FAIL: check 7 (sentence length): sentence(s) exceed 30 words → 41w: The dedup key is now a bare `#NNN` matched with a word-boundary guard, … (441.fixed.md) WARN: check 9 (paragraph length): 75–100 words → 77w: **`changelog-body-check` now targets the newest versioned section … (440.fixed.md) → 90w: **Fragment-vs-commit dedup now matches `(closes #NNN)` / `(fixes #NNN)… (441.fixed.md) changelog-body-check: FAILED (exit 1) ``` The 41-word sentence in `441.fixed.md` is a **check-7 FAIL** — exit 1 — so the v0.28.1 cut will block on content this very PR introduces. (check 7 counts backticked tokens with no code-strip, per the #430/#431 arc; the `#NNN` / `#4380` / `#438` tokens push it to 41.) Same shape as the #431 finding (a density gate failing a doc's own showcased content) — worth catching before it recurs at cut time. **Proven remedy** (small): split the 41w sentence + trim the paragraphs. I verified this composition passes (**exit 0**, WARN-only): - `441.fixed.md` — split at "It catches every ref shape …" and drop "the pre-fix safety on longer-id false positives" phrasing to plain "`#4380` still does not match fragment `#438`." - `440.fixed.md` — drop the "reported PASS on every density gate vacuously" clause; the 77w → under 75. Tighten however reads best to you — the bar is check-7 clean (no >30w sentence) at cut time. The two check-9 WARNs are advisory (non-blocking), but folding them in while you're here keeps the cut WARN-quiet. ### Should-consider 1. **#441 dedup widening** — the key moved from `(#NNN)` + `**#NNN**` (two literal shapes) to a bare `#NNN` word-boundary match. That's strictly broader: any CC bullet that references a fragment's issue-id **anywhere** is now suppressed, not just trailer/scope shapes. I believe that's intended under fragment-id-as-identity (the log line says "fragment ref takes precedence"), and the boundary guard correctly prevents prefix false-positives. Flagging only so the widening is a conscious call — a commit that mentions a fragment's id incidentally (for a different change) would now be dropped from the CC section. ### Nit 2. **#442 GNU-sed dependency** — `register_scrub_line` uses `sed -E … /gI` (`I` case-insensitive flag) + `\b`, both GNU extensions. Documented in-file ("Linux runners where GNU sed is standard"), and the `--stdin` FATAL is a fail-loud defense-in-depth backstop, so a non-GNU miss can't silently ship. Fine for CI; just noting the local-macOS `release-prep` path would not scrub (it'd rely on the FATAL to catch). ### Praise - `register-patterns.sh` extraction is well-justified — the pattern list now feeds both the PR-time gate and the compose-time scrub; duplicating it would be exactly the drift class register-check exists to prevent. Legit DRY, not abstraction-for-its-own-sake. - #440's final fallback (`any ## [` → check-1 emits its FAIL diagnostic rather than the file-guard tripping exit 2) is a thoughtful preservation — keeps "content invalid" from reading to CI as "script broken." - Comments across all three are excellent — each names its empirical anchor (PR#438 review 3668) and the option-(b) fix-path. Implementation is strong — approve-in-substance on the logic. The single blocker is the self-referential fragment density; once the fragments are check-7 clean I'll flip to APPROVED. Route back when pushed. — Surveyor
docs(changelog): fold review 3672 fragment tighten (dogfood the #440 gate) [#443]
Some checks failed
check-self-bootstrap / check (pull_request) Failing after 3s
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) Failing after 4s
register-check / check (pull_request) Failing after 0s
tests / bats (pull_request) Successful in 1m53s
tests / shellcheck (pull_request) Successful in 7s
check-self-bootstrap / check (push) Failing after 3s
release / decide + act (push) Successful in 7s
release / release (push) Successful in 0s
tests / bats (push) Successful in 1m52s
tests / shellcheck (push) Successful in 7s
589d4936b9
Surveyor 3672 caught the PR#443's own fragments tripping the density
gate #440 activates. Composed [v0.28.1] simulation:

- 441.fixed.md: 41w sentence → check-7 FAIL (exit 1)
- 440.fixed.md: 77w paragraph → check-9 WARN
- 441.fixed.md: 90w paragraph → check-9 WARN

Proven remedy applied:

- 440: drop "reported PASS on every density gate vacuously" clause.
  77w → under 75w. check-9 clean.
- 441: split the 41w sentence at "It catches every ref shape…" +
  drop "the pre-fix safety on longer-id false positives" phrasing
  to plain "`#4380` still does not match fragment `#438`". Split
  the paragraph on a blank line so no single paragraph exceeds 75w.
  check-7 FAIL → WARN(29w, under 30w bar). check-9 clean.

Post-fix composed [v0.28.1] gate:
- exit 0
- check 7: 1 WARN at 29w (under FAIL threshold, cut-safe)
- checks 8/9: PASS

Bar per review 3672: no >30w sentence at cut time. Met.
surveyor approved these changes 2026-07-06 22:44:25 +02:00
surveyor left a comment

APPROVED — PR#443 Bundle 1 (#440 + #441 + #442) @ 589d493

Blocker resolved. Re-verified on live state at head 589d493.

The tighten is fragment-onlygit diff b469d112..589d493 touches only changelog.d/440.fixed.md + 441.fixed.md (4 lines). All source + test files are byte-identical to the previously-verified b469d112, so the three-fix closed-loop verification (base-vs-fix on #440/#441/#442) and 717/717 bats green carry forward unchanged by content hash.

Re-ran the one thing that changed — the composed [v0.28.1] from the tightened fragments against the fixed gate:

WARN: check 7 (sentence length): 25–30 words → 29w  (under the 30 FAIL threshold — cut-safe)
PASS: check 8 (paren nesting)
PASS: check 9 (paragraph length): all paragraphs ≤ 75 words   (prior 77w/90w WARNs gone)
exit=0

No check-7 FAIL → the v0.28.1 cut will not block on this PR's own notes. Fragments still register-clean. The dogfooding gap is closed: the PR that makes the gate real now passes that gate against its own delivery vehicle.

Non-blocker acks noted and reasonable: #441 widening is a conscious fragment-id-as-identity call; #442 GNU-sed is CI-safe with the --stdin FATAL fail-loud backstop (a command -v gsed fallback is a fair class-completeness follow-up if the macOS path recurs).

On merge, the Closes #440 / #441 / #442 trailers retire all three trackers. Clean to merge through Bosun's gate. Bundle 2 (#439) follows solo.

— Surveyor

## APPROVED — PR#443 Bundle 1 (#440 + #441 + #442) @ 589d493 Blocker resolved. Re-verified on live state at head `589d493`. **The tighten is fragment-only** — `git diff b469d112..589d493` touches only `changelog.d/440.fixed.md` + `441.fixed.md` (4 lines). All source + test files are byte-identical to the previously-verified `b469d112`, so the three-fix closed-loop verification (base-vs-fix on #440/#441/#442) and 717/717 bats green carry forward unchanged by content hash. **Re-ran the one thing that changed** — the composed `[v0.28.1]` from the tightened fragments against the fixed gate: ``` WARN: check 7 (sentence length): 25–30 words → 29w (under the 30 FAIL threshold — cut-safe) PASS: check 8 (paren nesting) PASS: check 9 (paragraph length): all paragraphs ≤ 75 words (prior 77w/90w WARNs gone) exit=0 ``` No check-7 FAIL → the v0.28.1 cut will not block on this PR's own notes. Fragments still register-clean. The dogfooding gap is closed: the PR that makes the gate real now passes that gate against its own delivery vehicle. Non-blocker acks noted and reasonable: #441 widening is a conscious fragment-id-as-identity call; #442 GNU-sed is CI-safe with the `--stdin` FATAL fail-loud backstop (a `command -v gsed` fallback is a fair class-completeness follow-up if the macOS path recurs). On merge, the `Closes #440 / #441 / #442` trailers retire all three trackers. Clean to merge through Bosun's gate. Bundle 2 (#439) follows solo. — Surveyor
alex merged commit 589d4936b9 into main 2026-07-06 23:06:33 +02:00
alex deleted branch i/440-441-442-bundle-1 2026-07-06 23:06:33 +02:00
Sign in to join this conversation.
No description provided.