release-prep
Skill436 starsChanged 48 days agoMITView on GitHub
Prepare and publish a PredictRLM release from main. Use when asked to prepare, version, tag, or push a release. Accepts an optional release version.
- Commits and pushes
23 other projects use a version of this.
Adopted by
Most recently taken up by
- colonyops/hivetheir own version, first seen Nov 7, 2026
- microsoft/durabletask-pythontheir own version, first seen Nov 2, 2026
- Terryc21/sitreptheir own version, first seen Nov 1, 2026
- kala-project/acp-kittheir own version, first seen Oct 20, 2026
- finch-xu/cc-routertheir own version, first seen Oct 15, 2026
- barlevalon/skillstheir own version, first seen Oct 13, 2026
Other versions23 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 23
- dathere/qsv★ 3.8ksame name
- Devolutions/IronRDP★ 3.3ksame name
- johnhuang316/code-index-mcp★ 1ksame name
- Fu-Jie/awesome-openwebui★ 326same name
- Fu-Jie/openwebui-extensions★ 326same name
- finch-xu/cc-router★ 293same name
- ten9876/AetherSDR★ 259same name
- ayutaz/piper-plus★ 240same name
- opencrvs/opencrvs-core★ 122same name
- Terryc21/sitrep★ 50same name
13 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
The file
Show its rules and text
We split this skill into the rules it gives an agent
17 rules. 0 are common, 8 are distinctive, and 9 are very specific to this project.
0
Common
Most of the 21 edited versions we read keep these.
8
Distinctive
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Distinctive: line 33
Do not perform any release action until all preflight checks pass and the user explicitly approves the proposed version.
- Very specific: line 40
Run from the repository root, using Python 3.11+, uv, Git, and authenticated GitHub CLI (gh).
- Distinctive: line 44
Before reading tags, modifying files, creating a commit or tag, or pushing:
- Distinctive: line 56
If any check fails, stop and report it.
- Distinctive: line 59
After preflight passes, run git fetch origin --tags so version selection and tag collision checks include remote releases.
- Very specific: line 136
Read [project].version and CHANGELOG.md before approval.
- Distinctive: line 156
Wait for an explicit affirmative response accepting the proposal.
- Distinctive: line 166
Update only these two tracked release artifacts:
- Very specific: line 178
Add [<source-version>] pointing to the comparison from the preceding published tag to <tag>.
- Very specific: line 182
Run uv lock without --upgrade to refresh the ignored local lockfile.
- Very specific: line 224
Check the newly built wheel and sdist metadata both normalize to <distribution-version> using …
- Very specific: line 226
Do not mistake old files in dist/ for the current build.
- Very specific: line 229
Check the Tests workflow for the code being released.
- Very specific: line 234
Read docs/runbooks/long-running-local-runs.md before long-running local checks.
- Distinctive: line 257
If verification, commit, or branch push fails, stop.
- Distinctive: line 258
Never force-push or automatically amend/rebase to repair a release.
- Very specific: line 262
Only after verifying the release commit is on origin/main:
“Common” is measured: kept by at least 6 in 10 of the 21 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Prepare a release
Input: optional version. Accept 0.9.0, 0.9.0-rc3, 0.9.0rc3, or the
corresponding v-prefixed tag. Alpha and beta channels are also supported,
including Python spellings 0.9.0a3 and 0.9.0b3. Normalize to:
pyproject.tomland changelog version: hyphenated (0.9.0-rc3).- Git tag:
v-prefixed and hyphenated (v0.9.0-rc3). - Distribution filename / normalized PyPI version: PEP 440 (
0.9.0rc3).
The Release workflow in .github/workflows/release.yml compares the tag
without v to [project].version literally. Do not put the normalized
PEP 440 spelling in pyproject.toml for a hyphenated tag. Hatchling normalizes
distribution filenames but can preserve the source spelling in package metadata;
compare metadata versions using packaging.version.Version, not raw strings.
There is one PyPI distribution, predict-rlm, containing predict_rlm,
rlm_gepa, and dspy_codex_lm. These are not separately versioned releases.
There is no __version__ constant to update and no npm release. uv.lock is
ignored and untracked; refresh it locally, but do not force-add it. Skill
metadata versions and minimum-compatible versions are not release artifacts.
Do not perform any release action until all preflight checks pass and the user explicitly approves the proposed version. Do not switch branches, stash, discard, commit, or otherwise repair a failed preflight. Creating or editing this skill is not authorization to run a release.
1. Mandatory preflight
Run from the repository root, using Python 3.11+, uv, Git, and authenticated
GitHub CLI (gh). Run shell blocks with bash; set -euo pipefail makes a
failed check stop the block.
Before reading tags, modifying files, creating a commit or tag, or pushing:
set -euo pipefail
test "$(git branch --show-current)" = main \
|| { echo "Release preparation requires the main branch." >&2; exit 1; }
test -z "$(git status --porcelain=v1 --untracked-files=all)" \
|| { echo "Release preparation requires a completely clean worktree." >&2; exit 1; }
git remote get-url origin >/dev/null \
|| { echo "Release publication requires an origin remote." >&2; exit 1; }If any check fails, stop and report it. Do not inspect tags, propose a version, edit files, commit, create a tag, or push.
After preflight passes, run git fetch origin --tags so version selection and
tag collision checks include remote releases. Stop on fetch failure; never
force-update conflicting tags or automatically pull/rebase the branch.
2. Resolve and approve a version
Set RELEASE_VERSION to the exact user input, or an empty string to infer a
proposal. Whitespace is invalid. The following script performs no mutation and
prints <tag> <source-version> <distribution-version>:
RELEASE_VERSION='' python3 - <<'PY'
import os
import re
import subprocess
pattern = re.compile(
r"v?(?P<major>0|[1-9][0-9]*)\.(?P<minor>0|[1-9][0-9]*)\."
r"(?P<patch>0|[1-9][0-9]*)"
r"(?:-?(?P<channel>alpha|beta|rc|a|b)(?P<serial>0|[1-9][0-9]*))?"
)
tag_pattern = re.compile(
r"v(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)"
r"(?:-(?:alpha|beta|rc)(?:0|[1-9][0-9]*))?"
)
channel_order = {"alpha": 0, "beta": 1, "rc": 2, None: 3}
tags = subprocess.run(
["git", "tag", "--list"], check=True, text=True, capture_output=True
).stdout.splitlines()
supplied = os.environ["RELEASE_VERSION"]
if supplied:
match = pattern.fullmatch(supplied)
if match is None:
raise SystemExit("Invalid release version.")
parts = match.groupdict()
major, minor, patch = (int(parts[name]) for name in ("major", "minor", "patch"))
channel = {"a": "alpha", "b": "beta"}.get(parts["channel"], parts["channel"])
serial = int(parts["serial"] or 0)
else:
releases = []
for tag in tags:
if tag_pattern.fullmatch(tag) is None:
continue
parts = pattern.fullmatch(tag).groupdict()
releases.append((
int(parts["major"]), int(parts["minor"]), int(parts["patch"]),
channel_order[parts["channel"]], int(parts["serial"] or 0),
))
if not releases:
raise SystemExit("No supported release tags; provide an explicit version.")
major, minor, patch, order, serial = max(releases)
channel = {value: key for key, value in channel_order.items()}[order]
if channel is None:
patch += 1
else:
serial += 1
if channel is not None and patch != 0:
raise SystemExit("Prereleases require patch version zero; provide a stable or minor release version.")
base = f"{major}.{minor}.{patch}"
source = base if channel is None else f"{base}-{channel}{serial}"
package_channel = {"alpha": "a", "beta": "b", "rc": "rc"}
distribution = base if channel is None else f"{base}{package_channel[channel]}{serial}"
tag = f"v{source}"
if tag in tags:
raise SystemExit(f"Tag {tag} already exists.")
print(tag, source, distribution)
PYWithout input, the highest supported release tag determines the proposal:
- Stable → increment patch (
v1.2.3→v1.2.4). - Prerelease → increment serial, preserving base/channel (
v1.3.0-rc4→v1.3.0-rc5). - Numeric version ordering applies; stable outranks rc, beta, and alpha at the same base. Ignore unrelated tags. No supported tags → ask for a version.
Read [project].version and CHANGELOG.md before approval. Surface any mismatch
between the proposed version, current source version, and release notes. Do not
silently downgrade a source version or treat a patch proposal as appropriate
for breaking changes. Ask the user to resolve such a mismatch. If Unreleased
has no release-note content, stop; do not manufacture notes.
Present:
Proposed release: <tag>
pyproject.toml version: <source-version>
CHANGELOG.md heading: ## [<source-version>] - <YYYY-MM-DD>
Built distribution / PyPI version: <distribution-version>
uv.lock: local refresh only; not committed
A release commit containing only pyproject.toml and CHANGELOG.md will be pushed
to origin/main, then an annotated tag will be pushed to origin. The tag triggers
a GitHub Release, package build, and PyPI publication.
Proceed?Wait for an explicit affirmative response accepting the proposal. Supplying a version alone is not approval.
3. Apply and verify the approved release
Re-run mandatory preflight and git fetch origin --tags after approval. Run the
version script with the approved version to recheck tag availability. Set TAG,
SOURCE_VERSION, and DIST_VERSION to its three output values; export them for
the verification scripts below. Replace <YYYY-MM-DD> with the release date.
Update only these two tracked release artifacts:
- Set
[project].versioninpyproject.tomlto<source-version>. - Move the entire non-empty release-note body under
## [Unreleased]inCHANGELOG.mdinto## [<source-version>] - <YYYY-MM-DD>, leaving an empty## [Unreleased]above it. Preserve every note and existing historical release section. Keep reference-link definitions at the bottom, not in the release-note body.- Resolve the preceding published tag from Git history. Do not trust a stale
[Unreleased]comparison URL or invent missing historical release notes. - Point
[Unreleased]tohttps://github.com/Trampoline-AI/predict-rlm/compare/<tag>...HEAD. - Add
[<source-version>]pointing to the comparison from the preceding published tag to<tag>. For the first release, usehttps://github.com/Trampoline-AI/predict-rlm/releases/tag/<tag>.
- Resolve the preceding published tag from Git history. Do not trust a stale
Run uv lock without --upgrade to refresh the ignored local lockfile. Do not
stage it or change dependency constraints. Verify the diff contains only the
approved version, changelog heading/links, and preserved notes. If the version
was already set to the approved value, pyproject.toml need not have a diff;
CHANGELOG.md must still change.
set -euo pipefail
git diff --check
python3 - <<'PY'
import os
import re
import subprocess
import tomllib
from pathlib import Path
source = os.environ["SOURCE_VERSION"]
assert os.environ["TAG"] == f"v{source}"
project = tomllib.loads(Path("pyproject.toml").read_text())
assert project["project"]["version"] == source, "Source version differs from approval"
lock = tomllib.loads(Path("uv.lock").read_text())
editable = [p for p in lock["package"] if p["name"] == "predict-rlm" and p["source"] == {"editable": "."}]
assert len(editable) == 1 and editable[0]["version"] == os.environ["DIST_VERSION"], "Local lock version mismatch"
notes = Path("CHANGELOG.md").read_text()
assert re.search(rf"^## \[{re.escape(source)}\] - [0-9]{{4}}-[0-9]{{2}}-[0-9]{{2}}$", notes, re.M), "Missing release heading"
assert re.search(r"^## \[Unreleased\]\s+## \[", notes, re.M), "Unreleased must be empty"
url = "https://github.com/Trampoline-AI/predict-rlm"
assert f"[Unreleased]: {url}/compare/v{source}...HEAD" in notes.splitlines()
assert any(line.startswith(f"[{source}]: {url}/") for line in notes.splitlines()), "Missing release link"
changed = set(subprocess.run(
["git", "diff", "HEAD", "--name-only"], check=True, text=True, capture_output=True
).stdout.splitlines())
assert "CHANGELOG.md" in changed and changed <= {"CHANGELOG.md", "pyproject.toml"}, "Unexpected release diff"
untracked = subprocess.run(
["git", "ls-files", "--others", "--exclude-standard"], check=True, text=True, capture_output=True
).stdout
assert not untracked, "Unexpected untracked files"
PY
uv lock --check
uv buildCheck the newly built wheel and sdist metadata both normalize to
<distribution-version> using str(packaging.version.Version(metadata_version)).
Do not mistake old files in dist/ for the current build. The wheel must contain
all three import packages declared in pyproject.toml.
Check the Tests workflow for the code being released. Do not claim tests passed
without observing their results; resolve failures before publication. For local
checks, use uv run ruff check src/ tests/, make test-unit (all extras), and
make test-integration-jspi (real Deno/WASM). Real SBX coverage separately requires
sbx login and make test-integration-sbx; report unavailable/skipped coverage.
Read docs/runbooks/long-running-local-runs.md before long-running local checks.
A tag identifies a commit, not uncommitted files. Create and publish the release commit before tagging:
set -euo pipefail
git add pyproject.toml CHANGELOG.md
git commit -m "chore(predict-rlm): release $TAG"
test "$(git branch --show-current)" = main
test -z "$(git status --porcelain=v1 --untracked-files=all)"
git push origin main
python3 - <<'PY'
import subprocess
head = subprocess.check_output(["git", "rev-parse", "HEAD"], text=True).strip()
remote = subprocess.check_output(
["git", "ls-remote", "--exit-code", "--heads", "origin", "main"], text=True
).split()
assert remote == [head, "refs/heads/main"], "origin/main does not point at the release commit"
PYIf verification, commit, or branch push fails, stop. Do not create or push a tag. Never force-push or automatically amend/rebase to repair a release.
4. Tag, push, and verify publication
Only after verifying the release commit is on origin/main:
set -euo pipefail
git tag -a "$TAG" -m "Release $TAG"
git push origin "refs/tags/$TAG"
python3 - <<'PY'
import os
import subprocess
def git(*args):
return subprocess.check_output(["git", *args], text=True).strip()
tag = os.environ["TAG"]
head = git("rev-parse", "HEAD")
assert git("rev-list", "-n", "1", tag) == head
assert git("ls-remote", "--exit-code", "--heads", "origin", "main").split() == [head, "refs/heads/main"]
assert git("ls-remote", "--exit-code", "origin", f"refs/tags/{tag}^{{}}").split() == [head, f"refs/tags/{tag}^{{}}"]
PYThe annotated tag's remote peeled SHA must match the release commit. That commit contains the artifacts verified before committing. If tag push fails, report it and leave the local tag intact; do not delete, move, or force-push it.
Inspect the Release workflow run for this tag and SHA using gh run list
--workflow release.yml, then gh run watch <run-id> --exit-status and
gh run view <run-id>. Check gh release view "$TAG" as well.
The current workflow runs validate → GitHub Release → build → PyPI publish.
The publish job uses trusted publishing in the release environment and may
wait for environment approval. A pushed tag or visible GitHub Release is not
proof of PyPI publication. All jobs must succeed before claiming completion.
Confirm the normalized version appears at
https://pypi.org/pypi/predict-rlm/<distribution-version>/json.
For a failed run, report the failing job and logs. Do not move the tag, create a
replacement version, or run a manual upload. Rerun failed jobs in the same run
only after understanding the failure; this workflow does not configure
skip-existing, so a partial PyPI upload is not guaranteed to retry cleanly.
Report the tag, release commit SHA, pushed remote (origin), GitHub Release and
workflow URLs, PyPI version, and exact verification results. Distinguish a
pushed tag, an approval-pending job, and confirmed publication.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

