| name | release |
| description | Cut a new yolop release. Prepares the release PR, runs publish-readiness checks, monitors CI publish to crates.io and the everruns Homebrew tap. Use when the user asks to release, cut a version, publish, or ship to crates.io / brew. |
| metadata | {"internal":true} |
| user-invocable | true |
Release
Goal: cut a new yolop release and verify it lands on both crates.io and the
everruns/homebrew-tap Homebrew tap.
knowledge/specs/release.md owns the versioning rules, the changelog
format, the CI automation contract, post-release verification, hotfix and
rollback policy, and the secrets table. This skill owns the procedure. For a
non-release change, use /ship instead.
Releases are agent-prepared, human-merged, CI-published. The agent never tags
the release and never pushes to the tap — release.yml and cli-binaries.yml
do that.
0. Sync local state
Shallow clones lie: cloud sandboxes default to depth ≈ 50 and silently drop
older commits from git log.
git fetch --unshallow origin main 2>/dev/null || git fetch origin main
git fetch --tags
LATEST=$(git describe --tags --abbrev=0)
git log "$LATEST"..origin/main --oneline | wc -l
gh api "repos/everruns/yolop/compare/$LATEST...main" --jq '.total_commits'
If those two counts disagree, the clone is still shallow.
1. Pick the version
Use the version the user gave. Otherwise propose one from the unreleased commit
set under the spec's versioning rules, and confirm before proceeding.
2. Update the changelog
Build the commit list mechanically, then write the section in the format the
spec defines (§ Changelog Format):
git log "$LATEST"..HEAD --pretty=format:'%s' --reverse \
| grep -v '^chore(release): prepare v'
Map commits to PRs with gh pr list --state merged --base main --limit 200
when the subjects don't carry the number.
3. Bump the version
Edit version in Cargo.toml, then cargo update -p yolop to refresh the
lockfile entry.
yolop-yep is versioned separately. Bump it when its API or the wire protocol
changes, and update every workspace path dependency requirement that references
it.
First-party extensions under extensions/ are versioned separately too. Bump
one whose code changed since the last release, in both its Cargo.toml and its
plugin.json, or it is published nowhere and its manifest keeps pointing at the
previous tag's binaries. python3 scripts/publish_order.py lists exactly what
the release publishes:
python3 scripts/publish_order.py
git log "$LATEST"..HEAD --oneline -- extensions/ crates/
tuika and tuika-codeformatters are not released from here — they ship from
everruns/tuika. Bumping their version
requirements is an ordinary dependency bump, and a release that needs new
toolkit behavior waits on a tuika release first.
4. Verify locally
Review the commits since the previous tag for durable knowledge impact and
update the affected concepts, knowledge/index.md, and knowledge/log.md.
Confirm README.md and docs/ describe the released behavior. Then run the
checks in AGENTS.md.
5. Verify publish-readiness
This is the step local tests can't stand in for — it exercises the cargo publish packaging boundary, missing files referenced by Cargo.toml, and
version drift.
cargo publish --dry-run -p yolop-yep
cargo search yolop --limit 1
grep '^version' Cargo.toml
grep '"yolop"' Cargo.lock | head -1
cargo publish --dry-run fails locally for yolop and for any extension
whenever a new yolop-yep version isn't on crates.io yet — expected, not a
broken release. CI validates those publishes after the SDK goes live. If the SDK dry-run fails, fix
the root cause and re-run; never open a release PR with a known-broken publish
path.
6. Commit, push, open the PR
git add CHANGELOG.md Cargo.toml Cargo.lock
git commit -m "chore(release): prepare vX.Y.Z"
git push -u origin "$(git branch --show-current)"
Title the PR chore(release): prepare vX.Y.Z. The body carries the full
changelog section, a Publish-readiness report (which dry-runs ran, what
crates.io currently serves, that Cargo.toml and Cargo.lock agree), and an
unchecked Post-merge verification list covering release.yml, publish.yml,
cli-binaries.yml, crates.io, and the tap formula.
Do not enable auto-merge: a human must click squash so a real reviewer reads the
changelog.
7. Monitor after merge
Subscribe to PR activity so workflow completions wake you, then watch:
gh run list --workflow=release.yml --limit 1
gh run list --workflow=publish.yml --limit 1
gh run list --workflow=cli-binaries.yml --limit 1
Green workflows are not proof, and a matrix that silently builds one target
reports success just like a correct one. Run the spec's post-release verification yourself
and declare shipped only when crates.io reports X.Y.Z, every bumped
library and extension crate is live, each bumped extension has its
<crate>-v<version> release carrying the three server archives, and the tap
formula points at vX.Y.Z. crates.io publishes near-instantly; Homebrew takes minutes
for the build and tap commit, so a half-verified release looks shipped when it
isn't.
On failure, read the logs (gh run view <id> --log-failed) and either re-run
(transient — network or registry propagation) or roll forward with a hotfix PR
per the spec. Never leave a release half-shipped.