| 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, prek 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 step has a hard 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 downstream repos (kreuzberg, etc.) 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
prek run --all-files to fix lint/format issues before
committing. Re-stage anything the hooks rewrite. 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.Z carries 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 tag is not a release.
The GitHub release is what triggers downstream 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
git pull --ff-only
cargo check --all-features
cargo test
If any of those fail, stop. Fix first, release second.
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.md should show only adds
in the new section + the moved bullets.
2. Set the version via Taskfile
task set-version -- X.Y.Z
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
grep -E '^alef_version' alef.toml
grep ALEF_REV src/core/template_versions.rs
All three must match X.Y.Z (the ALEF_REV line includes a leading v).
3. Lint pass
prek run --all-files
Re-stage any files the hooks rewrote. If a hook 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 -A
git 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 main
git 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
git tag -l vX.Y.Z
git ls-remote --tags origin vX.Y.Z
If any of those are empty, redo the failed step — do not move on.
8. Downstream pins
For any consumer repo (kreuzberg etc.) 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 = "..." in Cargo.toml, alef_version in
alef.toml, or ALEF_REV in src/core/template_versions.rs instead of
using task set-version.
- Fix commits with no test added.
--no-verify to skip a real lint failure.
- AI attribution in commit/tag/release text.
- Squashing release prep with code fixes — keep
chore(release): X.Y.Z atomic.
Quick reference
| Step | Command | What it verifies |
|---|
| Pre-flight | cargo check --all-features && cargo test | Clean build + green tests |
| 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 | prek run --all-files | Pre-commit 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 |