feat(release): add wave-level prepare-release skill + engine#160
Merged
Conversation
Adds tools/prepare_release.py, a deterministic engine for the version-bump and dependency-floor bookkeeping half of cutting a genblaze release wave, plus .claude/skills/prepare-release/SKILL.md as a thin driver over it. Motivated by a concrete gap: a hand-edited release-prep pass this session bumped genblaze-core but silently missed cli's matching core-floor bump. The script makes that impossible by discovering packages dynamically (no hardcoded version literals or connector list) and resyncing cli's and the umbrella's genblaze-core/genblaze-s3/connector-extra floors to the final decided version of whatever they point at, independent of whether that specific package changed this wave -- forcing a version bump on the pin holder itself when needed, the same skip-existing drift class tools/check_pin_parity.py already guards against downstream. Refuses to land core on the version reserved for the raise_on_failure default flip. Idempotent by construction (re-running --apply, or a hand-edit, is a no-op for anything already past what was published at the last tag). The skill's allowed-tools frontmatter deliberately excludes git tag, gh release, twine upload, and make post-release -- it can prepare a merge-ready release PR but cannot tag or publish.
Remove the connector_extras and baseline_tag fixture parameters — no test call site ever overrode their defaults (dead speculative flexibility flagged in panel review). Behavior unchanged; 34 tests still pass.
jeronimodeleon
added a commit
that referenced
this pull request
Jul 16, 2026
PR #160 re-populated the [Unreleased] block after the [0.5.0] wave header was already cut, which fails the release workflow's changelog-gate. The tooling ships under the v0.5.0 tag anyway (it's on main before the tag; the tools/skill/docs aren't published to PyPI), so move the note into [0.5.0] under ### Internal and leave [Unreleased] empty. No packaged code changed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wave-level release-prep:
/prepare-releaseskill +tools/prepare_release.pyAdds a standardized, reproducible way to prep a genblaze release wave — codifying the manual v0.5.0 prep (and the traps it surfaced) so the next release is one guided run instead of back-and-forth.
Why (the failure mode this fixes)
During the v0.5.0 prep, hand-editing 8
pyproject.tomls + the CHANGELOG silently missed the CLIgenblaze-corefloor bump — caught only by CI. A prose-only skill would reproduce that. So the mechanical work lives in a testable engine, and the skill is a thin driver over it.tools/prepare_release.py(engine)libs/core,cli,libs/meta,libs/spec,libs/connectors/*); no hardcoded package list or version literal.cli's and the umbrella'sgenblaze-core/genblaze-s3/connector-extra floors to the local core version whether or not those packages changed (matches thetest_*_core_dependency_floor_matches_local_coreinvariants), so a pin-only change can't ship without a version bump (theskip-existing/pin-parity trap)._RAISE_ON_FAILURE_DEFAULT_FLIP_VERSIONfrom source and refuses to bump core onto it.--check/--applymodes;--set pkg=x/--bump pkg=minoroverrides; emits the### Released package versionslist for the CHANGELOG..claude/skills/prepare-release/SKILL.md(driver)allowed-tools, not prose: nogit tag,gh release,twine upload, ormake post-release— it cannot tag or publish; it goes as far as a release PR and emits the human tag/release/post-release commands.make pre-release(with the macOS env prereqs baked in) → open PR. LinksRELEASING.mdas source of truth; delegates per-package detail to/release-check./verify-docs,/security-review, andMIGRATING-<wave>.mdare conditional suggestions, not mandatory steps.Review
Built via TDD, then a 3-lens panel (over-engineering/DRY, correctness vs RELEASING.md/release.yml, safety). No P0/P1 except the one applied fix (removed dead fixture params, commit
037fe70). The correctness reviewer verified the engine live-caught a real, previously-invisible instance of the target bug class:genblaze-nvidia's README link fix sincev0.4.0shipped with no version bump. Remaining items are non-blocking P2 cosmetics (duplicate floor-report lines per-extra; a fails-closed regex assumption in the reserved-version extractor) — noted for follow-up.Verification:
pytest tools/tests/test_prepare_release.py34/34;ruff check/formatclean;--checkruns clean against the live repo.