Skill v1.0.1
currentAutomated scan100/100+1 new
version: "1.0.1" name: release-procedure description: >- Cut, tag, and publish an alef release end-to-end. Use this skill any time the user asks for a release, a version bump, a hotfix tag, or a CHANGELOG roll-up in this repo. Covers the full pipeline: changelog, version sync via Taskfile, Cargo.toml verification, poly lint pass, atomic commit (no AI signatures, no --no-verify when avoidable), git tag, and gh release create (not just a tag). license: MIT
Alef Release Procedure
Cut a new alef version with a verifiable, reproducible procedure. Skip no step. Every release step has a concrete verification — never assume; always check.
When to apply
- User asks to cut/release/publish a new version
- User asks to bump alef version
- After a stack of fix/feat commits that need a version cycle
- After a breaking change is committed (must bump MINOR pre-1.0, MAJOR otherwise)
- When consumer repos need a new pin
Hard rules
- Always update `CHANGELOG.md` — every release has a dated heading and one
bullet per user-visible change. Move entries from [Unreleased] into the new version section. Group under ### Added, ### Changed (BREAKING), ### Fixed, ### Removed. Never tag a version with an empty section.
- Always run `poly fmt --fix .` then `poly lint .` to fix lint/format issues before
publishing. Re-stage anything the formatter rewrites. Only commit with --no-verify if a hook is genuinely broken in a way unrelated to the change — and then file an issue.
- No AI signatures in commit messages, tag messages, or release notes.
No Co-Authored-By: Claude, no Generated by .... Never.
- Atomic commits —
chore(release): X.Y.Zcarries only the version bump
and changelog roll. Code fixes live in their own commits, merged before the release commit.
- Add tests for any fix that changed behavior. A release that includes a
fix without a regression test is a release that will regress.
- Use the Taskfile for version setting — never hand-edit
Cargo.toml,
alef.toml, or src/core/template_versions.rs. task set-version rewrites all three in lockstep.
- Publish with `gh release create` — a bare
git tagis not a release.
The GitHub release is what triggers consumer automation and what users discover. Alef ships as a single crate, so the tag push triggers exactly one cargo publish — no multi-crate sequencing, no index propagation race.
Procedure
0. Pre-flight
git status # working tree clean (or only release-prep diffs)git fetch origin # inspect freshness without rewriting local commits
If the release branch has diverged from its upstream, stop and ask how to reconcile it. Do not rebase or merge after committing unless the user explicitly asks for it.
1. Update CHANGELOG.md
- Open
CHANGELOG.md. - Move every bullet under
## [Unreleased]into a new section
## [X.Y.Z] - YYYY-MM-DD (today's date, ISO format).
- Re-create an empty
## [Unreleased]heading at the top. - If the release contains anything tagged
!(breaking) in commit messages,
surface it under ### Changed (BREAKING) with explicit migration guidance.
- Verify no entries are lost:
git diff CHANGELOG.mdshould show only adds
in the new section + the moved bullets.
2. Set the version via Taskfile
task set-version -- X.Y.Z # bumps Cargo.toml, alef.toml, ALEF_REV; runs cargo update
The set-version task is the only sanctioned way to bump versions in this repo. It rewrites Cargo.toml (package.version), alef.toml (alef_version), and src/core/template_versions.rs::ALEF_REV in one shot, then runs cargo update. Never hand-edit any of these — they must stay in lockstep.
After the task finishes, verify:
grep -E '^version' Cargo.toml # package versiongrep -E '^alef_version' alef.toml # alef.toml mirrorgrep ALEF_REV src/core/template_versions.rs # template version pin
All three must match X.Y.Z (the ALEF_REV line includes a leading v).
3. Lint pass
poly fmt --fix .poly lint .
Re-stage any files the formatter rewrote. If a lint fails for a real reason, fix that reason — never bypass with --no-verify to push past a lint failure.
4. Tests for changed behavior
For every fix: or feat: rolled into this release, confirm there is a test that would have caught the bug or covers the new surface. Add the test now if missing — release commit goes on top.
5. Commit
git add -Agit commit -m "chore(release): X.Y.Z"
The commit subject is exactly chore(release): X.Y.Z. No body unless the release is large enough to warrant a summary; never add AI attribution.
If gitfluff or another commit-msg hook rewrites the subject in an unhelpful way, prefer fixing the hook config over --no-verify. When the user has explicitly authorized --no-verify for this run, document which hooks were skipped in the release notes.
6. Tag and publish
git tag -a vX.Y.Z -m "vX.Y.Z"git push origin maingit push origin vX.Y.Z
Then create the GitHub release — this is the part most likely to be skipped and the most important:
gh release create vX.Y.Z \--title "vX.Y.Z" \--notes-from-tag \--verify-tag
If the changelog entry is rich enough to use as release notes, replace --notes-from-tag with --notes-file <(awk '/^## \[X.Y.Z\]/,/^## \[/' CHANGELOG.md | head -n -1) or build a small notes file from the new CHANGELOG section.
For pre-releases (RC, beta), add --prerelease.
7. Verify
gh release view vX.Y.Z # confirms the release exists with notesgit tag -l vX.Y.Z # confirms the tag exists locallygit ls-remote --tags origin vX.Y.Z # confirms it pushed
If any of those are empty, redo the failed step — do not move on.
8. Downstream pins
For any consumer repo that pins this version, open a follow-up PR that bumps the pin. Don't bundle that into the release commit.
Anti-patterns
- Tagging without a
gh release create— invisible release, breaks automation. - Empty
## [Unreleased]rolled forward to a new version section. - Hand-editing
version = "..."inCargo.toml,alef_versionin
alef.toml, or ALEF_REV in src/core/template_versions.rs instead of using task set-version.
- Fix commits with no test added.
--no-verifyto skip a real lint failure.- AI attribution in commit/tag/release text.
- Squashing release prep with code fixes — keep
chore(release): X.Y.Zatomic.
Quick reference
| Step | Command | What it verifies | |
|---|---|---|---|
| Pre-flight | git status && git fetch origin | Clean tree + remote state | |
| Changelog | manual edit of CHANGELOG.md | Every change is documented | |
| Version | task set-version -- X.Y.Z then grep -E '^version' Cargo.toml | Crate version updated | |
| Lint | poly fmt --fix . && poly lint . | Lint clean | |
| Commit | git commit -m "chore(release): X.Y.Z" | Atomic release commit | |
| Tag | git tag -a vX.Y.Z -m "vX.Y.Z" && git push --tags | Tag exists remotely | |
| Publish | gh release create vX.Y.Z --notes-from-tag --verify-tag | GitHub release exists | |
| Verify | gh release view vX.Y.Z | Release is discoverable |