Release
Checklist for wrapping a release of the labfreed package -- pick the version bump, regenerate README.md, and (this is the step it's easy to forget) sync the public Claude Code plugin in plugins/labfreed/ so its docs and code examples don't quietly drift out of date. Use whenever the user says to cut/wrap/prepare/ship a release, tag a new version, or publish a new version of the package.From its SKILL.md
npx -y skills add retothuerer/LabFREED --skill releaseAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.9 KB, as published. Nobody here has run it
Wrapping a release
Composes four existing pieces -- don't re-derive their logic here, just don't skip any of them:
- Version number -- classify changes and pick MAJOR/MINOR/PATCH per the
versioningskill; update__version__andCHANGELOG.mdthere. - Deliver on deprecation promises -- covered below. Only relevant when this release is a MAJOR bump; skip for MINOR/PATCH.
- README.md -- regenerate via the
update-readmeskill (build_tools/update_readme.py), which re-executesexamples/examples.pyand copies in the new changelog. - The public plugin (
plugins/labfreed/) -- covered below. This is the one that's easy to forget because nothing fails loudly when it goes stale: the package still works, tests still pass, only a user of the plugin would eventually notice Claude confidently suggesting an import path or API that no longer exists.
Delivering on deprecation promises (MAJOR bumps only)
Every deprecation added under the versioning skill's policy carries an explicit "will
be removed in vN" promise in its own warning message, and is tracked in
developer-docs/TODO.md's "Pending removals" section. A MAJOR release is the one place
that promise is cashed in -- it's silent, easy-to-forget cleanup work exactly like the
plugin sync below, so treat it with the same discipline:
- Read
developer-docs/TODO.md's "Pending removals" section and find every entry whose "removed in vN" matches the version being cut (i.e. N equals this release's major number). - For each: delete the deprecated symbol/module (not just its
@deprecateddecorator/warnings.warncall -- the whole shim), confirm nothing left in this repo'stests/still exercises the old name, and remove itsTODO.mdentry. - Call out every deletion explicitly in this version's
CHANGELOG.mdentry (per theversioningskill's "only delete at a MAJOR bump, call it out in the changelog" rule) -- a silent removal is a breaking change users have no way to anticipate from the changelog alone. - An entry whose target version hasn't arrived yet (e.g. "removed in v3.0" while cutting v2.0) stays untouched -- don't remove early just because a major bump is happening.
- If removing a symbol turns out to be unsafe (e.g.
labfreed-webtoolsor another known consumer still imports it, per a cross-reference note indesign-choices.mdorTODO.md), don't remove it silently past its promised version either -- flag it to the user and decide deliberately whether to extend the deprecation window (update the warning message andTODO.mdentry to the new target version) or proceed anyway.
This checklist is for a real, final release. A routine alpha/beta pre-release bump
toward a not-yet-shipped version is lighter-weight -- see the versioning skill's
"Alpha and beta pre-releases" section -- and does NOT need README regen or a plugin sync
on its own; those happen once, when the pre-release suffix finally drops.
Syncing the public plugin
The plugin's whole value is that its code examples actually run. Every release that changes anything import/API-shaped, re-verify it -- don't assume last release's content still holds.
- Re-run
plugins/labfreed/skills/labfreed/references/quickstart.md. Execute every snippet against the just-bumped code (a plain script pasting each block in order is enough -- that's how this file was originally written and verified). Update any snippet whose imports, call signature, or shown output changed. If a snippet now errors, that's a real finding -- fix the snippet, don't just delete the example. - Review
references/concepts.mdfor anything this release touched: PAC-CAT category tables, extension conventions, the PAC-ID Resolver/CIT terminology note, example issuers. Update or remove anything superseded. - Review
SKILL.md's "Version note" section. Replace it with this release's breaking changes (import path changes, renames, behavior changes) so someone reading it gets oriented to the current state, not last release's news. If there's been no breaking change since the last release, leave the note as-is rather than inventing one, but confirm it's still relevant instead of skipping the check. - Decide whether the plugin needs its own version bump. The plugin's
.claude-plugin/plugin.jsonversion tracks plugin content changes, not the package version -- bump it only if you actually changed something in step 1-3 above, using the plugin's own SemVer (a wording fix is a patch; a new/removed example section is at least a minor). Mirror the same version in this plugin's entry inside.claude-plugin/marketplace.json. If nothing in the plugin needed updating this release, say so explicitly and leave both versions untouched.
If a change was a real design decision (not just "we renamed a thing"), also check
whether it needs a design-choices.md entry -- see that skill.
Before calling it done
- Run the full test suite (
python3 -m pytest tests/) and readgit diffonREADME.mdand everything underplugins/labfreed/-- a clean run doesn't guarantee a clean diff (seeupdate-readme's notes on stale/non-deterministic output). - If this release adds real functionality (not a pure patch/bugfix), run the
check-coverageskill against whatever changed. Decide per finding whether to close the gap now or log it indeveloper-docs/TODO.mdand ship anyway -- this is a judgment call each time, not a hard gate on every release. - Publish by cutting a GitHub Release (tag = the dropped-suffix version) -- that's what
triggers
.github/workflows/pypi-publish.yml's test-gated publish to PyPI. Don't usebuild_tools/publish.sh/publish.ps1for the final release; those bypass the test gate and are meant for the alpha/beta bumps leading up to it (seeversioning). - Know which branch the marketplace is actually served from.
/plugin marketplace add owner/repo(no@ref) resolves to the repo's default branch on GitHub -- checkgit remote show originor the repo settings rather than assuming it'smain; at last check this repo's default wasdev, notmain. If the marketplace is meant to track releases only, either pin installs to@mainexplicitly when documenting the install command, or get the plugin/marketplace changes merged to whichever branch is actually the GitHub default -- don't let "it's ondev" and "we told people to add the marketplace unpinned" quietly disagree with each other.