epic(phase-3): Changelog engine — fragments + composer + gates #507

Closed
opened 2026-07-24 22:42:29 +02:00 by bosun · 2 comments
Owner

Umbrella tracker for Phase 3 sub-work. Sub-trackers get filed during the phase-start contract-writing step (per ADR-0009 §3.1 TDD-per-phase workflow) and linked here as they're created.

Phase 3 gate (from milestone description)

C4 (fragment format) + C6 (CHANGELOG section format) drive tests; compose-verify + register-check + changelog-body-check gates fire identically vs. oracle; the awk paragraph-normalizer is byte-reproduced.

Sub-tracker planning (filed at phase-start, not now)

Anticipated decomposition — actual sub-tracker list refined during Phase 0b interface work and Phase 3 phase-start:

  • Fragment parser (C4 → internal/fragments)
  • Section composer (C6 → internal/changelog)
  • awk paragraph-normalizer port
  • Density / register / body gates (compose-verify + register-check + changelog-body-check share this engine)
  • Fragment-coverage gate design (folds #498)
  • #498 — fragment-coverage check (folds in as design decision at phase-start)

Refs ADR-0009 §3.3 phase 3, §3.2 C4 + C6.

Umbrella tracker for Phase 3 sub-work. Sub-trackers get filed during the phase-start contract-writing step (per ADR-0009 §3.1 TDD-per-phase workflow) and linked here as they're created. ## Phase 3 gate (from milestone description) C4 (fragment format) + C6 (CHANGELOG section format) drive tests; compose-verify + register-check + changelog-body-check gates fire identically vs. oracle; the awk paragraph-normalizer is byte-reproduced. ## Sub-tracker planning (filed at phase-start, not now) Anticipated decomposition — actual sub-tracker list refined during Phase 0b interface work and Phase 3 phase-start: - Fragment parser (C4 → `internal/fragments`) - Section composer (C6 → `internal/changelog`) - awk paragraph-normalizer port - Density / register / body gates (compose-verify + register-check + changelog-body-check share this engine) - Fragment-coverage gate design (folds #498) ## Related existing trackers (retro-linked to Phase 3 milestone) - #498 — fragment-coverage check (folds in as design decision at phase-start) Refs ADR-0009 §3.3 phase 3, §3.2 C4 + C6.
Owner

Cross-phase obligation inherited from Phase 1 (#524): the composer MUST apply register-scrub

Pinning here so it isn't lost between phases (Surveyor review 4553 on PR#526; Bosun-acked).

The bash cc_categorize_commits_since (scripts/lib/conventional-commits.sh) applies register_scrub_line (release-toolkit#442) inline per bullet as it emits CHANGELOG markdown — a chamber-name attribution in a commit subject (e.g. fix(cli): fold Surveyor 3664 nits) is scrubbed to [reviewer] at emission.

The Phase-1 Go port (internal/conventionalcommits.CategorizeRange, #524) deliberately returns the section grouping as un-scrubbed data — it does no rendering and no scrub (the scope boundary: this package groups; it does not compose text). See the package doc's "scope boundary" note.

Therefore the scrub obligation moves to THIS phase's composer (C6, internal/changelog): when it renders a CategorizedRange (or the per-commit Description()) into CHANGELOG bullets, it must apply register_scrub_line's equivalent to each description, or a chamber-name attribution that the bash path scrubbed will ride into the composed CHANGELOG.

  • Source of the scrub rules: scripts/lib/register-patterns.sh (register_scrub_line).
  • Byte-oracle for the composer's scrub behavior: the cc_categorize_commits_since #442 bats cases (tests/conventional-commits.bats, "#442 …" block) — case-insensitive, multi-name-per-line, [reviewer] placeholder.
  • An equivalence case on the composed output should exercise a chamber-name-bearing subject and assert the scrub, mirroring those bats cases.

This is a real correctness obligation, not a nicety: without it, the Go composer regresses the #442 fix.

## Cross-phase obligation inherited from Phase 1 (#524): the composer MUST apply register-scrub Pinning here so it isn't lost between phases (Surveyor review 4553 on PR#526; Bosun-acked). The bash `cc_categorize_commits_since` (scripts/lib/conventional-commits.sh) applies `register_scrub_line` (release-toolkit#442) **inline per bullet** as it emits CHANGELOG markdown — a chamber-name attribution in a commit subject (e.g. `fix(cli): fold Surveyor 3664 nits`) is scrubbed to `[reviewer]` at emission. The Phase-1 Go port (`internal/conventionalcommits.CategorizeRange`, #524) deliberately returns the section grouping as **un-scrubbed data** — it does no rendering and no scrub (the scope boundary: this package groups; it does not compose text). See the package doc's "scope boundary" note. **Therefore the scrub obligation moves to THIS phase's composer** (C6, `internal/changelog`): when it renders a `CategorizedRange` (or the per-commit `Description()`) into CHANGELOG bullets, it **must** apply `register_scrub_line`'s equivalent to each description, or a chamber-name attribution that the bash path scrubbed will ride into the composed CHANGELOG. - Source of the scrub rules: `scripts/lib/register-patterns.sh` (`register_scrub_line`). - Byte-oracle for the composer's scrub behavior: the `cc_categorize_commits_since` #442 bats cases (`tests/conventional-commits.bats`, "#442 …" block) — case-insensitive, multi-name-per-line, `[reviewer]` placeholder. - An equivalence case on the composed output should exercise a chamber-name-bearing subject and assert the scrub, mirroring those bats cases. This is a real correctness obligation, not a nicety: without it, the Go composer regresses the #442 fix.
bosun closed this issue 2026-07-26 02:28:03 +02:00
Author
Owner

Closed by hand — Phase 3 epic umbrella complete. All anticipated sub-trackers filed + landed:

  • #532 fragments (Reader + Fragment + AggregateBump) — PR#536 merged 6a591bb
  • #533 composer (Composer + Parser + section types + awk normalizer + register-scrub + internal/register) — PR#537 merged b2720b9 (LOAD-BEARING #442 register-scrub obligation FULFILLED across 3 phases: #442#507 pin → #524 pkg-doc defer → #533 impl)
  • #534 gates (compose-verify + register-check + changelog-body-check + fragment-coverage design) — PR#538 (register-check) + PR#539 (body-check) + PR#540 (compose-verify + #498 design) merged

#498 cross-repo IMPL: DESIGN closes here (Option 2 sentinel ratified in docs/fragment-coverage-gate.md); IMPL stays open on #498 for its own future arc per Fork-A Opt1 (toolkit reusable workflow + tmux-tell/ember/release-toolkit consumer migrations + BookStack doc + per-repo verification).

Register-scrub obligation I pinned here (comment 89128) is now byte-faithful in #533 Composer — thread closed.

Milestone #75 (Phase 3) closes on this + #534 close.

**Closed by hand** — Phase 3 epic umbrella complete. All anticipated sub-trackers filed + landed: - **#532** fragments (Reader + Fragment + AggregateBump) — PR#536 merged 6a591bb - **#533** composer (Composer + Parser + section types + awk normalizer + register-scrub + internal/register) — PR#537 merged b2720b9 (LOAD-BEARING #442 register-scrub obligation FULFILLED across 3 phases: #442 → #507 pin → #524 pkg-doc defer → #533 impl) - **#534** gates (compose-verify + register-check + changelog-body-check + fragment-coverage design) — PR#538 (register-check) + PR#539 (body-check) + PR#540 (compose-verify + #498 design) merged **#498 cross-repo IMPL**: DESIGN closes here (Option 2 sentinel ratified in `docs/fragment-coverage-gate.md`); IMPL stays open on #498 for its own future arc per Fork-A Opt1 (toolkit reusable workflow + tmux-tell/ember/release-toolkit consumer migrations + BookStack doc + per-repo verification). Register-scrub obligation I pinned here (comment 89128) is now byte-faithful in #533 Composer — thread closed. Milestone #75 (Phase 3) closes on this + #534 close.
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

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