# Beads Release Formula v2 (Gate-Aware) # # This formula uses gates for async waits during CI, enabling clean phase handoffs. # Instead of polling, the polecat completes Phase 1, and a gate blocks Phase 2 # until GitHub Actions finishes. # # Phases: # 1. Prep & Push: preflight → push-tag (polecat work) # 2. Gate: await-ci (async wait for release.yml) # 3. Verify: verify-github, verify-npm, verify-pypi (parallel) # 4. Install: local-install → release-complete (fan-in) formula = "beads-release" description = """ Beads release workflow v2 - gate-aware async release. This formula orchestrates a complete release cycle with async gates: Phase 1 (Polecat Work): 1. Preflight checks (clean git, up to date) 2. Documentation updates (CHANGELOG, info.go) 3. Version bump (all components) 4. Git operations (commit, tag, push) Gate (Async Wait): 5. await-ci: Gate on GitHub Actions release.yml completion Phase 2 (Parallel Verification): 6. Verify GitHub release, npm package, PyPI package (concurrent) Phase 3 (Installation): 7. Local installation update 8. Daemon restart ## Usage ```bash bd mol wisp create beads-release --var version=0.44.0 ``` Or assign to a polecat: ```bash gt sling beads/polecats/p1 --formula beads-release --var version=0.44.0 ``` The polecat will complete Phase 1, then signal phase-complete. The gate blocks until release.yml finishes. A new polecat (or the same one) resumes for Phases 2-3. """ type = "workflow" phase = "vapor" # Ensures this runs as a wisp - bd pour will warn, gt sling --formula creates wisp version = 1 [vars.version] description = "The semantic version to release (e.g., 0.44.0)" required = true # ============================================================================= # Phase 1: Prep & Push # ============================================================================= [[steps]] id = "preflight-git" title = "Preflight: Check git status" description = """ Ensure working tree is clean before starting release. ```bash git status ``` If there are uncommitted changes, either: - Commit them first - Stash them: `git stash` - Abort and resolve """ [[steps]] id = "preflight-pull" title = "Preflight: Pull latest" needs = ["preflight-git"] description = """ Ensure we're up to date with origin. ```bash git pull --rebase ``` Resolve any conflicts before proceeding. """ [[steps]] id = "review-changes" title = "Review changes since last release" needs = ["preflight-pull"] description = """ Understand what's being released. ```bash git log $(git describe --tags --abbrev=0)..HEAD --oneline ``` Categorize changes: - Features (feat:) - Fixes (fix:) - Breaking changes - Documentation """ [[steps]] id = "update-changelog" title = "Update CHANGELOG.md" needs = ["review-changes"] description = """ Write the [Unreleased] section with all changes for {{version}}. Format: Keep a Changelog (https://keepachangelog.com) Sections: - ### Added - ### Changed - ### Fixed - ### Documentation The bump script will stamp the date automatically. """ [[steps]] id = "update-info-go" title = "Update info.go versionChanges" needs = ["update-changelog"] description = """ Add entry to versionChanges in cmd/bd/info.go. This powers `bd info --whats-new` for agents. ```go "{{version}}": { "summary": "Brief description", "changes": []string{ "Key change 1", "Key change 2", }, }, ``` Focus on workflow-impacting changes agents need to know. """ [[steps]] id = "bump-version-go" title = "Bump version in version.go" needs = ["update-info-go"] description = """ Update the Go version constant. ```bash # macOS sed -i '' 's/Version = "[^"]*"/Version = "{{version}}"/' cmd/bd/version.go # Linux sed -i 's/Version = "[^"]*"/Version = "{{version}}"/' cmd/bd/version.go ``` Verify: ```bash grep 'Version = ' cmd/bd/version.go ``` """ [[steps]] id = "bump-plugin-json" title = "Bump version in plugin JSON files" needs = ["bump-version-go"] description = """ Update Claude plugin manifest versions. ```bash # macOS/Linux with jq jq '.version = "{{version}}"' .claude-plugin/plugin.json > tmp && mv tmp .claude-plugin/plugin.json jq '.plugins[0].version = "{{version}}"' .claude-plugin/marketplace.json > tmp && mv tmp .claude-plugin/marketplace.json ``` Verify: ```bash jq -r '.version' .claude-plugin/plugin.json jq -r '.plugins[0].version' .claude-plugin/marketplace.json ``` """ [[steps]] id = "bump-mcp-python" title = "Bump version in MCP Python package" needs = ["bump-plugin-json"] description = """ Update the beads-mcp Python package version. ```bash # macOS sed -i '' 's/version = "[^"]*"/version = "{{version}}"/' integrations/beads-mcp/pyproject.toml sed -i '' 's/__version__ = "[^"]*"/__version__ = "{{version}}"/' integrations/beads-mcp/src/beads_mcp/__init__.py # Linux sed -i 's/version = "[^"]*"/version = "{{version}}"/' integrations/beads-mcp/pyproject.toml sed -i 's/__version__ = "[^"]*"/__version__ = "{{version}}"/' integrations/beads-mcp/src/beads_mcp/__init__.py ``` Verify: ```bash grep 'version = ' integrations/beads-mcp/pyproject.toml | head -1 grep '__version__ = ' integrations/beads-mcp/src/beads_mcp/__init__.py ``` """ [[steps]] id = "bump-npm-package" title = "Bump version in npm package" needs = ["bump-mcp-python"] description = """ Update the npm package version. ```bash # macOS/Linux with jq jq '.version = "{{version}}"' npm-package/package.json > tmp && mv tmp npm-package/package.json ``` Verify: ```bash jq -r '.version' npm-package/package.json ``` """ [[steps]] id = "bump-hook-templates" title = "Bump version in hook templates" needs = ["bump-npm-package"] description = """ Update version comment in git hook templates. ```bash # macOS for f in cmd/bd/templates/hooks/pre-commit cmd/bd/templates/hooks/post-merge cmd/bd/templates/hooks/pre-push cmd/bd/templates/hooks/post-checkout; do sed -i '' 's/# bd-hooks-version: .*/# bd-hooks-version: {{version}}/' "$f" done # Linux for f in cmd/bd/templates/hooks/pre-commit cmd/bd/templates/hooks/post-merge cmd/bd/templates/hooks/pre-push cmd/bd/templates/hooks/post-checkout; do sed -i 's/# bd-hooks-version: .*/# bd-hooks-version: {{version}}/' "$f" done ``` Verify: ```bash grep '# bd-hooks-version:' cmd/bd/templates/hooks/pre-commit ``` """ [[steps]] id = "bump-readme" title = "Bump version in README badge" needs = ["bump-hook-templates"] description = """ Update the Alpha version badge in README.md. ```bash # macOS sed -i '' 's/Alpha (v[^)]*)/Alpha (v{{version}})/' README.md # Linux sed -i 's/Alpha (v[^)]*)/Alpha (v{{version}})/' README.md ``` Verify: ```bash grep 'Alpha (v' README.md ``` """ [[steps]] id = "stamp-changelog" title = "Stamp changelog with release date" needs = ["bump-readme"] description = """ Add the release date to the [Unreleased] section header. ```bash DATE=$(date +%Y-%m-%d) # macOS sed -i '' "s/## \\[Unreleased\\]/## [Unreleased]\\ \\ ## [{{version}}] - $DATE/" CHANGELOG.md # Linux sed -i "s/## \\[Unreleased\\]/## [Unreleased]\\n\\n## [{{version}}] - $DATE/" CHANGELOG.md ``` Note: The update-changelog step handles the content; this step just adds the date stamp. Verify: ```bash grep -A2 '\\[Unreleased\\]' CHANGELOG.md ``` """ [[steps]] id = "verify-versions" title = "Verify version consistency" needs = ["stamp-changelog"] description = """ Confirm all versions match {{version}}. ```bash grep 'Version = ' cmd/bd/version.go jq -r '.version' .claude-plugin/plugin.json jq -r '.version' npm-package/package.json grep 'version = ' integrations/beads-mcp/pyproject.toml ``` All should show {{version}}. """ [[steps]] id = "commit-release" title = "Commit release" needs = ["verify-versions"] description = """ Stage and commit all version changes. ```bash git add -A git commit -m "chore: Bump version to {{version}}" ``` Review the commit to ensure all expected files are included. """ [[steps]] id = "create-tag" title = "Create release tag" needs = ["commit-release"] description = """ Create annotated git tag. ```bash git tag -a v{{version}} -m "Release v{{version}}" ``` Verify: `git tag -l | tail -5` """ [[steps]] id = "push-main" title = "Push to main" needs = ["create-tag"] description = """ Push the release commit to origin. ```bash git push origin main ``` If rejected, someone else pushed. Pull, rebase, try again. """ [[steps]] id = "push-tag" title = "Push release tag" needs = ["push-main"] description = """ Push the version tag to trigger CI release. ```bash git push origin v{{version}} ``` This triggers GitHub Actions to build artifacts and publish. **Phase 1 Complete**: After this step, signal phase-complete: ```bash gt done --phase-complete ``` The gate will block until CI finishes. A new session will resume at Phase 2. """ # ============================================================================= # Gate: CI Completion # ============================================================================= [[steps]] id = "await-ci" title = "Await CI: release.yml completion" needs = ["push-tag"] description = """ Gate step: Wait for GitHub Actions release workflow to complete. This gate blocks until the release.yml workflow run succeeds. The Refinery auto-discovers the workflow run triggered by v{{version}} and closes this gate when it completes. Expected time: 5-10 minutes The gate monitors: - Build artifacts (all platforms) - Test suite pass - npm publish - PyPI publish If the workflow fails, this gate remains open and requires manual intervention. """ [steps.gate] type = "gh:run" id = "release.yml" timeout = "30m" # ============================================================================= # Phase 2: Verification (Parallel) # ============================================================================= [[steps]] id = "verify-github" title = "Verify GitHub release" needs = ["await-ci"] description = """ Check the GitHub releases page. https://github.com/steveyegge/beads/releases/tag/v{{version}} Verify: - Release created - Binaries attached (linux, darwin, windows) - Checksums present ```bash gh release view v{{version}} --json assets --jq '.assets[].name' ``` """ [[steps]] id = "verify-npm" title = "Verify npm package" needs = ["await-ci"] description = """ Confirm npm package published. ```bash npm show @beads/bd version ``` Should show {{version}}. Also check: https://www.npmjs.com/package/@beads/bd Note: npm registry may have a small propagation delay (1-2 min). """ [[steps]] id = "verify-pypi" title = "Verify PyPI package" needs = ["await-ci"] description = """ Confirm PyPI package published. ```bash pip index versions beads-mcp 2>/dev/null | head -3 ``` Or check: https://pypi.org/project/beads-mcp/ Should show {{version}}. Note: PyPI may have a small propagation delay (1-2 min). """ # ============================================================================= # Phase 3: Installation (Fan-in) # ============================================================================= [[steps]] id = "local-install" title = "Update local installation" needs = ["verify-github", "verify-npm", "verify-pypi"] description = """ Update local bd to the new version. Option 1 - Homebrew: ```bash brew upgrade bd ``` Option 2 - Install script: ```bash curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash ``` Verify: ```bash bd --version ``` Should show {{version}}. """ [[steps]] id = "restart-daemons" title = "Restart daemons" needs = ["local-install"] description = """ Restart bd daemons to pick up new version. ```bash bd daemons killall ``` Daemons will auto-restart with new version on next bd command. Verify: ```bash bd daemons list ``` """ [[steps]] id = "release-complete" title = "Release complete" needs = ["restart-daemons"] description = """ Release v{{version}} is complete! Summary: - All version files updated - Git tag pushed - CI artifacts built (via gate) - npm and PyPI packages verified - Local installation updated - Daemons restarted Optional next steps: - Announce on social media - Update documentation site - Close related milestone """