Skip to content

fix(promote): guard recognizes any tagged-release tree + canonical release-process spec#49

Merged
misnaej merged 3 commits into
devfrom
fix/promotion-guard-any-tag
Jun 17, 2026
Merged

fix(promote): guard recognizes any tagged-release tree + canonical release-process spec#49
misnaej merged 3 commits into
devfrom
fix/promotion-guard-any-tag

Conversation

@misnaej

@misnaej misnaej commented Jun 17, 2026

Copy link
Copy Markdown
Owner

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_commit still compared HEAD against the latest tag only, so promoting a minor below the global-max tag (e.g. v1.22.0 while v1.23.0 is tagged) was blocked. Now _is_release_commit compares HEAD's tree against every v* 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→main promotion, 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.
  • CLAUDE.md release bullets + the /promote skill 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

- _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
@misnaej

misnaej commented Jun 17, 2026

Copy link
Copy Markdown
Owner Author

Squash-merge message (copy verbatim):

fix(promote): guard checks any tagged-release tree; add release-process spec

- _is_release_commit now checks all v* tag trees, fixing staged-minor-below-global-max regression
- Add docs/release-process.md as SSoT for versioning + dev→main promotion workflow
- Release guide + /promote skill point to spec instead of restating (FOUNDATION §12)
- test_main_skips_when_head_reproduces_older_tag locks the any-tag invariant; red before fix

@misnaej

misnaej commented Jun 17, 2026

Copy link
Copy Markdown
Owner Author

PR Verification Results

verified-at: d16c65c (PR #49, branch fix/promotion-guard-any-tag)

Design Check

Small, 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 _is_release_commit. A load-bearing why-comment documents the any-tag invariant inline; the project CLAUDE.md records it at the contributor level. No reviewer needed — scope is a single guard function and its regression test.

Security Review

No security surface. _is_release_commit performs read-only git tree comparisons (git cat-file -t, git rev-parse <tag>^{tree}). No external input, no credentials, no subprocess injection vectors. No change to public APIs or trust boundaries.

Documentation Check

Docstring verification: 0 errors, 0 warnings. Type hints complete. Why-comment in _is_release_commit and CLAUDE.md entry together satisfy the load-bearing documentation requirement. No public API surface changed.

Issue Management

No 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 Closes #N keyword needed.

Code Quality (from code_health/ logs)

  • Ruff: PASS (85 files unchanged, all checks passed)
  • Test naming: PASS (0 issues)
  • Repo structure: PASS (REPO_STRUCTURE.md in sync, 130 paths checked)
  • Docstring verification: PASS (0 errors, 0 warnings, 4 non-blocking info)
  • Docstring coverage: 100.0%
  • Plugin version: 1.23.1 > v1.23.0 (rolling-next policy correct)
  • CI: SUCCESS (run 27673721851)

Recommendation: Ready for merge

- 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
@misnaej misnaej changed the title fix(promote): rolling-next guard recognizes any tagged-release tree fix(promote): guard recognizes any tagged-release tree + canonical release-process spec Jun 17, 2026
- 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
@misnaej

misnaej commented Jun 17, 2026

Copy link
Copy Markdown
Owner Author

PR Verification Results

verified-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 Check

PASS — Minor findings only, all resolved. Code fix is strictly scoped: _is_release_commit iterates all v* tags (keeps #43's global resolution, signature simplified to KISS). SSoT consolidation clean; invariant→test contract is a sound anti-regression pattern — all 5 named tests verified to exist. Resolved: HIGH stale SKILL.md citations (now point to docs/release-process.md §1/§2), MEDIUM module docstring (now reflects "any published v* tag"). Accepted: LOW perf (YAGNI — fires once per commit, ~20 tags, early-exit); LOW CLAUDE.md sub-bullets (in-context reminders, defensible).

Security Review

NOT 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 Check

PASS — 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 Management

PR body contains Closes #50 — the canonical release-process spec issue wires auto-close on merge. No other open issues addressed by this PR.

Code Quality (from code_health/ logs)

  • Ruff: PASS (85 files unchanged, all checks passed)
  • Docstring verification: PASS (0 errors, 0 warnings, 4 non-blocking info)
  • Test naming: PASS (0 issues across 25 files)
  • Repo structure: PASS (REPO_STRUCTURE.md in sync, 131 paths checked)
  • CI: SUCCESS (run completed 2026-06-17)

Recommendation: Ready for merge

@misnaej misnaej merged commit 47dc0ae into dev Jun 17, 2026
1 check passed
@misnaej misnaej deleted the fix/promotion-guard-any-tag branch June 17, 2026 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant