diff --git a/docs/src/content/docs/get-started/migration.md b/docs/src/content/docs/get-started/migration.md index ea57135d9..eb5ec71e6 100644 --- a/docs/src/content/docs/get-started/migration.md +++ b/docs/src/content/docs/get-started/migration.md @@ -29,6 +29,10 @@ | `.ai-team/` directory | `.squad/` directory | | v0.5.4 (beta) | v0.8.x (latest) | +> **Distribution changed at v0.8.0** +> +> Versions before v0.8.0 were distributed exclusively through GitHub (`npx github:bradygaster/squad`). Starting with v0.8.0, Squad moved to npm under two packages: `@bradygaster/squad-cli` (CLI) and `@bradygaster/squad-sdk` (SDK). The `npx github:` path no longer works for any version. If you see it referenced in older docs or blog posts for versions before v0.8.0, that was historically accurate — but you can't use it today. For v0.8.0 and later, use `npm install -g @bradygaster/squad-cli`. + --- ## Scenario 1: Brand New User @@ -212,7 +216,7 @@ The `squad` command works the same way. Your `.squad/` directory does not need t ## Scenario 5: Was Using npx github: Distribution -The GitHub-native distribution (`npx github:bradygaster/squad`) has been removed. Squad is now distributed exclusively through npm. +The GitHub-native distribution (`npx github:bradygaster/squad`) has been removed. Squad is now distributed exclusively through npm. This change happened at v0.8.0 — versions before v0.8.0 only ever existed on GitHub, so if you were on a pre-0.8.0 version, v0.8.0 is where the npm packages began. ### Switch diff --git a/docs/src/content/docs/insider-program.md b/docs/src/content/docs/insider-program.md index efe69c8f8..898b2d539 100644 --- a/docs/src/content/docs/insider-program.md +++ b/docs/src/content/docs/insider-program.md @@ -17,19 +17,21 @@ The Insider Program gives you continuous access to development builds of Squad. ## How to Install and Upgrade -### Install Insider Build +### Install insider build ```bash -npx github:bradygaster/squad#insider +npm install -g @bradygaster/squad-cli@insider ``` -### Upgrade Existing Repo to Insider +### Upgrade to latest insider build + +Run the same install command — npm handles the upgrade: ```bash -npx github:bradygaster/squad#insider upgrade +npm install -g @bradygaster/squad-cli@insider ``` -This updates Squad-owned files (`squad.agent.md`, workflows, templates) to the latest insider build. Your `.squad/` team state (agents, decisions, casting, history) is always preserved. +This updates your CLI to the latest insider build. Your `.squad/` team state (agents, decisions, casting, history) is always preserved. --- @@ -75,7 +77,7 @@ You'll see this in your `squad.agent.md` HTML version comment: **Pin a specific tagged version:** ```bash -npx github:bradygaster/squad#v0.5.2-insider+ +npm install -g @bradygaster/squad-cli@ ``` --- @@ -102,7 +104,7 @@ Version: v0.4.2-insider+abc1234f Environment: CLI on macOS 14.1, Node 20.11.0 Steps: -1. npx github:bradygaster/squad#insider +1. npm install -g @bradygaster/squad-cli@insider 2. Follow quick start 3. Error in squad.agent.md... ``` @@ -114,10 +116,10 @@ Steps: Want to go back to stable releases? ```bash -npx github:bradygaster/squad +npm install -g @bradygaster/squad-cli ``` -This installs the latest stable version. Your `.ai-team/` state is safe — it'll work with any version. +This installs the latest stable version. Your `.squad/` state is safe — it'll work with any version. --- @@ -129,7 +131,7 @@ This installs the latest stable version. Your `.ai-team/` state is safe — it'l ### Q: Can I switch between insider and stable builds? -**A:** Yes. Insider builds are backward compatible with stable installs. Your `.ai-team/` directory works with any version. +**A:** Yes. Insider builds are backward compatible with stable installs. Your `.squad/` directory works with any version. ### Q: How often do insider builds update? @@ -137,15 +139,14 @@ This installs the latest stable version. Your `.ai-team/` state is safe — it'l ### Q: Will my team state be preserved? -**A:** Yes. `.ai-team/` is never overwritten on upgrade. All your agents, decisions, and histories are safe. +**A:** Yes. `.squad/` is never overwritten on upgrade. All your agents, decisions, and histories are safe. ### Q: What if an insider build has a bad bug? **A:** Roll back immediately: ```bash -npx github:bradygaster/squad # Back to stable -npx github:bradygaster/squad upgrade # Apply stable version +npm install -g @bradygaster/squad-cli # Back to stable ``` Then [report the issue](https://github.com/bradygaster/squad/issues). diff --git a/docs/src/content/docs/scenarios/client-compatibility.md b/docs/src/content/docs/scenarios/client-compatibility.md index 104a11476..5b363d210 100644 --- a/docs/src/content/docs/scenarios/client-compatibility.md +++ b/docs/src/content/docs/scenarios/client-compatibility.md @@ -14,8 +14,8 @@ Squad runs on multiple Copilot surfaces — each with its own agent spawning mec | **Background/async execution** | ✅ `mode: "background"` (fire-and-forget) | ⚠️ Sync only (parallel concurrent) | ? | ? | | **Parallel fan-out** | ✅ Background tasks + `read_agent` | ✅ Multiple subagents in one turn | ? | ? | | **File discovery (.github/agents/)** | ✅ Automatic | ✅ Automatic | ? | ? | -| **`.ai-team/` file access (read)** | ✅ Full | ✅ Full (workspace-scoped) | ? | ? | -| **`.ai-team/` file access (write)** | ✅ Full | ✅ Full (with approval prompt) | ? | ? | +| **`.squad/` file access (read)** | ✅ Full | ✅ Full (workspace-scoped) | ? | ? | +| **`.squad/` file access (write)** | ✅ Full | ✅ Full (with approval prompt) | ? | ? | | **SQL tool** | ✅ Available | ❌ Not available | ❌ Not available | ❌ Not available | | **MCP server access** | ✅ Full | ✅ Full (inherited) | ⚠️ Limited | ⚠️ Limited | @@ -69,7 +69,7 @@ Squad's **primary platform**. All features are fully supported. ### File Discovery & Access - **Auto-discovery:** `.github/agents/squad.agent.md` is discovered automatically -- **`.ai-team/` access:** Unrestricted (full filesystem) +- **`.squad/` access:** Unrestricted (full filesystem) - **Parallel reads:** Multiple file operations in one turn supported - **Parallel writes:** Multiple file creates/edits in one turn supported @@ -123,8 +123,8 @@ Squad runs on VS Code with **conditional support**. Key differences from CLI: - **Auto-discovery:** `.github/agents/squad.agent.md` auto-discovered from workspace on load (file watchers enabled — no restart needed on changes) - **Scope:** Workspace-scoped (cannot access outside workspace directory) -- **`.ai-team/` read:** ✅ Full access via `readFile` tool -- **`.ai-team/` write:** ✅ Full access via `createFile` / `editFiles` tools +- **`.squad/` read:** ✅ Full access via `readFile` tool +- **`.squad/` write:** ✅ Full access via `createFile` / `editFiles` tools - **First-time approval:** VS Code may prompt for file modification approval on first write (security feature) - **User experience:** "Always allow in this workspace" option available - Subsequent writes in same workspace are automatic @@ -160,7 +160,7 @@ Squad runs on VS Code with **conditional support**. Key differences from CLI: ### Questions to Answer - Does JetBrains Copilot support agent spawning via a tool equivalent to `task` or `runSubagent`? -- Can agents access workspace files and `.ai-team/` directories? +- Can agents access workspace files and `.squad/` directories? - What model selection mechanisms exist? - Is there a background/async mode? @@ -179,7 +179,7 @@ Squad runs on VS Code with **conditional support**. Key differences from CLI: ### Questions to Answer - Can GitHub Copilot spawn agents for background work? -- Can agents read `.ai-team/` files from the repository? +- Can agents read `.squad/` files from the repository? - Is there a GitHub-specific command protocol for delegation? --- @@ -203,7 +203,7 @@ Squad runs on VS Code with **conditional support**. Key differences from CLI: **Using Both:** - CLI is recommended for initial Squad setup and learning - VS Code works for day-to-day development once Squad is established -- They share the same `.ai-team/` state — both can read/write the same team files +- They share the same `.squad/` state — both can read/write the same team files - Team state is portable — init in CLI, use in VS Code, export/import across repos ### For Squad Developers @@ -252,7 +252,7 @@ This document is based on active research spikes (#32, #33, #34) conducted in Fe - **Proposal 032a** (Strausz): `runSubagent` API research — agent spawning mechanics on VS Code - **Proposal 032b** (Kujan): CLI spawn parity analysis — all 5 Squad spawn patterns mapped -- **Proposal 033a** (Strausz): VS Code file discovery — `.ai-team/` access and workspace scoping +- **Proposal 033a** (Strausz): VS Code file discovery — `.squad/` access and workspace scoping - **Proposal 034a** (Kujan): Model selection & background mode — per-agent model routing and async execution **Next steps:** diff --git a/docs/src/content/docs/scenarios/disaster-recovery.md b/docs/src/content/docs/scenarios/disaster-recovery.md index 320c7b6c8..53af31e39 100644 --- a/docs/src/content/docs/scenarios/disaster-recovery.md +++ b/docs/src/content/docs/scenarios/disaster-recovery.md @@ -2,7 +2,7 @@ **Try this to recover from data loss:** ``` -My .ai-team/ directory was deleted — help me recover the team state +My .squad/ directory was deleted — help me recover the team state ``` **Try this to revert bad code:** @@ -15,33 +15,33 @@ An agent wrote bad code — how do I revert it? The squad is confused — reset their context ``` -Recovery procedures for deleted `.ai-team/`, bad agent code, confused squads, and upgrade issues. Most problems are fixable with Git or re-init. +Recovery procedures for deleted `.squad/`, bad agent code, confused squads, and upgrade issues. Most problems are fixable with Git or re-init. --- -## 1. "I accidentally deleted `.ai-team/`" +## 1. "I accidentally deleted `.squad/`" -Recovery scenarios: deleted `.ai-team/`, bad agent code, confused squad, upgrade issues. +Recovery scenarios: deleted `.squad/`, bad agent code, confused squad, upgrade issues. **Solution:** It's in Git. Restore it. ```bash -git checkout .ai-team/ +git checkout .squad/ ``` -If you haven't committed `.ai-team/` yet, it's gone. Rebuild: +If you haven't committed `.squad/` yet, it's gone. Rebuild: ```bash -npx github:bradygaster/squad +npx @bradygaster/squad-cli ``` Start from scratch. If you exported your squad before, import the export: ```bash -npx github:bradygaster/squad import squad-export-2025-07-15.zip +npx @bradygaster/squad-cli import squad-export-2025-07-15.zip ``` -**Prevention:** Commit `.ai-team/` early. Don't let it stay uncommitted for long. +**Prevention:** Commit `.squad/` early. Don't let it stay uncommitted for long. --- @@ -85,7 +85,7 @@ Sonny reads the code, fixes the issue, commits. ## 3. "An agent made a wrong decision" -**What happened:** Neo decided to use REST when GraphQL was the better choice. The decision is logged in `.ai-team/decisions.md`. +**What happened:** Neo decided to use REST when GraphQL was the better choice. The decision is logged in `.squad/decisions.md`. **Solution:** Add a directive to override it. @@ -125,7 +125,7 @@ Agents now read the new decision and build accordingly. ``` 📋 Scribe — archiving recent session histories -Moved to .ai-team/history-archive/: +Moved to .squad/history-archive/: - Neo's session from 2025-07-14 - Morpheus's session from 2025-07-14 - Trinity's session from 2025-07-14 @@ -141,11 +141,11 @@ Agents **forget** the bad session. They still have their long-term skills and de ## 5. "I want to start over completely" -**Solution:** Delete `.ai-team/` and reinstall. +**Solution:** Delete `.squad/` and reinstall. ```bash -rm -rf .ai-team/ -npx github:bradygaster/squad +rm -rf .squad/ +npx @bradygaster/squad-cli ``` ``` @@ -162,11 +162,11 @@ You're back to day one. Clean slate. **What happened:** You upgraded Squad to a new version, and now something doesn't work. -**Solution:** Squad upgrades **never touch** `.ai-team/`. The issue is likely in: +**Solution:** Squad upgrades **never touch** `.squad/`. The issue is likely in: -1. **Workflow templates** — check `.ai-team-templates/` +1. **Workflow templates** — check `.squad-templates/` 2. **Squad agent definition** — check `.github/agents/squad.agent.md` -3. **Model configuration** — check `.ai-team/model-config.json` +3. **Model configuration** — check `.squad/model-config.json` Roll back the Squad agent definition: @@ -177,10 +177,10 @@ git checkout HEAD^ .github/agents/squad.agent.md Or reinstall the previous version: ```bash -npx github:bradygaster/squad@0.1.5 +npx @bradygaster/squad-cli@0.1.5 ``` -**Your team's knowledge is safe.** `.ai-team/` is untouched. +**Your team's knowledge is safe.** `.squad/` is untouched. **Prevention:** Check the CHANGELOG before upgrading. If the upgrade is major, test in a branch first. @@ -211,17 +211,17 @@ Or just close the Copilot session (Ctrl+C) and start a new one. ## 8. "Skills are outdated or wrong" -**What happened:** A skill file in `.ai-team/skills/` contains outdated information. Agents are following bad advice. +**What happened:** A skill file in `.squad/skills/` contains outdated information. Agents are following bad advice. **Solution:** Edit or delete the skill file. ```bash # Edit the skill -code .ai-team/skills/auth-rate-limiting.md +code .squad/skills/auth-rate-limiting.md # Or delete it -rm .ai-team/skills/auth-rate-limiting.md -git add .ai-team/skills/ +rm .squad/skills/auth-rate-limiting.md +git add .squad/skills/ git commit -m "Remove outdated auth rate limiting skill" ``` @@ -231,13 +231,13 @@ git commit -m "Remove outdated auth rate limiting skill" ## 9. "Decisions.md is a mess" -**What happened:** `.ai-team/decisions.md` has 200 entries and it's hard to find anything. +**What happened:** `.squad/decisions.md` has 200 entries and it's hard to find anything. **Solution:** Archive old decisions. ``` > Scribe, archive decisions older than 3 months. Move them to -> .ai-team/decisions-archive.md. +> .squad/decisions-archive.md. ``` ``` @@ -284,10 +284,10 @@ Each agent logs what they did in their `history.md`. ## Tips -- **`.ai-team/` is in Git.** If you delete it, restore from Git. If it's uncommitted, it's gone. +- **`.squad/` is in Git.** If you delete it, restore from Git. If it's uncommitted, it's gone. - **Code review catches bad agent code.** Use the Lead to review before merging. - **Override bad decisions with directives.** If an agent made the wrong call, tell the team the correct one. - **Archive confused histories.** If a session went badly, archive the learnings so agents forget. -- **Upgrades don't touch `.ai-team/`.** Your team's knowledge is safe across upgrades. +- **Upgrades don't touch `.squad/`.** Your team's knowledge is safe across upgrades. - **Edit skill files directly.** They're just markdown. If a skill is wrong, fix it or delete it. - **Agent histories are the audit log.** Check them to see what each agent did. diff --git a/docs/src/content/docs/scenarios/keep-my-squad.md b/docs/src/content/docs/scenarios/keep-my-squad.md index ca98ac408..61651284c 100644 --- a/docs/src/content/docs/scenarios/keep-my-squad.md +++ b/docs/src/content/docs/scenarios/keep-my-squad.md @@ -25,12 +25,12 @@ Squad persistence and portability. Your squad remembers skills, casting, and kno After working on a project for a few weeks, your squad has learned: -- **Skills** — patterns, conventions, best practices (23 skill files in `.ai-team/skills/`) -- **Decisions** — architectural choices, why you picked X over Y (`.ai-team/decisions.md`) -- **Histories** — project-specific context each agent accumulated (`.ai-team/agents/{name}/history.md`) -- **Casting state** — the chosen agent names, roles, universe (`.ai-team/casting-state.json`) +- **Skills** — patterns, conventions, best practices (23 skill files in `.squad/skills/`) +- **Decisions** — architectural choices, why you picked X over Y (`.squad/decisions.md`) +- **Histories** — project-specific context each agent accumulated (`.squad/agents/{name}/history.md`) +- **Casting state** — the chosen agent names, roles, universe (`.squad/casting-state.json`) -All of this lives in `.ai-team/`. Commit it, and anyone who clones your repo gets the full team. +All of this lives in `.squad/`. Commit it, and anyone who clones your repo gets the full team. --- @@ -40,7 +40,7 @@ When you finish a project or want to take your squad to a new one: ```bash cd ~/projects/finished-saas-app -npx github:bradygaster/squad export +npx @bradygaster/squad-cli export ``` ``` @@ -69,7 +69,7 @@ Start a new project: mkdir ~/projects/new-mobile-app cd ~/projects/new-mobile-app git init -npx github:bradygaster/squad +npx @bradygaster/squad-cli ``` When Squad asks what you're building: @@ -133,29 +133,29 @@ This is intentional. Skills are **reusable**. Project details are **not**. --- -## 5. Version Upgrades Don't Touch `.ai-team/` +## 5. Version Upgrades Don't Touch `.squad/` When Squad releases a new version: ```bash -npx github:bradygaster/squad@latest +npx @bradygaster/squad-cli@latest ``` ``` 🔄 Upgrading Squad from v0.1.5 to v0.2.0 ✅ .github/agents/squad.agent.md (updated to v0.2.0) -✅ .ai-team-templates/ (new workflow templates) +✅ .squad-templates/ (new workflow templates) ✅ .gitattributes (merge=union rules verified) -⚠️ Your .ai-team/ directory was NOT modified. +⚠️ Your .squad/ directory was NOT modified. Your team's memory, skills, and decisions are untouched. ``` Upgrades only change: - The Squad agent definition (`.github/agents/squad.agent.md`) -- Workflow templates (`.ai-team-templates/`) +- Workflow templates (`.squad-templates/`) - The installer itself Your **team's knowledge is safe**. @@ -164,10 +164,10 @@ Your **team's knowledge is safe**. ## 6. Git Commit Means Everyone Gets the Team -You commit `.ai-team/`: +You commit `.squad/`: ```bash -git add .ai-team/ +git add .squad/ git commit -m "Add Squad team with 3 weeks of accumulated knowledge" git push ``` diff --git a/docs/src/content/docs/scenarios/large-codebase.md b/docs/src/content/docs/scenarios/large-codebase.md index 4eb0d4ea5..02c3eef00 100644 --- a/docs/src/content/docs/scenarios/large-codebase.md +++ b/docs/src/content/docs/scenarios/large-codebase.md @@ -54,7 +54,7 @@ Your **codebase size doesn't matter** — agents aren't loading all 500K lines. ## 3. Routing Directs Work to the Right Agent -Routing rules in `.ai-team/routing.md` keep agents focused: +Routing rules in `.squad/routing.md` keep agents focused: ```markdown # Routing Rules @@ -94,12 +94,12 @@ After 10 sessions, agent histories can grow large. The Scribe **archives old lea ``` 📋 Scribe — archiving agent histories -Old learnings moved to .ai-team/history-archive/: +Old learnings moved to .squad/history-archive/: - Neo's session logs from June - Trinity's session logs from July Current histories now cover the last 3 sessions only. -Skills extracted from old sessions remain in .ai-team/skills/. +Skills extracted from old sessions remain in .squad/skills/. ``` Agents don't forget — they just move old details to the archive. **Generic knowledge becomes skills**, and **specific session logs are archived**. @@ -110,7 +110,7 @@ Agents don't forget — they just move old details to the archive. **Generic kno After an agent solves a problem, it writes a skill file: -`.ai-team/skills/stripe-webhook-verification.md`: +`.squad/skills/stripe-webhook-verification.md`: ```markdown # Stripe Webhook Verification @@ -124,7 +124,7 @@ const event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret); Next time **any agent** handles Stripe webhooks, they read this skill first. No rediscovery. No re-exploration. -Over time, your `.ai-team/skills/` directory becomes a **compressed knowledge base** — 50 skill files instead of 10,000 lines of history. +Over time, your `.squad/skills/` directory becomes a **compressed knowledge base** — 50 skill files instead of 10,000 lines of history. --- @@ -146,7 +146,7 @@ Agents will focus on: payment-service/package.json ``` -Or route by service in `.ai-team/routing.md`: +Or route by service in `.squad/routing.md`: ```markdown **Payment service work** → Morpheus diff --git a/docs/src/content/docs/scenarios/mid-project.md b/docs/src/content/docs/scenarios/mid-project.md index 436e3bbaa..edac25acc 100644 --- a/docs/src/content/docs/scenarios/mid-project.md +++ b/docs/src/content/docs/scenarios/mid-project.md @@ -28,14 +28,14 @@ You don't have to start from scratch. You don't have to rewrite anything. Instal ```bash cd ~/projects/halfway-done-app -npx github:bradygaster/squad +npx @bradygaster/squad-cli ``` ``` ✅ .github/agents/squad.agent.md (v0.2.0) -✅ .ai-team-templates/ -✅ .ai-team/skills/ (starter skills) -✅ .ai-team/ceremonies.md +✅ .squad-templates/ +✅ .squad/skills/ (starter skills) +✅ .squad/ceremonies.md ✅ .gitattributes (merge=union rules) Squad is ready. diff --git a/docs/src/content/docs/scenarios/multiple-squads.md b/docs/src/content/docs/scenarios/multiple-squads.md index cd47e6c4d..eb36836b5 100644 --- a/docs/src/content/docs/scenarios/multiple-squads.md +++ b/docs/src/content/docs/scenarios/multiple-squads.md @@ -32,7 +32,7 @@ In each repo with a trained squad: ```bash cd ~/projects/saas-app -npx github:bradygaster/squad export +npx @bradygaster/squad-cli export ``` ``` @@ -51,11 +51,11 @@ Repeat for your other repos: ```bash cd ~/projects/mobile-app -npx github:bradygaster/squad export +npx @bradygaster/squad-cli export # Produces: squad-export-2025-07-15-1.zip cd ~/projects/api-gateway -npx github:bradygaster/squad export +npx @bradygaster/squad-cli export # Produces: squad-export-2025-07-15-2.zip ``` @@ -70,7 +70,7 @@ Pick the squad whose domain knowledge is closest to your new project. ```bash cd ~/projects/new-platform git init -npx github:bradygaster/squad +npx @bradygaster/squad-cli ``` ``` @@ -99,8 +99,8 @@ Extract the other two exports and copy skill files: unzip squad-export-mobile-app.zip -d /tmp/mobile-squad # Copy specific skills you want -cp /tmp/mobile-squad/.ai-team/skills/react-native-debugging.md .ai-team/skills/ -cp /tmp/mobile-squad/.ai-team/skills/mobile-testing-patterns.md .ai-team/skills/ +cp /tmp/mobile-squad/.squad/skills/react-native-debugging.md .squad/skills/ +cp /tmp/mobile-squad/.squad/skills/mobile-testing-patterns.md .squad/skills/ ``` Repeat for the API gateway squad: @@ -108,8 +108,8 @@ Repeat for the API gateway squad: ```bash unzip squad-export-api-gateway.zip -d /tmp/gateway-squad -cp /tmp/gateway-squad/.ai-team/skills/rate-limiting-patterns.md .ai-team/skills/ -cp /tmp/gateway-squad/.ai-team/skills/auth-middleware-testing.md .ai-team/skills/ +cp /tmp/gateway-squad/.squad/skills/rate-limiting-patterns.md .squad/skills/ +cp /tmp/gateway-squad/.squad/skills/auth-middleware-testing.md .squad/skills/ ``` Skills are standalone markdown files. Agents load them automatically. @@ -120,7 +120,7 @@ Skills are standalone markdown files. Agents load them automatically. If another squad learned something critical that isn't in a skill file, you can manually append it to an agent's history. -Open `.ai-team/agents/{agent-name}/history.md` and add the knowledge as a session entry: +Open `.squad/agents/{agent-name}/history.md` and add the knowledge as a session entry: ```markdown ## Session: 2025-07-15 @@ -160,7 +160,7 @@ Agents now know they have hybrid knowledge. If you want to **replace** your imported squad with a different one: ```bash -npx github:bradygaster/squad import squad-export-mobile-app.zip --force +npx @bradygaster/squad-cli import squad-export-mobile-app.zip --force ``` This **overwrites** the existing squad. Use only if you're sure. @@ -172,5 +172,5 @@ This **overwrites** the existing squad. Use only if you're sure. - **One full import, then cherry-pick.** Import the squad with the closest domain match, then manually copy skills from the others. - **Skills are modular.** Each skill file is independent. Copy the ones you need, ignore the rest. - **Histories are context-heavy.** Don't import histories from unrelated projects — they contain project-specific details that will confuse agents. -- **Decisions can be manually merged.** If another squad made architectural decisions you want to preserve, copy them into `.ai-team/decisions.md` as new entries. +- **Decisions can be manually merged.** If another squad made architectural decisions you want to preserve, copy them into `.squad/decisions.md` as new entries. - **Skill files are the cleanest transfer.** They're generic, portable, and immediately useful across projects. diff --git a/docs/src/content/docs/scenarios/new-project.md b/docs/src/content/docs/scenarios/new-project.md index 34405bf52..4b9caf4f8 100644 --- a/docs/src/content/docs/scenarios/new-project.md +++ b/docs/src/content/docs/scenarios/new-project.md @@ -26,15 +26,15 @@ git init ## 2. Install Squad ```bash -npx github:bradygaster/squad +npx @bradygaster/squad-cli ``` ``` ✅ .github/agents/squad.agent.md (v0.2.0) ✅ .github/workflows/ (10 workflows) -✅ .ai-team-templates/ -✅ .ai-team/skills/ (starter skills) -✅ .ai-team/ceremonies.md +✅ .squad-templates/ +✅ .squad/skills/ (starter skills) +✅ .squad/ceremonies.md ✅ .gitattributes (merge=union rules) Squad is ready. @@ -91,7 +91,7 @@ You can adjust the team or skip straight to work (which is implicit confirmation > Yes. Rusty, set up the Go module and project structure. ``` -Squad creates `.ai-team/` (roster, charters, histories, routing rules, casting state) and spawns Rusty: +Squad creates `.squad/` (roster, charters, histories, routing rules, casting state) and spawns Rusty: ``` 🔧 Rusty — setting up Go module and project structure @@ -152,11 +152,11 @@ Every agent reads these decisions before their next task. As the list grows, the ## 7. Commit Your Team ```bash -git add .ai-team/ .ai-team-templates/ .github/ .gitattributes +git add .squad/ .squad-templates/ .github/ .gitattributes git commit -m "Add Squad team" ``` -Commit `.ai-team/` — it's your team's brain. Anyone who clones the repo gets the full team with all their accumulated knowledge. +Commit `.squad/` — it's your team's brain. Anyone who clones the repo gets the full team with all their accumulated knowledge. --- diff --git a/docs/src/content/docs/scenarios/open-source.md b/docs/src/content/docs/scenarios/open-source.md index b030d5b9c..18b1345d2 100644 --- a/docs/src/content/docs/scenarios/open-source.md +++ b/docs/src/content/docs/scenarios/open-source.md @@ -29,7 +29,7 @@ Squad helps: - **Triage incoming issues** automatically - **Guide contributors** with documented patterns - **Handle good-first-issue tasks** autonomously -- **Keep architecture decisions visible** in `.ai-team/decisions.md` +- **Keep architecture decisions visible** in `.squad/decisions.md` --- @@ -37,13 +37,13 @@ Squad helps: ```bash cd ~/projects/my-open-source-lib -npx github:bradygaster/squad +npx @bradygaster/squad-cli ``` Enable the Ralph heartbeat workflow: ```bash -cp .ai-team-templates/squad-heartbeat.yml .github/workflows/ +cp .squad-templates/squad-heartbeat.yml .github/workflows/ git add .github/workflows/squad-heartbeat.yml git commit -m "Enable Squad auto-triage" git push @@ -89,7 +89,7 @@ You review triaged issues and add `go:morpheus` if you approve. Enable the auto-assign workflow: ```bash -cp .ai-team-templates/copilot-auto-assign.yml .github/workflows/ +cp .squad-templates/copilot-auto-assign.yml .github/workflows/ git add .github/workflows/copilot-auto-assign.yml git commit -m "Enable Squad auto-assign" git push @@ -111,9 +111,9 @@ You review PR #145, approve, merge. Issue #144 closed. ## 5. Skills Document Your Project's Patterns -After Squad works on your project for a few weeks, `.ai-team/skills/` becomes a **living contributor guide**: +After Squad works on your project for a few weeks, `.squad/skills/` becomes a **living contributor guide**: -`.ai-team/skills/testing-conventions.md`: +`.squad/skills/testing-conventions.md`: ```markdown # Testing Conventions @@ -127,7 +127,7 @@ Mock external dependencies with `jest.mock()` Contributors can **read this file** to understand your testing norms. No need to repeat it in every PR review. -`.ai-team/skills/api-design-patterns.md`: +`.squad/skills/api-design-patterns.md`: ```markdown # API Design Patterns @@ -153,7 +153,7 @@ Use HTTP status codes correctly: ## 6. Decisions.md is Your Architecture Decision Record (ADR) -`.ai-team/decisions.md` becomes your **public ADR**: +`.squad/decisions.md` becomes your **public ADR**: ```markdown ### 2025-07-10: Use esbuild instead of Webpack @@ -182,7 +182,7 @@ Contributors see **why you made decisions**, not just what the code does. When someone forks your project, they can **import your squad**: ```bash -npx github:bradygaster/squad export +npx @bradygaster/squad-cli export ``` Share `squad-export-{date}.zip` in your repo's releases or documentation. @@ -192,7 +192,7 @@ Forkers import it: ```bash git clone https://github.com/forker/my-lib-fork.git cd my-lib-fork -npx github:bradygaster/squad import squad-export-2025-07-15.zip +npx @bradygaster/squad-cli import squad-export-2025-07-15.zip ``` Now they have **your team's knowledge** — skills, decisions, conventions. They're not starting from scratch. @@ -257,9 +257,9 @@ Add a badge to your README: This project uses [Squad](https://github.com/bradygaster/squad) for AI-assisted development. - **Triaging:** Issues are auto-labeled by Squad's Ralph agent -- **Patterns:** See `.ai-team/skills/` for coding conventions -- **Decisions:** See `.ai-team/decisions.md` for architectural rationale -- **Import the squad:** `npx github:bradygaster/squad import squad-export.zip` +- **Patterns:** See `.squad/skills/` for coding conventions +- **Decisions:** See `.squad/decisions.md` for architectural rationale +- **Import the squad:** `npx @bradygaster/squad-cli import squad-export.zip` ``` Contributors know what to expect. @@ -269,7 +269,7 @@ Contributors know what to expect. ## Tips - **Ralph triages issues for you.** Run the heartbeat workflow every 6 hours to auto-label new issues. -- **Skills are living contributor docs.** As your squad learns, `.ai-team/skills/` becomes a knowledge base contributors can read. +- **Skills are living contributor docs.** As your squad learns, `.squad/skills/` becomes a knowledge base contributors can read. - **Decisions.md is your ADR.** Architectural decisions are visible and explained, not hidden in Git history. - **Export your squad for forks.** Forkers get your team's accumulated knowledge — skills, conventions, decisions. - **good-first-issue + go:* = autonomous processing.** Mark issues as safe to auto-process, and Squad handles them. diff --git a/docs/src/content/docs/scenarios/private-repos.md b/docs/src/content/docs/scenarios/private-repos.md index 243560631..e6f7627d7 100644 --- a/docs/src/content/docs/scenarios/private-repos.md +++ b/docs/src/content/docs/scenarios/private-repos.md @@ -40,12 +40,12 @@ And select **Squad** from the `/agent` list (CLI) or `/agents` (VS Code), Squad --- -## 2. What's Stored in `.ai-team/` +## 2. What's Stored in `.squad/` -Squad writes everything to `.ai-team/` in your repository: +Squad writes everything to `.squad/` in your repository: ``` -.ai-team/ +.squad/ ├── team.md # Roster (agent names, roles) ├── routing.md # Work routing rules ├── decisions.md # Architectural decisions @@ -64,7 +64,7 @@ Squad writes everything to `.ai-team/` in your repository: **You control what's committed.** If you don't want agent histories in your repo, add them to `.gitignore`: ```gitignore -.ai-team/agents/*/history.md +.squad/agents/*/history.md ``` Now histories stay local. Charters, skills, and decisions are still committed. @@ -90,9 +90,9 @@ This is **project-specific knowledge**. If your repo is private and you want to ## 4. Skills Are Generic — Safe to Share -Skill files in `.ai-team/skills/` are **intentionally generic**: +Skill files in `.squad/skills/` are **intentionally generic**: -`.ai-team/skills/auth-rate-limiting.md`: +`.squad/skills/auth-rate-limiting.md`: ```markdown # Authentication Endpoints Must Be Rate-Limited @@ -115,7 +115,7 @@ No project-specific details. No code references. No file paths. When you run: ```bash -npx github:bradygaster/squad export +npx @bradygaster/squad-cli export ``` The export includes: @@ -166,12 +166,12 @@ Squad is **entirely local**. It's a GitHub Copilot agent, not a standalone servi If your repository is private and you're security-conscious: -- [ ] **Review `.ai-team/agents/*/history.md`** — make sure no secrets or sensitive details are logged +- [ ] **Review `.squad/agents/*/history.md`** — make sure no secrets or sensitive details are logged - [ ] **Add `history.md` to `.gitignore`** if you don't want histories committed - [ ] **Review exports before sharing** — check `squad-export-*.zip` for project-specific details -- [ ] **Audit `.ai-team/decisions.md`** — remove any decisions that reference internal systems or secrets +- [ ] **Audit `.squad/decisions.md`** — remove any decisions that reference internal systems or secrets - [ ] **Use GitHub token permissions wisely** — don't give Actions more permissions than needed -- [ ] **Skills are public-safe** — feel free to share `.ai-team/skills/` publicly +- [ ] **Skills are public-safe** — feel free to share `.squad/skills/` publicly --- @@ -194,7 +194,7 @@ If your repository is private and you're security-conscious: **Exclude histories from Git:** ``` -> Add .ai-team/agents/*/history.md to .gitignore. I don't want +> Add .squad/agents/*/history.md to .gitignore. I don't want > agent histories committed. ``` diff --git a/docs/src/content/docs/scenarios/release-process.md b/docs/src/content/docs/scenarios/release-process.md index 9674a6ada..22861b233 100644 --- a/docs/src/content/docs/scenarios/release-process.md +++ b/docs/src/content/docs/scenarios/release-process.md @@ -31,9 +31,9 @@ Complete step-by-step guide for Squad maintainers: three-branch model (dev/previ | 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) | +| **dev** | Development — all work happens here | All team members | ❌ No | Everything (`.squad/`, team-docs, etc.) | +| **preview** | Staging/testing — validated product only | Release coordinator | ✅ Yes | Distribution files only (`.squad/` blocked) | +| **main** | Production — release source for `npx` | Release coordinator | ✅ Yes | Distribution files only (`.squad/` blocked) | --- @@ -53,7 +53,7 @@ git reset --hard dev Remove forbidden paths: ```bash -git rm --cached -r .ai-team/ +git rm --cached -r .squad/ git rm --cached -r team-docs/ ``` @@ -244,7 +244,7 @@ Use `.gitignore` rules and verify `git status` before pushing: ```bash git status -git rm --cached -r .ai-team/ +git rm --cached -r .squad/ git commit -m "chore: remove runtime state files" git push ``` @@ -266,15 +266,15 @@ ssh -T git@github.com --- -### Issue: .ai-team/ Files Keep Getting Committed +### Issue: .squad/ Files Keep Getting Committed **Fix:** ```bash -git rm --cached -r .ai-team/ -grep ".ai-team" .gitignore || echo ".ai-team/" >> .gitignore +git rm --cached -r .squad/ +grep ".ai-team" .gitignore || echo ".squad/" >> .gitignore git add .gitignore -git commit -m "chore: ensure .ai-team/ is untracked" +git commit -m "chore: ensure .squad/ is untracked" git push origin dev ``` @@ -285,7 +285,7 @@ git push origin dev **Fix:** ```bash -npx github:bradygaster/squad upgrade +npx @bradygaster/squad-cli upgrade git add .github/workflows/ git commit -m "chore: restore Squad workflows" git push origin dev @@ -336,13 +336,13 @@ Kobayashi, create a chore/sync-from-main branch, merge main into it, create and ### To Test the Guard ``` -Kobayashi, test the guard workflow by creating a test branch with .ai-team/ content, creating a PR to main (should fail), removing the file (should pass), and cleaning up +Kobayashi, test the guard workflow by creating a test branch with .squad/ content, creating a PR to main (should fail), removing the file (should pass), and cleaning up ``` ### To Fix a Blocked PR ``` -Kobayashi, fetch the current PR state, remove all .ai-team/ and team-docs/ files, commit, push to update the PR, and wait for guard to pass +Kobayashi, fetch the current PR state, remove all .squad/ and team-docs/ files, commit, push to update the PR, and wait for guard to pass ``` --- diff --git a/docs/src/content/docs/scenarios/team-portability.md b/docs/src/content/docs/scenarios/team-portability.md index 5257ed599..5bf7623df 100644 --- a/docs/src/content/docs/scenarios/team-portability.md +++ b/docs/src/content/docs/scenarios/team-portability.md @@ -22,7 +22,7 @@ In the repo where your team currently lives: ```bash cd ~/projects/project-alpha -npx github:bradygaster/squad export +npx @bradygaster/squad-cli export ``` ``` @@ -35,7 +35,7 @@ This creates `squad-export.json` — a portable snapshot containing agents, cast You can also specify a custom output path: ```bash -npx github:bradygaster/squad export --out ~/exports/alpha-team.json +npx @bradygaster/squad-cli export --out ~/exports/alpha-team.json ``` --- @@ -46,7 +46,7 @@ The target repo needs Squad installed before importing: ```bash cd ~/projects/project-beta -npx github:bradygaster/squad +npx @bradygaster/squad-cli ``` ``` @@ -64,7 +64,7 @@ Squad is ready. ## 3. Import the Team ```bash -npx github:bradygaster/squad import ~/projects/project-alpha/squad-export.json +npx @bradygaster/squad-cli import ~/projects/project-alpha/squad-export.json ``` ``` @@ -87,7 +87,7 @@ Next steps: If `.ai-team/` already exists (e.g., this repo already had a team), import will fail: ```bash -npx github:bradygaster/squad import squad-export.json +npx @bradygaster/squad-cli import squad-export.json ``` ``` @@ -97,7 +97,7 @@ npx github:bradygaster/squad import squad-export.json Use `--force` to archive the existing team and replace it: ```bash -npx github:bradygaster/squad import squad-export.json --force +npx @bradygaster/squad-cli import squad-export.json --force ``` The existing `.ai-team/` is moved to `.ai-team-archive-2025-07-15-14-30-00/`. Nothing is deleted. diff --git a/docs/src/content/docs/scenarios/troubleshooting.md b/docs/src/content/docs/scenarios/troubleshooting.md index e7bee1c76..a0036ac74 100644 --- a/docs/src/content/docs/scenarios/troubleshooting.md +++ b/docs/src/content/docs/scenarios/troubleshooting.md @@ -16,7 +16,7 @@ Common issues and fixes for Squad installation and usage. --- -## `npx github:bradygaster/squad` appears to hang +## `npx @bradygaster/squad-cli` appears to hang **Problem:** Running the install command shows a frozen npm spinner. Nothing happens. @@ -29,7 +29,7 @@ Common issues and fixes for Squad installation and usage. eval "$(ssh-agent -s)" ssh-add ``` - Then re-run `npx github:bradygaster/squad`. + Then re-run `npx @bradygaster/squad-cli`. 2. **Disable npm's progress spinner** to reveal the prompt: ```bash @@ -94,7 +94,7 @@ See [Cross-organization authentication](./cross-org-auth) for detailed setup ins ## Node.js version too old -**Problem:** `npx github:bradygaster/squad` fails with an engine compatibility error, or Squad behaves unexpectedly. +**Problem:** `npx @bradygaster/squad-cli` fails with an engine compatibility error, or Squad behaves unexpectedly. **Cause:** Squad requires Node.js 20.0.0 or later (LTS), enforced via `engines` in `package.json`. @@ -123,7 +123,7 @@ If below v20, upgrade to the latest LTS: ```bash ls .github/agents/squad.agent.md ``` - If missing, re-run `npx github:bradygaster/squad`. + If missing, re-run `npx @bradygaster/squad-cli`. 2. Restart your Copilot session — close and reopen the terminal or editor. @@ -131,7 +131,7 @@ If below v20, upgrade to the latest LTS: ## Upgrade doesn't change anything -**Problem:** Running `npx github:bradygaster/squad upgrade` completes but nothing changes. +**Problem:** Running `npx @bradygaster/squad-cli upgrade` completes but nothing changes. **Cause:** You may already be on the latest version, or npm cached an old version. diff --git a/docs/src/content/docs/whatsnew.md b/docs/src/content/docs/whatsnew.md index 52155a152..22a4e4375 100644 --- a/docs/src/content/docs/whatsnew.md +++ b/docs/src/content/docs/whatsnew.md @@ -7,7 +7,7 @@ Full release history for Squad — from beta through the v1 TypeScript replatfor --- -## v0.8.2 — Current Release +## v0.8.25 — Current Release - **Version alignment** — CLI (0.8.1) and SDK (0.8.0) snapped to 0.8.2 across all packages - **Published to npm** — `@bradygaster/squad-sdk@0.8.2` and `@bradygaster/squad-cli@0.8.2` diff --git a/docs/src/navigation.ts b/docs/src/navigation.ts index 6b5d2b05a..952b08d8a 100644 --- a/docs/src/navigation.ts +++ b/docs/src/navigation.ts @@ -17,6 +17,7 @@ export const NAV_SECTIONS: NavSection[] = [ { title: 'Quick start', slug: 'get-started/five-minute-start' }, { title: 'Installation', slug: 'get-started/installation' }, { title: 'Choose your path', slug: 'get-started/choosing-your-path' }, + { title: 'Choose your interface', slug: 'get-started/choose-your-interface' }, { title: 'Your First Session', slug: 'get-started/first-session' }, { title: 'Migration Guide', slug: 'get-started/migration' }, ], @@ -25,12 +26,15 @@ export const NAV_SECTIONS: NavSection[] = [ title: 'Guide', dir: 'guide', items: [ - { title: 'Tips & Tricks', slug: 'guide/tips-and-tricks' }, + { title: 'Tips and Tricks', slug: 'guide/tips-and-tricks' }, { title: 'Sample Prompts', slug: 'guide/sample-prompts' }, + { title: 'FAQ', slug: 'guide/faq' }, + { title: 'Build autonomous agent', slug: 'guide/build-autonomous-agent' }, { title: 'Personal Squad', slug: 'guide/personal-squad' }, { title: 'Interactive Shell', slug: 'guide/shell' }, { title: 'Extensibility', slug: 'guide/extensibility' }, { title: 'Building Extensions', slug: 'guide/building-extensions' }, + { title: 'GitHub auth setup', slug: 'guide/github-auth-setup' }, { title: 'Contributing', slug: 'guide/contributing' }, { title: 'Contributors', slug: 'guide/contributors' }, ], @@ -40,16 +44,20 @@ export const NAV_SECTIONS: NavSection[] = [ dir: 'features', items: [ { title: 'Team Setup', slug: 'features/team-setup' }, + { title: 'Built-in roles', slug: 'features/built-in-roles' }, { title: 'Work Routing', slug: 'features/routing' }, { title: 'Model Selection', slug: 'features/model-selection' }, { title: 'Response Modes', slug: 'features/response-modes' }, { title: 'Parallel Execution', slug: 'features/parallel-execution' }, { title: 'Memory', slug: 'features/memory' }, { title: 'Skills', slug: 'features/skills' }, + { title: 'Context hygiene', slug: 'features/context-hygiene' }, { title: 'Directives', slug: 'features/directives' }, { title: 'Ceremonies', slug: 'features/ceremonies' }, + { title: 'Cost tracking', slug: 'features/cost-tracking' }, { title: 'Reviewer Protocol', slug: 'features/reviewer-protocol' }, { title: 'GitHub Issues', slug: 'features/github-issues' }, + { title: 'Issue templates', slug: 'features/issue-templates' }, { title: 'GitLab Issues', slug: 'features/gitlab-issues' }, { title: 'Labels & Triage', slug: 'features/labels' }, { title: 'PRD Mode', slug: 'features/prd-mode' }, @@ -84,6 +92,7 @@ export const NAV_SECTIONS: NavSection[] = [ { title: 'Tools & Hooks', slug: 'reference/tools-and-hooks' }, { title: 'Config', slug: 'reference/config' }, { title: 'Glossary', slug: 'reference/glossary' }, + { title: 'VS Code troubleshooting', slug: 'reference/vscode-troubleshooting' }, ], }, { diff --git a/package.json b/package.json index 7b2b82be9..417e224c0 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "packages/*" ], "scripts": { - "prebuild": "node scripts/bump-build.mjs && node scripts/sync-skill-templates.mjs && node scripts/sync-templates.mjs", + "prebuild": "node scripts/bump-build.mjs && node scripts/sync-skill-templates.mjs && node scripts/sync-templates.mjs && node scripts/sync-whatsnew-version.mjs", "build": "npm run build -w packages/squad-sdk && npm run build -w packages/squad-cli", "sync-templates": "node scripts/sync-templates.mjs", "test": "vitest run", diff --git a/scripts/sync-whatsnew-version.mjs b/scripts/sync-whatsnew-version.mjs new file mode 100644 index 000000000..fc5f8fe0b --- /dev/null +++ b/scripts/sync-whatsnew-version.mjs @@ -0,0 +1,75 @@ +#!/usr/bin/env node +/** + * sync-whatsnew-version.mjs + * + * Keeps the "## v{X} — Current Release" heading in whatsnew.md in sync with + * the version in package.json. Strips any -build.N or other pre-release suffix + * to produce a clean major.minor.patch version string. + * + * Usage: + * node scripts/sync-whatsnew-version.mjs + * + * Safe to run multiple times (idempotent). Writes the file only when changed. + */ + +import { readFileSync, writeFileSync } from 'node:fs'; +import { join, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, '..'); + +const PKG_PATH = join(root, 'package.json'); +const WHATSNEW_PATH = join(root, 'docs', 'src', 'content', 'docs', 'whatsnew.md'); + +const CURRENT_RELEASE_RE = /^## v\d+\.\d+\.\d+[\w.-]* — Current Release$/m; + +function cleanVersion(raw) { + // Strip -build.N, -preview.N, or any other pre-release suffix + return raw.replace(/-.*$/, ''); +} + +let pkg; +try { + pkg = JSON.parse(readFileSync(PKG_PATH, 'utf8')); +} catch (err) { + console.error(`❌ Could not read package.json at ${PKG_PATH}: ${err.message}`); + process.exit(1); +} + +if (typeof pkg.version !== 'string' || !pkg.version) { + console.error(`❌ package.json has no valid version field (got: ${JSON.stringify(pkg.version)})`); + process.exit(1); +} + +const version = cleanVersion(pkg.version); +const expected = `## v${version} — Current Release`; + +let original; +try { + original = readFileSync(WHATSNEW_PATH, 'utf8'); +} catch (err) { + console.error(`❌ Could not read whatsnew.md at ${WHATSNEW_PATH}: ${err.message}`); + process.exit(1); +} + +const match = original.match(CURRENT_RELEASE_RE); + +if (!match) { + console.warn('⚠️ No "## v{version} — Current Release" heading found in whatsnew.md — skipping.'); + process.exit(0); +} + +if (match[0] === expected) { + console.log(`✅ whatsnew.md already reflects v${version} — no change needed.`); + process.exit(0); +} + +const updated = original.replace(CURRENT_RELEASE_RE, expected); +try { + writeFileSync(WHATSNEW_PATH, updated, 'utf8'); +} catch (err) { + console.error(`❌ Could not write whatsnew.md at ${WHATSNEW_PATH}: ${err.message}`); + process.exit(1); +} +console.log(`✏️ Updated whatsnew.md: "${match[0]}" → "${expected}"`); diff --git a/test/docs-build.test.ts b/test/docs-build.test.ts index 2e2595c6d..df765e4d7 100644 --- a/test/docs-build.test.ts +++ b/test/docs-build.test.ts @@ -19,7 +19,7 @@ const EXPECTED_GET_STARTED = ['choose-your-interface', 'first-session', 'install const EXPECTED_GUIDES = ['build-autonomous-agent', 'tips-and-tricks', 'sample-prompts', 'personal-squad', 'contributing', 'contributors', 'shell', 'faq', 'extensibility', 'building-extensions', 'github-auth-setup']; -const EXPECTED_REFERENCE = ['cli', 'sdk', 'config', 'api-reference', 'integration', 'tools-and-hooks', 'glossary']; +const EXPECTED_REFERENCE = ['cli', 'sdk', 'config', 'api-reference', 'integration', 'tools-and-hooks', 'glossary', 'vscode-troubleshooting']; const EXPECTED_SCENARIOS= [ 'aspire-dashboard', @@ -90,6 +90,16 @@ const EXPECTED_FEATURES = [ const EXPECTED_CONCEPTS = ['architecture', 'github-workflow', 'memory-and-knowledge', 'parallel-work', 'portability', 'your-team']; +// Standalone pages at docs root that are intentionally not in any section subdirectory. +// Add new root-level pages here to acknowledge them as intentional. +const STANDALONE_PAGES = [ + 'whatsnew', + 'insider-program', + 'community', + 'sdk-first-mode', + 'tour-gitlab-issues', +]; + // Blog posts are discovered dynamically to avoid breaking tests when posts change const EXPECTED_BLOG = existsSync(BLOG_CONTENT_DIR) ? readdirSync(BLOG_CONTENT_DIR) @@ -375,3 +385,174 @@ describe('Docs Build Script (Astro)', () => { expect(html).toContain('id="search-modal"'); }); }); + +// --- Docs Hygiene Guards (source validation — no build required) --- + +describe('Docs Hygiene Guards', () => { + const ALL_SECTION_DIRS = ['get-started', 'guide', 'features', 'reference', 'scenarios', 'concepts', 'cookbook']; + const NAVIGATION_TS = join(DOCS_DIR, 'src', 'navigation.ts'); + + /** Extract every slug value from navigation.ts by reading it as text. */ + function getNavSlugs(): string[] { + const content = readFile(NAVIGATION_TS); + const matches = content.match(/slug:\s*['"]([^'"]+)['"]/g) || []; + const slugs = matches.map(m => m.replace(/slug:\s*['"]/, '').replace(/['"]$/, '')); + if (slugs.length === 0) { + throw new Error( + 'getNavSlugs() returned 0 slugs — navigation.ts may have changed format. ' + + `Check ${NAVIGATION_TS} and update the slug extraction regex if needed.` + ); + } + return slugs; + } + + /** All .md files in section subdirectories (excludes root-level files and blog). */ + function getSectionFiles(): Array<{ slug: string; filepath: string }> { + const results: Array<{ slug: string; filepath: string }> = []; + for (const section of ALL_SECTION_DIRS) { + const dir = join(DOCS_CONTENT_DIR, section); + if (!existsSync(dir)) continue; + for (const f of readdirSync(dir).filter(f => f.endsWith('.md'))) { + results.push({ slug: `${section}/${f.replace('.md', '')}`, filepath: join(dir, f) }); + } + } + return results; + } + + /** Root-level .md files directly under docs/src/content/docs/. */ + function getRootLevelFiles(): string[] { + return readdirSync(DOCS_CONTENT_DIR).filter(f => f.endsWith('.md')); + } + + /** Every .md file across all docs sections, root level, and blog — for content scanning. */ + function getAllDocsFilesForScanning(): string[] { + const files = getSectionFiles().map(f => f.filepath); + for (const f of getRootLevelFiles()) { + files.push(join(DOCS_CONTENT_DIR, f)); + } + if (existsSync(BLOG_CONTENT_DIR)) { + for (const f of readdirSync(BLOG_CONTENT_DIR).filter(f => f.endsWith('.md'))) { + files.push(join(BLOG_CONTENT_DIR, f)); + } + } + return files; + } + + it('no orphaned pages — every content file appears in navigation.ts or STANDALONE_PAGES', () => { + const navSlugs = getNavSlugs(); + const errors: string[] = []; + + for (const { slug } of getSectionFiles()) { + if (!navSlugs.includes(slug)) { + errors.push( + `"${slug}" is not in navigation.ts or the standalone allowlist. Add it to the nav or to STANDALONE_PAGES if it's intentionally standalone.` + ); + } + } + + for (const f of getRootLevelFiles()) { + const slug = f.replace('.md', ''); + if (!navSlugs.includes(slug) && !STANDALONE_PAGES.includes(slug)) { + errors.push( + `"${f}" is not in navigation.ts or the standalone allowlist. Add it to the nav or to STANDALONE_PAGES if it's intentionally standalone.` + ); + } + } + + expect(errors, errors.join('\n')).toHaveLength(0); + }); + + it('no dead nav links — every navigation.ts slug has a matching .md file on disk', () => { + const navSlugs = getNavSlugs(); + const errors: string[] = []; + + for (const slug of navSlugs) { + const filepath = join(DOCS_CONTENT_DIR, `${slug}.md`); + if (!existsSync(filepath)) { + errors.push( + `Nav entry "${slug}" has no matching content file. Remove it from navigation.ts or create the page.` + ); + } + } + + expect(errors, errors.join('\n')).toHaveLength(0); + }); + + it('no stale root-level legacy files — root .md files must be in STANDALONE_PAGES allowlist', () => { + const rootFiles = getRootLevelFiles(); + const errors: string[] = []; + + for (const f of rootFiles) { + const slug = f.replace('.md', ''); + if (!STANDALONE_PAGES.includes(slug)) { + errors.push( + `"${f}" is a root-level .md file not in STANDALONE_PAGES. Move it to a section directory or delete it.` + ); + } + } + + expect(errors, errors.join('\n')).toHaveLength(0); + }); + + // Files that may reference the deprecated install command as historical "before" + // examples — migration guides and upgrade docs intentionally show old vs. new. + // Blog posts are historical content and are never rewritten. + const LEGACY_INSTALL_ALLOWLIST: string[] = [ + join(DOCS_CONTENT_DIR, 'get-started', 'migration.md'), + join(DOCS_CONTENT_DIR, 'scenarios', 'upgrading.md'), + ]; + + // Files that may reference the legacy .ai-team/ directory name because they + // explain the migration from the old format or document the migration tooling. + // Blog posts are historical content and are never rewritten. + const LEGACY_DIR_ALLOWLIST: string[] = [ + join(DOCS_CONTENT_DIR, 'get-started', 'migration.md'), + join(DOCS_CONTENT_DIR, 'scenarios', 'upgrading.md'), + join(DOCS_CONTENT_DIR, 'scenarios', 'team-portability.md'), + join(DOCS_CONTENT_DIR, 'scenarios', 'switching-models.md'), + join(DOCS_CONTENT_DIR, 'scenarios', 'team-state-storage.md'), + join(DOCS_CONTENT_DIR, 'sdk-first-mode.md'), + join(DOCS_CONTENT_DIR, 'reference', 'cli.md'), + ]; + + it('allowlists contain only files that exist on disk', () => { + const allAllowlistFiles = [...new Set([...LEGACY_INSTALL_ALLOWLIST, ...LEGACY_DIR_ALLOWLIST])]; + const stale = allAllowlistFiles.filter(f => !existsSync(f)); + expect( + stale, + `Allowlist entries no longer exist on disk — remove them:\n${stale.join('\n')}` + ).toHaveLength(0); + }); + + it('no deprecated install commands — "npx github:bradygaster/squad" must not appear in any .md file', () => { + const errors: string[] = []; + + for (const filepath of getAllDocsFilesForScanning()) { + if (LEGACY_INSTALL_ALLOWLIST.includes(filepath)) continue; + if (filepath.startsWith(BLOG_CONTENT_DIR)) continue; + if (readFile(filepath).includes('npx github:bradygaster/squad')) { + errors.push( + `"${filepath}" contains deprecated install command "npx github:bradygaster/squad". Use "npm install -g @bradygaster/squad-cli" instead.` + ); + } + } + + expect(errors, errors.join('\n')).toHaveLength(0); + }); + + it('no deprecated .ai-team/ directory references in any .md file', () => { + const errors: string[] = []; + + for (const filepath of getAllDocsFilesForScanning()) { + if (LEGACY_DIR_ALLOWLIST.includes(filepath)) continue; + if (filepath.startsWith(BLOG_CONTENT_DIR)) continue; + if (readFile(filepath).includes('.ai-team/')) { + errors.push( + `"${filepath}" references deprecated ".ai-team/" directory. Use ".squad/" instead.` + ); + } + } + + expect(errors, errors.join('\n')).toHaveLength(0); + }); +}); diff --git a/test/whatsnew-version-sync.test.ts b/test/whatsnew-version-sync.test.ts new file mode 100644 index 000000000..a8d791b19 --- /dev/null +++ b/test/whatsnew-version-sync.test.ts @@ -0,0 +1,43 @@ +/** + * Validates that the "Current Release" version heading in whatsnew.md + * matches the version declared in package.json (stripped of build suffix). + * + * Fails CI when someone bumps package.json but forgets to update whatsnew.md. + */ + +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { join } from 'node:path'; + +const ROOT = join(import.meta.dirname, '..'); +const PKG_PATH = join(ROOT, 'package.json'); +const WHATSNEW_PATH = join(ROOT, 'docs', 'src', 'content', 'docs', 'whatsnew.md'); + +const CURRENT_RELEASE_RE = /^## v(\d+\.\d+\.\d+[\w.-]*) — Current Release$/m; + +function cleanVersion(raw: string): string { + return raw.replace(/-.*$/, ''); +} + +describe('whatsnew.md version sync', () => { + it('whatsnew.md "Current Release" heading matches package.json version', () => { + const pkg = JSON.parse(readFileSync(PKG_PATH, 'utf8')); + const expectedVersion = cleanVersion(pkg.version as string); + + const content = readFileSync(WHATSNEW_PATH, 'utf8'); + const match = content.match(CURRENT_RELEASE_RE); + + expect( + match, + 'whatsnew.md must contain a "## v{version} — Current Release" heading' + ).not.toBeNull(); + + const actualVersion = cleanVersion(match![1]); + + expect(actualVersion).toBe( + expectedVersion, + `whatsnew.md "Current Release" is v${actualVersion} but package.json is v${expectedVersion}. ` + + `Run: node scripts/sync-whatsnew-version.mjs` + ); + }); +});