release-process · diff
git:20260827.48e4974 to git:20260827.8361274
62 added, 538 removed. Audit A to A.
---
name: "release-process"
- description: "Step-by-step release checklist for Squad — prevents v0.8.22 and v0.9.4-style disasters"
+ description: "Operate Squad's automated preview and stable release channels safely"
domain: "release-management"
confidence: "high"
source: "team-decision"
---
- ## Context
-
- This is the **definitive release runbook** for Squad. Born from the v0.8.22
- release disaster and hardened by the v0.9.4 lessons, it covers npm packages,
- standalone archives, Homebrew, and WinGet.
-
- See also: `.squad/skills/release-process/SKILL.md` for the team-level skill with full incident history.
-
- **Rule:** No agent releases Squad without following this checklist. No exceptions. No improvisation.
-
- ---
-
- ## Pre-Release Validation
-
- Before starting ANY release work, validate the following:
-
- ### 1. Version Number Validation
-
- **Rule:** Only 3-part semver (major.minor.patch) or prerelease (major.minor.patch-tag.N) are valid. 4-part versions (0.8.21.4) are NOT valid semver and npm will mangle them.
-
- ```bash
- # Check version is valid semver
- node -p "require('semver').valid('0.8.22')"
- # Output: '0.8.22' = valid
- # Output: null = INVALID, STOP
-
- # For prerelease versions
- node -p "require('semver').valid('0.8.23-preview.1')"
- # Output: '0.8.23-preview.1' = valid
- ```
-
- **If `semver.valid()` returns `null`:** STOP. Fix the version. Do NOT proceed.
-
- ### 2. Distribution Credential Verification
-
- **Rule:** NPM_TOKEN must be an **Automation token** (no 2FA required). User tokens with 2FA will fail in CI with EOTP errors.
-
- ```bash
- # Check token type (requires npm CLI authenticated)
- npm token list
- ```
-
- Look for:
- - ✅ `read-write` tokens with NO 2FA requirement = Automation token (correct)
- - ❌ Tokens requiring OTP = User token (WRONG, will fail in CI)
-
- **How to create an Automation token:**
- 1. Go to npmjs.com → Settings → Access Tokens
- 2. Click "Generate New Token"
- 3. Select **"Automation"** (NOT "Publish")
- 4. Copy token and save as GitHub secret: `NPM_TOKEN`
-
- **If using a User token:** STOP. Create an Automation token first.
-
- The release workflow also requires:
-
- - `HOMEBREW_TAP_TOKEN`: fine-grained GitHub PAT restricted to
- `bradygaster/homebrew-squad`, with Contents read/write.
- - `WINGET_CREATE_GITHUB_TOKEN`: classic GitHub PAT with `public_repo`, owned by
- the account that maintains `tamirdresher/winget-pkgs`.
-
- Homebrew and WinGet publish only stable `vMAJOR.MINOR.PATCH` releases.
-
- ### 3. Branch and Tag State
-
- **Rule:** Release from `main` branch. Ensure clean state, no uncommitted changes, latest from origin.
-
- ```bash
- # Ensure on main and clean
- git checkout main
- git pull origin main
- git status # Should show: "nothing to commit, working tree clean"
-
- # Check tag doesn't already exist
- git tag -l "v0.8.22"
- # Output should be EMPTY. If tag exists, release already done or collision.
- ```
-
- **If tag exists:** STOP. Either release was already done, or there's a collision. Investigate before proceeding.
-
- ### 4. Disable bump-build.mjs
-
- **Rule:** `bump-build.mjs` is for dev builds ONLY. It must NOT run during release builds (it increments build numbers, creating 4-part versions).
-
- ```bash
- # Set env var to skip bump-build.mjs
- export SKIP_BUILD_BUMP=1
-
- # Verify it's set
- echo $SKIP_BUILD_BUMP
- # Output: 1
- ```
-
- **For Windows PowerShell:**
- ```powershell
- $env:SKIP_BUILD_BUMP = "1"
- ```
-
- **If not set:** `bump-build.mjs` will run and mutate versions. This causes disasters (see v0.8.22).
-
- ### 5. Root package.json Version Sync (v0.9.4 Lesson — PR #1043)
-
- **Rule:** `squad-release.yml` reads version from ROOT `package.json` (lines 31-35). If root is behind sub-packages (e.g., 0.9.1 while sub-packages are 0.9.4), the release workflow FAILS.
-
- ```bash
- # Verify all 3 package.json files match
- grep '"version"' package.json packages/squad-sdk/package.json packages/squad-cli/package.json
- # All 3 MUST show the same version
-
- # Fix if mismatched:
- npm version $VERSION --workspaces --include-workspace-root --no-git-tag-version
- ```
-
- **If versions don't match:** STOP. Run the `npm version` command above. This was the root cause of the v0.9.4 release delay.
-
- ### 6. CHANGELOG.md Version Entry (v0.9.4 Lesson — PR #1042)
-
- **Rule:** `squad-release.yml` validates that `CHANGELOG.md` contains `## [$VERSION]`. An `[Unreleased]` section alone is NOT sufficient.
-
- ```bash
- # Check CHANGELOG has the version entry
- grep -q "## \[$VERSION\]" CHANGELOG.md && echo "OK" || echo "MISSING — add version section"
- ```
-
- **Before promoting to main:**
- 1. Convert `[Unreleased]` to `[$VERSION] - YYYY-MM-DD` in CHANGELOG.md
- 2. Add a fresh `[Unreleased]` section above it
+ # Squad Release Process
- **If `## [$VERSION]` is missing:** STOP. Update CHANGELOG.md before promoting.
+ Read `.squad/skills/release-process/SKILL.md` for the canonical runbook and
+ recovery commands. The operational model is:
- ---
+ | Release | Trigger | Required version | Result |
+ |---------|---------|------------------|--------|
+ | Preview | Manual `squad-release.yml` dispatch from `dev` | `X.Y.Z-preview.N` | GitHub prerelease, npm `preview`, standalone archives |
+ | Stable | Manual `squad-promote.yml` dispatch from `dev` | `X.Y.Z` | Sanitized `main` push, GitHub stable release, npm `latest`, standalone archives, Homebrew, WinGet |
- ## Release Workflow
+ There is no staging `preview` branch. Do not create tags or GitHub Releases
+ manually.
- ### Step 1: Version Bump
+ ## Preconditions
- Update version in all 3 package.json files (root + both workspaces) in lockstep.
+ Before either channel:
```bash
- # Set target version (no 'v' prefix)
- VERSION="0.8.22"
-
- # Validate it's valid semver BEFORE proceeding
- node -p "require('semver').valid('$VERSION')"
- # Must output the version string, NOT null
-
- # Update all 3 package.json files
- npm version $VERSION --workspaces --include-workspace-root --no-git-tag-version
-
- # Verify all 3 match
+ git fetch origin dev main
+ git merge-base origin/dev origin/main
grep '"version"' package.json packages/squad-sdk/package.json packages/squad-cli/package.json
- # All 3 should show: "version": "0.8.22"
- ```
-
- **Checkpoint:** All 3 package.json files have identical versions. Run `semver.valid()` one more time to be sure.
-
- ### Step 2: Commit and Tag
-
- ```bash
- # Commit version bump
- git add package.json packages/squad-sdk/package.json packages/squad-cli/package.json
- git commit -m "chore: bump version to $VERSION
-
- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
-
- # Create tag (with 'v' prefix)
- git tag -a "v$VERSION" -m "Release v$VERSION"
-
- # Push commit and tag
- git push origin main
- git push origin "v$VERSION"
- ```
-
- **Checkpoint:** Tag created and pushed. Verify with `git tag -l "v$VERSION"`.
-
- ### Step 3: Create GitHub Release
-
- **CRITICAL:** Release must be **published**, NOT draft. Draft releases don't trigger `publish.yml` workflow.
-
- ```bash
- # Create GitHub Release (NOT draft)
- gh release create "v$VERSION" \
- --title "v$VERSION" \
- --notes "Release notes go here" \
- --latest
-
- # Verify release is PUBLISHED (not draft)
- gh release view "v$VERSION"
- # Output should NOT contain "(draft)"
- ```
-
- **If output contains `(draft)`:** STOP. Delete the release and recreate without `--draft` flag.
-
- ```bash
- # If you accidentally created a draft, fix it:
- gh release edit "v$VERSION" --draft=false
- ```
-
- **Checkpoint:** Release is published (NOT draft). `squad-release.yml` directly
- started its reusable npm and standalone publication jobs.
-
- ### Step 4: Monitor Workflow
-
- The `npm` and `standalone` jobs in `squad-release.yml` should start after
- release creation.
-
- ```bash
- # Watch the release workflow
- gh run list --workflow=squad-release.yml --limit 1
-
- # Get detailed status
- gh run view --log
- ```
-
- **Expected flow:**
- 1. `publish-sdk` job runs → publishes `@bradygaster/squad-sdk`
- 2. Verify step runs with retry loop (up to 5 attempts, 15s interval) to confirm SDK on npm registry
- 3. `publish-cli` job runs → publishes `@bradygaster/squad-cli`
- 4. Verify step runs with retry loop to confirm CLI on npm registry
- 5. Six standalone bundles and `SHA256SUMS.txt` are attached to the release
- 6. Stable releases update the Homebrew cask and open or reuse a WinGet PR
-
- **If workflow fails:** Check the logs. Common issues:
- - EOTP error = wrong NPM_TOKEN type (use Automation token)
- - Verify step timeout = npm propagation delay (retry loop should handle this, but propagation can take up to 2 minutes in rare cases)
- - Version mismatch = package.json version doesn't match tag
-
- **Checkpoint:** Both jobs succeeded. Workflow shows green checkmarks.
-
- ### Step 5: Verify npm Publication
-
- Manually verify both packages are on npm with correct `latest` dist-tag.
-
- ```bash
- # Check SDK
- npm view @bradygaster/squad-sdk version
- # Output: 0.8.22
-
- npm dist-tag ls @bradygaster/squad-sdk
- # Output should show: latest: 0.8.22
-
- # Check CLI
- npm view @bradygaster/squad-cli version
- # Output: 0.8.22
-
- npm dist-tag ls @bradygaster/squad-cli
- # Output should show: latest: 0.8.22
- ```
-
- **If versions don't match:** Something went wrong. Check workflow logs. DO NOT proceed with GitHub Release announcement until npm is correct.
-
- **Checkpoint:** Both packages show correct version. `latest` dist-tags point to the new version.
-
- ### Step 6: Test Installation
-
- Verify packages can be installed from npm (real-world smoke test).
-
- ```bash
- # Create temp directory
- mkdir /tmp/squad-release-test && cd /tmp/squad-release-test
-
- # Test SDK installation
- npm init -y
- npm install @bradygaster/squad-sdk
- node -p "require('@bradygaster/squad-sdk/package.json').version"
- # Output: 0.8.22
-
- # Test CLI installation
- npm install -g @bradygaster/squad-cli
- squad --version
- # Output: 0.8.22
-
- # Cleanup
- cd -
- rm -rf /tmp/squad-release-test
+ node -p "require('./packages/squad-cli/package.json').dependencies['@bradygaster/squad-sdk']"
+ grep -F "## [$VERSION]" CHANGELOG.md
+ npm run build
+ npx vitest run
```
- **If installation fails:** npm registry issue or package metadata corruption. DO NOT announce release until this works.
-
- **Checkpoint:** Both packages install cleanly. Versions match.
-
- ### Step 7: Sync dev to Next Preview
-
- After main release, sync dev to the next preview version.
-
- ```bash
- # Checkout dev
- git checkout dev
- git pull origin dev
-
- # Bump to next preview version (e.g., 0.8.23-preview.1)
- NEXT_VERSION="0.8.23-preview.1"
-
- # Validate semver
- node -p "require('semver').valid('$NEXT_VERSION')"
- # Must output the version string, NOT null
-
- # Update all 3 package.json files
- npm version $NEXT_VERSION --workspaces --include-workspace-root --no-git-tag-version
-
- # Commit
- git add package.json packages/squad-sdk/package.json packages/squad-cli/package.json
- git commit -m "chore: bump dev to $NEXT_VERSION
-
- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
-
- # Push
- git push origin dev
- ```
+ The ancestry command must return a commit, all three versions must match, the
+ CLI SDK dependency floor must be `>=VERSION`, and the changelog must contain
+ the exact release version.
- **Checkpoint:** dev branch now shows next preview version. Future dev builds will publish to `@preview` dist-tag.
+ Required Actions secrets:
- ---
+ - `NPM_TOKEN`: automation-capable npm publish token.
+ - `HOMEBREW_TAP_TOKEN`: classic PAT with `public_repo` from a collaborator with
+ write access to `bradygaster/homebrew-squad`.
+ - `WINGET_CREATE_GITHUB_TOKEN`: classic PAT with `public_repo` for
+ `tamirdresher/winget-pkgs`.
- ## Manual Publish (Fallback)
+ ## Preview
- If an automated publication job cannot be rerun from `squad-release.yml`, use
- `workflow_dispatch` for recovery.
+ After a PR sets an immutable prerelease version on `dev` and CI passes:
```bash
- # Recover npm publication from the immutable release tag
- gh workflow run squad-npm-publish.yml --ref main \
- -f version="0.8.22" \
- -f source_ref="v0.8.22"
-
- # Recover standalone assets and stable package-manager publication
- gh workflow run squad-standalone-release.yml --ref main \
- -f upload=true \
- -f release_tag="v0.8.22" \
- -f source_ref="v0.8.22"
-
- # Monitor the run
+ VERSION=0.14.0-preview.1
+ gh workflow run squad-release.yml --ref dev -f confirm_tag="v$VERSION"
gh run watch
```
- **Rule:** Only use this if automated publish failed. Always investigate why automation failed and fix it for next release.
-
- ### Direct Reusable Workflow Handoff (CRITICAL)
-
- GitHub does not emit downstream workflow events for releases created by the
- default `GITHUB_TOKEN`. `squad-release.yml` therefore calls
- `squad-npm-publish.yml` and `squad-standalone-release.yml` directly after
- creating a release. Do not replace this with an event-only chain.
-
- Publication is idempotent: existing npm versions, matching Homebrew content,
- and existing WinGet versions or pull requests are verified and skipped. Rerun
- the failed job after fixing credentials or an external-service failure.
-
- ---
-
- ## Rollback Procedure
-
- If a release is broken and needs to be rolled back:
-
- ### 1. Unpublish from npm (Nuclear Option)
-
- **WARNING:** npm unpublish is time-limited (24 hours) and leaves the version slot burned. Only use if version is critically broken.
-
- ```bash
- # Unpublish (requires npm owner privileges)
- npm unpublish @bradygaster/squad-sdk@0.8.22
- npm unpublish @bradygaster/squad-cli@0.8.22
- ```
-
- ### 2. Deprecate on npm (Preferred)
-
- **Preferred approach:** Mark version as deprecated, publish a hotfix.
-
- ```bash
- # Deprecate broken version
- npm deprecate @bradygaster/squad-sdk@0.8.22 "Broken release, use 0.8.22.1 instead"
- npm deprecate @bradygaster/squad-cli@0.8.22 "Broken release, use 0.8.22.1 instead"
-
- # Publish hotfix version
- # (Follow this runbook with version 0.8.22.1)
- ```
-
- ### 3. Delete GitHub Release and Tag
-
- ```bash
- # Delete GitHub Release
- gh release delete "v0.8.22" --yes
-
- # Delete tag locally and remotely
- git tag -d "v0.8.22"
- git push origin --delete "v0.8.22"
- ```
-
- ### 4. Revert Commit on main
-
- ```bash
- # Revert version bump commit
- git checkout main
- git revert HEAD
- git push origin main
- ```
-
- **Checkpoint:** Tag and release deleted. main branch reverted. npm packages deprecated or unpublished.
-
- ---
-
- ## Common Failure Modes
-
- ### EOTP Error (npm OTP Required)
-
- **Symptom:** Workflow fails with `EOTP` error.
- **Root cause:** NPM_TOKEN is a User token with 2FA enabled. CI can't provide OTP.
- **Fix:** Replace NPM_TOKEN with an Automation token (no 2FA). See "NPM_TOKEN Verification" above.
-
- ### Verify Step 404 (npm Propagation Delay)
-
- **Symptom:** Verify step fails with 404 even though publish succeeded.
- **Root cause:** npm registry propagation delay (5-30 seconds).
- **Fix:** Verify step now has retry loop (5 attempts, 15s interval). Should auto-resolve. If not, wait 2 minutes and re-run workflow.
-
- ### Version Mismatch (package.json ≠ tag)
-
- **Symptom:** Verify step fails with "Package version (X) does not match target version (Y)".
- **Root cause:** package.json version doesn't match the tag version.
- **Fix:** Ensure all 3 package.json files were updated in Step 1. Re-run `npm version` if needed.
-
- ### 4-Part Version Mangled by npm
-
- **Symptom:** Published version on npm doesn't match package.json (e.g., 0.8.21.4 became 0.8.2-1.4).
- **Root cause:** 4-part versions are NOT valid semver. npm's parser misinterprets them.
- **Fix:** NEVER use 4-part versions. Only 3-part (0.8.22) or prerelease (0.8.23-preview.1). Run `semver.valid()` before ANY commit.
-
- ### Draft Release Didn't Trigger Workflow
-
- **Symptom:** Release created but `publish.yml` never ran.
- **Root cause:** Release was created as a draft. Draft releases don't emit `release: published` event.
- **Fix:** Edit release and change to published: `gh release edit "v$VERSION" --draft=false`. Workflow should trigger immediately.
-
- ### Root package.json Version Drift (v0.9.4 — PR #1043)
-
- **Symptom:** `squad-release.yml` fails with "Version $VERSION not found in CHANGELOG.md" even though CHANGELOG looks correct.
- **Root cause:** Root `package.json` version is behind sub-packages. The workflow reads version from root, not from workspace packages.
- **Fix:** Run `npm version $VERSION --workspaces --include-workspace-root --no-git-tag-version` to sync all 3 package.json files.
-
- ### CHANGELOG Missing Version Section (v0.9.4 — PR #1042)
-
- **Symptom:** `squad-release.yml` fails with "Version $VERSION not found in CHANGELOG.md".
- **Root cause:** CHANGELOG.md still has `[Unreleased]` but no `## [$VERSION]` section.
- **Fix:** Convert `[Unreleased]` to `[$VERSION] - YYYY-MM-DD` and add a fresh `[Unreleased]` above it.
-
- ### Publication Jobs Missing After Release
-
- **Symptom:** `squad-release.yml` creates the release but its `npm` or
- `standalone` job is absent.
- **Root cause:** The direct reusable-workflow handoff was removed or the release
- job did not report `created=true`.
- **Fix:** Restore the direct calls in `squad-release.yml`. For an existing
- release, use the recovery dispatch commands above with the immutable release tag.
-
- ### Lockfile Integrity Check Rejects Workspace Packages (v0.9.4 — PR #1044)
+ The release workflow rejects stable versions on manual dispatch, creates a
+ GitHub prerelease, publishes npm `preview`, and uploads standalone bundles.
+ Homebrew, WinGet, the activation pin, and insider-tag promotion remain
+ stable-only.
- **Symptom:** `squad-npm-publish.yml` lockfile stability check fails on workspace packages.
- **Root cause:** Workspace packages resolve to bare relative paths (`packages/squad-sdk`), not `file:` URLs. The check tried to validate integrity hashes on non-registry packages.
- **Fix:** Filter lockfile integrity check to only validate packages resolved from npm registry (`startsWith('https://')`).
+ ## Stable
- ### Prebuild Bump Breaks Workspace Linking (v0.9.4)
+ After a PR replaces the preview version with `X.Y.Z` on `dev` and CI passes:
- **Symptom:** Local `npm run build` fails with resolution errors after running prebuild.
- **Root cause:** `scripts/bump-build.mjs` bumps `0.9.4` → `0.9.4-build.1`, breaking exact version match in CLI's dependency on SDK.
- **Fix:** Reset and reinstall:
```bash
- git checkout -- package.json packages/*/package.json
- rm -rf node_modules packages/*/node_modules
- npm install
- npm run build
- ```
-
- ---
-
- ## Validation Checklist
-
- Before starting ANY release, confirm:
-
- - [ ] Version is valid semver: `node -p "require('semver').valid('VERSION')"` returns the version string (NOT null)
- - [ ] NPM_TOKEN is an Automation token (no 2FA): `npm token list` shows `read-write` without OTP requirement
- - [ ] `HOMEBREW_TAP_TOKEN` has Contents read/write on `bradygaster/homebrew-squad`
- - [ ] `WINGET_CREATE_GITHUB_TOKEN` is a classic PAT with `public_repo`
- - [ ] Branch is clean: `git status` shows "nothing to commit, working tree clean"
- - [ ] Tag doesn't exist: `git tag -l "vVERSION"` returns empty
- - [ ] `SKIP_BUILD_BUMP=1` is set: `echo $SKIP_BUILD_BUMP` returns `1`
- - [ ] **Root package.json version matches sub-packages** (v0.9.4): `grep '"version"' package.json packages/*/package.json` — all 3 identical
- - [ ] **CHANGELOG.md has `## [$VERSION]` section** (v0.9.4): `grep "## \[$VERSION\]" CHANGELOG.md` returns a match
-
- Before creating GitHub Release:
-
- - [ ] All 3 package.json files have matching versions: `grep '"version"' package.json packages/*/package.json`
- - [ ] Commit is pushed: `git log origin/main..main` returns empty
- - [ ] Tag is pushed: `git ls-remote --tags origin vVERSION` returns the tag SHA
-
- After GitHub Release:
-
- - [ ] Release is published (NOT draft): `gh release view "vVERSION"` output doesn't contain "(draft)"
- - [ ] Release workflow shows `npm` and `standalone` publication jobs
-
- After workflow completes:
-
- - [ ] Both jobs succeeded: Workflow shows green checkmarks
- - [ ] SDK on npm: `npm view @bradygaster/squad-sdk version` returns correct version
- - [ ] CLI on npm: `npm view @bradygaster/squad-cli version` returns correct version
- - [ ] `latest` tags correct: `npm dist-tag ls @bradygaster/squad-sdk` shows `latest: VERSION`
- - [ ] Packages install: `npm install @bradygaster/squad-cli` succeeds
- - [ ] Release has six standalone archives and `SHA256SUMS.txt`
- - [ ] Stable release updated `bradygaster/homebrew-squad/Casks/squad.rb`
- - [ ] Stable release opened or reused the WinGet manifest PR
-
- After dev sync:
-
- - [ ] dev branch has next preview version: `git show dev:package.json | grep version` shows next preview
-
- ---
-
- ## Post-Mortem Reference
-
- This skill was created after the v0.8.22 release disaster and updated after v0.9.4. Full retrospective: `.squad/decisions/inbox/keaton-v0822-retrospective.md`
-
- **Key learnings (v0.8.22):**
- 1. No release without a runbook = improvisation = disaster
- 2. Semver validation is mandatory — 4-part versions break npm
- 3. NPM_TOKEN type matters — User tokens with 2FA fail in CI
- 4. Draft releases are a footgun — they don't trigger automation
- 5. Retry logic is essential — npm propagation takes time
-
- **Key learnings (v0.9.4 — PRs #1042, #1043, #1044):**
- 6. Root package.json MUST match sub-packages — squad-release.yml reads from root
- 7. CHANGELOG.md must have `## [$VERSION]` section — `[Unreleased]` is not enough
- 8. GITHUB_TOKEN events don't trigger downstream workflows — use direct reusable workflow calls
- 9. Lockfile integrity checks must filter out workspace packages (not from registry)
- 10. Prebuild version bump breaks local workspace linking — reset with git checkout
+ gh workflow run squad-promote.yml --ref dev -f dry_run=true
+ gh run watch
- **The full promotion chain (v0.9.4 documented):**
- ```
- dev → preview → main (via squad-promote.yml)
- main push → squad-release.yml validates CHANGELOG, creates tag + GitHub Release
- release job → directly calls reusable npm + standalone publication workflows
- npm → SDK + CLI packages
- standalone → six archives + checksums + Homebrew + WinGet PR
+ gh workflow run squad-promote.yml --ref dev -f dry_run=false
+ gh run watch
```
- **Never again.**
-
- ---
-
- ## Local Development
-
- ### Recovering from Prebuild Version Bump (v0.9.4)
+ Promotion merges `dev` directly into `main`, strips internal team state,
+ validates the release tree, builds it, runs tests, and pushes `main`. It then
+ explicitly dispatches `squad-release.yml` because `GITHUB_TOKEN` pushes do not
+ start another workflow. The release creates the tag and stable GitHub Release
+ and directly invokes npm and standalone publication.
- `scripts/bump-build.mjs` runs during `npm run prebuild` and mutates versions (e.g., `0.9.4` → `0.9.4-build.1`). This breaks workspace linking because CLI depends on exact version match with SDK.
+ ## Verify
- **Recovery steps:**
```bash
- git checkout -- package.json packages/*/package.json
- rm -rf node_modules packages/*/node_modules
- npm install
- npm run build
+ npm view @bradygaster/squad-sdk dist-tags.preview
+ npm view @bradygaster/squad-cli dist-tags.preview
+ npm view @bradygaster/squad-sdk dist-tags.latest
+ npm view @bradygaster/squad-cli dist-tags.latest
+ gh release view "v$VERSION"
```
- **Prevention:** Set `SKIP_BUILD_BUMP=1` before running builds locally if you don't need build-number incrementing.
+ Use the tag for the channel being released. Verify the GitHub Release contains
+ all six OS/architecture archives and `SHA256SUMS.txt`. Stable releases must also
+ update the Homebrew cask and create or reuse a WinGet PR.
- ---
+ ## Recovery
- ## Related
+ Do not recreate or overwrite the tag. Rerun a failed child job, or dispatch the
+ reusable npm/standalone workflow with `source_ref=v$VERSION`. Use `--ref dev`
+ for previews and `--ref main` for stable releases. The canonical runbook
+ contains the exact commands.
- - Team-level skill: `.squad/skills/release-process/SKILL.md`
- - v0.9.4 fixes: PR #1042 (CHANGELOG), PR #1043 (root package.json), PR #1044 (lockfile integrity)
- - v0.8.22 retrospective: `.squad/decisions/inbox/keaton-v0822-retrospective.md`
- - Playbook: `PUBLISH-README.md` (repo root)
+ After a stable release, prepare the next `X.Y.Z-preview.1` version in a normal
+ PR to `dev`.