Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 89 additions & 2 deletions .github/agents/squad.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,18 @@ When triggered:

### Issue Awareness

**On every session start (after resolving team root):** Check for open GitHub issues assigned to squad members via labels. Use the GitHub CLI or API to list issues with `squad:*` labels:
**On every session start (after resolving team root):** Check for open issues/work items assigned to squad members. Detect the platform first:

**GitHub:** Use `gh` CLI or GitHub MCP tools:
```
gh issue list --label "squad:{member-name}" --state open --json number,title,labels,body --limit 10
```

**Azure DevOps:** Read `.squad/config.json` for `ado.org`/`ado.project`, then use WIQL:
```
az boards query --wiql "SELECT [System.Id],[System.Title],[System.Tags] FROM WorkItems WHERE [System.Tags] Contains 'squad:{member-name}' AND [System.State] <> 'Closed' AND [System.TeamProject] = '{project}'" --org "https://dev.azure.com/{org}" --project "{project}" --output json
```

For each squad member with assigned issues, note them in the session context. When presenting a catch-up or when the user asks for status, include pending issues:

```
Expand Down Expand Up @@ -455,6 +461,7 @@ MCP (Model Context Protocol) servers extend Squad with tools for external servic

At task start, scan your available tools list for known MCP prefixes:
- `github-mcp-server-*` → GitHub API (issues, PRs, code search, actions)
- `azure-devops-*` → Azure DevOps API (work items, repos, PRs, pipelines, wiki)
- `trello_*` → Trello boards, cards, lists
- `aspire_*` → Aspire dashboard (metrics, logs, health)
- `azure_*` → Azure resource management
Expand Down Expand Up @@ -946,6 +953,65 @@ Before connecting to a GitHub repository, verify that the `gh` CLI is available

---

## Platform Detection

On session start, detect the platform from git remote:
- `github.com` → Use GitHub commands (`gh` CLI)
- `dev.azure.com` or `*.visualstudio.com` → Use Azure DevOps commands (`az` CLI)

If `squad.config.ts` specifies `workItems: 'planner'`, use Microsoft Planner for work items regardless of where the repo lives.

### Azure DevOps Mode

If the git remote points to Azure DevOps:

| GitHub concept | Azure DevOps equivalent | Command change |
|---|---|---|
| `gh issue list` | WIQL query via `az boards query` | `az boards query --wiql "SELECT ... FROM WorkItems WHERE ..."` |
| `gh pr list` | `az repos pr list` | `az repos pr list --status active` |
| `gh pr create` | `az repos pr create` | `az repos pr create --source-branch ... --target-branch ...` |
| `gh pr merge` | `az repos pr update --status completed` | Set PR status to completed |
| Issue labels | Work Item tags | `az boards work-item update --fields "System.Tags=..."` |
| `squad:{member}` label | `squad:{member}` tag on work items | Tags use `;` separator |

**Prerequisites for Azure DevOps:**
1. Run `az --version`. If missing: *"Azure DevOps mode requires the Azure CLI. Install from https://aka.ms/install-az-cli"*
2. Run `az extension show --name azure-devops`. If missing: *"Run `az extension add --name azure-devops`"*
3. Run `az account show`. If not logged in: *"Run `az login` to authenticate"*
4. Verify defaults: `az devops configure --list` — org and project must be set

**ADO Work Item Config (`.squad/config.json`):**

Read the `ado` section from `.squad/config.json` to resolve org, project, work item type, area/iteration paths:

```json
{
"platform": "azure-devops",
"ado": {
"org": "my-org",
"project": "work-items-project",
"defaultWorkItemType": "Scenario",
"areaPath": "MyProject\\Team Alpha",
"iterationPath": "MyProject\\Sprint 5"
}
}
```

- If `ado.org`/`ado.project` are set, use them for ALL work item operations (they may differ from the repo's org/project)
- If not set, parse org/project from `git remote get-url origin`
- Pass `--org https://dev.azure.com/{org} --project {project}` on every `az boards` command
- Use `ado.defaultWorkItemType` when creating work items (default: "User Story")

**Ralph on Azure DevOps:**
- **Read `.squad/config.json`** first — the `ado` section tells you which org/project to query for work items
- Replace `gh issue list --label "squad:untriaged"` with WIQL: `az boards query --wiql "SELECT ... WHERE [System.Tags] Contains 'squad:untriaged' AND [System.TeamProject] = '{project}'" --org ... --project ...`
- Replace `gh issue list --label "squad:{member}"` with WIQL: `az boards query --wiql "SELECT ... WHERE [System.Tags] Contains 'squad:{member}'" --org ... --project ...`
- Replace `gh pr list` with `az repos pr list` (uses repo org/project, not work item org/project)
- When creating work items, use `ado.defaultWorkItemType`, include `ado.areaPath` and `ado.iterationPath` if configured
- Branch naming stays the same: `squad/{issue-number}-{slug}`

---

## Ralph — Work Monitor

Ralph is a built-in squad member whose job is keeping tabs on work. **Ralph tracks and drives the work queue.** Always on the roster, one job: make sure the team never sits idle.
Expand All @@ -970,14 +1036,17 @@ Ralph always appears in `team.md`: `| Ralph | Work Monitor | — | 🔄 Monitor
| "Ralph, idle" / "Take a break" / "Stop monitoring" | Fully deactivate (stop loop + idle-watch) |
| "Ralph, scope: just issues" / "Ralph, skip CI" | Adjust what Ralph monitors this session |
| References PR feedback or changes requested | Spawn agent to address PR review feedback |
| "merge PR #N" / "merge it" (recent context) | Merge via `gh pr merge` |
| "merge PR #N" / "merge it" (recent context) | Merge via `gh pr merge` (GitHub) or `az repos pr update --status completed` (ADO) |

These are intent signals, not exact strings — match meaning, not words.

When Ralph is active, run this check cycle after every batch of agent work completes (or immediately on activation):

**Step 1 — Scan for work** (run these in parallel):

> **Platform-aware:** Detect the platform from git remote. If Azure DevOps, read `.squad/config.json` for the `ado` section FIRST — it tells you which org/project to query for work items (may differ from the repo). Use `az boards query` / `az repos pr list` instead of `gh`. If Planner, use Graph API. Do NOT guess the ADO project from the repo name — read the config.

**GitHub:**
```bash
# Untriaged issues (labeled squad but no squad:{member} sub-label)
gh issue list --label "squad" --state open --json number,title,labels,assignees --limit 20
Expand All @@ -992,6 +1061,24 @@ gh pr list --state open --json number,title,author,labels,isDraft,reviewDecision
gh pr list --state open --draft --json number,title,author,labels,checks --limit 20
```

**Azure DevOps:**
```bash
# Read org/project from .squad/config.json → ado.org, ado.project
# Fall back to git remote URL parsing if not configured

# Untriaged work items
az boards query --wiql "SELECT [System.Id],[System.Title],[System.State],[System.Tags] FROM WorkItems WHERE [System.Tags] Contains 'squad:untriaged' AND [System.TeamProject] = '{project}' ORDER BY [System.CreatedDate] DESC" --org "https://dev.azure.com/{org}" --project "{project}" --output table

# Member-assigned work items
az boards query --wiql "SELECT [System.Id],[System.Title],[System.State],[System.Tags] FROM WorkItems WHERE [System.Tags] Contains 'squad:{member}' AND [System.State] <> 'Closed' AND [System.TeamProject] = '{project}' ORDER BY [System.CreatedDate] DESC" --org "https://dev.azure.com/{org}" --project "{project}" --output table

# Open PRs (uses repo org/project, NOT work item org/project)
az repos pr list --status active --output table

# Create a work item (uses configured type, area path, iteration path)
az boards work-item create --type "{ado.defaultWorkItemType}" --title "{title}" --fields "System.Tags=squad; squad:untriaged" --org "https://dev.azure.com/{org}" --project "{project}"
```

**Step 2 — Categorize findings:**

| Category | Signal | Action |
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ coverage/
.test-cli-*
# Docs site generated files
docs/dist/

.squad/.first-run
.squad/config.json
226 changes: 226 additions & 0 deletions docs/blog/023-squad-goes-enterprise-azure-devops.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
---
title: "Squad Goes Enterprise — Azure DevOps, Area Paths, and Cross-Project Work Items"
date: 2026-03-07
author: "Tamir Dresher"
wave: null
tags: [squad, azure-devops, enterprise, platform-adapter, work-items, area-paths, iteration-paths]
status: published
hero: "Squad now speaks Azure DevOps natively — auto-detection, configurable work item types, area/iteration paths, and cross-project support for enterprise environments."
---

# Squad Goes Enterprise — Azure DevOps, Area Paths, and Cross-Project Work Items

> Blog post #23 — How Squad learned to work with enterprise ADO environments where nothing is "standard."

## The Problem

GitHub repos have issues. Simple. One repo, one issue tracker, one set of labels.

Enterprise Azure DevOps? Not so much. Your code might live in one project, your work items in another. Your org might use "Scenario" instead of "User Story." Your team's backlog is scoped by area paths. Your sprints use iteration paths. And there's no PAT to manage — you authenticate via `az login`.

Squad needed to understand all of this. Not just "detect ADO" — actually *work* in enterprise ADO environments where every project has its own rules.

## What Shipped

### Platform Auto-Detection

Squad reads your git remote URL and figures out where you are:

```
https://dev.azure.com/myorg/myproject/_git/myrepo → azure-devops
git@ssh.dev.azure.com:v3/myorg/myproject/myrepo → azure-devops
https://myorg.visualstudio.com/myproject/_git/myrepo → azure-devops
```

No configuration needed. `squad init` detects ADO and:
- Skips `.github/workflows/` generation (those don't run in ADO)
- Writes `"platform": "azure-devops"` to `.squad/config.json`
- Generates ADO-appropriate MCP config examples

### Configurable Work Item Types

Not every ADO project uses "User Story." Some use "Scenario," "Bug," or custom types locked down by org policy. Now you can configure it:

```json
{
"version": 1,
"platform": "azure-devops",
"ado": {
"defaultWorkItemType": "Scenario"
}
}
```

Squad uses your configured type for all work item creation — Ralph triage, agent task creation, everything.

### Area Paths — Route to the Right Team

In enterprise ADO, area paths determine which team's backlog a work item appears in. A work item in `"MyProject\Frontend"` shows up on the Frontend team's board. One in `"MyProject\Platform"` goes to Platform.

```json
{
"ado": {
"areaPath": "MyProject\\Team Alpha"
}
}
```

Now when Squad creates work items, they land on the right team's board — not lost in the root backlog.

### Iteration Paths — Sprint Placement

Same story for sprints. Enterprise teams plan in iterations, and work items need to appear in the right sprint:

```json
{
"ado": {
"iterationPath": "MyProject\\Sprint 5"
}
}
```

### Cross-Project Work Items — The Enterprise Killer Feature

Here's the one that matters most for large organizations: **your git repo and your work items might live in completely different ADO projects — or even different orgs.**

Common pattern in enterprise:
- **Code** lives in `Engineering/my-service` (locked-down project with strict CI)
- **Work items** live in `Planning/team-backlog` (PM-managed project with custom process templates)

Squad now supports this cleanly:

```json
{
"version": 1,
"platform": "azure-devops",
"ado": {
"org": "planning-org",
"project": "team-backlog",
"defaultWorkItemType": "Scenario",
"areaPath": "team-backlog\\Alpha Squad",
"iterationPath": "team-backlog\\2026-Q1\\Sprint 5"
}
}
```

When `ado.org` or `ado.project` are set, Squad uses them for all work item operations (create, query, tag, comment) while continuing to use the git remote's org/project for repo operations (branches, PRs, commits).

The WIQL queries, `az boards` commands, and Ralph's triage loop all respect this split.

## The Full Config Reference

All fields are optional. Omit any field to use the default.

| Field | Default | Description |
|-------|---------|-------------|
| `ado.org` | *(from git remote)* | ADO org for work items |
| `ado.project` | *(from git remote)* | ADO project for work items |
| `ado.defaultWorkItemType` | `"User Story"` | Type for new work items |
| `ado.areaPath` | *(project default)* | Team backlog routing |
| `ado.iterationPath` | *(project default)* | Sprint board placement |

## Security — No PATs Needed

Squad uses `az login` for authentication. No Personal Access Tokens to rotate, no secrets in config files. Your Azure CLI session handles everything.

For environments where MCP tools are available, Squad also supports the Azure DevOps MCP server for richer API access:

```json
{
"mcpServers": {
"azure-devops": {
"command": "npx",
"args": ["-y", "@azure/devops-mcp-server"]
}
}
}
```

## Security Hardening

The ADO adapter went through a thorough security review:

- **Shell injection prevention** — All `execSync` calls replaced with `execFileSync` (args as arrays, not concatenated strings)
- **WIQL injection prevention** — `escapeWiql()` helper doubles single-quotes in all user-supplied values
- **Bearer token protection** — Planner adapter passes tokens via `curl --config stdin` instead of CLI args (invisible to `ps aux`)

## What We Tested

External integration testing against real ADO environments (WDATP, OS, SquadDemo projects):

| Test | Result |
|------|--------|
| ADO project connectivity | ✅ |
| Repo discovery | ✅ |
| Branch creation | ✅ |
| Git clone + push | ✅ |
| Squad init (platform detection) | ✅ |
| PR creation + auto-complete | ✅ |
| PR read/list/comment | ✅ |
| Commit search | ✅ |
| Work item CRUD | ✅ |
| WIQL tag queries | ✅ |
| Cross-project work items | ✅ |

The only blockers encountered were project-specific restrictions (locked-down work item types in WDATP) — not Squad bugs.

## Ralph in ADO

Ralph's coordinator prompt is now platform-aware. When running against ADO, Ralph uses WIQL queries instead of GitHub issue queries:

```wiql
SELECT [System.Id] FROM WorkItems
WHERE [System.Tags] Contains 'squad'
AND [System.State] <> 'Closed'
AND [System.TeamProject] = 'team-backlog'
ORDER BY [System.CreatedDate] DESC
```

The full triage → assign → branch → PR → merge loop works end-to-end with ADO.

## Ralph + ADO: The Governance Fix

The coordinator prompt (`squad.agent.md`) is what tells Ralph *where* to look for work. Previously, it only had GitHub commands — `gh issue list`, `gh pr list`. Even if the ADO adapter was perfect, Ralph would still scan GitHub because that's what the governance file told it to do.

We fixed this at every level:
- **MCP detection** — Added `azure-devops-*` to the tool prefix table so the coordinator recognizes ADO MCP tools
- **Platform Detection section** — New section in the governance file explaining how to detect GitHub vs ADO from the git remote
- **Issue Awareness** — Now shows both GitHub and ADO queries, with instructions to read `.squad/config.json` first
- **Ralph Step 1** — Platform-aware scan with both GitHub and ADO command blocks, plus the critical instruction: *"Read `.squad/config.json` for the `ado` section FIRST — do NOT guess the ADO project from the repo name"*

This is the kind of bug that's invisible in unit tests — the code works, but the governance prompt doesn't tell the coordinator to use it.

## Getting Started

```bash
# 1. Install Squad
npm install -g @bradygaster/squad-cli

# 2. Clone your ADO repo
git clone https://dev.azure.com/your-org/your-project/_git/your-repo
cd your-repo

# 3. Make sure az CLI is set up
az login
az extension add --name azure-devops

# 4. Init Squad (auto-detects ADO)
squad init

# 5. Edit .squad/config.json if you need custom work item config
# 6. Start working!
```

Full documentation: [Enterprise Platforms Guide](../features/enterprise-platforms.md)

## What's Next

- **Process template introspection** — Auto-detect available work item types from the ADO process template (#240)
- **ADO webhook integration** — Real-time work item change notifications
- **Azure Pipelines scaffolding** — Generate pipeline YAML during `squad init` for ADO repos

---

*The enterprise doesn't bend to your tools. Your tools bend to the enterprise. Squad now does.*

PR: [#191 — Azure DevOps platform adapter](https://github.com/bradygaster/squad/pull/191)
Loading