Skip to content
Merged
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
77635b8
feat(cli): upgrade squad watch to full work monitor with --execute mo…
invalid-email-address Mar 30, 2026
8529c46
feat(cli): add opt-in watch features — board, monitoring, two-pass, w…
invalid-email-address Mar 30, 2026
9952a61
docs+tests: complete PR deliverables for watch work monitor (#708)
invalid-email-address Mar 30, 2026
6bccda9
fix: resolve CI failures — TypeScript .killed type + cspell vulns (#708)
invalid-email-address Mar 30, 2026
7130512
fix: address Squad review findings — execFile shell bug + twoPassScan…
invalid-email-address Mar 30, 2026
e28ec61
fix(test): bump help output line threshold for new watch flags (#708)
invalid-email-address Mar 30, 2026
efbad87
fix(test): use source path imports for watch-execute tests (#708)
invalid-email-address Mar 30, 2026
aaf9631
feat(watch): add PlatformAdapter abstraction for multi-platform suppo…
invalid-email-address Mar 30, 2026
642a6dc
refactor(watch): replace WatchPlatform with SDK PlatformAdapter
invalid-email-address Mar 31, 2026
93b9bf6
fix(test): add missing closing brace in watch-execute tests
invalid-email-address Mar 31, 2026
312fb77
refactor(watch): plugin-based capability system (#708)
invalid-email-address Mar 31, 2026
fcd42fe
fix(test): update import path for watch capability refactor (#708)
invalid-email-address Mar 31, 2026
e1056fe
fix: update package.json export path for watch directory (#708)
invalid-email-address Mar 31, 2026
6a44457
fix(test): update remaining watch import paths in ralph tests (#708)
invalid-email-address Mar 31, 2026
d5d078f
fix(test): handle subdirectory commands in wiring regression test
invalid-email-address Mar 31, 2026
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
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Added — Full Work Monitor for squad watch (#708)
- `--execute` flag spawns Copilot sessions to work on actionable issues autonomously
- Multi-platform support — auto-detects GitHub vs Azure DevOps from git remote URL
- Azure DevOps support: uses SDK PlatformAdapter for work items, tags, and PRs
- `--monitor-teams` / `--monitor-email` scan Teams/email for actionable items via WorkIQ
- `--board` enables project board lifecycle (In Progress → Done/Blocked + reconciliation)
- `--two-pass` lightweight scan then hydrate only actionable issues (saves API quota)
- `--wave-dispatch` parallel sub-task execution within issues (dependency-aware)
- `--retro` enforces retrospective checks (Fridays or when missed >7 days)
- `--decision-hygiene` auto-merges decision inbox when >5 files
- `--max-concurrent N` controls parallel issue execution (default: 1)
- `--timeout N` sets per-issue execution timeout in minutes (default: 30)
- `--copilot-flags "..."` passes extra flags to Copilot CLI sessions
- SubSquad discovery: automatically detects `.squad/subsquads/` for routing
- All features disabled by default — existing `squad watch` behavior unchanged

### Added — StorageProvider Abstraction Layer
- **StorageProvider interface** (#640) — pluggable I/O contract decoupling the runtime from `node:fs`
- **FSStorageProvider** (#640) — Node.js `fs` wrapper, default provider for CLI and local workflows
Expand Down
174 changes: 174 additions & 0 deletions docs/src/content/blog/watch-monitor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
---
title: "From Triage Bot to Work Monitor"
date: 2026-03-30
author: "Brady"
tags: [squad, ralph, watch, work-monitor, automation, execution]
status: published
hero: "Ralph started as a label router that idled when the board was clear. Now he spawns Copilot sessions and actually does the work."
---

# From Triage Bot to Work Monitor

> ⚠️ **Experimental** — Squad is alpha software. APIs, commands, and behavior may change between releases.

> _Ralph started as a label router that idled when the board was clear. Now he spawns Copilot sessions and actually does the work._

## What Changed

`squad watch` used to be a simple triage loop. Every N minutes, it would:

1. Fetch open issues with the `squad` label
2. Route them to team members based on routing rules
3. Add labels like `squad:eecom` or `squad:gnc`
4. Idle when done

That's it. Ralph was a label router — useful, but not autonomous. When the board cleared, Ralph just sat there waiting for humans to do the work.

**Issue #708 changed that.**

With `--execute`, Ralph transforms from a triage bot into a full work monitor. He doesn't just label issues — he spawns Copilot CLI sessions to actually work on them.

```bash
squad watch --execute --interval 15
```

This one flag turns Ralph from a watcher into a worker.

## The Unix Pipe Philosophy

The design follows the Unix philosophy: each flag is a composable feature that does one thing well.

- `--execute` → spawn Copilot sessions for actionable issues
- `--monitor-teams` → scan Teams messages via WorkIQ
- `--monitor-email` → scan email for alerts and action items
- `--board` → manage project board lifecycle (In Progress / Done / Blocked)
- `--two-pass` → lightweight scan, then hydrate only actionable issues
- `--wave-dispatch` → parallel sub-task execution within issues
- `--retro` → enforce retrospective checks (Fridays or >7 days)
- `--decision-hygiene` → auto-merge decision inbox when >5 files

Each flag is opt-in. Existing `squad watch` behavior is unchanged — triage only, no execution.

## Code Example: From Simple to Full Monitor

**Basic triage (original behavior):**
```bash
squad watch
```

**Add execution:**
```bash
squad watch --execute
```

**Add project board lifecycle:**
```bash
squad watch --execute --board
```

**Full monitor with all features:**
```bash
squad watch --execute \
--board \
--two-pass \
--monitor-teams \
--retro \
--decision-hygiene \
--max-concurrent 2 \
--interval 15
```

## Architecture of a Round

When all features are enabled, each round follows this cycle:

1. **Self-pull**: `git fetch && git pull --ff-only` to stay current
2. **Scan**: Fetch open issues (two-pass if enabled: lightweight list → hydrate actionable only)
3. **Triage**: Label untriaged issues based on routing rules
4. **Execute**: Spawn Copilot sessions for actionable issues
- Issues are actionable if: assigned to a squad member, not assigned to a human, and not blocked
- Wave dispatch groups sub-tasks by dependency and runs them in parallel
- Max concurrency controlled by `--max-concurrent N` (default: 1)
- Each issue gets a timeout (`--timeout N` minutes, default: 30)
5. **Board**: Update project board status columns
- Move claimed issues to "In Progress"
- Move completed issues to "Done"
- Reconcile mismatches (closed issues not in Done, open issues in Done)
6. **Monitor**: Scan Teams/email for new actionable items
- Teams: query WorkIQ for action items, reviews, urgent requests
- Email: query for CI failures, Dependabot alerts, security vulnerabilities
- Create GitHub issues with bridge labels (`teams-bridge`, `email-bridge`)
7. **Housekeep**: Governance checks
- Retro: if it's Friday after 14:00 UTC or last retro was >7 days ago, spawn a retro session
- Decision hygiene: if `.squad/decisions/inbox/` has >5 files, spawn a merge session
8. **Report**: Log round summary, sleep until next interval

## Example Execution Output

```
🔄 Ralph — Round 1
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔴 Untriaged: 2
🟡 Assigned: 5
🚀 Executed: 3

▶ [14:23:10] Executing #42 "Fix auth redirect bug" → gh copilot --message "Work on issue #42..."
✓ [14:25:43] #42 completed

▶ [14:25:44] Executing #45 "Add retry logic" → gh copilot --message "Work on issue #45..."
✓ [14:28:20] #45 completed

▶ [14:28:21] Executing #47 "Update docs" → gh copilot --message "Work on issue #47..."
✗ [14:58:21] #47 failed: Timed out after 30m

[14:58:22] Two-pass: 15 total → 3 actionable (hydrated)
[14:58:23] Board: #42 → Done
[14:58:23] Board: #45 → Done
✓ [14:58:24] Teams monitor scan complete
✓ [14:58:25] Email monitor scan complete
[14:58:26] Round 1 complete — sleeping 15 minutes
```

## The Three Layers of Ralph

| Layer | When | How |
|-------|------|-----|
| **In-session** | You're at the keyboard | "Ralph, go" — active loop while work exists |
| **Local watchdog** | You're away but machine is on | `squad watch --execute` |
| **Cloud heartbeat** | Fully unattended | `squad-heartbeat.yml` GitHub Actions events |

The in-session loop is ephemeral — it lives only while the Copilot session is active. The local watchdog runs as a separate process and polls at your chosen interval. The cloud heartbeat is the fully unattended layer that triggers on GitHub events (issue close, PR merge, manual dispatch).

## Why This Matters

Before #708, Ralph was a coordinator. He routed work to team members but never picked up the tools himself.

Now, Ralph is a worker. He claims issues, posts comments, spawns Copilot sessions, manages the project board, scans Teams and email, and enforces governance checks.

This closes the gap between "someone triaged this issue" and "someone is working on this issue." Ralph doesn't just label the work — he starts it.

## What's Next

The next iteration will add:

- **SubSquad discovery**: automatically detect `.squad/subsquads/` for routing across multiple codebases
- **Channel routing**: route notifications to specific Teams channels based on work type
- **Multi-machine coordination**: distribute work across multiple Ralph instances

Ralph is no longer just a triage bot. He's a work monitor — and he's just getting started.

---

**Try it:**
```bash
squad watch --execute --interval 15
```

**Full feature set:**
```bash
squad watch --execute --board --two-pass --monitor-teams --retro --decision-hygiene --max-concurrent 2
```

---

_PR #709 · Issue #708 · Shipped 2026-03-30_
153 changes: 151 additions & 2 deletions docs/src/content/docs/features/ralph.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,11 @@ Ralph does **not** ask permission to continue — he keeps working. The only thi

## Watch Mode (`squad watch`)

Ralph's in-session loop processes work while it exists, then idles. For **persistent polling** when you're away from the keyboard, run the `squad watch` command in a separate terminal:
Ralph's in-session loop processes work while it exists, then idles. For **persistent polling** when you're away from the keyboard, run the `squad watch` command in a separate terminal.

### Triage Mode (Default)

Basic usage — triage only, no execution:

```bash
squad watch # polls every 10 minutes (default)
Expand All @@ -204,12 +208,157 @@ This runs as a standalone local process (not inside Copilot) that:
- Assigns @copilot to `squad:copilot` issues (if auto-assign is enabled)
- Runs until Ctrl+C

### Full Work Monitor Mode (`--execute`)

Add `--execute` to transform Ralph from a triage bot into a full work monitor that spawns Copilot sessions and actually does the work:

```bash
squad watch --execute # basic work monitor
squad watch --execute --interval 15 # check every 15 minutes
squad watch --execute --max-concurrent 2 # work on 2 issues in parallel
```

When `--execute` is enabled, Ralph spawns Copilot CLI sessions for actionable issues (assigned to a squad member, not blocked, not already assigned to a human).

**Example execution output:**

```
🔄 Ralph — Round 1
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔴 Untriaged: 2
🟡 Assigned: 5
🚀 Executed: 3

▶ [14:23:10] Executing #42 "Fix auth redirect bug" → gh copilot --message "Work on issue #42..."
✓ [14:25:43] #42 completed
▶ [14:25:44] Executing #45 "Add retry logic" → gh copilot --message "Work on issue #45..."
✓ [14:28:20] #45 completed
```

### All Watch Flags

All new features are **opt-in** and disabled by default. Existing `squad watch` behavior is unchanged.

#### Execution Control

| Flag | Description | Example |
|------|-------------|---------|
| `--execute` | Enable work execution (spawn Copilot to work on issues) | `squad watch --execute` |
| `--max-concurrent N` | Max parallel issues per round (default: 1) | `squad watch --execute --max-concurrent 3` |
| `--timeout N` | Per-issue timeout in minutes (default: 30) | `squad watch --execute --timeout 45` |
| `--copilot-flags "..."` | Pass extra flags to Copilot CLI | `squad watch --execute --copilot-flags "--model gpt-4"` |

#### Issue Scanning

| Flag | Description | Example |
|------|-------------|---------|
| `--two-pass` | Lightweight list → hydrate actionable only (saves API quota) | `squad watch --two-pass` |
| `--wave-dispatch` | Parallel sub-task execution within issues (dependency-aware) | `squad watch --execute --wave-dispatch` |

#### Communication Bridges

| Flag | Description | Example |
|------|-------------|---------|
| `--monitor-teams` | Scan Teams for actionable messages each round (requires WorkIQ MCP) | `squad watch --monitor-teams` |
| `--monitor-email` | Scan email for alerts and action items each round (requires WorkIQ MCP) | `squad watch --monitor-email` |

#### Project Board Lifecycle

| Flag | Description | Example |
|------|-------------|---------|
| `--board` | Enable project board lifecycle (In Progress / Done / Blocked + reconciliation) | `squad watch --board` |
| `--board-project N` | Project board number (default: 1) | `squad watch --board --board-project 2` |

#### Housekeeping & Governance

| Flag | Description | Example |
|------|-------------|---------|
| `--retro` | Enforce retrospective checks (Fridays or when missed >7 days) | `squad watch --retro` |
| `--decision-hygiene` | Auto-merge decision inbox when >5 files | `squad watch --decision-hygiene` |
| `--channel-routing` | Route notifications to specific Teams channels (requires `.squad/teams-channels.json`) | `squad watch --channel-routing` |

### Common Workflows

**Basic triage + work execution:**
```bash
squad watch --execute --interval 10
```

**Full monitor with all features:**
```bash
squad watch --execute --board --two-pass --monitor-teams --retro --decision-hygiene --max-concurrent 2 --interval 15
```

**Cost-conscious (two-pass, lower concurrency):**
```bash
squad watch --execute --two-pass --max-concurrent 1 --timeout 20
```

**Teams + email bridge only (no issue execution):**
```bash
squad watch --monitor-teams --monitor-email --interval 5
```

### Round Cycle (Full Monitor)

When all features are enabled, each round follows this cycle:

1. **Self-pull**: `git fetch && git pull --ff-only` to stay current
2. **Scan**: Fetch open issues (two-pass if enabled)
3. **Triage**: Label untriaged issues based on routing rules
4. **Execute**: Spawn Copilot sessions for actionable issues (wave dispatch if enabled)
5. **Board**: Update project board status, reconcile mismatches
6. **Monitor**: Scan Teams/email for new actionable items
7. **Housekeep**: Check for retro, merge decision inbox if needed
8. **Report**: Log round summary, sleep until next interval

### Advanced: `--agent-cmd` (Hidden Flag)

For advanced users who know what they're doing:

```bash
squad watch --execute --agent-cmd "custom-agent-wrapper"
```

This fully overrides the agent command. The default is `gh copilot --message "<prompt>"` plus any `--copilot-flags`. Use this to plug in custom agent wrappers or alternative Copilot entry points.

### Azure DevOps Support

Ralph supports Azure DevOps repos and work items via the SDK's PlatformAdapter. When your git remote points to `dev.azure.com` or `visualstudio.com`, Ralph auto-detects ADO — no flag needed.

**Setup:**

1. Install Azure CLI: `az extension add --name azure-devops`
2. Authenticate: `az login`
3. Add ADO config to `.squad/config.json`:
```json
{
"platform": "ado",
"ado": {
"org": "YOUR_ORG",
"project": "YOUR_PROJECT"
}
}
```

**Usage:**
```bash
squad watch # auto-detects from git remote
squad watch --execute # full work monitor (auto-detects platform)
```

**Key differences from GitHub:**
- ADO uses **tags** instead of labels — `squad:data` becomes a tag on the work item
- ADO uses `az boards` CLI instead of `gh` — Ralph checks `az` availability
- ADO rate limiting is handled differently — the circuit breaker skips quota checks
- ADO PRs don't expose `statusCheckRollup` — CI status columns may be empty

### Three layers of Ralph

| Layer | When | How |
|-------|------|-----|
| **In-session** | You're at the keyboard | "Ralph, go" — active loop while work exists |
| **Local watchdog** | You're away but machine is on | `squad watch --interval 10` |
| **Local watchdog** | You're away but machine is on | `squad watch --interval 10` (triage) or `squad watch --execute` (full monitor) |
| **Cloud heartbeat** | Fully unattended | `squad-heartbeat.yml` GitHub Actions events (issue close, PR merge, manual dispatch) |

## Ralph's Board View
Expand Down
11 changes: 11 additions & 0 deletions docs/src/content/docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ squad init
| `squad link <team-repo-path>` | Link project to a remote team root | Yes |
| `squad triage` | Auto-triage issues and assign to team (primary name; `watch` is an alias) | Yes |
| `squad triage --interval <min>` | Continuous triage (default: every 10 min) | Yes |
| `squad watch --execute` | Enable work execution (spawn Copilot to work on issues) | Yes |
| `squad watch --monitor-teams` | Scan Teams for actionable messages each round | Yes |
| `squad watch --monitor-email` | Scan email for alerts and action items each round | Yes |
| `squad watch --board` | Enable project board lifecycle management | Yes |
| `squad watch --two-pass` | Use two-pass scanning (lightweight → hydrate) | Yes |
| `squad watch --wave-dispatch` | Parallel sub-task execution within issues | Yes |
| `squad watch --retro` | Enforce retrospective checks | Yes |
| `squad watch --decision-hygiene` | Auto-merge decision inbox | Yes |
| `squad watch --max-concurrent N` | Max parallel issues per round (default: 1) | Yes |
| `squad watch --timeout N` | Per-issue timeout in minutes (default: 30) | Yes |
| `squad watch --copilot-flags "..."` | Extra flags for Copilot CLI | Yes |
| `squad copilot` | Add the @copilot coding agent to the team | Yes |
| `squad copilot --off` | Remove @copilot from the team | Yes |
| `squad copilot --auto-assign` | Enable auto-assignment for @copilot | Yes |
Expand Down
4 changes: 2 additions & 2 deletions packages/squad-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@
"import": "./dist/cli/commands/init-remote.js"
},
"./commands/watch": {
"types": "./dist/cli/commands/watch.d.ts",
"import": "./dist/cli/commands/watch.js"
"types": "./dist/cli/commands/watch/index.d.ts",
"import": "./dist/cli/commands/watch/index.js"
},
"./commands/start": {
"types": "./dist/cli/commands/start.d.ts",
Expand Down
Loading
Loading