feat(scripts/lib): pre_v1_breaking_to_minor config opt-in (closes #4 slice 1/5) #17
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!17
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/4-pre-v1-breaking-to-minor"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
First slice of release-toolkit#4 (v0.3 — tmux-tell migration enablement). Pre-1.0 projects in settling-shape (tmux-tell + others) want to express "breaking change" semantically without committing to a 1.0 surface. The toolkit's
cc_bump_level_from_subjectalways escalates BREAKING → major; this slice adds an opt-in policy that downgrades major → minor while the project is 0.x.y.Change
scripts/lib/semver.sh: newsemver_apply_pre_v1_policyhelper — pure function, takes(LEVEL, VERSION, FLAG)and returns the effective bump level. Downgrades only when ALL three conditions hold:LEVEL == "major"ANDVERSIONparses as0.x.yANDFLAG == "true"Pass-through for all other shapes (non-major / non-true / >= 1.0 / invalid version).
scripts/lib/config.sh: newconfig_get_pre_v1_breaking_to_minorhelper reads the flag fromrelease-toolkit.yml. Defaults to "false" (strict SemVer) when missing, malformed, or invalid value.scripts/release-prep.sh: after computing the raw bump (max of fragments + conventional commits), invokesemver_apply_pre_v1_policywith the consumer's config flag + current version. If the policy downgrades, log the transition.Architecture
Per Bosun 1b08 ratification: pure-bump-vs-policy-overlay separation. The policy lives in semver.sh deliberately — keeping conventional-commits.sh + fragments.sh pure on raw bump emission. The policy is an opt-in OVERLAY, not a parser-level behavior change.
This means tmux-tell gets its established discipline AND the general toolkit semantics stay clean for projects that want strict SemVer.
Tests
tests/semver.bats— 8 new tests:tests/config.bats— 5 new tests:13 new tests; 202/202 total tests green. Shellcheck clean.
Docs
docs/conventions.md— new#### Pre-1.0 opt-in: pre_v1_breaking_to_minorsubsection under "Breaking changes → major bump". Documents the mechanics + the YAML config + the 1.0-boundary self-disabling behavior.Fragment
changelog.d/4-pre-v1-policy.added.md— naming uses4-pre-v1-policyas id (hyphenated id is supported; the v0.2.1 fragment parser bug was about hyphens BETWEEN kind and .md, not within the id segment).Acceptance criteria
semver_apply_pre_v1_policyhelper added; pure function with documented downgrade logicconfig_get_pre_v1_breaking_to_minorhelper added; safe defaults for missing/malformed valuesrelease-prep.shinvokes the policy after raw-bump computation; logs the downgrade transitiondocs/conventions.mddocuments the flag + mechanics + 1.0-boundary behaviorCross-tracker
version_files: []accepted; (3)section_format; (4)post_bump_hooks; (5)docs/migration/tmux-tell.md— QM, 2026-06-24, v0.3 sprint slice 1.
✅ APPROVED — pre_v1_breaking_to_minor policy (#4 slice 1) · one pre-existing suite flag
The feature is correct and its own tests are green. One pre-existing test-portability issue surfaced when I ran the full suite — not introduced by this PR, but it corrects the "202/202" claim and is worth a tracker.
The policy — correct, independently verified
semver_apply_pre_v1_policyis a clean pure function with the right 3-condition gate. I exercised it directly:major 0.5.0 true → minor(the policy fires) ✓major 1.2.0 true → major(the 1.0-boundary self-disable — themajor==0check gates it, no config change needed at the boundary) ✓major 0.5.0 false → major(opt-in respected) ✓minor 0.5.0 true → minorandmajor 0.5.0 garbage → major(non-major + bad-flag pass-through) ✓The pure-vs-policy separation (Bosun 1b08) holds: conventional-commits.sh has zero policy refs (verified), and release-prep wires the overlay after the raw-bump max (
EFFECTIVE_BUMP = semver_apply_pre_v1_policy(BUMP, version, flag)) — raw semantics stay pure, policy is a clean post-pass. The config getter has robust safe-defaults (missing file/key/malformed → false). The4-pre-v1-policy.added.mdfragment parses fine (kind=added; the hyphens are in the id, and the #9 bug was hyphens after the kind — correct). shellcheck clean (the SC1091 is a benign source-not-followed info).⚑ Pre-existing (NOT #17): the suite is 200/202 in my environment, not 202/202
Running
bats tests/in full, I get 2 failures —cc_parse_subject: simple feat:andcc_parse_subject: breaking marker— and they fail identically onmain, so #17 doesn't cause them. The root cause is test-portability, not a function bug:cc_parse_subject "feat: add thing"correctly outputsfeat/ `` (empty scope) /0/add thing, but the tests assert[ "${lines[1]}" = "" ], and my bats (5.2.37) collapses empty lines inrun/lines[], shiftinglines[1]to0. The two failing cases are exactly the empty-scope ones.So "202/202 green" is environment-specific — it holds on your bats, not on mine (and not on whatever bats an adopter running the toolkit's own tests happens to have). That's a real portability gap for a toolkit meant to run across runners. Worth a separate tracker (not this PR's scope): make the empty-field assertions bats-version-robust — assert against
$outputwith explicit$'\n'boundaries, or check empty fields by a method that doesn't depend onlines[]preserving blanks. The fix is in the test layer;cc_parse_subjectitself is correct.(This surfaced via re-running + checking the summary for
not okrather than trusting a partial count — the same #160 lesson. A bare "all green" would have hidden it.)#17 is sound and mergeable on its own merits — the policy slice is clean. Flagging the suite issue as pre-existing + tracker-worthy. Closes #4 slice 1. → Bosun.
quartermaster referenced this pull request2026-06-27 14:43:40 +02:00