Skip to content

fix(coordinator): route "spawn a squad" / "another squad" prompts through the cross-squad skill#1307

Merged
tamirdresher merged 2 commits into
bradygaster:devfrom
tamirdresher:squad/fix-squad-spawning-routing
Jun 13, 2026
Merged

fix(coordinator): route "spawn a squad" / "another squad" prompts through the cross-squad skill#1307
tamirdresher merged 2 commits into
bradygaster:devfrom
tamirdresher:squad/fix-squad-spawning-routing

Conversation

@tamirdresher

Copy link
Copy Markdown
Collaborator

Symptom

A coordinator initialised by squad init saw prompts like ""spawn two squads of designers and devs"" and fanned out raw task agents inside its own context, treating ""squad"" as generic English for ""team / group"". It never invoked the bundled cross-squad or cross-squad-communication skills, so the peer-squad delegation protocol (registry / manifest / sync CLI / git-async / GitHub-issue patterns) was bypassed entirely.

Two structural holes in squad.agent.md allowed this:

  1. The Routing table had no row that mapped ""spawn a squad"" phrasing to the Squad-PRODUCT concept (only ""upgrade squad"" / ""squad commands"" rows covered Squad-as-a-product vocabulary).
  2. The Skill-aware-routing block was process discipline (""check skill directories by domain relevance"") with no hard ""if the user's word matches a skill name, MUST load the skill"" trigger.

Fix

Two surgical edits to the canonical .squad-templates/squad.agent.md (synced to all 4 mirror copies via scripts/sync-templates.mjs --sync):

  1. New routing-table row — matches ""spawn a squad"", ""another squad"", ""two squads"", ""second squad"", ""fan out to squads"", ""delegate to a squad"", or any phrasing that treats ""squad"" as a unit to spawn or address. Action: invoke the skill tool on cross-squad AND cross-squad-communication BEFORE any task spawn, then delegate via Pattern 0/1/2/3 — never fan out raw task agents in the coordinator's own context.

  2. New ""Hard trigger — keyword-to-skill match"" paragraph at the top of the Skill-aware-routing block — if any word in the request matches an installed skill name (e.g., ""squad"" → cross-squad, ""reflect"" → reflect, ""ceremony"" → matching ceremony skill, ""fact-check"" → fact-checking, ""release"" → release-process), the coordinator MUST invoke the skill tool to fully load that skill BEFORE designing its approach. Includes a one-line ""failure mode this rule closes"" pointer so the guard survives future paraphrasing.

  3. Companion cross-squad/SKILL.md opener strengthened — added a one-line ""Read this FIRST any time the user says 'squad' as a thing to spawn / delegate to / address"" callout above the existing ## Context paragraph, so even a coordinator that skips the routing-table row still hits the trigger when it does eventually load the skill.

Regression test

test/template-sync.test.ts now asserts, for every mirrored copy of squad.agent.md (5 locations — canonical .squad-templates/ + 3 template mirrors + .github/agents/), that:

  • The routing-table row exists and contains all three trigger phrases (""spawn a squad"", ""another squad"", ""two squads"").
  • The row's action cell references the cross-squad skill AND the skill tool.
  • The ""Hard trigger"" + ""keyword-to-skill match"" markers are both present in the Skill-aware-routing block.
  • The hard-trigger paragraph names the worked example ""squad"" → cross-squad so future edits cannot drop the concrete mapping.

Verified: 223/223 template-sync tests pass.

Composability

Disjoint from all other open PRs in the v0.10 stabilisation set (#1292, #1293, #1295, #1298, #1300, #1301, #1302, #1303, #1304, #1306). Only modifies .squad-templates/squad.agent.md + its 4 mirrors + cross-squad/SKILL.md + the template-sync test.

Rollout for existing installs

Either:

  • squad upgrade once this lands (pulls the new template into .squad/squad.agent.md automatically), or
  • Hand-patch .squad/squad.agent.md against the diff and restart the Copilot CLI session.

In both cases the user must restart the Copilot CLI session for the new routing to take effect — squad.agent.md is read once at session start.

…ough the cross-squad skill

A coordinator initialised by `squad init` saw prompts like "spawn two
squads of designers and devs" and fanned out raw `task` agents inside
its own context, treating "squad" as generic English for "team / group".
It never invoked the bundled `cross-squad` or `cross-squad-communication`
skills, so the peer-squad delegation protocol (registry / manifest / sync
CLI / git-async / GH-issue patterns) was bypassed entirely.

Two structural holes in squad.agent.md allowed this:

  1. The Routing table had no row mapping "spawn a squad" phrasing to the
     Squad-PRODUCT concept (only "upgrade squad" / "squad commands" rows
     covered Squad-as-a-product vocabulary).
  2. The Skill-aware-routing block was process discipline ("check skill
     directories by domain relevance") with no hard "if the user's word
     matches a skill name, MUST load the skill" trigger.

This fix:

  - Adds a new routing-table row for the squad-spawning vocabulary
    ("spawn a squad", "another squad", "two squads", "second squad",
    "fan out to squads", "delegate to a squad"). Action: invoke the
    skill tool on cross-squad AND cross-squad-communication BEFORE any
    task spawn, then delegate via Pattern 0/1/2/3.

  - Adds a "Hard trigger — keyword-to-skill match" paragraph at the top
    of the Skill-aware-routing block. If any word in the user's request
    matches an installed skill name (squad → cross-squad, reflect →
    reflect, ceremony → matching ceremony skill, fact-check →
    fact-checking, release → release-process), the coordinator MUST
    invoke the skill tool to fully load that skill before designing its
    approach. Includes a "failure mode this rule closes" pointer so the
    guard survives future paraphrasing.

  - Strengthens cross-squad/SKILL.md with a Read-this-FIRST callout
    above the existing Context paragraph, so even a coordinator that
    skips the routing-table row still hits the trigger when it does
    eventually load the skill.

  - Adds a regression test (template-sync.test.ts) that asserts the row
    + the hard-trigger paragraph + the worked example are present in
    every mirrored copy of squad.agent.md (5 locations).

All 4 mirrors re-synced via `scripts/sync-templates.mjs --sync`.
Verified: 223/223 template-sync tests pass.

Composability: disjoint from bradygaster#1292/bradygaster#1293/bradygaster#1295/bradygaster#1298/bradygaster#1300/bradygaster#1301/bradygaster#1302/
bradygaster#1303/bradygaster#1304/bradygaster#1306 — only touches squad.agent.md mirrors + cross-squad/
SKILL.md + the template-sync test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 13, 2026 13:16
@github-actions

github-actions Bot commented Jun 13, 2026

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

github-actions Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

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

PR Scope: 🔧 Infrastructure

⚠️ 3 item(s) to address before review

Status Check Details
Single commit 2 commits — consider squashing before review
Not in draft Ready for review
Branch up to date Up to date with dev
Copilot review No Copilot review yet — it may still be processing
Changeset present Changeset file found
Scope clean ⚠️ PR includes 1 .squad/ file(s) — ensure these are intentional
No merge conflicts No merge conflicts
Copilot threads resolved 0 active Copilot thread(s) resolved (4 outdated skipped)
CI passing 7 check(s) still running

Files Changed (10 files, +342 −3)

File +/−
.changeset/fix-squad-spawning-routing.md +40 −0
.github/agents/squad.agent.md +4 −0
.squad-templates/squad.agent.md +4 −0
.squad/skills/cross-squad/SKILL.md +47 −1
packages/squad-cli/templates/skills/cross-squad/SKILL.md +47 −1
packages/squad-cli/templates/squad.agent.md.template +4 −0
packages/squad-sdk/templates/skills/cross-squad/SKILL.md +47 −1
packages/squad-sdk/templates/squad.agent.md.template +4 −0
templates/squad.agent.md.template +4 −0
test/template-sync.test.ts +141 −0

Total: +342 −3


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

@github-actions

github-actions Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

🟠 Impact Analysis — PR #1307

Risk tier: 🟠 HIGH

📊 Summary

Metric Count
Files changed 10
Files added 1
Files modified 9
Files deleted 0
Modules touched 7

🎯 Risk Factors

  • 10 files changed (6-20 → MEDIUM)
  • 7 modules touched (5-8 → HIGH)

📦 Modules Affected

ci-workflows (1 file)
  • .github/agents/squad.agent.md
root (2 files)
  • .changeset/fix-squad-spawning-routing.md
  • templates/squad.agent.md.template
squad-cli (2 files)
  • packages/squad-cli/templates/skills/cross-squad/SKILL.md
  • packages/squad-cli/templates/squad.agent.md.template
squad-sdk (2 files)
  • packages/squad-sdk/templates/skills/cross-squad/SKILL.md
  • packages/squad-sdk/templates/squad.agent.md.template
squad-state (1 file)
  • .squad/skills/cross-squad/SKILL.md
templates (1 file)
  • .squad-templates/squad.agent.md
tests (1 file)
  • test/template-sync.test.ts

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

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

Updates the Coordinator’s routing guidance so prompts like “spawn a squad / another squad / two squads” are treated as Squad-as-a-product / peer delegation (via cross-squad workflows) rather than generic “team” phrasing.

Changes:

  • Added a routing-table row for squad-spawning phrasing and a new “Hard trigger — keyword-to-skill match” rule in squad.agent.md (synced across all mirrored copies).
  • Strengthened the cross-squad skill’s opener to explicitly disambiguate “squad” as a peer instance and discourage fanning out raw task agents.
  • Added template-sync regression tests and a changeset for the behavior change.

Reviewed changes

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

Show a summary per file
File Description
test/template-sync.test.ts Adds regression assertions ensuring the new routing row + hard-trigger paragraph exist across all squad.agent.md mirrors.
.squad-templates/squad.agent.md Canonical template update: adds “spawn a squad” routing row + keyword-to-skill hard trigger.
templates/squad.agent.md.template Mirror of canonical squad.agent.md template changes for distribution.
packages/squad-cli/templates/squad.agent.md.template CLI template mirror of the new routing row + hard trigger.
packages/squad-sdk/templates/squad.agent.md.template SDK template mirror of the new routing row + hard trigger.
.github/agents/squad.agent.md Repo’s agent copy updated to match the canonical routing/trigger guidance.
.squad/skills/cross-squad/SKILL.md Adds a prominent “Read this FIRST…” callout clarifying peer-squad semantics.
packages/squad-cli/templates/skills/cross-squad/SKILL.md Mirrors the new cross-squad callout into CLI skill templates.
packages/squad-sdk/templates/skills/cross-squad/SKILL.md Mirrors the new cross-squad callout into SDK skill templates.
.changeset/fix-squad-spawning-routing.md Declares patch bumps and documents the coordinator routing fix.

Comment thread .squad-templates/squad.agent.md Outdated
| Ralph commands ("Ralph, go", "keep working", "Ralph, status", "Ralph, idle") | Follow Ralph — Work Monitor (see that section) |
| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad-commands/SKILL.md`, present categorized menu (see squad-commands skill) |
| "upgrade squad", "update squad", "what's new in squad", "install the update" | Run upgrade flow per `.squad/templates/session-init-reference.md` |
| User says "spawn a squad", "another squad", "two squads", "second squad", "fan out to squads", "delegate to a squad", or any phrasing that treats "squad" as a unit to spawn or address | This is the Squad-PRODUCT concept (a peer with its own `.squad/`), NOT generic English "team" or "group". **Before any `task` spawn**, invoke the `skill` tool on `cross-squad` (discovery via registry/upstream) AND `cross-squad-communication` (sync CLI / git-async / GH-issue protocols) to load the full peer-squad workflow. Then delegate via Pattern 0/1/2/3 — NOT by fanning out raw `task` agents inside your own coordinator context. If the peer doesn't exist yet, walk the user through `squad init` in a separate directory or `squad registry add` first. |
<!-- Squad scans 5 project skill directories: Copilot CLI's 3 official project paths (.github/skills/, .claude/skills/, .agents/skills/) per https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-skills — plus Squad's 2 conventions .squad/skills/ and .copilot/skills/. Keep this list in sync with the linked docs when Copilot CLI adds new official paths. -->
**Skill-aware routing:** Before spawning, check ALL project skill directories in precedence order for skills relevant to the task domain:

**Hard trigger — keyword-to-skill match (do this FIRST, before any spawn or task call):** If any word in the user's request matches the name of an installed skill (e.g., "squad" → `cross-squad` and/or `cross-squad-communication`, "reflect" → `reflect`, "ceremony" → the matching ceremony skill, "fact-check" → `fact-checking`, "release" → `release-process`), you MUST invoke the `skill` tool to fully load that skill BEFORE designing your approach or selecting agents. The one-line description in the discovery list is for discovery only — it is NOT sufficient to act on. Read the full SKILL.md, then route. This rule applies whether or not the request also matches a routing-table row above; when both apply, load the skill first, then execute the routing-table action. Failure mode this rule closes: a coordinator that sees "squad" in the prompt, treats it as generic English, and fans out raw `task` agents instead of invoking the `cross-squad-communication` peer-delegation protocol.

## Context

> **Read this FIRST any time the user says "squad" as a thing to spawn, delegate to, address, or fan out to** — e.g., *"spawn two squads of designers and devs"*, *"ask the other squad"*, *"delegate to a squad"*. In Squad-PRODUCT vocabulary, "squad" is a **peer** (an independent installation with its own `.squad/`, `team.md`, MCP server, and agents) — NOT a generic English synonym for "team" or "group". Do not fan out raw `task` agents inside your own coordinator context when the user means "another squad". Use the discovery and communication patterns below (and the companion `cross-squad-communication` skill for the actual protocols).
Comment on lines +246 to +248
// ---------------------------------------------------------------------------
// 5. Squad-spawning routing guard (regression for the "spawn a squad" hole)
// ---------------------------------------------------------------------------
tamirdresher added a commit to tamirdresher/squad that referenced this pull request Jun 13, 2026
… ambiguity + anti-patterns

Real-world failure (2026-06-13): even AFTER the routing-table row and
hard-trigger paragraph from b5d05fb landed, a peer-squad coordinator
*still* did ad-hoc `task` fan-out for "spawn two squads of engineers
and QAs". Self-diagnosis surfaced four contributing failure modes:

  1. Prior-session anchoring (saw earlier `reviews/squad-alpha/` folders
     and matched the pattern without re-evaluating user intent).
  2. Ambiguous wording, lazy interpretation (silently picked the
     cheaper option instead of asking).
  3. Coordinator doctrine biases toward `task` fan-out (the existing
     Eager Execution / Parallel Fan-Out section pulled the coordinator
     back even after it had loaded `cross-squad`).
  4. Cost/overhead instinct ("two real squads for a 30-line app feels
     disproportionate" — judged silently instead of surfacing the
     trade-off).

The original PR bradygaster#1307 fix closed modes 1 and 3 mechanically (forces
the skill to load) but left modes 2 and 4 open (didn't dictate what
to DO with that knowledge). This commit closes them:

A. squad.agent.md routing row — added two explicit clauses:
   - "**Default = literal Squad install.** Calling `task` sub-agents
     'squad-alpha' / 'squad-beta' does NOT make them squads — that is
     the explicit anti-pattern."
   - "**If the request is ambiguous** ... you MUST `ask_user` with a
     2-choice prompt — and never silently pick the cheaper option."
   No escape hatch. The coordinator can no longer rationalise the
   downgrade as a judgment call.

B. cross-squad/SKILL.md — added a full `## Disambiguation: 'squad' vs
   ad-hoc agents` section with:
   - Default-behaviour table mapping common phrasings to expected
     coordinator actions (real squads vs ad-hoc agents vs ambiguous).
   - ask_user 2-choice protocol verbatim (heavier/persistent vs
     lighter/ephemeral) so the coordinator has the exact prompt shape.
   - Four named anti-patterns drawn directly from the observed failure:
     * Naming task agents "squad-alpha" doesn't make them squads
     * Prior-session anchoring (pattern is a hint, not a contract)
     * Silent cheaper-option pick (judgment call belongs to the user)
     * Loading the skill but doing task fan-out anyway (disambiguation
       rule OVERRIDES generic fan-out doctrine when "squad" was the
       trigger)
   - Sharpened `description:` so the squad skill-aware-router has
     better natural-language hooks.
   - `triggers:` frontmatter array (Copilot CLI ignores `triggers:` per
     sdk/index.js decompile, but the squad coordinator's skill-aware
     routing system uses natural-language matching against frontmatter
     + content, so documenting the phrases here helps that matcher fire).

C. Regression tests in test/template-sync.test.ts:
   - Routing row must mention `ask_user` + "anti-pattern" (new × 5
     mirrors = 5 assertions).
   - cross-squad/SKILL.md must have `## Disambiguation` section,
     default-behaviour rule, ask_user requirement, the squad-alpha
     anti-pattern, and triggers: frontmatter (5 new × 3 mirrors = 15
     assertions).
   - 20 new assertions total; 243/243 template-sync tests pass.

cross-squad/SKILL.md mirrored to packages/squad-cli/templates/skills/
and packages/squad-sdk/templates/skills/ (byte-identical). squad.agent.md
re-synced to all 4 mirrors via scripts/sync-templates.mjs.

Composability: still disjoint from all other open PRs. Pure additions
to two files (squad.agent.md row, cross-squad/SKILL.md content) plus
mirrors + tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tamirdresher added a commit to tamirdresher/squad that referenced this pull request Jun 13, 2026
tamirdresher added a commit to tamirdresher/squad that referenced this pull request Jun 13, 2026

@bradygaster bradygaster left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

✅ Flight approves. Cross-squad routing now hard-triggers the correct skills, ambiguity is surfaced instead of silently downgraded, mirrors are synced, and regression coverage is in place.

@tamirdresher tamirdresher merged commit b79e64a into bradygaster:dev Jun 13, 2026
14 checks passed
tamirdresher added a commit to tamirdresher/squad that referenced this pull request Jun 14, 2026
…te skills (bradygaster#1308 phase 1)

squad.agent.md is loaded as the agent prompt at every Copilot session
start. v0.10.0-insider.1 ships it at 81 KB / 1137 lines and the v0.10
stabilisation pass alone added +10.6 KB / +114 lines. Every byte is
paid at every session.

Phase 1 fix: extract three low-cross-reference, high-byte sections to
satellite skills the coordinator loads on demand via the skill tool —
same pattern that worked for cross-squad-communication (bradygaster#1295).

  - coordinator-init-mode        — Init Mode Phase 1 + Phase 2 (5.4 KB)
  - coordinator-source-of-truth  — Source of Truth Hierarchy   (4.4 KB)
  - coordinator-response-mode    — Response Mode Selection +
                                    Lightweight Spawn Template  (3.9 KB)

Result: squad.agent.md 81 KB → 70 KB (-13.9 %, -140 lines). 19 skills
installed at .github/skills/ (was 16). Behaviour unchanged — each
removed section is replaced with a stub naming the trigger condition
and instructing the coordinator to skill(coordinator-X) before acting.

Sections that stay in squad.agent.md (intentional):
  - Team Mode + state-backend handshake + HARD RULE — handshake must
    fire before any state write
  - Routing table — hit on every user prompt
  - Hard trigger keyword-to-skill match paragraph (bradygaster#1307) — load-bearing
  - How to Spawn an Agent — referenced from every routing action
  - Coordinator Identity / Personal Squad / Memory Governance Tools —
    frequently re-read inline

Wired changes:
  - New canonical sources at .squad/skills/coordinator-{x}/SKILL.md
    plus 2 template-dir mirrors
  - MANIFEST_SKILL_NAMES grows by 3 entries (16 → 19)
  - TEMPLATE_MANIFEST grows by 3 entries with ../.github/skills/
    destinations (post-bradygaster#1304 install location)
  - .squad-templates/squad.agent.md replaces each section with a stub
  - 4 mirrored squad.agent.md copies re-synced via
    scripts/sync-templates.mjs --sync

Tests: 287/287 pass. The existing 'should install every
manifest-curated skill (regression: bradygaster#1289, bradygaster#1264)'
already iterates MANIFEST_SKILL_NAMES, so it automatically asserts the
3 new skills install.

Smoke test: fresh squad init produces 19 skills at .github/skills/
and squad.agent.md is 70 KB.

Follow-ups (separate PRs) for the still-large sections:
  - Routing (9.2 KB) — extract action-cell verbiage, keep trigger table
  - Team Mode (5.5 KB) — extract worktree-awareness sub-sections
  - How to Spawn (3.2 KB) — extract role-emoji catalog

Target after 2-3 follow-ups: ~45 KB coordinator file.

Closes bradygaster#1308 (phase 1).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

3 participants