diff --git a/.changeset/1454-init-confirmation-roster.md b/.changeset/1454-init-confirmation-roster.md deleted file mode 100644 index 3ce99ad9c..000000000 --- a/.changeset/1454-init-confirmation-roster.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Ensure first-time Squad casting includes the complete proposed roster and universe inside the blocking confirmation prompt, so users can review the team even when preceding assistant output is not displayed. diff --git a/.changeset/bump-otel-sdk-2x.md b/.changeset/bump-otel-sdk-2x.md deleted file mode 100644 index 06d0af4dd..000000000 --- a/.changeset/bump-otel-sdk-2x.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -deps: bump @opentelemetry/sdk-metrics and @opentelemetry/sdk-trace-node from 1.x to 2.8.0 diff --git a/.changeset/bundle-missing-skills-1289-1264.md b/.changeset/bundle-missing-skills-1289-1264.md deleted file mode 100644 index 87d4ad480..000000000 --- a/.changeset/bundle-missing-skills-1289-1264.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Fix #1289, #1264: Bundle missing skills on `squad init` and strip fabricated provenance from tiered-memory SKILL.md - -**Problem** - -Two regressions shipped in v0.10.0 caused several skills to silently never reach users: - -1. **#1289** — `squad-commands` and `squad-version-check` were in `MANIFEST_SKILL_NAMES` (sdk-init.ts) but missing from `packages/squad-sdk/templates/skills/`. The install loop silently skipped them with `if (storage.existsSync(srcSkill))`, so every `squad init` produced an install with these two skills absent. The trigger phrase `squad commands` was a dead no-op for every v0.10.0 user. - -2. **#1264** — `tiered-memory`, `iterative-retrieval`, and `reflect` skill files existed in both templates dirs but were never added to `MANIFEST_SKILL_NAMES`, so they never installed either. Additionally, `tiered-memory/SKILL.md` claimed `confidence: high` and `source: earned (production measurements in tamirdresher/tamresearch1, 34-74KB baseline payloads)` — the referenced repository does not exist and the measurement table at the bottom of the SKILL contained fabricated numbers. The SKILL also referenced `docs/tiered-memory-guide.md`, which does not exist. - -3. The previously-merged cross-squad fix (#1291) updated `cross-squad/SKILL.md` content but never added it to `MANIFEST_SKILL_NAMES`, so it also never installed. - -**Fix** - -- **Source of truth.** Added the 5 missing skill directories to `.squad/skills/` (`squad-commands`, `squad-version-check`, `tiered-memory`, `iterative-retrieval`, `reflect`). The pre-existing `sync-skill-templates.mjs` runs in `prebuild` and propagates them to both `packages/squad-cli/templates/skills/` and `packages/squad-sdk/templates/skills/`. - -- **`MANIFEST_SKILL_NAMES`** grew from 10 → 14 entries: added `tiered-memory`, `iterative-retrieval`, `reflect`, `cross-squad`. - -- **Anti-regression guard.** The install loop in `sdk-init.ts` now collects missing skill source dirs and `throw`s with a clear remediation message (`Run \`node scripts/sync-skill-templates.mjs\``) instead of silently skipping. This is what would have surfaced #1289 at build time instead of in user installs. - -- **Provenance honesty.** `tiered-memory/SKILL.md` rewritten to: - - Frontmatter: `confidence: design (runtime not yet implemented)` + `source: design proposal` - - Added prominent "Status (v0.10.0)" callout linking to #1264 for the runtime gap - - Removed the fabricated `tamirdresher/tamresearch1` measurement table - - Removed reference to non-existent `docs/tiered-memory-guide.md` - - References section now points to real issues (#1264, #686, #600) - -- **Test guard.** New regression test in `test/init.test.ts` (`should install every manifest-curated skill`) asserts every entry in the expected manifest list ends up at `.copilot/skills/{name}/SKILL.md` after `initSquad()`. - -**Out of scope (tracked separately)** - -The tiered-memory runtime (storage scaffolding under `.squad/memory/hot|cold|wiki/`, Scribe promotion logic, spawn-template tier-aware reads) remains tracked in #1264. This change lands the install-time fixes; runtime work follows in a separate PR. - -The comprehensive `cross-squad-communication` plugin from `tamirdresher/squad-skills` is also separate; this change just adds the existing upstream `cross-squad` skill to the manifest so users get the registry-aware version that landed with #1291. diff --git a/.changeset/canary-false-positives.md b/.changeset/canary-false-positives.md deleted file mode 100644 index 61a1da19a..000000000 --- a/.changeset/canary-false-positives.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Fix #1461 canary false-positives: add HEAD canary to coordinator prompt and make the Canary Check three-state + coordinator-scoped so spawned/non-Squad agents no longer false-halt and truncation is positively detected. diff --git a/.changeset/casting-identity-not-state.md b/.changeset/casting-identity-not-state.md deleted file mode 100644 index 569abea80..000000000 --- a/.changeset/casting-identity-not-state.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -docs: clarify in `init.ts` and `.gitattributes` / `.gitignore` generators that `.squad/casting/*` files are authoritative identity (registry + history), NOT mutable two-layer state. They belong on `main`, must be committed, and should NOT receive a `merge=union` driver or be added to `.gitignore`. Pure comment additions — no runtime behavior change. diff --git a/.changeset/cli-upgrade-fixes.md b/.changeset/cli-upgrade-fixes.md deleted file mode 100644 index 159088d0a..000000000 --- a/.changeset/cli-upgrade-fixes.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Fix CLI and upgrade bugs: -- `squad externalize` and `squad internalize` now appear in `squad --help` output (#1050) -- `squad build` writes files to the externalized state directory when applicable (#1048) -- `squad new agent` correctly adds agent definitions to `squad.config.ts` (#1047) -- `squad upgrade` backs up customized `squad.agent.md` before overwriting; supports `--dry-run` (#1052) -- Explicit `@agent` mentions bypass direct-response handler and route to named agent (#1029) -- `state-mcp` server uses lazy initialization to avoid blocking multi-MCP startup (#1353) diff --git a/.changeset/conditional-state-gitignore.md b/.changeset/conditional-state-gitignore.md deleted file mode 100644 index 48b5f0db6..000000000 --- a/.changeset/conditional-state-gitignore.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch -"@bradygaster/squad-cli": patch ---- - -fix: conditional .gitignore entries for two-layer/orphan state backends - -When the state backend is `two-layer` or `orphan`, `squad init` and `squad upgrade` now add `.squad/decisions.md` and `.squad/agents/*/history.md` to `.gitignore` (delimited by `# Squad: state owned by squad-state branch` marker comments). When the backend is switched back to `local`, the marker block is removed so those files become committable again. - -Defense-in-depth complement to the existing pre-commit hook — prevents `git add .`, IDE "stage all", and `git add -A` from silently staging two-layer state into the working tree. diff --git a/.changeset/consolidate-watch-agent-spawn.md b/.changeset/consolidate-watch-agent-spawn.md deleted file mode 100644 index 8e17a3923..000000000 --- a/.changeset/consolidate-watch-agent-spawn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Consolidate the duplicated `buildAgentCommand()`/spawn-with-timeout logic in the `execute` and `wave-dispatch` watch capabilities into the shared `agent-spawn.ts` module (#994). As a side effect, `execute`'s Copilot session spawn now goes through the same Windows `cmd.exe` argument-escaping path (DEP0190) as the rest of the watch capabilities. diff --git a/.changeset/consolidated-0.11.0.md b/.changeset/consolidated-0.11.0.md new file mode 100644 index 000000000..f2524f8dc --- /dev/null +++ b/.changeset/consolidated-0.11.0.md @@ -0,0 +1,107 @@ +--- +"@bradygaster/squad-cli": minor +"@bradygaster/squad-sdk": minor +--- + +## Consolidated changelog — 0.11.0 development cycle + +> 81 changeset fragments consolidated into a single entry to unblock CI. + +### Features + +- Add `squad update-check` — reads the existing self-update cache (`update-check.json`) and reports current/latest vers... +- Fix #1314: ship `ralph-instructions.md` template for `squad watch --execute` +- feat(models): add category-based cost policy wired end-to-end + `squad models refresh` +- feat: add `squad preset install ` for sharing presets via repo URL or local path (#1224) +- feat(platform): add `setAssignee()` to PlatformAdapter so assignee changes route through the platform abstraction (Gi... +- feat(platform): hydrate work-item `body` via `getWorkItem` and route two-pass scan through the adapter +- Add `externalize` and `internalize` to the top-level `squad --help` command list so they are discoverable (#1050). +- Add @copilot team member prompt during `squad init` +- Add reasoning effort support to agent spawning pipeline +- Add `squad registry add/list/remove` for discovery-only peer squads (no inheritance) +- Add sub-session spawn backend for Copilot App integration +- Add **cross-squad-communication** as a built-in skill (companion to cross-squad) + +### Bug Fixes + +- Fix #1289, #1264: Bundle missing skills on `squad init` and strip fabricated provenance from tiered-memory SKILL.md +- Fix #1461 canary false-positives: add HEAD canary to coordinator prompt and make the Canary Check three-state + coord... +- fix: conditional .gitignore entries for two-layer/orphan state backends +- Coordinator template now warns before launching 2+ parallel background agents in a shared worktree: global-scope git ... +- Move bundled skills from `.copilot/skills/` to `.github/skills/` so they're visible to all Copilot surfaces (closes #... +- Fix #1142: `ralph-triage.js` hardcoded `hostname: 'api.github.com'` in its `https.request()` call, so `Squad Heartbea... +- Fix two upgrade-pipeline gaps from #1190: the postinstall ESM patcher now patches every search root instead of stoppi... +- Fix StateBackendStorageAdapter.deleteDir leaving nested keys behind: a single-level list+delete pass missed deeper su... +- Fix #1296: stop writing `squad_state_` to `~/.copilot/mcp-config.json` on every `squad init` / `squad upgrade` +- Fix #1299 (deep): Fact Checker gets the same plumbing as Rai — rich charter at init + state directory + policy template +- Fix #1299: tell the coordinator to roster Fact Checker (and Ralph + Rai explicitly) in the casting flow +- Fix #1305: coordinator must probe for `squad_state` / `memory.*` tools before writing state, and hard-refuse writes w... +- Fix #1396: `squad export` now resolves externalized state. After `squad externalize`, export read the local `.squad/`... +- `squad copilot` and `squad rc` now follow externalized state: roster reads and writes go to the external state dir wh... +- `squad cast` now discovers project agents from the external state dir when state is externalized. `LocalAgentSource` ... +- Pin GitHub Actions references to full-length commit SHAs across the 10 shipped workflow templates (`squad-ci.yml`, `s... +- Fix #1639: `squad watch`'s self-pull capability stashed uncommitted local changes before `git pull --ff-only`, but on... +- Pin the CLI's squad-sdk dependency to the matching package version so published installs cannot keep an older SDK tha... +- Force the CLI's squad-sdk dependency through the repo workspace by using a root file dependency plus an npm override ... +- Fix coordinator inline-dispatch regression: restore always-on dispatch gate in the Squad coordinator template +- fix: update adapter/client.ts for @github/copilot-sdk 1.0.4 API changes +- Fix Windows shell spawn issues and gh auth false-negative +- Add Layer A/B/C dispatch-enforcement governance to coordinator scaffolding and audit hooks +- Fix `squad doctor` so `decisions.md` passes validation when two-layer or orphan state backends store it on the `squad... +- Remove duplicate `cast` entry in `squad -h` output +- Fix `squad externalize`/`internalize` corrupting non-UTF-8 files under `.squad/`. Both commands copied files through ... +- Fix #1222: Auto-scaffold Fact Checker agent during `squad init`, `squad cast`, and `squad upgrade` +- Fix local test-suite failures by aligning personal squad path expectations, stabilizing observer file classification,... +- Fix identity/ state writes and widen squad_decide author validation (#1255, #1256). +- Fix permission handler to use `approve-once` instead of deprecated `approved` kind, aligning with Copilot CLI v1.0.54... +- Fix `squad preset save/apply` to round-trip custom routing configuration. Previously, `routing.md` was not included i... +- fix: release pipeline version pinning (#1203, #1204) +- Fix: strip surrounding quotes from routing.md example phrases in `parseRoutingMarkdown` +- fix(sdk): normalize dotted ToolRegistry names at Copilot external-tool boundary +- fix(sdk): export `addSquadStateGitignoreBlock` / `removeSquadStateGitignoreBlock` from the package root +- Fix `skill(Squad)` discovery — rename disambiguation skill to `squad-help` (supersedes #1297) +- fix: respect SQUAD_HOME in capabilities.ts and comms-teams.ts, implement SQUAD_PERSONAL_DIR env var, fix Windows shel... +- Make `/squad` a real slash command — rename `squad-commands` skill to `squad` with `user-invocable: true` +- Coordinator now recognises "spawn a squad" / "another squad" / "two squads" as Squad-PRODUCT vocabulary +- Fix shellcheck SC2086 in workflow templates: quote `$GITHUB_OUTPUT` redirects +- Fix YAML escaping in skill command apm.yml generation +- Fix #1288: `squad preset apply` now wires team.md, routing.md, and casting state +- Fix #1377 follow-ups: spawn-backend fallback, slot-leak guards, timeouts, prompt sanitization +- Fix cross-building a POSIX standalone bundle from a Windows host. The builder extracted the entire Node.js runtime ar... + +### Dependencies + +- deps: bump @opentelemetry/sdk-metrics and @opentelemetry/sdk-trace-node from 1.x to 2.8.0 +- Fix CLI and upgrade bugs: +- Bump @types/node from ^22.0.0 to ^25.9.3 in cli and sdk packages. Removes a no-longer-needed @ts-expect-error directi... +- chore: upgrade to TypeScript 6 (closes #1325, #1328, #1334) +- Bump vitest from v3 to v4 alongside @vitest/coverage-v8 v4 to resolve peer-dep mismatch. Both packages now align at ^... + +### Chores + +- chore: adapt CLI to ink 7.0.6 +- Rename user-facing Aspire terminology in CLI help text and command output. Aspire is a standalone OTLP dashboard, not... +- Rename `hire` command to `cast` in CLI help and documentation. The `hire` command continues to work as a silent alias... + +### Documentation + +- Fix platform-specific path examples in personal squad docs, JSDoc, and bundled skill templates. + +### Other + +- Ensure first-time Squad casting includes the complete proposed roster and universe inside the blocking confirmation p... +- docs: clarify in `init.ts` and `.gitattributes` / `.gitignore` generators that `.squad/casting/*` files are authorita... +- Consolidate the duplicated `buildAgentCommand()`/spawn-with-timeout logic in the `execute` and `wave-dispatch` watch ... +- Thread a `contextTier` concept end-to-end through the agent spawning pipeline, mirroring `reasoningEffort`. +- `squad init` now defaults to writing `"chat.newSession.defaultMode": "Squad"` into `.vscode/settings.json`, so new VS... +- Assign unique colors to squad member labels from a curated palette using deterministic hashing of slugified agent names. +- Expose memory.* tools (classify, write, search, promote, delete, audit) through the squad_state MCP server so agents ... +- Prefer newest model per series in fallback chains, add GPT-5.6 IDs, fix Ralph free-model wording. +- Harden squad observer change resolution against directory events, symlinks, and filesystem scan errors. +- Migrate OTel Resource API to `resourceFromAttributes` for compatibility with `@opentelemetry/resources` 2.x (replaces... +- Refresh the model catalog to GitHub Copilot CLI-reachable IDs and prune dead fallback IDs. +- Slim squad.agent.md by extracting 3 sections to satellite skills (closes #1308 phase 1) +- docs(casting): make agent name allocation spoiler-aware +- Write an npx-free `squad_state` MCP spec when Squad runs from a standalone bundle. Previously `squad init` and `squad... +- Prefer `squad.exe` over `squad.cmd` when writing the `squad_state` MCP spec from a standalone bundle on Windows. Sinc... +- Sync lockfile for the vscode-jsonrpc 8→9 bump in packages/squad-sdk. v9 adds the missing `exports` field that v8 lack... diff --git a/.changeset/context-tier.md b/.changeset/context-tier.md deleted file mode 100644 index 71f3f3294..000000000 --- a/.changeset/context-tier.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor -"@bradygaster/squad-cli": minor ---- - -Thread a `contextTier` concept end-to-end through the agent spawning pipeline, mirroring `reasoningEffort`. - -Adds the ability to select a model's context window / context tier (Default vs Long-context / 1M) wherever a model and reasoning effort can already be chosen: - -- New `SquadContextTier = "default" | "long_context"` type and optional `SquadSessionConfig.contextTier`. -- Per-model `supportedContextTiers` / `defaultContextTier` in the model catalog so requests validate and clamp against what a model supports (e.g. Opus 4.8 → 264K default / 1M long context, inferred from billing token prices). -- `ModelConfig.defaultContextTier` and `agentContextTierOverrides` config-schema fields, with `readContextTier` / `writeContextTier` / `readAgentContextTierOverrides` / `writeAgentContextTierOverrides` / `resolveContextTier` / `clampContextTier` helpers mirroring the reasoning-effort resolvers (unsupported tier clamps to the model default; unknown treated as default; `auto` sentinel means "not set"). -- Charter `## Model` → `**Context Tier:**` support in the charter compiler. -- `contextTier` threaded through `spawn-backend.ts` (camelCase for task spawns, `context_tier` snake_case for session kickoff) and `fan-out.ts`. -- New `squad config context-tier [] [--agent ] [--clear]` CLI subcommand parallel to `squad config model`. diff --git a/.changeset/docs-platform-path-fixes.md b/.changeset/docs-platform-path-fixes.md deleted file mode 100644 index d2be7342c..000000000 --- a/.changeset/docs-platform-path-fixes.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch -"@bradygaster/squad-cli": patch ---- - -Fix platform-specific path examples in personal squad docs, JSDoc, and bundled skill templates. diff --git a/.changeset/feat-1170-update-check-json.md b/.changeset/feat-1170-update-check-json.md deleted file mode 100644 index 2608be7ee..000000000 --- a/.changeset/feat-1170-update-check-json.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@bradygaster/squad-cli": minor ---- - -Add `squad update-check` — reads the existing self-update cache (`update-check.json`) and reports current/latest version, release channel, and update availability, without replicating OS-specific cache path resolution or TTL-freshness checks in every consumer. - -- `--json` emits structured output for editor extensions, CI scripts, and coordinator instructions. -- `--refresh` bypasses the cache and re-fetches from the npm registry. -- Exit codes: `0` (up to date / no cache yet), `1` (update available), `2` (transport failure during `--refresh`). -- Honors `SQUAD_NO_UPDATE_CHECK=1` — no network call, exits `0` silently. - -Closes #1170. diff --git a/.changeset/feat-1314-ralph-instructions-template.md b/.changeset/feat-1314-ralph-instructions-template.md deleted file mode 100644 index 1ad70d92a..000000000 --- a/.changeset/feat-1314-ralph-instructions-template.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix #1314: ship `ralph-instructions.md` template for `squad watch --execute` - -The `.squad/ralph-instructions.md` escape hatch used by `squad watch --execute` -had no canonical template, no documentation, and was never created by `squad init` -or `squad upgrade`. This left users who discovered the code path inventing their -own format with no contract or safety guidance. - -This patch promotes the escape hatch to a documented feature: - -- Adds `packages/squad-cli/templates/ralph-instructions.md` — a comment-documented - stub that explains the override format, trust implications, and the stable contract - (what CAN vs CANNOT be customized via this file). -- Registers it in `TEMPLATE_MANIFEST` as a user-owned entry - (`overwriteOnUpgrade: false`) so `squad init` and `squad upgrade` install it - without clobbering user customizations. The destination path - (`ralph-instructions.md` under `.squad/`) exactly matches the `existsSync` lookup - in `execute.ts`. -- Adds three regression tests in `init-upgrade-parity.test.ts`: install on init, - non-overwrite on upgrade (preservation), and install-when-missing on upgrade. -- Adds one new test in `watch-capabilities.test.ts` asserting the `existsSync` - path includes the correct `.squad/ralph-instructions.md` segment derived from - `teamRoot`. - -Closes #1314 diff --git a/.changeset/feat-cost-policy-1080.md b/.changeset/feat-cost-policy-1080.md deleted file mode 100644 index 72e65da81..000000000 --- a/.changeset/feat-cost-policy-1080.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor -"@bradygaster/squad-cli": minor ---- - -feat(models): add category-based cost policy wired end-to-end + `squad models refresh` - -Adds an opt-in cost-ceiling policy on GitHub's billing category axis -(`lightweight`/`versatile`/`powerful`), kept deliberately separate from the -existing quality `ModelTier` axis. The policy is fully wired through the agent -lifecycle: an implicit over-ceiling pick is deterministically downgraded, an -explicit override is honored but warned about, and the outcome is surfaced via -the event bus and logs (never swallowed). When no in-ceiling model exists the -policy fails closed and loud. Unknown/out-of-catalog model IDs still pass -through unchanged. - -Also adds `squad models refresh`, a diagnostic that reconciles the committed -seed catalog against live sources — the canonical Copilot models API (optional, -via `gh auth token`) with a graceful auth-free fallback to the public -github/docs pricing YAML — writing results to the gitignored local cache. On -the authenticated happy path it additionally enriches the API-discovered -catalog with pricing (and release status) from the docs YAML, joined by model -id; enrichment is best-effort and fail-open, so a docs fetch/parse failure never -breaks the refresh. - -No hardcoded per-token pricing and no `included`/zero-credit concept; pricing is -diagnostic-only and is not wired into policy enforcement. diff --git a/.changeset/feat-preset-install.md b/.changeset/feat-preset-install.md deleted file mode 100644 index 4c47d0c29..000000000 --- a/.changeset/feat-preset-install.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -"@bradygaster/squad-cli": minor -"@bradygaster/squad-sdk": minor ---- - -feat: add `squad preset install ` for sharing presets via repo URL or local path (#1224) - -Closes #1224. Adds a new subcommand that installs a single preset from a GitHub URL or local path into `$SQUAD_HOME/presets//` — the peer-to-peer preset sharing flow that was missing in v0.10.0. - -### CLI - -```bash -# From a GitHub repo (preset at /preset.json or /presets//) -squad preset install https://github.com/tamir/my-presets#my-awesome-team - -# From a sub-path -squad preset install https://github.com/tamir/my-presets/tree/main/presets/my-awesome-team - -# From SSH URL -squad preset install git@github.com:tamir/my-presets.git#my-awesome-team - -# From a local path -squad preset install ./my-awesome-team - -# Override the installed name -squad preset install https://github.com/tamir/my-presets#my-awesome-team --name corp-team - -# Overwrite an existing preset -squad preset install --force -``` - -After install, the preset is a normal entry in `$SQUAD_HOME/presets/` — `squad preset list`, `squad preset apply `, and `squad init --preset ` all work as today. - -### Why - -The existing `squad preset init --remote` flow is for syncing your *whole* `$SQUAD_HOME` repo across machines (single-user, multi-machine use case). There was no built-in way to install just *one* preset from someone else's repo. Users had to: -1. Manually clone the repo to a temp dir -2. `cp -r /presets/ $SQUAD_HOME/presets/` -3. Then `squad preset apply ` - -…or hijack `SQUAD_HOME` (which collides with their own personal squad config). - -### What it does - -1. Resolves source — GitHub URL → shallow `git clone --depth 1` to a temp dir; local path → use as-is -2. Locates the preset within the source via 3 patterns: - - Source dir contains `preset.json` → single-preset source - - Source dir contains a `presets/` collection → require `--name` (or `#name` fragment) to pick - - Source dir IS the `presets/` dir → require `--name`, or auto-pick if only one preset -3. Validates the preset's `preset.json` manifest (name, agents[]) before any destructive action -4. Verifies `agents/` directory exists -5. Copies `preset.json` (with optional rename) + `agents/` into `$SQUAD_HOME/presets//` -6. Fail-stops if destination exists, unless `--force` is passed -7. Cleans up the temp clone whether install succeeds or fails - -### What's NOT in scope (deferred to follow-ups) - -- `squad preset uninstall` — `rm -rf $SQUAD_HOME/presets/` works for now -- `squad preset update ` to pull a fresh version from origin -- Public preset registry / discovery catalog diff --git a/.changeset/fix-1014-parallel-spawn-warning.md b/.changeset/fix-1014-parallel-spawn-warning.md deleted file mode 100644 index 80ffe2f18..000000000 --- a/.changeset/fix-1014-parallel-spawn-warning.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Coordinator template now warns before launching 2+ parallel background agents in a shared worktree: global-scope git operations (stash/clean/restore) from one agent can silently delete another agent's untracked files. Warn-only — worktree mode remains opt-in. The worktree reference no longer claims shared-worktree concurrency is safe when agents touch different files. diff --git a/.changeset/fix-1126-skills-to-github-skills.md b/.changeset/fix-1126-skills-to-github-skills.md deleted file mode 100644 index e44599011..000000000 --- a/.changeset/fix-1126-skills-to-github-skills.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor -"@bradygaster/squad-cli": minor ---- - -Move bundled skills from `.copilot/skills/` to `.github/skills/` so they're visible to all Copilot surfaces (closes #1126) - -## Symptom (per #1126) - -Squad-bundled skills installed at `.copilot/skills/` are **invisible to every Copilot surface except Squad itself**: -- ❌ GitHub Copilot cloud agent -- ❌ Copilot CLI (outside Squad sessions) -- ❌ VS Code Copilot extension (agent mode) -- ❌ `@copilot` coding agent on issues -- ❌ Any future Copilot surface - -Per the [official Agent Skills docs](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills), [add-skills docs](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/cloud-agent/add-skills), and [VS Code docs](https://code.visualstudio.com/docs/copilot/customization/agent-skills), the canonical **project-level** custom-skills location is `.github/skills/`. `.copilot/skills/` at repo root is not recognized by any Copilot surface — the home-directory equivalent `~/.copilot/skills/` IS recognized for **personal** skills, which is the source of the original mistake. - -## Fix - -1. **`squad init`** writes bundled skills to `.github/skills/{name}/SKILL.md` (was `.copilot/skills/`). -2. **`squad upgrade`** does the same AND auto-migrates legacy `.copilot/skills/{manifest-skill}/` into `.github/skills/{manifest-skill}/` (best-effort, preserves user-added non-manifest skills at `.copilot/skills/`, tombstones the legacy dir when empty). -3. **`TEMPLATE_MANIFEST`** destinations rewritten: all 10 skill entries now target `../.github/skills/` instead of `../.copilot/skills/`. -4. **`ENSURE_DIRECTORIES`** (upgrade.ts) updated so existing squads get `.github/skills/` created on upgrade. -5. **squad.agent.md** narrative updated: 5-path scan order now lists `.github/skills/` as path #2 (Copilot CLI's canonical custom-skills location) and `.copilot/skills/` as path #3 (Legacy install path; `squad upgrade` migrates). Personal scope (`~/.copilot/skills/`) preserved as-is. -6. **All other docs** (`spawn-reference.md`, `README.md`, `squad-commands` skill, `release-process` skill, `build.ts`, SDK type comments) updated to reference `.github/skills/` as the install destination. - -## Migration semantics (`squad upgrade`) - -`migrateLegacyCopilotSkills()` runs **before** `syncAllSkills`: - -| Scenario | Migration action | User-added skills at `.copilot/skills/` | -|---|---|---| -| `.copilot/skills/{manifest-skill}/` exists, `.github/skills/{manifest-skill}/` does NOT | Move legacy → new; remove legacy | Untouched | -| `.copilot/skills/{manifest-skill}/` exists AND `.github/skills/{manifest-skill}/` exists | Tombstone legacy (new wins) | Untouched | -| `.copilot/skills/my-custom-skill/` (NOT in TEMPLATE_MANIFEST) | Left alone | Preserved | -| `.copilot/skills/` becomes empty after migration | Directory removed | n/a | - -All migration steps are best-effort with try/catch — disk-write failures don't block upgrade. - -## Tests - -New regression tests: -- `test/init.test.ts > should install Squad-bundled skills at .github/skills/...` — asserts canonical path, asserts legacy path is NOT created -- `test/cli/upgrade.test.ts > should migrate manifest skills from .copilot/skills/ to .github/skills/` — asserts manifest skill moves, user-added skill preserved -- `test/cli/upgrade.test.ts > should NOT clobber a customized .github/skills/{name} if the legacy copy exists` — asserts both-locations case tombstones legacy without losing the new - -Updated existing tests: -- `test/builtin-skills.test.ts` regex now matches `.github/skills/` -- `test/cli/init.test.ts`, `test/init.test.ts`, `test/init-sdk.test.ts`, `test/cli/upgrade.test.ts`, `test/human-journeys.test.ts`, `test/repl-ux-fixes.test.ts`, `test/cli/init-upgrade-parity.test.ts` — install-path assertions updated to `.github/skills/` - -**188/188 init/upgrade/builtin tests pass; `npm run lint` clean.** - -## What's NOT changed (intentional) - -- **`.copilot/skills/` scan path stays in `squad.agent.md`'s 5-path skill discovery** — the coordinator still discovers user-added skills at the legacy location for backward compat; only Squad-installed (manifest) skills migrate. -- **`~/.copilot/skills/` (personal scope) is unchanged** — that's Copilot CLI's official personal-skills location and remains valid. -- **`test/skill-source.test.ts`, `test/skills-export-import.test.cjs`, `test/tools.test.ts`, `test/skill-script-loader.test.ts`** are NOT touched — they test the runtime skill loader and tool behavior, which still supports `.copilot/skills/` as a valid scan path. - -## Composability - -- **Disjoint from #1292, #1293, #1295, #1297, #1298, #1300, #1301, #1302, #1303** — touches the same `TEMPLATE_MANIFEST` array as #1292/#1295/#1303 but only modifies the destination path, not the source or entry list. Conflicts on `MANIFEST_SKILL_NAMES` are trivial: take the union of skill names with the `../.github/skills/` destination from this PR. -- This is the **canonical fix** for #1126; closes that issue. - -## Out of scope (separate follow-ups) - -- Backward-compat shim that adds a `.copilot/skills -> .github/skills` symlink. Not needed because users won't be looking at `.copilot/skills/` anymore once their tools find skills at `.github/skills/`. Filed as a follow-up if anyone reports broken muscle memory. -- A `squad doctor --skills` check that warns when `.copilot/skills/` still has manifest skills after upgrade (suggesting the migration silently failed). Worth adding to the next maintenance pass. diff --git a/.changeset/fix-1142-ralph-triage-ghe-api-host.md b/.changeset/fix-1142-ralph-triage-ghe-api-host.md deleted file mode 100644 index 44feeb4f8..000000000 --- a/.changeset/fix-1142-ralph-triage-ghe-api-host.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Fix #1142: `ralph-triage.js` hardcoded `hostname: 'api.github.com'` in its `https.request()` call, so `Squad Heartbeat (Ralph)` failed with a 401 on GitHub Enterprise (the `GITHUB_TOKEN` there is only valid against the enterprise API host, not github.com). - -Added a `resolveGithubApiBase()` helper that picks the API base in order — `GITHUB_API_URL` (set by Actions on both github.com and GHE runners), then `GITHUB_SERVER_URL` + `/api/v3`, then `https://api.github.com` as a last-resort fallback — and builds the request from a `URL` object instead of a hardcoded hostname/path pair. No behavior change on github.com-hosted repos, since `GITHUB_API_URL` there already resolves to `https://api.github.com`. - -Fixed in the canonical `.squad-templates/ralph-triage.js` and synced to all 3 mirror targets (`templates/`, `packages/squad-cli/templates/`, `packages/squad-sdk/templates/`). diff --git a/.changeset/fix-1190-esm-patch-doctor-commit-hooks.md b/.changeset/fix-1190-esm-patch-doctor-commit-hooks.md deleted file mode 100644 index 035a6f94e..000000000 --- a/.changeset/fix-1190-esm-patch-doctor-commit-hooks.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix two upgrade-pipeline gaps from #1190: the postinstall ESM patcher now patches every search root instead of stopping at the first already-patched copy, and `squad upgrade` re-runs it against the repo-local node_modules so globally-installed CLIs no longer leave the consumer repo's vscode-jsonrpc/copilot-sdk unpatched. `squad doctor` now also verifies the pre-commit/post-commit hooks required by the two-layer/orphan state backends, instead of only the four sync hooks. diff --git a/.changeset/fix-1211-deletedir-external-stub.md b/.changeset/fix-1211-deletedir-external-stub.md deleted file mode 100644 index fe18c8de2..000000000 --- a/.changeset/fix-1211-deletedir-external-stub.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch -"@bradygaster/squad-cli": patch ---- - -Fix StateBackendStorageAdapter.deleteDir leaving nested keys behind: a single-level list+delete pass missed deeper subtrees (e.g. `agents/x/history/2026/log.md` survived a delete of `agents/x`), silently leaking state on git-notes and orphan backends. deleteDir now walks the full subtree on every backend. Also rename the unimplemented `stateBackend: 'external'` placeholder to `'external-stub'` so it can no longer be confused with the real external-state feature (`squad externalize` / `stateLocation: 'external'`); the legacy name is still accepted and normalized with a one-time deprecation warning. diff --git a/.changeset/fix-1296-stop-mcp-home-pollution.md b/.changeset/fix-1296-stop-mcp-home-pollution.md deleted file mode 100644 index cf8f38fec..000000000 --- a/.changeset/fix-1296-stop-mcp-home-pollution.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix #1296: stop writing `squad_state_` to `~/.copilot/mcp-config.json` on every `squad init` / `squad upgrade` - -`squad init` (line 408 of `packages/squad-cli/src/cli/core/init.ts`) and `squad upgrade` (line 738 of `upgrade.ts`) unconditionally called `ensureSquadStateMcpInUserConfig`, which wrote a `squad_state_` entry to `~/.copilot/mcp-config.json` keyed by a stable hash of the project path. Every new `squad init` accumulated another entry in HOME with no garbage collection. - -This contradicted the explicit iter-8 design intent documented at `packages/squad-cli/src/cli/core/mcp-root.ts:1-27`: - -> *iter-7: wrote `squad_state_` into the user's HOME `~/.copilot/mcp-config.json`. That polluted HOME with one entry per Squad project and required a stale-entry GC that we never built. It also touched a file outside the project, which is surprising for `squad init` / `squad upgrade`.* -> -> *iter-8 flips it back inside the project: we write `squad_state` to a repo-root `.mcp.json` ... **No HOME modifications.*** - -The repo-root `.mcp.json` writes (init.ts:403 / upgrade.ts:728) already cover all documented Copilot CLI launch modes: - -- ``copilot`` from the project root → walks up from cwd to git root, auto-loads `.mcp.json` -- ``copilot -p`` from the project root → same `.mcp.json` is found - -For ``copilot -p`` invocations launched from **outside** the project root, the right pattern is `--additional-mcp-config @.mcp.json` (already documented as the recommended pattern at init.ts:494). - -**Changes** - -- Removed the unconditional `ensureSquadStateMcpInUserConfig` call from `init.ts:408` and `upgrade.ts:738`. Replaced both with comments explaining the iter-8 design and pointing at #1296. -- Removed the now-unused import from both files. -- The function definition itself (`mcp-root.ts:178-228`) is **kept** — a future `squad doctor --mcp-prune` cleanup helper may want to inspect HOME for orphan entries. It's just no longer called from the init/upgrade auto-flow. - -**Tests** - -New regression test in `test/cli/init.test.ts`: - -> `should NOT write any squad_state entries to ~/.copilot/mcp-config.json (regression: #1296)` - -Isolates the developer's real HOME by setting `USERPROFILE`/`HOME` to a temp dir before init, then asserts no `squad_state*` keys appear under that temp HOME after init. The test passes only because the unconditional write is gone — previously this assertion would have failed. - -All 40 existing init tests still pass; `npm run lint` clean. - -**Cleanup** - -A follow-up could add `squad doctor --mcp-prune` to walk `~/.copilot/mcp-config.json`, find `squad_state_` entries whose target directory no longer exists, and remove them. Out of scope for this fix. diff --git a/.changeset/fix-1299-fact-checker-full-plumbing.md b/.changeset/fix-1299-fact-checker-full-plumbing.md deleted file mode 100644 index bbe9ff5c2..000000000 --- a/.changeset/fix-1299-fact-checker-full-plumbing.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -"@bradygaster/squad-cli": minor -"@bradygaster/squad-sdk": minor ---- - -Fix #1299 (deep): Fact Checker gets the same plumbing as Rai — rich charter at init + state directory + policy template - -PR #1300 (also #1299) fixed the documentation gap so the coordinator knows to roster Fact Checker. This PR fixes the **structural** gap behind it. Per user testing on 2026-06-13, even after #1300 the actual agent on disk is still a "name on disk with a 21-line placeholder" — three concrete problems: - -| Piece | Rai before this PR | Fact Checker before this PR | -|-------|--------------------|------------------------------| -| `charter.md` at init | Generic 478-byte stub from `generateCharter()` | Generic 523-byte stub from `generateCharter()` | -| Rich charter template usage | Only used by `squad upgrade` (never by `squad init`) | Same — never used by `squad init` | -| `.squad/{name}/policy.md` | ✅ Seeded from `rai-policy.md` (4160 bytes) | ❌ Directory does not exist | -| `.squad/{name}/audit-trail.md` | ✅ Seeded with append-only header | ❌ Directory does not exist | -| `merge=union` in `.gitattributes` | ✅ `.squad/rai/audit-trail.md` | ❌ No entry for fact-checker | -| `fact-checker-charter.md` distribution | n/a | Only in `packages/squad-cli/templates/` — missing from `.squad-templates/` (canonical source) AND `packages/squad-sdk/templates/`, so the SDK init path could never find it | - -## Fix (4 parts) - -### Part 1 — Rich charter at init (benefits BOTH Rai and Fact Checker) - -`packages/squad-sdk/src/config/init.ts` agent loop now looks up `{templatesDir}/{role}-charter.md` for each agent and uses that as `charter.md` content if it exists. Falls back to `generateCharter()` for user-defined agents that have no rich template (everyone except the built-ins). - -Result: a fresh `squad init` produces `.squad/agents/Rai/charter.md` with the full Rai charter (4525 bytes) and `.squad/agents/fact-checker/charter.md` with the full Fact Checker charter (3024 bytes). Previously both were 478-byte stubs. - -### Part 2 — `.squad/fact-checker/` state dir, mirroring `.squad/rai/` - -Added a new block in `init.ts` (right after the Rai seeding at lines 879–941) that creates: - -- `.squad/fact-checker/policy.md` — seeded from `templates/fact-checker-policy.md` (or a minimal inline fallback if the template is stripped) -- `.squad/fact-checker/audit-trail.md` — seeded with an append-only header - -The policy template (`.squad-templates/fact-checker-policy.md`, ~6 KB) is the canonical authority for the dual-mode operating rules per #789 + #1254: - -- **Mode 1 Verification:** confidence rating taxonomy (✅/⚠️/❌/🔍), what gets checked (URLs, packages, APIs, file paths, signatures, quotes, statistics, cross-references) -- **Mode 2 Devil's Advocate:** required brief structure (steelman → assumptions → pre-mortem → alternatives → risk acceptance) -- **Hard rules:** anti-fabrication guarantees — never cite unverified URL/package/API, never invent measurement data, never fabricate counter-hypotheses, never block on opinion -- **Advisory by default** with two narrow blocking exceptions (❌ at Pre-Ship; coordinator-escalated DA risk) -- **Opt-out model** mirroring Rai's -- **Audit trail rules** — succinct (verdict + citation, never raw source material) -- **Reviewer Rejection Protocol integration** for ❌ Contradicted verdicts - -### Part 3 — Fix the `.squad-templates/` distribution gap - -The existing `fact-checker-charter.md` had been added directly to `packages/squad-cli/templates/` only, bypassing the canonical `.squad-templates/` source. That meant `sync-templates.mjs` couldn't propagate it to `packages/squad-sdk/templates/` (which `getSDKTemplatesDir()` resolves at runtime), so the SDK init code path could never find the rich charter even if it tried. - -Fix: copied `fact-checker-charter.md` to `.squad-templates/` and re-synced. Now all 4 mirror targets have it. This unblocks Part 1. - -### Part 4 — Plumbing updates - -- `.gitattributes` block: added `.squad/fact-checker/audit-trail.md merge=union` alongside Rai's existing entry -- `packages/squad-cli/src/cli/core/templates.ts`: new `TEMPLATE_MANIFEST` entry for `fact-checker-policy.md → templates/fact-checker-policy.md` so `squad upgrade` propagates it -- `.squad-templates/squad.agent.md` Files Catalog table: 2 new rows for `.squad/fact-checker/policy.md` (authoritative) and `.squad/fact-checker/audit-trail.md` (derived/append-only) - -## Tests - -`test/init.test.ts` gains 3 regression tests (28/28 pass total): - -1. `should seed .squad/fact-checker/{policy,audit-trail}.md (regression: bradygaster/squad#1299)` — asserts policy declares both modes + anti-fabrication rules + confidence ratings; audit trail is append-only. -2. `should use the rich fact-checker-charter.md template for built-in agents at init (#1299)` — asserts the rendered charter is > 1 KB (not the 478-byte stub) and contains Verification Methodology + Confidence Ratings. -3. `should use the rich Rai-charter.md template at init (companion to fact-checker fix, #1299)` — asserts Rai gets the same treatment; charter references `.squad/rai/policy.md` and `.squad/rai/audit-trail.md`. - -`npm run lint` clean. - -## Composability - -This PR builds on #1300 (which adds the `## Fact Checker` section to `squad.agent.md` and the "team size" line fix). Both modify `.squad-templates/squad.agent.md` but in **disjoint regions**: - -- #1300 touches the team-size line at L56 and inserts a new `## Fact Checker` section before `## PRD Mode` -- #1301 touches the Files Catalog table at L710-711 - -They will merge cleanly in either order. The user-facing experience requires BOTH to land for full plumbing. - -## Closes / refs - -Closes #1299 (deep fix; #1300 was the surface fix). diff --git a/.changeset/fix-1299-fact-checker-roster-instructions.md b/.changeset/fix-1299-fact-checker-roster-instructions.md deleted file mode 100644 index 46ca9339e..000000000 --- a/.changeset/fix-1299-fact-checker-roster-instructions.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Fix #1299: tell the coordinator to roster Fact Checker (and Ralph + Rai explicitly) in the casting flow - -When a user runs `squad init` followed by `copilot --agent squad`, the coordinator's first-time casting flow correctly creates `.squad/agents/fact-checker/` on disk (per merged PR #1223) but **omits Fact Checker from the `## Members` table** in `.squad/team.md`. Rai is included, Ralph is included, Scribe is included — Fact Checker is silently dropped. - -## Root cause - -`.squad-templates/squad.agent.md` (the canonical coordinator instructions, mirrored to all package templates) had two gaps: - -1. **Line 56** said *"Determine team size (typically 4–5 + Scribe)"* — naming only Scribe among the always-on built-ins. -2. The Rai section (line 884) explicitly told the coordinator *"Rai always appears in team.md: `| Rai | RAI Reviewer | ...`"*, but **no equivalent section existed for Fact Checker**. - -So the model added Rai correctly (saw the roster-entry instruction) but had no instruction to add Fact Checker, even though the agent directory was scaffolded. - -## Fix - -1. Updated the team-size line to *"typically 4–5 + Scribe + Ralph + Rai + Fact Checker — the 4 always-on built-ins, see their dedicated sections below"*. -2. Added a full `## Fact Checker — Verification & Devil's Advocate` section that mirrors the Rai structure: - - Declares the single-agent dual-mode design (per #789 + #1254) — *"single agent, two modes"* - - Explicit **Roster Entry** line: *"Fact Checker always appears in `team.md`: `| Fact Checker | Fact Checker | .squad/agents/fact-checker/charter.md | 🔍 Verifier |`"* - - Trigger phrase table for both Verification mode and Devil's Advocate mode - - Confidence rating taxonomy (✅/⚠️/❌/🔍) - - DA brief structure (steelman, assumptions, pre-mortem, alternatives, risk acceptance) - - Boundaries, background-mode default, state location - -## Changes - -- `.squad-templates/squad.agent.md` (canonical source) updated. -- `sync-templates.mjs --sync` propagates to all 4 mirror targets: - - `templates/squad.agent.md.template` - - `packages/squad-cli/templates/squad.agent.md.template` - - `packages/squad-sdk/templates/squad.agent.md.template` - - `.github/agents/squad.agent.md` (this repo's own coordinator file) - -## Test coverage - -New `test/squad-agent-roster.test.ts` runs against **all 4 template targets** and asserts: - -- The "Determine team size" line mentions Scribe, Ralph, Rai, **and** Fact Checker -- A `## Fact Checker` section exists with an explicit "always appears in team.md" roster-entry line -- The Fact Checker section declares dual operating mode (Verification + Devil's Advocate) — anchors the design from #789 + #1254 so a future PR can't accidentally split them again (cf. closed PR #1294) -- The Ralph + Rai sections are still present and unmodified - -All 40 existing init/cli/init tests still pass; `npm run lint` clean. - -## Verification - -After this PR ships, a fresh `squad init` + `copilot --agent squad` produces a `team.md ## Members` table that includes Fact Checker alongside Scribe, Ralph, and Rai. - -Closes #1299 diff --git a/.changeset/fix-1305-state-backend-handshake.md b/.changeset/fix-1305-state-backend-handshake.md deleted file mode 100644 index 40af92ac4..000000000 --- a/.changeset/fix-1305-state-backend-handshake.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -"@bradygaster/squad-cli": minor -"@bradygaster/squad-sdk": minor ---- - -Fix #1305: coordinator must probe for `squad_state` / `memory.*` tools before writing state, and hard-refuse writes when the bridge isn't reachable on non-local backends - -## Symptom - -A coordinator session against a Squad with `stateBackend: "two-layer"` wrote `.squad/decisions.md` + four `.squad/agents/{name}/history.md` files + a `.squad/decisions/inbox/copilot-directive-…md` via raw `create`/`edit` tools — never calling any `squad_state_*` or `memory.*` tool. The pre-commit hook caught the contract violation; the agent treated it as a "git problem" instead of the symptom it was. - -## Root cause (two failure modes stacked) - -**Mechanical (Copilot CLI):** Copilot CLI loads MCP server tools lazily — they're registered (via `.mcp.json`) but not always advertised in the model's initial function list. Models have to use `tool_search_tool_regex` to find them or guess they exist. The `squad_state` MCP server is correctly registered with `tools: ["*"]` and responds to `initialize`/`tools/list` over stdio — but the model's tool block at session start may not include them. This is a Copilot CLI architectural choice (lazy discovery vs. preload), not something Squad can fix server-side. - -**Behavioral (squad.agent.md):** The pre-1305 prompt said *"When memory tools are available, use them before writing durable memory by hand"* and *"If memory tools are not available, fall back to squad_decide or squad_state_write"*. Models read `"available"` as `"listed in my tool prompt"` instead of `"after probing to find out"`. There was no hard refusal clause for the case where the agent is about to violate the state-backend contract. - -## Fix - -Two changes to `.squad-templates/squad.agent.md` (synced to all 4 mirror targets): - -### 1. New "State-backend handshake" section (MANDATORY, runs once per session) - -Inserted right after the `stateBackend` resolution at L131. Steps: - -1. If `STATE_BACKEND ∈ {"local", "worktree"}`: file ops on `.squad/` are valid; skip the probe. -2. Otherwise: probe for `squad_state_health` via `tool_search_tool_regex` (or equivalent tool-discovery mechanism). On success, call `squad_state_health` once to confirm the bridge answers. -3. **If the probe fails**: HALT before any state write. Output a precise error to the user (verbatim text in the template): *"Squad's runtime state bridge is missing for backend `{STATE_BACKEND}`. The `squad_state` MCP server in `.mcp.json` is not reachable in this Copilot session. Restart Copilot CLI so `.mcp.json` is loaded, or change `stateBackend` to `local` in `.squad/config.json`."* - -### 2. Replaced soft "if not available" language with a HARD RULE in `### Memory Governance Tools` - -Lists the runtime-owned paths that are FORBIDDEN to write via `create`/`edit`/`write_file` on non-local backends when the bridge isn't reachable: - -- `.squad/decisions.md` -- `.squad/decisions/inbox/**` -- `.squad/agents/*/history.md` -- `.squad/casting/*.json` -- `.squad/identity/*.md` -- `.squad/memory/**` -- `.squad/orchestration-log/**` -- `.squad/log/**` -- `.squad/rai/audit-trail.md` -- `.squad/fact-checker/audit-trail.md` - -Clarified the local-backend carve-out so `STATE_BACKEND ∈ {"local", "worktree"}` users still freely use `create`/`edit`/`write_file` on `.squad/`. - -Also clarified that `memory.*` and `squad_state_*` share the same MCP server (they're aliases in the same registry — see `packages/squad-cli/src/cli/commands/state-mcp.ts`) so models stop treating them as separate availability checks. - -## Tests - -New `test/state-backend-handshake.test.ts` runs against all 4 template mirror targets and asserts (20 tests = 5 assertions × 4 files): - -- Mandatory handshake section exists with "every session" + "before any state mutation" timing -- Probe step exists with `squad_state_health` + tool-discovery mechanism -- HALT step exists with restart-CLI + change-stateBackend remediation -- HARD RULE exists listing the forbidden paths + `create`/`edit`/`write_file` tools by name -- Local/worktree carve-out preserved - -20/20 pass; `npm run lint` clean. - -## What's NOT in scope (filed/tracked separately) - -**Server-side fix (auto-preload MCP tools):** The mechanical root cause is a Copilot CLI feature — preload MCP server tools into the model's function list at session start instead of behind lazy discovery. Out of Squad's control. If maintainers agree it's worth pursuing, file as a feature request against `github/copilot-cli`. With this PR's prompt-level enforcement in place, the server-side fix becomes a nice-to-have rather than load-bearing. - -**Skill reinforcement (init-mode, agent-conduct):** Could repeat the rules in `.squad/skills/init-mode/SKILL.md` and `.squad/skills/agent-conduct/SKILL.md` as defense-in-depth for users who skip `squad upgrade`. Worth a small follow-up PR; not blocking. - -Closes #1305 diff --git a/.changeset/fix-1396-export-external-state.md b/.changeset/fix-1396-export-external-state.md deleted file mode 100644 index 1b8a8e420..000000000 --- a/.changeset/fix-1396-export-external-state.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix #1396: `squad export` now resolves externalized state. After `squad externalize`, export read the local `.squad/` directory directly, so it either failed with a misleading "No squad found — run init first" or silently exported stale/scaffolded local files instead of the real team state in the external directory. Export now routes through the same `effectiveSquadDir()` resolution used by `build`, `loop`, `plugin`, `watch`, and `doctor`, reading `team.md`, `decisions.md`, `routing.md`, `casting/`, `agents/`, and `.squad`-local skills from the effective state directory. diff --git a/.changeset/fix-1397-1398-external-state-reads.md b/.changeset/fix-1397-1398-external-state-reads.md deleted file mode 100644 index ba881a51a..000000000 --- a/.changeset/fix-1397-1398-external-state-reads.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -`squad copilot` and `squad rc` now follow externalized state: roster reads and writes go to the external state dir when `.squad/config.json` has the `stateLocation: external` marker, instead of always using the local `.squad/team.md`. diff --git a/.changeset/fix-1399-cast-external-state.md b/.changeset/fix-1399-cast-external-state.md deleted file mode 100644 index b26e3245d..000000000 --- a/.changeset/fix-1399-cast-external-state.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor -"@bradygaster/squad-cli": patch ---- - -`squad cast` now discovers project agents from the external state dir when state is externalized. `LocalAgentSource` accepts an optional explicit agents directory that overrides the `.squad/agents` probing, since externalized state keeps agents at `/agents` with no `.squad` nesting. diff --git a/.changeset/fix-1441-pin-actions-sha.md b/.changeset/fix-1441-pin-actions-sha.md deleted file mode 100644 index 53f73649f..000000000 --- a/.changeset/fix-1441-pin-actions-sha.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Pin GitHub Actions references to full-length commit SHAs across the 10 shipped workflow templates (`squad-ci.yml`, `squad-docs.yml`, `squad-heartbeat.yml`, `squad-issue-assign.yml`, `squad-label-enforce.yml`, `squad-preview.yml`, `squad-promote.yml`, `squad-release.yml`, `squad-triage.yml`, `sync-squad-labels.yml`), matching the same hardening already applied to this repo's own `.github/workflows/`. Orgs that require SHA-pinned actions as a supply-chain policy can now use `squad init`/`squad upgrade` without hand-patching every installed workflow. Closes #1441. diff --git a/.changeset/fix-1639-self-pull-stash-loss.md b/.changeset/fix-1639-self-pull-stash-loss.md deleted file mode 100644 index a11267827..000000000 --- a/.changeset/fix-1639-self-pull-stash-loss.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix #1639: `squad watch`'s self-pull capability stashed uncommitted local changes before `git pull --ff-only`, but only popped the stash back if the pull succeeded — a thrown pull error (diverged history, no tracking branch, network failure) jumped past the pop and reported success anyway, leaving the user's local changes sitting in `git stash` with nothing in the round output saying so. Restructured so the stash-pop always runs regardless of pull outcome, and a stash that genuinely can't be restored now comes back as a failed capability result instead of a silent success. diff --git a/.changeset/fix-cli-sdk-version-range.md b/.changeset/fix-cli-sdk-version-range.md deleted file mode 100644 index acec3c3f2..000000000 --- a/.changeset/fix-cli-sdk-version-range.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Pin the CLI's squad-sdk dependency to the matching package version so published installs cannot keep an older SDK that lacks APIs required by the CLI. diff --git a/.changeset/fix-cli-sdk-workspace-pin.md b/.changeset/fix-cli-sdk-workspace-pin.md deleted file mode 100644 index 70050760a..000000000 --- a/.changeset/fix-cli-sdk-workspace-pin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Force the CLI's squad-sdk dependency through the repo workspace by using a root file dependency plus an npm override for the CLI package. This keeps fresh installs linked to the local SDK prerelease instead of pulling the stale published SDK. Closes #1405. diff --git a/.changeset/fix-coordinator-inline-dispatch-gate.md b/.changeset/fix-coordinator-inline-dispatch-gate.md deleted file mode 100644 index 5871a8941..000000000 --- a/.changeset/fix-coordinator-inline-dispatch-gate.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Fix coordinator inline-dispatch regression: restore always-on dispatch gate in the Squad coordinator template - -**Problem** - -In v0.10.0 the Squad coordinator started doing domain work itself instead of dispatching to roster agents (it worked in v0.9.4). Root cause: commit `afe78188` (#1035, "context overflow sentinel + coordinator size reduction") relocated the concrete inline-dispatch gate and the dispatch mechanics out of the always-on coordinator prompt (`.squad-templates/squad.agent.md`) into lazy-loaded reference files (`client-compatibility-reference.md`, `spawn-reference.md`). The remaining inline one-liner ("inline work is last-resort fallback only") was too soft, and the concrete "when may I work inline?" rule + the VS Code `runSubagent` how-to were no longer in-context, so the coordinator defaulted to executing work itself. - -**Fix** - -Three minimal edits to the canonical coordinator template (`.squad-templates/squad.agent.md`), synced to all mirrors via `npm run sync-templates`: - -1. **Client Compatibility** — replaced the soft one-liner with an explicit **Inline-dispatch gate**: doing domain work inline is permitted ONLY in Direct Mode, or when NEITHER `task` NOR `runSubagent` is available; otherwise the coordinator MUST dispatch. -2. **How to Spawn an Agent** — added a one-line **STOP gate**: about to produce a domain artifact with no `task` / `runSubagent` call this turn → STOP and dispatch (exceptions: Direct Mode, or no spawn tool exists). -3. Re-inlined a ~5-line **VS Code `runSubagent` micro-playbook** so the how-to-dispatch mechanics are always-on instead of lazy-loaded. - -The legitimate Direct/Lightweight response modes are preserved (Lightweight still spawns one agent; Direct still answers from context without spawning). - -**Validation** - -New deterministic, subprocess-free regression test `test/coordinator-inline-dispatch-gate.test.ts` asserts the gate/STOP-gate/micro-playbook exist in canonical and that the gate is present in all 5 synced copies (parity). Red before the fix (8/8 failing), green after. Existing requires a `squad upgrade` for existing installs to pick up the new template. diff --git a/.changeset/fix-copilot-sdk-type-compat.md b/.changeset/fix-copilot-sdk-type-compat.md deleted file mode 100644 index 05fd158c7..000000000 --- a/.changeset/fix-copilot-sdk-type-compat.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -fix: update adapter/client.ts for @github/copilot-sdk 1.0.4 API changes - -Fixes 5 TypeScript errors caused by breaking changes in `@github/copilot-sdk@1.0.4`: - -- Replace removed `cliPath`/`cliArgs`/`useStdio`/`port`/`cliUrl` options with the new `RuntimeConnection` pattern -- Update `ping()` return type from `timestamp: number` to `timestamp: string` -- Make `SquadModelBilling.multiplier` optional to match upstream `ModelBilling` -- Replace `client.on()` with `client.onLifecycle()` for session lifecycle events diff --git a/.changeset/fix-dep0190-shell-spawn.md b/.changeset/fix-dep0190-shell-spawn.md deleted file mode 100644 index 8cb081f75..000000000 --- a/.changeset/fix-dep0190-shell-spawn.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix Windows shell spawn issues and gh auth false-negative - -- **DEP0190 fix:** Added `escapeForCmd()`/`escapeArgs()` to properly quote args when `shell: true` is used on Windows. Changed `shell: true` → `shell: IS_WINDOWS`. -- **Capability migration:** Moved monitor-email, monitor-teams, retro, decision-hygiene from inline `buildAgentCommand`/`spawnWithTimeout` to shared `agent-spawn.ts` module. -- **gh auth fix:** Use `gh auth token` instead of `gh auth status` — the latter returns non-zero when any keyring entry is stale, even if the active account works fine. -- **Copilot flag fix:** Use `-p` (correct) instead of `--message` (non-existent) for copilot CLI prompt flag. -- **Default --yolo:** When `--execute` is active and no `copilotFlags`/`agentCmd` are set, default to `--yolo` so copilot doesn't hang waiting for permission prompts. \ No newline at end of file diff --git a/.changeset/fix-dispatch-enforcement-policy-gate.md b/.changeset/fix-dispatch-enforcement-policy-gate.md deleted file mode 100644 index bd1c72a1a..000000000 --- a/.changeset/fix-dispatch-enforcement-policy-gate.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Add Layer A/B/C dispatch-enforcement governance to coordinator scaffolding and audit hooks - -This release note covers the dispatch-enforcement work in PR #1537: stronger coordinator routing guardrails, new DispatchGuard audit hooks and fixtures, and Ralph/Scribe charter updates that keep domain work delegated and mechanically audited. diff --git a/.changeset/fix-doctor-two-layer-decisions.md b/.changeset/fix-doctor-two-layer-decisions.md deleted file mode 100644 index 53ec10ff1..000000000 --- a/.changeset/fix-doctor-two-layer-decisions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix `squad doctor` so `decisions.md` passes validation when two-layer or orphan state backends store it on the `squad-state` branch instead of in the working tree. diff --git a/.changeset/fix-duplicate-cast-help.md b/.changeset/fix-duplicate-cast-help.md deleted file mode 100644 index d74cb589f..000000000 --- a/.changeset/fix-duplicate-cast-help.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Remove duplicate `cast` entry in `squad -h` output diff --git a/.changeset/fix-externalize-binary-corruption.md b/.changeset/fix-externalize-binary-corruption.md deleted file mode 100644 index 0e5a9de8a..000000000 --- a/.changeset/fix-externalize-binary-corruption.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix `squad externalize`/`internalize` corrupting non-UTF-8 files under `.squad/`. Both commands copied files through a UTF-8 string round-trip (`readSync`/`writeSync`), which replaced every byte >= 0x80 with U+FFFD and, because the source was deleted right after, destroyed the only intact copy. They now copy bytes via `storage.copySync`, so binary state (diagrams, archives, a future SQLite state db) survives the round trip intact. diff --git a/.changeset/fix-fact-checker-auto-scaffold.md b/.changeset/fix-fact-checker-auto-scaffold.md deleted file mode 100644 index 899c60d98..000000000 --- a/.changeset/fix-fact-checker-auto-scaffold.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix #1222: Auto-scaffold Fact Checker agent during `squad init`, `squad cast`, and `squad upgrade` - -The Fact Checker role was added in v0.10.0 (#789) with its catalog entry, charter template, skill, AGENT_TEMPLATES map entry, and template manifest entry — but it was never wired into the user-facing onboarding flow. Users running `squad init` got Scribe/Ralph/Rai but never saw Fact Checker. Users running `squad upgrade` from older versions never got Rai or Fact Checker scaffolded either (upgrade was intentionally silent on agents). - -This change wires Fact Checker (and Rai, as a defensive backfill) into three code paths: - -- **`init.ts`** — adds `fact-checker` to the default `agents:` array passed to `sdkInitSquad()`. Fresh `squad init` now produces `.squad/agents/fact-checker/`. -- **`cast.ts`** — adds `factCheckerMember()`, `factCheckerCharter()`, `hasFactChecker` branches in `castTeam()`, and the roster banner line. Interactive `squad cast` now offers Fact Checker as an always-on background agent. -- **`upgrade.ts`** — new `ensureBuiltinAgents()` runs in `runEnsureChecks()`. Idempotently scaffolds `.squad/agents/Rai/` and `.squad/agents/fact-checker/` from shipped charter templates if missing. Never overwrites existing charters or history files. Scribe and Ralph are intentionally NOT scaffolded by upgrade (they predate this fix in all squads, and their charters are inlined in cast.ts). - -Result: any squad — fresh init, interactive cast, or upgrade from any prior version — now ends up with Fact Checker available. - diff --git a/.changeset/fix-green-suite.md b/.changeset/fix-green-suite.md deleted file mode 100644 index 7e7911126..000000000 --- a/.changeset/fix-green-suite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -Fix local test-suite failures by aligning personal squad path expectations, stabilizing observer file classification, and skipping environment-dependent docs/Aspire checks when required local dependencies are unavailable. diff --git a/.changeset/fix-identity-write-author-validation.md b/.changeset/fix-identity-write-author-validation.md deleted file mode 100644 index ae4ac9053..000000000 --- a/.changeset/fix-identity-write-author-validation.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -Fix identity/ state writes and widen squad_decide author validation (#1255, #1256). - -- **#1255**: Add `identity/` to the `validateMutableStateToolKey` allowlist so agents can write to `identity/now.md` and other files under `identity/` as required by `squad.agent.md`. -- **#1256**: Relax the `squad_decide` author regex from `^[a-zA-Z0-9_-]+$` to accept any printable ASCII character (e.g. spaces, parens) while enforcing a 200-character cap. The raw author string is preserved in the `**By:**` display line; a slugified form (lowercase, non-alphanumeric replaced with `-`, collapsed and trimmed) is used for the inbox filename to keep filenames filesystem-safe. Reject author strings that sanitize to an empty slug (e.g. spaces/punctuation only); report the actual written filename in the success message. diff --git a/.changeset/fix-permission-contract.md b/.changeset/fix-permission-contract.md deleted file mode 100644 index c40727410..000000000 --- a/.changeset/fix-permission-contract.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch -"@bradygaster/squad-cli": patch ---- - -Fix permission handler to use `approve-once` instead of deprecated `approved` kind, aligning with Copilot CLI v1.0.54+ permission contract diff --git a/.changeset/fix-preset-routing-roundtrip.md b/.changeset/fix-preset-routing-roundtrip.md deleted file mode 100644 index b9c50147a..000000000 --- a/.changeset/fix-preset-routing-roundtrip.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -Fix `squad preset save/apply` to round-trip custom routing configuration. Previously, `routing.md` was not included in preset snapshots, so custom label tables, module ownership mappings, and other routing rules were lost on `preset apply`. Now `savePreset` captures the full `routing.md` and `applyPreset` restores it faithfully. diff --git a/.changeset/fix-release-pipeline-versions.md b/.changeset/fix-release-pipeline-versions.md deleted file mode 100644 index cc918ff55..000000000 --- a/.changeset/fix-release-pipeline-versions.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -fix: release pipeline version pinning (#1203, #1204) - -- Lower SDK dependency floor from `>=0.10.0` to `>=0.9.0` so the CLI tarball - resolves against the last published SDK when the current version isn't yet on - the registry. -- Add `isLocalOrUnpublishedVersion` guard to `buildMcpServerSpecs` so local dev - builds and versions with build metadata (`+`) fall back to `@insider` instead - of writing an unresolvable version string into MCP config. -- Extend `resolveSquadStateMcpSpec` to short-circuit for build-metadata versions. -- Add CI step to verify SDK dependency is resolvable before publishing the CLI. diff --git a/.changeset/fix-routing-strip-example-quotes.md b/.changeset/fix-routing-strip-example-quotes.md deleted file mode 100644 index 365753800..000000000 --- a/.changeset/fix-routing-strip-example-quotes.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -Fix: strip surrounding quotes from routing.md example phrases in `parseRoutingMarkdown` - -`parseRoutingMarkdown` split the Examples cell on commas but never stripped the surrounding quotes, so a quoted example like `"unit tests"` was stored verbatim (quotes included). When `compileRoutingRules` / `matchRoute` later tokenized it, the quote characters glued onto the boundary words (`"unit`, `tests"`), producing regex patterns that could never match — so routing tables that used quoted examples silently routed every message to the fallback agent. - -Leading/trailing quotes (`"`, `'`, `` ` ``) are now stripped from each example, so quoted and unquoted examples behave identically. Adds regression tests covering both the parse step and end-to-end `matchRoute`. diff --git a/.changeset/fix-sdk-dotted-tool-names.md b/.changeset/fix-sdk-dotted-tool-names.md deleted file mode 100644 index 84eb024ed..000000000 --- a/.changeset/fix-sdk-dotted-tool-names.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -fix(sdk): normalize dotted ToolRegistry names at Copilot external-tool boundary - -Squad's ToolRegistry uses canonical dotted names (e.g. `memory.classify`) but the -Copilot SDK CLI server enforces `^[a-zA-Z0-9_-]+$` on external tool names, rejecting -dots. This caused `createSession({ tools: registry.getTools() })` to fail. - -Adds `normalizeToolNameForCopilot()` and `normalizeToolsInConfig()` at the adapter -boundary to convert dots to underscores before forwarding to the SDK. Hook callbacks -(`onPreToolUse`/`onPostToolUse`) reverse-map wire names back to canonical so consumers -always receive `memory.classify`, not `memory_classify`. Both functions are exported -from `@bradygaster/squad-sdk/client` for consumer use. diff --git a/.changeset/fix-sdk-export-gitignore-state.md b/.changeset/fix-sdk-export-gitignore-state.md deleted file mode 100644 index 0f23309b8..000000000 --- a/.changeset/fix-sdk-export-gitignore-state.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -fix(sdk): export `addSquadStateGitignoreBlock` / `removeSquadStateGitignoreBlock` from the package root - -`packages/squad-cli/src/cli/commands/migrate-backend.ts` imports these helpers from -`@bradygaster/squad-sdk`, but they were never re-exported from `src/index.ts`. This broke -the CLI TypeScript build (`TS2305: has no exported member`). Re-export the two functions -(plus their marker constants) so the CLI compiles and the state-backend migration command -resolves them. Unblocks cutting a stable release that carries the #1378 inline-dispatch-gate fix. diff --git a/.changeset/fix-skill-squad-rename-to-squad-help.md b/.changeset/fix-skill-squad-rename-to-squad-help.md deleted file mode 100644 index 29907db3c..000000000 --- a/.changeset/fix-skill-squad-rename-to-squad-help.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch -"@bradygaster/squad-cli": patch ---- - -Fix `skill(Squad)` discovery — rename disambiguation skill to `squad-help` (supersedes #1297) - -PR #1297 added a disambiguation skill named `squad` so models calling `skill(Squad)` would get a redirect instead of "Skill not found". After local end-to-end testing on 2026-06-13: **the skill ships to disk correctly but never shows up in Copilot CLI's `/skills` list**. - -## Root cause (verified against Copilot CLI source 1.0.62-2) - -Decompiling `~/.copilot/pkg/win32-x64/1.0.62-2/app.js`: - -1. **Copilot CLI's skill schema is `{name, description, source, baseDir, allowedTools, pluginName, pluginVersion}`** (line 989). Frontmatter fields like `triggers:`, `domain:`, `confidence:`, `license:` are silently ignored. -2. **Skill loader returns `{skills, warnings, errors}`** (line 4427). Skills that fail to load are reported as errors. -3. **A skill named `squad` collides with the Copilot agent named `Squad`** (registered at `.github/agents/squad.agent.md`). The agent wins; the skill is hidden from `/skills`. - -The original `triggers:` frontmatter from #1297 was based on a wrong assumption — Copilot CLI doesn't read that field. Triggering happens via natural-language match against `description:`, and the skill name is what `skill(X)` looks up. - -## Fix - -1. **Rename** the disambiguation skill `squad` → `squad-help`. Avoids the agent-name collision, descriptive enough that the model can find it via description match when a user says *"how do I use squad"* or *"squad help"*. -2. **Update SKILL.md content:** - - `name: "squad-help"` (was `"squad"`) - - Removed `triggers:`, `domain:`, `confidence:`, `source:`, `license:` (all ignored by Copilot CLI) - - Added `allowedTools: []` (matches Copilot CLI's schema) - - `description:` rewritten to be self-explanatory so natural-language match works - - Body still explains the agent-vs-skill distinction and routes to `task(agent_type="Squad", …)` for misdirected `skill(Squad)` attempts - - Added explicit note about `/squad` slash command: it does not exist (slash commands are built-in CLI keywords, not auto-mapped from skills) and there's no way to create one without a Copilot CLI feature change -3. **Update** `MANIFEST_SKILL_NAMES` in `packages/squad-sdk/src/config/init.ts`: `'squad'` → `'squad-help'`. -4. **Add** `TEMPLATE_MANIFEST` entry in `packages/squad-cli/src/cli/core/templates.ts` for `squad-help` so `squad upgrade` also propagates the skill (independent of #1297 which only updated MANIFEST_SKILL_NAMES — `squad upgrade` uses a different code path that reads TEMPLATE_MANIFEST). - -## Test coverage - -New `test/init.test.ts > should install the squad-help disambiguation skill`: -- Asserts `.copilot/skills/squad-help/SKILL.md` exists after `initSquad()` -- Asserts the frontmatter says `name: "squad-help"` (not `"squad"`) — regression guard against re-introducing the collision -- Asserts content references `agent_type="Squad"` (the correct invocation path) -- Asserts content references `squad-commands` (the right next-step skill) - -26/26 init tests pass; `npm run lint` clean. - -## Supersedes #1297 - -PR #1297 added a colliding-name skill. This PR is the correct version. Close #1297 in favor of this one; the consolidated changeset will be picked up here. - -## Out of scope (separate issue worth filing) - -`squad upgrade` synced only 10 of 16 installed skills in local testing — `TEMPLATE_MANIFEST` (used by upgrade) is out of sync with `MANIFEST_SKILL_NAMES` (used by init). Specifically, `tiered-memory`, `iterative-retrieval`, `reflect`, `cross-squad`, `cross-squad-communication` (added in PRs #1292 + #1295) have entries in `MANIFEST_SKILL_NAMES` but not in `TEMPLATE_MANIFEST`. Will file a follow-up to add those to `TEMPLATE_MANIFEST` so both code paths agree. diff --git a/.changeset/fix-squad-home-env-bugs.md b/.changeset/fix-squad-home-env-bugs.md deleted file mode 100644 index e5bd0da9d..000000000 --- a/.changeset/fix-squad-home-env-bugs.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch -"@bradygaster/squad-cli": patch ---- - -fix: respect SQUAD_HOME in capabilities.ts and comms-teams.ts, implement SQUAD_PERSONAL_DIR env var, fix Windows shell flag in loop preflight, link personal squad during init - -- capabilities.ts: use `resolveSquadHome()` instead of hardcoded `~/.squad/` for machine-capabilities.json (#1280) -- comms-teams.ts: use `resolveSquadHome()` instead of hardcoded `~/.squad/` for Teams OAuth token storage (#1279) -- resolution.ts: implement `SQUAD_PERSONAL_DIR` env var override in `resolvePersonalSquadDir()` (#1278) -- loop.ts: add `shell: process.platform === 'win32'` to `checkCopilotCli()` execFile call (#1372) -- init.ts: set `teamRoot` in config.json to personal squad directory when one exists (#1010, #984) diff --git a/.changeset/fix-squad-slash-command.md b/.changeset/fix-squad-slash-command.md deleted file mode 100644 index dc4e364d6..000000000 --- a/.changeset/fix-squad-slash-command.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor -"@bradygaster/squad-cli": minor ---- - -Make `/squad` a real slash command — rename `squad-commands` skill to `squad` with `user-invocable: true` - -## What this enables - -Users can type `/squad` in any Copilot CLI session in a squad-initialized project and get the categorized command catalog (Install & Upgrade, Team Management, Issues & PRs, Plugins & Skills, Model & Cost, Sessions & State). This is what users naturally expect — Squad ships an in-chat command surface, and the slash key is the muscle memory. - -## Verified mechanism (Copilot CLI 1.0.62-2) - -Decompiling `~/.copilot/pkg/win32-x64/1.0.62-2/sdk/index.js` line 2618: - -```js -getLoadedSkills().filter(e => e.userInvocable) - .map(e => ({name: `/${eF(e)}`, isSkill: true, skill: e})) -``` - -Any skill with frontmatter `user-invocable: true` is auto-registered by Copilot CLI as a slash command at `/`. The built-in `customize-cloud-agent` skill shipped with Copilot CLI uses this exact pattern with `user-invocable: false`; setting it to `true` makes the skill appear in `/skills` AND as a slash keystroke. - -The previous skill `squad-commands` had no `user-invocable` field (Copilot CLI defaults to false), so `/squad-commands` did not exist. Users either typed natural language ("squad commands", "what can squad do") or never discovered the menu. - -## Changes - -1. **Renamed** the `squad-commands` skill to `squad` (canonical source in `.squad/skills/squad/`). -2. **Frontmatter rewritten** to match Copilot CLI's actual schema (verified against decompiled source): - - `name: squad` (was `squad-commands` — `/squad` is shorter, intuitive, and matches the agent name without colliding because slash commands and skill lookups are separate namespaces) - - `user-invocable: true` ← **the load-bearing change** - - `description:` rewritten to be self-explanatory so natural-language match also still works - - `allowedTools: []` (matches Copilot CLI's schema) - - Removed unused fields: `domain:`, `confidence:`, `source:`, `triggers:` (all silently ignored by Copilot CLI) -3. **Body text** updated to reference `/squad` as the primary invocation path. -4. **`MANIFEST_SKILL_NAMES`** in `packages/squad-sdk/src/config/init.ts`: `'squad-commands'` → `'squad'`. -5. **`TEMPLATE_MANIFEST`** in `packages/squad-cli/src/cli/core/templates.ts`: updated `source` + `destination` + `description` to reflect the rename. -6. **Removed** stale `packages/{squad-cli,squad-sdk}/templates/skills/squad-commands/` directories. - -## Test coverage - -New `test/init.test.ts > should install the squad slash-command skill with user-invocable: true`: -- Asserts `.copilot/skills/squad/SKILL.md` exists after `initSquad()` -- Asserts frontmatter contains `user-invocable: true` (load-bearing — without this, no slash command) -- Asserts frontmatter `name: squad` (load-bearing — slash command is `/`) -- Asserts the menu presentation rules are still in the body - -26/26 init tests pass; `npm run lint` clean. - -## How users will experience this - -After `squad init` + opening Copilot CLI in the project: - -``` -> /squad -📋 Squad Commands — pick a category: - 1. Install & Upgrade - 2. Team Management - 3. Issues & PRs - 4. Plugins & Skills - 5. Model & Cost - 6. Sessions & State -``` - -## Composability with other open PRs - -- **Disjoint from #1292** (skills bundling, 4 new entries). Both modify `MANIFEST_SKILL_NAMES` but `squad-commands → squad` is a rename, not an add. Merge order doesn't matter — the renamer wins. -- **Disjoint from #1302** (`squad-help` disambiguation skill). `squad-help` covers the `skill(Squad)` misdirect case; this PR covers the `/squad` slash command UX. They're complementary. - -## Out of scope (future, mentioned in user request) - -The user wants to eventually install the `squad` skill **machine-wide** (e.g., `~/.copilot/skills/squad/`) so `/squad init` works in any folder even before `squad` is initialized in that project. That's a separate piece of work because: -1. It requires a `squad install --global-skill` command or similar (none exists today) -2. The `/squad` menu currently calls into `squad` CLI subcommands that assume `.squad/` exists in cwd — the menu would need a "Init Mode" branch for the "no `.squad/` yet" case -3. Copilot CLI's `~/.copilot/skills/` is a personal scope, so it'd need to be opt-in per-user - -Will file a follow-up issue tracking that work after this lands. diff --git a/.changeset/fix-squad-spawning-routing.md b/.changeset/fix-squad-spawning-routing.md deleted file mode 100644 index 5e86ee042..000000000 --- a/.changeset/fix-squad-spawning-routing.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Coordinator now recognises "spawn a squad" / "another squad" / "two squads" as Squad-PRODUCT vocabulary - -## Symptom - -A coordinator initialised by `squad init` saw prompts like *"spawn two squads of designers and devs"* and fanned out raw `task` agents inside its own context, treating "squad" as generic English for "team / group". It never invoked the bundled `cross-squad` or `cross-squad-communication` skills, so the peer-squad delegation protocol (registry / manifest / sync CLI / git-async / GitHub-issue patterns) was bypassed entirely. - -Two structural holes in `squad.agent.md` allowed this: - -1. The Routing table had no row that mapped "spawn a squad" phrasing to the Squad-PRODUCT concept. -2. The Skill-aware-routing block was process discipline ("check skill directories by domain relevance") with no hard "if the user's word matches a skill name, MUST load the skill" trigger. - -## Fix - -Two surgical edits to the canonical `.squad-templates/squad.agent.md` (synced to all 4 mirror copies via `scripts/sync-templates.mjs --sync`): - -1. **New routing-table row** — matches "spawn a squad", "another squad", "two squads", "second squad", "fan out to squads", "delegate to a squad", or any phrasing that treats "squad" as a unit to spawn or address. Action: invoke the `skill` tool on `cross-squad` AND `cross-squad-communication` BEFORE any `task` spawn, then delegate via Pattern 0/1/2/3 — never fan out raw `task` agents in the coordinator's own context. - -2. **New "Hard trigger — keyword-to-skill match" paragraph** at the top of the Skill-aware-routing block — if any word in the request matches an installed skill name (e.g., "squad" → `cross-squad`, "reflect" → `reflect`, "ceremony" → matching ceremony skill, "fact-check" → `fact-checking`, "release" → `release-process`), the coordinator MUST invoke the `skill` tool to fully load that skill BEFORE designing its approach. Includes a one-line "failure mode this closes" pointer so the rule survives future paraphrasing. - -3. **Companion `cross-squad/SKILL.md` opener strengthened** — added a one-line "Read this FIRST any time the user says 'squad' as a thing to spawn / delegate to / address" callout above the existing `## Context` paragraph, so even a coordinator that skips the routing-table row still hits the trigger when it does eventually load the skill. - -## Regression test - -`test/template-sync.test.ts` now asserts, for every mirrored copy of `squad.agent.md` (5 locations — canonical + 3 template mirrors + `.github/agents/`), that: - -* The routing-table row exists and contains all three trigger phrases ("spawn a squad", "another squad", "two squads"). -* The row's action cell references the `cross-squad` skill AND the `skill` tool. -* The "Hard trigger" + "keyword-to-skill match" markers are both present in the Skill-aware-routing block. -* The hard-trigger paragraph names the worked example `"squad" → cross-squad` so future edits can't drop the concrete mapping. - -223/223 template-sync tests pass. - -## Composability - -Disjoint from all other open PRs in the v0.10 stabilisation set (#1292, #1293, #1295, #1298, #1300, #1301, #1302, #1303, #1304, #1306). Only modifies `.squad-templates/squad.agent.md` + its 4 mirrors + `cross-squad/SKILL.md` + the template-sync test. Existing squads can pick up the fix two ways: (a) `squad upgrade` once this lands, or (b) hand-patch `.squad/squad.agent.md` against the upstream diff and restart the Copilot CLI session. diff --git a/.changeset/fix-workflow-shellcheck-quoting.md b/.changeset/fix-workflow-shellcheck-quoting.md deleted file mode 100644 index 4e815494a..000000000 --- a/.changeset/fix-workflow-shellcheck-quoting.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Fix shellcheck SC2086 in workflow templates: quote `$GITHUB_OUTPUT` redirects - -All `>> $GITHUB_OUTPUT` (and `>> $GITHUB_STEP_SUMMARY`) redirects in `run:` blocks were unquoted, causing `actionlint` + shellcheck to report SC2086 (double quote to prevent globbing and word splitting) in downstream repos that run `actionlint` in their CI. The fix is purely additive quotes around the variable; behaviour is unchanged. - -**Files fixed:** -- `.squad-templates/workflows/squad-heartbeat.yml` (canonical source — synced to all mirrors) -- `templates/workflows/squad-heartbeat.yml` -- `packages/squad-cli/templates/workflows/squad-heartbeat.yml` -- `packages/squad-sdk/templates/workflows/squad-heartbeat.yml` - -**Squad's own workflows also fixed:** -- `.github/workflows/squad-heartbeat.yml` -- `.github/workflows/squad-repo-health.yml` -- `.github/workflows/squad-ci.yml` - -A new `.github/workflows/squad-workflow-lint.yml` CI job is added to lint both Squad's own workflows and the bundled templates on every PR and push to `dev`/`main`, so this class of regression is caught before it ships. diff --git a/.changeset/fix-yaml-escaping-skill.md b/.changeset/fix-yaml-escaping-skill.md deleted file mode 100644 index 3c2623fd9..000000000 --- a/.changeset/fix-yaml-escaping-skill.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix YAML escaping in skill command apm.yml generation - -Use `JSON.stringify()` for skill descriptions in generated apm.yml files -to properly escape quotes and newlines, preventing invalid YAML output. diff --git a/.changeset/forge-set-assignee.md b/.changeset/forge-set-assignee.md deleted file mode 100644 index f85757b0e..000000000 --- a/.changeset/forge-set-assignee.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor -"@bradygaster/squad-cli": patch ---- - -feat(platform): add `setAssignee()` to PlatformAdapter so assignee changes route through the platform abstraction (GitHub + ADO) instead of inline `gh`/`az` calls - -`GitHubAdapter.setAssignee` uses `gh issue edit --add/--remove-assignee`; `AzureDevOpsAdapter.setAssignee` sets `System.AssignedTo`. The watch command's `editWorkItem` now delegates assignee operations to the adapter, removing the hardcoded GitHub-vs-ADO branch. diff --git a/.changeset/forge-two-pass-adapter.md b/.changeset/forge-two-pass-adapter.md deleted file mode 100644 index 11208ce8e..000000000 --- a/.changeset/forge-two-pass-adapter.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor -"@bradygaster/squad-cli": patch ---- - -feat(platform): hydrate work-item `body` via `getWorkItem` and route two-pass scan through the adapter - -`WorkItem` now carries an optional `body`, populated by both `GitHubAdapter` (`gh issue view --json body`) and `AzureDevOpsAdapter` (`System.Description`). The watch `two-pass` capability hydrates actionable items through `adapter.getWorkItem` instead of a hardcoded `gh issue view`, so it works on Azure DevOps as well as GitHub. diff --git a/.changeset/help-externalize-internalize.md b/.changeset/help-externalize-internalize.md deleted file mode 100644 index 4d71e7b76..000000000 --- a/.changeset/help-externalize-internalize.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Add `externalize` and `internalize` to the top-level `squad --help` command list so they are discoverable (#1050). diff --git a/.changeset/init-prompt-copilot-member.md b/.changeset/init-prompt-copilot-member.md deleted file mode 100644 index eb3dc7a95..000000000 --- a/.changeset/init-prompt-copilot-member.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"@bradygaster/squad-cli": minor ---- - -Add @copilot team member prompt during `squad init` - -During interactive `squad init`, users are now prompted to add @copilot -as an autonomous team member. Answering yes adds the Coding Agent section -to team.md and copies copilot-instructions.md into the project. Non-interactive -mode skips silently with a hint to run `squad copilot enable` later. diff --git a/.changeset/init-vscode-default.md b/.changeset/init-vscode-default.md deleted file mode 100644 index a3a8a9b93..000000000 --- a/.changeset/init-vscode-default.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": minor ---- - -`squad init` now defaults to writing `"chat.newSession.defaultMode": "Squad"` into `.vscode/settings.json`, so new VS Code chat sessions open in Squad mode automatically. The edit is JSONC-aware (preserves comments, trailing commas, and existing keys), idempotent, and skipped when the key already exists. Pass `--no-vscode-default` to opt out entirely. diff --git a/.changeset/ink7-adaptation.md b/.changeset/ink7-adaptation.md deleted file mode 100644 index 626297867..000000000 --- a/.changeset/ink7-adaptation.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -chore: adapt CLI to ink 7.0.6 - -Updates the ink dependency from ^6.8.0 to ^7.0.6 and adapts keyboard handling in InputPrompt.tsx to ink 7's revised API: - -- key.meta no longer fires on bare Escape; guard updated to use key.escape -- useInput callbacks are now wrapped in reconciler.discreteUpdates(), which flushes React state synchronously at end of callback; rewrote Enter/paste handler to call setValue('') inside the flush rather than in a deferred timer - -Closes #1322, #1335. diff --git a/.changeset/label-color-palette.md b/.changeset/label-color-palette.md deleted file mode 100644 index 03da6e16a..000000000 --- a/.changeset/label-color-palette.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Assign unique colors to squad member labels from a curated palette using deterministic hashing of slugified agent names. diff --git a/.changeset/memory-tools-mcp-exposure.md b/.changeset/memory-tools-mcp-exposure.md deleted file mode 100644 index 7a6a30528..000000000 --- a/.changeset/memory-tools-mcp-exposure.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Expose memory.* tools (classify, write, search, promote, delete, audit) through the squad_state MCP server so agents can discover and call them. Also pin squad_state to user-level ~/.copilot/mcp-config.json for external `copilot -p` mode compatibility. diff --git a/.changeset/models-gpt56-fallback-ordering.md b/.changeset/models-gpt56-fallback-ordering.md deleted file mode 100644 index be69178b0..000000000 --- a/.changeset/models-gpt56-fallback-ordering.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -Prefer newest model per series in fallback chains, add GPT-5.6 IDs, fix Ralph free-model wording. - -Follow-up to #1444 (tamirdresher review comment — catalog follow-up): - -- `DEFAULT_FALLBACK_CHAINS.standard` and `MODELS.FALLBACK_CHAINS.standard` now lead with `claude-sonnet-5` (newest Sonnet; was `claude-sonnet-4.6`). Premium chains already led with `claude-opus-4.8` post-#1444. -- Adds `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna` to `MODEL_CATALOG` (tier: standard, githubCategory: powerful — mirrors `gpt-5.5`) and inserts them into the standard fallback chain. CLI-reachability validated 2026-07-13. -- Updates shipped template assets (`model-selection-reference.md`, `ralph-circuit-breaker.md`, model-selection SKILL files) to match the current runtime chains and remove "Free — unlimited" / multiplier-table wording that no longer applies under usage-based billing. -- Note: `MODELS.DEFAULT` (`claude-sonnet-4.6`) is intentionally unchanged — separate decision. -- Note: `DOCS_NAME_TO_ID` entries for gpt-5.6 in `cli/commands/models.ts` are deferred until PR #1445 merges. - -Refs #1080, #1183. diff --git a/.changeset/observer-hardening.md b/.changeset/observer-hardening.md deleted file mode 100644 index e71207b54..000000000 --- a/.changeset/observer-hardening.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -Harden squad observer change resolution against directory events, symlinks, and filesystem scan errors. diff --git a/.changeset/otel-resource-api-migration.md b/.changeset/otel-resource-api-migration.md deleted file mode 100644 index 8b6b1082f..000000000 --- a/.changeset/otel-resource-api-migration.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -Migrate OTel Resource API to `resourceFromAttributes` for compatibility with `@opentelemetry/resources` 2.x (replaces the removed `Resource` class constructor in `packages/squad-sdk/src/runtime/otel.ts` and `test/aspire-integration.test.ts`) \ No newline at end of file diff --git a/.changeset/preset-apply-wires-team-1288.md b/.changeset/preset-apply-wires-team-1288.md deleted file mode 100644 index 0f2df1982..000000000 --- a/.changeset/preset-apply-wires-team-1288.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch -"@bradygaster/squad-cli": patch ---- - -Fix #1288: `squad preset apply` now wires team.md, routing.md, and casting state - -`squad preset apply ` used to copy only the preset's agent charters into `.squad/agents/`. It left: - -- `.squad/team.md` `## Members` table empty -- `.squad/routing.md` with no Work Type rows for the preset agents -- `.squad/casting/registry.json`, `history.json`, and `policy.json` not created - -Net result: the coordinator's mode-switch check saw an empty `## Members` table and treated every session as **Init Mode**, proposing to re-scaffold a team the user already applied — defeating the entire purpose of presets. - -This change adds a new merge-friendly scaffold module (`packages/squad-sdk/src/presets/scaffold.ts`) that, after `applyPreset` copies the charters, wires the preset agents into: - -- **team.md** `## Members` — creates the file from scratch if missing, or merges new rows into an existing `## Members` table while preserving the surrounding content (Coordinator section, Project Context, etc.). Idempotent: a second apply does not duplicate rows. -- **routing.md** `## Work Type → Agent` — creates from scratch or appends new rows after the existing routing table. Each preset agent becomes `| | | — |`. -- **casting/registry.json** — merges new agents into an existing registry without clobbering pre-existing entries. Universe = `preset:` so future casts can distinguish preset-provided agents. -- **casting/history.json** — appends a preset-application snapshot and a universe_usage_history entry. -- **casting/policy.json** — created with sensible defaults only if missing; never overwrites an existing policy. - -Failure modes: - -- Agents with `status: 'error'` in the per-agent results (e.g., source dir missing) are excluded from the wiring step. -- Agents with `status: 'skipped'` (already exist in target) ARE wired into team.md/registry so the team reflects user intent. -- If the scaffolding itself throws (e.g., disk error), a synthetic error result is appended to the return value so the CLI can surface it; per-agent install results are preserved. - -Out of scope (tracked separately): deduplicating these writers with the equivalent fresh-write versions in `packages/squad-cli/src/cli/core/cast.ts`. A future refactor can move both call sites to the shared SDK module. - -Test coverage in `test/presets.test.ts`: -- `wires preset agents into team.md ## Members (#1288)` -- `merges preset agents into an existing team.md without duplicating rows (#1288)` — includes idempotency assertion -- `writes casting registry.json, history.json, and policy.json (#1288)` -- `appends routing rows for preset agents to routing.md (#1288)` - -Closes #1288 diff --git a/.changeset/reasoning-effort.md b/.changeset/reasoning-effort.md deleted file mode 100644 index 54ed26a13..000000000 --- a/.changeset/reasoning-effort.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor ---- - -Add reasoning effort support to agent spawning pipeline - -Thread `reasoningEffort` through the full agent lifecycle: - -- **Charter**: Parse `**Reasoning Effort:**` from `## Model` section in `charter.md` -- **Config**: Read/write `defaultReasoningEffort` and `agentReasoningEffortOverrides` in `.squad/config.json` -- **Resolution**: New `resolveReasoningEffort()` with layered priority (per-agent config override > global config > spawn override > charter preference > undefined) -- **Clamping**: New `clampReasoningEffort()` caps effort to model's max supported level -- **Lifecycle**: `SpawnAgentOptions.reasoningEffortOverride` passes through to `SquadSessionConfig` -- **Fan-Out**: `AgentSpawnConfig.reasoningEffortOverride` passes through to `createSession()` -- **Builders**: `defineAgent()` and `defineDefaults()` accept `reasoningEffort: "low" | "medium" | "high" | "xhigh"` -- **Template**: Updated charter template with `**Reasoning Effort:** auto` -- **Validation**: `"auto"` and invalid values are normalized to `undefined` at parse time diff --git a/.changeset/refresh-model-catalog-1080.md b/.changeset/refresh-model-catalog-1080.md deleted file mode 100644 index 8ed6623f6..000000000 --- a/.changeset/refresh-model-catalog-1080.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor ---- - -Refresh the model catalog to GitHub Copilot CLI-reachable IDs and prune dead fallback IDs. - -- MODEL_CATALOG now lists only currently-valid, CLI-reachable models (13 total) and drops removed IDs (gpt-4.1, gpt-5, gpt-5.1*, gpt-5.2*, gemini-3-pro-preview, claude-sonnet-4, claude-opus-4.5, claude-opus-4.6-fast). -- Fallback chains (runtime constants + SDK defaults), schema defaults, and the economy-mode map are updated to real IDs only, fixing routing that pointed at models no longer offered. -- Adds an optional `githubCategory` cost-ceiling field (lightweight/versatile/powerful) to `ModelInfo`, sourced from the models API `model_picker_category`. This is a separate cost axis from the existing quality `tier`; the two are intentionally not conflated. -- No hardcoded per-token USD pricing is added for new entries, and no `included`/zero-credit flag is introduced. -- `validateConfigDetailed` now emits a non-blocking `warnings` entry when `config.models.defaultModel` is a non-empty string that is not present in the current `MODEL_CATALOG`, helping users catch stale model IDs in config files without blocking config load. - -Refs #1080, #1183. diff --git a/.changeset/registry-subcommand.md b/.changeset/registry-subcommand.md deleted file mode 100644 index 08be83809..000000000 --- a/.changeset/registry-subcommand.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -"@bradygaster/squad-cli": minor -"@bradygaster/squad-sdk": minor ---- - -Add `squad registry add/list/remove` for discovery-only peer squads (no inheritance) - -The existing `squad upstream add` triggers inheritance (skills/decisions/wisdom flow from the other squad into yours at session start). For peer relationships where you want discovery and delegation but NOT inheritance, you previously had to hand-edit `.squad/squad-registry.json` — the `squad discover` error message even told you to "create a squad-registry.json" manually. - -This adds a real CLI surface for the registry, symmetric to `squad upstream`: - -- `squad registry add ` — registers a peer, validates its manifest, refuses on duplicate name -- `squad registry list` — shows all registered peers -- `squad registry remove ` — removes by name - -It also fixes a subtle path-semantics confusion: `readManifest()` now accepts BOTH `repo-root` and `repo-root/.squad` paths (the docs/SKILL showed the `.squad`-suffixed form, but the code previously joined `.squad/manifest.json` onto whatever you gave it, so the suffixed form silently failed). The SDK helpers (`readSquadRegistry`, `writeSquadRegistry`, `addRegistryEntry`, `removeRegistryEntry`) are exported for tooling. - -The `cross-squad` SKILL and the `squad discover` empty-state hint are updated to reflect the new command. - -Closes #1290. diff --git a/.changeset/release-0.11.0.md b/.changeset/release-0.11.0.md deleted file mode 100644 index 225502b45..000000000 --- a/.changeset/release-0.11.0.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-cli": minor -"@bradygaster/squad-sdk": minor ---- - -Stage the 0.11.0 release by cleaning the committed package versions and publishing the 0.11.0 changelog notes. diff --git a/.changeset/rename-dotnet-aspire-to-aspire.md b/.changeset/rename-dotnet-aspire-to-aspire.md deleted file mode 100644 index c083185a4..000000000 --- a/.changeset/rename-dotnet-aspire-to-aspire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Rename user-facing Aspire terminology in CLI help text and command output. Aspire is a standalone OTLP dashboard, not limited to .NET apps. diff --git a/.changeset/rename-hire-to-cast.md b/.changeset/rename-hire-to-cast.md deleted file mode 100644 index 562014ed6..000000000 --- a/.changeset/rename-hire-to-cast.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": minor ---- - -Rename `hire` command to `cast` in CLI help and documentation. The `hire` command continues to work as a silent alias (like `cls`/`clear` in PowerShell) — no deprecation, no warnings, it just does the same thing. All user-facing text now presents `cast` as the canonical verb because we're casting agents, not hiring humans. diff --git a/.changeset/slim-squad-agent-md-phase1.md b/.changeset/slim-squad-agent-md-phase1.md deleted file mode 100644 index 1b4b05ebf..000000000 --- a/.changeset/slim-squad-agent-md-phase1.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor -"@bradygaster/squad-cli": minor ---- - -Slim squad.agent.md by extracting 3 sections to satellite skills (closes #1308 phase 1) - -## Symptom - -`squad.agent.md` is loaded as the agent prompt at every Copilot session start. As of v0.10.0-insider.1 it sits at **81 KB / 1,137 lines** and was steadily growing — the v0.10 stabilisation pass alone added +10.6 KB / +114 lines. Every byte of that file is paid at every session. - -## Phase 1 fix (this PR) - -Extract three **low-cross-reference, high-byte** sections into satellite skills the coordinator loads on demand via the `skill` tool. Same pattern that already worked for `cross-squad-communication` (#1295). - -| Extracted to satellite skill | Bytes saved in main file | -|---|---| -| `coordinator-init-mode` (Init Mode Phase 1 + Phase 2) | 5.4 KB | -| `coordinator-source-of-truth` (Source of Truth Hierarchy table) | 4.4 KB | -| `coordinator-response-mode` (Response Mode Selection + Lightweight Spawn Template) | 3.9 KB | - -### Result - -- `squad.agent.md`: **81 KB → 70 KB** (-13.9%, -140 lines) -- Three new bundled skills (`coordinator-source-of-truth`, `coordinator-response-mode`, `coordinator-init-mode`) installed alongside the existing 16 — total 19 skills at `.github/skills/` -- Behaviour unchanged: each removed section is replaced with a stub that names the trigger condition and instructs the coordinator to `skill(coordinator-X)` before acting - -## Stubs left in `squad.agent.md` - -Each extracted section keeps a short stub (4-12 lines) so the coordinator still knows the section exists and what triggers it. The full algorithm/table/template lives in the satellite skill. - -Example (Source of Truth, was 30+ lines, now 9): - -```markdown -## Source of Truth Hierarchy - -Squad files split into **authoritative** (governance, roster, charters — static) and -**derived / append-only** (decisions, history, logs — runtime-owned). The four -governing rules: - -1. **`squad.agent.md` wins** any conflict with another file. -2. **Append-only files** are never retroactively edited. -3. **Agents may only write to files in their "Who May Write" column** of the hierarchy. -4. **Only Squad (Coordinator)** records accepted decisions in `.squad/decisions.md`. - -**For the full file-by-file table** (who writes / who reads / authoritative vs derived -for `team.md`, `decisions.md`, `routing.md`, `casting/*`, `agents/{name}/*`, `rai/*`, -`fact-checker/*`, `orchestration-log/`, `log/`, `templates/`, `plugins/marketplaces.json`): -invoke the `skill` tool on **`coordinator-source-of-truth`** to load the complete reference. -``` - -## What is NOT extracted (intentional) - -These sections stay in `squad.agent.md` because they're loaded on EVERY prompt and / or are load-bearing for first-touch behaviour: - -- **Team Mode + state-backend handshake + HARD RULE** (#1306) — handshake must fire before any state write -- **Routing table** — the trigger table for every user prompt -- **Hard trigger — keyword-to-skill match** paragraph (#1307) — load-bearing for the spawn-routing fix -- **How to Spawn an Agent** — referenced from every routing-table action -- **Coordinator Identity / Personal Squad / Memory Governance Tools** — frequently re-read inline - -Follow-up issues will tackle these one at a time if/when needed. - -## Wired changes - -- New: `.squad/skills/coordinator-{source-of-truth,response-mode,init-mode}/SKILL.md` are the **canonical source files** kept in the squad repo itself (the same convention every other bundled skill follows). At install/upgrade time they are copied to `.github/skills/coordinator-{x}/SKILL.md` in the user's repo — that's the Copilot CLI custom-skills location adopted by #1304 (formerly `.copilot/skills/`). -- Mirrored at build time to `packages/squad-cli/templates/skills/` and `packages/squad-sdk/templates/skills/` via `scripts/sync-skill-templates.mjs` (same path every other manifest skill takes). -- `MANIFEST_SKILL_NAMES` in `packages/squad-sdk/src/config/init.ts` grows by 3 entries (now 19) -- `TEMPLATE_MANIFEST` in `packages/squad-cli/src/cli/core/templates.ts` grows by 3 entries with `../.github/skills/` destinations (matching the post-#1304 install location) -- `.squad-templates/squad.agent.md` replaces each extracted section with a stub -- 4 mirrored copies re-synced via `scripts/sync-templates.mjs --sync` - -## Tests - -- `test/init.test.ts > should install every manifest-curated skill (regression: bradygaster/squad#1289, #1264)` — already imports `MANIFEST_SKILL_NAMES` and iterates it, so it automatically asserts the 3 new skills install. **287/287 tests pass.** -- Smoke test: fresh `squad init` produces 19 skills at `.github/skills/`, `squad.agent.md` is 70 KB. - -## Composability - -Disjoint from all other open PRs. Pure file moves + a few line replacements + 3 manifest entries. - -## Follow-ups (separate PRs) - -The remaining high-bloat sections in `squad.agent.md` are stickier and need careful design to extract: - -- **Routing table** (9.2 KB) — needed on every prompt; can't be lazy-loaded as-is. May be slimmable by moving the action-cell verbiage into satellite skills (the trigger table stays, the action prose moves). -- **Team Mode** (5.5 KB) — contains the state-backend handshake, which MUST fire on every session. Maybe extract the worktree-awareness / casting-migration sub-sections. -- **How to Spawn an Agent** (3.2 KB) — could extract the role-emoji catalog. - -Target: get the coordinator down to **~45 KB** in 2-3 follow-up PRs. diff --git a/.changeset/spawn-backend-followups-1377.md b/.changeset/spawn-backend-followups-1377.md deleted file mode 100644 index 590d9d2ed..000000000 --- a/.changeset/spawn-backend-followups-1377.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -Fix #1377 follow-ups: spawn-backend fallback, slot-leak guards, timeouts, prompt sanitization - -Addresses the six deferred review items from the #1385 review (sub-sessions in the Copilot App). All are hardening fixes to the spawn coordinator (`packages/squad-sdk/src/coordinator/`) plus a template probe-order correction. - -**Blockers** - -1. **App→task fallback (`fan-out.ts`).** When the platform `SpawnBackend` (e.g. App sub-sessions) returns `success: false` — concurrency cap, unavailable tool, transient error — `spawnSingle()` no longer throws and fails the agent. It emits a `session.spawn_fallback` event and falls through to the direct `createSession` path, honoring the template contract ("if `create_session` fails, retry with `task`"). The direct path is now extracted into a shared `spawnViaCreateSession()` helper. - -2. **Concurrency slot leak (`fan-out.ts`).** `registerSpawnRelease()` now (a) treats `completed` as a terminal status (previously only `idle`/`error`/`destroyed` released the slot), and (b) installs an unref'd max-lifetime safety timer (default 1h) that force-releases the slot if a silently-crashed sub-session emits no terminal event. The timer is cleared on normal release. - -3. **Template detection-order drift.** Re-synced the canonical `.squad-templates/squad.agent.md` probe order (`create_session` → `runSubagent` → `task` → inline) to all mirror copies, which had `task` and `runSubagent` swapped. - -**Risks** - -4. **Prompt-injection hardening (`fan-out.ts`).** `buildInitialPrompt()` now runs caller-supplied `task`/`context` through `sanitizePromptValue()` (defense-in-depth): strips control characters, neutralizes forged `**Marker:**` headers, and caps length. Not a complete prompt-injection defense, but it stops trivial structural-marker spoofing. - -5. **`createSession` timeout (`spawn-backend.ts`).** Both backends wrap the injected `createSession` call in a timeout (`createSessionTimeoutMs`, default 60s, 0 disables) so a hung factory cannot pin `pendingSpawnCount` / a concurrency slot forever. `SessionSpawnBackend`'s `finally` still decrements the pending counter on timeout. - -6. **Honest `isAvailable()` (`spawn-backend.ts`).** Both backends previously returned `true` unconditionally. They now return a real heuristic (`typeof createSession === 'function'`) and accept an injectable `availabilityCheck` predicate via options. - -Adds vitest coverage for the fallback path, `completed`-status release, the safety-timeout release, both createSession timeouts, prompt sanitization, and `isAvailable()`. diff --git a/.changeset/spoiler-aware-casting.md b/.changeset/spoiler-aware-casting.md deleted file mode 100644 index f352e57a8..000000000 --- a/.changeset/spoiler-aware-casting.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -"@bradygaster/squad-cli": patch -"@bradygaster/squad-sdk": patch ---- - -docs(casting): make agent name allocation spoiler-aware - -Agent names are drawn from fictional universes as easter eggs and are -shown in plain text across `team.md`, prompts, logs, and generated files. -Previously the casting rules optimized only for theme fit and uniqueness, -so a freshly set-up squad could surface a character name that encodes a -future title, role, transformation, or fate — spoiling the source -material for a user who is only part-way through it. - -This change updates the canonical naming guidance so that name allocation -now: - -- Prefers the name a character has when first introduced. -- Avoids titles or epithets a character only earns later. -- Avoids names that reveal a transformation, fate, hidden identity, or - later reveal. -- Falls back to a safer character from the same universe when unsure. -- Keeps existing name mappings stable — only the next/new allocation - picks a different spoiler-safe character, so already-named agents are - never renamed. - -Updates the `squad.agent.md` name-allocation rule and the -`casting-reference.md` reference (new "Spoiler Awareness" section), -propagated to all template copies via `scripts/sync-templates.mjs`. diff --git a/.changeset/standalone-cross-build-fix.md b/.changeset/standalone-cross-build-fix.md deleted file mode 100644 index 3960c9935..000000000 --- a/.changeset/standalone-cross-build-fix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Fix cross-building a POSIX standalone bundle from a Windows host. The builder extracted the entire Node.js runtime archive, which contains symlinks (`bin/npm`, `bin/npx`, `bin/corepack`) that Windows cannot create — so building a `linux` or `darwin` bundle from Windows failed with `Can't create ... Invalid argument`. It now extracts only the `node` binary it actually ships, and reports the underlying tar error when extraction fails. diff --git a/.changeset/standalone-mcp-spec-1593.md b/.changeset/standalone-mcp-spec-1593.md deleted file mode 100644 index c39097407..000000000 --- a/.changeset/standalone-mcp-spec-1593.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Write an npx-free `squad_state` MCP spec when Squad runs from a standalone bundle. Previously `squad init` and `squad upgrade` always emitted `npx -y @bradygaster/squad-cli@ state-mcp` into `.mcp.json`, and probed registry.npmjs.org to pick the version — so a machine installed without npm access still ended up with an MCP entry it could not launch. The resolver now detects a bundle via `SQUAD_STANDALONE_HOME` and points at that bundle's launcher by absolute path, short-circuiting before the registry probe. diff --git a/.changeset/standalone-prefer-exe.md b/.changeset/standalone-prefer-exe.md deleted file mode 100644 index 0c5c83985..000000000 --- a/.changeset/standalone-prefer-exe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-cli": patch ---- - -Prefer `squad.exe` over `squad.cmd` when writing the `squad_state` MCP spec from a standalone bundle on Windows. Since the fix for CVE-2024-27980 Node refuses to spawn a `.cmd` without `shell: true`, so an MCP client that spawns the command directly would fail to start the server. Windows bundles now ship a real `squad.exe`, and the resolver picks it first. diff --git a/.changeset/sub-sessions-spawn-backend.md b/.changeset/sub-sessions-spawn-backend.md deleted file mode 100644 index b9d1c7f9e..000000000 --- a/.changeset/sub-sessions-spawn-backend.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor -"@bradygaster/squad-cli": minor ---- - -Add sub-session spawn backend for Copilot App integration - -Spawn cast members as sub-sessions when running in the Copilot App (Tauri desktop), -giving users richer UX with each squad member visible in the left navigation: - -- **SpawnBackend interface**: Thin abstraction with `TaskSpawnBackend` (CLI) and - `SessionSpawnBackend` (App) implementations -- **Detection**: `detectSpawnBackend()` probes for `create_session` tool availability - at coordinator startup; `detectSpawnPlatform()` returns the platform type -- **Session naming**: `"{Name} {verb}ing {noun}"` convention with 40-char limit - via `truncateSessionName()` and `buildSessionName()` helpers -- **Concurrency cap**: Maximum 4-5 simultaneous sub-sessions with queuing -- **Depth limit**: No sub-sub-sessions — max depth 1 -- **Fallback**: Graceful degradation to `task` tool if `create_session` fails -- **Zero CLI impact**: Behavior unchanged when `create_session` is absent -- **Template updates**: `squad.agent.md` and `spawn-reference.md` updated with - App dispatch mechanism, platform detection probe, and sub-session rules diff --git a/.changeset/types-node-25.md b/.changeset/types-node-25.md deleted file mode 100644 index 0dde9d78e..000000000 --- a/.changeset/types-node-25.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch -"@bradygaster/squad-cli": patch ---- - -Bump @types/node from ^22.0.0 to ^25.9.3 in cli and sdk packages. Removes a no-longer-needed @ts-expect-error directive in cli-entry.ts now that process.emit is properly typed. \ No newline at end of file diff --git a/.changeset/typescript-6.md b/.changeset/typescript-6.md deleted file mode 100644 index ae8a4fb80..000000000 --- a/.changeset/typescript-6.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch -"@bradygaster/squad-cli": patch ---- - -chore: upgrade to TypeScript 6 (closes #1325, #1328, #1334) - -- Bumps `typescript` devDependency from `^5.7.0` to `^6.0.3` in packages/squad-sdk, packages/squad-cli, and the root workspace. -- Bumps `@typescript-eslint/parser` in root from `^8.57.1` to `^8.61.1` to align with the already-present `^8.61.1` plugin (v8.61.1 peer-deps cover `typescript >=4.8.4 <6.1.0`). -- Adds `"types": ["node"]` to `compilerOptions` in `packages/squad-cli/tsconfig.json` and `packages/squad-sdk/tsconfig.json`; TypeScript 6 no longer auto-injects Node globals without an explicit `types` declaration. diff --git a/.changeset/vitest-4-upgrade.md b/.changeset/vitest-4-upgrade.md deleted file mode 100644 index 0eac58616..000000000 --- a/.changeset/vitest-4-upgrade.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch -"@bradygaster/squad-cli": patch ---- - -Bump vitest from v3 to v4 alongside @vitest/coverage-v8 v4 to resolve peer-dep mismatch. Both packages now align at ^4.1.9 across root and all sample workspaces. No API adaptations required — vitest 4's spying rewrite is backwards-compatible for the mock/spyOn patterns used in this codebase. diff --git a/.changeset/vscode-jsonrpc-9-sdk.md b/.changeset/vscode-jsonrpc-9-sdk.md deleted file mode 100644 index 7ccaa4ae9..000000000 --- a/.changeset/vscode-jsonrpc-9-sdk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@bradygaster/squad-sdk": patch ---- - -Sync lockfile for the vscode-jsonrpc 8→9 bump in packages/squad-sdk. v9 adds the missing `exports` field that v8 lacked, making `vscode-jsonrpc/node` resolvable under strict ESM without `patch-esm-imports.mjs` runtime workarounds. \ No newline at end of file diff --git a/.changeset/wire-cross-squad-communication-skill.md b/.changeset/wire-cross-squad-communication-skill.md deleted file mode 100644 index 898af4c20..000000000 --- a/.changeset/wire-cross-squad-communication-skill.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -"@bradygaster/squad-sdk": minor -"@bradygaster/squad-cli": minor ---- - -Add **cross-squad-communication** as a built-in skill (companion to cross-squad) - -The merged registry work (#1291) added `squad registry add/list/remove` and the `cross-squad/SKILL.md` for discovery. But discovery is only half the story — once a peer squad is known, agents need to know **how** to actually exchange information with it (sync CLI sessions, async git-based requests, issue-based delegation). - -This change ports `cross-squad-communication` from [tamirdresher/squad-skills](https://github.com/tamirdresher/squad-skills/tree/main/plugins/cross-squad-communication) into Squad's bundled skills so a fresh `squad init` produces a coordinator that already knows the four communication patterns. The plugin was validated against two production squad instances (one GitHub-hosted, one Azure DevOps-hosted) before being ported. - -**What this skill teaches** - -| Pattern | When to use | -|---|---| -| Pattern 0: Synchronous CLI session | Quick knowledge queries — spawn `copilot -C ` with the prompt text via `-p (Get-Content $promptFile -Raw)` | -| Pattern 1: Read-only metadata scan | "What's the architecture of squad X?" — read their `team.md` / `decisions.md` directly | -| Pattern 2: Async git-based request/response | Long-running work, PR reviews, multi-cycle tasks. Request files in `.squad/cross-squad/requests/`, response files in `.squad/cross-squad/responses/`. | -| Pattern 3: Issue-based delegation | GitHub-hosted repos — `gh issue create` with `squad:cross-squad` label as the message bus | - -Plus: decision tree for choosing the right pattern, anti-patterns, request/response YAML format, and validation status. - -**Changes** - -- New `.squad/skills/cross-squad-communication/SKILL.md` (canonical source). `sync-skill-templates.mjs` (prebuild) propagates to both `packages/squad-cli/templates/skills/` and `packages/squad-sdk/templates/skills/`. -- `MANIFEST_SKILL_NAMES` in `packages/squad-sdk/src/config/init.ts` grows by 1 entry: `cross-squad-communication`. Now 11 entries. -- `cross-squad/SKILL.md` (the registry-aware skill from #1291) gets a one-paragraph "Companion skill" note at the top pointing to `cross-squad-communication` for protocol details. The two skills are designed to be used together: `cross-squad` answers "who?" (discovery via registry), `cross-squad-communication` answers "how?" (the 4 communication patterns). - -**Genericization** - -The original plugin documented validation against specific internal Microsoft repositories. Examples in this version use generic names (`platform-squad`, `research-squad`, etc.) so they're meaningful to all upstream users. The protocol mechanics are unchanged. The frontmatter `source:` attributes the port to `tamirdresher/squad-skills`. - -**Test coverage** - -New `test/init.test.ts > should install cross-squad-communication skill (companion to cross-squad — #5)`: asserts the SKILL.md ends up at `.copilot/skills/cross-squad-communication/SKILL.md` after `initSquad()` and that the content contains the expected pattern names. 26/26 init tests pass; `npm run lint` clean. - -**Composition with #1291** - -```bash -# 1. Init produces a squad that already knows both skills -squad init - -# 2. Register a peer squad (#1291) -squad registry add ../peer-squad-repo - -# 3. Ask the coordinator: "what are the team members of the peer squad?" -# → The coordinator now has cross-squad-communication's Pattern 1 in scope -# and knows to read team.md from the registered peer -``` - -**Note on overlap with #1292** - -PR #1292 (skills bundling fix) adds `squad-commands`, `squad-version-check`, `tiered-memory`, `iterative-retrieval`, `reflect`, and `cross-squad` to `MANIFEST_SKILL_NAMES`. That PR and this one both modify the same array but add disjoint entries. When both merge, the manifest grows to 15 entries (10 base + 4 from #1292 + 1 from here). Either PR can land first. diff --git a/workflows/squad.md b/workflows/squad.md index 25ec85943..564d56cda 100644 --- a/workflows/squad.md +++ b/workflows/squad.md @@ -50,7 +50,7 @@ safe-outputs: expires: 14d create-issue: labels: [squad] - max: 50 + max: 75 add-comment: max: 20 --- @@ -2391,6 +2391,16 @@ Post a brief acknowledgment using the `add-comment` safe-output: ##### Step 1: Validate Preconditions +**Label pre-flight (all activations):** + +Before creating any issues, ensure required labels exist in the repository: +1. Check if the `squad` label exists using `gh label list --search squad`. +2. If missing, create it: `gh label create squad --description "Squad-managed work item" --color 0075ca` +3. For each agent label needed (`squad:{name}`), check and create if missing: + `gh label create "squad:{name}" --description "Assigned to {name}" --color e4e669` + +This prevents safe-output failures due to missing labels in newly-onboarded repos. + **If a phase is specified (`/squad plan activate phase {N}`):** 1. **Check phase acceptance.** Search for the latest @@ -2439,6 +2449,32 @@ Post a brief acknowledgment using the `add-comment` safe-output: > each `create-issue` call. Do not hardcode, increment, or guess issue numbers > based on repository state or previous creations. +##### Transient Failure Handling + +> If a `create-issue` or `add-comment` call returns a 5xx error or timeout: +> +> 1. **Retry once** — repeat the identical safe-output call. +> 2. **If retry fails** — STOP and report per Hallucination Guard rules above. +> 3. **Do NOT retry on 4xx errors** — these indicate a real problem (label +> missing, max limit reached, malformed body). Report immediately. + +##### Output Budget Awareness + +Before beginning issue creation, count the total issues to create (epics + +tasks for the target scope): + +- **≤ 30 issues:** Proceed normally with standard issue bodies. +- **31–50 issues:** Use MINIMAL bodies — scope sentence + AC bullets only. + Omit the `---` footer and `> /squad plan activate` attribution line. +- **> 50 issues:** STOP and post a comment: + *"This plan requires {N} issues, which exceeds the safe single-run budget. + Use `/squad plan activate phase {N}` to activate one phase at a time."* + Then end the run. Do NOT attempt partial creation. + +> **Recommended:** For plans with more than 3 epics or 15 total tasks, +> prefer `/squad plan activate phase {N}` over full activation. Phase-by-phase +> is more reliable and stays within output budget limits. + ##### Step 2: Create GitHub Issues — Full Hierarchy **When a phase is specified:** Filter the implementation plan to only include @@ -2507,6 +2543,9 @@ its issue number instead of creating a duplicate. ``` - **Parent relationship:** Add as a sub-issue of the root intent issue (native GitHub sub-issues). The root intent issue is the triggering issue. + If the sub-issue API fails (404, 422, or permission error), fall back + gracefully — the `Parent: #{N}` line in the body provides traceability. + Do NOT fail activation on sub-issue relationship failures. - **Milestone:** Assign to the corresponding GitHub milestone created in 2a. Create epics in dependency order. @@ -2549,6 +2588,8 @@ phase-specific), use the `create-issue` safe-output: ``` - **Parent relationship:** Add as a sub-issue of the EPIC issue (NOT the root intent issue). Tasks are children of their epic, not of the root. + If the sub-issue API fails, fall back gracefully — the `Parent: #{N}` line + in the body provides traceability. Continue creating remaining issues. - **Milestone:** Assign to the same milestone as the parent epic. **Size handling:** If a GitHub Project is configured with a Size single-select