fix(promote): guard recognizes any tagged-release tree + canonical release-process spec#49
Conversation
- _is_release_commit compares HEAD's tree against every v* tag, not just the latest — so promoting a minor below the global-max tag (staged catch-up) passes the guard - regression test locks it; CLAUDE.md documents it as load-bearing - plugin.json 1.23.1
|
Squash-merge message (copy verbatim): |
PR Verification Resultsverified-at: d16c65c (PR #49, branch fix/promotion-guard-any-tag) Design CheckSmall, focused bugfix — no new abstractions or patterns introduced. The fix is strictly more-permissive (any v* tag's tree, not just the global-max) and is precisely scoped to Security ReviewNo security surface. Documentation CheckDocstring verification: 0 errors, 0 warnings. Type hints complete. Why-comment in Issue ManagementNo open issues are directly closed by this PR. PR #43 (the root cause) is already merged. Issue #21 (the parent feature) remains open as tier-4-low tech-debt — this fix does not complete it. No Code Quality (from
|
- docs/release-process.md: versioning + dev→main promotion + invariant→test contract (each behavior names the test that locks it) - CLAUDE.md release bullets + /promote skill point to it (no duplication) - closes #50
- verify_plugin_version module docstring: skip on any v* tag (was 'latest') - promote SKILL: 3 CLAUDE.md citations → docs/release-process.md §1/§2 - CLAUDE.md: drop dangling 'step 3 above' → point to the spec
PR Verification Resultsverified-at: 1916be5 (PR #49, branch fix/promotion-guard-any-tag) All reviewer findings from 63789b4 addressed in 1916be5. Reports provided by caller (no re-run needed). Design CheckPASS — Minor findings only, all resolved. Code fix is strictly scoped: Security ReviewNOT RUN — not required. The code change is a read-only git tree/tag comparison (subprocess list-form, no shell, no user input, no writes); the rest is documentation. No attack surface. Documentation CheckPASS — Invariant→test table (§4) verified row-by-row: every code location exists, behaves as claimed, and every named test exists and locks the invariant (5/5 green). §1–§3 accurate against code. SSoT links resolve. Python docstring fixed. Stale citations fixed. Issue ManagementPR body contains Code Quality (from
|
Fixes the promotion regression and institutionalizes the process so it can't recur (the root cause was the absence of a spec, per #50).
The fix (#43 regression)
#43 switched the rolling-next guard's tag resolution to global semver-max but only did half the job —
_is_release_commitstill compared HEAD against the latest tag only, so promoting a minor below the global-max tag (e.g.v1.22.0whilev1.23.0is tagged) was blocked. Now_is_release_commitcompares HEAD's tree against everyv*tag. Keeps #43's global resolution (no revert).The systemic fix (closes #50) — documentation is the point
docs/release-process.md— the single source of truth for forge's versioning +dev→mainpromotion, with an invariant→test contract: every behavior the code must satisfy names the test that goes red if it drifts. The fix(guards): align protected-branch default + version-guard tag resolution + CHANGELOG #43 regression slipped through precisely because that invariant was documented and tested nowhere./promoteskill now point to the spec instead of restating it (FOUNDATION §12 single source of truth); REPO_STRUCTURE lists it.Locked
test_main_skips_when_head_reproduces_older_tag— reproduces the v1.22.0-below-v1.23.0 case; red before the fix, green after.Semver
PATCH (1.23.0 → 1.23.1) — bug fix + docs.
Testing
629 passed, 1 skipped.
Closes #50