Skip to content

feat(cli): add squad registry add/list/remove for discovery-only peer squads (#1290) - #1291

Merged
tamirdresher merged 1 commit into
devfrom
squad/1290-registry-subcommand
Jun 12, 2026
Merged

feat(cli): add squad registry add/list/remove for discovery-only peer squads (#1290)#1291
tamirdresher merged 1 commit into
devfrom
squad/1290-registry-subcommand

Conversation

@tamirdresher

Copy link
Copy Markdown
Collaborator

Summary

Closes #1290.

Adds CLI surface for managing .squad/squad-registry.json, symmetric to squad upstream. Registry entries are discovery-only — peers are visible to squad discover and addressable via squad delegate, but their skills/decisions/wisdom/routing are NOT inherited. This is the cleanest answer for "I want to reference another squad without making it a parent."

What's new

squad registry add <name> <path>     # validates manifest, refuses duplicate
squad registry list                   # show registered peers
squad registry remove <name>          # remove by name

Why

Previously, the only way to register a peer squad without inheritance was to hand-edit .squad/squad-registry.json. The squad discover error message even said "create a squad-registry.json" — telling users to bypass the CLI. That's a UX asymmetry — squad upstream add exists, but the registry equivalent didn't.

Path-semantics fix (same PR)

readManifest() now accepts BOTH repo-root and repo-root/.squad paths. The docs/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 failedsquad discover returned nothing with no error. Empirically reproduced before the fix; both forms work after.

Files

File Change
packages/squad-sdk/src/runtime/cross-squad.ts Dual-path readManifest + registry CRUD helpers + RegistryEntry / AddRegistryEntryResult types
packages/squad-sdk/src/index.ts Export new helpers/types
packages/squad-cli/src/cli/commands/cross-squad.ts New registryCommand with add/list/remove
packages/squad-cli/src/cli-entry.ts registry command handler + help text
.squad/skills/cross-squad/SKILL.md (+2 template mirrors) Document registry vs upstream distinction explicitly; fix the wrong path form
test/cross-squad-registry.test.ts 18 new tests
.changeset/registry-subcommand.md Minor bump for both packages

Also updates the squad discover empty-state hint to mention squad registry add.

Tests

50/50 pass (32 existing cross-squad.test.ts + 18 new):

  • Dual-path readManifest (repo-root, .squad, .squad/)
  • Registry round-trip + malformed-JSON resilience
  • addRegistryEntry: success / duplicate-name / invalid-manifest
  • removeRegistryEntry: exists / missing
  • End-to-end: registry entries surface in discoverSquads with source=registry
 ✓ test/cross-squad.test.ts (32 tests) 61ms
 ✓ test/cross-squad-registry.test.ts (18 tests) 125ms
 Test Files  2 passed (2)
      Tests  50 passed (50)

End-to-end verified

Ran on local test fixture (squad-memory-governance-test registering squad-advanced-squad-session-slides as a peer):

$ squad registry add friend-squad ../squad-advanced-squad-session-slides/.squad
✓ Registered peer squad "friend-squad" → ...\.squad
  Capabilities: multi-agent, copilot, sdk, cli
  Repo: bradygaster/squad
  Accepts: issues, prs

$ squad discover
Discovered squads:
  squad  →  bradygaster/squad  (multi-agent, copilot, sdk, cli)
    Accepts: issues, prs  |  Source: registry (friend-squad)

$ squad registry add friend-squad ...
✗ A peer named "friend-squad" is already registered. Remove it first: ...

$ squad registry add bogus /nonexistent
✗ No valid .squad/manifest.json found at /nonexistent.
  Expected: /nonexistent/.squad/manifest.json (or /nonexistent/manifest.json if you pointed at .squad/).

$ squad registry remove friend-squad
✓ Removed peer squad "friend-squad" from the registry.

$ squad discover
No squads discovered. Add a peer with "squad registry add <name> <path>", or an upstream with "squad upstream add".

Build clean (npm run build 14s, exit 0).

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>
Copilot AI review requested due to automatic review settings June 12, 2026 17:44
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Squad File Leakage Detected

The following .squad/ files were modified in this PR:

  • .squad/skills/cross-squad/SKILL.md

These files affect team routing, agent charters, and decisions.
If intentional, ensure approval from the team lead.

@github-actions

Copy link
Copy Markdown
Contributor

🟠 Impact Analysis — PR #1291

Risk tier: 🟠 HIGH

📊 Summary

Metric Count
Files changed 9
Files added 2
Files modified 7
Files deleted 0
Modules touched 5
Critical files 1

🎯 Risk Factors

  • 9 files changed (6-20 → MEDIUM)
  • 5 modules touched (5-8 → HIGH)
  • Critical files touched: packages/squad-sdk/src/index.ts

📦 Modules Affected

root (1 file)
  • .changeset/registry-subcommand.md
squad-cli (3 files)
  • packages/squad-cli/src/cli-entry.ts
  • packages/squad-cli/src/cli/commands/cross-squad.ts
  • packages/squad-cli/templates/skills/cross-squad/SKILL.md
squad-sdk (3 files)
  • packages/squad-sdk/src/index.ts
  • packages/squad-sdk/src/runtime/cross-squad.ts
  • packages/squad-sdk/templates/skills/cross-squad/SKILL.md
squad-state (1 file)
  • .squad/skills/cross-squad/SKILL.md
tests (1 file)
  • test/cross-squad-registry.test.ts

⚠️ Critical Files

  • packages/squad-sdk/src/index.ts

This report is generated automatically for every PR. See #733 for details.

@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Architectural Review

⚠️ Architectural review: 1 warning(s), 1 info.

Severity Category Finding Files
🟡 warning export-surface Package entry point(s) modified with 7 new/changed export(s). New public API surface requires careful review for backward compatibility. packages/squad-sdk/src/index.ts
ℹ️ info template-sync Template files changed in packages/squad-cli/templates/ but not in other template locations. If these templates should stay in sync, consider updating the others too. Changed: packages/squad-cli/templates/, Unchanged: templates/, .squad-templates/, .github/workflows/

Automated architectural review — informational only.

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

ℹ️ This comment updates on each push. Last checked: commit b420990

PR Scope: 📦🔧 Mixed (product + infrastructure)

⚠️ 2 item(s) to address before review

Status Check Details
Single commit 1 commit — clean history
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 ⚠️ PR includes 1 .squad/ file(s) — ensure these are intentional
No merge conflicts No merge conflicts
Copilot threads resolved No Copilot review threads
CI passing 1 check(s) still running

Files Changed (9 files, +545 −19)

File +/−
.changeset/registry-subcommand.md +20 −0
.squad/skills/cross-squad/SKILL.md +17 −5
packages/squad-cli/src/cli-entry.ts +10 −0
packages/squad-cli/src/cli/commands/cross-squad.ts +85 −2
packages/squad-cli/templates/skills/cross-squad/SKILL.md +17 −5
packages/squad-sdk/src/index.ts +6 −0
packages/squad-sdk/src/runtime/cross-squad.ts +107 −2
packages/squad-sdk/templates/skills/cross-squad/SKILL.md +17 −5
test/cross-squad-registry.test.ts +266 −0

Total: +545 −19


This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.

@tamirdresher
tamirdresher merged commit 217e0bd into dev Jun 12, 2026
15 checks passed
@tamirdresher
tamirdresher deleted the squad/1290-registry-subcommand branch June 12, 2026 17:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new squad registry CLI surface for managing discovery-only peer squads (no inheritance) via .squad/squad-registry.json, alongside SDK helpers and documentation updates. Also updates readManifest() to accept both repo-root and .squad/-suffixed paths, and adds a dedicated test suite covering registry CRUD + integration into discovery.

Changes:

  • Add squad registry add/list/remove (CLI) backed by new SDK registry CRUD helpers/types.
  • Fix readManifest() to support both repo-root and repo-root/.squad inputs; update empty-state discover hint accordingly.
  • Add new tests and update cross-squad SKILL docs to clearly distinguish registry (discovery-only) vs upstream (inheritance).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/cross-squad-registry.test.ts New test coverage for registry CRUD helpers, dual-path manifest reads, and discover integration.
packages/squad-sdk/templates/skills/cross-squad/SKILL.md Template documentation update: registry vs upstream distinction + correct path semantics.
packages/squad-sdk/src/runtime/cross-squad.ts Implements dual-path readManifest, registry CRUD helpers/types, and updates discover empty-state messaging.
packages/squad-sdk/src/index.ts Exports new registry helpers/types from the SDK public surface.
packages/squad-cli/templates/skills/cross-squad/SKILL.md CLI template documentation update matching the new registry behavior and examples.
packages/squad-cli/src/cli/commands/cross-squad.ts Adds registryCommand implementing add/list/remove and printing manifest details.
packages/squad-cli/src/cli-entry.ts Wires the new registry command into help output and command dispatch.
.squad/skills/cross-squad/SKILL.md Repo skill doc updated to match new registry semantics and recommended usage.
.changeset/registry-subcommand.md Changeset for minor bumps to CLI + SDK.

Comment on lines +130 to +133
const normalized = repoPath.replace(/[/\\]$/, '');
const root = normalized.endsWith('.squad') || normalized.endsWith('/.squad') || normalized.endsWith('\\.squad')
? normalized.slice(0, normalized.length - '.squad'.length).replace(/[/\\]$/, '')
: normalized;
Comment on lines +265 to +267
// ============================================================================
// Registry CRUD — manage .squad/squad-registry.json
// ============================================================================
Comment on lines +267 to +270
console.log(` ${BOLD}registry${RESET} Manage peer squads for cross-squad discovery (no inheritance)`);
console.log(` Usage: registry add <name> <path>`);
console.log(` registry list`);
console.log(` registry remove <name>`);
Comment on lines +124 to +126
const squadDirInfo = detectSquadDir(process.cwd());
const squadDir = squadDirInfo.path;

tamirdresher pushed a commit to tamirdresher/squad that referenced this pull request Jun 13, 2026
…tocols)

PR bradygaster#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 bradygaster#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 bradygaster#1292:
PR bradygaster#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>
tamirdresher added a commit that referenced this pull request Jun 13, 2026
…tocols) (#1295)

* feat(sdk): bundle cross-squad-communication skill (#5 cross-squad protocols)

PR #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 #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 #1292:
PR #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>

* fix: TEMPLATE_MANIFEST entry for cross-squad-communication + pattern numbering + honest source/validation

Five reviewer follow-ups on #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 #1292/#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>

* fix(skill): cross-squad-communication uses real Copilot CLI invocations (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>

* fix(skill): every cross-squad copilot spawn passes --agent squad

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>

---------

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>
tamirdresher pushed a commit to tamirdresher/squad that referenced this pull request Jun 13, 2026
…ance from tiered-memory (bradygaster#1289, bradygaster#1264)

Two regressions shipped in v0.10.0 caused several skills to silently never
reach users:

* bradygaster#1289 — squad-commands + squad-version-check were in MANIFEST_SKILL_NAMES
  but missing from packages/squad-sdk/templates/skills/. The install loop
  silently skipped missing source dirs (storage.existsSync check, no log),
  so every squad init produced an install with these two absent and the
  `squad commands` trigger phrase was a dead no-op for every v0.10.0 user.
* bradygaster#1264 — tiered-memory, iterative-retrieval, reflect existed in templates
  but were never added to MANIFEST_SKILL_NAMES. tiered-memory/SKILL.md also
  claimed confidence: high with fabricated tamirdresher/tamresearch1 measurement
  data, and referenced a non-existent docs/tiered-memory-guide.md.
* PR bradygaster#1291 updated cross-squad/SKILL.md but never added it to the manifest.

This change:

* Adds 5 missing skill dirs to .squad/skills/ (canonical source): squad-commands,
  squad-version-check, tiered-memory, iterative-retrieval, reflect.
  sync-skill-templates.mjs (which runs in prebuild) propagates them to both
  packages/squad-cli/templates/skills/ and packages/squad-sdk/templates/skills/.
* Grows MANIFEST_SKILL_NAMES from 10 → 14 entries: adds tiered-memory,
  iterative-retrieval, reflect, cross-squad.
* Replaces the silent skip in sdk-init.ts with a thrown error that names the
  missing skill(s) and points at sync-skill-templates.mjs. This is what would
  have surfaced bradygaster#1289 at build time instead of in user installs.
* Rewrites tiered-memory/SKILL.md to be honest about status:
  - frontmatter: confidence: design + source: design proposal
  - prominent Status callout linking to bradygaster#1264 for the runtime gap
  - removed fabricated measurement table
  - removed reference to non-existent docs/tiered-memory-guide.md
  - References section points only to real issues (bradygaster#1264, bradygaster#686, bradygaster#600)
* Adds a regression test in test/init.test.ts that asserts every
  manifest-curated skill ends up installed at .copilot/skills/{name}/SKILL.md.

Verified:
* npm run lint — passes (after build)
* test/init.test.ts — 26/26 pass including new regression test
* Targeted suites (test/init, test/cli/init, test/sdk) — 292/292 pass

Out of scope (tracked separately):
* tiered-memory runtime backing (.squad/memory/hot|cold|wiki/ scaffolding,
  Scribe promotion, tier-aware spawn template) — follow-up in bradygaster#1264
* cross-squad-communication plugin port from tamirdresher/squad-skills —
  separate PR

Closes bradygaster#1289
Refs bradygaster#1264

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tamirdresher added a commit that referenced this pull request Jun 13, 2026
…-memory provenance (#1289, #1264) (#1292)

* fix(sdk,cli): bundle missing skills on init + strip fabricated provenance from tiered-memory (#1289, #1264)

Two regressions shipped in v0.10.0 caused several skills to silently never
reach users:

* #1289 — squad-commands + squad-version-check were in MANIFEST_SKILL_NAMES
  but missing from packages/squad-sdk/templates/skills/. The install loop
  silently skipped missing source dirs (storage.existsSync check, no log),
  so every squad init produced an install with these two absent and the
  `squad commands` trigger phrase was a dead no-op for every v0.10.0 user.
* #1264 — tiered-memory, iterative-retrieval, reflect existed in templates
  but were never added to MANIFEST_SKILL_NAMES. tiered-memory/SKILL.md also
  claimed confidence: high with fabricated tamirdresher/tamresearch1 measurement
  data, and referenced a non-existent docs/tiered-memory-guide.md.
* PR #1291 updated cross-squad/SKILL.md but never added it to the manifest.

This change:

* Adds 5 missing skill dirs to .squad/skills/ (canonical source): squad-commands,
  squad-version-check, tiered-memory, iterative-retrieval, reflect.
  sync-skill-templates.mjs (which runs in prebuild) propagates them to both
  packages/squad-cli/templates/skills/ and packages/squad-sdk/templates/skills/.
* Grows MANIFEST_SKILL_NAMES from 10 → 14 entries: adds tiered-memory,
  iterative-retrieval, reflect, cross-squad.
* Replaces the silent skip in sdk-init.ts with a thrown error that names the
  missing skill(s) and points at sync-skill-templates.mjs. This is what would
  have surfaced #1289 at build time instead of in user installs.
* Rewrites tiered-memory/SKILL.md to be honest about status:
  - frontmatter: confidence: design + source: design proposal
  - prominent Status callout linking to #1264 for the runtime gap
  - removed fabricated measurement table
  - removed reference to non-existent docs/tiered-memory-guide.md
  - References section points only to real issues (#1264, #686, #600)
* Adds a regression test in test/init.test.ts that asserts every
  manifest-curated skill ends up installed at .copilot/skills/{name}/SKILL.md.

Verified:
* npm run lint — passes (after build)
* test/init.test.ts — 26/26 pass including new regression test
* Targeted suites (test/init, test/cli/init, test/sdk) — 292/292 pass

Out of scope (tracked separately):
* tiered-memory runtime backing (.squad/memory/hot|cold|wiki/ scaffolding,
  Scribe promotion, tier-aware spawn template) — follow-up in #1264
* cross-squad-communication plugin port from tamirdresher/squad-skills —
  separate PR

Closes #1289
Refs #1264

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: precheck drift, end-user remediation, TEMPLATE_MANIFEST sync, frontmatter, single-source test

Five reviewer follow-ups on #1292 (closes #1289, refs #1264):

1. (1292-a) Drift guard ran the copy loop FIRST and threw at the
   end if any source dir was missing — leaving a partial skills
   install on disk. Refactored to a pre-check pass that walks
   MANIFEST_SKILL_NAMES once for existence, throws if any source
   is missing, then runs the copy loop only if everything is
   present. Result: no partial state when a packaging bug ships.

2. (1292-b) Remediation text told the user to 'run
   scripts/sync-skill-templates.mjs from the squad repo root',
   which doesn't exist in an installed @bradygaster/squad-sdk
   tarball. Rewrote the message to target end users (try
   squad upgrade, report a bug if it persists) and kept the
   contributor hint as a parenthetical aside.

3. (1292-c) MANIFEST_SKILL_NAMES grew to 14 entries (squad-commands,
   squad-version-check, tiered-memory, iterative-retrieval, reflect,
   cross-squad added across PRs), but TEMPLATE_MANIFEST in
   packages/squad-cli/src/cli/core/templates.ts had only 10 — so
   squad upgrade would skip the new ones. Added matching entries
   for tiered-memory/iterative-retrieval/reflect/cross-squad (the 4
   not already covered by other PRs).

4. (1292-d) packages/squad-cli/templates/skills/squad-version-check/
   SKILL.md (and the 2 mirrors) shipped without ANY YAML
   frontmatter — just a freeform '**Confidence:**' Markdown line.
   isSkillContent() in consult.ts requires '---\\nname:...\\nconfidence:'
   front-matter to classify the file as a skill, so squad-version-
   check was misclassified in share / promote / merge flows. Added
   proper frontmatter (name, description, allowedTools, confidence,
   domain, source) to all 3 mirrors.

5. (1292-e) The regression test duplicated the MANIFEST_SKILL_NAMES
   list literal — adding a new skill would have required two edits
   to stay green. Exported MANIFEST_SKILL_NAMES from sdk/config and
   updated the test to import + iterate the same array the install
   loop reads. Future skill additions only need one edit.

Verified: 26/26 init tests 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>
bradygaster added a commit that referenced this pull request Jun 22, 2026
)

* 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.…
bradygaster added a commit that referenced this pull request Jun 30, 2026
* 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…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add squad registry add/list/remove for discovery-only peer squads (no inheritance)

3 participants