Skip to content

PRD: ADO-Driven Squadding — Full Azure DevOps Support #581

Open

Description

@jackbatzner

PRD: ADO-Driven Squadding — Full Azure DevOps Support

Author: Jack Batzner
Status: Draft — Proposal

Problem Statement

Squad's automation layer — squad watch, triage, agent dispatch, and CI workflows — is hardcoded to GitHub. The SDK has a full AzureDevOpsAdapter with area path, iteration, and work item type support, but nothing above the SDK layer uses it. Teams using Azure DevOps for work tracking cannot adopt Squad without abandoning their existing workflow tooling.

This PRD proposes enabling 100% ADO-driven squadding: work item creation through agent implementation through PR review, entirely within Azure DevOps.

Current State

What exists (SDK layer — ready)

  • AzureDevOpsAdapter — full CRUD for work items, PRs, branches, tags, comments (feature-parity with GitHubAdapter)
  • Area path / iteration / work item type support — config-driven via .squad/config.json
  • detectPlatform() — auto-detects GitHub vs ADO from git remote URL
  • detectWorkItemSource() — exists but is never called
  • Ralph command templates for ADO — defined in ralph-commands.ts but never invoked

What's hardcoded to GitHub (automation layer — the gap)

  • watch.ts — calls ghIssueList(), ghIssueEdit(), ghPrList() directly, never uses PlatformAdapter
  • Agent dispatch — uses GitHub's proprietary agent_assignment API via secrets.COPILOT_ASSIGN_TOKEN
  • 5 CI workflows — webhook-driven, GitHub Actions-specific (squad-triage.yml, squad-issue-assign.yml, squad-label-enforce.yml, squad-heartbeat.yml, sync-squad-labels.yml)

What already works without any changes

  • Squad config files are platform-agnostic — .squad/team.md, .squad/routing.md, .squad/agents/*/charter.md are all plain markdown with no GitHub-specific content
  • squad.config.ts — the SDK mode config is platform-neutral
  • squad build — generates .squad/ from config, no platform dependency

Feature Parity Matrix: GitHub vs ADO

Every Squad capability on GitHub mapped to its ADO equivalent.

Core Squad Files

Capability GitHub ADO Parity
Team roster (.squad/team.md) ✅ Works ✅ Works 🟢 Full — plain markdown
Routing rules (.squad/routing.md) ✅ Works ✅ Works 🟢 Full — plain markdown
Agent charters (.squad/agents/*/charter.md) ✅ Works ✅ Works 🟢 Full — plain markdown
Config (.squad/config.json) ✅ Works ✅ Works 🟢 Full — already has ADO fields
squad build ✅ Works ✅ Works 🟢 Full — no platform dependency
squad init ✅ Scaffolds GitHub templates ⚠️ No ADO templates 🟡 Needs --platform ado

Work Item Management

Capability GitHub ADO Parity
Create work items gh issue create AzureDevOpsAdapter.createWorkItem() 🟢 SDK ready
List/query work items gh issue list adapter.listWorkItems() + WIQL 🟢 SDK ready
Update work items gh issue edit adapter.updateWorkItem() 🟢 SDK ready
Add comments gh issue comment adapter.addComment() 🟢 SDK ready
Labels / Tags GitHub labels (flat) ADO tags (flat) 🟢 Functionally equivalent
Area path routing ❌ N/A ✅ Native 🟢 Supported natively
Iteration / Sprint ❌ N/A ✅ Native 🟢 Supported natively
Work item types Issue only PBI / Bug / Task / Epic / Feature 🟢 Supported — config-driven

Pull Request Management

Capability GitHub ADO Parity
Create PRs GitHubAdapter.createPullRequest() AzureDevOpsAdapter.createPullRequest() 🟢 SDK ready
List PRs GitHubAdapter.listPullRequests() AzureDevOpsAdapter.listPullRequests() 🟢 SDK ready
Merge PRs GitHubAdapter.mergePullRequest() AzureDevOpsAdapter.mergePullRequest() 🟢 SDK ready
Create branches GitHubAdapter.createBranch() AzureDevOpsAdapter.createBranch() 🟢 SDK ready
PR → work item linking #123 references AB# linking (native) 🟢 Different syntax, same result

Agent Dispatch

Capability GitHub ADO Parity
Manual dispatch Click "Assign to Copilot" on issue Click "Create PR with Copilot" on work item 🟢 Azure Boards + Copilot Coding Agent (GA)
Custom agent selection .github/agents/*.agent.md in Copilot UI Same files in Azure Boards Copilot dropdown 🟢 Same mechanism
Auto-dispatch (event) GitHub Actions → agent_assignment API Service Hook → Pipeline → ? 🟡 No public API to invoke Copilot Coding Agent programmatically
Auto-dispatch (polling) squad watch (GitHub only) squad watch --platform ado 🔴 watch.ts hardcoded to gh CLI

Event-Driven Automation

GitHub Workflow What It Does ADO Equivalent Parity
squad-triage.yml Issue created → route via routing.md Service Hook → Pipeline 🟢 Direct equivalent
squad-issue-assign.yml Issue labeled squad:* → assign Copilot Service Hook → Pipeline → assign 🟡 Assign works, but Copilot invocation needs bridge
squad-label-enforce.yml Issue labeled → enforce mutual exclusivity Service Hook → Pipeline → ADO REST API 🟢 Direct equivalent
squad-heartbeat.yml Cron 30min → bulk triage Scheduled Pipeline 🟢 ADO Pipelines support cron natively
sync-squad-labels.yml Push team.md → sync labels Pipeline with push trigger 🟢 Direct equivalent
squad-ci.yml PR → lint, build, test ADO Pipeline with PR trigger 🟢 Standard CI

Board & Planning

Capability GitHub ADO Parity
Board visibility GitHub Projects (manual setup) ADO Boards (native) 🟢 Supported
Sprint planning Manual ADO iterations 🟢 Supported
Capacity planning ❌ N/A ✅ Native 🟢 Supported
Burndown charts ❌ N/A ✅ Native 🟢 Supported

Gap Summary

🟢 No changes needed

  • All Squad config files (team.md, routing.md, charters, config.json, squad build)
  • Work item CRUD + PR management (SDK adapter is complete)
  • Manual agent dispatch (Azure Boards + Copilot Coding Agent, GA)
  • Custom agent selection from ADO UI (same .github/agents/ files)
  • CI/CD (ADO Pipelines = GitHub Actions)
  • Board/sprint/capacity planning (ADO native)

🟡 Workarounds exist

  • Auto-dispatch to Copilot Coding Agent — No public API to programmatically trigger it. Workaround: Pipeline creates a GitHub issue assigned to Copilot → Copilot picks it up. Or use squad watch locally.
  • squad init --platform ado — Currently scaffolds GitHub-only. Need --platform ado flag for ADO Pipeline templates.

🔴 Code changes required

  • squad watch for ADO — The only blocking code change. Details below.

What Will Be Implemented

Summary

# Change Type Scope Files
1 Platform-agnostic squad watch Modified code ~50-100 lines refactored watch.ts, detect.ts
2 Charter dispatch schema New feature New frontmatter field parsed charter.ts, watch.ts
3 ADO Pipeline templates New files 5 YAML templates templates/ado-pipelines/
4 squad init --platform ado Modified code New CLI flag + template copy init.ts
5 ADO setup documentation New file Setup guide for Service Hooks + Pipelines docs/

What's NOT changing: Squad's core architecture, charter format, team.md/routing.md, squad build, the existing GitHub path, or how agents operate. This is purely wiring the existing PlatformAdapter + AzureDevOpsAdapter into the automation layer that currently skips them.


Details

1. Platform-agnostic squad watch (the main code change)

The problem: watch.ts calls GitHub-specific functions directly.

// BEFORE — watch.ts (hardcoded to GitHub)
const issues = await ghIssueList({ label: 'squad', state: 'open' });
for (const issue of issues) {
  await ghIssueEdit(issue.number, { addLabels: [`squad:${agent}`] });
}
const prs = await ghPrList({ state: 'open' });

The fix: Route through PlatformAdapter so the same code works for both platforms.

// AFTER — watch.ts (platform-agnostic)
const adapter = await detectPlatform();  // returns GitHubAdapter or AzureDevOpsAdapter
const items = await adapter.listWorkItems({ 
  tags: ['squad'], 
  state: 'open',
  areaPath: config.ado?.areaPath  // ADO-only, ignored on GitHub
});
for (const item of items) {
  await adapter.addTag(item.id, `squad:${agent}`);
}
const prs = await adapter.listPullRequests({ state: 'open' });

Scope: ~50-100 lines changed in watch.ts. The PlatformAdapter interface and AzureDevOpsAdapter already exist — this is wiring, not building.

Files touched:

  • packages/squad-cli/src/cli/commands/watch.ts — replace ghIssueList/ghIssueEdit/ghPrList with adapter.* calls
  • packages/squad-sdk/src/platform/detect.ts — call detectWorkItemSource() (exists but unused)

2. Charter-based dispatch (new schema)

Add a dispatch block to charter frontmatter so agents declare how they receive work:

# .squad/agents/coder/charter.md (frontmatter)
name: coder
dispatch:
  strategy: ado-assignment    # or: github-copilot, local-cli, webhook
  identity: "agent-identity"  # who gets assigned in the platform
  branch: main
Strategy How It Works Who Uses It
github-copilot GitHub's agent_assignment API (current behavior) GitHub teams
ado-assignment Azure Boards Copilot integration or Service Hook trigger ADO teams with Copilot
local-cli squad watch dispatches locally Anyone, any platform
webhook POST work item payload to URL Custom platforms

Files touched:

  • packages/squad-sdk/src/config/charter.ts — parse dispatch from frontmatter
  • packages/squad-cli/src/cli/commands/watch.ts — read dispatch strategy when assigning

3. ADO Pipeline templates (new files)

Ship ADO Pipeline YAML equivalents of the 5 GitHub Actions workflows. These get scaffolded by squad init --platform ado:

# .azuredevops/pipelines/squad-triage-pipeline.yml
# Triggered by ADO Service Hook on "Work item created"
trigger: none

pool:
  vmImage: 'ubuntu-latest'

steps:
  - checkout: self
  - task: NodeTool@0
    inputs: { versionSpec: '20.x' }
  - script: |
      npx @bradygaster/squad-cli triage \
        --platform ado \
        --work-item-id $(WORK_ITEM_ID) \
        --area-path "$(AREA_PATH)"
    env:
      ADO_PAT: $(ADO_PAT)
      GITHUB_TOKEN: $(GITHUB_TOKEN)
# .azuredevops/pipelines/squad-heartbeat-pipeline.yml
# Equivalent of squad-heartbeat.yml (cron every 30 min)
trigger: none
schedules:
  - cron: '*/30 * * * *'
    displayName: 'Squad heartbeat'
    branches: { include: [main] }
    always: true

pool:
  vmImage: 'ubuntu-latest'

steps:
  - checkout: self
  - task: NodeTool@0
    inputs: { versionSpec: '20.x' }
  - script: |
      npx @bradygaster/squad-cli heartbeat \
        --platform ado \
        --area-path "$(SQUAD_AREA_PATH)"
    env:
      ADO_PAT: $(ADO_PAT)
      GITHUB_TOKEN: $(GITHUB_TOKEN)

Full set shipped:

Template Trigger Equivalent Of
squad-triage-pipeline.yml Service Hook: work item created squad-triage.yml
squad-assign-pipeline.yml Service Hook: work item updated (tag) squad-issue-assign.yml
squad-label-enforce-pipeline.yml Service Hook: work item updated squad-label-enforce.yml
squad-heartbeat-pipeline.yml Scheduled (cron 30 min) squad-heartbeat.yml
squad-sync-labels-pipeline.yml Push trigger on .squad/team.md sync-squad-labels.yml

Files touched:

  • templates/ado-pipelines/ — new directory with 5 YAML files
  • packages/squad-cli/src/cli/commands/init.ts — add --platform ado flag, copy templates

4. squad init --platform ado (scaffolding)

$ squad init --platform ado

✓ Created .squad/team.md
✓ Created .squad/routing.md
✓ Created .squad/agents/coder/charter.md (with dispatch.strategy: ado-assignment)
✓ Created .squad/config.json (with ado.org, ado.project, ado.areaPath)
✓ Created .azuredevops/pipelines/squad-triage-pipeline.yml
✓ Created .azuredevops/pipelines/squad-heartbeat-pipeline.yml
✓ Created .azuredevops/pipelines/squad-assign-pipeline.yml
✓ Created .azuredevops/pipelines/squad-label-enforce-pipeline.yml
✓ Created .azuredevops/pipelines/squad-sync-labels-pipeline.yml
✓ Created docs/ado-setup.md (Service Hook configuration guide)

Files touched:

  • packages/squad-cli/src/cli/commands/init.ts — add --platform option
  • templates/ado-pipelines/ — template source files

What Won't Be Supported (Known Limitations)

Limitation Why Workaround
Programmatic Copilot Coding Agent invocation No public API exists — it's UI-only (click button on work item) Pipeline creates GitHub issue → Copilot picks up; or squad watch dispatches locally
ADO-native PR agent (no GitHub repo) Copilot Coding Agent requires a GitHub repo Use squad watch --platform ado for pure-ADO repos with ADO Repos
GitHub label ↔ ADO tag atomicity ADO tags don't support the same atomic add/remove as GitHub labels squad watch handles retries; Pipeline templates use ADO REST API with optimistic concurrency

Open Questions

None — multi-platform (hybrid GitHub + ADO in a single repo) is deferred until there is a concrete need.


Prior Art

Issues

Pull Requests

External References — Azure Boards + Copilot Coding Agent (Public)

External References — ADO Automation Primitives (Public)

Community Examples

Squad Source Code

  • ADO adapter: packages/squad-sdk/src/platform/azure-devops.ts
  • Platform types: packages/squad-sdk/src/platform/types.ts
  • Watch loop: packages/squad-cli/src/cli/commands/watch.ts
  • Platform detection: packages/squad-sdk/src/platform/detect.ts
  • Agent charters: .squad/agents/*/charter.md
  • Routing rules: .squad/routing.md

CC: @bradygaster , @tamirdresher

Activity

  1. github-actions commented on Mar 28, 2026

    @github-actions
    Contributor

    🏗️ Squad Triage — Flight (Lead)

    Issue: #581 — PRD: ADO-Driven Squadding — Full Azure DevOps Support
    Assigned to: FIDO (Quality Owner)
    Reason: Issue relates to testing/quality work

    @copilot evaluation: 🔴 Not suitable — issue involves work outside the coding agent's capability profile.

    Team roster:

    • Flight (Lead) → label: squad:flight
    • Procedures (Prompt Engineer) → label: squad:procedures
    • EECOM (Core Dev) → label: squad:eecom
    • FIDO (Quality Owner) → label: squad:fido
    • PAO (DevRel) → label: squad:pao
    • CAPCOM (SDK Expert) → label: squad:capcom
    • CONTROL (TypeScript Engineer) → label: squad:control
    • Surgeon (Release Manager) → label: squad:surgeon
    • Booster (CI/CD Engineer) → label: squad:booster
    • GNC (Node.js Runtime) → label: squad:gnc
    • Network (Distribution) → label: squad:network
    • RETRO (Security) → label: squad:retro
    • INCO (CLI UX & Visual Design) → label: squad:inco
    • GUIDO (VS Code Extension) → label: squad:guido
    • Telemetry (Aspire & Observability) → label: squad:telemetry
    • VOX (REPL & Interactive Shell) → label: squad:vox
    • DSKY (TUI Engineer) → label: squad:dsky
    • Sims (E2E Test Engineer) → label: squad:sims
    • Handbook (SDK Usability) → label: squad:handbook
    • Ralph (Work Monitor) → label: squad:ralph
    • @copilot (Coding Agent) → label: squad:copilot

    To reassign, remove the current squad:* label and add the correct one.

  2. github-actions commented on Mar 28, 2026

    @github-actions
    Contributor

    📋 Assigned to Flight (Lead)

    Issue: #581 — PRD: ADO-Driven Squadding — Full Azure DevOps Support

    Flight will pick this up in the next Copilot session.

    For Copilot coding agent: If enabled, this issue will be worked automatically.
    Otherwise, start a Copilot session and say:
    Flight, work on issue #581

  3. github-actions commented on Mar 28, 2026

    @github-actions
    Contributor

    📋 Assigned to EECOM (Core Dev)

    Issue: #581 — PRD: ADO-Driven Squadding — Full Azure DevOps Support

    EECOM will pick this up in the next Copilot session.

    For Copilot coding agent: If enabled, this issue will be worked automatically.
    Otherwise, start a Copilot session and say:
    EECOM, work on issue #581

  4. diberry commented on Mar 31, 2026

    @diberry
    Contributor

    🔄 Ralph status: PRD — ADO-driven squadding. No PR. Long-term backlog.

  5. 3 remaining items

  6. github-actions commented on Sep 10, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: CONTROL
    Reason: Matched module path "src/config/" to primary owner "CONTROL 👩‍💻"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  7. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: CONTROL
    Reason: Matched module path "src/config/" to primary owner "CONTROL 👩‍💻"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  8. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: CONTROL
    Reason: Matched module path "src/config/" to primary owner "CONTROL 👩‍💻"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  9. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: CONTROL
    Reason: Matched module path "src/config/" to primary owner "CONTROL 👩‍💻"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  10. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: CONTROL
    Reason: Matched module path "src/config/" to primary owner "CONTROL 👩‍💻"
    Source: module-ownership

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  11. github-actions commented on Sep 13, 2026

    @github-actions
    Contributor

    🔄 Ralph — Auto-Triage

    Assigned to: architect
    Reason: No module, routing, or role keyword match — routed to Lead/Architect
    Source: lead-fallback

    Ralph auto-triaged this issue using routing rules.
    To reassign, swap the squad:* label.

  12. added
    post-2.0Deferred until after the 2.0 line
    and removed
    wave:3-laterWave 3 — backlog, future
    on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or improvementgo:needs-researchNeeds investigationpost-2.0Deferred until after the 2.0 linepriority:p2Next sprintsquadSquad triage inbox — Lead will assign to a membersquad:architectAssigned to architect (Lead Architect)triagedIssue has been triagedtype:featureNew capability

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions