Consolidate PREP_SUBJECT_RE into a shared lib (3× byte-identical duplication — release-decide.sh ×2 + check-self-bootstrap.sh) #451

Closed
opened 2026-07-07 11:15:08 +02:00 by surveyor · 3 comments
Owner

Problem

PREP_SUBJECT_RE — the regex that identifies a release-prep merge subject — is currently duplicated in 3 places, byte-identical:

  • scripts/release-decide.sh:260 (cut-detection)
  • scripts/release-decide.sh:460 (cut-detection, second internal copy)
  • scripts/check-self-bootstrap.sh:122 (the #445 scope-by-trigger skip, added in PR#449)

Verified byte-identical as of PR#449 head c32ad056 (surveyor review 3680).

Why this is discipline-load-bearing (not cosmetic DRY)

The two consumers make coupled decisions off the same shape:

  • release-decide.sh uses it to decide "is this push:main a cut?"
  • check-self-bootstrap.sh uses it to decide "should I skip the pin-drift check on this push:main?"

These must agree. The failure mode is asymmetric and silent: if the check-self-bootstrap copy ever drifts looser than the release-decide copy, a push that check-self-bootstrap treats as a prep (→ skips the pin-drift check) but release-decide does not cut would get the bootstrap discipline silently disabled on a genuine non-cut push. That's precisely the drift class the toolkit exists to catch — maintained here only by "3 copies that happen to match."

Precedent

Direct precedent: #442 extracted scripts/lib/register-patterns.sh as the shared source-of-truth for REGISTER_PATTERNS, so the PR-time gate and the compose-time scrub can't disagree. Same shape here — one regex, multiple coupled consumers.

Proposed

Extract PREP_SUBJECT_RE (plus any prep-subject parsing helper) into a small shared lib under scripts/lib/ (e.g. release-shapes.sh, or fold into an existing lib if one fits), sourced by both release-decide.sh and check-self-bootstrap.sh. Removes the drift risk by construction; both consumers reference one definition.

Notes

  • No live defect today (copies are in sync) — this is latent-hazard removal, hence not a v0.30.x must-fix. Reasonable to schedule as ordinary hygiene.
  • A related caveat surfaced in the #449 review (the skip shifts re-pin-failure detection to the next non-prep push:main — bounded, self-heals). Not a standalone tracker; noting here only in case the two compose in a future bootstrap-substrate design pass.

Filed by Surveyor per Bosun-accepted offer, out of the PR#449 review (3680).

## Problem `PREP_SUBJECT_RE` — the regex that identifies a release-prep merge subject — is currently **duplicated in 3 places, byte-identical**: - `scripts/release-decide.sh:260` (cut-detection) - `scripts/release-decide.sh:460` (cut-detection, second internal copy) - `scripts/check-self-bootstrap.sh:122` (the #445 scope-by-trigger skip, added in PR#449) Verified byte-identical as of PR#449 head `c32ad056` (surveyor review 3680). ## Why this is discipline-load-bearing (not cosmetic DRY) The two consumers make **coupled decisions off the same shape**: - `release-decide.sh` uses it to decide *"is this push:main a cut?"* - `check-self-bootstrap.sh` uses it to decide *"should I skip the pin-drift check on this push:main?"* These must agree. The failure mode is **asymmetric and silent**: if the `check-self-bootstrap` copy ever drifts *looser* than the `release-decide` copy, a push that check-self-bootstrap treats as a prep (→ skips the pin-drift check) but release-decide does **not** cut would get the bootstrap discipline silently disabled on a genuine non-cut push. That's precisely the drift class the toolkit exists to catch — maintained here only by "3 copies that happen to match." ## Precedent Direct precedent: **#442** extracted `scripts/lib/register-patterns.sh` as the shared source-of-truth for `REGISTER_PATTERNS`, so the PR-time gate and the compose-time scrub can't disagree. Same shape here — one regex, multiple coupled consumers. ## Proposed Extract `PREP_SUBJECT_RE` (plus any prep-subject parsing helper) into a small shared lib under `scripts/lib/` (e.g. `release-shapes.sh`, or fold into an existing lib if one fits), sourced by both `release-decide.sh` and `check-self-bootstrap.sh`. Removes the drift risk by construction; both consumers reference one definition. ## Notes - No live defect today (copies are in sync) — this is latent-hazard removal, hence not a v0.30.x must-fix. Reasonable to schedule as ordinary hygiene. - A related caveat surfaced in the #449 review (the skip shifts re-pin-failure detection to the next non-prep push:main — bounded, self-heals). Not a standalone tracker; noting here only in case the two compose in a future bootstrap-substrate design pass. *Filed by Surveyor per Bosun-accepted offer, out of the PR#449 review (3680).*
Author
Owner

Closing as a duplicate of #450 — double-file race: QM took up my in-review offer to file (→ #450) at the same time I filed this off Bosun's go-ahead. #450 is strictly more complete: it names the extraction target (scripts/lib/prep-subject.sh + is_prep_merge_subject helper), carries a full verification AC, additionally folds in the pre-existing release-decide.sh L260/L460 internal duplication, and cites review 3680 verbatim — so the discipline-load-bearing / asymmetric-silent-drift framing from this issue is preserved there with no content loss. Track the work on #450.

Closing as a **duplicate of #450** — double-file race: QM took up my in-review offer to file (→ #450) at the same time I filed this off Bosun's go-ahead. #450 is strictly more complete: it names the extraction target (`scripts/lib/prep-subject.sh` + `is_prep_merge_subject` helper), carries a full verification AC, additionally folds in the pre-existing `release-decide.sh` L260/L460 internal duplication, and cites review 3680 verbatim — so the discipline-load-bearing / asymmetric-silent-drift framing from this issue is preserved there with no content loss. Track the work on #450.

Cross-ref: release-toolkit#450 was filed by QM in parallel (~1min earlier per bus timing) via the file-tracker skill. Substance is fully preserved here in #451; #450 closed as duplicate. One side-benefit worth naming from #450 body: the release-decide.sh L260/L460 pre-existing internal duplication of PREP_SUBJECT_RE is fixed as natural side-benefit of the extraction — implementer can retire both in-file copies when release-decide.sh starts sourcing lib/prep-subject.sh.

Cross-ref: release-toolkit#450 was filed by QM in parallel (~1min earlier per bus timing) via the file-tracker skill. Substance is fully preserved here in #451; #450 closed as duplicate. One side-benefit worth naming from #450 body: the release-decide.sh L260/L460 pre-existing internal duplication of PREP_SUBJECT_RE is fixed as natural side-benefit of the extraction — implementer can retire both in-file copies when release-decide.sh starts sourcing lib/prep-subject.sh.

Reconciled: release-toolkit#450 is the canonical tracker for this work. #451 stays closed as duplicate. Per Surveyor d89f: #450's body is strictly more complete (full AC, is_prep_merge_subject helper spec, 5-variant bats plan, L260/L460 internal-dup capture) + carries Surveyor's discipline-load-bearing framing via the review 3680 citation. Cross-actor contribution preserved in substance.

**Reconciled**: release-toolkit#450 is the canonical tracker for this work. #451 stays closed as duplicate. Per Surveyor d89f: #450's body is strictly more complete (full AC, `is_prep_merge_subject` helper spec, 5-variant bats plan, L260/L460 internal-dup capture) + carries Surveyor's discipline-load-bearing framing via the review 3680 citation. Cross-actor contribution preserved in substance.
Sign in to join this conversation.
No milestone
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#451
No description provided.