Repository navigation
feat(sdk): bundle cross-squad-communication skill (#5 cross-squad protocols) - #1295
Conversation
🛫 PR Readiness Check
PR Scope: 📦🔧 Mixed (product + infrastructure)
|
| Status | Check | Details |
|---|---|---|
| ❌ | Single commit | 4 commits — consider squashing before review |
| ✅ | Not in draft | Ready for review |
| ✅ | Branch up to date | Up to date with dev |
| ❌ | Copilot review | No Copilot review yet — it may still be processing |
| ✅ | Changeset present | Changeset file found |
| ✅ | Scope clean | |
| ✅ | No merge conflicts | No merge conflicts |
| ✅ | Copilot threads resolved | 0 active Copilot thread(s) resolved (6 outdated skipped) |
| ❌ | CI passing | 7 check(s) still running |
Files Changed (11 files, +1395 −14)
| File | +/− |
|---|---|
.changeset/wire-cross-squad-communication-skill.md |
+53 −0 |
.squad/skills/cross-squad-communication/SKILL.md |
+399 −0 |
.squad/skills/cross-squad/SKILL.md |
+2 −0 |
packages/squad-cli/src/cli/core/templates.ts |
+6 −0 |
packages/squad-cli/templates/skills/cross-squad-communication/SKILL.md |
+399 −0 |
packages/squad-cli/templates/skills/cross-squad/SKILL.md |
+2 −0 |
packages/squad-sdk/src/config/init.ts |
+1 −0 |
packages/squad-sdk/templates/skills/cross-squad-communication/SKILL.md |
+399 −0 |
packages/squad-sdk/templates/skills/cross-squad/SKILL.md |
+2 −0 |
test/cross-squad.test.ts |
+114 −0 |
test/init.test.ts |
+18 −14 |
Total: +1395 −14
This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.
🟠 Impact Analysis — PR #1295Risk tier: 🟠 HIGH 📊 Summary
🎯 Risk Factors
📦 Modules Affectedroot (1 file)
squad-cli (3 files)
squad-sdk (3 files)
squad-state (2 files)
tests (2 files)
This report is generated automatically for every PR. See #733 for details. |
🏗️ Architectural Review
Automated architectural review — informational only. |
|
There was a problem hiding this comment.
Pull request overview
This PR bundles a new built-in skill, cross-squad-communication, so freshly initialized squads have documented protocols for communicating with peer squads (beyond discovery), and wires it into the SDK’s init manifest alongside a regression test and changeset.
Changes:
- Add the new
cross-squad-communicationskill (canonical in.squad/skills/, mirrored into both CLI and SDK template skill directories). - Register
cross-squad-communicationinMANIFEST_SKILL_NAMESsoinitSquad()installs it into.copilot/skills/. - Add an init regression test plus a changeset describing the new bundled skill.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
test/init.test.ts |
Adds regression test asserting initSquad() installs cross-squad-communication. |
packages/squad-sdk/src/config/init.ts |
Adds cross-squad-communication to the SDK init skill manifest. |
.squad/skills/cross-squad-communication/SKILL.md |
Canonical documentation for cross-squad communication protocols/patterns. |
.squad/skills/cross-squad/SKILL.md |
Adds a companion-skill note pointing from discovery (cross-squad) to communication protocols. |
packages/squad-sdk/templates/skills/cross-squad-communication/SKILL.md |
SDK template mirror of the new skill. |
packages/squad-sdk/templates/skills/cross-squad/SKILL.md |
SDK template mirror updated with the companion-skill note. |
packages/squad-cli/templates/skills/cross-squad-communication/SKILL.md |
CLI template mirror of the new skill. |
packages/squad-cli/templates/skills/cross-squad/SKILL.md |
CLI template mirror updated with the companion-skill note. |
.changeset/wire-cross-squad-communication-skill.md |
Declares minor bumps for SDK/CLI and documents the bundled skill addition. |
| 'agent-collaboration', | ||
| 'squad-commands', | ||
| 'squad-version-check', | ||
| 'cross-squad-communication', | ||
| ] as const; |
| ## Context | ||
| When an organization runs multiple Squad instances (e.g., platform-squad, frontend-squad, data-squad), those squads need to discover each other, share context, and hand off work across repository boundaries. This skill teaches agents how to coordinate across squads without creating tight coupling. | ||
|
|
||
| > **Companion skill — for protocol details:** `cross-squad-communication/SKILL.md` covers the four communication patterns (sync CLI, async git-based, issue-based) once a peer squad is discovered via the registry below. This skill answers "who?" — the companion answers "how?". |
|
|
||
| When multiple repositories each have their own Squad (AI team), they need to exchange information: knowledge queries, PR reviews, task delegation, and dependency analysis. Each squad has its own agents, MCP tools, and issue tracker — there is no shared runtime. | ||
|
|
||
| > **Companion skill — read first:** `cross-squad/SKILL.md` covers **discovery** of peer squads via `squad registry add/list/remove`. This skill picks up after a peer is known and covers the **communication protocols** themselves (sync CLI, async git, issue-based). The two are designed to be used together. |
|
|
||
| --- | ||
|
|
||
| ### Pattern 4: Cross-Repo Dependency Scan |
| description: "Protocol for sending queries, delegating tasks, and sharing context between independent Squad instances across different repositories" | ||
| domain: "multi-repo coordination" | ||
| confidence: "medium" | ||
| source: "Ported from tamirdresher/squad-skills (plugins/cross-squad-communication, validated against two production squad instances). Companion to the registry-aware cross-squad skill — this one teaches the actual communication protocols once a peer is discovered." |
|
|
||
| ## Validation Status | ||
|
|
||
| Originally designed and validated against two production squad instances (a GitHub-hosted platform squad with ~10 agents and an Azure DevOps-hosted automation squad with ~4 agents). The protocols are platform-agnostic; the examples in this document use generic names so you can substitute your own repos. |
…numbering + honest source/validation Five reviewer follow-ups on github#1295: 1. MANIFEST_SKILL_NAMES added 'cross-squad-communication' but TEMPLATE_MANIFEST didn't — 'squad upgrade' would skip the skill even though 'squad init' installed it. Added the missing entry to TEMPLATE_MANIFEST so upgrade syncs it like every other manifest skill. (Same drift bug pattern noted on github#1292/github#1303.) 2-3. Both SKILL.md files (companion 'cross-squad' and full 'cross-squad-communication') said the skill covers 'the four communication patterns (sync CLI, async git-based, issue-based)' but only listed three — Pattern 1 (read-only knowledge query) was missing from the intro list. Rewrote both intro lines to spell out all four: Pattern 0 (sync CLI), Pattern 1 (read-only), Pattern 2 (git-based async), Pattern 3 (issue-based). 4. The doc had 'Pattern 4: Cross-Repo Dependency Scan' which broke the 'four numbered patterns 0-3' framing — Pattern 4 isn't a communication protocol, it's a one-off analysis utility for discovering how two repos relate. Moved it to a clearly labeled '### Appendix' section with a note explaining why it's not a numbered pattern. 5. Frontmatter 'source:' claimed the skill was 'validated against two production squad instances' but the Validation Status section said Patterns 2 and 3 were 'untested end-to-end'. Reworded 'source:' to acknowledge that only Pattern 0 (and partially Pattern 1) are end-to-end-validated; Patterns 2/3 are documented from design and need live validation before production use. Also softened the same overclaim in the Validation Status prose (replaced 'validated against two production' with 'drafted against two prototype' + explicit acknowledgement that 2/3 are design-only). All 3 mirrored copies of cross-squad-communication/SKILL.md and 3 copies of cross-squad/SKILL.md kept in sync (canonical = .squad/, mirrors = packages/squad-cli/templates/, packages/squad-sdk/templates/). Verified: 31/31 init + builtin-skills tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
All 5 reviewer threads addressed in commit f5415a2:
All 3 mirrors (canonical + cli/templates + sdk/templates) kept in sync. 31/31 init + builtin-skills tests pass locally. |
|
Follow-up commit cb6098b — fixes 5 CLI-correctness bugs in the SKILL.md that another squad caught while trying to actually invoke the protocol. Verified against
All 14 call-site occurrences updated; 3 mirrors kept in sync. New regression test in Had this skill landed as drafted, every fresh |
# Conflicts: # packages/squad-cli/src/cli/core/templates.ts # packages/squad-sdk/src/config/init.ts # test/init.test.ts
# Conflicts: # packages/squad-cli/src/cli/core/templates.ts # packages/squad-sdk/src/config/init.ts # test/init.test.ts
bradygaster
left a comment
There was a problem hiding this comment.
✅ Flight approves. Cross-squad communication is bundled coherently as a companion skill with clear protocol coverage.
…des #1297) (#1302) * fix(skills): rename disambiguation skill 'squad' -> 'squad-help' (supersedes #1297) PR #1297 added a disambiguation skill named 'squad' so models calling skill(Squad) would get a redirect. After local end-to-end testing on 2026-06-13: 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 app.js): 1. Copilot CLI's skill schema is {name, description, source, baseDir, allowedTools, pluginName, pluginVersion} (line 989). Frontmatter fields 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. Fix: * Rename 'squad' -> 'squad-help' (avoids the agent-name collision; still descriptive enough for natural-language match when user says 'how do I use squad' or 'squad help') * SKILL.md content: name: 'squad-help', removed unused triggers:/domain:/ confidence:/source:/license: fields, added allowedTools: [], rewrote description: to be self-explanatory, added explicit note that /squad slash command does NOT exist (slash commands are CLI built-ins, not auto-mapped from skills) * MANIFEST_SKILL_NAMES in sdk-init.ts: 'squad' -> 'squad-help' * New TEMPLATE_MANIFEST entry in templates.ts for squad-help (so squad upgrade also propagates the skill - that code path uses TEMPLATE_MANIFEST instead of MANIFEST_SKILL_NAMES) Tests: new test asserts .copilot/skills/squad-help/SKILL.md exists with right frontmatter; explicit regression guard against re-introducing name: 'squad'. 26/26 init tests pass. npm run lint clean. Supersedes #1297. Out of scope (separate issue worth filing): squad upgrade synced only 10 of 16 installed skills - TEMPLATE_MANIFEST (used by upgrade) is out of sync with MANIFEST_SKILL_NAMES (used by init). Skills from PRs #1292 + #1295 (tiered-memory, iterative-retrieval, reflect, cross-squad, cross-squad-communication) have entries in MANIFEST_SKILL_NAMES but not TEMPLATE_MANIFEST. Follow-up will fix. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(skill): add confidence + domain frontmatter to squad-help Reviewer follow-up on #1302: the isSkillContent() classifier in sharing/consult.ts:990 requires BOTH name: AND confidence: in the frontmatter to recognize a file as a skill. Without confidence:, squad-help would not be detected as a skill in cross-squad merge / share / promote flows — it would be misclassified as a generic markdown decision. The Copilot CLI itself silently ignores custom frontmatter fields (per sdk/index.js decompile — only name/description/allowedTools/ user-invocable are read), so adding confidence: high and domain: squad-onboarding is safe at the CLI surface and necessary at the SDK surface. Applied identically to all 3 mirrored copies of squad-help/SKILL.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
…tocols) PR github#1291 added squad registry add/list/remove and the cross-squad/SKILL.md for peer discovery. But discovery is only half the story — once a peer is known, agents need to know HOW to actually exchange info with it. This change ports cross-squad-communication from tamirdresher/squad-skills into the bundled skills so a fresh squad init produces a coordinator that knows the four communication patterns: * Pattern 0: Synchronous CLI session (--working-directory targeting peer) * Pattern 1: Read-only metadata scan (team.md / decisions.md) * Pattern 2: Async git-based request/response (.squad/cross-squad/...) * Pattern 3: Issue-based delegation (gh issue with squad:cross-squad label) Plus decision tree for pattern choice, anti-patterns, request/response YAML schemas, and validation status. Changes: * .squad/skills/cross-squad-communication/SKILL.md (379 lines, canonical source). sync-skill-templates.mjs propagates to both packages templates. * 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 gets a one-paragraph "Companion skill" note pointing to cross-squad-communication for protocol details. Together: cross-squad answers "who?" (registry discovery), cross-squad-communication answers "how?" (the 4 patterns). The original plugin documented validation against specific internal Microsoft repos. Examples in this version use generic names (platform-squad, research-squad) so they are meaningful to upstream users. Protocol mechanics are unchanged. Frontmatter source: attributes the port. Test: new "should install cross-squad-communication skill" in init.test.ts asserts SKILL.md is at install path and content contains expected pattern names. 26/26 init tests pass. npm run lint clean. Composes with github#1291: * squad init → both skills bundled * squad registry add ../peer → peer discoverable * coordinator: "ask peer X for their team members" → uses Pattern 1 by reading team.md from the registered peer Note on overlap with github#1292: PR github#1292 (skills bundling fix) adds 4 entries to MANIFEST_SKILL_NAMES; this PR adds 1. Disjoint additions to the same array; either can land first. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…numbering + honest source/validation Five reviewer follow-ups on github#1295: 1. MANIFEST_SKILL_NAMES added 'cross-squad-communication' but TEMPLATE_MANIFEST didn't — 'squad upgrade' would skip the skill even though 'squad init' installed it. Added the missing entry to TEMPLATE_MANIFEST so upgrade syncs it like every other manifest skill. (Same drift bug pattern noted on github#1292/github#1303.) 2-3. Both SKILL.md files (companion 'cross-squad' and full 'cross-squad-communication') said the skill covers 'the four communication patterns (sync CLI, async git-based, issue-based)' but only listed three — Pattern 1 (read-only knowledge query) was missing from the intro list. Rewrote both intro lines to spell out all four: Pattern 0 (sync CLI), Pattern 1 (read-only), Pattern 2 (git-based async), Pattern 3 (issue-based). 4. The doc had 'Pattern 4: Cross-Repo Dependency Scan' which broke the 'four numbered patterns 0-3' framing — Pattern 4 isn't a communication protocol, it's a one-off analysis utility for discovering how two repos relate. Moved it to a clearly labeled '### Appendix' section with a note explaining why it's not a numbered pattern. 5. Frontmatter 'source:' claimed the skill was 'validated against two production squad instances' but the Validation Status section said Patterns 2 and 3 were 'untested end-to-end'. Reworded 'source:' to acknowledge that only Pattern 0 (and partially Pattern 1) are end-to-end-validated; Patterns 2/3 are documented from design and need live validation before production use. Also softened the same overclaim in the Validation Status prose (replaced 'validated against two production' with 'drafted against two prototype' + explicit acknowledgement that 2/3 are design-only). All 3 mirrored copies of cross-squad-communication/SKILL.md and 3 copies of cross-squad/SKILL.md kept in sync (canonical = .squad/, mirrors = packages/squad-cli/templates/, packages/squad-sdk/templates/). Verified: 31/31 init + builtin-skills tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ns (ghcs→copilot, real flags)
The cross-squad-communication SKILL.md as drafted instructed coordinators
to use a non-existent CLI shape. Verified empirically against
`copilot --help` (v1.0.62):
- `ghcs` is not a binary on a clean install; the real CLI is
`copilot` (resolved to C:\ProgramData\global-npm\copilot.ps1 on
a default node install).
- `--working-directory <dir>` does not exist. Real flag is
`-C <directory>` (git-style "change directory first").
- `--no-mcp` does not exist. Real flag is `--disable-builtin-mcps`.
- `-p, --prompt <text>` takes the prompt STRING, not a path. Earlier
examples passed `-p \` (a path), which makes the CLI try
to execute the path string as a prompt. Read the file with
`Get-Content -Raw` first.
- `--allow-all-tools` was missing from autonomous (non-interactive)
invocations — without it every tool call prompts for permission and
hangs the cross-squad delegation indefinitely.
- Log directory was `~/.agency/logs/` (older `agency` runtime). New
CLI logs under `~/.copilot/logs/`. Switched to a `Test-Path`-guarded
fallback so both transitional and clean installs resolve correctly.
All 14 call-site occurrences in cross-squad-communication/SKILL.md
updated (3 mirrored copies). Mirrors verified byte-identical.
New regression test in test/cross-squad.test.ts asserts each of the 8
correctness properties (ghcs/—working-directory/—no-mcp absent;
`copilot -C`, `--allow-all-tools`, `--disable-builtin-mcps`,
`-p (Get-Content`, and `.copilot\\logs + Test-Path` present) for
every mirror. 8 × 3 mirrors = 24 new assertions; 56/56 cross-squad
tests pass.
Catches a fairly large embarrassment: had this skill landed as drafted,
every fresh `squad init` coordinator would have run a totally bogus
CLI command on the first delegation attempt. Credit to the peer-squad
`read this skill, ran into errors, asked why` loop for surfacing it.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A peer-squad delegation that runs the Copilot CLI without --agent squad
gets a generic Copilot CLI session — the spawned process never loads
.github/agents/squad.agent.md, the peer's team.md, MCP tools, casting,
or coordinator behaviour. The whole point of cross-squad delegation
collapses: the answer comes from an off-the-shelf model, not from the
peer's Squad.
All 7 example command lines in cross-squad-communication/SKILL.md
(Pattern 0 Options A/B/C, Liveness Protocol MCP-skip retry, and the
two Anti-Pattern examples) now include --agent squad. Also added a new
top-of-Patterns "Universal rule: every copilot spawn into a peer squad
MUST pass --agent squad" section that:
- States the rule once, prominently.
- Explains the failure mode (generic session, no team.md / MCP /
coordinator loaded) so future edits don't strip the flag thinking
it's redundant.
- Notes the only exception (--resume preserves original session
agent).
- Generalises the rule beyond cross-squad: "anywhere else you spawn
copilot into a Squad-initialised repo — e.g., post-init tips and
any automation that invokes the CLI on a squadified folder."
Also added a precondition note to Pattern 0 Requirements: the target
repo must be Squad-initialised (.squad/config.json +
.github/agents/squad.agent.md present) so --agent squad resolves.
Verified empirically: copilot --help (v1.0.62) confirms
--agent <agent> is the real flag name.
squad delegate (CLI command) was audited and does NOT need this fix
— it uses `gh issue create`, not `copilot`, so the issue body lands
in the peer repo's GitHub Issues for async pickup, not via direct CLI
spawn.
Regression tests in test/cross-squad.test.ts:
- 'every copilot spawn into a peer squad includes --agent squad'
— scans every copilot command line (excluding --resume / prose
references) and asserts each one has --agent squad. Tells you
the exact offending line on failure.
- 'explains WHY --agent squad is required (universal rule paragraph)'
— defends against a future edit that strips the rationale.
- 2 new assertions × 3 mirror locations = 6 new tests.
- 62/62 cross-squad tests pass.
All 3 mirrored copies of cross-squad-communication/SKILL.md kept in
sync (canonical = .squad/, mirrors = packages/squad-cli/templates/,
packages/squad-sdk/templates/).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
6b0eac2 to
bb292cf
Compare
…ough the cross-squad skill (#1307) * fix(coordinator): route "spawn a squad" / "another squad" prompts through the cross-squad skill 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 / GH-issue patterns) was bypassed entirely. Two structural holes in squad.agent.md allowed this: 1. The Routing table had no row mapping "spawn a squad" phrasing to the Squad-PRODUCT concept (only "upgrade squad" / "squad commands" rows covered Squad-as-a-product vocabulary). 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. This fix: - Adds a new routing-table row for the squad-spawning vocabulary ("spawn a squad", "another squad", "two squads", "second squad", "fan out to squads", "delegate to a squad"). Action: invoke the skill tool on cross-squad AND cross-squad-communication BEFORE any task spawn, then delegate via Pattern 0/1/2/3. - Adds a "Hard trigger — keyword-to-skill match" paragraph at the top of the Skill-aware-routing block. If any word in the user's request matches an installed skill name (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 "failure mode this rule closes" pointer so the guard survives future paraphrasing. - Strengthens cross-squad/SKILL.md with a Read-this-FIRST 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. - Adds a regression test (template-sync.test.ts) that asserts the row + the hard-trigger paragraph + the worked example are present in every mirrored copy of squad.agent.md (5 locations). All 4 mirrors re-synced via `scripts/sync-templates.mjs --sync`. Verified: 223/223 template-sync tests pass. Composability: disjoint from #1292/#1293/#1295/#1298/#1300/#1301/#1302/ #1303/#1304/#1306 — only touches squad.agent.md mirrors + cross-squad/ SKILL.md + the template-sync test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(coordinator): strengthen squad-spawn disambiguation — ask_user on ambiguity + anti-patterns Real-world failure (2026-06-13): even AFTER the routing-table row and hard-trigger paragraph from b5d05fb landed, a peer-squad coordinator *still* did ad-hoc `task` fan-out for "spawn two squads of engineers and QAs". Self-diagnosis surfaced four contributing failure modes: 1. Prior-session anchoring (saw earlier `reviews/squad-alpha/` folders and matched the pattern without re-evaluating user intent). 2. Ambiguous wording, lazy interpretation (silently picked the cheaper option instead of asking). 3. Coordinator doctrine biases toward `task` fan-out (the existing Eager Execution / Parallel Fan-Out section pulled the coordinator back even after it had loaded `cross-squad`). 4. Cost/overhead instinct ("two real squads for a 30-line app feels disproportionate" — judged silently instead of surfacing the trade-off). The original PR #1307 fix closed modes 1 and 3 mechanically (forces the skill to load) but left modes 2 and 4 open (didn't dictate what to DO with that knowledge). This commit closes them: A. squad.agent.md routing row — added two explicit clauses: - "**Default = literal Squad install.** Calling `task` sub-agents 'squad-alpha' / 'squad-beta' does NOT make them squads — that is the explicit anti-pattern." - "**If the request is ambiguous** ... you MUST `ask_user` with a 2-choice prompt — and never silently pick the cheaper option." No escape hatch. The coordinator can no longer rationalise the downgrade as a judgment call. B. cross-squad/SKILL.md — added a full `## Disambiguation: 'squad' vs ad-hoc agents` section with: - Default-behaviour table mapping common phrasings to expected coordinator actions (real squads vs ad-hoc agents vs ambiguous). - ask_user 2-choice protocol verbatim (heavier/persistent vs lighter/ephemeral) so the coordinator has the exact prompt shape. - Four named anti-patterns drawn directly from the observed failure: * Naming task agents "squad-alpha" doesn't make them squads * Prior-session anchoring (pattern is a hint, not a contract) * Silent cheaper-option pick (judgment call belongs to the user) * Loading the skill but doing task fan-out anyway (disambiguation rule OVERRIDES generic fan-out doctrine when "squad" was the trigger) - Sharpened `description:` so the squad skill-aware-router has better natural-language hooks. - `triggers:` frontmatter array (Copilot CLI ignores `triggers:` per sdk/index.js decompile, but the squad coordinator's skill-aware routing system uses natural-language matching against frontmatter + content, so documenting the phrases here helps that matcher fire). C. Regression tests in test/template-sync.test.ts: - Routing row must mention `ask_user` + "anti-pattern" (new × 5 mirrors = 5 assertions). - cross-squad/SKILL.md must have `## Disambiguation` section, default-behaviour rule, ask_user requirement, the squad-alpha anti-pattern, and triggers: frontmatter (5 new × 3 mirrors = 15 assertions). - 20 new assertions total; 243/243 template-sync tests pass. cross-squad/SKILL.md mirrored to packages/squad-cli/templates/skills/ and packages/squad-sdk/templates/skills/ (byte-identical). squad.agent.md re-synced to all 4 mirrors via scripts/sync-templates.mjs. Composability: still disjoint from all other open PRs. Pure additions to two files (squad.agent.md row, cross-squad/SKILL.md content) plus mirrors + tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…te skills (github#1308 phase 1) squad.agent.md is loaded as the agent prompt at every Copilot session start. v0.10.0-insider.1 ships it at 81 KB / 1137 lines and the v0.10 stabilisation pass alone added +10.6 KB / +114 lines. Every byte is paid at every session. Phase 1 fix: extract three low-cross-reference, high-byte sections to satellite skills the coordinator loads on demand via the skill tool — same pattern that worked for cross-squad-communication (github#1295). - coordinator-init-mode — Init Mode Phase 1 + Phase 2 (5.4 KB) - coordinator-source-of-truth — Source of Truth Hierarchy (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). 19 skills installed at .github/skills/ (was 16). Behaviour unchanged — each removed section is replaced with a stub naming the trigger condition and instructing the coordinator to skill(coordinator-X) before acting. Sections that stay in squad.agent.md (intentional): - Team Mode + state-backend handshake + HARD RULE — handshake must fire before any state write - Routing table — hit on every user prompt - Hard trigger keyword-to-skill match paragraph (github#1307) — load-bearing - How to Spawn an Agent — referenced from every routing action - Coordinator Identity / Personal Squad / Memory Governance Tools — frequently re-read inline Wired changes: - New canonical sources at .squad/skills/coordinator-{x}/SKILL.md plus 2 template-dir mirrors - MANIFEST_SKILL_NAMES grows by 3 entries (16 → 19) - TEMPLATE_MANIFEST grows by 3 entries with ../.github/skills/ destinations (post-github#1304 install location) - .squad-templates/squad.agent.md replaces each section with a stub - 4 mirrored squad.agent.md copies re-synced via scripts/sync-templates.mjs --sync Tests: 287/287 pass. The existing 'should install every manifest-curated skill (regression: bradygaster/squad#1289, github#1264)' already iterates MANIFEST_SKILL_NAMES, so it automatically asserts the 3 new skills install. Smoke test: fresh squad init produces 19 skills at .github/skills/ and squad.agent.md is 70 KB. Follow-ups (separate PRs) for the still-large sections: - Routing (9.2 KB) — extract action-cell verbiage, keep trigger table - Team Mode (5.5 KB) — extract worktree-awareness sub-sections - How to Spawn (3.2 KB) — extract role-emoji catalog Target after 2-3 follow-ups: ~45 KB coordinator file. Closes github#1308 (phase 1). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
) * fix: auto-scaffold Fact Checker agent during init and cast (#1222) The Fact Checker role landed in v0.10.0 (#789) with catalog entry, charter template, skill, AGENT_TEMPLATES map entry, and template manifest entry — but was never wired into the user-facing onboarding flow. Users running 'squad init' got Scribe/Ralph/Rai but never saw Fact Checker as a default or cast option. This mirrors how Rai was wired: - init.ts: adds 'fact-checker' to the default agents: array passed to sdkInitSquad() - cast.ts: adds factCheckerMember(), factCheckerCharter(), hasFactChecker branches in castTeam(), and the roster banner line Smoke-tested locally: 'squad init' in a clean repo now produces .squad/agents/fact-checker/charter.md alongside scribe/ralph/Rai. Closes #1222 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(upgrade): auto-scaffold Rai + Fact Checker on squad upgrade (#1222) Extends the #1222 fix to the third code path. \squad upgrade\ was intentionally silent on agents (preserves user state). For users upgrading from v0.9.x or earlier (no Rai) or v0.10.0 (no fact-checker), this means they'd never get the built-in agents unless they re-ran \squad init\ (which would overwrite other state). Adds \�nsureBuiltinAgents()\ to \ unEnsureChecks()\. Idempotent — only scaffolds when the agent directory is absent. Never overwrites existing charters or history files. Sources content from the shipped \ emplates/{Rai,fact-checker}-charter.md\ templates (already present via TEMPLATE_MANIFEST). Scribe and Ralph are intentionally NOT scaffolded by upgrade — they predate this fix in every squad, and their charters are inlined in cast.ts (no shipped template file). Smoke tested locally: - Set up a simulated v0.9.4 squad (scribe + ralph only) - Ran \squad upgrade\ → 'scaffolded 2 built-in agent(s): Rai, fact-checker' - Ran upgrade again → no re-scaffold (idempotent) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(permissions): use 'approve-once' for Copilot CLI v1.0.54+ contract (#1192) The Copilot CLI post-v1.0.54 changed the permission handler contract to expect 'approve-once' instead of 'approved'. Update the handler, type definition, and error hint to match the new contract. Closes #1191 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: Squad.Agents.AI - Microsoft Agent Framework adapter for the Squad CLI (#1207) * feat: Squad.Agents.AI community NuGet for MAF integration Squad CLI as Microsoft.Extensions.AI IChatClient, composing GitHub.Copilot.SDK via AsAIAgent() from Microsoft.Agents.AI.GitHub.Copilot 1.7.0-preview. Closes Track A of the Q1-Q7 design lock (see tamresearch1 .squad/decisions.md Decisions 441, 443, 444, 447). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: add PR body for #3 * fix(SquadAgent): inherit AIAgent (was IChatClient force-cast) - SquadAgent now properly inherits from Microsoft.Agents.AI.AIAgent - Removed (IChatClient)(object)agent force-cast - Overrides all AIAgent abstract members (CreateSessionCoreAsync, RunCoreAsync, etc.) - DI registration now registers AIAgent (not IChatClient) - README updated to use AIAgent.RunAsync API - No more abstraction inversion; AIAgent is the correct layer Fixes the architectural error identified by Tamir. * docs(SquadAgent): rewrite README — prerequisites, Hello World, troubleshooting, preview callout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(SquadAgent): GitHubTokenProvider callback + redact options ToString Adds async token provider pattern for production scenarios (KeyVault/MSI integration). - GitHubTokenProvider property takes precedence over GitHubToken - GitHubToken marked [JsonIgnore] to prevent serialization leaks - SquadAgentOptions.ToString() redacts GitHubToken field - Updated CreateCopilotClient to resolve token from provider first Mitigates P0 #3: token leakage via ILogger structured-log calls, IOptions snapshots, and serializers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(SquadAgent): document GitHubTokenProvider callback for production token management Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(SquadAgent): bind ConnectionStrings__squad via IConfigureOptions + add smoke tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(README): replace removed WithTeamRoot with positional teamRoot ctor WithTeamRoot was deleted in commit 35767c90 in favor of mandatory positional teamRoot constructor argument on AddSquad. The Aspire example in the Squad.Agents.AI README still showed the old fluent API, which would now fail at compile time for anyone copy-pasting. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test(squad-agents-ai): add routing integration tests Closes the routing-verification gap identified during squad-squad onboarding: the API surface existed but routing semantics weren't functionally tested. New tests verify persona pass-through, boundary-instruction injection on first turn, WorkingDirectory isolation (Decision 452a), and CopilotClientOptions-based routing (Decision 447). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci(squad-agents-ai): add .NET build/test/pack workflow PR #3 CI was Node/docs-only — adding the .NET gate so green actually reflects the package code. Matrix on ubuntu + windows, restore/build/test/pack, uploads TestResults and nupkg artifacts. Closes the build-verification gap identified during squad-squad onboarding (see .squad/decisions.md adoption record, 2026-06-02). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci(squad-agents-ai): NuGet publish workflow + Dependabot config - .github/workflows/squad-agents-ai-release.yml: workflow_dispatch and tag-driven publish to nuget.org with --skip-duplicate idempotency, fail-fast on missing NUGET_API_KEY secret, optional GitHub Release on tag - .github/dependabot.yml: nuget (src + test) + github-actions, weekly, M.A.AI major allowed, OpenTelemetry major deferred (per Decision 602) Closes the release-pipeline + supply-chain-tracking gaps identified during squad-squad onboarding. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(squad-agents-ai): release-ready docs + .csproj packaging metadata - README updates / XML docs on public surface - CHANGELOG.md with [0.1.0-preview] - 2026-06-02 entry - .csproj: Description, RepositoryUrl, Authors, PackageTags, PackageReadmeFile - Verified via dotnet pack — .nupkg contains README, LICENSE, xml-docs Closes the docs-readiness gap for v0.1-preview publish. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * ci(squad-agents-ai): switch release triggers to dev/main branch-driven Per Tamir's release-strategy directive (decisions.md 2026-06-02): - dev merges → prerelease publish (suffix scheme mirrors Squad CLI) - main merges → stable publish - workflow_dispatch retained as manual escape hatch - tag-driven trigger removed (branches are the source of truth) Version derivation pattern adapted from the Squad CLI's existing release workflow. --skip-duplicate retained for idempotent reruns. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs+fix: PR #3 review pass — hygiene, XML docs, cliArgs, multi-named connections - Rewrite the package README and PR validation flow around the AIAgent surface and ambient Copilot authentication. - Keep public docs free of internal process references and remove obsolete deferral language. - Preserve connection-string cliArgs through CopilotClientOptions and cover the behavior with a routing test. - Add named connection-string lookup via AddSquadAgent("name") using ConnectionStrings:squad-{name}. - Document the new public overloads and verify the package builds without warnings. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: Round 2 — keyed DI, BYOK delegate, routing gate, security hardening - Add ConfigureCopilotClient delegate on SquadAgentOptions for BYOK - Add routing gate: snapshot/restore Cwd/CliPath/CliArgs after delegate (Picard C1) - Add 4 AddKeyedSquadAgent overloads with .NET 8+ keyed DI - Fix Environment credential leak: [JsonIgnore] on Environment, GitHubTokenProvider, ConfigureCopilotClient - ToString() redacts token-pattern keys (TOKEN/KEY/SECRET/HMAC/PASSWORD/CREDENTIAL) - Add 21 new tests (43 total): security redaction, keyed DI, BYOK routing gate - Update README: streaming, keyed DI, BYOK, security sections Complies with: Picard C1-C4, Worf SC-1 through SC-8. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: add Squad.Agents.AI sample app demonstrating DI, keyed DI, BYOK, and streaming - samples/squad-agents-ai-sample/Program.cs: four runnable flows Flow 1 -- AddSquadAgent + RunAsync (basic DI) Flow 2 -- AddKeyedSquadAgent x2 + GetRequiredKeyedService<SquadAgent> Flow 3 -- ConfigureCopilotClient delegate (BYOK token + env var injection) Flow 4 -- RunStreamingAsync with await foreach token-by-token output - samples/squad-agents-ai-sample/Squad.Agents.AI.Sample.csproj: net10.0, project reference to src/Squad.Agents.AI, Microsoft.Extensions.Hosting 10.0.0 - samples/squad-agents-ai-sample/README.md: prerequisites, run commands, per-flow walkthrough, troubleshooting table - .github/workflows/squad-agents-ai-ci.yml: adds paths trigger and restore + build steps for the sample (no run step -- requires live CLI) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor(Squad.Agents.AI): co-locate sample under src/ and consolidate README - Moves the sample app from samples/squad-agents-ai-sample/ to src/Squad.Agents.AI/samples/Squad.Agents.AI.Sample/ so it lives alongside the package it demonstrates. - Folds the sample's standalone README into the package README, giving consumers one canonical doc for both the API and the runnable demo. - Adds <Compile Remove="samples/**/*.cs" /> to Squad.Agents.AI.csproj so the library's wildcard glob does not pick up Program.cs in the co-located samples subdirectory. - Updates the .csproj project reference, and CI workflow paths to match the new layout. - Verified end-to-end: dotnet build, dotnet test (43/43 passing), and a sample sanity-check run (clear CLI-not-found error, no stack trace). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore(Squad.Agents.AI): remove outdated draft PR body file The standalone pr-body.md was an early draft authored before the live PR description took its final shape. The PR body on GitHub is the canonical source; this file is dead weight and would confuse maintainers reviewing the diff. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(Squad.Agents.AI): address PR #1207 reviewer feedback (12 items) - Snapshot CliArgs by value, not reference, so in-place mutation by SDK consumers is also caught by the routing guard. - Validate name/connectionName/serviceKey is non-empty in all DI registration overloads; previously null/whitespace produced invalid connection-string keys. - Replace ghp_-prefixed placeholder in the sample with a clearly-fake token to avoid tripping secret-scanning and to remove a real-token lookalike. - Remove brittle 'PR #3' references from README and CHANGELOG; describe the feature without tying to a specific PR thread. - Update NuGet metadata and README links to point to bradygaster/squad (canonical repo) instead of the tamirdresher fork. - Multi-target the test project to match the package's target framework set so CI exercises every framework the package ships against. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor(Squad.Agents.AI): adopt DelegatingAIAgent base + MAF ctor pattern (PR #1207 r2) Addresses westey-m's review feedback: - Extend Microsoft.Agents.AI.DelegatingAIAgent — drops ~70 lines of manual Core* overrides; pass-through is provided by the base class. - Adopt MAF constructor pattern: \(string squadFolderPath, SquadAgentOptions? options = null, ILoggerFactory? loggerFactory = null)\. Required settings on the constructor, options optional, ILoggerFactory stays on ctor for DI injection. - Routing-guard, IAsyncDisposable, and security posture preserved. - Add Squad.Agents.AI.slnx solution for easy IDE open. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Reno (Copilot) <reno@clawpilotsquad.dev> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <Copilot@users.noreply.github.com> Co-authored-by: tamirdresher <tamirdresher@users.noreply.github.com> * ci(Squad.Agents.AI): switch NuGet publish to Trusted Publishing (OIDC) (#1240) Replace the long-lived NUGET_API_KEY repo secret with NuGet/login@v1 OIDC token exchange (1-hour API key) per the modern Trusted Publishing flow: https://learn.microsoft.com/nuget/nuget-org/trusted-publishing Why --- - No long-lived credentials stored in the repo. - Token is scoped to this workflow + repo + branch via the OIDC subject claim and the Trusted Publishing policy registered on nuget.org. - Eliminates the chicken-and-egg between needing admin to set NUGET_API_KEY and needing the package live to validate the workflow. What changed ------------ - Add `id-token: write` to the publish job (required for OIDC). - Drop the `Verify NuGet API key` step. - Drop the `--api-key ` reference to secrets.NUGET_API_KEY. - Add `NuGet/login@v1` step that exchanges the OIDC token for a short-lived API key, exposed via `steps.nuget-login.outputs.NUGET_API_KEY`. - Add a fail-fast check for the new `vars.NUGET_USER` repository variable (non-sensitive; the nuget.org profile name that performs the exchange). - Update the file header documentation to reflect the new flow and link to the Trusted Publishing setup page. Required configuration before first publish ------------------------------------------- 1. Create the `Squad` organization on nuget.org and add owners. 2. Configure a Trusted Publishing policy at https://www.nuget.org/account/trusted-publishing owned by the Squad org: Repository Owner: bradygaster Repository: squad Workflow File: squad-agents-ai-release.yml Environment: (empty) 3. Set repository variable NUGET_USER (Settings → Secrets and variables → Actions → Variables) to a Squad-org-member's nuget.org profile name (NOT email). Variable, not secret — the username is non-sensitive. Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(Squad.Agents.AI): expose SessionConfig + default OnPermissionRequest (#1252) Squad.Agents.AI 0.1.0-preview.2 calls `CopilotClient.AsAIAgent(instructions, name)` which leaves `SessionConfig.OnPermissionRequest` unset. The first call to `SquadAgent.CreateSessionAsync()` therefore throws: System.ArgumentException: An OnPermissionRequest handler is required when creating a session. For example, to allow all permissions, use CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll }); There was no public way for consumers to fix it from the outside — `ConfigureCopilotClient` only exposes `CopilotClientOptions`, not the per-session `SessionConfig` that owns the permission handler. What changed ------------ - `SquadAgent` now switches to the `AsAIAgent(client, sessionConfig, ...)` overload and constructs a `SessionConfig` with: - `OnPermissionRequest = PermissionHandler.ApproveAll` (sensible default for a host-process Squad adapter; the host already chose to instantiate Squad and is responsible for sandboxing). - `WorkingDirectory` defaulting to the resolved `Cwd` / `SquadFolderPath`. - `SystemMessage = new SystemMessageConfig { Content = Instructions }` when `SquadAgentOptions.Instructions` is set. - `SquadAgentOptions.ConfigureSession: Action<SessionConfig>?` is new — runs after Squad applies its defaults so a consumer can swap in a stricter permission handler, pin the model, restrict tools, etc. Tests ----- - New `SquadAgentSessionConfigTests` (4 cases) exercising the new surface: `ConfigureSession` is settable, runs against the live SessionConfig, can replace the permission handler, and can set `AvailableTools`. - All existing 43 tests still pass per TFM (141 total across net8/9/10). Verified -------- - The end-to-end consumer smoke test in `C:\Users\tamirdresher\source\repos\squad-agents-ai-consume-test` previously had to fall back to the raw SDK because of the missing handler. With this change, `SquadAgent.CreateSessionAsync()` returns successfully and `RunAsync` drives real 3-turn conversations against `.squad/`-init'd teams. Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Squad.Agents.AI 0.2.0: bump to MAF 1.10.0-rc1 / SDK 1.0.0 GA — file-IO works (#1259) * Squad.Agents.AI: bump to MAF 1.10.0-rc1 / SDK 1.0.0 GA — file-IO now works Microsoft.Agents.AI.GitHub.Copilot bumped from 1.7.0-preview to 1.10.0-rc1, which transitively brings GitHub.Copilot.SDK 1.0.0 GA. SDK 1.0.0 reshaped CopilotClientOptions and SessionConfig (the breaking namespace + property renames are mirrored below), but in return Copilot CLI 1.0.61 talks to the SDK over the new ACP-style protocol — meaning the agent's view/grep/powershell tools finally work end-to-end without 'permission errors' or 'content exclusion policy' hallucinations. SDK 1.0.0 API migrations applied: * Namespace GitHub.Copilot.SDK -> GitHub.Copilot. * CopilotClientOptions.Cwd -> WorkingDirectory. * CopilotClientOptions.CliPath + .CliArgs collapsed into a single CopilotClientOptions.Connection (RuntimeConnection). We now build the Connection via RuntimeConnection.ForStdio(CliPath, CliArgs) only when the consumer supplied either a custom CLI path or extra CLI args; otherwise the SDK's default child-process connection is used and the bundled copilot.exe (downloaded by the SDK's build/ targets) is invoked. * SessionConfig.ConfigDir -> SessionConfig.ConfigDirectory. * PermissionRequestHandler is no longer a named delegate type; we use type inference where the test code referenced it. Public Squad.Agents.AI surface is intentionally unchanged: SquadAgentOptions still exposes Cwd, CliPath, CliArgs, ConfigureSession, ConfigureCopilotClient. We translate to the SDK 1.0.0 shape internally. Routing gate (Picard Condition 1 / Worf SC-3) updated to snapshot and restore WorkingDirectory + Connection instead of the old Cwd / CliPath / CliArgs trio. A delegate that REPLACES Connection (e.g. via RuntimeConnection.ForStdio(...)) is reverted, mirroring the previous CliPath / CliArgs hijack tests. Verified end-to-end against a real .squad-initialised team root: the coordinator successfully reads .squad/team.md and enumerates every cast member with their role. The dotnet test suite passes 46/46 across net8.0, net9.0, and net10.0 (-1 vs baseline because the old CliPath and CliArgs hijack tests collapsed into a single Connection hijack test, which is the right granularity for SDK 1.0.0). Version bumped 0.1.0-preview -> 0.2.0 to surface the MAF/SDK transitive bump. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address Copilot review feedback (#1259) - Remove duplicate 'using GitHub.Copilot' in SquadAgentSessionConfigTests (regex replace inadvertently doubled the directive when migrating from the old GitHub.Copilot.SDK namespace). - Drop hardcoded teamRoot override I left behind in the sample Program.cs during the CLI-not-found debug session. The sample now correctly reads SQUAD_TEAM_ROOT (or falls back to CWD) as documented. - Fix mismatched comment in SquadAgent: the SDK-protocol section now correctly references --allow-all (matching the flag actually injected in CreateCopilotClient), not the narrower --allow-all-tools. - Detect more existing permission-opening flags before injecting our default --allow-all so a host that opts in via --allow-all-paths, --allow-all-urls, or the omnibus --yolo no longer gets --allow-all prepended on top. Comparison is now case-insensitive. Updated the connection-string test that asserted the old over-eager behavior. Also add .vs/, *.user, *.userprefs to .gitignore so VS solution junk doesn't surface in git status. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address pre-existing Copilot review comments from PR #1212 (#1258) - Workflow permissions: add issues: write to squad-pr-nudge, squad-impact, and squad-repo-health workflows that call issues.createComment - Logic bug: fix ahead_by → behind_by in pr-nudge stale branch check - Logic bug: fix PR_LABELS fallback producing string instead of null - Script fix: check legacy statuses for failure/error in checkCIStatus() - Script fix: truncation row column count mismatch in pr-readiness.mjs - Script fix: validate JSON.parse result is array before using as labels - Script fix: isNodeBuiltin now validates node: prefix against known builtins - YAML escaping: use JSON.stringify for skill descriptions in apm.yml Closes #1213 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: expose memory tools via MCP + route writes through governed pipeline (#1251) - Expose memory.classify, memory.write, memory.search, memory.promote, memory.delete, memory.audit through the squad_state MCP server (#1244) - Pin squad_state to user-level ~/.copilot/mcp-config.json during init/upgrade for external `copilot -p` mode compatibility (#1247) - Update squad.agent.md directive-capture and decision-recording instructions to route through memory.write instead of raw squad_state_write to the drop-box (#1246) Closes #1244 Closes #1247 Closes #1246 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(skills): update path references from .squad/skills/ to .copilot/skills/ (#1260) The CLI and SDK write skills to .copilot/skills/ by default, but docs still referenced .squad/skills/. Update all documentation to use the canonical .copilot/skills/ path and add a note about legacy fallback. Closes #1241 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(init): prompt to add @copilot as a team member during squad init (#1262) Add an interactive prompt during squad init that asks users if they want to add @copilot (the GitHub Copilot coding agent) as an autonomous team member. If accepted, 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. Closes #1147 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: align skills path + state-backend upgrade flow (#1241, #1226) (#1249) - Update all docs references from .squad/skills/ to .copilot/skills/ - Note that both paths are scanned at read time but .copilot/skills/ is write default - List all 6 git hooks (add pre-commit and post-commit to docs) - Correct 'read-only reference' claim about migrated files - Add recovery section for pre-commit hook refusal scenarios Closes #1241 Closes #1226 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Squad.Agents.AI 0.3.0: first-class subagent observability (#1265) Adds a typed OnSubagentTrace callback + OpenTelemetry ActivitySource so consumers can see subagent dispatch (the coordinator's 'task' tool spawning specialist sub-agents and their replies) without writing their own polymorphic dispatch over the raw GitHub.Copilot SessionEvent hierarchy. The previous 0.2.x surface required consumers to write the same boilerplate the aspire-squad-resource demo had to (CopilotSessionTraceMapper.cs): switch on every event subtype, unwrap subagent context, manage Activity lifetime. 0.3.0 makes that the SDK's job. New public surface: * SquadAgentOptions.OnSubagentTrace (Action<SquadAgentTraceEvent>) Set this to subscribe to subagent lifecycle (Selected / Started / Completed / Failed), assistant messages from coordinator AND subagents, tool start/complete, and SessionIdle. Setting OnSubagentTrace implicitly turns on SessionConfig.IncludeSubAgentStreamingEvents so subagent replies actually flow up to the parent session (otherwise they stay inside the subagent session and never reach the callback). * SquadAgentTraceEvent record — typed envelope (Kind, RawEventType, Timestamp, SdkAgentId, SubagentName, SubagentDisplayName, ToolCallId, Content, Success, RawEvent). Carries the original SessionEvent on RawEvent for advanced consumers but exposes everything else through neutral primitive types so the callback signature has no transitive dependency on GitHub.Copilot.SDK. * SquadAgentTraceEventKind enum — categorises the SessionEvent into the well-known cases that downstream observability surfaces want. * SquadAgentDiagnostics.ActivitySourceName ('Microsoft.Agents.AI.Squad') + SquadAgentDiagnostics.ActivitySource — one Activity per subagent dispatch is opened on SubagentStartedEvent and disposed on the matching SubagentCompletedEvent / SubagentFailedEvent, tagged with squad.subagent.name, squad.subagent.display_name, squad.subagent.sdk_agent_id, and squad.subagent.reply_preview (a short truncated copy of the subagent's assistant message). Hosts that .AddSource(SquadAgentDiagnostics.ActivitySourceName) on their OpenTelemetry tracer get these spans in their backend — the Aspire dashboard renders them in the trace view automatically. Internal: * SquadSubagentTraceMapper — wires SessionEvent -> SquadAgentTraceEvent and the Activity lifecycle. Held by SquadAgent and disposed during DisposeAsync to drain any subagent activities that never received a matching Completed event (e.g. session ended mid-dispatch). * InternalsVisibleTo=Squad.Agents.AI.Tests so the mapper can be unit tested directly without spinning a real CLI session. Tests: 54/54 passing across net8, net9, net10 (+8 new tests for the observability surface including Activity lifetime, tag propagation, mid-session disposal, and consumer-callback exception isolation). Verified end-to-end against the tamresearch1 Star Trek squad: the OnSubagentTrace callback observed two parallel subagent dispatches (Picard, Data), captured each of their replies attributed to the right SdkAgentId, and the matching 'squad.subagent Picard' / 'squad.subagent Data' OTel spans opened and closed cleanly with the reply tagged on each span. Version bumped 0.2.0 -> 0.3.0 to signal the new public surface. Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore(lockfile): sync package-lock with package.json after v0.10.0 bump (#1266) After the v0.10.0 stable release on 2026-06-07, the root package-lock.json still recorded packages/squad-cli@0.9.6-preview.15 and packages/squad-sdk@0.9.6-preview.13 for the workspace entries. The package.json files were updated correctly during the release, but the lockfile workspace metadata was not regenerated. This causes `npm ci --ignore-scripts` to fail in the `sdk-exports-validation` CI job whenever package.json versions diverge from these stale lockfile entries (which happens on every build that runs `scripts/bump-build.mjs`). Confirmed on PR #1257. This commit regenerates only the workspace version metadata (`packages/squad-cli` and `packages/squad-sdk`) — no dependency trees are touched. Verified locally on Windows + Node v23.5.0: - `npm ci --ignore-scripts` at repo root: ✅ exit 0 (was already passing on dev because root package.json/lockfile match; failure mode is the workspace-entry mismatch surfacing under specific build conditions) - `npm install --ignore-scripts`: no further drift produced - Full `npm test` suite: 6535 passed / 134 failed / 60 skipped — the 134 failures are all pre-existing Windows file-locking flakiness (EBUSY/ENOTEMPTY/hook-timeout); identical failure mode and similar count on the immediate pre-merge commit cc37a2f7 (125 failures pre-merge, 134 post-merge — diff is within flake noise). - Targeted re-run of the 5 "newly failing" files in isolation: 93/93 passing — confirms the bulk-run failures are concurrency-induced flakes, not regressions from the recent merges (#1251, #1258, #1260, #1262, #1249). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(bump-build): also update package-lock workspace entries (#1267) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: release pipeline version pinning (#1203, #1204) (#1250) * 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 current version isn't yet on the registry (Closes #1203) - Add isLocalOrUnpublishedVersion guard so local dev builds and versions with build metadata (+) fall back to @insider instead of writing unresolvable version strings into MCP config (Closes #1204) - Extend resolveSquadStateMcpSpec to short-circuit for build-metadata versions - Add CI step to verify SDK dependency is resolvable before CLI publish Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: reset accidentally-bumped version 0.10.0-build.2 -> 0.10.0 Pre-publish version guard rejects -build.N suffixes (release pipeline policy). The bump was made by an unintended local 'npm run build' run before commit. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tamir Dresher <tamir.dresher@gmail.com> Co-authored-by: Copilot <tamirdresher@users.noreply.github.com> * chore: include CHANGELOG.md in published npm tarball (#1257) * chore: include CHANGELOG.md in published npm tarball Add CHANGELOG.md to the files array in both squad-cli and squad-sdk package.json files so changelogs are included in published npm tarballs. This enables offline what's-new prompts and removes the need for GitHub API calls to show release notes. Closes #1171 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: reset accidentally-bumped versions to 0.10.0 Pre-publish version guard rejects -build.N suffixes (release pipeline policy). Both SDK and CLI package.json had -build.4 from a local 'npm run build' run before commit. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tamir Dresher <tamir.dresher@gmail.com> Co-authored-by: Copilot <tamirdresher@users.noreply.github.com> * Squad.Agents.AI 0.4.0: default-on subagent observability + Aspire-style connection-string lookup (#1271) Two small but high-impact changes that remove ~30 lines of boilerplate from every consumer (Aspire and otherwise) and make the OpenTelemetry story self-explanatory. ## 1. EmitSubagentActivities (default true) — telemetry independent of callback Today, the per-subagent OpenTelemetry Activity emission is a side-effect of setting `OnSubagentTrace`. A host that just wants `squad.subagent {Name}` spans in their backend has to wire a callback they don't need. `Microsoft.Agents.AI.Squad` is silent until then. 0.4.0 makes activity emission the default: * New `SquadAgentOptions.EmitSubagentActivities` (defaults to `true`). * `SquadAgent` installs `SquadSubagentTraceMapper` whenever `EmitSubagentActivities || OnSubagentTrace != null`, so spans flow with zero extra wiring. * `OnSubagentTrace` becomes a pure customisation hook (logging, dashboards, metrics) — independent of telemetry. Set `EmitSubagentActivities = false` to opt out of built-in spans when you want to handle telemetry yourself. Plus richer span shape: every lifecycle phase is now an `ActivityEvent` on the live subagent span (visible as annotated markers on the timeline in Aspire / Jaeger / etc.): * `squad.subagent.start` — on SubagentStarted * `squad.subagent.message` — on AssistantMessage (with message_preview tag) * `squad.subagent.completed` — on SubagentCompleted * `squad.subagent.failed` — on SubagentFailed Net effect for a consumer: builder.Services.AddOpenTelemetry() .WithTracing(t => t.AddSource(SquadAgentDiagnostics.ActivitySourceName)); builder.Services.AddSquadAgent(o => o.SquadFolderPath = "/team"); …and the dashboard lights up. No callback wiring, no Activity.Current?.AddEvent plumbing in the host. ## 2. Aspire-style connection-string lookup (with legacy fallback) Aspire injects connection strings under the literal resource name — e.g. an AppHost that calls `builder.AddSquad("research-squad", ...)` exposes `ConnectionStrings:research-squad` to the consumer. The 0.3.0 SDK only looked at `ConnectionStrings:squad-research-squad` (prefixed), so Aspire consumers had to manually call `Configuration.GetConnectionString(name)`, parse the URI, and feed `SquadFolderPath` into the configure callback themselves. 0.4.0 tries the literal name first and falls back to the legacy prefixed form: | Style | Example | Lookup | |--------------------------------------|---------------------------------------------|--------------------------------------------| | Aspire-style direct (tried first) | `AddSquadAgent("research-squad")` | `ConnectionStrings:research-squad` | | Legacy prefixed fallback | `AddSquadAgent("research")` | `ConnectionStrings:squad-research` | Both work. Existing consumers using `ConnectionStrings:squad-{name}` continue unchanged; new Aspire consumers get the natural one-line registration. ## Tests 54 → 64 tests, all passing on net8.0/9.0/10.0. New `SquadAgentDefaultObservabilityTests` covers: * Default-on activity emission (without consumer callback) * Opt-out path (`EmitSubagentActivities = false`) — span suppression + callback still fires * Each ActivityEvent name (`start` / `message` / `completed` / `failed`) * Connection-string precedence: Aspire-direct preferred, prefixed fallback used, same rule applies for keyed registrations Existing `SquadSubagentTraceTests` and the new class share an `[Collection("SquadActivityListeners")]` so they run serially — process-global `ActivityListener` state caused cross-test pollution otherwise. ## Files * `src/Squad.Agents.AI/SquadAgentOptions.cs` — new `EmitSubagentActivities` property + reworked `OnSubagentTrace` XML doc to clarify independence. * `src/Squad.Agents.AI/SquadAgent.cs` — install trace mapper when telemetry OR callback is requested. * `src/Squad.Agents.AI/SquadSubagentTraceMapper.cs` — accept `emitActivities` flag; gate `StartActivity`/`Dispose` on it; add `ActivityEvent` annotations at every lifecycle boundary. * `src/Squad.Agents.AI/SquadAgentOptionsConfigurator.cs` — accept a list of candidate connection-string names; first non-empty wins. * `src/Squad.Agents.AI/SquadServiceCollectionExtensions.cs` — new `GetConnectionStringNames` returns `[name, "squad-"+name]` so both Aspire and legacy conventions resolve. * `src/Squad.Agents.AI/Squad.Agents.AI.csproj` — bump 0.3.0 → 0.4.0. * `src/Squad.Agents.AI/README.md` — new "Subagent observability" section, updated "Aspire / configuration path" section, two new option rows in the Key Options table. ## Backward compatibility Fully backward compatible. The two-arg `SquadSubagentTraceMapper` constructor defaults `emitActivities` to `true`, `EmitSubagentActivities` defaults to `true`, and the legacy `ConnectionStrings:squad-{name}` lookup still resolves. Net change for an existing consumer that had OnSubagentTrace set: nothing (mapper runs in both 0.3.0 and 0.4.0 because OnSubagentTrace is non-null). Net change for a consumer that did NOT set OnSubagentTrace but did AddSource: they now get spans they always asked for. Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Squad.Agents.AI 0.5.0: auto-inject --agent squad (CLI parity by default) (#1275) * Squad.Agents.AI 0.5.0: auto-inject --agent squad (CLI parity by default) The whole point of SquadAgent is to wrap a Squad coordinator team — but the 0.4.x SDK launched the underlying copilot.exe with the CLI's built-in generic agent. The coordinator therefore had no instructions to eager-execute, fan out, or dispatch via the task tool, so it role-played responses inline. Concretely: this SDK call builder.Services.AddSquadAgent(o => o.SquadFolderPath = teamRoot); did NOT behave the same as running copilot --agent squad interactively against the same team root. Consumers had to remember to add `opts.CliArgs.Add(""--agent""); opts.CliArgs.Add(""squad"");` themselves, which is an SDK leak — the class is literally called SquadAgent. 0.5.0 makes --agent squad the SDK default: * New `SquadAgentOptions.AgentFileName` (defaults to `""squad""`). * On client construction, SquadAgent looks for `{teamRoot}/.github/agents/{AgentFileName}.agent.md`. If it exists, `--agent {AgentFileName}` is auto-prepended to the CLI args. * If the file is missing (folder not Squad-initialized), the inject is silently skipped and a Debug log line explains why. The CLI then starts with its default agent, which is what 0.4.x did anyway. * If the consumer already supplied `--agent X` in `CliArgs`, the explicit value wins and we do NOT add a second one. * Set `AgentFileName = null` (or whitespace) to opt out entirely. Net effect: SquadAgent.RunAsync now matches `copilot --agent squad` for any Squad-initialized team root, without the consumer doing anything. ## Tests 64 -> 71 tests, all passing on net8.0/9.0/10.0. New `SquadAgentDefaultAgentFlagTests` (uses a per-test temp dir to scaffold or omit the agent file deterministically): * Default AgentFileName is ""squad"" * Auto-inject when squad.agent.md exists * No inject when the file is missing (graceful degradation) * Explicit --agent in CliArgs wins (no second --agent added) * Custom AgentFileName=""data"" injects --agent data when data.agent.md exists * AgentFileName=null opts out entirely * AgentFileName=whitespace opts out entirely Backward compatibility: existing routing tests use a non-existent `C:\squad-team-root` path, so the file-existence check silently skips the inject — those tests continue to pass with no changes. ## Files * `src/Squad.Agents.AI/SquadAgentOptions.cs` — new `AgentFileName` property with XML doc covering the default, the opt-out, and the not-yet-initialized fallback. * `src/Squad.Agents.AI/SquadAgent.cs` — auto-inject logic in `CreateCopilotClient` (after the `--allow-all` block, before `options.CliArgs` are appended) with file-existence + already-supplied guards and a Debug log when the file is missing. * `src/Squad.Agents.AI/Squad.Agents.AI.csproj` — bump 0.4.0 -> 0.5.0. * `src/Squad.Agents.AI/README.md` — new ""Coordinator agent selection"" section with the precedence table; `AgentFileName` row added to Key Options table. * `+test/Squad.Agents.AI.Tests/SquadAgentDefaultAgentFlagTests.cs` Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * amend: use SessionConfig.Agent instead of --agent CLI args GitHub.Copilot SDK's SessionConfigBase exposes an Agent (string) property that is the first-class equivalent of the Copilot CLI's --agent flag. It discovers and loads .github/agents/{name}.agent.md exactly the same way the CLI does, but without us having to munge CliArgs. Switch the 0.5.0 default-coordinator-agent implementation: - SquadAgent now sets sessionConfig.Agent = options.AgentFileName (default ""squad"") right after constructing the SessionConfig, before ConfigureSession runs. - Drop the --agent CliArgs hack (we no longer need to detect ""did the consumer already pass --agent?"" because ConfigureSession naturally wins over our default). - Tests now assert against sessionConfig.Agent via reflection over the inner DelegatingAIAgent — exactly what consumers using ConfigureSession would see. - README ""Coordinator agent selection"" section reworded to say ""sets SessionConfig.Agent"" instead of ""auto-adds --agent"". 71/71 tests still pass on net8.0/9.0/10.0. The fifth new test (ConfigureSession_CanOverrideAutoSetAgent) explicitly proves the ConfigureSession callback can replace the auto-set value, which is the clean override path now that --agent CliArgs is gone. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Squad.Agents.AI 0.5.1: fix 0.5.0 regression — use --agent CLI flag (not SessionConfig.Agent) (#1277) 0.5.0 (#1275) replaced the previous --agent CliArgs approach with sessionConfig.Agent = options.AgentFileName, on the theory that the SDK property was the first-class equivalent of the CLI's --agent flag. It is not. SessionConfig.Agent looks up the name in the SDK's CustomAgents registry (programmatic agent definitions, never populated by SquadAgent), NOT in .github/agents/*.agent.md files on disk. The result was a runtime error on every RunAsync call against a Squad-initialised team: Communication error with Copilot CLI: Request session.create failed with message: Custom agent 'squad' not found Verified at GitHub.Copilot.SDK 1.0.0: * SessionConfigBase.Agent (string) — selects from CustomAgents * SessionConfigBase.CustomAgents (IList<CustomAgentConfig>) — programmatically defined inline agents (Name, Prompt, Tools, Skills, Model, etc.). Empty by default. * The CLI's --agent flag is currently the only path that reads .github/agents/{name}.agent.md on disk. 0.5.1 reverts to the original CliArgs implementation: * SquadAgent now auto-prepends '--agent {AgentFileName}' to combinedCliArgs (back to what 0.5.0 originally proposed before the SessionConfig.Agent detour). * The file-existence check at {teamRoot}/.github/agents/{name}.agent.md still gates the inject so non-Squad-initialized folders degrade gracefully (no --agent passed -> CLI uses default agent). * The 'consumer already supplied --agent in CliArgs' guard is back so the SDK does not add a duplicate. Tests: * New SquadAgentDefaultAgentFlagTests covers all seven cases via reflection over Connection.Args (the CLI-args path the SDK actually uses): default 'squad' value, auto-inject when file exists, no inject when missing, explicit --agent wins, custom AgentFileName works, AgentFileName=null/whitespace opts out. * The older SquadAgentDefaultAgentTests (which targeted SessionConfig.Agent) is removed since that property does NOT do what we wanted. 71/71 tests passing on net8.0/9.0/10.0. Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add squad registry add/list/remove for discovery-only peer squads (#1291) Closes #1290. Adds CLI surface for managing .squad/squad-registry.json, symmetric to squad upstream. Registry entries are discovery-only (visible to squad discover and squad delegate) but do NOT trigger inheritance of the peer squad's skills/decisions/wisdom/routing. Previously users had to hand-edit .squad/squad-registry.json — even the squad discover empty-state hint told them to "create a squad-registry.json" manually. This adds proper commands: squad registry add <name> <path> # validates manifest, refuses duplicate squad registry list # show all registered peers squad registry remove <name> # remove by name Also fixes a subtle path-semantics confusion: readManifest() now accepts BOTH the repo root AND a path with a trailing .squad segment. The docs and SKILL.md showed the .squad-suffixed form but the code previously joined .squad/manifest.json onto whatever you gave it, so the suffixed form silently failed empirical reproduction (discover returned nothing). Test coverage: 18 new tests in cross-squad-registry.test.ts covering the dual-path readManifest fix, registry round-trip, add/list/remove behavior including duplicate-name and invalid-manifest rejection, and end-to-end integration with discoverSquads. Also updates: - cross-squad SKILL.md (canonical + 2 template mirrors) to document the registry vs upstream distinction explicitly - squad discover empty-state hint to mention squad registry add - squad help text with the new commands - SDK exports for the new registry helpers + RegistryEntry/ AddRegistryEntryResult types End-to-end verified locally: - squad registry add (both repo-root and .squad-suffixed paths) - squad registry list (rich output) - squad registry remove (success + missing-name warning) - squad discover picks up registry entries with source=registry - 50/50 tests pass (32 existing + 18 new) - npm run build clean Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(cli): stop writing squad_state to ~/.copilot/mcp-config.json on every init/upgrade (#1296) (#1298) * fix(cli): stop writing squad_state to ~/.copilot/mcp-config.json on every init/upgrade (#1296) squad init (init.ts:408) and squad upgrade (upgrade.ts:738) unconditionally called ensureSquadStateMcpInUserConfig, writing squad_state_<hash> to ~/.copilot/mcp-config.json keyed by a stable project-path hash. Each 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, which says iter-8 stops writing to HOME and writes squad_state ONLY to repo-root .mcp.json. The repo-root .mcp.json writes (init.ts:403 / upgrade.ts:728) already cover all documented Copilot CLI launch modes - copilot and copilot -p both walk up from cwd to find .mcp.json. Out-of-tree copilot -p invocations should use --additional-mcp-config @.mcp.json (already documented at init.ts:494). Changes: * Removed the unconditional ensureSquadStateMcpInUserConfig call from init.ts:408 and upgrade.ts:738. Replaced both with comments explaining iter-8 + #1296. * Removed the now-unused import from both files. * Kept the function definition at mcp-root.ts:178-228 - a future squad doctor --mcp-prune cleanup helper may want to inspect HOME. Tests: * New regression test in test/cli/init.test.ts: "should NOT write any squad_state entries to ~/.copilot/mcp-config.json (#1296)". Isolates the developer's real HOME by setting USERPROFILE/HOME to a temp dir before init, asserts no squad_state* keys appear under temp HOME. * All 40 existing init tests still pass. npm run lint clean. Closes #1296 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: comments reference actual Copilot CLI version (≥1.0.59), drop hardcoded test line numbers Reviewer follow-ups on #1298 (closes #1296): 1. The comments in init.ts/upgrade.ts/mcp-root.ts referenced 'Copilot CLI 5.3+' as the version that auto-loads .mcp.json. The real shipping CLI is at 1.0.62 (5.3 was a typo'd projection from review). Updated all 5 occurrences to '≥1.0.59' — the lowest version where the .mcp.json walk-up behavior is documented. 2. The init.test.ts regression comment hard-coded line numbers (init.ts:408, upgrade.ts:738) that will go stale on any unrelated edit to those files. Rewrote the comment to identify the call by function name (ensureSquadStateMcpInUserConfig) instead — durable against re-orderings. Verified: regression: #1296 test still passes (1/16 in init.test). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(init): post-init package.json script tip includes --agent squad The post-init tip showing how to add a non-interactive `squad:copilot` script to package.json was: "squad:copilot": "copilot --additional-mcp-config @.mcp.json" This omits `--agent squad`, so users who copy/paste it get a generic Copilot CLI session that doesn't load the Squad coordinator, team.md, casting, or MCP-wired memory/state tools — only the additional MCP config gets loaded. Same underlying issue surfaced in the cross-squad- communication SKILL.md sweep (squad/wire-cross-squad-skill commit 6b0eac21): anywhere we spawn `copilot` into a Squad-initialised repo, we must pass `--agent squad`. Single-line fix: "squad:copilot": "copilot --agent squad --additional-mcp-config @.mcp.json" Verified: a fresh `squad init` smoke test now prints the corrected tip line verbatim. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> * fix(sdk): wire team.md/routing.md/casting state on \squad preset apply\ (#1288) (#1293) * fix(sdk): wire team.md/routing.md/casting state on `squad preset apply` (#1288) `squad preset apply <name>` only copied agent charters into .squad/agents/. It left .squad/team.md `## Members` empty, .squad/routing.md missing `## Work Type -> Agent` rows, and never created .squad/casting/registry.json, history.json, or policy.json. Net result: the coordinator's mode-switch check saw an empty Members table and treated every session as Init Mode, proposing to re-scaffold the team the user already applied. This change adds a merge-friendly scaffold module (packages/squad-sdk/src/presets/scaffold.ts) that runs after charters are copied and: * writes/updates team.md `## Members` (creates from scratch if missing; appends new rows to an existing table while preserving the surrounding Coordinator / Project Context sections; idempotent on repeat apply) * writes/updates routing.md `## Work Type -> Agent` (creates or appends) * writes/merges casting/registry.json (universe = `preset:<name>`) * appends a snapshot to casting/history.json + a universe_usage_history entry * creates casting/policy.json with defaults only if missing (never clobbers) Agents with `status: 'error'` are excluded from wiring; agents with `status: 'skipped'` (already exist in target) ARE wired so the team reflects user intent. Scaffolder failure is reported as a synthetic error result without masking the per-agent install results. Verified: * npm run lint passes * test/presets.test.ts: 28/28 pass including 4 new regression tests - wires preset agents into team.md ## Members (#1288) - merges preset agents into an existing team.md without duplicating rows - writes casting registry.json, history.json, and policy.json (#1288) - appends routing rows for preset agents to routing.md (#1288) Out of scope (tracked separately): deduplicating these writers with the equivalent fresh-write versions in packages/squad-cli/src/cli/core/cast.ts. Closes #1288 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(presets): role-aware Status cell + non-colliding sentinel for synthetic scaffold error Two reviewer follow-ups on #1293 (closes #1288): 1. Members-table Status was hardcoded to '✅ Active' for every preset agent. Presets that ship one of the always-on built-ins (Scribe, Ralph, Rai, Fact Checker) would render with the wrong status label compared to a fresh cast: '✅ Active' instead of '📋 Silent' / '🔄 Monitor' / '🛡️ RAI' / '🔍 Verifier'. Added a small statusForRole() helper that mirrors the role→status mapping in cast.ts:652-655 (case-insensitive role matching to tolerate preset authors who lowercase the role string). Built-in role names get their canonical labels; everything else falls back to '✅ Active'. Added a regression test asserting the labels for a preset that ships scribe/ralph/rai/fact-checker + one regular agent. 2. Synthetic scaffold-failure result row used 'agent: presetName' for its 'agent' field. If the preset itself happens to include an agent literally named after the preset ('squad preset apply geektime' on a preset whose roster has a 'geektime' agent), the consumer of PresetApplyResult[] could not distinguish the synthetic scaffold- level error from a real per-agent install error. Replaced with the angle-bracketed sentinel '<scaffold>' (which validateName() rejects, so it can never collide with a real agent name) and moved the preset name into the human-readable reason string so consumers don't lose that context. Verified: 29/29 preset tests pass (28 existing + 1 new role-status test). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> * fix(docs): tell coordinator to roster Fact Checker on first-time cast (#1299) (#1300) * fix(docs): tell coordinator to roster Fact Checker on first-time cast (#1299) squad init correctly creates .squad/agents/fact-checker/ on disk (per merged PR #1223). But when the user opens copilot --agent squad and the coordinator runs first-time casting, it OMITS Fact Checker from the team.md ## Members table while including Scribe, Ralph, and Rai. Root cause: .squad-templates/squad.agent.md had two gaps: 1. Line 56 said "team size (typically 4-5 + Scribe)" — naming only Scribe 2. Rai had a dedicated ## Rai section with explicit "Rai always appears in team.md" instruction — Fact Checker had no equivalent section So the model added Rai (because instructed to) but had no instruction to add Fact Checker, even though the agent dir was scaffolded on disk. Fix: * Update team-size line to name all 4 always-on built-ins: Scribe + Ralph + Rai + Fact Checker * Add full ## Fact Checker — Verification & Devil's Advocate section mirroring the Rai pattern: roster-entry instruction, dual operating mode (per #789 + #1254), trigger phrase table, confidence ratings, DA brief structure, boundaries, state location Sync via sync-templates.mjs --sync propagates squad.agent.md changes to all 4 mirror targets: .squad-templates/, templates/, packages/squad-cli/ templates/, packages/squad-sdk/templates/, .github/agents/. Tests: new test/squad-agent-roster.test.ts runs against all 4 template targets and asserts: * The "Determine team size" line names all 4 built-ins * A ## Fact Checker section exists with "always appears in team.md" * The section declares dual operating mode (anchors #789 + #1254 design so a future PR can't accidentally split Fact Checker and Devil's Advocate again — cf. closed PR #1294) * Existing Ralph + Rai sections still present 16/16 pass. Closes #1299 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * doc(squad.agent.md): clarify Fact Checker is exempt from casting + correct on-demand reference path Reviewer follow-ups on #1300: 1. Team-size phrasing — the line read 'typically 4-5 + Scribe + Ralph + Rai + Fact Checker' which a model could parse as arithmetic (4-5 + 4 = 8-9, but it could also collapse). Rewrote it to make the composition explicit: '4-5 cast (user-domain) agents + 4 always-on built-ins = 8-9 total roster entries'. 2. Cast-exemption parity — Scribe, Ralph, and Rai each have an explicit 'exempt from casting' bullet but Fact Checker did not. Added the matching bullet right after Rai's. 3. Bad on-demand reference path — the FC section pointed at '.squad/templates/fact-checker-charter.md'. That file IS shipped (TEMPLATE_MANIFEST destination 'templates/fact-checker-charter.md') but only AFTER 'squad init' or 'squad upgrade' has populated .squad/templates/. A reader of squad.agent.md on an un-initialized repo (or in .github/agents/ on the cloud agent surface) would follow a dead link. Repointed to the '.squad/agents/fact-checker/charter.md' instance that ensureBuiltinAgents creates as part of the same init/upgrade path — that's where the rich charter actually lives at runtime per #1299 + #1301. All 4 mirrored copies re-synced via scripts/sync-templates.mjs. fact-checker-role.test.ts: 8/8 pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> * fix(sdk): plumb Fact Checker like Rai — rich charter at init + .squad/fact-checker/ state dir (#1299 deep) (#1301) * fix(sdk): plumb Fact Checker like Rai — rich charter at init + .squad/fact-checker/ state dir (#1299 deep) PR #1300 fixed the documentation gap so the coordinator knows to roster Fact Checker. This PR fixes the structural gap behind it. Per user testing 2026-06-13: even after #1300 the actual agent on disk was still "a name on disk with a 21-line placeholder". Three structural problems: 1. squad init never used the rich {role}-charter.md templates. Both Rai and fact-checker got 478-byte generic stubs from generateCharter(). Rich templates only ran via squad upgrade's ensureBuiltinAgents path. 2. fact-checker had no state dir. Rai gets .squad/rai/{policy.md, audit-trail.md} via init.ts lines 879-941. fact-checker had nothing equivalent. 3. fact-checker-charter.md was only in packages/squad-cli/templates/ — missing from .squad-templates/ (canonical source) AND packages/ squad-sdk/templates/. SDK init's getSDKTemplatesDir() resolves to the SDK templates dir, so even if init tried to read the rich charter, the file wasn't there. Fix (4 parts): Part 1 - Rich charter at init (benefits BOTH Rai and fact-checker): * SDK 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. * Result: fresh squad init produces .squad/agents/Rai/charter.md at 4525 bytes (full Rai charter) and fact-checker/charter.md at 3024 bytes (full FC charter). Previously both were 478-byte stubs. Part 2 - .squad/fact-checker/ state dir mirroring .squad/rai/: * New block in init.ts (right after the Rai seeding) creates .squad/fact-checker/policy.md (from templates/fact-checker-policy.md or inline fallback) and audit-trail.md. * New .squad-templates/fact-checker-policy.md (~6KB) is the canonical authority for dual-mode operating rules per #789 + #1254: - Mode 1 Verification: ✅/⚠️/❌/🔍 confidence rating taxonomy - Mode 2 Devil's Advocate: required brief structure - Hard anti-fabrication rules - Advisory by default with narrow blocking exceptions - Audit trail rules (succinct, never raw source) Part 3 - Fix .squad-templates/ distribution gap: * Copied fact-checker-charter.md into .squad-templates/ so sync-templates.mjs propagates it to all 4 mirror targets including packages/squad-sdk/templates/. This unblocks Part 1. Part 4 - Plumbing: * .gitattributes: .squad/fact-checker/audit-trail.md merge=union * TEMPLATE_MANIFEST: fact-checker-policy.md * squad.agent.md Files Catalog: 2 new rows for FC state files Tests: 3 new regression tests in test/init.test.ts (28/28 pass total). 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 PRs modify squad.agent.md in disjoint regions and merge in either order. Full plumbing requires BOTH to land. Closes #1299 (deep fix; #1300 was the surface fix) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(sdk): lowercase fallback for rich-charter template lookup + sync .github/agents Two reviewer follow-ups on #1301 (#1299 deep): 1. Case-sensitive FS bug in rich-charter lookup The lookup tried '\-charter.md' and '\-charter.md' only. For Rai (role='Rai', name='Rai') this becomes 'Rai-charter.md', but the actual file shipped lowercase ('rai-charter.md'). On Windows the lookup succeeded because the filesystem is case-insensitive; on Linux CI it silently missed and fell back to the 478-byte generic stub — exactly the regression #1299 was trying to fix. Reproduced by 'should use the rich Rai-charter.md template at init' failing with 'expected 476 to be greater than 1000' on GitHub Actions. Add toLowerCase() candidates after the exact-case ones. De-dupe via a Set so we don't double-stat when role and name are already lowercase (fact-checker case). Guard each candidate against blank keys. 2. Template-sync parity The canonical .squad-templates/squad.agent.md gained two Fact Checker rows in the Files Catalog but the mirrored .github/agents/squad.agent.md copy was never re-synced, so the template-sync.test.ts byte-for-byte parity check would have fired. Run 'node scripts/sync-templates.mjs --sync' to regenerate. Verified: vitest 'rich Rai-charter' passes locally after the fix (previously failing on Linux CI run 27464079078). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> * fix(skills): rename squad disambiguation skill to squad-help (supersedes #1297) (#1302) * fix(skills): rename disambiguation skill 'squad' -> 'squad-help' (supersedes #1297) PR #1297 added a disambiguation skill named 'squad' so models calling skill(Squad) would get a redirect. After local end-to-end testing on 2026-06-13: 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 app.js): 1. Copilot CLI's skill schema is {name, description, source, baseDir, allowedTools, pluginName, pluginVersion} (line 989). Frontmatter fields 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. Fix: * Rename 'squad' -> 'squad-help' (avoids the agent-name collision; still descriptive enough for natural-language match when user says 'how do I use squad' or 'squad help') * SKILL.md content: name: 'squad-help', removed unused triggers:/domain:/ confidence:/source:/license: fields, added allowedTools: [], rewrote description: to be self-explanatory, added explicit note that /squad slash command does NOT exist (slash commands are CLI built-ins, not auto-mapped from skills) * MANIFEST_SKILL_NAMES in sdk-init.ts: 'squad' -> 'squad-help' * New TEMPLATE_MANIFEST entry in templates.ts for squad-help (so squad upgrade also propagates the skill - that code path uses TEMPLATE_MANIFEST instead of MANIFEST_SKILL_NAMES) Tests: new test asserts .copilot/skills/squad-help/SKILL.md exists with right frontmatter; explicit regression guard against re-introducing name: 'squad'. 26/26 init tests pass. npm run lint clean. Supersedes #1297. Out of scope (separate issue worth filing): squad upgrade synced only 10 of 16 installed skills - TEMPLATE_MANIFEST (used by upgrade) is out of sync with MANIFEST_SKILL_NAMES (used by init). Skills from PRs #1292 + #1295 (tiered-memory, iterative-retrieval, reflect, cross-squad, cross-squad-communication) have entries in MANIFEST_SKILL_NAMES but not TEMPLATE_MANIFEST. Follow-up will fix. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(skill): add confidence + domain frontmatter to squad-help Reviewer follow-up on #1302: the isSkillContent() classifier in sharing/consult.ts:990 requires BOTH name: AND confidence: in the frontmatter to recognize a file as a skill. Without confidence:, squad-help would not be detected as a skill in cross-squad merge / share / promote flows — it would be misclassified as a generic markdown decision. The Copilot CLI itself silently ignores custom frontmatter fields (per sdk/index.js decompile — only name/description/allowedTools/ user-invocable are read), so adding confidence: high and domain: squad-onboarding is safe at the CLI surface and necessary at the SDK surface. Applied identically to all 3 mirrored copies of squad-help/SKILL.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.…
…te skills (#1311) * feat(prompt): slim squad.agent.md by extracting 3 sections to satellite skills (#1308 phase 1) squad.agent.md is loaded as the agent prompt at every Copilot session start. v0.10.0-insider.1 ships it at 81 KB / 1137 lines and the v0.10 stabilisation pass alone added +10.6 KB / +114 lines. Every byte is paid at every session. Phase 1 fix: extract three low-cross-reference, high-byte sections to satellite skills the coordinator loads on demand via the skill tool — same pattern that worked for cross-squad-communication (#1295). - coordinator-init-mode — Init Mode Phase 1 + Phase 2 (5.4 KB) - coordinator-source-of-truth — Source of Truth Hierarchy (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). 19 skills installed at .github/skills/ (was 16). Behaviour unchanged — each removed section is replaced with a stub naming the trigger condition and instructing the coordinator to skill(coordinator-X) before acting. Sections that stay in squad.agent.md (intentional): - Team Mode + state-backend handshake + HARD RULE — handshake must fire before any state write - Routing table — hit on every user prompt - Hard trigger keyword-to-skill match paragraph (#1307) — load-bearing - How to Spawn an Agent — referenced from every routing action - Coordinator Identity / Personal Squad / Memory Governance Tools — frequently re-read inline Wired changes: - New canonical sources at .squad/skills/coordinator-{x}/SKILL.md plus 2 template-dir mirrors - MANIFEST_SKILL_NAMES grows by 3 entries (16 → 19) - TEMPLATE_MANIFEST grows by 3 entries with ../.github/skills/ destinations (post-#1304 install location) - .squad-templates/squad.agent.md replaces each section with a stub - 4 mirrored squad.agent.md copies re-synced via scripts/sync-templates.mjs --sync Tests: 287/287 pass. The existing 'should install every manifest-curated skill (regression: bradygaster/squad#1289, #1264)' already iterates MANIFEST_SKILL_NAMES, so it automatically asserts the 3 new skills install. Smoke test: fresh squad init produces 19 skills at .github/skills/ and squad.agent.md is 70 KB. Follow-ups (separate PRs) for the still-large sections: - Routing (9.2 KB) — extract action-cell verbiage, keep trigger table - Team Mode (5.5 KB) — extract worktree-awareness sub-sections - How to Spawn (3.2 KB) — extract role-emoji catalog Target after 2-3 follow-ups: ~45 KB coordinator file. Closes #1308 (phase 1). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test+changeset: follow 'Determine team size' assertion to coordinator-init-mode skill CI failure on #1311: test/squad-agent-roster.test.ts asserted the 'Determine team size' line is in squad.agent.md.template, but after #1308 phase 1 that line moved into the coordinator-init-mode skill. Restructured the test into two describe blocks: 1. squad.agent.md.template — must still keep an Init Mode STUB that names the coordinator-init-mode satellite skill AND preserves the load-bearing eager-execution exception callout. This makes sure future edits can't accidentally drop the satellite reference. 2. coordinator-init-mode/SKILL.md (3 mirrors) — must contain the 'Determine team size' line naming all four built-ins, AND must mark each of Scribe/Ralph/Rai/Fact Checker as 'exempt from casting'. The regression coverage from #1299 follows the content. 22/22 tests pass. Also addressed the changeset review comment: clarified that .squad/skills/coordinator-*/SKILL.md are the canonical source files in the squad repo (where every other bundled skill source lives), and they're copied to .github/skills/ on install/upgrade per #1304. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: git-add the canonical .squad/skills/coordinator-*/ source dirs (review on #1311) Reviewer caught a real bug: the new coordinator-* skill source dirs existed in my worktree but had never been `git add`-ed because `.squad/` is gitignored on this repo (specific subpaths under it are exception-tracked). The template mirrors at packages/squad-{cli,sdk}/templates/skills/coordinator-*/ shipped fine, but the canonical sources at .squad/skills/coordinator-*/SKILL.md weren't in the tree — so: - The changeset claim that .squad/skills/coordinator-*/ is the canonical source was untrue on dev. - scripts/sync-skill-templates.mjs would not see the new skills when run from a fresh checkout, breaking the contributor workflow (canonical → mirrors). Sync would silently drop the 3 new skills on the next prebuild. Force-added the 3 dirs (`git add -f` because of the .squad/ ignore rule, same as every other tracked skill under .squad/skills/). Verified: `node scripts/sync-skill-templates.mjs` now lists coordinator-* among the 26 discovered skills and re-produces the 2 template mirrors byte-identical to the canonical sources. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: extractInitMode follows satellite skill + version regex tolerates pre-release tail Two narrow fixes uncovered while smoke-testing the slim squad.agent.md PR (#1311) and the 0.10.0-insider.1 release pipeline: 1. test/init-flow.test.cjs — after the Init Mode prose moved from squad.agent.md to the coordinator-init-mode satellite skill (#1308 / PR #1311), the structural assertions in 'Init Mode prompt structure (#66)' had nothing to read in the parent file. They now follow the pointer via the new readSatelliteSkill() helper (which prefers the installed copy at .github/skills/<name>/SKILL.md and falls back to the source repo template at packages/squad-sdk/templates/skills/), so the same gates (STOP/WAIT, 'Look right?', numbered confirm-before- create flow, Phase 2 trigger) keep being enforced — just against the prompt the coordinator actually loads at runtime. 2. test/version-stamping.test.cjs + index.cjs — the version regex [0-9.]+(?:-[a-z]+)? truncated pre-release versions with a numeric tail (e.g. 0.10.0-insider.1 → 0.10.0-insider, 0.10.0-build.3 → 0.10.0-build). That made the test 'upgrade detects same version' fail locally on any contributor who built the package (pkg.version gets stamped 0.10.0-build.N during build). More importantly it made the legacy index.cjs upgrade re-run the full upgrade flow for npm- installed insider users (who have 0.10.0-insider.1 on disk) instead of printing 'Already up to date'. Widened to [0-9.]+(?:-[a-z]+(?:\.[0-9]+)?)? — matches everything we already accepted plus the .N tail used by npm pre-release dist-tags and the build-time stamping script. All 133 .cjs tests now pass (was 123 pass / 10 fail before). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(docs): rephrase 'fenced code block' row in skill-security-scanner table CI failure on dev tip (567f447, Squad CI run 27488323855): test/docs-build.test.ts > 'all code blocks are properly fenced (even count of backticks)' → expected 1 to be 0 test/docs-build.test.ts > 'code blocks contain language specification or valid content' → expected 1 to be greater than 1 Root cause: a 4-backtick table cell intended to display a literal triple-backtick: | Inside a fenced code block (\\\\ \\\ \\\\) | Suppressed | made the regex /\\\/g see 5 triple-backtick occurrences across the file (instead of the 2 from the real bash example), tripping both the even-fence check and the line-count > 1 check. Rephrased the table to say 'three backticks' / 'single backtick' in prose — no embedded delimiters, no need to defend against the markdown fence escape mechanism. Reads cleaner anyway. Verified locally: 22/22 docs-build tests pass; npm run build in docs/ completes (171 files emitted; pagefind indexes 168 pages, 6911 words). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: auto-scaffold Fact Checker agent during init and cast (#1222)
The Fact Checker role landed in v0.10.0 (#789) with catalog entry,
charter template, skill, AGENT_TEMPLATES map entry, and template
manifest entry — but was never wired into the user-facing onboarding
flow. Users running 'squad init' got Scribe/Ralph/Rai but never saw
Fact Checker as a default or cast option.
This mirrors how Rai was wired:
- init.ts: adds 'fact-checker' to the default agents: array passed
to sdkInitSquad()
- cast.ts: adds factCheckerMember(), factCheckerCharter(),
hasFactChecker branches in castTeam(), and the roster banner line
Smoke-tested locally: 'squad init' in a clean repo now produces
.squad/agents/fact-checker/charter.md alongside scribe/ralph/Rai.
Closes #1222
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(upgrade): auto-scaffold Rai + Fact Checker on squad upgrade (#1222)
Extends the #1222 fix to the third code path. \squad upgrade\ was
intentionally silent on agents (preserves user state). For users
upgrading from v0.9.x or earlier (no Rai) or v0.10.0 (no fact-checker),
this means they'd never get the built-in agents unless they re-ran
\squad init\ (which would overwrite other state).
Adds \�nsureBuiltinAgents()\ to \
unEnsureChecks()\. Idempotent —
only scaffolds when the agent directory is absent. Never overwrites
existing charters or history files. Sources content from the shipped
\ emplates/{Rai,fact-checker}-charter.md\ templates (already present
via TEMPLATE_MANIFEST).
Scribe and Ralph are intentionally NOT scaffolded by upgrade — they
predate this fix in every squad, and their charters are inlined in
cast.ts (no shipped template file).
Smoke tested locally:
- Set up a simulated v0.9.4 squad (scribe + ralph only)
- Ran \squad upgrade\ → 'scaffolded 2 built-in agent(s): Rai, fact-checker'
- Ran upgrade again → no re-scaffold (idempotent)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(permissions): use 'approve-once' for Copilot CLI v1.0.54+ contract (#1192)
The Copilot CLI post-v1.0.54 changed the permission handler contract to
expect 'approve-once' instead of 'approved'. Update the handler, type
definition, and error hint to match the new contract.
Closes #1191
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: Squad.Agents.AI - Microsoft Agent Framework adapter for the Squad CLI (#1207)
* feat: Squad.Agents.AI community NuGet for MAF integration
Squad CLI as Microsoft.Extensions.AI IChatClient, composing
GitHub.Copilot.SDK via AsAIAgent() from Microsoft.Agents.AI.GitHub.Copilot 1.7.0-preview.
Closes Track A of the Q1-Q7 design lock (see tamresearch1 .squad/decisions.md
Decisions 441, 443, 444, 447).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: add PR body for #3
* fix(SquadAgent): inherit AIAgent (was IChatClient force-cast)
- SquadAgent now properly inherits from Microsoft.Agents.AI.AIAgent
- Removed (IChatClient)(object)agent force-cast
- Overrides all AIAgent abstract members (CreateSessionCoreAsync, RunCoreAsync, etc.)
- DI registration now registers AIAgent (not IChatClient)
- README updated to use AIAgent.RunAsync API
- No more abstraction inversion; AIAgent is the correct layer
Fixes the architectural error identified by Tamir.
* docs(SquadAgent): rewrite README — prerequisites, Hello World, troubleshooting, preview callout
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(SquadAgent): GitHubTokenProvider callback + redact options ToString
Adds async token provider pattern for production scenarios (KeyVault/MSI integration).
- GitHubTokenProvider property takes precedence over GitHubToken
- GitHubToken marked [JsonIgnore] to prevent serialization leaks
- SquadAgentOptions.ToString() redacts GitHubToken field
- Updated CreateCopilotClient to resolve token from provider first
Mitigates P0 #3: token leakage via ILogger structured-log calls, IOptions snapshots, and serializers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs(SquadAgent): document GitHubTokenProvider callback for production token management
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(SquadAgent): bind ConnectionStrings__squad via IConfigureOptions + add smoke tests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs(README): replace removed WithTeamRoot with positional teamRoot ctor
WithTeamRoot was deleted in commit 35767c90 in favor of mandatory positional
teamRoot constructor argument on AddSquad. The Aspire example in the
Squad.Agents.AI README still showed the old fluent API, which would now
fail at compile time for anyone copy-pasting.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test(squad-agents-ai): add routing integration tests
Closes the routing-verification gap identified during
squad-squad onboarding: the API surface existed but
routing semantics weren't functionally tested. New tests
verify persona pass-through, boundary-instruction injection
on first turn, WorkingDirectory isolation (Decision 452a),
and CopilotClientOptions-based routing (Decision 447).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci(squad-agents-ai): add .NET build/test/pack workflow
PR #3 CI was Node/docs-only — adding the .NET gate so green
actually reflects the package code. Matrix on ubuntu + windows,
restore/build/test/pack, uploads TestResults and nupkg artifacts.
Closes the build-verification gap identified during squad-squad
onboarding (see .squad/decisions.md adoption record, 2026-06-02).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci(squad-agents-ai): NuGet publish workflow + Dependabot config
- .github/workflows/squad-agents-ai-release.yml: workflow_dispatch
and tag-driven publish to nuget.org with --skip-duplicate idempotency,
fail-fast on missing NUGET_API_KEY secret, optional GitHub Release on tag
- .github/dependabot.yml: nuget (src + test) + github-actions, weekly,
M.A.AI major allowed, OpenTelemetry major deferred (per Decision 602)
Closes the release-pipeline + supply-chain-tracking gaps identified
during squad-squad onboarding.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs(squad-agents-ai): release-ready docs + .csproj packaging metadata
- README updates / XML docs on public surface
- CHANGELOG.md with [0.1.0-preview] - 2026-06-02 entry
- .csproj: Description, RepositoryUrl, Authors, PackageTags, PackageReadmeFile
- Verified via dotnet pack — .nupkg contains README, LICENSE, xml-docs
Closes the docs-readiness gap for v0.1-preview publish.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci(squad-agents-ai): switch release triggers to dev/main branch-driven
Per Tamir's release-strategy directive (decisions.md 2026-06-02):
- dev merges → prerelease publish (suffix scheme mirrors Squad CLI)
- main merges → stable publish
- workflow_dispatch retained as manual escape hatch
- tag-driven trigger removed (branches are the source of truth)
Version derivation pattern adapted from the Squad CLI's existing
release workflow. --skip-duplicate retained for idempotent reruns.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs+fix: PR #3 review pass — hygiene, XML docs, cliArgs, multi-named connections
- Rewrite the package README and PR validation flow around the AIAgent surface and ambient Copilot authentication.
- Keep public docs free of internal process references and remove obsolete deferral language.
- Preserve connection-string cliArgs through CopilotClientOptions and cover the behavior with a routing test.
- Add named connection-string lookup via AddSquadAgent("name") using ConnectionStrings:squad-{name}.
- Document the new public overloads and verify the package builds without warnings.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: Round 2 — keyed DI, BYOK delegate, routing gate, security hardening
- Add ConfigureCopilotClient delegate on SquadAgentOptions for BYOK
- Add routing gate: snapshot/restore Cwd/CliPath/CliArgs after delegate (Picard C1)
- Add 4 AddKeyedSquadAgent overloads with .NET 8+ keyed DI
- Fix Environment credential leak: [JsonIgnore] on Environment, GitHubTokenProvider, ConfigureCopilotClient
- ToString() redacts token-pattern keys (TOKEN/KEY/SECRET/HMAC/PASSWORD/CREDENTIAL)
- Add 21 new tests (43 total): security redaction, keyed DI, BYOK routing gate
- Update README: streaming, keyed DI, BYOK, security sections
Complies with: Picard C1-C4, Worf SC-1 through SC-8.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: add Squad.Agents.AI sample app demonstrating DI, keyed DI, BYOK, and streaming
- samples/squad-agents-ai-sample/Program.cs: four runnable flows
Flow 1 -- AddSquadAgent + RunAsync (basic DI)
Flow 2 -- AddKeyedSquadAgent x2 + GetRequiredKeyedService<SquadAgent>
Flow 3 -- ConfigureCopilotClient delegate (BYOK token + env var injection)
Flow 4 -- RunStreamingAsync with await foreach token-by-token output
- samples/squad-agents-ai-sample/Squad.Agents.AI.Sample.csproj: net10.0,
project reference to src/Squad.Agents.AI, Microsoft.Extensions.Hosting 10.0.0
- samples/squad-agents-ai-sample/README.md: prerequisites, run commands,
per-flow walkthrough, troubleshooting table
- .github/workflows/squad-agents-ai-ci.yml: adds paths trigger and
restore + build steps for the sample (no run step -- requires live CLI)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor(Squad.Agents.AI): co-locate sample under src/ and consolidate README
- Moves the sample app from samples/squad-agents-ai-sample/ to
src/Squad.Agents.AI/samples/Squad.Agents.AI.Sample/ so it lives
alongside the package it demonstrates.
- Folds the sample's standalone README into the package README, giving
consumers one canonical doc for both the API and the runnable demo.
- Adds <Compile Remove="samples/**/*.cs" /> to Squad.Agents.AI.csproj
so the library's wildcard glob does not pick up Program.cs in the
co-located samples subdirectory.
- Updates the .csproj project reference, and CI workflow paths to match
the new layout.
- Verified end-to-end: dotnet build, dotnet test (43/43 passing), and a
sample sanity-check run (clear CLI-not-found error, no stack trace).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore(Squad.Agents.AI): remove outdated draft PR body file
The standalone pr-body.md was an early draft authored before the live PR description took its final shape. The PR body on GitHub is the canonical source; this file is dead weight and would confuse maintainers reviewing the diff.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(Squad.Agents.AI): address PR #1207 reviewer feedback (12 items)
- Snapshot CliArgs by value, not reference, so in-place mutation by SDK consumers
is also caught by the routing guard.
- Validate name/connectionName/serviceKey is non-empty in all DI registration
overloads; previously null/whitespace produced invalid connection-string keys.
- Replace ghp_-prefixed placeholder in the sample with a clearly-fake token to
avoid tripping secret-scanning and to remove a real-token lookalike.
- Remove brittle 'PR #3' references from README and CHANGELOG; describe the
feature without tying to a specific PR thread.
- Update NuGet metadata and README links to point to bradygaster/squad (canonical
repo) instead of the tamirdresher fork.
- Multi-target the test project to match the package's target framework set so
CI exercises every framework the package ships against.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* refactor(Squad.Agents.AI): adopt DelegatingAIAgent base + MAF ctor pattern (PR #1207 r2)
Addresses westey-m's review feedback:
- Extend Microsoft.Agents.AI.DelegatingAIAgent — drops ~70 lines of
manual Core* overrides; pass-through is provided by the base class.
- Adopt MAF constructor pattern: \(string squadFolderPath,
SquadAgentOptions? options = null, ILoggerFactory? loggerFactory = null)\.
Required settings on the constructor, options optional, ILoggerFactory
stays on ctor for DI injection.
- Routing-guard, IAsyncDisposable, and security posture preserved.
- Add Squad.Agents.AI.slnx solution for easy IDE open.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Reno (Copilot) <reno@clawpilotsquad.dev>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: tamirdresher <tamirdresher@users.noreply.github.com>
* ci(Squad.Agents.AI): switch NuGet publish to Trusted Publishing (OIDC) (#1240)
Replace the long-lived NUGET_API_KEY repo secret with NuGet/login@v1 OIDC
token exchange (1-hour API key) per the modern Trusted Publishing flow:
https://learn.microsoft.com/nuget/nuget-org/trusted-publishing
Why
---
- No long-lived credentials stored in the repo.
- Token is scoped to this workflow + repo + branch via the OIDC subject claim
and the Trusted Publishing policy registered on nuget.org.
- Eliminates the chicken-and-egg between needing admin to set NUGET_API_KEY
and needing the package live to validate the workflow.
What changed
------------
- Add `id-token: write` to the publish job (required for OIDC).
- Drop the `Verify NuGet API key` step.
- Drop the `--api-key ` reference to secrets.NUGET_API_KEY.
- Add `NuGet/login@v1` step that exchanges the OIDC token for a short-lived
API key, exposed via `steps.nuget-login.outputs.NUGET_API_KEY`.
- Add a fail-fast check for the new `vars.NUGET_USER` repository variable
(non-sensitive; the nuget.org profile name that performs the exchange).
- Update the file header documentation to reflect the new flow and link to
the Trusted Publishing setup page.
Required configuration before first publish
-------------------------------------------
1. Create the `Squad` organization on nuget.org and add owners.
2. Configure a Trusted Publishing policy at
https://www.nuget.org/account/trusted-publishing owned by the Squad org:
Repository Owner: bradygaster
Repository: squad
Workflow File: squad-agents-ai-release.yml
Environment: (empty)
3. Set repository variable NUGET_USER (Settings → Secrets and variables →
Actions → Variables) to a Squad-org-member's nuget.org profile name
(NOT email). Variable, not secret — the username is non-sensitive.
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(Squad.Agents.AI): expose SessionConfig + default OnPermissionRequest (#1252)
Squad.Agents.AI 0.1.0-preview.2 calls `CopilotClient.AsAIAgent(instructions, name)`
which leaves `SessionConfig.OnPermissionRequest` unset. The first call to
`SquadAgent.CreateSessionAsync()` therefore throws:
System.ArgumentException: An OnPermissionRequest handler is required when
creating a session. For example, to allow all permissions, use
CreateSessionAsync(new() { OnPermissionRequest = PermissionHandler.ApproveAll });
There was no public way for consumers to fix it from the outside —
`ConfigureCopilotClient` only exposes `CopilotClientOptions`, not the per-session
`SessionConfig` that owns the permission handler.
What changed
------------
- `SquadAgent` now switches to the `AsAIAgent(client, sessionConfig, ...)` overload
and constructs a `SessionConfig` with:
- `OnPermissionRequest = PermissionHandler.ApproveAll` (sensible default for
a host-process Squad adapter; the host already chose to instantiate Squad
and is responsible for sandboxing).
- `WorkingDirectory` defaulting to the resolved `Cwd` / `SquadFolderPath`.
- `SystemMessage = new SystemMessageConfig { Content = Instructions }` when
`SquadAgentOptions.Instructions` is set.
- `SquadAgentOptions.ConfigureSession: Action<SessionConfig>?` is new — runs
after Squad applies its defaults so a consumer can swap in a stricter
permission handler, pin the model, restrict tools, etc.
Tests
-----
- New `SquadAgentSessionConfigTests` (4 cases) exercising the new surface:
`ConfigureSession` is settable, runs against the live SessionConfig, can
replace the permission handler, and can set `AvailableTools`.
- All existing 43 tests still pass per TFM (141 total across net8/9/10).
Verified
--------
- The end-to-end consumer smoke test in
`C:\Users\tamirdresher\source\repos\squad-agents-ai-consume-test` previously
had to fall back to the raw SDK because of the missing handler. With this
change, `SquadAgent.CreateSessionAsync()` returns successfully and
`RunAsync` drives real 3-turn conversations against `.squad/`-init'd teams.
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Squad.Agents.AI 0.2.0: bump to MAF 1.10.0-rc1 / SDK 1.0.0 GA — file-IO works (#1259)
* Squad.Agents.AI: bump to MAF 1.10.0-rc1 / SDK 1.0.0 GA — file-IO now works
Microsoft.Agents.AI.GitHub.Copilot bumped from 1.7.0-preview to 1.10.0-rc1,
which transitively brings GitHub.Copilot.SDK 1.0.0 GA. SDK 1.0.0 reshaped
CopilotClientOptions and SessionConfig (the breaking namespace + property
renames are mirrored below), but in return Copilot CLI 1.0.61 talks to the
SDK over the new ACP-style protocol — meaning the agent's view/grep/powershell
tools finally work end-to-end without 'permission errors' or 'content
exclusion policy' hallucinations.
SDK 1.0.0 API migrations applied:
* Namespace GitHub.Copilot.SDK -> GitHub.Copilot.
* CopilotClientOptions.Cwd -> WorkingDirectory.
* CopilotClientOptions.CliPath + .CliArgs collapsed into a single
CopilotClientOptions.Connection (RuntimeConnection). We now build the
Connection via RuntimeConnection.ForStdio(CliPath, CliArgs) only when the
consumer supplied either a custom CLI path or extra CLI args; otherwise
the SDK's default child-process connection is used and the bundled
copilot.exe (downloaded by the SDK's build/ targets) is invoked.
* SessionConfig.ConfigDir -> SessionConfig.ConfigDirectory.
* PermissionRequestHandler is no longer a named delegate type; we use
type inference where the test code referenced it.
Public Squad.Agents.AI surface is intentionally unchanged: SquadAgentOptions
still exposes Cwd, CliPath, CliArgs, ConfigureSession, ConfigureCopilotClient.
We translate to the SDK 1.0.0 shape internally.
Routing gate (Picard Condition 1 / Worf SC-3) updated to snapshot and restore
WorkingDirectory + Connection instead of the old Cwd / CliPath / CliArgs trio.
A delegate that REPLACES Connection (e.g. via RuntimeConnection.ForStdio(...))
is reverted, mirroring the previous CliPath / CliArgs hijack tests.
Verified end-to-end against a real .squad-initialised team root: the
coordinator successfully reads .squad/team.md and enumerates every cast
member with their role. The dotnet test suite passes 46/46 across net8.0,
net9.0, and net10.0 (-1 vs baseline because the old CliPath and CliArgs
hijack tests collapsed into a single Connection hijack test, which is the
right granularity for SDK 1.0.0).
Version bumped 0.1.0-preview -> 0.2.0 to surface the MAF/SDK transitive bump.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address Copilot review feedback (#1259)
- Remove duplicate 'using GitHub.Copilot' in SquadAgentSessionConfigTests
(regex replace inadvertently doubled the directive when migrating from
the old GitHub.Copilot.SDK namespace).
- Drop hardcoded teamRoot override I left behind in the sample Program.cs
during the CLI-not-found debug session. The sample now correctly reads
SQUAD_TEAM_ROOT (or falls back to CWD) as documented.
- Fix mismatched comment in SquadAgent: the SDK-protocol section now
correctly references --allow-all (matching the flag actually injected
in CreateCopilotClient), not the narrower --allow-all-tools.
- Detect more existing permission-opening flags before injecting our
default --allow-all so a host that opts in via --allow-all-paths,
--allow-all-urls, or the omnibus --yolo no longer gets --allow-all
prepended on top. Comparison is now case-insensitive. Updated the
connection-string test that asserted the old over-eager behavior.
Also add .vs/, *.user, *.userprefs to .gitignore so VS solution junk
doesn't surface in git status.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address pre-existing Copilot review comments from PR #1212 (#1258)
- Workflow permissions: add issues: write to squad-pr-nudge, squad-impact,
and squad-repo-health workflows that call issues.createComment
- Logic bug: fix ahead_by → behind_by in pr-nudge stale branch check
- Logic bug: fix PR_LABELS fallback producing string instead of null
- Script fix: check legacy statuses for failure/error in checkCIStatus()
- Script fix: truncation row column count mismatch in pr-readiness.mjs
- Script fix: validate JSON.parse result is array before using as labels
- Script fix: isNodeBuiltin now validates node: prefix against known builtins
- YAML escaping: use JSON.stringify for skill descriptions in apm.yml
Closes #1213
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: expose memory tools via MCP + route writes through governed pipeline (#1251)
- Expose memory.classify, memory.write, memory.search, memory.promote,
memory.delete, memory.audit through the squad_state MCP server (#1244)
- Pin squad_state to user-level ~/.copilot/mcp-config.json during
init/upgrade for external `copilot -p` mode compatibility (#1247)
- Update squad.agent.md directive-capture and decision-recording
instructions to route through memory.write instead of raw
squad_state_write to the drop-box (#1246)
Closes #1244
Closes #1247
Closes #1246
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs(skills): update path references from .squad/skills/ to .copilot/skills/ (#1260)
The CLI and SDK write skills to .copilot/skills/ by default, but docs
still referenced .squad/skills/. Update all documentation to use the
canonical .copilot/skills/ path and add a note about legacy fallback.
Closes #1241
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(init): prompt to add @copilot as a team member during squad init (#1262)
Add an interactive prompt during squad init that asks users if they
want to add @copilot (the GitHub Copilot coding agent) as an autonomous
team member. If accepted, 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.
Closes #1147
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: align skills path + state-backend upgrade flow (#1241, #1226) (#1249)
- Update all docs references from .squad/skills/ to .copilot/skills/
- Note that both paths are scanned at read time but .copilot/skills/ is write default
- List all 6 git hooks (add pre-commit and post-commit to docs)
- Correct 'read-only reference' claim about migrated files
- Add recovery section for pre-commit hook refusal scenarios
Closes #1241
Closes #1226
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Squad.Agents.AI 0.3.0: first-class subagent observability (#1265)
Adds a typed OnSubagentTrace callback + OpenTelemetry ActivitySource so consumers
can see subagent dispatch (the coordinator's 'task' tool spawning specialist
sub-agents and their replies) without writing their own polymorphic dispatch over
the raw GitHub.Copilot SessionEvent hierarchy.
The previous 0.2.x surface required consumers to write the same boilerplate the
aspire-squad-resource demo had to (CopilotSessionTraceMapper.cs): switch on every
event subtype, unwrap subagent context, manage Activity lifetime. 0.3.0 makes that
the SDK's job.
New public surface:
* SquadAgentOptions.OnSubagentTrace (Action<SquadAgentTraceEvent>)
Set this to subscribe to subagent lifecycle (Selected / Started / Completed /
Failed), assistant messages from coordinator AND subagents, tool start/complete,
and SessionIdle. Setting OnSubagentTrace implicitly turns on
SessionConfig.IncludeSubAgentStreamingEvents so subagent replies actually flow
up to the parent session (otherwise they stay inside the subagent session and
never reach the callback).
* SquadAgentTraceEvent record — typed envelope (Kind, RawEventType, Timestamp,
SdkAgentId, SubagentName, SubagentDisplayName, ToolCallId, Content, Success,
RawEvent). Carries the original SessionEvent on RawEvent for advanced consumers
but exposes everything else through neutral primitive types so the callback
signature has no transitive dependency on GitHub.Copilot.SDK.
* SquadAgentTraceEventKind enum — categorises the SessionEvent into the well-known
cases that downstream observability surfaces want.
* SquadAgentDiagnostics.ActivitySourceName ('Microsoft.Agents.AI.Squad') +
SquadAgentDiagnostics.ActivitySource — one Activity per subagent dispatch is
opened on SubagentStartedEvent and disposed on the matching
SubagentCompletedEvent / SubagentFailedEvent, tagged with squad.subagent.name,
squad.subagent.display_name, squad.subagent.sdk_agent_id, and
squad.subagent.reply_preview (a short truncated copy of the subagent's
assistant message). Hosts that .AddSource(SquadAgentDiagnostics.ActivitySourceName)
on their OpenTelemetry tracer get these spans in their backend — the Aspire
dashboard renders them in the trace view automatically.
Internal:
* SquadSubagentTraceMapper — wires SessionEvent -> SquadAgentTraceEvent and the
Activity lifecycle. Held by SquadAgent and disposed during DisposeAsync to
drain any subagent activities that never received a matching Completed event
(e.g. session ended mid-dispatch).
* InternalsVisibleTo=Squad.Agents.AI.Tests so the mapper can be unit tested
directly without spinning a real CLI session.
Tests: 54/54 passing across net8, net9, net10 (+8 new tests for the
observability surface including Activity lifetime, tag propagation, mid-session
disposal, and consumer-callback exception isolation).
Verified end-to-end against the tamresearch1 Star Trek squad: the OnSubagentTrace
callback observed two parallel subagent dispatches (Picard, Data), captured each
of their replies attributed to the right SdkAgentId, and the matching
'squad.subagent Picard' / 'squad.subagent Data' OTel spans opened and closed
cleanly with the reply tagged on each span.
Version bumped 0.2.0 -> 0.3.0 to signal the new public surface.
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore(lockfile): sync package-lock with package.json after v0.10.0 bump (#1266)
After the v0.10.0 stable release on 2026-06-07, the root package-lock.json
still recorded packages/squad-cli@0.9.6-preview.15 and
packages/squad-sdk@0.9.6-preview.13 for the workspace entries. The
package.json files were updated correctly during the release, but the
lockfile workspace metadata was not regenerated.
This causes `npm ci --ignore-scripts` to fail in the
`sdk-exports-validation` CI job whenever package.json versions diverge
from these stale lockfile entries (which happens on every build that
runs `scripts/bump-build.mjs`). Confirmed on PR #1257.
This commit regenerates only the workspace version metadata
(`packages/squad-cli` and `packages/squad-sdk`) — no dependency
trees are touched. Verified locally on Windows + Node v23.5.0:
- `npm ci --ignore-scripts` at repo root: ✅ exit 0 (was already passing
on dev because root package.json/lockfile match; failure mode is the
workspace-entry mismatch surfacing under specific build conditions)
- `npm install --ignore-scripts`: no further drift produced
- Full `npm test` suite: 6535 passed / 134 failed / 60 skipped — the
134 failures are all pre-existing Windows file-locking flakiness
(EBUSY/ENOTEMPTY/hook-timeout); identical failure mode and similar
count on the immediate pre-merge commit cc37a2f7 (125 failures
pre-merge, 134 post-merge — diff is within flake noise).
- Targeted re-run of the 5 "newly failing" files in isolation: 93/93
passing — confirms the bulk-run failures are concurrency-induced
flakes, not regressions from the recent merges (#1251, #1258, #1260,
#1262, #1249).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(bump-build): also update package-lock workspace entries (#1267)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: release pipeline version pinning (#1203, #1204) (#1250)
* 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 current version isn't yet
on the registry (Closes #1203)
- Add isLocalOrUnpublishedVersion guard so local dev builds and versions
with build metadata (+) fall back to @insider instead of writing
unresolvable version strings into MCP config (Closes #1204)
- Extend resolveSquadStateMcpSpec to short-circuit for build-metadata versions
- Add CI step to verify SDK dependency is resolvable before CLI publish
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: reset accidentally-bumped version 0.10.0-build.2 -> 0.10.0
Pre-publish version guard rejects -build.N suffixes (release pipeline
policy). The bump was made by an unintended local 'npm run build' run
before commit.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tamir Dresher <tamir.dresher@gmail.com>
Co-authored-by: Copilot <tamirdresher@users.noreply.github.com>
* chore: include CHANGELOG.md in published npm tarball (#1257)
* chore: include CHANGELOG.md in published npm tarball
Add CHANGELOG.md to the files array in both squad-cli and squad-sdk
package.json files so changelogs are included in published npm tarballs.
This enables offline what's-new prompts and removes the need for
GitHub API calls to show release notes.
Closes #1171
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: reset accidentally-bumped versions to 0.10.0
Pre-publish version guard rejects -build.N suffixes (release pipeline
policy). Both SDK and CLI package.json had -build.4 from a local
'npm run build' run before commit.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tamir Dresher <tamir.dresher@gmail.com>
Co-authored-by: Copilot <tamirdresher@users.noreply.github.com>
* Squad.Agents.AI 0.4.0: default-on subagent observability + Aspire-style connection-string lookup (#1271)
Two small but high-impact changes that remove ~30 lines of boilerplate from every
consumer (Aspire and otherwise) and make the OpenTelemetry story self-explanatory.
## 1. EmitSubagentActivities (default true) — telemetry independent of callback
Today, the per-subagent OpenTelemetry Activity emission is a side-effect of setting
`OnSubagentTrace`. A host that just wants `squad.subagent {Name}` spans in their
backend has to wire a callback they don't need. `Microsoft.Agents.AI.Squad` is
silent until then.
0.4.0 makes activity emission the default:
* New `SquadAgentOptions.EmitSubagentActivities` (defaults to `true`).
* `SquadAgent` installs `SquadSubagentTraceMapper` whenever
`EmitSubagentActivities || OnSubagentTrace != null`, so spans flow with zero
extra wiring.
* `OnSubagentTrace` becomes a pure customisation hook (logging, dashboards,
metrics) — independent of telemetry. Set `EmitSubagentActivities = false` to
opt out of built-in spans when you want to handle telemetry yourself.
Plus richer span shape: every lifecycle phase is now an
`ActivityEvent` on the live subagent span (visible as annotated markers on the
timeline in Aspire / Jaeger / etc.):
* `squad.subagent.start` — on SubagentStarted
* `squad.subagent.message` — on AssistantMessage (with message_preview tag)
* `squad.subagent.completed` — on SubagentCompleted
* `squad.subagent.failed` — on SubagentFailed
Net effect for a consumer:
builder.Services.AddOpenTelemetry()
.WithTracing(t => t.AddSource(SquadAgentDiagnostics.ActivitySourceName));
builder.Services.AddSquadAgent(o => o.SquadFolderPath = "/team");
…and the dashboard lights up. No callback wiring, no Activity.Current?.AddEvent
plumbing in the host.
## 2. Aspire-style connection-string lookup (with legacy fallback)
Aspire injects connection strings under the literal resource name —
e.g. an AppHost that calls `builder.AddSquad("research-squad", ...)` exposes
`ConnectionStrings:research-squad` to the consumer. The 0.3.0 SDK only looked at
`ConnectionStrings:squad-research-squad` (prefixed), so Aspire consumers had to
manually call `Configuration.GetConnectionString(name)`, parse the URI, and feed
`SquadFolderPath` into the configure callback themselves.
0.4.0 tries the literal name first and falls back to the legacy prefixed form:
| Style | Example | Lookup |
|--------------------------------------|---------------------------------------------|--------------------------------------------|
| Aspire-style direct (tried first) | `AddSquadAgent("research-squad")` | `ConnectionStrings:research-squad` |
| Legacy prefixed fallback | `AddSquadAgent("research")` | `ConnectionStrings:squad-research` |
Both work. Existing consumers using `ConnectionStrings:squad-{name}` continue
unchanged; new Aspire consumers get the natural one-line registration.
## Tests
54 → 64 tests, all passing on net8.0/9.0/10.0.
New `SquadAgentDefaultObservabilityTests` covers:
* Default-on activity emission (without consumer callback)
* Opt-out path (`EmitSubagentActivities = false`) — span suppression + callback
still fires
* Each ActivityEvent name (`start` / `message` / `completed` / `failed`)
* Connection-string precedence: Aspire-direct preferred, prefixed fallback used,
same rule applies for keyed registrations
Existing `SquadSubagentTraceTests` and the new class share an
`[Collection("SquadActivityListeners")]` so they run serially — process-global
`ActivityListener` state caused cross-test pollution otherwise.
## Files
* `src/Squad.Agents.AI/SquadAgentOptions.cs` — new `EmitSubagentActivities`
property + reworked `OnSubagentTrace` XML doc to clarify independence.
* `src/Squad.Agents.AI/SquadAgent.cs` — install trace mapper when telemetry OR
callback is requested.
* `src/Squad.Agents.AI/SquadSubagentTraceMapper.cs` — accept
`emitActivities` flag; gate `StartActivity`/`Dispose` on it; add
`ActivityEvent` annotations at every lifecycle boundary.
* `src/Squad.Agents.AI/SquadAgentOptionsConfigurator.cs` — accept a list of
candidate connection-string names; first non-empty wins.
* `src/Squad.Agents.AI/SquadServiceCollectionExtensions.cs` — new
`GetConnectionStringNames` returns `[name, "squad-"+name]` so both Aspire
and legacy conventions resolve.
* `src/Squad.Agents.AI/Squad.Agents.AI.csproj` — bump 0.3.0 → 0.4.0.
* `src/Squad.Agents.AI/README.md` — new "Subagent observability" section,
updated "Aspire / configuration path" section, two new option rows in the
Key Options table.
## Backward compatibility
Fully backward compatible. The two-arg `SquadSubagentTraceMapper` constructor
defaults `emitActivities` to `true`, `EmitSubagentActivities` defaults to
`true`, and the legacy `ConnectionStrings:squad-{name}` lookup still resolves.
Net change for an existing consumer that had OnSubagentTrace set: nothing (mapper
runs in both 0.3.0 and 0.4.0 because OnSubagentTrace is non-null). Net change
for a consumer that did NOT set OnSubagentTrace but did AddSource: they now get
spans they always asked for.
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Squad.Agents.AI 0.5.0: auto-inject --agent squad (CLI parity by default) (#1275)
* Squad.Agents.AI 0.5.0: auto-inject --agent squad (CLI parity by default)
The whole point of SquadAgent is to wrap a Squad coordinator team — but the
0.4.x SDK launched the underlying copilot.exe with the CLI's built-in generic
agent. The coordinator therefore had no instructions to eager-execute, fan
out, or dispatch via the task tool, so it role-played responses inline.
Concretely: this SDK call
builder.Services.AddSquadAgent(o => o.SquadFolderPath = teamRoot);
did NOT behave the same as running
copilot --agent squad
interactively against the same team root. Consumers had to remember to add
`opts.CliArgs.Add(""--agent""); opts.CliArgs.Add(""squad"");` themselves, which
is an SDK leak — the class is literally called SquadAgent.
0.5.0 makes --agent squad the SDK default:
* New `SquadAgentOptions.AgentFileName` (defaults to `""squad""`).
* On client construction, SquadAgent looks for
`{teamRoot}/.github/agents/{AgentFileName}.agent.md`. If it exists,
`--agent {AgentFileName}` is auto-prepended to the CLI args.
* If the file is missing (folder not Squad-initialized), the inject is
silently skipped and a Debug log line explains why. The CLI then starts
with its default agent, which is what 0.4.x did anyway.
* If the consumer already supplied `--agent X` in `CliArgs`, the explicit
value wins and we do NOT add a second one.
* Set `AgentFileName = null` (or whitespace) to opt out entirely.
Net effect: SquadAgent.RunAsync now matches `copilot --agent squad` for
any Squad-initialized team root, without the consumer doing anything.
## Tests
64 -> 71 tests, all passing on net8.0/9.0/10.0.
New `SquadAgentDefaultAgentFlagTests` (uses a per-test temp dir to scaffold
or omit the agent file deterministically):
* Default AgentFileName is ""squad""
* Auto-inject when squad.agent.md exists
* No inject when the file is missing (graceful degradation)
* Explicit --agent in CliArgs wins (no second --agent added)
* Custom AgentFileName=""data"" injects --agent data when data.agent.md exists
* AgentFileName=null opts out entirely
* AgentFileName=whitespace opts out entirely
Backward compatibility: existing routing tests use a non-existent
`C:\squad-team-root` path, so the file-existence check silently skips the
inject — those tests continue to pass with no changes.
## Files
* `src/Squad.Agents.AI/SquadAgentOptions.cs` — new `AgentFileName`
property with XML doc covering the default, the opt-out, and the
not-yet-initialized fallback.
* `src/Squad.Agents.AI/SquadAgent.cs` — auto-inject logic in
`CreateCopilotClient` (after the `--allow-all` block, before
`options.CliArgs` are appended) with file-existence + already-supplied
guards and a Debug log when the file is missing.
* `src/Squad.Agents.AI/Squad.Agents.AI.csproj` — bump 0.4.0 -> 0.5.0.
* `src/Squad.Agents.AI/README.md` — new ""Coordinator agent selection""
section with the precedence table; `AgentFileName` row added to Key
Options table.
* `+test/Squad.Agents.AI.Tests/SquadAgentDefaultAgentFlagTests.cs`
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* amend: use SessionConfig.Agent instead of --agent CLI args
GitHub.Copilot SDK's SessionConfigBase exposes an Agent (string) property
that is the first-class equivalent of the Copilot CLI's --agent flag. It
discovers and loads .github/agents/{name}.agent.md exactly the same way
the CLI does, but without us having to munge CliArgs.
Switch the 0.5.0 default-coordinator-agent implementation:
- SquadAgent now sets sessionConfig.Agent = options.AgentFileName (default
""squad"") right after constructing the SessionConfig, before
ConfigureSession runs.
- Drop the --agent CliArgs hack (we no longer need to detect ""did the
consumer already pass --agent?"" because ConfigureSession naturally wins
over our default).
- Tests now assert against sessionConfig.Agent via reflection over the
inner DelegatingAIAgent — exactly what consumers using ConfigureSession
would see.
- README ""Coordinator agent selection"" section reworded to say
""sets SessionConfig.Agent"" instead of ""auto-adds --agent"".
71/71 tests still pass on net8.0/9.0/10.0. The fifth new test
(ConfigureSession_CanOverrideAutoSetAgent) explicitly proves the
ConfigureSession callback can replace the auto-set value, which is the
clean override path now that --agent CliArgs is gone.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Squad.Agents.AI 0.5.1: fix 0.5.0 regression — use --agent CLI flag (not SessionConfig.Agent) (#1277)
0.5.0 (#1275) replaced the previous --agent CliArgs approach with
sessionConfig.Agent = options.AgentFileName, on the theory that the SDK
property was the first-class equivalent of the CLI's --agent flag.
It is not. SessionConfig.Agent looks up the name in the SDK's CustomAgents
registry (programmatic agent definitions, never populated by SquadAgent),
NOT in .github/agents/*.agent.md files on disk. The result was a runtime
error on every RunAsync call against a Squad-initialised team:
Communication error with Copilot CLI: Request session.create failed with
message: Custom agent 'squad' not found
Verified at GitHub.Copilot.SDK 1.0.0:
* SessionConfigBase.Agent (string) — selects from CustomAgents
* SessionConfigBase.CustomAgents (IList<CustomAgentConfig>) —
programmatically defined inline agents (Name, Prompt, Tools, Skills,
Model, etc.). Empty by default.
* The CLI's --agent flag is currently the only path that reads
.github/agents/{name}.agent.md on disk.
0.5.1 reverts to the original CliArgs implementation:
* SquadAgent now auto-prepends '--agent {AgentFileName}' to combinedCliArgs
(back to what 0.5.0 originally proposed before the SessionConfig.Agent
detour).
* The file-existence check at {teamRoot}/.github/agents/{name}.agent.md
still gates the inject so non-Squad-initialized folders degrade
gracefully (no --agent passed -> CLI uses default agent).
* The 'consumer already supplied --agent in CliArgs' guard is back so the
SDK does not add a duplicate.
Tests:
* New SquadAgentDefaultAgentFlagTests covers all seven cases via reflection
over Connection.Args (the CLI-args path the SDK actually uses):
default 'squad' value, auto-inject when file exists, no inject when
missing, explicit --agent wins, custom AgentFileName works,
AgentFileName=null/whitespace opts out.
* The older SquadAgentDefaultAgentTests (which targeted SessionConfig.Agent)
is removed since that property does NOT do what we wanted.
71/71 tests passing on net8.0/9.0/10.0.
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add squad registry add/list/remove for discovery-only peer squads (#1291)
Closes #1290.
Adds CLI surface for managing .squad/squad-registry.json, symmetric to
squad upstream. Registry entries are discovery-only (visible to
squad discover and squad delegate) but do NOT trigger inheritance of
the peer squad's skills/decisions/wisdom/routing.
Previously users had to hand-edit .squad/squad-registry.json — even the
squad discover empty-state hint told them to "create a squad-registry.json"
manually. This adds proper commands:
squad registry add <name> <path> # validates manifest, refuses duplicate
squad registry list # show all registered peers
squad registry remove <name> # remove by name
Also fixes a subtle path-semantics confusion: readManifest() now accepts
BOTH the repo root AND a path with a trailing .squad segment. The docs
and SKILL.md showed the .squad-suffixed form but the code previously
joined .squad/manifest.json onto whatever you gave it, so the suffixed
form silently failed empirical reproduction (discover returned nothing).
Test coverage: 18 new tests in cross-squad-registry.test.ts covering
the dual-path readManifest fix, registry round-trip, add/list/remove
behavior including duplicate-name and invalid-manifest rejection, and
end-to-end integration with discoverSquads.
Also updates:
- cross-squad SKILL.md (canonical + 2 template mirrors) to document the
registry vs upstream distinction explicitly
- squad discover empty-state hint to mention squad registry add
- squad help text with the new commands
- SDK exports for the new registry helpers + RegistryEntry/
AddRegistryEntryResult types
End-to-end verified locally:
- squad registry add (both repo-root and .squad-suffixed paths)
- squad registry list (rich output)
- squad registry remove (success + missing-name warning)
- squad discover picks up registry entries with source=registry
- 50/50 tests pass (32 existing + 18 new)
- npm run build clean
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(cli): stop writing squad_state to ~/.copilot/mcp-config.json on every init/upgrade (#1296) (#1298)
* fix(cli): stop writing squad_state to ~/.copilot/mcp-config.json on every init/upgrade (#1296)
squad init (init.ts:408) and squad upgrade (upgrade.ts:738) unconditionally
called ensureSquadStateMcpInUserConfig, writing squad_state_<hash> to
~/.copilot/mcp-config.json keyed by a stable project-path hash. Each 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, which says iter-8 stops
writing to HOME and writes squad_state ONLY to repo-root .mcp.json.
The repo-root .mcp.json writes (init.ts:403 / upgrade.ts:728) already cover
all documented Copilot CLI launch modes - copilot and copilot -p both walk
up from cwd to find .mcp.json. Out-of-tree copilot -p invocations should
use --additional-mcp-config @.mcp.json (already documented at init.ts:494).
Changes:
* Removed the unconditional ensureSquadStateMcpInUserConfig call from
init.ts:408 and upgrade.ts:738. Replaced both with comments explaining
iter-8 + #1296.
* Removed the now-unused import from both files.
* Kept the function definition at mcp-root.ts:178-228 - a future
squad doctor --mcp-prune cleanup helper may want to inspect HOME.
Tests:
* New regression test in test/cli/init.test.ts: "should NOT write any
squad_state entries to ~/.copilot/mcp-config.json (#1296)". Isolates
the developer's real HOME by setting USERPROFILE/HOME to a temp dir
before init, asserts no squad_state* keys appear under temp HOME.
* All 40 existing init tests still pass. npm run lint clean.
Closes #1296
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: comments reference actual Copilot CLI version (≥1.0.59), drop hardcoded test line numbers
Reviewer follow-ups on #1298 (closes #1296):
1. The comments in init.ts/upgrade.ts/mcp-root.ts referenced
'Copilot CLI 5.3+' as the version that auto-loads .mcp.json. The
real shipping CLI is at 1.0.62 (5.3 was a typo'd projection from
review). Updated all 5 occurrences to '≥1.0.59' — the lowest
version where the .mcp.json walk-up behavior is documented.
2. The init.test.ts regression comment hard-coded line numbers
(init.ts:408, upgrade.ts:738) that will go stale on any unrelated
edit to those files. Rewrote the comment to identify the call by
function name (ensureSquadStateMcpInUserConfig) instead — durable
against re-orderings.
Verified: regression: #1296 test still passes (1/16 in init.test).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(init): post-init package.json script tip includes --agent squad
The post-init tip showing how to add a non-interactive `squad:copilot`
script to package.json was:
"squad:copilot": "copilot --additional-mcp-config @.mcp.json"
This omits `--agent squad`, so users who copy/paste it get a generic
Copilot CLI session that doesn't load the Squad coordinator, team.md,
casting, or MCP-wired memory/state tools — only the additional MCP
config gets loaded. Same underlying issue surfaced in the cross-squad-
communication SKILL.md sweep (squad/wire-cross-squad-skill commit
6b0eac21): anywhere we spawn `copilot` into a Squad-initialised repo,
we must pass `--agent squad`.
Single-line fix:
"squad:copilot": "copilot --agent squad --additional-mcp-config @.mcp.json"
Verified: a fresh `squad init` smoke test now prints the corrected
tip line verbatim.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
* fix(sdk): wire team.md/routing.md/casting state on \squad preset apply\ (#1288) (#1293)
* fix(sdk): wire team.md/routing.md/casting state on `squad preset apply` (#1288)
`squad preset apply <name>` only copied agent charters into .squad/agents/.
It left .squad/team.md `## Members` empty, .squad/routing.md missing
`## Work Type -> Agent` rows, and never created .squad/casting/registry.json,
history.json, or policy.json. Net result: the coordinator's mode-switch check
saw an empty Members table and treated every session as Init Mode, proposing
to re-scaffold the team the user already applied.
This change adds a merge-friendly scaffold module
(packages/squad-sdk/src/presets/scaffold.ts) that runs after charters are
copied and:
* writes/updates team.md `## Members` (creates from scratch if missing;
appends new rows to an existing table while preserving the surrounding
Coordinator / Project Context sections; idempotent on repeat apply)
* writes/updates routing.md `## Work Type -> Agent` (creates or appends)
* writes/merges casting/registry.json (universe = `preset:<name>`)
* appends a snapshot to casting/history.json + a universe_usage_history entry
* creates casting/policy.json with defaults only if missing (never clobbers)
Agents with `status: 'error'` are excluded from wiring; agents with
`status: 'skipped'` (already exist in target) ARE wired so the team
reflects user intent. Scaffolder failure is reported as a synthetic error
result without masking the per-agent install results.
Verified:
* npm run lint passes
* test/presets.test.ts: 28/28 pass including 4 new regression tests
- wires preset agents into team.md ## Members (#1288)
- merges preset agents into an existing team.md without duplicating rows
- writes casting registry.json, history.json, and policy.json (#1288)
- appends routing rows for preset agents to routing.md (#1288)
Out of scope (tracked separately): deduplicating these writers with the
equivalent fresh-write versions in packages/squad-cli/src/cli/core/cast.ts.
Closes #1288
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(presets): role-aware Status cell + non-colliding sentinel for synthetic scaffold error
Two reviewer follow-ups on #1293 (closes #1288):
1. Members-table Status was hardcoded to '✅ Active' for every preset
agent. Presets that ship one of the always-on built-ins (Scribe,
Ralph, Rai, Fact Checker) would render with the wrong status label
compared to a fresh cast: '✅ Active' instead of '📋 Silent' /
'🔄 Monitor' / '🛡️ RAI' / '🔍 Verifier'.
Added a small statusForRole() helper that mirrors the role→status
mapping in cast.ts:652-655 (case-insensitive role matching to
tolerate preset authors who lowercase the role string). Built-in
role names get their canonical labels; everything else falls back
to '✅ Active'. Added a regression test asserting the labels for a
preset that ships scribe/ralph/rai/fact-checker + one regular agent.
2. Synthetic scaffold-failure result row used 'agent: presetName'
for its 'agent' field. If the preset itself happens to include an
agent literally named after the preset ('squad preset apply geektime'
on a preset whose roster has a 'geektime' agent), the consumer of
PresetApplyResult[] could not distinguish the synthetic scaffold-
level error from a real per-agent install error.
Replaced with the angle-bracketed sentinel '<scaffold>' (which
validateName() rejects, so it can never collide with a real agent
name) and moved the preset name into the human-readable reason
string so consumers don't lose that context.
Verified: 29/29 preset tests pass (28 existing + 1 new role-status test).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
* fix(docs): tell coordinator to roster Fact Checker on first-time cast (#1299) (#1300)
* fix(docs): tell coordinator to roster Fact Checker on first-time cast (#1299)
squad init correctly creates .squad/agents/fact-checker/ on disk (per
merged PR #1223). But when the user opens copilot --agent squad and the
coordinator runs first-time casting, it OMITS Fact Checker from the
team.md ## Members table while including Scribe, Ralph, and Rai.
Root cause: .squad-templates/squad.agent.md had two gaps:
1. Line 56 said "team size (typically 4-5 + Scribe)" — naming only Scribe
2. Rai had a dedicated ## Rai section with explicit "Rai always appears
in team.md" instruction — Fact Checker had no equivalent section
So the model added Rai (because instructed to) but had no instruction to
add Fact Checker, even though the agent dir was scaffolded on disk.
Fix:
* Update team-size line to name all 4 always-on built-ins: Scribe + Ralph
+ Rai + Fact Checker
* Add full ## Fact Checker — Verification & Devil's Advocate section
mirroring the Rai pattern: roster-entry instruction, dual operating
mode (per #789 + #1254), trigger phrase table, confidence ratings, DA
brief structure, boundaries, state location
Sync via sync-templates.mjs --sync propagates squad.agent.md changes to
all 4 mirror targets: .squad-templates/, templates/, packages/squad-cli/
templates/, packages/squad-sdk/templates/, .github/agents/.
Tests: new test/squad-agent-roster.test.ts runs against all 4 template
targets and asserts:
* The "Determine team size" line names all 4 built-ins
* A ## Fact Checker section exists with "always appears in team.md"
* The section declares dual operating mode (anchors #789 + #1254 design
so a future PR can't accidentally split Fact Checker and Devil's
Advocate again — cf. closed PR #1294)
* Existing Ralph + Rai sections still present
16/16 pass.
Closes #1299
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* doc(squad.agent.md): clarify Fact Checker is exempt from casting + correct on-demand reference path
Reviewer follow-ups on #1300:
1. Team-size phrasing — the line read 'typically 4-5 + Scribe + Ralph +
Rai + Fact Checker' which a model could parse as arithmetic
(4-5 + 4 = 8-9, but it could also collapse). Rewrote it to make the
composition explicit: '4-5 cast (user-domain) agents + 4 always-on
built-ins = 8-9 total roster entries'.
2. Cast-exemption parity — Scribe, Ralph, and Rai each have an
explicit 'exempt from casting' bullet but Fact Checker did not.
Added the matching bullet right after Rai's.
3. Bad on-demand reference path — the FC section pointed at
'.squad/templates/fact-checker-charter.md'. That file IS shipped
(TEMPLATE_MANIFEST destination 'templates/fact-checker-charter.md')
but only AFTER 'squad init' or 'squad upgrade' has populated
.squad/templates/. A reader of squad.agent.md on an
un-initialized repo (or in .github/agents/ on the cloud agent
surface) would follow a dead link. Repointed to the
'.squad/agents/fact-checker/charter.md' instance that
ensureBuiltinAgents creates as part of the same init/upgrade
path — that's where the rich charter actually lives at runtime
per #1299 + #1301.
All 4 mirrored copies re-synced via scripts/sync-templates.mjs.
fact-checker-role.test.ts: 8/8 pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
* fix(sdk): plumb Fact Checker like Rai — rich charter at init + .squad/fact-checker/ state dir (#1299 deep) (#1301)
* fix(sdk): plumb Fact Checker like Rai — rich charter at init + .squad/fact-checker/ state dir (#1299 deep)
PR #1300 fixed the documentation gap so the coordinator knows to roster
Fact Checker. This PR fixes the structural gap behind it. Per user
testing 2026-06-13: even after #1300 the actual agent on disk was still
"a name on disk with a 21-line placeholder".
Three structural problems:
1. squad init never used the rich {role}-charter.md templates. Both Rai
and fact-checker got 478-byte generic stubs from generateCharter().
Rich templates only ran via squad upgrade's ensureBuiltinAgents path.
2. fact-checker had no state dir. Rai gets .squad/rai/{policy.md,
audit-trail.md} via init.ts lines 879-941. fact-checker had nothing
equivalent.
3. fact-checker-charter.md was only in packages/squad-cli/templates/ —
missing from .squad-templates/ (canonical source) AND packages/
squad-sdk/templates/. SDK init's getSDKTemplatesDir() resolves to the
SDK templates dir, so even if init tried to read the rich charter,
the file wasn't there.
Fix (4 parts):
Part 1 - Rich charter at init (benefits BOTH Rai and fact-checker):
* SDK 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.
* Result: fresh squad init produces .squad/agents/Rai/charter.md at
4525 bytes (full Rai charter) and fact-checker/charter.md at 3024
bytes (full FC charter). Previously both were 478-byte stubs.
Part 2 - .squad/fact-checker/ state dir mirroring .squad/rai/:
* New block in init.ts (right after the Rai seeding) creates
.squad/fact-checker/policy.md (from templates/fact-checker-policy.md
or inline fallback) and audit-trail.md.
* New .squad-templates/fact-checker-policy.md (~6KB) is the canonical
authority for dual-mode operating rules per #789 + #1254:
- Mode 1 Verification: ✅/⚠️/❌/🔍 confidence rating taxonomy
- Mode 2 Devil's Advocate: required brief structure
- Hard anti-fabrication rules
- Advisory by default with narrow blocking exceptions
- Audit trail rules (succinct, never raw source)
Part 3 - Fix .squad-templates/ distribution gap:
* Copied fact-checker-charter.md into .squad-templates/ so
sync-templates.mjs propagates it to all 4 mirror targets including
packages/squad-sdk/templates/. This unblocks Part 1.
Part 4 - Plumbing:
* .gitattributes: .squad/fact-checker/audit-trail.md merge=union
* TEMPLATE_MANIFEST: fact-checker-policy.md
* squad.agent.md Files Catalog: 2 new rows for FC state files
Tests: 3 new regression tests in test/init.test.ts (28/28 pass total).
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 PRs modify
squad.agent.md in disjoint regions and merge in either order. Full
plumbing requires BOTH to land.
Closes #1299 (deep fix; #1300 was the surface fix)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(sdk): lowercase fallback for rich-charter template lookup + sync .github/agents
Two reviewer follow-ups on #1301 (#1299 deep):
1. Case-sensitive FS bug in rich-charter lookup
The lookup tried '\-charter.md' and '\-charter.md'
only. For Rai (role='Rai', name='Rai') this becomes 'Rai-charter.md', but
the actual file shipped lowercase ('rai-charter.md'). On Windows the lookup
succeeded because the filesystem is case-insensitive; on Linux CI it silently
missed and fell back to the 478-byte generic stub — exactly the regression
#1299 was trying to fix. Reproduced by 'should use the rich Rai-charter.md
template at init' failing with 'expected 476 to be greater than 1000' on
GitHub Actions.
Add toLowerCase() candidates after the exact-case ones. De-dupe via a Set
so we don't double-stat when role and name are already lowercase
(fact-checker case). Guard each candidate against blank keys.
2. Template-sync parity
The canonical .squad-templates/squad.agent.md gained two Fact Checker rows
in the Files Catalog but the mirrored .github/agents/squad.agent.md copy
was never re-synced, so the template-sync.test.ts byte-for-byte parity
check would have fired. Run 'node scripts/sync-templates.mjs --sync' to
regenerate.
Verified: vitest 'rich Rai-charter' passes locally after the fix
(previously failing on Linux CI run 27464079078).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
* fix(skills): rename squad disambiguation skill to squad-help (supersedes #1297) (#1302)
* fix(skills): rename disambiguation skill 'squad' -> 'squad-help' (supersedes #1297)
PR #1297 added a disambiguation skill named 'squad' so models calling
skill(Squad) would get a redirect. After local end-to-end testing on
2026-06-13: 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 app.js):
1. Copilot CLI's skill schema is {name, description, source, baseDir,
allowedTools, pluginName, pluginVersion} (line 989). Frontmatter fields
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.
Fix:
* Rename 'squad' -> 'squad-help' (avoids the agent-name collision; still
descriptive enough for natural-language match when user says 'how do
I use squad' or 'squad help')
* SKILL.md content: name: 'squad-help', removed unused triggers:/domain:/
confidence:/source:/license: fields, added allowedTools: [], rewrote
description: to be self-explanatory, added explicit note that /squad
slash command does NOT exist (slash commands are CLI built-ins, not
auto-mapped from skills)
* MANIFEST_SKILL_NAMES in sdk-init.ts: 'squad' -> 'squad-help'
* New TEMPLATE_MANIFEST entry in templates.ts for squad-help (so
squad upgrade also propagates the skill - that code path uses
TEMPLATE_MANIFEST instead of MANIFEST_SKILL_NAMES)
Tests: new test asserts .copilot/skills/squad-help/SKILL.md exists with
right frontmatter; explicit regression guard against re-introducing
name: 'squad'. 26/26 init tests pass. npm run lint clean.
Supersedes #1297.
Out of scope (separate issue worth filing): squad upgrade synced only
10 of 16 installed skills - TEMPLATE_MANIFEST (used by upgrade) is out
of sync with MANIFEST_SKILL_NAMES (used by init). Skills from PRs #1292
+ #1295 (tiered-memory, iterative-retrieval, reflect, cross-squad,
cross-squad-communication) have entries in MANIFEST_SKILL_NAMES but
not TEMPLATE_MANIFEST. Follow-up will fix.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(skill): add confidence + domain frontmatter to squad-help
Reviewer follow-up on #1302: the isSkillContent() classifier in
sharing/consult.ts:990 requires BOTH name: AND confidence: in the
frontmatter to recognize a file as a skill. Without confidence:,
squad-help would not be detected as a skill in cross-squad merge /
share / promote flows — it would be misclassified as a generic
markdown decision.
The Copilot CLI itself silently ignores custom frontmatter fields
(per sdk/index.js decompile — only name/description/allowedTools/
user-invocable are read), so adding confidence: high and domain:
squad-onboarding is safe at the CLI surface and necessary at the
SDK surface.
Applied identically to all 3 mirrored copies of squad-help/SKILL.md.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
* fix(prompt): co…
* fix(sdk): export gitignore-state helpers; bump Squad.Agents.AI to 0.5.5 (#1387)
migrate-backend.ts imports addSquadStateGitignoreBlock/removeSquadStateGitignoreBlock
from @bradygaster/squad-sdk, but src/index.ts never re-exported them, breaking the CLI
TypeScript build (TS2305). Re-export both helpers (and their marker constants) so the CLI
compiles. Also bump the stale Squad.Agents.AI NuGet version 0.5.1 -> 0.5.5 so a republish
pins to the fixed CLI.
Unblocks a stable release carrying the #1378 inline-dispatch-gate fix.
Refs #1386
Co-authored-by: brady gaster <bradygaster@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(tracing): capture task-tool dispatch + tool requests for subagent OTel (#1384)
Adds a "subagent dispatched" envelope to the SquadSubagentTraceMapper so
consumers and OTel backends see the LLM-supplied persona identity from the
moment the coordinator invokes the `task` tool — instead of waiting for the
later SubagentStartedEvent (which only carries the catalog `agent_type`,
e.g. always "general-purpose").
Mapper / public surface:
- Add `SubagentDispatched` to `SquadAgentTraceEventKind` and four persona
properties on `SquadAgentTraceEvent`
(`DispatchedPersonaName/Description/AgentType/Prompt`).
- Rewrite mapper to key live activities by `ToolCallId` (primary) and
maintain a `SdkAgentId → ToolCallId` lookup so `AssistantMessageEvent`s
(which only carry `AgentId`) can find the right span. Activities are
opened on the task-dispatch event and labelled with the persona name from
the start, then augmented on `SubagentStartedEvent`.
- Surface `AssistantMessageData.ToolRequests[].Name` on the typed envelope
as `RequestedToolNames`, and add a `squad.subagent.tool_requests`
ActivityEvent so tool-only assistant turns (empty Content) are visible
on the OTel span as "called gh, view, grep" instead of a blank marker.
Sample:
- Add Flow 5 demonstrating both the typed `OnSubagentTrace` callback and
an `ActivityListener` for OTel.
- Update Flow 1 to use the same handler with the new tool-name surfacing
and a short `ShortId` formatter so parallel subagents are
visually distinct.
- Fix Flow 3 (BYOK): merge the parent process env with custom vars to
avoid the `Assertion failed: ncrypto::CSPRNG(nullptr, 0)` Node crash on
Windows.
SDK:
- When forwarding `options.Environment` to the Copilot client, merge with
the parent process env (instead of replacing it) so the native CLI
inherits SYSTEMROOT/PATH/TEMP and doesn't crash on crypto init.
Tests (82 total, all pass on net8.0/net9.0/net10.0):
- 11 new tests covering task-dispatch parsing, `subagent_type` alias,
bare-arguments fallback, `ToolRequests` extraction, the
`squad.subagent.tool_requests` ActivityEvent, ToolCallId-keyed activity
lifecycle, parallel dispatches, missing-arguments path, and the
`sessionConfig.Agent = "Squad"` routing assertion update.
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: escape args for cmd.exe shell on Windows (DEP0190) (#1388)
* fix: escape args for cmd.exe shell on Windows (DEP0190)
When execFile is called with shell: true on Windows, Node concatenates
args with spaces but does NOT quote them. This causes multi-word prompts
(e.g. the -p/--message arg) to be split by cmd.exe, resulting in
'The system cannot find the file specified' errors.
Changes:
- Add escapeForCmd() and escapeArgs() to agent-spawn.ts that properly
wrap args containing spaces/metacharacters in double quotes
- Apply escaping in spawnWithTimeout() and spawnAgent() before passing
to execFile
- Migrate monitor-email, monitor-teams, retro, and decision-hygiene
capabilities to use the shared agent-spawn module instead of
duplicated inline buildAgentCommand/spawnWithTimeout functions
- Fix preflight checks to use IS_WINDOWS instead of hardcoded shell:true
Also resolves the Node DEP0190 deprecation warning about passing args
to a child process with shell option true being a security risk, since
args are now properly escaped before concatenation.
Fixes bradygaster/squad#TBD
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: use gh auth token instead of gh auth status for auth checks
gh auth status returns a non-zero exit code when ANY account in the
keyring has an invalid/stale token, even if the active account (e.g.
via GH_TOKEN env var) is perfectly fine. This causes squad watch and
other commands to incorrectly report 'gh CLI not authenticated'.
Switch to gh auth token which only checks the active account and
returns the token on success.
Fixes the false-negative auth check when users have multiple gh
accounts with a stale keyring entry.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: use -p flag instead of --message for copilot CLI
The copilot CLI accepts -p/--prompt for non-interactive mode, not
--message. The --message flag doesn't exist, causing 'unknown option'
errors when capabilities try to invoke copilot.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: default to --yolo when --execute is active
Copilot CLI hangs in non-interactive (-p) mode without permission
flags because it prompts for tool/path/url approval. Since squad watch
spawns copilot headlessly, default to --yolo (equivalent to
--allow-all) when execute mode is active and no explicit copilotFlags
or agentCmd are set.
Users can still override with --copilot-flags to use a more
restrictive set of permissions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: add changeset for shell spawn fixes
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(coordinator): spawn cast members as sub-sessions in Copilot App (#1385)
* feat(coordinator): spawn cast members as sub-sessions in Copilot App
Add SpawnBackend abstraction with TaskSpawnBackend (CLI) and
SessionSpawnBackend (App) implementations. When create_session tool
is available, agents spawn as sub-sessions with real-time visibility
in the left nav. Zero CLI impact — behavior unchanged without the tool.
Key design:
- Platform detection via tool availability probe at session start
- Naming: '{Name} {verb}ing {noun}' (40-char max, sentence case)
- Concurrency cap: 4-5 simultaneous sub-sessions
- Depth limit: max 1 (no sub-sub-sessions)
- Graceful fallback: App backend fails → degrade to task tool
Closes #1377
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(coordinator): address PR review - wire spawnBackend, fix detection order, add release()
- Reorder platform detection: create_session > runSubagent > task > inline
- Wire spawnBackend.spawn() into spawnSingle() with fallback to createSession
- Both backends now require injected createSession callback (real session creation)
- Add release(handle) to SpawnBackend interface for concurrency tracking
- SessionSpawnBackend: proper pending/active tracking, reject (not queue) at cap
- Remove unused SpawnRequest import (now used in fan-out wiring)
- Add tests for spawn-backend and fan-out integration
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: brady gaster <bradygaster@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(coordinator): address #1385 review follow-ups (#1390)
Hardening fixes for the sub-session spawn backend (#1377):
- App->task fallback: spawnSingle() falls back to createSession when the
platform backend fails instead of failing the agent (emits
session.spawn_fallback)
- Slot-leak guards: registerSpawnRelease() handles 'completed' status and
adds an unref'd max-lifetime safety timer
- createSession timeout in both backends (createSessionTimeoutMs, default 60s)
- Honest isAvailable() with injectable availabilityCheck predicate
- Prompt sanitization for caller task/context (sanitizePromptValue)
- Re-synced template platform-detection probe order to mirrors
Adds vitest coverage for all six items.
Closes #1377
Co-authored-by: brady gaster <bradygaster@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Rename .NET Aspire references to Aspire (#1239)
* docs: rename .NET Aspire references
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Apply suggestions from code review
Co-authored-by: Meir Blachman <meirblachman@gmail.com>
---------
Co-authored-by: Meir Blachman <meblachm@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: simplify workflow files by removing .ai-team fallback logic (#1263)
Remove dead .ai-team/ fallback code from workflow templates. The .squad/
directory is the canonical location since the rename — the fallback paths
were never triggered and added unnecessary complexity.
Changes:
- Remove .ai-team/ fallback branches from triage, issue-assign, heartbeat,
and sync-squad-labels workflows
- Clean up empty if-blocks left by fallback removal
- Simplify warning messages to reference only .squad/team.md
- Change let → const for team/routing file paths (no longer reassigned)
- Sync all template copies (.squad-templates/, packages/)
Guard rail checks in squad-preview.yml and squad-promote.yml are preserved
since they legitimately prevent .ai-team/ files from shipping.
Closes #1167
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(routing): strip surrounding quotes from routing.md examples (#1357)
parseRoutingMarkdown kept surrounding quotes on Examples cells, so a quoted example tokenized with the quote glued on and compiled to patterns that never matched, silently routing everything to fallback. Strip leading/trailing quotes so quoted and unquoted examples behave identically. Adds parse and matchRoute regression tests.
Co-authored-by: duau_microsoft <107149404+duau_microsoft@users.noreply.github.com>
* fix(cli): add externalize/internalize to top-level squad --help (#1232)
The top-level `squad --help` command list omitted the externalize and
internalize commands, leaving them undiscoverable. Add both entries
(descriptions sourced verbatim from command-help.ts) plus a regression
test guarding the top-level command list.
Closes #1050
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* deps: bump @types/node from 25.9.4 to 26.0.0 in /packages/squad-cli (#1365)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 25.9.4 to 26.0.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
---
updated-dependencies:
- dependency-name: "@types/node"
dependency-version: 26.0.0
dependency-type: direct:development
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* deps: bump @types/node from 25.9.4 to 26.0.0 in /packages/squad-sdk (#1366)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 25.9.4 to 26.0.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
---
updated-dependencies:
- dependency-name: "@types/node"
dependency-version: 26.0.0
dependency-type: direct:development
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* ci: bump esbuild and tsx in /samples/storage-provider-sqlite (#1380)
Bumps [esbuild](https://github.com/evanw/esbuild) to 0.28.1 and updates ancestor dependency [tsx](https://github.com/privatenumber/tsx). These dependencies need to be updated together.
Updates `esbuild` from 0.27.4 to 0.28.1
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.27.4...v0.28.1)
Updates `tsx` from 4.21.0 to 4.22.4
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.21.0...v4.22.4)
---
updated-dependencies:
- dependency-name: esbuild
dependency-version: 0.28.1
dependency-type: indirect
- dependency-name: tsx
dependency-version: 4.22.4
dependency-type: direct:development
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* deps: bump @opentelemetry/sdk-trace-base from 1.30.1 to 2.8.0 in /packages/squad-sdk (#1368)
Bumps [@opentelemetry/sdk-trace-base](https://github.com/open-telemetry/opentelemetry-js) from 1.30.1 to 2.8.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-js/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-js/compare/v1.30.1...v2.8.0)
---
updated-dependencies:
- dependency-name: "@opentelemetry/sdk-trace-base"
dependency-version: 2.8.0
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* deps: bump @opentelemetry/resources from 1.30.1 to 2.8.0 in /packages/squad-sdk (#1369)
Bumps [@opentelemetry/resources](https://github.com/open-telemetry/opentelemetry-js) from 1.30.1 to 2.8.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-js/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-js/compare/v1.30.1...v2.8.0)
---
updated-dependencies:
- dependency-name: "@opentelemetry/resources"
dependency-version: 2.8.0
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* deps: bump @github/copilot-sdk from 0.3.0 to 1.0.4 (#1361)
Bumps [@github/copilot-sdk](https://github.com/github/copilot-sdk) from 0.3.0 to 1.0.4.
- [Release notes](https://github.com/github/copilot-sdk/releases)
- [Changelog](https://github.com/github/copilot-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/copilot-sdk/compare/v0.3.0...v1.0.4)
---
updated-dependencies:
- dependency-name: "@github/copilot-sdk"
dependency-version: 1.0.3
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* deps: bump @github/copilot-sdk from 0.3.0 to 1.0.4 in /packages/squad-sdk (#1371)
Bumps [@github/copilot-sdk](https://github.com/github/copilot-sdk) from 0.3.0 to 1.0.4.
- [Release notes](https://github.com/github/copilot-sdk/releases)
- [Changelog](https://github.com/github/copilot-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/copilot-sdk/compare/v0.3.0...v1.0.4)
---
updated-dependencies:
- dependency-name: "@github/copilot-sdk"
dependency-version: 1.0.3
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* deps: bump cspell from 9.7.0 to 10.0.1 (#1362)
Bumps [cspell](https://github.com/streetsidesoftware/cspell/tree/HEAD/packages/cspell) from 9.7.0 to 10.0.1.
- [Release notes](https://github.com/streetsidesoftware/cspell/releases)
- [Changelog](https://github.com/streetsidesoftware/cspell/blob/main/packages/cspell/CHANGELOG.md)
- [Commits](https://github.com/streetsidesoftware/cspell/commits/v10.0.1/packages/cspell)
---
updated-dependencies:
- dependency-name: cspell
dependency-version: 10.0.1
dependency-type: direct:development
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* docs(casting): add spoiler-awareness to casting/naming rules (#1196)
* Add spoiler-awareness guideline to casting/naming rules
Squad's casting system allocated character names from fictional universes
but never screened them for plot spoilers. The existing easter-egg rule
only hides the casting *rationale*, not spoiler-bearing names. A name that
encodes a character's later title, role, transformation, or fate can spoil
a user who is mid-way through the source material, since names appear in
plain text across team.md, prompts, and logs.
Adds an always-loaded Name Allocation rule in squad.agent.md and a new
"Spoiler Awareness" section in casting-reference.md (with a scrubbed
motivating example), propagated to all mirrors via sync-templates.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(casting): restore CRLF endings on casting-reference.md to remove false diff
The Spoiler Awareness edit was made on files whose committed blobs use CRLF, but local normalization rewrote them to LF. That made all 104 existing lines appear changed (122 ins / 104 del) and hid the real 18-line addition. Restoring CRLF collapses the diff to the genuine change only (18 insertions, 0 deletions).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs(casting): clarify spoiler guidance wording
Address review feedback on the Spoiler Awareness section:
- Use standard spelling 'midway' instead of 'mid-way'.
- Replace the ambiguous 'Never reorganize the casting around the spoiler'
with explicit guidance: keep existing name mappings stable and only
let the next/new allocation pick a different spoiler-safe character.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: add changeset for spoiler-aware casting
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(prompt): slim squad.agent.md by extracting 3 sections to satellite skills (#1311)
* feat(prompt): slim squad.agent.md by extracting 3 sections to satellite skills (#1308 phase 1)
squad.agent.md is loaded as the agent prompt at every Copilot session
start. v0.10.0-insider.1 ships it at 81 KB / 1137 lines and the v0.10
stabilisation pass alone added +10.6 KB / +114 lines. Every byte is
paid at every session.
Phase 1 fix: extract three low-cross-reference, high-byte sections to
satellite skills the coordinator loads on demand via the skill tool —
same pattern that worked for cross-squad-communication (#1295).
- coordinator-init-mode — Init Mode Phase 1 + Phase 2 (5.4 KB)
- coordinator-source-of-truth — Source of Truth Hierarchy (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). 19 skills
installed at .github/skills/ (was 16). Behaviour unchanged — each
removed section is replaced with a stub naming the trigger condition
and instructing the coordinator to skill(coordinator-X) before acting.
Sections that stay in squad.agent.md (intentional):
- Team Mode + state-backend handshake + HARD RULE — handshake must
fire before any state write
- Routing table — hit on every user prompt
- Hard trigger keyword-to-skill match paragraph (#1307) — load-bearing
- How to Spawn an Agent — referenced from every routing action
- Coordinator Identity / Personal Squad / Memory Governance Tools —
frequently re-read inline
Wired changes:
- New canonical sources at .squad/skills/coordinator-{x}/SKILL.md
plus 2 template-dir mirrors
- MANIFEST_SKILL_NAMES grows by 3 entries (16 → 19)
- TEMPLATE_MANIFEST grows by 3 entries with ../.github/skills/
destinations (post-#1304 install location)
- .squad-templates/squad.agent.md replaces each section with a stub
- 4 mirrored squad.agent.md copies re-synced via
scripts/sync-templates.mjs --sync
Tests: 287/287 pass. The existing 'should install every
manifest-curated skill (regression: bradygaster/squad#1289, #1264)'
already iterates MANIFEST_SKILL_NAMES, so it automatically asserts the
3 new skills install.
Smoke test: fresh squad init produces 19 skills at .github/skills/
and squad.agent.md is 70 KB.
Follow-ups (separate PRs) for the still-large sections:
- Routing (9.2 KB) — extract action-cell verbiage, keep trigger table
- Team Mode (5.5 KB) — extract worktree-awareness sub-sections
- How to Spawn (3.2 KB) — extract role-emoji catalog
Target after 2-3 follow-ups: ~45 KB coordinator file.
Closes #1308 (phase 1).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test+changeset: follow 'Determine team size' assertion to coordinator-init-mode skill
CI failure on #1311: test/squad-agent-roster.test.ts asserted the
'Determine team size' line is in squad.agent.md.template, but after
#1308 phase 1 that line moved into the coordinator-init-mode skill.
Restructured the test into two describe blocks:
1. squad.agent.md.template — must still keep an Init Mode STUB that
names the coordinator-init-mode satellite skill AND preserves the
load-bearing eager-execution exception callout. This makes sure
future edits can't accidentally drop the satellite reference.
2. coordinator-init-mode/SKILL.md (3 mirrors) — must contain the
'Determine team size' line naming all four built-ins, AND must
mark each of Scribe/Ralph/Rai/Fact Checker as 'exempt from
casting'. The regression coverage from #1299 follows the content.
22/22 tests pass.
Also addressed the changeset review comment: clarified that
.squad/skills/coordinator-*/SKILL.md are the canonical source files
in the squad repo (where every other bundled skill source lives),
and they're copied to .github/skills/ on install/upgrade per #1304.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: git-add the canonical .squad/skills/coordinator-*/ source dirs (review on #1311)
Reviewer caught a real bug: the new coordinator-* skill source dirs
existed in my worktree but had never been `git add`-ed because
`.squad/` is gitignored on this repo (specific subpaths under it are
exception-tracked). The template mirrors at
packages/squad-{cli,sdk}/templates/skills/coordinator-*/ shipped fine,
but the canonical sources at .squad/skills/coordinator-*/SKILL.md
weren't in the tree — so:
- The changeset claim that .squad/skills/coordinator-*/ is the
canonical source was untrue on dev.
- scripts/sync-skill-templates.mjs would not see the new skills
when run from a fresh checkout, breaking the contributor workflow
(canonical → mirrors). Sync would silently drop the 3 new skills
on the next prebuild.
Force-added the 3 dirs (`git add -f` because of the .squad/ ignore
rule, same as every other tracked skill under .squad/skills/).
Verified: `node scripts/sync-skill-templates.mjs` now lists
coordinator-* among the 26 discovered skills and re-produces the
2 template mirrors byte-identical to the canonical sources.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test: extractInitMode follows satellite skill + version regex tolerates pre-release tail
Two narrow fixes uncovered while smoke-testing the slim squad.agent.md PR
(#1311) and the 0.10.0-insider.1 release pipeline:
1. test/init-flow.test.cjs — after the Init Mode prose moved from
squad.agent.md to the coordinator-init-mode satellite skill (#1308 /
PR #1311), the structural assertions in 'Init Mode prompt structure
(#66)' had nothing to read in the parent file. They now follow the
pointer via the new readSatelliteSkill() helper (which prefers the
installed copy at .github/skills/<name>/SKILL.md and falls back to
the source repo template at packages/squad-sdk/templates/skills/),
so the same gates (STOP/WAIT, 'Look right?', numbered confirm-before-
create flow, Phase 2 trigger) keep being enforced — just against the
prompt the coordinator actually loads at runtime.
2. test/version-stamping.test.cjs + index.cjs — the version regex
[0-9.]+(?:-[a-z]+)? truncated pre-release versions with a numeric
tail (e.g. 0.10.0-insider.1 → 0.10.0-insider, 0.10.0-build.3 →
0.10.0-build). That made the test 'upgrade detects same version'
fail locally on any contributor who built the package (pkg.version
gets stamped 0.10.0-build.N during build). More importantly it made
the legacy index.cjs upgrade re-run the full upgrade flow for npm-
installed insider users (who have 0.10.0-insider.1 on disk) instead
of printing 'Already up to date'. Widened to
[0-9.]+(?:-[a-z]+(?:\.[0-9]+)?)? — matches everything we already
accepted plus the .N tail used by npm pre-release dist-tags and the
build-time stamping script.
All 133 .cjs tests now pass (was 123 pass / 10 fail before).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(docs): rephrase 'fenced code block' row in skill-security-scanner table
CI failure on dev tip (567f4475, Squad CI run 27488323855):
test/docs-build.test.ts > 'all code blocks are properly fenced (even
count of backticks)' → expected 1 to be 0
test/docs-build.test.ts > 'code blocks contain language specification
or valid content' → expected 1 to be greater than 1
Root cause: a 4-backtick table cell intended to display a literal
triple-backtick:
| Inside a fenced code block (\\\\ \\\ \\\\) | Suppressed |
made the regex /\\\/g see 5 triple-backtick occurrences across the
file (instead of the 2 from the real bash example), tripping both the
even-fence check and the line-count > 1 check.
Rephrased the table to say 'three backticks' / 'single backtick' in
prose — no embedded delimiters, no need to defend against the markdown
fence escape mechanism. Reads cleaner anyway.
Verified locally: 22/22 docs-build tests pass; npm run build in docs/
completes (171 files emitted; pagefind indexes 168 pages, 6911 words).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(cli): rename hire to cast (#1394)
The canonical command for adding team members is now 'cast' — we're casting
agents, not hiring humans. 'hire' continues to work silently as an alias
(like cls/clear in PowerShell).
- squad cast (no args) → shows roster (existing behavior preserved)
- squad cast --name X --role Y → launches team creation wizard
- squad hire → always launches the wizard (silent alias)
Updated all CLI help text, README docs, blog posts, SDK templates, and
skill files. Added 'cast' to test expectations while keeping 'hire' in
the recognized-commands list.
Closes #1393
Co-authored-by: brady gaster <bradygaster@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add OSS release checklist files (#1217)
* Add OSS release checklist files
- CODE_OF_CONDUCT.md (Contributor Covenant v1.4)
- SUPPORT.md (points to GitHub Discussions)
- .github/CODEOWNERS (@bradygaster @tamirdresher)
- README.md: add Requirements, License, Maintainers, Support, Contributing, Code of Conduct sections
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* feat: add 'squad preset install <source>' for sharing presets via repo URL (#1224) (#1225)
* feat: add 'squad preset install <source>' for sharing presets via repo URL (#1224)
Closes #1224. Adds a new subcommand that installs a single preset from
a GitHub URL or local path into \\/presets/<name>/\ — the
peer-to-peer preset sharing flow that was missing in v0.10.0.
SDK side (squad-sdk/src/presets/index.ts):
- New \installPresetFromSource(source, options)\ function
- Resolves source: GitHub URL → shallow git clone --depth 1 to OS temp;
local path → use as-is
- Locates preset within source via 3 patterns:
- dir contains preset.json → single-preset source
- dir contains presets/ subdir → require --name to pick
- dir IS the presets/ dir → require --name (or auto-pick if only one)
- Validates preset.json before any destructive action
- Copies preset.json (with optional rename) + agents/ into squad home
- Cleans up temp clones in finally block (success or failure)
- Exports: installPresetFromSource, InstallPresetOptions, InstallPresetResult
CLI side (squad-cli/src/cli/commands/preset.ts):
- New 'install' dispatcher case + presetInstall() function
- Supports --name <override>, --force
- Module docstring + default usage help updated to include 'install'
Supported source shapes:
https://github.com/owner/repo
https://github.com/owner/repo#preset-name (frag as subdir hint)
https://github.com/owner/repo/tree/branch/path/... (sub-path)
git\@github.com:owner/repo.git (SSH)
./local/path (single preset OR collection)
Smoke tested all 6 cases locally:
1. Local single-preset → installs under manifest.name ✅
2. Idempotent re-install fails without --force ✅
3. --force overwrites ✅
4. --name renames + updates manifest.name ✅
5. Invalid source → clear error ✅
6. GitHub URL (cloned bradygaster/squad's presets/builtin/default) ✅
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(presets): address 6 review comments — security, validation, fragment semantics, tests, help block
Addresses all six review comments on bradygaster/squad#1225:
1. [security] git clone via execSync was vulnerable to shell injection
because the command was built as a string. Switched to execFileSync
with an argument array (no shell), so source / ref values containing
';' '&&' '|' backticks etc. can no longer be interpreted by a shell.
The earlier ad-hoc whitespace/quote escaping was the wrong defence
layer.
2. [security] nameHint was used in path.join without validation. A value
like '../something' would have escaped the presets/ directory. Added
validatePathSegment() that rejects path separators ('/' '\\'), '..',
'.', null bytes. Applied both at the public installPresetFromSource()
entry AND inside locatePresetWithinSource() as defence-in-depth in
case future callers go direct. Also added validateSubPath() for the
URL-fragment-derived subPath: rejects absolute paths and '..' segments.
3. [correctness] Fragment semantics: 'repo#some-name' (bare fragment, no
slash) was being treated as a literal subPath, so it looked for
<clone>/some-name/ and broke the documented <clone>/presets/some-name/
collection layout from the PR description. Restructured
resolveInstallSource to return a new nameHint field alongside subPath:
- Fragment WITH '/' -> literal subPath (e.g. repo#packs/team-a)
- Fragment WITHOUT '/' -> preset-name HINT (e.g. repo#my-team)
The nameHint is forwarded to locatePresetWithinSource without being
used as a path segment itself, so the common collection layout now
works as advertised.
4. [UX] --name parsing didn't validate that a value was actually
provided. 'squad preset install <src> --name' (no value) or
'--name --force' (next arg is a flag) silently produced undefined or
'--force' as the override and failed downstream with a confusing
error. Added an early fail-fast guard with a clear usage hint.
5. [tests] Added 7 focused tests for installPresetFromSource covering
the new code path:
- single-preset local source (startDir/preset.json present)
- collection local source + --name selection
- collection source without --name throws with helpful message
- --force overwrite of an existing same-name preset
- --name rename + manifest.name stamping (other fields preserved)
- --name path-escape attempts are rejected
- empty source throws 'required'
Remote (URL) branch isn't stubbed here — splitting the git-clone
call into a small helper that tests can mock is a separate follow-up.
6. [docs] preset help block in command-help.ts still printed
Usage: squad preset <list|show|apply|save|init> without 'install'.
Updated to include 'install <source>', the new --name option, and a
concise documentation of the fragment semantics from fix #3.
Verified locally: 36/36 preset tests pass (29 existing + 7 new);
14/14 command-help tests pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: update adapter/client.ts for @github/copilot-sdk 1.0.4 API changes (#1403)
* fix: update adapter/client.ts for @github/copilot-sdk 1.0.4 API changes
- Replace removed cliPath/cliArgs/useStdio/port/cliUrl options with RuntimeConnection
- 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 lifecycle events
Unblocks Dependabot PRs #1364 and #1370 which surface these type errors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: update test mocks for @github/copilot-sdk 1.0.4 API changes
- Add RuntimeConnection and onLifecycle to all 4 copilot-sdk test mocks
- Fix command-help.test.ts expected commands list (remove stale entries)
- Regenerate package-lock.json after merging dev (OTel dep alignment)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: brady gaster <bradygaster@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* deps: bump @opentelemetry/sdk-metrics and sdk-trace-node to 2.8.0 (#1404)
Bumps both OpenTelemetry SDK packages from 1.x to 2.8.0:
- @opentelemetry/sdk-metrics: ^1.30.0 → ^2.8.0
- @opentelemetry/sdk-trace-node: ^1.30.0 → ^2.8.0
The createGauge API is still supported in SDK 2.x — no code changes
needed. All OTel tests and SDK export validations pass.
Closes #1364, Closes #1370
Co-authored-by: brady gaster <bradygaster@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(cli): pin squad-sdk to workspace:* (fixes prerelease build crash) (#1406)
* fix(cli): pin squad-sdk workspace dependency
Closes #1405
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix CLI SDK workspace resolution
Closes #1405
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix green test suite (#1416)
* Fix green test suite
Align local test expectations with current personal squad paths, stabilize observer file category detection, skip unavailable docs/Aspire capabilities, and add the missing OTel context test dependency.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix observer review hardening
Closes #1416
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Stage 0.11.0 release (#1420)
Prepare clean 0.11.0 package versions and CHANGELOG notes for release staging.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Guard symlink test for Windows/restricted environments (#1418)
* fix(test): guard observer symlink setup
Handle restricted symlink creation in the observer symlink test so Windows and locked-down environments can continue the suite.
Refs #1416
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address symlink test review feedback
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add tools: ["*"] to Squad coordinator agent template (#1424)
Without this field, Copilot CLI 1.0.66+ interprets the missing tools key as tools: [], so the Squad coordinator loads with no built-in tools (shell, view, edit, grep, glob) and only MCP-exposed tools (skill, sql) remain available. Basic operations like listing files or editing fail.
Setting tools: ["*"] in the canonical .squad-templates/squad.agent.md and mirrored copies (top-level templates/, packages/squad-cli/templates/, packages/squad-sdk/templates/) restores the previous behavior of exposing all built-in tools to the coordinator. .github/agents/squad.agent.md is intentionally left out of this PR.
Resolves the architectural-review nudge: sync-templates.mjs treats .squad-templates/ as canonical; mirrors are bundled into the published npm packages, so all of them must carry the fix for the next release to ship correctly.
* fix(sdk): allow identity/* state writes and widen squad_decide author validation (#1419)
* fix(sdk): allow identity/* state writes and widen squad_decide author validation
- add identity/ to the mutable-state allowlist (Closes #1255)
- relax squad_decide author regex with a 200-char cap; slugify author
for the inbox filename while preserving the raw display name (Closes #1256)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(sdk): address Copilot review — reject empty author slug, report real filename
Closes #1255
Closes #1256
Add empty-slug guard: authors that slugify to empty string (e.g. ' ', '()', '---', '...') now return a failure instead of writing a malformed filename. Fix success message to report the actual slugified filename written on disk instead of the raw author string.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: remove duplicate cast entry in squad -h output (#1428)
* fix: remove duplicate cast entry in squad -h output
Consolidate the two 'cast' help entries into a single entry with unified
description showing it displays the current session cast (project + personal
agents) and accepts --name/--role flags for adding agents.
Closes #1423
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: add changeset for cast help fix
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* style: fix indentation on cast usage line
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(presets): round-trip routing.md in preset save/apply (#1429)
* fix(presets): round-trip routing.md in preset save/apply
savePreset now captures .squad/routing.md into the preset snapshot.
applyPreset restores the saved routing.md before scaffolding so that
custom label tables, module ownership mappings, and other routing
rules survive the save/apply cycle.
Closes #1412
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(presets): address review - overwriteRouting option and truthiness checks
- Add overwriteRouting option to applyPreset so callers (e.g. squad init
--preset) can replace an existing skeleton routing.md with the preset's
saved version without forcing agent overwrites.
- Use !== undefined instead of truthiness for readSync results so
intentionally-empty routing.md files are faithfully round-tripped.
- Add regression test for overwriteRouting replacing existing skeleton.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(cli): pin squad-sdk dependency (#1431)
* fix(cli): pin squad-sdk dependency
Ensure published squad-cli installs require the matching squad-sdk version so APIs introduced in 0.11.0 cannot be paired with an older SDK.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix: use >=0.11.0 range and add missing export assertions
- Change SDK dep from ^0.11.0 to >=0.11.0 to survive lockstep minor bumps
- Add readSquadRegistry, addRegistryEntry, removeRegistryEntry to
cross-package exports test (also 0.11.0-only CLI imports)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: brady gaster <bradygaster@github.com>
* deps: bump astro from 6.4.7 to 7.0.3 in /docs (#1409)
Bumps [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) from 6.4.7 to 7.0.3.
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@7.0.3/packages/astro)
---
updated-dependencies:
- dependency-name: astro
dependency-version: 7.0.3
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* feat(sdk,cli): thread contextTier through agent spawning pipeline (#1448)
* feat(sdk): thread contextTier through agent spawning pipeline
Adds a contextTier concept (default vs long_context / 1M context window)
threaded end-to-end through the SDK and CLI, mirroring the reasoningEffort
plumbing from #1148. Models expose supportedContextTiers/defaultContextTier;
requests validate and clamp against what a model supports. Adds the
'squad config context-tier' CLI subcommand and coordinator guidance.
Closes #1446
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(sdk): simplify clampContextTier guard to match clampReasoningEffort (addresses PR review)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix doctor decisions check for two-layer state (#1434)
* Fix doctor decisions check for two-layer state
Closes #1433
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add orphan doctor coverage
Address review feedback by exercising the orphan backend decisions.md path alongside two-layer and git-notes.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Improve doctor backend fallback message
Address review feedback by reporting the resolved backend when doctor cannot inspect the configured squad-state backend.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Normalize doctor hook backend detection
Address review feedback by applying legacy backend alias normalization before deciding whether sync hooks are required.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Fix docs build for Astro markdown plugins
Declare Astro's legacy markdown processor package and avoid running the expensive docs build twice in the same test.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* chore: add auto version-promote workflow for dev branch (#1457)
After a release is published from main, this workflow automatically
bumps the dev branch to the next minor version (e.g., 0.11.0 -> 0.12.0).
Addresses #1455
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(templates): resolve GitHub API host from env in ralph-triage.js (#1438)
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 resolveGithubApiBase(), which 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. The request is now built from a URL object
instead of a hardcoded hostname/path pair. No behavior change on
github.com-hosted repos.
Fixed in the canonical .squad-templates/ralph-triage.js and synced to
the 3 mirror targets. Added unit tests covering all three resolution
branches.
Documented the env var resolution order in the CI/CD integration docs
so GHE users can discover it.
Closes #1142
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(cli): resolve externalized state in squad export (#1443)
After `squad externalize` moves team state out of the working tree,
`squad export` still read directly from the local .squad/ directory via
detectSquadDir(). Depending on what remained locally, it either died
with the misleading "No squad found — run init first" (the marker-only
.squad/ has no team.md) or silently exported stale/re-scaffolded local
files instead of the real team knowledge in the external state dir —
a corrupt backup that reports success.
Route export through effectiveSquadDir(), the same external-state-aware
resolution already used by build, loop, plugin, watch, and doctor. All
state reads (team.md, decisions.md, routing.md, casting/, agents/, and
.squad-local skills) now come from the effective state directory; the
existence check and manifest build both use it. Working-tree skill
sources (.copilot/skills, .ai-team/skills) are unchanged, as is legacy
.ai-team behavior (no external marker there, resolution falls through
to the local path).
Added two regression tests that fail without the fix: one exporting
from a marker-only externalized project (previously fatal), one
proving external state wins over stale local files when the
stateLocation marker is set (previously exported the stale copy).
Fixes #1396
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(init): include proposed roster in confirmation prompt (#1460)
Make the blocking ask_user question self-contained by reusing every
exact step-4 roster line (universe, members, roles, scopes) so users
can review the team even when preceding assistant output is hidden.
Closes #1454
Co-authored-by: Kartik <kartikkabadi@users.noreply.github.com>
* Refresh model catalog to CLI-reachable IDs and prune dead fallback chains (#1444)
* fix(models): refresh catalog to CLI-reachable IDs and prune dead fallbacks
Replace the model catalog with the 13 GitHub Copilot CLI-reachable models
(copilot-cli integration set) and remove IDs no longer offered
(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). Update runtime + SDK fallback chains,
schema defaults, and the economy-mode map to real IDs, fixing routing that
referenced retired models.
Add an optional githubCategory cost-ceiling field (lightweight/versatile/
powerful) sourced from the models API model_picker_category, kept as a
separate axis from the existing quality tier. No hardcoded per-token pricing
is added for new entries and no included/zero-credit flag is introduced.
Add catalog-refresh invariant tests: no dead IDs in chains; every chain ID
exists in the catalog; gpt-5 is treated as dead (verified absent from the
Copilot models API and the public github/docs pricing YAML); and the
MODEL_CATALOG ID set exactly equals the expected curated 13-ID seed so any
unexpected reintroduction fails. Update existing model/economy/config tests.
Refs #1080
Refs #1183
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(templates): sync shipped prompt/template assets + CLI strings to refreshed model catalog
Addresses the reviewer correctness note on PR #1444: shipped prompt/template assets
still referenced model IDs removed from the runtime catalog by the catalog-refresh
commit (f5479b0f), meaning generated squads could steer real agent spawns toward
unreachable IDs. Fixes all occurrences across canonical sources; sync scripts
propagate the changes to the 10 auto-generated copies.
Template/skill canonical source fixes (4 sources → 10 synced copies):
- .squad-templates/model-selection-reference.md: claude-opus-4.5→4.6 (Visual role +
Premium chain + spawn example), remove claude-sonnet-4 from Standard chain, remove
gpt-5.1-codex-mini+gpt-4.1 from Fast chain, gemini-3-pro-preview→gemini-2.5-pro
(analytical diversity switch), Valid-models section refreshed to 13-ID catalog
- .squad-templates/ralph-circuit-breaker.md: remove gpt-4.1 from multiplier table,
OPEN-state fallback list, JSON/PS state examples, and config reference table
- .squad/skills/model-selection/SKILL.md: remove claude-opus-4.6-fast+claude-opus-4.5
from Premium chain, claude-sonnet-4 from Standard chain, gpt-5.1-codex-mini+gpt-4.1
from Fast chain (fallback chains section only — lines 119-121)
- .squad/skills/economy-mode/SKILL.md: gpt-4.1→gpt-5-mini throughout economy table,
claude-opus-4.5→claude-opus-4.6 (Normal Mode premium row), remove "Prefer gpt-4.1
over gpt-5-mini" paragraph
Manual edit (outside sync path):
- .copilot/skills/model-selection/SKILL.md: same chain fixes as model-selection SKILL
plus gemini-3-pro-preview→gemini-2.5-pro, claude-opus-4.5→4.6 (Visual role + task
table), gpt-5.2-codex→gpt-5.3-codex (Layer 1 example + Example 3), Valid-models
section refreshed
CLI user-facing display string fixes (4 files, dead token only):
- packages/squad-cli/src/cli/commands/economy.ts: gpt-4.1→gpt-5-mini (×2, economy
downgrade display — matches ECONOMY_MODEL_MAP already updated in f5479b0f)
- packages/squad-cli/src/cli/shell/error-messages.ts: gpt-4.1→gpt-5-mini (rate-limit
recovery suggestion)
- packages/squad-cli/src/cli-entry.ts: claude-sonnet-4→claude-sonnet-4.6 (start help
example)
- packages/squad-cli/src/cli/core/command-help.ts: claude-sonnet-4→claude-sonnet-4.6
(start help example)
Test: expand DEAD_MODEL_IDS in test/catalog-refresh.test.ts to include claude-opus-4.5
and claude-opus-4.6-fast (live-but-dropped-from-seed for runtime chains, but dead in
practice for template guidance). Add new `describe` block "template asset catalog
invariants" that globs .squad-templates/**/*.md, .squad/skills/**/*.md, and
.copilot/skills/**/*.md at test time, scanning each for dead IDs with a
(?![-.\d]) lookahead to prevent gpt-5 from matching gpt-5-mini or gpt-5.4.
All 7 catalog-refresh invariants GREEN. `npm run lint` clean.
Refs #1080, #1183
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(review): add fallback-degradation tests, sonnet ordering comments, and catalog warning
B1: add describe block in test/compat-v041.test.ts asserting getNextFallback
for removed IDs ('gpt-4.1', 'claude-sonnet-4') resolves to a live catalog
model and does not throw.
A1: add inline comments in packages/squad-sdk/src/config/models.ts and
packages/squad-sdk/src/runtime/constants.ts explaining why claude-sonnet-4.6
precedes claude-sonnet-5 in the standard fallback chain (established default
with known pricing vs newer model with no tracked pricing yet).
A3: in validateConfigDetailed (packages/squad-sdk/src/runtime/config.ts),
push a non-blocking warning when config.models.defaultModel is a non-empty
string not present in MODEL_CATALOG. Existing configs with dead IDs still
load — a warning is emitted, not an error. Test added to
test/config-integration.test.ts.
Changeset: fold A3 mention into .changeset/refresh-model-catalog-1080.md.
Addresses reviewer feedback on bradygaster/squad#1444.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(review): correct A1 comment — ordering is MODELS.DEFAULT primacy only
Both claude-sonnet-4.6 and claude-sonnet-5 carry identical cost: 5 /
speed: 7 metadata. The previous comment overstated the pricing angle.
The sole code-backed reason for 4.6 leading the standard chain is that
it is MODELS.DEFAULT (the established primary); sonnet-5 was newly added
in this catalog refresh and is first fallback.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(platform): add setAssignee() to PlatformAdapter (GitHub + ADO) (#1413)
Routes assignee changes through the adapter instead of inline gh/az calls in watch. Adds GitHub + ADO impls, refactors editWorkItem, tests + changeset.
Co-authored-by: OrenMaoz <ormaoz@microsoft.com>
* refactor(cli): consolidate duplicated agent-spawn logic across watch capabilities (#1437)
execute.ts and wave-dispatch.ts each carried their own copy of
buildAgentCommand() and a spawn-with-timeout helper, diverging from the
shared agent-spawn.ts module added for #920/#923 because they needed
the withAdditionalMcpConfig wiring. Extract a buildCopilotCommand()
helper and extend spawnAgent() with optional pid-tracking so both
capabilities import from the shared module instead of keeping local
copies. As a side effect, execute's Copilot spawn now goes through the
same Windows cmd.exe argument-escaping path as the rest of watch.
Fixes #994
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ci: pin GitHub Actions references to full-length commit SHAs (#1442)
Every uses: reference across .github/workflows/*.yml (and the local
setup-squad-node composite action they call into) pointed at a
floating version tag (@v7, @v6, etc.) instead of an immutable commit
SHA. Orgs that require SHA-pinned actions as a supply-chain policy
can't adopt Squad's shipped workflows without hand-patching them,
and re-patching again on every squad upgrade.
Resolved each of the 10 unique action@tag pairs in use to its current
commit SHA via the GitHub API and rewrote every uses: line to
owner/repo@<sha> #vX, keeping the original version as a trailing
comment for readability/auditability. The two ./.github/actions/...
local action references are untouched — they have no tag to pin,
they're already pinned by living in-repo.
Also pinned the same 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) across
all 4 template locations (.squad-templates/ canonical source, plus
its 3 synced mirrors: templates/, packages/squad-cli/templates/,
packages/squad-sdk/templates/) so squad init/upgrade ships pinned
workflows too, not just this repo's own dogfooded copies. These
templates use older tags than .github/workflows (checkout@v4 vs v7,
github-script@v7 vs v9, etc.) — pinned each to its own existing tag
rather than silently bumping versions, since a version bump is a
separate concern from pinning. squad-insider-release.yml (template)
was left untouched: it has no .github/workflows counterpart, it's a
distinct downstream-only workflow (different triggers/jobs/permissions
entirely, not a sync pair with squad-insider-publish.yml).
61 files, 172 lines changed, no other content touched. Verified all
changed workflow/action YAML still parses with js-yaml. Added a
changeset since this now touches governed template paths.
Fixes #1441
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(cli): patch repo-local node_modules on upgrade, check commit hooks in doctor (#1463)
The postinstall ESM patcher returned at the first search root that already
had a patched copy, so on global installs the consumer repo's node_modules
was never reached — the cwd entry added to SEARCH_ROOTS in 2d9f0b4e was
effectively dead code. The patcher now patches every root it finds, and
squad upgrade re-runs it against the repo's own node_modules via
runEnsureChecks, covering both the normal and already-current paths.
squad doctor's hook check now includes pre-commit/post-commit (the hooks
that guard and flush two-layer state) for two-layer/orphan backends,
matching the full set install-hooks.ts installs, instead of only the four
sync hooks.
Part of #1190
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(cli,sdk): follow externalized state in squad cast agent discovery (#1465)
squad externalize writes teamRoot '.' plus the stateLocation marker, so
an externalized repo lands in resolveSquadPaths' remote mode with a
repo-local teamDir — squad cast then probes <repo>/.squad/agents, which
after externalize is a marker dir holding stale leftovers or nothing.
The real agents live at <externalStateDir>/agents with no .squad
nesting, a shape LocalAgentSource's probing can't reach from any base
path.
LocalAgentSource gains an optional explicit agents directory that wins
over the .squad/agents probing (additive, existing callers unchanged),
and cast passes <externalStateDir>/agents when the marker is set.
resolveExternalStateDir is imported from the /resolution subpath the
command already uses — pulling the sdk root barrel into cast.ts added
seconds to the module load and tripped the cast test suite's 5s timeout.
Fixes #1399
Part of #1402
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: align external-state page with actual externalize/internalize behavior (#1466)
The page promised gitignore behavior the code never had: externalize
only ignores .squad/config.json (the machine-specific marker), not all
of .squad/, and internalize doesn't touch .gitignore at all. The marker
example was also missing the version/teamRoot/projectKey fields the
command actually writes, the stateLocation table listed an "internal"
value that is never written (absence means internal), and the git
status sample showed a gitignored file as untracked, which git doesn't
do. Internalize copies state back rather than moving it — the external
copy stays in place (#1401 tracks whether that should become a move).
Documents current behavior only, no code change.
Fixes #1400
Part of #1402
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs/models: prefer newest per series (Opus 4.8), add GPT-5.6 IDs, fix Ralph free-model wording (#1469)
* docs/models: prefer newest per series (Opus 4.8 + Sonnet 5), add GPT-5.6 IDs, fix Ralph free-model wording
Follow-up to bradygaster/squad#1444 (merged), addressing tamirdresher's
three explicit requests in https://github.com/bradygaster/squad/pull/1444#issuecomment-4954513635
(refs #1080, #1183).
Item 1 — Prefer newest model per series (fallback ordering):
- packages/squad-sdk/src/config/models.ts: DEFAULT_FALLBACK_CHAINS.standard
now leads with claude-sonnet-5 (was claude-sonnet-4.6).
- packages/squad-sdk/src/runtime/constants.ts: MODELS.FALLBACK_CHAINS.standard
same reorder. Premium chains already led with claude-opus-4.8 post-#1444.
- model-selection-reference.md, SKILL.md files: examples now show
claude-opus-4.8 first in Premium, claude-sonnet-5 first in Standard.
Item 2 — Add GPT-5.6 model IDs (gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna):
- Added to MODEL_CATALOG in models.ts (tier: standard, githubCategory: powerful
— mirrors gpt-5.5 sibling entry).
- Added to DEFAULT_FALLBACK_CHAINS.standard and MODELS.FALLBACK_CHAINS.standard
(after claude-sonnet-4.6, before gpt-5.4).
- Reachability: CLI-observed as Standard-tier reachable models (2026-07-13).
- NOTE: gpt-5.6 entries in DOCS_NAME_TO_ID (cli/commands/models.ts) are
deferred until draft PR #1445 merges (that file is in #1445's diff).
- Updated Valid Models in all model-selection-reference.md + SKILL.md copies.
Item 3 — Ralph circuit-breaker free-model wording:
- .squad-templates/ralph-circuit-breaker.md: replaced multiplier table
(0x / "Free — unlimited") with usage-based framing (lightweight category —
lowest-cost, still billed). Updated preferredModel example to claude-sonnet-5.
- Synced to all 3 template targets via sync-templates.mjs.
NOTE: MODELS.DEFAULT (claude-sonnet-4.6) is intentionally left unchanged.
That global default is out of scope for this PR — can be a separate decision.
TDD: test/catalog-refresh.test.ts — wrote failing tests first (8 RED), then
implemented changes. Final result: 16/16 tests GREEN.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(models): sync full Standard chain in doc/skill examples; add changeset
Address Copilot review comments on PR #1469:
- 3 doc/skill files had abbreviated Standard fallback chain (omitting
gpt-5.6-terra, gpt-5.6-luna, gemini-2.5-pro). Now matches the full
SDK runtime chain exactly:
claude-sonnet-5 → claude-sonnet-4.6 → gpt-5.6-sol → gpt-5.6-terra
→ gpt-5.6-luna → gpt-5.4 → gpt-5.3-codex → claude-sonnet-4.5
→ gemini-2.5-pro → (omit model param)
Files: .squad-templates/model-selection-reference.md,
.copilot/skills/model-selection/SKILL.md (manual),
.squad/skills/model-selection/SKILL.md (sync canonical)
Synced to all 3 template targets + 2 skill package targets.
- Premium chain confirmed correct (claude-opus-4.8 first) — no change
needed.
- Add .changeset/models-gpt56-fallback-ordering.md (@bradygaster/squad-sdk
patch) to satisfy Changelog Gate CI check.
16/16 catalog-refresh tests remain GREEN.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test: update stale standard-chain[0] assertions to claude-sonnet-5
Three test files hard-coded the old fallback chain head (claude-sonnet-4.6)
that was intentionally reordered in the parent commit (newest-per-series
first, tamirdresher PR #1444 follow-up). The tests remain logically correct
— they now assert the NEW intended behavior.
- test/compat-v041.test.ts: standard[0] → 'claude-sonnet-5'
- test/models.test.ts: standard[0] → 'claude-sonnet-5'
- test/agents.test.ts: standard fallback chain toEqual updated
(reordered + added gpt-5.6-sol/terra/luna)
Inline comment added to each noting the deliberate reorder.
Pre-existing failures (cli-packaging-smoke, init-scaffolding) are EBUSY
file-lock errors unrelated to these changes — confirmed on baseline.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(models): correct gpt-5.6 billing categories to match live Copilot API
Live API (canonical) returns: sol=powerful, terra=versatile, luna=lightweight.
Original seed incorrectly set all three to 'powerful' (mirroring gpt-5.5).
Tier (standard) and fallback-chain membership are unchanged; only githubCategory
(the cost-policy billing axis) is corrected.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* deps: bump the minor-patch group across 1 directory with 22 updates (#1451)
---
updated-dependencies:
- dependency-name: "@github/copilot-sdk"
dependency-version: 1.0.5
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: minor-patch
- dependency-name: "@opentelemetry/context-async-hooks"
dependency-version: 2.9.0
dependency-type: direct:development
update-type: version-update:semver-minor
dependency-group: minor-patch
- dependency-name: "@opentelemetry/exporter-metrics-otlp-grpc"
dependency-version: 0.220.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: minor-patch
- dependency-name: "@opentelemetry/exporter-trace-otlp-grpc"
dependency-version: 0.220.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: minor-patch
- dependency-name: "@opentelemetry/resources"
dependency-version: 2.9.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: minor-patch
- dependency-name: "@opentelemetry/sdk-metrics"
dependency-version: 2.9.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: minor-patch
- dependency-name: "@opentelemetry/sdk-node"
dependency-version: 0.220.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: …
PR #1291 added
squad registry add/list/removeand thecross-squad/SKILL.mdfor peer discovery. But discovery is only half the story — once a peer is known, agents need to know how to actually exchange info with it.This change ports
cross-squad-communicationfrom tamirdresher/squad-skills into the bundled skills so a freshsquad initproduces a coordinator that knows the four communication patterns.What this skill teaches
copilotwith--working-directoryset to target repoteam.md/decisions.mddirectly.squad/cross-squad/requests/+.squad/cross-squad/responses/gh issue createwithsquad:cross-squadlabel as the message busPlus: decision tree for choosing the right pattern, anti-patterns, request/response YAML format, validation status.
Changes
.squad/skills/cross-squad-communication/SKILL.md(379 lines, canonical source).sync-skill-templates.mjs(which runs inprebuild) propagates to bothpackages/squad-cli/templates/skills/andpackages/squad-sdk/templates/skills/.MANIFEST_SKILL_NAMESinpackages/squad-sdk/src/config/init.tsgrows by 1 entry:cross-squad-communication→ 11 entries total.cross-squad/SKILL.md(the registry-aware skill from feat(cli): add squad registry add/list/remove for discovery-only peer squads (#1290) #1291) gets a one-paragraph "Companion skill" note at the top pointing tocross-squad-communicationfor protocol details. The two are designed to be used together:cross-squadanswers "who?" (discovery via registry),cross-squad-communicationanswers "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 are meaningful to all upstream users. The protocol mechanics are unchanged. The frontmattersource:attributes the port totamirdresher/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.mdafterinitSquad()and the content contains the expected pattern names. 26/26 init tests pass;npm run lintclean.Composition with #1291
`�ash
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, andcross-squadtoMANIFEST_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.