Running the Squad
The Squad Coordinator routes your request to a cast of HVE Core agents, runs eligible roles
in parallel, and persists roster, routing, decisions, and history under
.copilot-tracking/squad/.
Invoke the coordinator#
Use the matching Squad agent's conversation for requests, not your system shell. In VS Code Copilot Harness, choose the agent from the agents dropdown; CLI and App also use the corresponding agent. See Getting Started for installation and your first conversation.
/squad request="add input validation to the login form"
Using VS Code Copilot Harness? Select Squad Coordinator from the
agents dropdown and send the request text shown in the selected VS Code tab without the
/squad prefix. Each host tab names the matching agent for federation, document,
governance-report, and learning workflows.
Optional inputs#
-
profile=default|full|security|design|accessibility|architecture|azure|modernization|compliance|operations|product— seeds which cast is created on first run. If omitted on a fresh project, the coordinator inspects your repo and proposes a recommended profile before creating anything. -
pack=power-platform,pack=m365-copilot, orpack=aws— adds a technology vertical's specialist roles on top of the profile. A pack never replaces the profile, and you can apply more than one (comma-separated). See Packs below. -
tier=fast|default— a per-turn model-tier hint that overrides the coordinator's cost-first defaults. -
routing=off|ranked|economy|manual— how each role's model is chosen, saved inteam.mduntil you change it.off(default) applies no policy;rankedpicks the model that best fits each role's work among the models your host offers;economyPre-release only v0.19.0-pre isrankedwith cheaper picks for five implementation roles, after your consent;manualasks you to pick, with suggestions pre-filled. See Model selection per role below. -
discovery=quick|standard|deep|skip— runs the discovery gate at that depth without being asked, or skips it. See Discovery gate below. -
owner=<Member Name>— picks a specific named member when two rows inteam.mdshare the sameRole(for exampleowner=Betawhen the roster has twodeveloperrows). -
mode=autonomous|autopilot— the autonomy mode for this turn. Omit it to run interactively, approving each step. -
cost-ceiling=<positive USD>|unset— sets, replaces, or explicitly removes the current run's estimated model-spend ceiling. Omission inherits an active ceiling only within the same run. See Cost admission control below.
/squad request="threat-model the auth service" profile=security
/squad request="design the approvals app" profile=architecture pack=power-platform
/squad request="summarize the data layer" tier=fast
/squad request="reduce onboarding drop-off" discovery=standard
/squad request="build the booking service end to end" mode=autopilot cost-ceiling=20
/squad request="run security research and implement" routing=manual/squad entry point.
Autonomy modes#
How much the squad does before it asks you:
| Mode | How to run it | Who approves what |
|---|---|---|
| Interactive (default) | no mode flag |
You approve each step (research, plan, implement, review). A ping fires at every step gate. |
mode=autonomous |
mode=autonomous |
A narrow validator loop: the council re-validates one implementer output (max 2 cycles), then returns. |
mode=autopilot |
mode=autopilot |
The squad runs research → plan → implement → review on its own and asks you only for impactful actions (deploy, git push, merge, schema/data changes) and to validate the final outcome. |
Autopilot is the "tell it once, let it run" mode: it sequences the whole pipeline autonomously but always stops for a human before anything irreversible and before release. The two impactful/final stop-points fire a notification through the approval channel you choose at build time (interactive mode pings you at every step instead).
Autopilot hand-off pipelining#
Under mode=autopilot, the coordinator dispatches stage N's Scribe hand-off and
stage N+1's role together, as two calls in one parallel tool-call block, whenever no barrier
applies and three conditions hold: stage N's own artifact is confirmed on
disk, the host's subagent-dispatch tool can be called more than once in one parallel tool-call
block (VS Code's runSubagent, or Copilot CLI's task tool with or without
mode: background), and pipelining has not been disabled by a prior verification
failure in this run. Handing off to the Scribe alone and waiting is a defect in that case.
A cost-ceiling does not turn pipelining off. The Cost Preflight round that admits
stage N+1 runs between the two parallel blocks and counts stage N's not-yet-recorded spend as a
pending reservation, so the ceiling never under-counts spend while a hand-off is in flight.
An inner run under untargeted federation autopilot pipelines at its own sub-squad root too.
Pipelining remains off in the following cases:
- Watch Mode
- The squad is a federation root (marked by presence of
federation.md) - The active Cost Preflight round is
approved-over-ceiling, whose dispatch units stay sequential - The host has no subagent-dispatch tool that accepts more than one call per block
- After a pipelined hand-off (one that ran beside a role) has failed verification in this run; a failed hand-off that ran alone is corrected without turning pipelining off
When pipelining is off, the coordinator dispatches stage N's Scribe hand-off, waits for it to complete and be verified, and only then dispatches stage N+1 — exactly as in prior versions. When pipelining is active, stage N+1 starts while stage N's hand-off is in flight, but stage N+2 does not start until stage N's hand-off has returned and passed verification.
Verification and safety gates#
A bare Measure-SquadLedger.ps1 -Check is not sufficient for pipelined verification.
Instead, the coordinator takes a pre-dispatch snapshot of the target history file's heading count,
then verifies using -ExpectedHistoryCounts with that snapshot plus the entries this
hand-off is expected to add. The coordinator also uses -BaselinePath to preserve a
content-level baseline (Length, SHA-256, heading count) of every deliverable written so far this run,
allowing detection of corrupted or modified prefixes in subsequent writes.
When a pipelined hand-off fails verification, pipelining is disabled for the rest of the run. The bad write is never rewritten by the Scribe; instead, a new append-only correction entry is dispatched, and the affected deliverable is restored by re-dispatching its owning role (not by editing history). The run does not cross the next barrier until a human approves the fix.
.copilot-tracking/squad/ and its contents are git-ignored, so ledger state is local
evidence, not part of reviewed history. The delivered code, plans, and review records in
plans/, research/, reviews/ and project files are tracked normally.
Benchmark harness#
An opt-in paired benchmark harness exists at tests/tier1/benchmark/Invoke-PipeliningBenchmark.ps1
(requires COPILOT_GITHUB_TOKEN). The live benchmark has not yet produced a baseline result,
so pipelining behavior is described here and in the squad source references; no performance claim is made.
Cost admission control#
cost-ceiling is an optional ceiling on estimated model spend for one
run. Initialization is outside the ceiling: the confirmed setup Scribe dispatch
creates the roster, state, and pricing files and records that setup spend without consuming
a ceiling slot. After initialization, before the first work dispatch and every later round,
Cost Preflight builds a demand manifest from planned roles, dispatch classes, fixed model
rates, orchestration, maximum conditional cycles, and eligible calibration.
It does not quote billed cost, cap GitHub's invoice, or govern the Azure resources your
implementation may create.
remaining USD = max(0, ceiling USD - accumulated estimated spend)
projected cost USD = sum(calibrated planned-dispatch estimates)
admission cost USD = projected cost USD × 3.0
The factor-of-three admission reserve is a conservative policy allowance for uncertain future
token use, not a statistical confidence interval. Displayed totals are rounded only after the
row estimates are summed. A forecast reaches medium confidence only when demand is
bounded, models and rates are known, the rate table is valid, and calibration matches the
current estimator revision. Otherwise the squad reports cannot-confirm rather than
presenting an optimistic answer.
Set, inherit, replace, or remove a ceiling#
| Input | Effective behavior |
|---|---|
cost-ceiling=20 |
Set or replace the active run's ceiling with $20. |
| Argument omitted, same run | Inherit the active positive ceiling. Omission never silently removes a guard. |
cost-ceiling=unset |
Explicitly remove the ceiling while preserving accumulated consumption totals. |
| Argument omitted, new run | Start as not-requested; no cost-ceiling comparison or stop applies. |
Inheritance is bound to the recorded run ID. A later request that continues that run keeps its ceiling; a new autopilot topic, Watch event, or federation meta-run gets a new ID and does not inherit one. Estimated consumption is still recorded when no ceiling is active, and all non-cost gates continue to apply.
# Set a $20 ceiling for this run
/squad request="implement the approved plan" mode=autopilot cost-ceiling=20
# Same run: $20 remains active because omission means inherit
/squad request="apply the review fixes"
# Same run: remove the guard explicitly
/squad request="continue without a cost ceiling" cost-ceiling=unsetWhat each decision means#
| Decision | Meaning | Can work dispatch? |
|---|---|---|
not-requested |
No effective ceiling exists for this run. | Yes, subject to the normal non-cost gates. |
within-ceiling |
The conservative admission cost fits the remaining amount. | Yes, but only the slots named by that round. |
over-ceiling |
The known forecast exceeds the remaining amount, or accumulated spend has reached the boundary. | No. Before the boundary, the user may choose bounded proceed. |
approved-over-ceiling |
The user accepted a known overage for the unchanged demand and pricing inputs. | Yes, one sequential dispatch unit at a time while spend remains below the ceiling. |
cannot-confirm |
Demand, model pricing, rate-table shape, or calibration cannot support a defensible forecast. | No. Change the uncertain inputs; approval cannot waive missing evidence. |
Proceeding after an over-ceiling forecast#
Before asking, the squad shows the ceiling, accumulated estimated spend, remaining amount,
projected remaining-demand cost, conservative admission cost, and the stop limitation. If you
proceed, it preserves the original over-ceiling record and appends an auditable
approved-over-ceiling round linked to your approval. Approval applies only to the
unchanged manifest and pricing basis; expanded, repriced, or low-confidence demand opens a new
gate.
The ceiling is checked between dispatch units. A model call already in
progress cannot be interrupted. The final child and its mandatory Scribe accounting handoff
can therefore take the recorded estimate above the ceiling. The coordinator then records a
terminal over-ceiling round and starts no later child.
Reaching the boundary does not block the project forever. To resume, set a new positive ceiling
above current accumulated spend, explicitly remove the ceiling with
cost-ceiling=unset, reduce or reprice the remaining demand and run a new preflight,
or begin a new run. Re-approving the already exceeded value is deliberately not an option,
because it would no longer define a stopping boundary.
Examples with accumulated spend#
| Current state | Next request | Result |
|---|---|---|
| No prior ceiling; estimated spend is $10.80 | cost-ceiling=10 on the same run |
Remaining is $0.00 and the new request does not dispatch until the ceiling changes or is removed. |
| Ceiling is $20; estimated spend is $10.80 | Ceiling argument omitted on the same run | The $20 ceiling is inherited; $9.20 remains before considering the new demand. |
| Ceiling is $20; estimated spend is $10.80 | cost-ceiling=unset |
The guard is removed; $10.80 remains recorded and later work is not cost-gated. |
| A new run starts | Ceiling argument omitted | The new run records not-requested and proceeds without a cost ceiling. |
Where to inspect the decision#
The latest compact decision is in state.json under
currentRun.costPreflight. The reproducible record is the matching
## Cost Preflight entry in decisions.md, including its demand table,
evaluated and permitted slot sets, reason, and Decision Ref. Every admitted history entry
carries that Decision Ref and consumes one permitted slot exactly once. The accumulated
estimated totals remain in consumption.md; model rates, dispatch-size assumptions,
and calibration are in consumption-rates.md.
Federation scope#
Ordinary federation routing applies the supplied ceiling independently to every selected
sub-squad, whether you name one with squad= or let meta-routing select one or
several. Each selected sub-squad uses its own state, accumulated estimate, lifecycle, and
stop boundary exactly like a plain squad. The federation root records routing and summary
totals but keeps its aggregate Cost Preflight as not-requested.
Only federation-wide mode=autopilot without a squad= target applies
one aggregate ceiling across all selected inner runs plus federation coordinator and
root-writer orchestration. It uses the federation root's
consumption-rates.md, does not also pass the ceiling into child runs, and counts
completed meta slots across every round. An approved aggregate overage runs one sub-squad
and root-writer unit at a time so the federation can stop at the shared boundary.
Discovery gate — when there is nothing written down yet#
Two gates run ahead of the work, and they fire on opposite triggers. The discovery gate fires when there is no input artifact and produces one; the intake gate fires when there is one and validates it. The brief a discovery session writes is itself an input artifact, so it flows straight into the intake gate.
no input artifact → discovery gate → brief → intake gate → research → plan → implement → review
input artifact → intake gate → research → plan → implement → reviewValidation can be automatic. Ideation cannot. The intake gate fires on its own because assessing an artifact is something an agent can do alone. Discovery is offered rather than automatic, because the value of a brainstorm is your ideas and context. An automatic discovery gate would be AI brainstorming with itself and handing you a confident brief nobody agreed to.
When you are offered it#
The coordinator offers the gate only when all four hold:
- The roster is
productorfull— those are the only profiles that seedanalyst, which writes the brief. - No PRD, BRD, spec, story, design doc, transcript, or file you pointed at grounds the turn.
- The turn advances toward a plan, a build, or a deliverable — not a question or a lookup.
- The request states a goal (reduce onboarding drop-off) rather than a settled task (add a retry to the webhook client).
In every other profile the gate is silent — no offer, normal routing. That is the deliberate difference from the intake gate, which escalates when its role is missing: inputs that exist should not go unvalidated, but a brainstorm nobody asked for is not a check being skipped. You are asked once per topic; declining is recorded and never re-offered.
Passing discovery= always works, on any profile and even after you declined. It is
a command rather than an offer, so a non-product squad will name the roles it must
add and ask once before running.
Depth tiers#
| Depth | Roles dispatched, in order | Produces | Use when |
|---|---|---|---|
quick (default) |
analyst | brief | The goal is clear; only scope, users, and the success measure need settling. |
standard |
designer → analyst | framing, solution themes, brief | The problem itself is open and several directions are worth exploring first. |
deep |
designer → challenger + experimenter → analyst | framing, themes, objections, riskiest assumption, brief | The direction is expensive or hard to reverse and deserves a pressure-test and a cheap test. |
skip |
none | a Depth: skip verdict recording the declination |
You do not want a session, or the framing is already settled elsewhere. |
deep needs challenger, which only full seeds. Choosing it
in a product squad prompts the coordinator to add the role or run
standard instead — it never silently drops a role from a tier you chose.
What you get#
The dispatched roles interview you, one question at a time, and stop rather
than guess when they cannot reach you. Only the analyst writes a file: a short brief at
<date>-<topic-id>-brief.md in the analyst's deliverable root, carrying
the problem, why now, scope boundaries, the success measure, the options considered, the chosen
direction, assumptions, and open questions. A ## Discovery Verdict lands in
decisions.md alongside it.
The discarded options are the part worth protecting. A brainstorm's durable value is not the idea that won — that survives on its own — but the record of what was rejected and why, which is what stops the squad relitigating the same directions three turns later.
The gate never runs on an unattended path. There is nobody there to answer the offer, so the triggering payload becomes the input artifact and the intake gate assesses that instead.
Requirements intake gate#
When a run is grounded in requirement or input artifacts — a PRD, BRD, spec, user
story, design doc, transcript, or a file you point the squad at — the coordinator runs
an intake gate before it plans or builds, checking those inputs for
completeness, clarity, testability, consistency, and scope. It records an
## Intake Readiness Verdict in decisions.md
(Ready, Ready-With-Gaps, or Not-Ready).
On Not-Ready the squad does not build on shaky inputs: it dispatches the analyst
or product-owner to fill the blocking gaps and re-validates (capped at two cycles), and
escalates to you when a gap needs a human decision. When no input artifact grounds the run,
the gate is a silent no-op. It ships with the product and full
profiles; other profiles are offered the role when a run turns out to be requirements-driven.
When the input is a brief the discovery gate just produced, the validator is resolved to a different agent than the one that wrote it — the PRD Quality Reviewer checking a PRD Builder brief, for instance. A gate that validates its own output is a formality, not a check.
Approving remotely (unattended / VM runs)#
If you run the squad on a VM for a long job, pick the github-issue approval
channel at build time. At each gate the squad opens a GitHub issue, assigns and @mentions you
(so you get a GitHub mobile push), and waits. You approve from your phone with a comment —
/approve, /approve-all, /changes: <note>, or
/stop — or a squad/* label, without touching the VM. Only your
registered handle (or a repo collaborator) can approve, and only those keywords act.
The other channels are webhook (an outbound Teams/Slack/Discord ping only) and
in-chat (the default, which needs you at the PC). No channel requires the package
to ship an email or chat transport — when a channel's tooling is absent it degrades to an
in-chat approval, and the squad never proceeds on a timeout.
Remote approval setup (one-time, only for github-issue)#
Local and in-chat runs need nothing extra. To approve remotely from a VM run, set up the channel once:
-
Authenticate GitHub on the run host. Either run
gh auth login(theghCLI is sufficient on a headless VM) or configure the officialgithubMCP server. The package ships a reference entry in.github/skills/squad/mcp.template.jsonyou can merge into your.vscode/mcp.json; the GitHub MCP is preferred when present, and the squad falls back togh, then to in-chat. The token needsrepo+issuesscope. -
Install the approval watcher. Copy the reference workflow
.github/skills/squad/github-approval-watcher.workflow.ymlto.github/workflows/squad-approval-watcher.ymlin the repo that hosts your approval issues, then commit it. It relays your/approve,/approve-all,/changes:, or/stopreply back so the run resumes — and only an authorized handle's recognized keyword acts (free-form comment text is never executed as a command). -
Pick
github-issueat build time and give the coordinator the GitHub handle to @mention and theowner/repofor approval issues (defaults to the current repo).
Watch Mode — trigger the squad from a new issue#
Watch Mode is the event-driven, "continuous AI" side of the squad: instead of you typing
/squad, a repository event starts the run. The shipped pattern turns a
new issue labeled squad/auto into a headless
mode=autopilot run that opens a draft pull request which closes
the issue. It reuses everything you already configured — the autopilot pipeline, the
council, and the github-issue approval channel — so a gate still pauses for
your approval from a phone.
The diagram could not be rendered. Its source remains available below.
Diagram source
flowchart TD
A["Issue labeled squad/auto"] --> B{"Write collaborator?"}
B -- no --> X["Ignored, comment left on issue"]
B -- yes --> C["Copilot CLI runs Squad Coordinator with mode=autopilot"]
C --> D["Profile inferred from the issue (fallback: default)"]
D --> E["Research, Plan, Implement, Review"]
E --> F{"Impactful or Risk Gate?"}
F -- yes --> G["Approve from phone via github-issue"]
G --> E
F -- no --> H["Open DRAFT pull request that closes the issue"]
H --> I["You review and merge"]
The issue title and body are always treated as data, never instructions: the run reads them as the task description and never as commands that change its roster, routing, gates, or approvals. The run opens a draft PR only — it never merges, force-pushes, or deploys; those stay human-approved gates, backed by your branch protection.
Enable Watch Mode (one-time)#
-
Create a Copilot token. Generate a fine-grained personal access token with
the Copilot Requests permission and add it as the repository secret
COPILOT_GITHUB_TOKEN. The built-in Actions token cannot authenticate Copilot, so this dedicated secret is required. - Protect your default branch. Require a pull request and review before merge, so the squad's draft PR can never merge itself.
-
Allow Actions to open pull requests. In Settings → Actions
→ General → Workflow permissions, enable "Allow GitHub Actions to
create and approve pull requests." Without it, the squad can push its branch but GitHub
blocks the draft PR with a 403 — the run finishes with the branch created but no
PR. The workflow's
pull-requests: writepermission is not sufficient on its own. (This setting also lets Actions approve PRs; your branch protection keeps merges human-gated. For tighter scoping, use a dedicated PAT or GitHub App token for PR creation instead of this toggle.) -
Install the trigger workflow. Copy the reference workflow
.github/skills/squad/squad-watch.workflow.ymlto.github/workflows/squad-watch.yml, review it, and commit it. -
Install the approval watcher (if you have not already) so gate approvals
flow back: copy
.github/skills/squad/github-approval-watcher.workflow.ymlto.github/workflows/squad-approval-watcher.yml. -
Label an issue
squad/autoto start a run. Only a repository collaborator with write access can trigger it; an unauthorized label is ignored and noted on the issue.
Create and apply the squad/auto label#
The trigger is an ordinary GitHub label named exactly squad/auto. Create it once,
then applying it to any issue starts a run — anyone with write access can do both. In the
GitHub UI: Issues → Labels → New label, name it squad/auto,
and save. Or with the gh CLI:
gh label create squad/auto --description "Hand this issue to the squad" --color 1D76DB
gh issue edit 42 --add-label squad/auto
Labeling is the signal: the issues: [labeled] event fires, the workflow checks the
label is squad/auto and the labeler has write access, and the run begins. One run
stays active per issue (a re-label will not start a second, competing run). The
squad/auto trigger label is separate from the squad/* approval labels
(squad/approved, squad/stop, …) the approval watcher reads at a
gate.
Watch Mode is opt-in and in-repo only for now: an unlabeled issue does nothing, and pull
requests from forks never start a privileged run (the workflow never uses
pull_request_target).
Optional: a New Issue template for squad/auto#
Hand-labeling works fine, but a repository can also add a New Issue form that
pre-applies the squad/auto label at creation, so filing a squad task is a single
step. Copy the reference form
.github/skills/squad/squad-task.issue-template.yml to
.github/ISSUE_TEMPLATE/squad-task.yml, review it, and commit it — this adds a
"Squad task" option to the repository's New Issue page with fields for the task, optional
acceptance criteria, and an optional profile hint. This is purely a convenience: it is entirely
optional, and an ordinary issue labeled by hand starts a run exactly the same way.
Other triggers (beyond a new issue)#
A new labeled issue is just the first entry in Watch Mode's event-to-intent map.
The contract (.github/instructions/squad/squad-watch-mode.instructions.md) defines
how any repository event becomes a routed run: the trigger only supplies the event payload as
data, and the coordinator's routing table picks the role. The shipped reference workflow wires
all of them in one file — a single Prepare run step authorizes the
actor, enforces fork-safety, and builds the routed prompt for whichever event fired.
| Trigger | How it fires | What the squad does | Shipped? |
|---|---|---|---|
| New issue | Apply the squad/auto label |
mode=autopilot → draft PR that closes the issue |
Yes |
| Manual dispatch | Actions tab → Run workflow (a request or an issue number) | mode=autopilot or a routed run |
Yes |
| Pull request | Apply a squad/review label to a same-repo PR |
Routes to the tester role → review comments on the PR |
Yes |
| Comment command | Comment /squad <request> on an issue or PR |
Routes per the command → per-role outcome | Yes |
| Scheduled sweep | The cron in the workflow |
A maintenance sweep (dependency/docs/SSSC) → draft PR or issue | Yes |
| Push | A push to the configured branch pattern | A validation council → verdict (opens an issue only on Stop) | Yes |
Every trigger runs through the same guardrails: an opt-in gate (a squad/* label or
an authorized /squad keyword), an authorized actor, the payload treated as data,
human-approved gates for anything impactful, and same-repo only (fork PRs are skipped and
pull_request_target is never used). Two triggers are time/branch based, so tune them
for your repo before enabling — and delete any trigger you do not want:
# In .github/workflows/squad-watch.yml
on:
schedule:
- cron: '0 6 * * 1' # when the maintenance sweep runs — adjust or remove
push:
branches: ['release/**'] # which pushes get a validation council — adjust or remove
The issues, pull_request, issue_comment, and
workflow_dispatch triggers need no tuning — they are gated by labels and the
/squad keyword, so they stay dormant until you opt an item in.
Every run gets its own sub-squad#
Unattended runs are only trustworthy if you can see what they did. So every Watch Mode run
executes inside a federation sub-squad dedicated to its triggering event. Issue
#123 gets members/issue-123/, with its own roster, decisions log, per-agent history,
and consumption ledger. Nothing from one automated run bleeds into another's trail, and months
later you can still open a folder and read exactly which roles ran, what they decided, and why.
You do not have to set the federation up first. Watch Mode bootstraps whatever is missing before the run starts:
| What your repo has | What Watch Mode does |
|---|---|
| Nothing yet | Creates the federation, then the event's sub-squad |
| A plain single squad | Auto-promotes it into a federation (your existing state relocated intact, logs preserved byte-for-byte), then adds the event's sub-squad alongside it |
| Already a federation | Adds the event's sub-squad |
| The event's sub-squad already exists | Reuses it and resumes — a re-labelled issue or a new PR push stays in one trail |
The names are deterministic, so you always know where to look:
issue-123 # an issue, or a /squad comment on it
pr-456 # a PR review, or a /squad comment on the PR
sweep-2026-07-27 # a scheduled maintenance sweep
push-release-2-0-a1b2c3d # a push to release/2.0 at commit a1b2c3d
dispatch-9911223344 # a free-form manual dispatch (workflow run id)
Two safety properties matter here. First, a sub-squad name is a folder path, so it is derived
only from structural event metadata — issue and PR numbers, branch refs,
commit shas, the run id, the date. Never from an issue title or a comment body, which anyone
can write. Second, the bootstrap never writes into a sub-squad it did not create:
if the derived name collides with one of your own, the run comments on the source issue and
stops instead of overwriting it. Watch-created sub-squads are marked Owner=watch-mode
in federation.md and registered with a narrow, ref-keyed route, so your interactive
/squad-federation requests never land in one by accident.
These sub-squads are kept — they are the audit trail, so nothing prunes them automatically. Archiving or removing one is a deliberate thing you ask for.
Finding the details behind a gate#
When the squad pauses at a gate — a Cost Preflight, discovery, intake-readiness, or council verdict, an impactful action, or the final
outcome — the chat message stays deliberately short so it does not bury the conversation.
The full reasoning lives in .copilot-tracking/squad/decisions.md, which is
append-only: a new ## Council Verdict entry is inserted in the
file (often in the middle, next to earlier entries), not always at the end. To save you
hunting for it, every gate message carries a Decision Ref — a deep link
straight to the exact section:
.copilot-tracking/squad/decisions.md#council-verdict-2026-07-07-residual-controls.copilot-tracking/squad/decisions.md#cost-preflight-2026-09-13-run-001-round-002
The anchor is the Markdown heading of the verdict entry (lower-cased, spaces to hyphens), so
opening the link in VS Code or on GitHub Pages jumps you straight to the verdict, its
findings-by-role table, and the conditions — no scrolling required. The gate message and the
notification payload both include this Decision Ref; the State
pointer to state.json and the history file remains as a fallback.
Where each gate records its details:
The diagram could not be rendered. Its source remains available below.
Diagram source
flowchart TD
A["Gate reached (council / impactful / final)"] --> B["Short chat / notification message"]
B --> C["Decision Ref deep link"]
C --> D["decisions.md#council-verdict-DATE-TOPIC — verdict, findings, conditions"]
B -. fallback .-> E["state.json + history — run state and audit trail"]
B --> F["notifications.md — append-only ping log"]
First run (Init Mode)#
When a project has no .copilot-tracking/squad/team.md, the coordinator proposes a
squad profile and asks whether to proceed. If you decline, you can pick a different profile or
build a custom roster from a described menu of every available role — so you
always choose from real, deployed agents and never invent one. It then asks for an optional
approval channel
(github-issue for remote/phone approval, webhook, or
in-chat), then seeds team.md, routing.md,
decisions.md, notifications.md, state.json, and a
history/ directory. It never writes files before you confirm. After that, each
/squad call routes against the seeded roster.
On a brand-new project (no squad yet), Init Mode first offers a choice: a single
squad (the default) for one team across the repo, or a federation of
several named sub-squads. Choosing a federation hands off to /squad-federation
(see below); choosing a single squad keeps the flow above unchanged.
Federation — several sub-squads in one repo#
Federation lets one repository host more than one squad side by side — for example a
product sub-squad for the business team and an azure sub-squad for the
architects. It is opt-in and additive: a repository that never opts in behaves
exactly like a single squad. Each sub-squad is an ordinary squad — same roster,
routing, decisions, history, and consumption — only rooted at
.copilot-tracking/squad/members/<name>/ instead of the top level.
# Build a federation (propose → confirm → create)
/squad-federation init
# Route a request to a specific sub-squad
/squad-federation request="draft the Q3 roadmap" squad=product
# Omit squad= and let meta-routing pick by keyword/domain
/squad-federation request="design the landing-zone network"/squad-federation.
A meta layer at .copilot-tracking/squad/ holds
federation.md (the registry of sub-squads) and meta-routing.md
(request pattern → sub-squad), plus a federation-level decisions and history trail. The
Squad Federation Coordinator reads them, picks the sub-squad(s) — or honors
your explicit squad=<name> — and runs each sub-squad's normal per-turn
protocol scoped to its own root.
The coordinator decides which squad you are on by a simple rule: a
federation.md at the top means a federation (use /squad-federation);
a top-level team.md means a plain squad (use /squad as before). The
two are mutually exclusive, so an existing single-squad project is untouched — until you
choose to promote it (below).
Every sub-squad has a required, unique, lower-kebab-case name, because the name
is at once its members/<name>/ folder and the squad=<name>
selector you type. Init validates names before creating any folder and asks you to rename on a
collision — it never silently reuses or overwrites a sub-squad directory. Profiles are
proposed per sub-squad from your repo and request (just like a single squad), and you can accept,
swap a profile, add or remove a sub-squad, or build a custom roster for any of them.
Promote a single squad to a federation#
If you started on an older version with a single squad and now want the federation shape for a more complex, multi-team or multi-domain project, you do not start over. Promotion adopts your existing squad into a federation as its first sub-squad, moving its state intact rather than rebuilding it.
# Promote the current single squad into a federation
/squad-federation promote
# Or ask the Squad Coordinator and accept its handoff
/squad request="I want to move this squad to a federation"
Promotion runs a propose → confirm → migrate → seed → route
flow and never moves or writes anything before you confirm. On confirmation it relocates the
whole top-level state tree — team.md, routing.md,
decisions.md, history/, consumption, and the rest — into
members/<name>/, preserving your append-only decision and history logs
byte-for-byte, then seeds the meta layer (federation.md,
meta-routing.md, and a federation-level decisions/history trail). That move removes
the top-level team.md, so from the next turn /squad-federation owns
turns and /squad detects the federation and defers.
It is safe and additive: a relocation, not a delete or rewrite; it refuses on a
name collision or when a federation.md already exists; and a consumer who never
promotes is completely unaffected. You can adopt more sub-squads alongside the promoted one in
the same turn, or add them later (see below).
Add a sub-squad to an existing federation#
Federations grow. Once a federation exists, sending init to its coordinator (or just asking
to add a sub-squad) runs Expansion Mode — the same init
entry point builds a federation on a fresh project and expands one that
already exists.
# Add a new sub-squad to the current federation
/squad-federation init request="add a security sub-squad for threat modeling"
Expansion proposes the new sub-squad (name, profile, roles) and, on your confirmation, seeds it
under members/<new>/ and registers it — appending a row to
federation.md and a route to meta-routing.md, plus a federation
decision entry. It is additive and non-destructive: existing sub-squads are
never edited or removed, and it refuses on a name collision. After it completes, the new
sub-squad is routable by squad=<new> or by meta-routing keyword.
Autonomy modes work inside a targeted sub-squad. With squad=azure,
autopilot runs that one sub-squad's full pipeline. Drop the squad= target
for federation-wide autopilot: it orders the selected sub-squads by dependency (confirmed at the first
gate), runs each one's standard autopilot in turn, lifts every Impactful-Action and Risk Gate to
the federation level (attributed to the sub-squad that raised it), applies one aggregate
cost-ceiling with the lifecycle and bounded approval behavior described in
Cost admission control, and ends with a single
consolidated final-outcome validation. Each
sub-squad's inner pipeline is unchanged, and it never auto-releases.
# Target one existing sub-squad
/squad-federation squad=azure mode=autopilot request="implement the approved infrastructure plan"
# Or coordinate the work across the federation
/squad-federation mode=autopilot request="implement the approved cross-squad plan"Promote a learning (/squad-learn)#
Live agent memory always stays local to each consumer. When a squad run surfaces a durable,
broadly applicable learning, /squad-learn drafts a sanitized candidate from
consumer-local memory and opens a pull request to promote it. It never modifies live memory and
never pushes without your explicit approval.
/squad-learn
/squad-learn target=upstream
/squad-learn target=tenant learning="re-read reviewer verdicts before re-dispatching"
The command walks through discover → sanitize → choose target → open PR. Two
targets are offered: upstream promotes to the public package so the merged learning
reaches every consumer, and tenant promotes to your organization's private
tenant-internal repository so the learning stays inside the tenant. Both are gated by a human
pull-request review, the defense against memory poisoning, data leakage, and context drift. The
tenant target requires the private learnings repository to exist first (see the
tenant scaffold);
upstream works out of the box.
Search and export squad knowledge (/squad-document)#
/squad-document searches squad state — decisions, history, routing, roster,
and project documentation — to answer a question or produce a focused document. Instead
of reading decision logs and history files directly, you describe what you need in natural
language and the command synthesizes a grounded answer written to a local file.
/squad-document request="summarize all council verdicts from last week"
/squad-document request="what did the architect decide about the data layer?" format=html
/squad-document request="produce a stakeholder briefing" format=docx outputPath=docs/briefing.docx
/squad-document request="list all escalations" squad=productInputs#
request— (required) what you want to find or document, in natural language.format={md|html|pdf|docx}— output format (defaults tomd). Falls back to Markdown when the requested format's tooling is unavailable.outputPath=<path>— where to save the file. Defaults todocs/squad-document-<YYYY-MM-DD>.<ext>.squad=<name>— in a federation, scope the search to a specific sub-squad. When omitted, searches across all sub-squads.
Every statement in the output is grounded in squad artifacts — the command cites source files and marks gaps as explicit Open Questions rather than inventing content. Squad state is read-only input; the command never modifies any state file.
Governance dashboard (/squad-governance-report)#
/squad-governance-report generates a self-contained HTML governance dashboard
from squad state. It visualizes coordination activity, governance gates, cost distribution,
role dispatch patterns, compliance indicators, and key outcomes so a developer or stakeholder
can assess squad health at a glance — without manually reading decision logs or history
files.
/squad-governance-report
/squad-governance-report output=docs/governance.html period=30d
/squad-governance-report squad=azure period=7dInputs#
output=<path>— where to save the HTML file. Defaults todocs/squad-governance-report-<YYYY-MM-DD>.html.squad=<name>— in a federation, scope to a specific sub-squad. When omitted, aggregates across all sub-squads.period={all|30d|7d}— time window to include (defaults toall).
Dashboard sections#
The generated report contains seven sections:
- Governance Gates — council verdicts, intake checks, human gates, and escalation counts.
- Council Verdicts — verdict distribution (Go / Go-With-Conditions / Stop) with findings by role.
- Cost Breakdown — estimated cost by role and model tier.
- Role Dispatch Activity — dispatch counts, models used, success rate, and autonomy tier distribution.
- Risk & Compliance — artifact evidence, test verification, impactful-action gating, and open escalations.
- Activity Timeline — chronological view of dispatches and decisions.
- Key Outcomes — deployments, issues created, tests run, files changed, and delivered capabilities.
The output is a single .html file with no external dependencies — all styles
are inlined, so it renders correctly when opened in any browser or shared as an attachment.
/squad-governance-report.
Profiles#
The cast each profile seeds:
| Profile | Members | Use when |
|---|---|---|
default | researcher, lead, developer, tester, scribe | General-purpose work; recommended starting point |
full | every role in the cast except the opt-in roles and the four unbacked ones | Complex, cross-cutting projects |
security | researcher, lead, developer, tester, security, supply-chain, rai, privacy, fact-checker, scribe | Security, supply-chain, privacy, threat-modeling, and responsible-AI focus |
design | researcher, lead, developer, tester, designer, accessibility, scribe | UX/UI and product-design focus |
accessibility | researcher, lead, developer, tester, accessibility, designer, scribe | Accessibility conformance as the goal itself — WCAG 2.2, Section 508, or EN 301 549 assessment and remediation |
architecture | researcher, lead, developer, tester, architect, azure-architect, cost-manager, scribe | System design and architecture focus |
azure | researcher, lead, developer, tester, azure-architect, iac-author, deployer, asbuilt-author, azure-diagnose, architect, cost-manager, security, modernizer, scribe | Azure build with IaC authoring, deployment, post-deploy documentation, troubleshooting, budget, and security oversight |
modernization | researcher, lead, developer, tester, modernizer, architect, azure-architect, iac-author, cost-manager, asbuilt-author, scribe | Legacy uplift — framework and dependency upgrades, re-platforming, SQL or cloud migration |
compliance | researcher, lead, developer, tester, security, supply-chain, vuln-manager, privacy, rai, accessibility, risk-manager, scribe | Conformance evidence is the goal — an audit, an attestation, or a customer security questionnaire |
operations | researcher, lead, developer, tester, azure-diagnose, performance, observability, asbuilt-author, iac-author, deployer, scribe | Running a deployed system — incidents, reliability targets, instrumentation design, and as-built documentation |
product | researcher, lead, developer, tester, analyst, designer, product-owner, presenter, technical-writer, experimenter, data-scientist, intake-validator, scribe | Business discovery and delivery — requirements, design thinking, roadmap, and stakeholder deliverables (often non-technical) |
Every profile includes the methodology spine — researcher,
lead, developer, and tester — plus scribe,
so Research → Plan → Implement → Review runs in any profile. Each profile adds its
specialist roles on top. Some roles are seeded only in full, among them
challenger, which pressure-tests a plan and checks it against the research it rests
on, and prompt-engineer, which authors and reviews prompt artifacts. Any role in the
cast can also be added to any roster on request — a profile is a convenient starting set,
not a ceiling.
Some roles are opt-in and appear in no profile at all, not even
full, for one of two reasons. backlog-executor writes work items into
a live Azure DevOps or Jira project, and a tracker write reaches a whole team —
notifications, subscriptions, and webhooks fire the moment an item lands — so the squad
never seeds that reach by default. qa-engineer, release-engineer, and
every pack role are opt-in for a different reason: the agent that fills them is published
elsewhere and simply is not there until you install it, and a roster should never advertise
capability your project does not have. Either way the coordinator offers the role the
first time you ask for work that needs it, naming what it would do and, where something must be
installed, the exact command. Accept and it joins your team for good; decline and the squad
tells you what it cannot do rather than quietly doing it badly. See Backlog writes
below.
The council is sized to the work, not to a fixed quorum. Only
full seeds every council role (architect, security,
cost-manager, product-owner, rai), and no other profile
needs to. A council dispatches only the roles for the lenses the work touches — two of
them, all five, or rai alone — and records every lens it left out with the
reason. When a needed council role is not on your roster, the coordinator offers it as a
council extension. If your opening request already signals a council, the offer comes
at Init, in the same confirmation as your profile; otherwise it comes when the council fires.
In autopilot the squad asks only when a needed role is missing, and Watch Mode reports the role
to add rather than adding it. Decline and the squad records a council waiver and carries on;
the waiver never clears a Risk Gate or an impactful action.
Four roles are listed but unselectable, and they are listed on purpose:
devrel, networking, gcp, and identity. There
is no agent and no skill behind any of them, here or upstream, so a role would be a promise
rather than a capability. Each says why and what would change it, which is more useful than a
gap you discover halfway through a turn.
Packs#
A profile answers what kind of work is this. A pack answers
what is it built on. You pick exactly one profile and layer zero or more packs on top,
so a technology vertical composes with whatever concern you already chose — a Power
Platform project that also needs an audit trail takes compliance plus the
power-platform pack, rather than forcing a choice between them.
The difference is structural, not cosmetic. A profile carries the methodology spine and can
deliver on its own; a pack carries specialists only and needs a profile underneath it. That is
also why azure and modernization stay profiles: they behave as the
dominant shape of a team rather than as an addition to one.
| Pack | Adds | Use when |
|---|---|---|
power-platform | pp-architect, pp-connector | The project is built on Power Platform — Power Apps, Power Automate, Dataverse, Power Pages, or Copilot Studio |
m365-copilot | m365-agent-architect, m365-agent-integrator | The project is built on Microsoft 365 Copilot — declarative agents, TypeSpec agent definitions, API plugins, MCP-backed agents, or Microsoft Graph integration |
aws | aws-architect, aws-diagnose | The project is built on AWS — Lambda and serverless, ECS or EKS, CDK, SAM, CloudFormation, Organizations and landing zones, or a live AWS workload to triage |
pp-architect designs the solution: which components to use, how environments and
DLP policies are set up, how the Dataverse model and the solution lifecycle hang together.
pp-connector builds custom connectors and wires them into Copilot Studio agents.
Both advise and author files; neither runs pac against your tenant or publishes a
connector, so nothing reaches a live environment without you doing it.
m365-agent-architect designs a Microsoft 365 Copilot declarative agent: what it
should be able to do, how its instructions and conversation starters read, and whether it is
defined as a JSON manifest or in TypeSpec. m365-agent-integrator connects that
agent to the systems behind it — MCP server tools, sign-in through Entra, and Microsoft
Graph — and plans the tenant rollout. As with Power Platform, both stop at the handoff:
neither provisions an agent or publishes it to your tenant.
aws-architect designs AWS workloads — which services, how the accounts and
landing zone are laid out, and the CDK, SAM, or CloudFormation to build it — judged
against the AWS Well-Architected pillars. aws-diagnose works a live incident
read-only, from the CloudWatch alarm through metrics, logs, and traces to a root-cause
hypothesis it can show you the evidence for; it recommends a mitigation and never applies one.
Because AWS is a pack rather than a profile, a multi-cloud project takes azure and
the aws pack together and gets both, instead of being asked to choose. There is no
gcp pack: nothing upstream covers Google Cloud, and the squad says so rather than
implying general multi-cloud reach.
A pack is opt-in. Its roles are filled by agents published in github/awesome-copilot rather than by this package, so hve-squad references them instead of shipping them — you install a pack's resources deliberately, and no consumer carries a vertical they never asked for. The coordinator gives you the exact install command when you apply the pack, or the first time a request needs a role the pack would provide.
You rarely have to remember packs exist. The squad offers one the same way it offers a profile — on the first run when your repo carries the signals, or when your request simply names the domain (“turn this business plan into a Power Platform solution” is enough, even in a repo with no Power Platform files yet). It also offers one later, the first time a request needs a role only that pack provides. An offer is never an application: you confirm.
Ask the squad to drop a pack when you are done with that work and it comes back off the roster. Removal only takes out the roles that pack still owns — a role your profile or another pack also contributes stays — and it does not damage the record: the decision log and each agent's history are append-only, so removal adds an entry rather than erasing any. Anything those roles already produced stays on disk, and the resources stay installed, so re-applying the pack later costs nothing.
Some verticals are not packs#
Two domains arrive as extra reach on a role you already have, rather than as a pack, because no
upstream agent behind them passed the squad's verification gate — and a pack needs roles,
which need an agent. Power BI and Fabric (semantic-model review, DAX
optimization, report design, Lakehouse fundamentals) sit with data-scientist.
AI application engineering (Microsoft Agent Framework, Semantic Kernel) sits
with developer.
There is nothing to apply for either. developer is in every profile, so the AI
engineering side is always there. data-scientist is seeded by full and
product; in any other profile, ask a Power BI or Fabric question and the squad will
notice the role is missing and offer to add it, the same way it offers any other role. That works,
but you find out at the moment you need it rather than when you build the squad — which is
the honest cost of a vertical that could not become a pack.
Worked combinations#
The profile comes from the shape of the work and the pack from the technology, so the same pack turns up against several profiles. These are illustrations, not a fixed list — any pack goes with any profile:
| What you are doing | Command |
|---|---|
| Greenfield Power Platform app | profile=default pack=power-platform |
| Power Platform app that has to produce audit evidence | profile=compliance pack=power-platform |
| Designing an AWS workload before anything is built | profile=architecture pack=aws |
| One estate spanning Azure and AWS | profile=azure pack=aws |
| On call for a live AWS workload | profile=operations pack=aws |
| An M365 Copilot agent that handles personal data | profile=security pack=m365-copilot |
| A Power Platform solution fronted by an M365 Copilot agent | profile=default pack=power-platform,m365-copilot |
The operations plus aws row is the one a profile could never have
served: operations already brings the Azure troubleshooter, and the pack puts the AWS
one beside it, so a single squad triages both clouds. The last row is the other case a profile
could not serve — two verticals at once, where a profile makes you pick one.
Profile, pack, or federation?#
Three things can add capability, and it is easy to reach for the wrong one. The rule is short:
One piece of work that needs extra expertise is a profile plus a pack. Those roles have to share a plan, a review, and the same conversation.
Two streams of work with separate deliverables and owners is a federation. Those teams need coordinating, not putting in the same room.
Take a Power Platform app that has to pass an audit. As
profile=compliance pack=power-platform that is one squad: the Power Platform
architect and the privacy role are dispatched against the same request, and the DLP decision and
the data-retention decision are made together, in one plan and one review. Split the same job
into a compliance sub-squad and a power-platform sub-squad and you get
two teams, each with its own decision log and its own history, deciding one thing in two rooms
that never met.
It is also worth knowing that a federation does not reach a technology vertical any faster than a plain squad does. Every sub-squad is seeded from a profile, so a vertical arrives on it by applying the pack — exactly as it would anywhere else. Building a sub-squad named after a vertical still needs the pack, and adds a duplicated research-plan-build-review core and a second set of state files for nothing extra.
Federate when there really are two products — say a Power Platform app and an Azure data platform, different owners, shipping separately. The first of those still carries the pack. See Federation above for how sub-squads work.
Azure execution layer#
The azure profile adds an Azure build-and-deploy capability modeled on a
deployable Azure template repo, delivered the package way — as reference templates plus
squad agents:
- Squad Azure Architect authors the HLD/LLD (AVM modules, landing-zone patterns).
- Squad IaC Author converts that LLD into Bicep or Terraform under
infra/{track}/{project}. - Squad Cost Manager produces indicative estimates and WAF Cost Optimization findings.
- Squad Deployer runs a read-only Azure Policy precheck (effective assignments and predicted denials), then
what-if/plan, and finally the deploy — strictly behind the Impactful-Action Gate, never without your approval. - Squad As-Built Author inventories deployed resources via Azure Resource Graph, builds a compliance matrix from Azure Policy state, and drafts an operations runbook and backup/DR plan — all read-only, never deploys or mutates resources.
- Squad Azure Diagnose queries Resource Health, Azure Monitor logs (KQL), and Resource Graph to correlate ranked hypotheses and recommend (never apply) remediations for unhealthy resources.
The azure-scaffold skill bundles documentation-only reference templates a squad
agent copies into your repo: a dev container (Azure CLI + Bicep, Terraform + TFLint,
gh, Node, Python), azure/login@v2 OIDC deploy workflows for Bicep
and Terraform, a Setup-AzureOidc.ps1 wizard (Entra app registration, federated
credentials, RBAC, GitHub secrets), a read-only Get-PolicyBaseline.ps1 plus a
scheduled governance workflow, and the infra/bicep/{project} /
infra/terraform/{project} convention. Nothing runs from the package — activation
is always an explicit copy-and-commit into your repo, and authentication is OIDC (no stored
secrets).
Azure MCP capability#
The Deployer precheck, As-Built Author, and Azure Diagnose all use the
azure-resource capability, which prefers the official
@azure/mcp server when configured and falls back to the az CLI
and the Azure Resource Graph REST API automatically when it is not. The squad never
blocks on a missing MCP for a read capability like this one.
To wire the Azure MCP server, merge the azure server entry from
.github/skills/squad/mcp.template.json into your
.vscode/mcp.json and reload VS Code. The server authenticates via
az login (DefaultAzureCredential) — no stored secrets. You can
ask the coordinator to scaffold this for your VS Code workspace:
/squad request="merge the squad MCP template into my VS Code workspace"Backlog writes (Azure DevOps and Jira)#
The product-owner role plans a backlog and stops at a finalized handoff file. Turning
that plan into real work items is a separate, gated step owned by the opt-in
backlog-executor role — the same shape as the Azure Deployer: preview first,
approve, then write.
- Ask. With a planned backlog in hand, ask the squad to create the items:
/squad request="create these work items in Azure DevOps" - Accept the role. If your squad does not carry
backlog-executor, the coordinator offers to add it and names the tracker and project it would write to. - Review the preview. The role reads your handoff file and shows every item it would create or update — type, title, parent, target project, and the fields it would set — plus the total count. Nothing has been written yet.
- Check the warnings. It also searches the live tracker for items that already match and flags probable duplicates with their existing IDs, and it strips internal planning references out of the outbound text so no tracking paths or placeholder IDs land in your backlog.
- Approve. One approval covers one batch. Change the handoff, re-run, or target a different project and you get a fresh preview and a fresh approval.
Writes are recorded item by item in a log file next to your handoff, so a batch that fails partway through resumes from the first unwritten item instead of creating duplicates. Nothing is rolled back automatically — whatever landed is reported back to you.
Two limits are deliberate. Writing needs the Azure DevOps MCP server (or, for Jira, the
jira skill) configured; unlike the read capabilities, there is no
fallback — the role stops and tells you what is missing rather than reaching your
tracker by a route you never set up. And because a tracker write is an Impactful Action, an
unattended Watch Mode run produces the preview and stops there; the write always waits for a
person.
Modernization#
The modernizer role plans modernization work and routes it to the right
execution engine, all from the single /squad entry point:
- Same-stack modernization — framework and dependency upgrades, deprecated-API remediation, containerization, and Azure-migration readiness. The plan recommends the squad
developerrole for scoped edits, or Microsoft's official GitHub Copilot App Modernization extension and CLI for large batch upgrades. - Cross-stack re-platform — rewrites across languages or frameworks (for example, a Node.js backend rebuilt on .NET, or a React app rebuilt in Angular). The plan captures a behavior contract for the current system, sequences an incremental (strangler-fig) rewrite, and routes execution to the
developerandarchitectroles under council review — never the official upgrade tooling.
Modernization runs at the confirm tier: the role produces a plan that gates
implementation, and cross-domain phases route through the council before any code changes.
Branded PowerPoint decks#
The presenter role (seeded by the product and full
profiles) generates decks from your content. Give it your branded .pptx once and
every deck inherits your slide masters, layouts, theme colors, and fonts. The branding rule
ships with hve-squad and switches on by itself — you never copy a file, edit a config, or
restate the template on each request.
When you ask for a deck, the coordinator dispatches the PowerPoint Subagent,
which runs the powerpoint skill's build_deck.py. Branding is applied
through the --template flag (PowerShell -TemplatePath): the build
inherits the template's slide masters, layouts, and theme, discards the
template's own example slides, then adds only the slides defined in your content.
The template is everything. A polished deck comes from a well-built template far more than from the generator. Spend your effort on the master and layouts in PowerPoint, and the squad fills them in consistently.
1 — Prepare a branded template#
Open PowerPoint, build a 16:9 template, and save it as a .pptx with:
- Slide Masters carrying your backgrounds, logo placement, and footer — set under View → Slide Master.
-
Named layouts the builder maps onto, at minimum
Title Slide,Title and Content, andSection Header. -
Theme colors and fonts defined in the theme
(Slide Master → Colors / Fonts) so
@theme_namereferences resolve to your brand palette.
You do not need to leave example slides in the file — a --template build
discards them and keeps only the masters, layouts, and theme.
2 — Put it in a stable place#
The template lives at a fixed path so the squad always knows where to find it:
.github/brand/pptx-brand-template.pptx
You do not have to create that folder yourself. If you just hand the squad your
.pptx (or point it at one), it offers to save a copy there for you.
3 — It applies automatically#
hve-squad ships the branding instruction as part of the package, so on apm install
it lands at .github/instructions/pptx-brand-template.instructions.md and switches
on by itself. Its applyTo matches **/.copilot-tracking/ppt/**, so the
PowerPoint Subagent reads it every time it works on a deck — using your template as
--template for full rebuilds and --source for partial ones. If no
template is present yet, the builder does not quietly fall back to a plain deck: it asks
whether you have a branded .pptx and offers to save it for you.
Full rebuild vs. partial rebuild. --template creates a new
deck and keeps only masters, layouts, and theme — use it for new decks and full
regenerations. To update a few slides in an existing deck, the builder uses
--source with --slides instead. Never combine the two: with both,
--template wins and every slide not listed is lost.
4 — Align content with the template (optional, technical)#
You can skip this — the squad handles it for you. For tighter control, declare the
template and map layout names in content/global/style.yaml:
template:
path: ".github/brand/pptx-brand-template.pptx"
preserve_dimensions: true
layouts:
title: "Title Slide"
content: "Title and Content"
section: "Section Header"
Then in each slide's content.yaml, reference colors with @theme_name
rather than hardcoded hex values, so every slide adapts to whatever theme the template defines.
5 — Always validate#
The PowerPoint skill's validation pass is what turns a correct deck into a polished one. It runs geometric checks (margins, overflow, spacing) and optional vision checks (overlaps, contrast, alignment, leftover placeholders), then loops back to fix issues. Let it iterate rather than accepting the first build — that loop is the difference between "it generated" and "it looks great."
After that, request an on-brand deck without any per-request template wiring:
/squad request="build a 6-slide overview deck for the booking service"Run cost ledger#
Each run estimates the model cost and AI-credit consumption of every dispatch so a project
can see what a run spent. The Squad Scribe records this in three places under
.copilot-tracking/squad/:
-
a per-dispatch consumption block appended to
history/<agent>.mdwith the resolved model, how it was resolved, the tier, the estimated internal tool-loop turns, estimated input/cached/cache-write/output tokens, estimated cost, and estimated credits; -
an aggregated
consumption.mdledger of members, models, and credits, split into an Attribution table (who ran, on what model) and a Usage & Cost table (turns, tokens, cost, credits) that share the same row order, totaled for the run, with a cost-comparison line against a single-model manual baseline; -
a
consumption-rates.mdper-model token-rate table — the single place to update when GitHub Copilot pricing changes.
Every figure is an estimate, not a billed amount: no per-dispatch token
telemetry exists, so token counts are estimated and cost and credits are derived (1 AI credit
= $0.01 USD). The run totals also surface in state.json under
currentRun.
Model selection per role (routing=)#
Default behavior (routing=off): No model parameter
is passed to any dispatch, so each agent runs on its own frontmatter model or the session
model, exactly as before this feature existed.
routing= has four modes. The mode is saved in team.md
and stays in effect on later requests until you change it, so you pass it once:
-
off(default) — no model is chosen;team.mdhas noModelcolumn. -
ranked— the squad picks the model that best fits each role's work, among the models your host offers, and shows each pick in aModelcolumn under aModel routing: rankedline. - Pre-release only v0.19.0-pre
economy— asranked, except that five low-impact implementation roles get the cheapest model that fits their work well enough; shown under aModel routing: economyline. Opt-in, and only after you accept the trade. See Economy mode below. -
manual— you pick once, with suggestions pre-filled; your picks are stored in theModelcolumn under aModel routing: manualline.
How ranked picks are made. Each role maps to an assignment class
(research, planning, implementation, review,
council, intake, bookkeeping). The model catalog scores
every model 0–3 for each class, and the squad picks the highest fit, then the lowest blended
cost, then the newest generation of the same model family. It never breaks a tie by a
model's name. The roles themselves, and the agent behind each one, are listed in the squad
skill's references/roster-catalog.md. On the Copilot CLI the seeded roster resolves to, for example,
researcher → claude-opus-5.5, lead →
gpt-5.6-sol, developer → gpt-5.3-codex,
intake-validator → claude-sonnet-5.5, and scribe →
claude-haiku-4.5.
How manual picks are made. When you switch to routing=manual,
at squad creation or later, the coordinator asks before dispatching anything. You can accept
the suggested model for every role, choose one model per assignment class, and then override
individual roles. Every question lists only models your host can run that meet
the role's Model Tier floor. On the Copilot CLI and the GitHub Copilot app, that
is the exact list the task tool advertises. VS Code advertises no list, so the
squad offers catalog models priced at or below your session model; if VS Code rejects a
pick, you are asked again with the list VS Code reports.
Pre-release only v0.19.0-pre
Economy mode (routing=economy). Only these five roles change
model: developer, technical-writer, presenter,
prompt-engineer, and data-scientist. Each gets the cheapest catalog
model with a fit of 2 or better for implementation work, within the role's own
Model Tier floor; every other role, including product-owner,
deployer, iac-author, release-engineer,
backlog-executor, and every review, council, intake, research, planning, and
bookkeeping role, keeps its ranked pick. After a Fail verdict, a
Critical or High finding, or a blocked owner, that owner is re-dispatched once on its
ranked pick, then reviewed again.
Consent. The first time you switch to economy, before any
dispatch, the coordinator tells you once what changes and what does not, and the Scribe
records a ## Economy Mode Accepted decision with your name, the previous mode,
the trade you accepted, and the list of things that are never weakened. If that decision is
missing, the helper script reports consent: missing as a warning, and the
coordinator states the trade and records it before the next dispatch. A Watch Mode or other unattended run
never switches into economy from issue, PR, or comment text.
Never weakened. Economy never skips, shortens, or relaxes the Risk Gate,
the Impactful-Action Gate, the security review, the final tester review, the task-fit council
with its extension and waiver, or any other gate, and it never lowers a floor. Under
off, ranked, and manual the squad behaves exactly as
v0.18.1 does.
What a Model cell holds. One exact model id from the
Model ID column of consumption-rates.md (for example
claude-sonnet-5.5). A cell below the role's floor, an unknown id, or an id
containing shell or prompt metacharacters is refused and logged, never guessed.
Precedence (highest wins, per role):
routing=manual: the role's validModelcell.routing=ranked: the ranked pick for that role (routing=economyPre-release only v0.19.0-pre: the economy pick).-
tier=(the existing static-tier input) or the seededteam.mdModel Tier — today's fallback, unchanged. - Omit the parameter — the no-policy default.
Dispatch copies the cell: under ranked, economyPre-release only v0.19.0-pre, or manual, every
dispatch to a roster agent passes that row's Model cell exactly, except the Scribe,
whose own model pin governs. In the plugin distribution, the dispatch-guards hook
refuses a dispatch whose model is missing or differs from the cell, and names the
cell to copy. It only compares; it never fills or changes a cell.
Unevaluated models: A model the host offers but the catalog does not carry is
never ranked or suggested. You can still type it as a manual pick; it is then labelled
unevaluated in the dispatch record.
Which model to start the session on. The model you pick in the chat, or pass
with --model, runs the coordinator: it reads the roster, plans the stages, and
dispatches every role. routing= never changes it. Start on a fixed model from the
catalog's balanced class (the vendor's mid tier), as capable as
claude-sonnet-5.5. Pick any model of that class your host offers, for example
claude-sonnet-5.5, gpt-6-sol, gpt-5.6-terra,
gemini-3.8-flash, or grok-4.7; the squad skill's
references/model-catalog.md holds the current list. A
frontier-reasoning model adds cost to every coordinator turn without improving the
work, which ranked already sends to frontier models where it pays off. A
fast-lightweight model is more likely to miss required steps, such as copying the
Model cell or sending the Scribe hand-off together with the next stage. Under
auto, the host can switch the coordinator's model mid-run, and the ledger cannot
price its share (see Fixed model versus auto).
The former models=<key>:<id>,... input is retired. If you pass it,
it is not applied, and the coordinator points you to routing=manual.
Examples:
# Switch to ranked selection; team.md gains a Model column showing each role's pick.
/squad request="implement the design" routing=ranked# Switch to economy; the squad states the trade and records your consent first.
/squad request="update the getting-started guide" routing=economy# Switch to manual selection; you are asked for the models before the request runs.
/squad request="design the data layer" routing=manual
# Return to the default; the Model column is removed.
/squad request="review the implementation" routing=off
# Switch the product sub-squad to manual selection; each sub-squad keeps its own picks.
/squad-federation squad=product routing=manualLedger validation#
The Scribe runs a write-completeness Self-Check exactly once per hand-off, after all writes are persisted. This check re-counts dispatch records and consumption blocks in every touched history file to confirm they match what was written, and verifies the consumption ledger's per-role and run-total rows sum correctly from the blocks recorded on disk.
When PowerShell 7+ is available, the coordinator also runs the helper script
Measure-SquadLedger.ps1 -Check (with -SquadRoot <root> pointing to a squad
root) from the squad skill's scripts/ directory. This read-only helper
re-derives the entire ledger from the history files and consumption-rates.md, and exits
non-zero if it detects any of these conditions:
- A divergence between the ledger's run total and the sum of its own rows.
- A divergence between the ledger's run total and
state.json'scurrentRuntotals. Missing or unparseablestate.jsonfails the check; a federation root (marked byfederation.md) is logged as not-applicable instead. - An identity-guard failure: recorded per-file ordered block identities in the ledger
### Derivationblock must form an ordered prefix of that file's current identities. Overwrites, reorders, or removals of history entries fail this guard; appends pass. A plain-Check(no-ExpectedHistoryCounts) only warns on ledgers with no recorded identities at all (legacy format compatibility). Combined with-ExpectedHistoryCounts— the Scribe's own post-write self-check — a Derivation missing identities entirely, or missing them for only some of the touched files (a partial paste), fails instead of warning.
The Scribe does not hand-copy these figures. Its only write path for them is
Measure-SquadLedger.ps1 -Write, which replaces the Attribution, Usage & Cost, and
Derivation sections of consumption.md and sets state.json's two
currentRun totals from the same derivation. Every other byte of both files is left
unchanged. It refuses and writes nothing on a federation root, beside -Check, or when either
file lacks the section it replaces. The coordinator puts the exact command in each Scribe hand-off
as ledgerCommand, and the Scribe runs it as its last write. Run -Check
afterwards to confirm the write.
Observed usage. The estimates stay, and real usage sits beside them. With
-SessionLog auto, which ledgerCommand carries, the script reads the host's
own session log (~/.copilot/session-state/<session>/events.jsonl, written by
the Copilot CLI and the VS Code agent host) and adds an Observed Usage (host-reported)
section to consumption.md. Per agent, it lists the model that actually ran, whether
it matches the ledger, and real total tokens beside the estimated ones. It also gives the host's
billed AI units for the whole session, coordinator included. A Without HVE Squad table
compares the observed run with the same role work on one model and no Scribe, both priced with
the catalog's blended mix. The host reports one token total per dispatch, not the input, cached,
and output split, so that comparison is a like-for-like estimate rather than a bill.
Requirements for running the squad#
- A
runSubagentortasktool must be enabled so the coordinator can dispatch the cast. - The memory tool should be available for durable per-agent notes under
/memories/repo/. - For the
github-issueapproval channel only: an authenticatedghCLI orgithubMCP on the run host, and the approval-watcher workflow installed. Interactive and in-chat runs need neither.
You can re-cast the squad later by editing .copilot-tracking/squad/team.md or
asking the coordinator to switch profiles.
Running on other hosts#
The squad ships both prompts and agents. VS Code Copilot Harness, GitHub Copilot CLI, and the GitHub Copilot app all run Squad workflows through user-invocable agents. Prompt files remain an alternative in VS Code, but selecting the mapped agent avoids an intermediary call and is the invocation model that works everywhere.
| Entry point | VS Code Copilot Harness | Copilot CLI and Copilot app |
|---|---|---|
| Run a squad | select the Squad Coordinator agent | select the Squad Coordinator agent |
| Run a federation | select the Squad Federation Coordinator agent | select the Squad Federation Coordinator agent |
| Search and export | select the Squad Document agent | select the Squad Document agent |
| Governance dashboard | select the Squad Governance Report agent | select the Squad Governance Report agent |
| Promote a learning | select the Squad Learn agent | select the Squad Learn agent |
On the CLI you can select an agent interactively with /agent, or start a headless
run with --agent:
copilot --agent="Squad Coordinator" --prompt 'request="add input validation to the login form" profile=security'
Named parameters carry over. request=,
profile=, pack=, tier=, mode=,
owner=, format=, period= and the rest are parsed by
each agent's own Inputs section, not by the prompt file. Type them in the request
text and they work identically on every host.
The squad skill is also discovered on the CLI, so /squad loads the
squad operating procedure into whatever agent you are already talking to. That is not the same
as running the coordinator — select the agent when you want a real squad turn.
Known host limits#
-
Agent bodies are capped at 30,000 characters outside VS Code. Every squad
agent ships under that cap; the procedure lives in the
squadskill and is retrieved on demand rather than injected on every turn. -
model:must be a single string. VS Code also accepts a YAML array; the CLI rejects the file outright and the agent never loads. Per-role model preference belongs in theModel Tiercolumn ofteam.md. -
Path-scoped instructions load only on an
applyTomatch outside VS Code, so an agent that has not yet touched squad state may run without them. The package shipssquad-floor.instructions.mdscoped to**for that reason: it carries dispatch discipline, the single-writer Scribe rule, the state paths, and proof of dispatch, and applies regardless of which file is in play. -
${input:…}substitution is VS Code-only. The agents restate their inputs in plain parameter names for that reason. -
There is no question tool outside VS Code. The discovery and intake gates
interview you one question at a time, and in VS Code that runs through
vscode_askQuestions. The Copilot CLI and the app ship no equivalent, so the dispatched role returns its question and the coordinator asks it in the response text instead. The discipline is the same on every host: an unanswered blocking question stops the turn rather than becoming a recorded assumption.
Fixed model versus auto#
Under automatic model selection the host routes each request itself and overrides a subagent's pinned model: a role pinned to Sonnet can be measured running a different model entirely. Frontmatter is a request, not a guarantee — an account that is not entitled to a pinned model gets the session model substituted silently on the dispatch path.
The ledger therefore records what the host reported for each dispatch, not what the
roster asked for. When cost attribution matters, run with a fixed session model
(--model <id> on the CLI, or a pinned model in the VS Code picker) so the
roster's cost-first tiers actually take effect.