| name | release |
| description | Use when the user wants to release a new version, says "time to release", "let's release", "cut a release", "version bump", or similar. Orchestrates the full release workflow including milestone check, version bump, changelog generation, validation, tagging, and PR creation. Also invocable as /release. |
Release Workflow
This skill orchestrates a complete release. Follow each phase in order. Stop and report if any phase fails.
Phase 1: Milestone Check
Before creating a release branch, verify the milestone is ready.
-
Determine the target milestone. Look at open milestones:
gh api "repos/{owner}/{repo}/milestones?state=open&sort=due_on" --jq '.[] | "\(.number) \(.title) open:\(.open_issues) closed:\(.closed_issues)"'
-
If there are multiple open milestones, ask the user which one to release.
-
If the target milestone has open issues, stop and ask the user:
- List the open issues:
gh api "repos/{owner}/{repo}/milestones/{number}/issues?state=open" --jq ... (or use gh issue list --milestone)
- Present options:
a. Move open issues to the next milestone (specify or create it)
b. Pause to work on the open issues first
c. Close the issues if they're no longer relevant
- Do NOT proceed until all issues in the target milestone are closed or moved.
-
Once the milestone is clean (0 open issues), proceed.
Phase 2: Version Number
- Read the current version from
pyproject.toml (authoritative source).
- The milestone title tells you the target version (e.g.,
v0.7.3 means version 0.7.3).
- Validate it's a valid semver bump from the current version.
- Present the version to the user for confirmation: "Release version X.Y.Z? (current: A.B.C)"
- Wait for confirmation before proceeding.
Phase 3: Create Release Branch
git checkout main
git pull origin main
git checkout -b release/vX.Y.Z
Phase 4: Bump Version
Update version in ALL of these files (pyproject.toml is authoritative):
- pyproject.toml -
version = "X.Y.Z"
- src/omnifocus_mcp/init.py -
__version__ = "X.Y.Z"
- CLAUDE.md (.claude/CLAUDE.md) -
**Version:** vX.Y.Z in the header line
- README.md - All references to the old version (check with grep for old version string)
Use the Edit tool for each file. Be precise about what to change.
Phase 5: Generate CHANGELOG
-
Get all commits since the last release:
git log v{previous_version}..HEAD --oneline
Use the previous version tag directly (e.g., v0.8.1). Do NOT use git describe --tags --abbrev=0 — it walks commit ancestry and may not find tags that were created before a squash/rebase merge.
-
Get merged PRs since the last release:
gh pr list --state merged --base main --search "merged:>YYYY-MM-DD" --json number,title,labels
(Use the date of the last tag)
-
Generate a CHANGELOG entry following the existing format in CHANGELOG.md:
- Use Keep a Changelog format:
## [X.Y.Z] - YYYY-MM-DD
- Categorize changes: Added, Changed, Fixed, Removed
- Reference PR/issue numbers with (#N)
- Be concise but descriptive
- Include today's date
-
Insert the new entry at the top of CHANGELOG.md (after the header, before the previous version).
Phase 6: Test Coverage Review
-
Run coverage report:
pytest --cov=omnifocus_mcp --cov-report=term-missing tests/ -q
-
Compare overall coverage against the fail_under threshold in pyproject.toml. If coverage dropped below the threshold, stop and report — new code likely needs tests.
-
Get the cumulative diff to identify changed files:
git diff v{previous}..HEAD --stat
-
Audit changed src/ files for adequate test coverage:
- New code paths without unit tests
- Modified AppleScript strings without integration tests (per CLAUDE.md hard rule: "If you wrote or modified an AppleScript string, integration tests must cover it before merge")
- New parameters or return fields without test assertions
-
Flag any gaps. If coverage dropped or critical paths are untested, stop and fix before proceeding.
Phase 7: Code Review
-
Get the cumulative diff since the last release:
git diff v{previous}..HEAD
-
Launch the superpowers:code-reviewer agent to review the full diff. Provide context about the release scope (PRs included, features added/changed).
-
The reviewer will report issues by severity:
- Critical — security issues, data loss risks, correctness bugs → blocks the release
- Important — code quality, missed edge cases → fix or document in PR
- Minor — style, naming, suggestions → note in PR description
-
If Critical issues are found, stop and fix before proceeding.
-
Include Important/Minor findings in the release PR description under a "Code Review Notes" section.
Phase 8: Documentation Review
-
Enumerate documentation to check:
README.md — feature descriptions, installation, usage examples
.claude/CLAUDE.md — version, test counts, coverage %, API surface count, performance baselines
CHANGELOG.md — new entry completeness
docs/** — architecture, profiling, AppleScript gotchas, automation notes
- Tool docstrings in
src/omnifocus_mcp/server_fastmcp.py
- Skill files in
.claude/skills/
-
Verify accuracy against changes in this release:
- Stale version numbers (should still be old version — Phase 4 bumped them)
- Outdated performance baselines if perf-related changes were made
- Missing feature documentation for new capabilities
- Incorrect cross-references between docs
- Test count / coverage stats in CLAUDE.md header
- README coverage badge (
coverage-XX%25-brightgreen) matches actual coverage
-
Flag discrepancies and fix them on the release branch before proceeding.
Phase 9: Validation
Run ALL validation checks. Stop on any failure.
-
Version sync check:
./scripts/check_version_sync.sh
-
Client-server parity:
./scripts/check_client_server_parity.sh
-
Complexity check:
./scripts/check_complexity.sh
-
Unit tests:
make test
-
Dependency audit:
./scripts/check_dependencies.sh
-
AppleScript safety audit:
./scripts/check_applescript_safety.sh
If any check fails, fix the issue and re-run. Do not proceed with failures.
Phase 10: Commit, Push, and PR
-
Commit the version bump and changelog:
git add -A
git commit -m "release: vX.Y.Z"
-
Push the branch:
git push -u origin release/vX.Y.Z
-
Create the PR to main:
gh pr create --title "release: vX.Y.Z" --body "..."
Include any Code Review Notes from Phase 7 in the PR body.
-
Tell the user the PR is ready for review. Do NOT merge it automatically.
Phase 11: Merge, Tag, and Push Tag
After the user approves the PR:
-
Merge using rebase merge:
gh pr merge NNN --rebase --delete-branch
-
Switch to main and pull:
git checkout main
git pull origin main
-
Create the tag on main (where it will be reachable via git describe):
./scripts/create_tag.sh vX.Y.Z
-
Push the tag:
git push origin vX.Y.Z
-
Verify tag reachability:
git describe --tags --abbrev=0
Phase 12: Close Milestone
After the tag is pushed, close the milestone:
gh api -X PATCH "repos/{owner}/{repo}/milestones/{number}" -f state=closed
Notes
- CHANGELOG is only updated on release branches, never on feature branches.
- Tags are created on main after the PR merge. This ensures they are reachable via
git describe, which walks commit ancestry. Squash/rebase merges create new commits, so tags on the release branch would become orphaned.
- Use rebase merge for release PRs. Merge commits are blocked by
required_linear_history on main.
- Integration tests (
make test-integration, make test-e2e) require a real OmniFocus test database. Ask the user if they want to run them — they're optional for the release validation.