Release Process for Squad Maintainers
Try this to ship a new version:
We're ready to ship v1.2.0 — run the release process: changelog, tags, and publish
Try this to promote to production:
Merge preview to main and cut a production release
Complete step-by-step guide for Squad maintainers: three-branch model (dev/preview/main), guard workflows, PR merging, and production release procedures.
Table of Contents
- Branch Model Overview
- Preview Build Workflow
- Pull Request Workflow
- Merging Back to Dev
- Full Release Lifecycle
- Branch Protection Rules
- Testing the Guard Workflow
- Troubleshooting
- Sample Prompts
Branch Model Overview
Squad uses a three-branch model for release safety:
| Branch | Purpose | Who Commits | Guard Active? | Files Allowed |
|---|---|---|---|---|
| dev | Development — all work happens here | All team members | ❌ No | Everything (.ai-team/, team-docs, etc.) |
| preview | Staging/testing — validated product only | Release coordinator | ✅ Yes | Distribution files only (.ai-team/ blocked) |
| main | Production — release source for npx |
Release coordinator | ✅ Yes | Distribution files only (.ai-team/ blocked) |
Key principle: .ai-team/ (team state) and internal team-docs/ (except blog) never leave dev. When code ships, it ships clean.
Preview Build Workflow
Purpose: Create a staging environment to test the full release before pushing to production.
Step 1: Create the Preview Branch
Start on dev and ensure you have the latest commits:
git checkout dev
git pull origin dev
Create a preview branch (or reset if it exists):
git checkout -b preview 2>/dev/null || git checkout preview
git reset --hard dev
Step 2: Remove Forbidden Files (Guard Enforcement)
Before pushing to preview, remove forbidden paths that the guard workflow will block:
# Remove .ai-team/ (keep local copy via .gitignore)
git rm --cached -r .ai-team/
# Remove team-docs/
git rm --cached -r team-docs/
If nothing was removed, that’s fine:
git status
# On branch preview
# nothing to commit, working tree clean
If there are changes:
git commit -m "chore: remove forbidden paths for preview branch"
git push -f origin preview
Step 3: Verify Guard Passes
The guard workflow (.github/workflows/squad-main-guard.yml) runs automatically on any PR to preview or main. Check the workflow run in GitHub Actions:
# View workflow runs for the preview branch
gh run list --branch preview --status completed
Expected output: ✅ All checks pass (no forbidden files found).
If the guard fails, see Testing the Guard Workflow for debugging.
Step 4: Test on Preview
Push test branches off preview and create PRs back to preview to validate the release:
# Create a feature branch off preview
git checkout -b test/release-validation
echo "# Release validation" > RELEASE_TEST.md
git add RELEASE_TEST.md
git commit -m "test: release validation"
git push -u origin test/release-validation
Create a PR via gh:
gh pr create --base preview --title "Release validation test" --body "Validate preview build."
The guard checks this PR. If it passes, your preview branch is clean.
Pull Request Workflow
Creating a PR (Feature Work on Dev)
When a feature is complete on dev, create a PR for review:
git checkout -b feature/my-feature
# ... make changes ...
git add .
git commit -m "feat: my new feature"
git push -u origin feature/my-feature
Create the PR:
gh pr create --base dev --title "feat: my new feature" --body "Description of changes"
Reviewing a PR
Reviewers use the GitHub UI or gh CLI:
# View open PRs
gh pr list --base dev
# Review a specific PR
gh pr view 123 --web
Comments, approvals, and change requests flow through GitHub. No special commands needed.
Merging a PR to Dev
Once approved, merge to dev:
gh pr merge 123 --merge --auto
This squash-merges the PR and deletes the feature branch. To keep history with merge commits:
gh pr merge 123 --create-branch-off-target --auto
After merge, update your local dev:
git checkout dev
git pull origin dev
Merging Back to Dev
After a release ships from main, sync changes back to dev (for docs updates, changelog, version bumps made during release):
Step 1: Create a Sync PR
On your dev branch:
git checkout dev
git pull origin dev
git checkout -b chore/sync-from-main
Merge main into the sync branch:
git merge main --no-ff --no-edit
This brings all production commits back to dev, preserving the release tag and history.
Step 2: Resolve Conflicts (if any)
If conflicts exist, resolve them:
git status
# Lists conflicted files
git add .
git commit -m "chore: resolve merge conflicts from main"
Step 3: Push and Create PR
git push -u origin chore/sync-from-main
gh pr create --base dev --title "chore: sync from main" --body "Bring production changes back to dev"
Step 4: Merge Back
gh pr merge --merge --auto
git checkout dev && git pull origin dev
Full Release Lifecycle
Complete journey from feature work to production tag.
Phase 1: Preparation (on dev)
Time: Before release day. All features complete, all tests passing.
- Update CHANGELOG.md:
# Edit CHANGELOG.md with new version entry
# Format: ## [X.Y.Z] — YYYY-MM-DD
# Sections: Added, Changed, Community, Deprecated, Removed, Fixed
nano CHANGELOG.md
Example entry:
## [0.4.0] — 2026-02-15
### Added
- MCP tool discovery and integration
- Plugin marketplace support
- Notification system (Trello, Teams, GitHub)
- 11 new universes (Futurama, Seinfeld, The Office, etc.)
- Branch protection guard (squad-main-guard.yml)
### Changed
- VS Code support now fully compatible (zero code changes)
- Agent progress signals with [MILESTONE] markers
- Universe count: 20 → 31
### Community
- @csharpfritz: MCP tool discovery (#11), user docs (#16)
- @spboyer: VS Code compatibility (#17)
- Update version in package.json:
# Edit version field
nano package.json
# "version": "0.4.0"
- Commit to dev:
git add CHANGELOG.md package.json
git commit -m "chore: prepare release v0.4.0"
git push origin dev
Phase 2: Preview Build (on preview)
Time: Release day morning. Validate all files before shipping.
Follow Preview Build Workflow above. Summary:
git checkout preview
git reset --hard origin/dev
git rm --cached -r .ai-team/ 2>/dev/null
git rm --cached -r team-docs/ 2>/dev/null
git commit -m "chore: remove forbidden paths for preview" 2>/dev/null
git push -f origin preview
# Wait for guard workflow to pass
Check GitHub Actions:
gh run list --branch preview --status completed --limit 1
Expected: ✅ All checks pass.
Phase 3: Merge to Main (on main)
Time: Release day afternoon, after preview validation.
- Create a release PR to main:
git checkout main
git pull origin main
git checkout -b release/v0.4.0
git merge --no-ff preview -m "Release v0.4.0"
git push -u origin release/v0.4.0
- Create PR for final review:
gh pr create --base main --title "Release v0.4.0" --body "Final release PR. Guard enforces file restrictions."
- Wait for guard to pass, then merge:
gh pr merge --merge --auto
The guard validates that only distribution-safe files reach main.
Phase 4: Tag the Release (on main)
Time: After merge to main. This triggers the release workflow.
git checkout main
git pull origin main
git tag -a v0.4.0 -m "Release v0.4.0: MCP integration, Plugin marketplace, Notifications"
git push origin v0.4.0
Tag format: vX.Y.Z (semantic versioning). The version MUST match package.json version.
Phase 5: Verify the Release
The tag push triggers .github/workflows/release.yml:
# Monitor the release workflow
gh run list --workflow release.yml --status in_progress
gh run list --workflow release.yml --status completed --limit 1
Check what the workflow does:
- Runs full test suite
- Creates a GitHub Release with notes
- Validates that only distribution files were shipped
If the workflow fails, see Troubleshooting.
Phase 6: Sync Back to Dev
After release, bring version/changelog updates back to dev:
git checkout dev
git pull origin dev
git checkout -b chore/sync-from-main
git merge main --no-ff
git push -u origin chore/sync-from-main
gh pr merge --merge --auto
git pull origin dev
Branch Protection Rules
The repository enforces protection rules on main and preview to prevent accidental shipping of forbidden files.
What’s Protected
| Branch | Rule | Effect |
|---|---|---|
main |
Require guard workflow to pass | PRs with .ai-team/ or team-docs/ (except blog) are blocked |
main |
Require PR review | All PRs require at least 1 approval |
main |
Require status checks to pass | Tests must pass before merge allowed |
preview |
Require guard workflow to pass | PRs with .ai-team/ or team-docs/ (except blog) are blocked |
The Guard Workflow
File: .github/workflows/squad-main-guard.yml
When it runs: On any PR to main or preview (events: opened, synchronize, reopened)
What it checks:
// Forbidden on main and preview:
✗ .ai-team/** (zero exceptions — team state never ships)
✗ team-docs/** (zero exceptions — internal team docs never ship)
// Allowed everywhere:
✓ index.js (distribution)
✓ squad.agent.md (distribution)
✓ templates/**/* (distribution)
✓ docs/**/* (distribution)
✓ test/**/* (distribution)
✓ CHANGELOG.md (distribution)
✓ README.md (distribution)
✓ package.json (distribution)
✓ .github/workflows/** (distribution)
Failure behavior: If forbidden files detected:
## 🚫 Forbidden files detected in PR to main
The following files must NOT be merged into `main`.
`.ai-team/` is runtime team state — it belongs on dev branches only.
`team-docs/` is internal team content — it belongs on dev branches only.
### Forbidden files found:
- `.ai-team/agents/neo/history.md`
- `.ai-team/decisions.md`
- `team-docs/internal/roadmap.md`
### How to fix:
git rm --cached -r .ai-team/
git rm --cached -r team-docs/
git commit -m "chore: remove forbidden paths from PR"
git push
Success behavior: If all files pass:
✅ No forbidden paths found in PR — all clear.
Testing the Guard Workflow
Verify the guard blocks forbidden files. Use a sacrificial PR.
Test 1: Verify Guard Blocks .ai-team/
- Create a test branch:
git checkout -b test/guard-ai-team-block
- Add a fake .ai-team/ file:
mkdir -p .ai-team/agents/test
echo "test content" > .ai-team/agents/test/history.md
git add .ai-team/agents/test/history.md
git commit -m "test: add .ai-team/ file to verify guard blocks it"
git push -u origin test/guard-ai-team-block
- Create PR to main:
gh pr create --base main --title "test: guard should block .ai-team/" \
--body "This PR tests that the guard blocks .ai-team/ files"
- Check the PR status:
gh pr view <PR_NUMBER>
# or view in browser
gh pr view <PR_NUMBER> --web
Expected: ❌ Guard workflow reports forbidden files. PR cannot merge until .ai-team/ is removed.
- Clean up the PR:
git rm --cached -r .ai-team/
git commit -m "fix: remove .ai-team/ file"
git push
Expected: ✅ Guard workflow passes. PR is now mergeable.
- Delete the branch:
gh pr close --delete-branch
git checkout dev && git branch -D test/guard-ai-team-block
Test 2: Verify Guard Blocks Internal team-docs/
- Create a test branch:
git checkout -b test/guard-team-docs-block
- Add an internal team-docs file:
mkdir -p team-docs/internal
echo "internal roadmap" > team-docs/internal/roadmap.md
git add team-docs/internal/roadmap.md
git commit -m "test: add internal team-docs/ file"
git push -u origin test/guard-team-docs-block
- Create PR to preview:
gh pr create --base preview --title "test: guard should block team-docs/internal/" \
--body "This PR tests that the guard blocks internal team-docs/ files"
Expected: ❌ Guard blocks team-docs/internal/roadmap.md.
- Clean up:
git rm --cached -r team-docs/internal/
git commit -m "fix: remove internal team-docs/"
git push
Expected: ✅ Guard passes.
- Delete the branch:
gh pr close --delete-branch
Test 3: Verify Guard Blocks team-docs/
- Create a test branch:
git checkout -b test/guard-blocks-team-docs
- Add a team-docs file:
mkdir -p team-docs
echo "# Internal Notes" > team-docs/notes.md
git add team-docs/notes.md
git commit -m "test: add team-docs file (should be blocked)"
git push -u origin test/guard-blocks-team-docs
- Create PR to main:
gh pr create --base main --title "test: guard should block team-docs/" \
--body "This PR tests that all team-docs files are blocked"
Expected: ❌ Guard fails. ALL team-docs/ content is blocked on main and preview.
- Delete the branch:
gh pr close --delete-branch
Troubleshooting
Issue: Guard Workflow Failed — Forbidden Files Detected
Error message: 🚫 Forbidden files detected in PR to main
Cause: You have .ai-team/ or internal team-docs/ files in the PR.
Fix:
# Remove .ai-team/ (keeps local copy)
git rm --cached -r .ai-team/
# Remove team-docs/
git rm --cached -r team-docs/
# Commit and push
git commit -m "chore: remove forbidden paths"
git push
The guard will re-run automatically. Wait for ✅ pass.
Issue: SSH Hangs During Push
Symptom: git push hangs indefinitely.
Cause: SSH authentication timeout or network issue.
Fix:
# Try with HTTP instead (if you have auth configured)
git remote set-url origin https://github.com/bradygaster/squad.git
git push origin <branch>
# Or explicitly use SSH with a shorter timeout
GIT_SSH_COMMAND="ssh -v" git push origin <branch>
# If still stuck, check your SSH key
ssh -T git@github.com
Issue: .ai-team/ Files Keep Getting Committed
Symptom: .ai-team/ shows as untracked but somehow appears in commits.
Cause: Files were previously tracked (added with git add -f before .gitignore was updated).
Fix: Remove tracked copies permanently (one time per repo):
# Remove .ai-team/ from git tracking
git rm --cached -r .ai-team/
# Verify .gitignore has .ai-team/
grep ".ai-team" .gitignore
# If not, add it
echo ".ai-team/" >> .gitignore
# Commit
git add .gitignore
git commit -m "chore: ensure .ai-team/ is untracked"
git push origin dev
Issue: Missing Workflows in .github/workflows/
Symptom: Guard workflow doesn’t exist or other Squad workflows missing.
Cause: Workflows not installed during Squad init, or accidentally deleted.
Fix: Re-run upgrade to restore workflows:
npx github:bradygaster/squad upgrade
git add .github/workflows/
git commit -m "chore: restore Squad workflows"
git push origin dev
Available Squad workflows:
squad-main-guard.yml— Blocks forbidden files from main/previewsquad-heartbeat.yml— Ralph’s periodic triage and labelingsquad-issue-assign.yml— Auto-assign labeled issuessquad-label-enforce.yml— Enforce label namespace integritysquad-triage.yml— Triage unlabeled issuessync-squad-labels.yml— Sync static label definitions
Issue: GitHub Release Not Created After Tag
Symptom: Tag pushed but no GitHub Release appears.
Cause: Release workflow failed, or release already exists for that tag.
Fix:
# Check workflow status
gh run list --workflow release.yml --status completed --limit 1
# View the latest run details
gh run view <RUN_ID>
# If the workflow failed, check logs
gh run view <RUN_ID> --log
# If no release exists, create manually
gh release create v0.4.0 --title "v0.4.0" \
--notes-file CHANGELOG.md
# To set as prerelease (for 0.x versions)
gh release create v0.4.0 --title "v0.4.0" --prerelease \
--notes-file CHANGELOG.md
Sample Prompts
Use these with Kobayashi or in Copilot sessions to guide release work.
To Prepare for Release
Kobayashi, prepare v0.4.0 for release:
1. Update CHANGELOG.md with the new version entry
2. Update version in package.json
3. Commit both changes to dev branch
Use these features as the new entry:
- MCP tool discovery and integration
- Plugin marketplace support
- Notification system
- 11 new universes
- Branch protection guard
To Build a Preview
Kobayashi, build a preview branch:
1. Create preview branch from dev
2. Remove .ai-team/ and team-docs/ (except blog)
3. Commit the removal
4. Push to origin
5. Wait for guard workflow to pass
6. Confirm the guard result
To Tag a Release
Kobayashi, tag the release:
1. Checkout main
2. Create and push tag v0.4.0
3. Verify the release workflow starts
4. Report when it completes
To Sync After Release
Kobayashi, sync main back to dev:
1. Create a chore/sync-from-main branch
2. Merge main into it
3. Create and merge PR back to dev
4. Confirm dev is up to date
To Test the Guard
Kobayashi, test the guard workflow:
1. Create a test branch test/guard-ai-team-block
2. Add .ai-team/agents/test/history.md with dummy content
3. Commit and push
4. Create PR to main
5. Report the guard result (should fail)
6. Remove the file and push again
7. Report the final guard result (should pass)
8. Clean up the branch
To Fix a Blocked PR
Kobayashi, fix this blocked PR:
1. Fetch the current PR state
2. Remove all .ai-team/ and team-docs/ files
3. Commit the removal
4. Push to update the PR
5. Wait for guard to pass
Key Files Reference
- Guard workflow:
.github/workflows/squad-main-guard.yml - Release workflow:
.github/workflows/release.yml(if it exists) - Changelog:
CHANGELOG.md - Distribution config:
package.json(version, files array) - Ignore rules:
.gitignore,.npmignore,.gitattributes - Branch protection settings: GitHub repo Settings → Branches
- Distributed via:
npx github:bradygaster/squad
Tips
- Preview is your staging environment. Test everything there before merging to main.
- Guard is your safety net. Let it block forbidden files—it’s preventing distribution corruption.
.ai-team/never leaves dev. It’s runtime state, not product.- Tag from main only. This is your single source of truth for releases.
- Version in package.json must match git tag. Keep them in sync.
- Communicate releases. Update team.md, decisions.md, and CHANGELOG.md before shipping.
- Use
ghCLI for everything. It’s faster and more reliable than web UI for scripting.