@bradygaster/squad-sdk 0.8.25 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +296 -296
- package/dist/adapter/client.d.ts +17 -0
- package/dist/adapter/client.d.ts.map +1 -1
- package/dist/adapter/client.js +101 -1
- package/dist/adapter/client.js.map +1 -1
- package/dist/agents/history-shadow.d.ts.map +1 -1
- package/dist/agents/history-shadow.js +129 -62
- package/dist/agents/history-shadow.js.map +1 -1
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +2 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/model-selector.d.ts +2 -0
- package/dist/agents/model-selector.d.ts.map +1 -1
- package/dist/agents/model-selector.js +41 -35
- package/dist/agents/model-selector.js.map +1 -1
- package/dist/agents/personal.d.ts +35 -0
- package/dist/agents/personal.d.ts.map +1 -0
- package/dist/agents/personal.js +67 -0
- package/dist/agents/personal.js.map +1 -0
- package/dist/build/github-dist.js +42 -42
- package/dist/builders/index.d.ts +3 -2
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/builders/index.js +28 -0
- package/dist/builders/index.js.map +1 -1
- package/dist/builders/types.d.ts +13 -0
- package/dist/builders/types.d.ts.map +1 -1
- package/dist/config/init.d.ts +8 -0
- package/dist/config/init.d.ts.map +1 -1
- package/dist/config/init.js +304 -193
- package/dist/config/init.js.map +1 -1
- package/dist/config/models.d.ts +112 -0
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +329 -18
- package/dist/config/models.js.map +1 -1
- package/dist/coordinator/index.js +2 -2
- package/dist/coordinator/index.js.map +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/platform/azure-devops.d.ts +42 -0
- package/dist/platform/azure-devops.d.ts.map +1 -1
- package/dist/platform/azure-devops.js +75 -0
- package/dist/platform/azure-devops.js.map +1 -1
- package/dist/platform/comms-file-log.d.ts.map +1 -1
- package/dist/platform/comms-file-log.js +2 -1
- package/dist/platform/comms-file-log.js.map +1 -1
- package/dist/platform/index.d.ts +2 -1
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/index.js +1 -0
- package/dist/platform/index.js.map +1 -1
- package/dist/ralph/capabilities.d.ts +67 -0
- package/dist/ralph/capabilities.d.ts.map +1 -0
- package/dist/ralph/capabilities.js +111 -0
- package/dist/ralph/capabilities.js.map +1 -0
- package/dist/ralph/index.d.ts +2 -0
- package/dist/ralph/index.d.ts.map +1 -1
- package/dist/ralph/index.js +6 -5
- package/dist/ralph/index.js.map +1 -1
- package/dist/ralph/rate-limiting.d.ts +99 -0
- package/dist/ralph/rate-limiting.d.ts.map +1 -0
- package/dist/ralph/rate-limiting.js +170 -0
- package/dist/ralph/rate-limiting.js.map +1 -0
- package/dist/resolution.d.ts +24 -2
- package/dist/resolution.d.ts.map +1 -1
- package/dist/resolution.js +106 -6
- package/dist/resolution.js.map +1 -1
- package/dist/roles/catalog-categories.d.ts +146 -0
- package/dist/roles/catalog-categories.d.ts.map +1 -0
- package/dist/roles/catalog-categories.js +374 -0
- package/dist/roles/catalog-categories.js.map +1 -0
- package/dist/roles/catalog-engineering.d.ts +212 -0
- package/dist/roles/catalog-engineering.d.ts.map +1 -0
- package/dist/roles/catalog-engineering.js +549 -0
- package/dist/roles/catalog-engineering.js.map +1 -0
- package/dist/roles/catalog.d.ts +24 -0
- package/dist/roles/catalog.d.ts.map +1 -0
- package/dist/roles/catalog.js +28 -0
- package/dist/roles/catalog.js.map +1 -0
- package/dist/roles/index.d.ts +69 -0
- package/dist/roles/index.d.ts.map +1 -0
- package/dist/roles/index.js +197 -0
- package/dist/roles/index.js.map +1 -0
- package/dist/roles/types.d.ts +87 -0
- package/dist/roles/types.d.ts.map +1 -0
- package/dist/roles/types.js +14 -0
- package/dist/roles/types.js.map +1 -0
- package/dist/runtime/benchmarks.js +5 -5
- package/dist/runtime/benchmarks.js.map +1 -1
- package/dist/runtime/constants.d.ts +2 -2
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +5 -3
- package/dist/runtime/constants.js.map +1 -1
- package/dist/runtime/cross-squad.d.ts +118 -0
- package/dist/runtime/cross-squad.d.ts.map +1 -0
- package/dist/runtime/cross-squad.js +234 -0
- package/dist/runtime/cross-squad.js.map +1 -0
- package/dist/runtime/otel-init.d.ts +24 -17
- package/dist/runtime/otel-init.d.ts.map +1 -1
- package/dist/runtime/otel-init.js +29 -20
- package/dist/runtime/otel-init.js.map +1 -1
- package/dist/runtime/otel-metrics.d.ts +5 -0
- package/dist/runtime/otel-metrics.d.ts.map +1 -1
- package/dist/runtime/otel-metrics.js +54 -0
- package/dist/runtime/otel-metrics.js.map +1 -1
- package/dist/runtime/rework.d.ts +71 -0
- package/dist/runtime/rework.d.ts.map +1 -0
- package/dist/runtime/rework.js +107 -0
- package/dist/runtime/rework.js.map +1 -0
- package/dist/runtime/scheduler.d.ts +128 -0
- package/dist/runtime/scheduler.d.ts.map +1 -0
- package/dist/runtime/scheduler.js +427 -0
- package/dist/runtime/scheduler.js.map +1 -0
- package/dist/runtime/squad-observer.d.ts.map +1 -1
- package/dist/runtime/squad-observer.js +4 -0
- package/dist/runtime/squad-observer.js.map +1 -1
- package/dist/runtime/streaming.d.ts +2 -0
- package/dist/runtime/streaming.d.ts.map +1 -1
- package/dist/runtime/streaming.js +6 -0
- package/dist/runtime/streaming.js.map +1 -1
- package/dist/runtime/telemetry.d.ts +2 -0
- package/dist/runtime/telemetry.d.ts.map +1 -1
- package/dist/runtime/telemetry.js +6 -0
- package/dist/runtime/telemetry.js.map +1 -1
- package/dist/sharing/consult.d.ts +2 -2
- package/dist/sharing/consult.js +83 -83
- package/dist/sharing/consult.js.map +1 -1
- package/dist/sharing/export.d.ts.map +1 -1
- package/dist/sharing/export.js +17 -4
- package/dist/sharing/export.js.map +1 -1
- package/dist/skills/handler-types.d.ts +271 -0
- package/dist/skills/handler-types.d.ts.map +1 -0
- package/dist/skills/handler-types.js +31 -0
- package/dist/skills/handler-types.js.map +1 -0
- package/dist/skills/index.d.ts +3 -0
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +3 -0
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/skill-script-loader.d.ts +65 -0
- package/dist/skills/skill-script-loader.d.ts.map +1 -0
- package/dist/skills/skill-script-loader.js +227 -0
- package/dist/skills/skill-script-loader.js.map +1 -0
- package/dist/skills/skill-source.d.ts.map +1 -1
- package/dist/skills/skill-source.js +5 -1
- package/dist/skills/skill-source.js.map +1 -1
- package/dist/tools/index.d.ts +10 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +49 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/upstream/resolver.d.ts.map +1 -1
- package/dist/upstream/resolver.js +14 -5
- package/dist/upstream/resolver.js.map +1 -1
- package/package.json +34 -3
- package/templates/casting/Futurama.json +10 -0
- package/templates/casting-history.json +4 -4
- package/templates/casting-policy.json +37 -35
- package/templates/casting-reference.md +104 -0
- package/templates/casting-registry.json +3 -3
- package/templates/ceremonies.md +41 -41
- package/templates/charter.md +53 -53
- package/templates/constraint-tracking.md +38 -38
- package/templates/cooperative-rate-limiting.md +229 -0
- package/templates/copilot-instructions.md +46 -46
- package/templates/history.md +10 -10
- package/templates/identity/now.md +9 -9
- package/templates/identity/wisdom.md +15 -15
- package/templates/issue-lifecycle.md +412 -0
- package/templates/keda-scaler.md +164 -0
- package/templates/machine-capabilities.md +75 -0
- package/templates/mcp-config.md +90 -98
- package/templates/multi-agent-format.md +28 -28
- package/templates/orchestration-log.md +27 -27
- package/templates/package.json +3 -0
- package/templates/plugin-marketplace.md +49 -49
- package/templates/ralph-circuit-breaker.md +313 -0
- package/templates/ralph-triage.js +543 -0
- package/templates/raw-agent-output.md +37 -37
- package/templates/roster.md +60 -60
- package/templates/routing.md +39 -54
- package/templates/run-output.md +50 -50
- package/templates/schedule.json +19 -0
- package/templates/scribe-charter.md +119 -119
- package/templates/skill.md +24 -24
- package/templates/skills/agent-collaboration/SKILL.md +42 -0
- package/templates/skills/agent-conduct/SKILL.md +24 -0
- package/templates/skills/architectural-proposals/SKILL.md +151 -0
- package/templates/skills/ci-validation-gates/SKILL.md +84 -0
- package/templates/skills/cli-wiring/SKILL.md +47 -0
- package/templates/skills/client-compatibility/SKILL.md +89 -0
- package/templates/skills/cross-squad/SKILL.md +114 -0
- package/templates/skills/distributed-mesh/SKILL.md +287 -0
- package/templates/skills/distributed-mesh/mesh.json.example +30 -0
- package/templates/skills/distributed-mesh/sync-mesh.ps1 +111 -0
- package/templates/skills/distributed-mesh/sync-mesh.sh +104 -0
- package/templates/skills/docs-standards/SKILL.md +71 -0
- package/templates/skills/economy-mode/SKILL.md +114 -0
- package/templates/skills/external-comms/SKILL.md +329 -0
- package/templates/skills/gh-auth-isolation/SKILL.md +183 -0
- package/templates/skills/git-workflow/SKILL.md +204 -0
- package/templates/skills/github-multi-account/SKILL.md +95 -0
- package/templates/skills/history-hygiene/SKILL.md +36 -0
- package/templates/skills/humanizer/SKILL.md +105 -0
- package/templates/skills/init-mode/SKILL.md +102 -0
- package/templates/skills/model-selection/SKILL.md +117 -0
- package/templates/skills/nap/SKILL.md +24 -0
- package/templates/skills/personal-squad/SKILL.md +57 -0
- package/templates/skills/project-conventions/SKILL.md +56 -56
- package/templates/skills/release-process/SKILL.md +423 -0
- package/templates/skills/reskill/SKILL.md +92 -0
- package/templates/skills/reviewer-protocol/SKILL.md +79 -0
- package/templates/skills/secret-handling/SKILL.md +200 -0
- package/templates/skills/session-recovery/SKILL.md +155 -0
- package/templates/skills/squad-conventions/SKILL.md +69 -0
- package/templates/skills/test-discipline/SKILL.md +37 -0
- package/templates/skills/windows-compatibility/SKILL.md +74 -0
- package/templates/squad.agent.md +1287 -1146
- package/templates/workflows/squad-ci.yml +24 -24
- package/templates/workflows/squad-docs.yml +54 -50
- package/templates/workflows/squad-heartbeat.yml +171 -316
- package/templates/workflows/squad-insider-release.yml +61 -61
- package/templates/workflows/squad-issue-assign.yml +161 -161
- package/templates/workflows/squad-label-enforce.yml +181 -181
- package/templates/workflows/squad-preview.yml +55 -55
- package/templates/workflows/squad-promote.yml +120 -120
- package/templates/workflows/squad-release.yml +77 -77
- package/templates/workflows/squad-triage.yml +260 -260
- package/templates/workflows/sync-squad-labels.yml +169 -169
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
# Issue Lifecycle — Repo Connection & PR Flow
|
|
2
|
+
|
|
3
|
+
Reference for connecting Squad to a repository and managing the issue→branch→PR→merge lifecycle.
|
|
4
|
+
|
|
5
|
+
## Repo Connection Format
|
|
6
|
+
|
|
7
|
+
When connecting Squad to an issue tracker, store the connection in `.squad/team.md`:
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
## Issue Source
|
|
11
|
+
|
|
12
|
+
**Repository:** {owner}/{repo}
|
|
13
|
+
**Connected:** {date}
|
|
14
|
+
**Platform:** {GitHub | Azure DevOps | Planner}
|
|
15
|
+
**Filters:**
|
|
16
|
+
- Labels: `{label-filter}`
|
|
17
|
+
- Project: `{project-name}` (ADO/Planner only)
|
|
18
|
+
- Plan: `{plan-id}` (Planner only)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Detection triggers:**
|
|
22
|
+
- User says "connect to {repo}"
|
|
23
|
+
- User says "monitor {repo} for issues"
|
|
24
|
+
- Ralph is activated without an issue source
|
|
25
|
+
|
|
26
|
+
## Platform-Specific Issue States
|
|
27
|
+
|
|
28
|
+
Each platform tracks issue lifecycle differently. Squad normalizes these into a common board state.
|
|
29
|
+
|
|
30
|
+
### GitHub
|
|
31
|
+
|
|
32
|
+
| GitHub State | GitHub API Fields | Squad Board State |
|
|
33
|
+
|--------------|-------------------|-------------------|
|
|
34
|
+
| Open, no assignee | `state: open`, `assignee: null` | `untriaged` |
|
|
35
|
+
| Open, assigned, no branch | `state: open`, `assignee: @user`, no linked PR | `assigned` |
|
|
36
|
+
| Open, branch exists | `state: open`, linked branch exists | `inProgress` |
|
|
37
|
+
| Open, PR opened | `state: open`, PR exists, `reviewDecision: null` | `needsReview` |
|
|
38
|
+
| Open, PR approved | `state: open`, PR `reviewDecision: APPROVED` | `readyToMerge` |
|
|
39
|
+
| Open, changes requested | `state: open`, PR `reviewDecision: CHANGES_REQUESTED` | `changesRequested` |
|
|
40
|
+
| Open, CI failure | `state: open`, PR `statusCheckRollup: FAILURE` | `ciFailure` |
|
|
41
|
+
| Closed | `state: closed` | `done` |
|
|
42
|
+
|
|
43
|
+
**Issue labels used by Squad:**
|
|
44
|
+
- `squad` — Issue is in Squad backlog
|
|
45
|
+
- `squad:{member}` — Assigned to specific agent
|
|
46
|
+
- `squad:untriaged` — Needs triage
|
|
47
|
+
- `go:needs-research` — Needs investigation before implementation
|
|
48
|
+
- `priority:p{N}` — Priority level (0=critical, 1=high, 2=medium, 3=low)
|
|
49
|
+
- `next-up` — Queued for next agent pickup
|
|
50
|
+
|
|
51
|
+
**Branch naming convention:**
|
|
52
|
+
```
|
|
53
|
+
squad/{issue-number}-{kebab-case-slug}
|
|
54
|
+
```
|
|
55
|
+
Example: `squad/42-fix-login-validation`
|
|
56
|
+
|
|
57
|
+
### Azure DevOps
|
|
58
|
+
|
|
59
|
+
| ADO State | Squad Board State |
|
|
60
|
+
|-----------|-------------------|
|
|
61
|
+
| New | `untriaged` |
|
|
62
|
+
| Active, no branch | `assigned` |
|
|
63
|
+
| Active, branch exists | `inProgress` |
|
|
64
|
+
| Active, PR opened | `needsReview` |
|
|
65
|
+
| Active, PR approved | `readyToMerge` |
|
|
66
|
+
| Resolved | `done` |
|
|
67
|
+
| Closed | `done` |
|
|
68
|
+
|
|
69
|
+
**Work item tags used by Squad:**
|
|
70
|
+
- `squad` — Work item is in Squad backlog
|
|
71
|
+
- `squad:{member}` — Assigned to specific agent
|
|
72
|
+
|
|
73
|
+
**Branch naming convention:**
|
|
74
|
+
```
|
|
75
|
+
squad/{work-item-id}-{kebab-case-slug}
|
|
76
|
+
```
|
|
77
|
+
Example: `squad/1234-add-auth-module`
|
|
78
|
+
|
|
79
|
+
### Microsoft Planner
|
|
80
|
+
|
|
81
|
+
Planner does not have native Git integration. Squad uses Planner for task tracking and GitHub/ADO for code management.
|
|
82
|
+
|
|
83
|
+
| Planner Status | Squad Board State |
|
|
84
|
+
|----------------|-------------------|
|
|
85
|
+
| Not Started | `untriaged` |
|
|
86
|
+
| In Progress, no PR | `inProgress` |
|
|
87
|
+
| In Progress, PR opened | `needsReview` |
|
|
88
|
+
| Completed | `done` |
|
|
89
|
+
|
|
90
|
+
**Planner→Git workflow:**
|
|
91
|
+
1. Task created in Planner bucket
|
|
92
|
+
2. Agent reads task from Planner
|
|
93
|
+
3. Agent creates branch in GitHub/ADO repo
|
|
94
|
+
4. Agent opens PR referencing Planner task ID in description
|
|
95
|
+
5. Agent marks task as "Completed" when PR merges
|
|
96
|
+
|
|
97
|
+
## Issue → Branch → PR → Merge Lifecycle
|
|
98
|
+
|
|
99
|
+
### 1. Issue Assignment (Triage)
|
|
100
|
+
|
|
101
|
+
**Trigger:** Ralph detects an untriaged issue or user manually assigns work.
|
|
102
|
+
|
|
103
|
+
**Actions:**
|
|
104
|
+
1. Read `.squad/routing.md` to determine which agent should handle the issue
|
|
105
|
+
2. Apply `squad:{member}` label (GitHub) or tag (ADO)
|
|
106
|
+
3. Transition issue to `assigned` state
|
|
107
|
+
4. Optionally spawn agent immediately if issue is high-priority
|
|
108
|
+
|
|
109
|
+
**Issue read command:**
|
|
110
|
+
```bash
|
|
111
|
+
# GitHub
|
|
112
|
+
gh issue view {number} --json number,title,body,labels,assignees
|
|
113
|
+
|
|
114
|
+
# Azure DevOps
|
|
115
|
+
az boards work-item show --id {id} --output json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 2. Branch Creation (Start Work)
|
|
119
|
+
|
|
120
|
+
**Trigger:** Agent accepts issue assignment and begins work.
|
|
121
|
+
|
|
122
|
+
**Actions:**
|
|
123
|
+
1. Ensure working on latest base branch (usually `main` or `dev`)
|
|
124
|
+
2. Create feature branch using Squad naming convention
|
|
125
|
+
3. Transition issue to `inProgress` state
|
|
126
|
+
|
|
127
|
+
**Branch creation commands:**
|
|
128
|
+
|
|
129
|
+
**Standard (single-agent, no parallelism):**
|
|
130
|
+
```bash
|
|
131
|
+
git checkout main && git pull && git checkout -b squad/{issue-number}-{slug}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Worktree (parallel multi-agent):**
|
|
135
|
+
```bash
|
|
136
|
+
git worktree add ../worktrees/{issue-number} -b squad/{issue-number}-{slug}
|
|
137
|
+
cd ../worktrees/{issue-number}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
> **Note:** Worktree support is in progress (#525). Current implementation uses standard checkout.
|
|
141
|
+
|
|
142
|
+
### 3. Implementation & Commit
|
|
143
|
+
|
|
144
|
+
**Actions:**
|
|
145
|
+
1. Agent makes code changes
|
|
146
|
+
2. Commits reference the issue number
|
|
147
|
+
3. Pushes branch to remote
|
|
148
|
+
|
|
149
|
+
**Commit message format:**
|
|
150
|
+
```
|
|
151
|
+
{type}({scope}): {description} (#{issue-number})
|
|
152
|
+
|
|
153
|
+
{detailed explanation if needed}
|
|
154
|
+
|
|
155
|
+
{breaking change notice if applicable}
|
|
156
|
+
|
|
157
|
+
Closes #{issue-number}
|
|
158
|
+
|
|
159
|
+
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Commit types:** `feat`, `fix`, `docs`, `refactor`, `test`, `chore`, `perf`, `style`, `build`, `ci`
|
|
163
|
+
|
|
164
|
+
**Push command:**
|
|
165
|
+
```bash
|
|
166
|
+
git push -u origin squad/{issue-number}-{slug}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 4. PR Creation
|
|
170
|
+
|
|
171
|
+
**Trigger:** Agent completes implementation and is ready for review.
|
|
172
|
+
|
|
173
|
+
**Actions:**
|
|
174
|
+
1. Open PR from feature branch to base branch
|
|
175
|
+
2. Reference issue in PR description
|
|
176
|
+
3. Apply labels if needed
|
|
177
|
+
4. Transition issue to `needsReview` state
|
|
178
|
+
|
|
179
|
+
**PR creation commands:**
|
|
180
|
+
|
|
181
|
+
**GitHub:**
|
|
182
|
+
```bash
|
|
183
|
+
gh pr create --title "{title}" \
|
|
184
|
+
--body "Closes #{issue-number}\n\n{description}" \
|
|
185
|
+
--head squad/{issue-number}-{slug} \
|
|
186
|
+
--base main
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Azure DevOps:**
|
|
190
|
+
```bash
|
|
191
|
+
az repos pr create --title "{title}" \
|
|
192
|
+
--description "Closes #{work-item-id}\n\n{description}" \
|
|
193
|
+
--source-branch squad/{work-item-id}-{slug} \
|
|
194
|
+
--target-branch main
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**PR description template:**
|
|
198
|
+
```markdown
|
|
199
|
+
Closes #{issue-number}
|
|
200
|
+
|
|
201
|
+
## Summary
|
|
202
|
+
{what changed}
|
|
203
|
+
|
|
204
|
+
## Changes
|
|
205
|
+
- {change 1}
|
|
206
|
+
- {change 2}
|
|
207
|
+
|
|
208
|
+
## Testing
|
|
209
|
+
{how this was tested}
|
|
210
|
+
|
|
211
|
+
{If working as a squad member:}
|
|
212
|
+
Working as {member} ({role})
|
|
213
|
+
|
|
214
|
+
{If needs human review:}
|
|
215
|
+
⚠️ This task was flagged as "needs review" — please have a squad member review before merging.
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 5. PR Review & Updates
|
|
219
|
+
|
|
220
|
+
**Review states:**
|
|
221
|
+
- **Approved** → `readyToMerge`
|
|
222
|
+
- **Changes requested** → `changesRequested`
|
|
223
|
+
- **CI failure** → `ciFailure`
|
|
224
|
+
|
|
225
|
+
**When changes are requested:**
|
|
226
|
+
1. Agent addresses feedback
|
|
227
|
+
2. Commits fixes to the same branch
|
|
228
|
+
3. Pushes updates
|
|
229
|
+
4. Requests re-review
|
|
230
|
+
|
|
231
|
+
**Update workflow:**
|
|
232
|
+
```bash
|
|
233
|
+
# Make changes
|
|
234
|
+
git add .
|
|
235
|
+
git commit -m "fix: address review feedback"
|
|
236
|
+
git push
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Re-request review (GitHub):**
|
|
240
|
+
```bash
|
|
241
|
+
gh pr ready {pr-number}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### 6. PR Merge
|
|
245
|
+
|
|
246
|
+
**Trigger:** PR is approved and CI passes.
|
|
247
|
+
|
|
248
|
+
**Merge strategies:**
|
|
249
|
+
|
|
250
|
+
**GitHub (merge commit):**
|
|
251
|
+
```bash
|
|
252
|
+
gh pr merge {pr-number} --merge --delete-branch
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**GitHub (squash):**
|
|
256
|
+
```bash
|
|
257
|
+
gh pr merge {pr-number} --squash --delete-branch
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Azure DevOps:**
|
|
261
|
+
```bash
|
|
262
|
+
az repos pr update --id {pr-id} --status completed --delete-source-branch true
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Post-merge actions:**
|
|
266
|
+
1. Issue automatically closes (if "Closes #{number}" is in PR description)
|
|
267
|
+
2. Feature branch is deleted
|
|
268
|
+
3. Squad board state transitions to `done`
|
|
269
|
+
4. Worktree cleanup (if worktree was used — #525)
|
|
270
|
+
|
|
271
|
+
### 7. Cleanup
|
|
272
|
+
|
|
273
|
+
**Standard workflow cleanup:**
|
|
274
|
+
```bash
|
|
275
|
+
git checkout main
|
|
276
|
+
git pull
|
|
277
|
+
git branch -d squad/{issue-number}-{slug}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Worktree cleanup (future, #525):**
|
|
281
|
+
```bash
|
|
282
|
+
cd {original-cwd}
|
|
283
|
+
git worktree remove ../worktrees/{issue-number}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Spawn Prompt Additions for Issue Work
|
|
287
|
+
|
|
288
|
+
When spawning an agent to work on an issue, include this context block:
|
|
289
|
+
|
|
290
|
+
```markdown
|
|
291
|
+
## ISSUE CONTEXT
|
|
292
|
+
|
|
293
|
+
**Issue:** #{number} — {title}
|
|
294
|
+
**Platform:** {GitHub | Azure DevOps | Planner}
|
|
295
|
+
**Repository:** {owner}/{repo}
|
|
296
|
+
**Assigned to:** {member}
|
|
297
|
+
|
|
298
|
+
**Description:**
|
|
299
|
+
{issue body}
|
|
300
|
+
|
|
301
|
+
**Labels/Tags:**
|
|
302
|
+
{labels}
|
|
303
|
+
|
|
304
|
+
**Acceptance Criteria:**
|
|
305
|
+
{criteria if present in issue}
|
|
306
|
+
|
|
307
|
+
**Branch:** `squad/{issue-number}-{slug}`
|
|
308
|
+
|
|
309
|
+
**Your task:**
|
|
310
|
+
{specific directive to the agent}
|
|
311
|
+
|
|
312
|
+
**After completing work:**
|
|
313
|
+
1. Commit with message referencing issue number
|
|
314
|
+
2. Push branch
|
|
315
|
+
3. Open PR using:
|
|
316
|
+
```
|
|
317
|
+
gh pr create --title "{title}" --body "Closes #{number}\n\n{description}" --head squad/{issue-number}-{slug} --base {base-branch}
|
|
318
|
+
```
|
|
319
|
+
4. Report PR URL to coordinator
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Ralph's Role in Issue Lifecycle
|
|
323
|
+
|
|
324
|
+
Ralph (the work monitor) continuously checks issue and PR state:
|
|
325
|
+
|
|
326
|
+
1. **Triage:** Detects untriaged issues, assigns `squad:{member}` labels
|
|
327
|
+
2. **Spawn:** Launches agents for assigned issues
|
|
328
|
+
3. **Monitor:** Tracks PR state transitions (needsReview → changesRequested → readyToMerge)
|
|
329
|
+
4. **Merge:** Automatically merges approved PRs
|
|
330
|
+
5. **Cleanup:** Marks issues as done when PRs merge
|
|
331
|
+
|
|
332
|
+
**Ralph's work-check cycle:**
|
|
333
|
+
```
|
|
334
|
+
Scan → Categorize → Dispatch → Watch → Report → Loop
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
See `.squad/templates/ralph-reference.md` for Ralph's full lifecycle.
|
|
338
|
+
|
|
339
|
+
## PR Review Handling
|
|
340
|
+
|
|
341
|
+
### Automated Approval (CI-only projects)
|
|
342
|
+
|
|
343
|
+
If the project has no human reviewers configured:
|
|
344
|
+
1. PR opens
|
|
345
|
+
2. CI runs
|
|
346
|
+
3. If CI passes, Ralph auto-merges
|
|
347
|
+
4. Issue closes
|
|
348
|
+
|
|
349
|
+
### Human Review Required
|
|
350
|
+
|
|
351
|
+
If the project requires human approval:
|
|
352
|
+
1. PR opens
|
|
353
|
+
2. Human reviewer is notified (GitHub/ADO notifications)
|
|
354
|
+
3. Reviewer approves or requests changes
|
|
355
|
+
4. If approved + CI passes, Ralph merges
|
|
356
|
+
5. If changes requested, agent addresses feedback
|
|
357
|
+
|
|
358
|
+
### Squad Member Review
|
|
359
|
+
|
|
360
|
+
If the issue was assigned to a squad member and they authored the PR:
|
|
361
|
+
1. Another squad member reviews (conflict of interest avoidance)
|
|
362
|
+
2. Original author is locked out from re-working rejected code (rejection lockout)
|
|
363
|
+
3. Reviewer can approve edits or reject outright
|
|
364
|
+
|
|
365
|
+
## Common Issue Lifecycle Patterns
|
|
366
|
+
|
|
367
|
+
### Pattern 1: Quick Fix (Single Agent, No Review)
|
|
368
|
+
```
|
|
369
|
+
Issue created → Assigned to agent → Branch created → Code fixed →
|
|
370
|
+
PR opened → CI passes → Auto-merged → Issue closed
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Pattern 2: Feature Development (Human Review)
|
|
374
|
+
```
|
|
375
|
+
Issue created → Assigned to agent → Branch created → Feature implemented →
|
|
376
|
+
PR opened → Human reviews → Changes requested → Agent fixes →
|
|
377
|
+
Re-reviewed → Approved → Merged → Issue closed
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Pattern 3: Research-Then-Implement
|
|
381
|
+
```
|
|
382
|
+
Issue created → Labeled `go:needs-research` → Research agent spawned →
|
|
383
|
+
Research documented → Research PR merged → Implementation issue created →
|
|
384
|
+
Implementation agent spawned → Feature built → PR merged
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Pattern 4: Parallel Multi-Agent (Future, #525)
|
|
388
|
+
```
|
|
389
|
+
Epic issue created → Decomposed into sub-issues → Each sub-issue assigned →
|
|
390
|
+
Multiple agents work in parallel worktrees → PRs opened concurrently →
|
|
391
|
+
All PRs reviewed → All PRs merged → Epic closed
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Anti-Patterns
|
|
395
|
+
|
|
396
|
+
- ❌ Creating branches without linking to an issue
|
|
397
|
+
- ❌ Committing without issue reference in message
|
|
398
|
+
- ❌ Opening PRs without "Closes #{number}" in description
|
|
399
|
+
- ❌ Merging PRs before CI passes
|
|
400
|
+
- ❌ Leaving feature branches undeleted after merge
|
|
401
|
+
- ❌ Using `checkout -b` when parallel agents are active (causes working directory conflicts)
|
|
402
|
+
- ❌ Manually transitioning issue states — let the platform and Squad automation handle it
|
|
403
|
+
- ❌ Skipping the branch naming convention — breaks Ralph's tracking logic
|
|
404
|
+
|
|
405
|
+
## Migration Notes
|
|
406
|
+
|
|
407
|
+
**v0.8.x → v0.9.x (Worktree Support):**
|
|
408
|
+
- `checkout -b` → `git worktree add` for parallel agents
|
|
409
|
+
- Worktree cleanup added to post-merge flow
|
|
410
|
+
- `TEAM_ROOT` passing to agents to support worktree-aware state resolution
|
|
411
|
+
|
|
412
|
+
This template will be updated as worktree lifecycle support lands in #525.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# KEDA External Scaler for GitHub Issue-Driven Agent Autoscaling
|
|
2
|
+
|
|
3
|
+
> Scale agent pods to zero when idle, up when work arrives — driven by GitHub Issues.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
When running Squad on Kubernetes, agent pods sit idle when no work exists. [KEDA](https://keda.sh) (Kubernetes Event-Driven Autoscaler) solves this for queue-based workloads, but GitHub Issues isn't a native KEDA trigger.
|
|
8
|
+
|
|
9
|
+
The `keda-copilot-scaler` is a KEDA External Scaler (gRPC) that bridges this gap:
|
|
10
|
+
1. Polls GitHub API for issues matching specific labels (e.g., `squad:copilot`)
|
|
11
|
+
2. Reports queue depth as a KEDA metric
|
|
12
|
+
3. Handles rate limits gracefully (Retry-After, exponential backoff)
|
|
13
|
+
4. Supports composite scaling decisions
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Prerequisites
|
|
18
|
+
- Kubernetes cluster with KEDA v2.x installed
|
|
19
|
+
- GitHub personal access token (PAT) with `repo` scope
|
|
20
|
+
- Helm 3.x
|
|
21
|
+
|
|
22
|
+
### 1. Install the Scaler
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
helm install keda-copilot-scaler oci://ghcr.io/tamirdresher/keda-copilot-scaler \
|
|
26
|
+
--namespace squad-scaler --create-namespace \
|
|
27
|
+
--set github.owner=YOUR_ORG \
|
|
28
|
+
--set github.repo=YOUR_REPO \
|
|
29
|
+
--set github.token=YOUR_TOKEN
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or with Kustomize:
|
|
33
|
+
```bash
|
|
34
|
+
kubectl apply -k https://github.com/tamirdresher/keda-copilot-scaler/deploy/kustomize
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Create a ScaledObject
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
apiVersion: keda.sh/v1alpha1
|
|
41
|
+
kind: ScaledObject
|
|
42
|
+
metadata:
|
|
43
|
+
name: picard-scaler
|
|
44
|
+
namespace: squad
|
|
45
|
+
spec:
|
|
46
|
+
scaleTargetRef:
|
|
47
|
+
name: picard-deployment
|
|
48
|
+
minReplicaCount: 0 # Scale to zero when idle
|
|
49
|
+
maxReplicaCount: 3
|
|
50
|
+
pollingInterval: 30 # Check every 30 seconds
|
|
51
|
+
cooldownPeriod: 300 # Wait 5 minutes before scaling down
|
|
52
|
+
triggers:
|
|
53
|
+
- type: external
|
|
54
|
+
metadata:
|
|
55
|
+
scalerAddress: keda-copilot-scaler.squad-scaler.svc.cluster.local:6000
|
|
56
|
+
owner: your-org
|
|
57
|
+
repo: your-repo
|
|
58
|
+
labels: squad:copilot # Only count issues with this label
|
|
59
|
+
threshold: "1" # Scale up when >= 1 issue exists
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 3. Verify
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Check the scaler is running
|
|
66
|
+
kubectl get pods -n squad-scaler
|
|
67
|
+
|
|
68
|
+
# Check ScaledObject status
|
|
69
|
+
kubectl get scaledobject picard-scaler -n squad
|
|
70
|
+
|
|
71
|
+
# Watch scaling events
|
|
72
|
+
kubectl get events -n squad --watch
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Scaling Behavior
|
|
76
|
+
|
|
77
|
+
| Open Issues | Target Replicas | Behavior |
|
|
78
|
+
|------------|----------------|----------|
|
|
79
|
+
| 0 | 0 | Scale to zero — save resources |
|
|
80
|
+
| 1–3 | 1 | Single agent handles work |
|
|
81
|
+
| 4–10 | 2 | Scale up for parallel processing |
|
|
82
|
+
| 10+ | 3 (max) | Maximum parallelism |
|
|
83
|
+
|
|
84
|
+
The threshold and max replicas are configurable per ScaledObject.
|
|
85
|
+
|
|
86
|
+
## Rate Limit Awareness
|
|
87
|
+
|
|
88
|
+
The scaler tracks GitHub API rate limits:
|
|
89
|
+
- Reads `X-RateLimit-Remaining` from API responses
|
|
90
|
+
- Backs off when quota is low (< 100 remaining)
|
|
91
|
+
- Reports rate limit metrics as secondary KEDA triggers
|
|
92
|
+
- Never exhausts API quota from polling
|
|
93
|
+
|
|
94
|
+
## Integration with Squad
|
|
95
|
+
|
|
96
|
+
### Machine Capabilities (#514)
|
|
97
|
+
|
|
98
|
+
Combine with machine capability labels for intelligent scheduling:
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
# Only scale pods on GPU-capable nodes
|
|
102
|
+
spec:
|
|
103
|
+
template:
|
|
104
|
+
spec:
|
|
105
|
+
nodeSelector:
|
|
106
|
+
node.squad.dev/gpu: "true"
|
|
107
|
+
triggers:
|
|
108
|
+
- type: external
|
|
109
|
+
metadata:
|
|
110
|
+
labels: squad:copilot,needs:gpu
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Cooperative Rate Limiting (#515)
|
|
114
|
+
|
|
115
|
+
The scaler exposes rate limit metrics that feed into the cooperative rate limiting system:
|
|
116
|
+
- Current `X-RateLimit-Remaining` value
|
|
117
|
+
- Predicted time to exhaustion (from predictive circuit breaker)
|
|
118
|
+
- Can return 0 target replicas when rate limited → pods scale to zero
|
|
119
|
+
|
|
120
|
+
## Architecture
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
GitHub API KEDA Kubernetes
|
|
124
|
+
┌──────────┐ ┌──────────┐ ┌──────────────┐
|
|
125
|
+
│ Issues │◄── poll ──►│ Scaler │──metrics─►│ HPA / KEDA │
|
|
126
|
+
│ (REST) │ │ (gRPC) │ │ Controller │
|
|
127
|
+
└──────────┘ └──────────┘ └──────┬───────┘
|
|
128
|
+
│
|
|
129
|
+
scale up/down
|
|
130
|
+
│
|
|
131
|
+
┌──────▼───────┐
|
|
132
|
+
│ Agent Pods │
|
|
133
|
+
│ (0–N replicas)│
|
|
134
|
+
└──────────────┘
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Configuration Reference
|
|
138
|
+
|
|
139
|
+
| Parameter | Default | Description |
|
|
140
|
+
|-----------|---------|-------------|
|
|
141
|
+
| `github.owner` | — | Repository owner |
|
|
142
|
+
| `github.repo` | — | Repository name |
|
|
143
|
+
| `github.token` | — | GitHub PAT with `repo` scope |
|
|
144
|
+
| `github.labels` | `squad:copilot` | Comma-separated label filter |
|
|
145
|
+
| `scaler.port` | `6000` | gRPC server port |
|
|
146
|
+
| `scaler.pollInterval` | `30s` | GitHub API polling interval |
|
|
147
|
+
| `scaler.rateLimitThreshold` | `100` | Stop polling below this remaining |
|
|
148
|
+
|
|
149
|
+
## Source & Contributing
|
|
150
|
+
|
|
151
|
+
- **Repository:** [tamirdresher/keda-copilot-scaler](https://github.com/tamirdresher/keda-copilot-scaler)
|
|
152
|
+
- **License:** MIT
|
|
153
|
+
- **Language:** Go
|
|
154
|
+
- **Tests:** 51 passing (unit + integration)
|
|
155
|
+
- **CI:** GitHub Actions
|
|
156
|
+
|
|
157
|
+
The scaler is maintained as a standalone project. PRs and issues welcome.
|
|
158
|
+
|
|
159
|
+
## References
|
|
160
|
+
|
|
161
|
+
- [KEDA External Scalers](https://keda.sh/docs/latest/concepts/external-scalers/) — KEDA documentation
|
|
162
|
+
- [Squad on AKS](https://github.com/tamirdresher/squad-on-aks) — Full Kubernetes deployment example
|
|
163
|
+
- [Machine Capabilities](machine-capabilities.md) — Capability-based routing (#514)
|
|
164
|
+
- [Cooperative Rate Limiting](cooperative-rate-limiting.md) — Multi-agent rate management (#515)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Machine Capability Discovery & Label-Based Routing
|
|
2
|
+
|
|
3
|
+
> Enable Ralph to skip issues requiring capabilities the current machine lacks.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
When running Squad across multiple machines (laptops, DevBoxes, GPU servers, Kubernetes nodes), each machine has different tooling. The capability system lets you declare what each machine can do, and Ralph automatically routes work accordingly.
|
|
8
|
+
|
|
9
|
+
## Setup
|
|
10
|
+
|
|
11
|
+
### 1. Create a Capabilities Manifest
|
|
12
|
+
|
|
13
|
+
Create `~/.squad/machine-capabilities.json` (user-wide) or `.squad/machine-capabilities.json` (project-local):
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"machine": "MY-LAPTOP",
|
|
18
|
+
"capabilities": ["browser", "personal-gh", "onedrive"],
|
|
19
|
+
"missing": ["gpu", "docker", "azure-speech"],
|
|
20
|
+
"lastUpdated": "2026-03-22T00:00:00Z"
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. Label Issues with Requirements
|
|
25
|
+
|
|
26
|
+
Add `needs:*` labels to issues that require specific capabilities:
|
|
27
|
+
|
|
28
|
+
| Label | Meaning |
|
|
29
|
+
|-------|---------|
|
|
30
|
+
| `needs:browser` | Requires Playwright / browser automation |
|
|
31
|
+
| `needs:gpu` | Requires NVIDIA GPU |
|
|
32
|
+
| `needs:personal-gh` | Requires personal GitHub account |
|
|
33
|
+
| `needs:emu-gh` | Requires Enterprise Managed User account |
|
|
34
|
+
| `needs:azure-cli` | Requires authenticated Azure CLI |
|
|
35
|
+
| `needs:docker` | Requires Docker daemon |
|
|
36
|
+
| `needs:onedrive` | Requires OneDrive sync |
|
|
37
|
+
| `needs:teams-mcp` | Requires Teams MCP tools |
|
|
38
|
+
|
|
39
|
+
Custom capabilities are supported — any `needs:X` label works if `X` is in the machine's `capabilities` array.
|
|
40
|
+
|
|
41
|
+
### 3. Run Ralph
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
squad watch --interval 5
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Ralph will log skipped issues:
|
|
48
|
+
```
|
|
49
|
+
⏭️ Skipping #42 "Train ML model" — missing: gpu
|
|
50
|
+
✓ Triaged #43 "Fix CSS layout" → Picard (routing-rule)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## How It Works
|
|
54
|
+
|
|
55
|
+
1. Ralph loads `machine-capabilities.json` at startup
|
|
56
|
+
2. For each open issue, Ralph extracts `needs:*` labels
|
|
57
|
+
3. If any required capability is missing, the issue is skipped
|
|
58
|
+
4. Issues without `needs:*` labels are always processed (opt-in system)
|
|
59
|
+
|
|
60
|
+
## Kubernetes Integration
|
|
61
|
+
|
|
62
|
+
On Kubernetes, machine capabilities map to node labels:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
# Node labels (set by capability DaemonSet or manually)
|
|
66
|
+
node.squad.dev/gpu: "true"
|
|
67
|
+
node.squad.dev/browser: "true"
|
|
68
|
+
|
|
69
|
+
# Pod spec uses nodeSelector
|
|
70
|
+
spec:
|
|
71
|
+
nodeSelector:
|
|
72
|
+
node.squad.dev/gpu: "true"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
A DaemonSet can run capability discovery on each node and maintain labels automatically. See the [squad-on-aks](https://github.com/tamirdresher/squad-on-aks) project for a complete Kubernetes deployment example.
|