@slamb2k/mad-skills 2.0.29 → 2.0.31

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mad-skills",
3
3
  "description": "AI-assisted planning, development and governance tools",
4
- "version": "2.0.29",
4
+ "version": "2.0.31",
5
5
  "author": {
6
6
  "name": "slamb2k",
7
7
  "url": "https://github.com/slamb2k"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slamb2k/mad-skills",
3
- "version": "2.0.29",
3
+ "version": "2.0.31",
4
4
  "description": "Claude Code skills collection — full lifecycle development tools",
5
5
  "type": "module",
6
6
  "repository": {
@@ -128,84 +128,9 @@ For each applicable row, in order:
128
128
  - **fallback**: notify user with Detail, continue with degraded behavior
129
129
  5. After all checks: summarize what's available and what's degraded
130
130
 
131
- ### AzDO Tooling Detection
132
-
133
- When `PLATFORM == azdo`, determine which tooling is available. Set `AZDO_MODE`
134
- for use in all subsequent phases:
135
-
136
- ```bash
137
- if az devops -h &>/dev/null; then
138
- AZDO_MODE="cli"
139
- else
140
- AZDO_MODE="rest"
141
- fi
142
- ```
143
-
144
- - **`cli`**: Use `az repos` / `az pipelines` commands (preferred)
145
- - **`rest`**: Use Azure DevOps REST API via `curl`. Requires a PAT (personal
146
- access token) in `AZURE_DEVOPS_EXT_PAT` or `AZDO_PAT` env var. If no PAT
147
- is found, prompt the user to either install the CLI or set the env var.
148
-
149
- Report in pre-flight:
150
- - ✅ `az devops cli` — version found
151
- - ⚠️ `az devops cli` — not found → using REST API fallback
152
- - ❌ `az devops cli` — not found, no PAT configured → halt with setup instructions
153
-
154
- ### AzDO Configuration Validation
155
-
156
- When `PLATFORM == azdo`, extract organization and project from the remote URL
157
- and validate they are usable. These values are needed by every `az repos` /
158
- `az pipelines` command and every REST API call.
159
-
160
- ```bash
161
- # Extract org and project from remote URL patterns:
162
- # https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
163
- # https://{ORG}@dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
164
- # {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}
165
-
166
- REMOTE_URL=$(git remote get-url origin 2>/dev/null)
167
-
168
- if echo "$REMOTE_URL" | grep -q 'dev\.azure\.com'; then
169
- AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/\([^/]*\)/.*|\1|p')
170
- AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/[^/]*/\([^/]*\)/.*|\1|p')
171
- AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
172
- elif echo "$REMOTE_URL" | grep -q 'vs-ssh\.visualstudio\.com'; then
173
- AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*vs-ssh\.visualstudio\.com:v3/\([^/]*\)/.*|\1|p')
174
- AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*vs-ssh\.visualstudio\.com:v3/[^/]*/\([^/]*\)/.*|\1|p')
175
- AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
176
- elif echo "$REMOTE_URL" | grep -q 'visualstudio\.com'; then
177
- AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*//\([^.]*\)\.visualstudio\.com.*|\1|p')
178
- AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*/\([^/]*\)/_git/.*|\1|p')
179
- AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
180
- fi
181
-
182
- if [ -z "$AZDO_ORG" ] || [ -z "$AZDO_PROJECT" ]; then
183
- echo "❌ Could not extract organization/project from remote URL"
184
- echo " Remote: $REMOTE_URL"
185
- echo ""
186
- echo "Ensure the remote URL follows one of these formats:"
187
- echo " https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}"
188
- echo " https://{ORG}.visualstudio.com/{PROJECT}/_git/{REPO}"
189
- echo " {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}"
190
- # HALT — cannot proceed without org/project context
191
- fi
192
- ```
193
-
194
- When `AZDO_MODE == cli`, also configure the defaults so commands work correctly:
195
- ```bash
196
- az devops configure --defaults organization="$AZDO_ORG_URL" project="$AZDO_PROJECT"
197
- ```
198
-
199
- When `AZDO_MODE == rest`, store these for API calls:
200
- - Base URL: `$AZDO_ORG_URL/$AZDO_PROJECT/_apis`
201
- - Auth header: `Authorization: Basic $(echo -n ":$PAT" | base64)`
202
-
203
- Report in pre-flight:
204
- - ✅ `azdo context` — org: `{AZDO_ORG}`, project: `{AZDO_PROJECT}`
205
- - ❌ `azdo context` — could not parse from remote URL → halt with instructions
206
-
207
- Pass `{AZDO_MODE}`, `{AZDO_ORG}`, `{AZDO_PROJECT}`, `{AZDO_ORG_URL}` into
208
- all phase prompts alongside `{PLATFORM}`.
131
+ When `PLATFORM == azdo`, follow `references/azdo-platform.md` for tooling
132
+ detection (`AZDO_MODE`) and configuration validation (`AZDO_ORG`, `AZDO_PROJECT`).
133
+ Pass these variables into all phase prompts alongside `{PLATFORM}`.
209
134
 
210
135
  ---
211
136
 
@@ -0,0 +1,83 @@
1
+ # Azure DevOps Platform Support
2
+
3
+ Shared procedures for AzDO tooling detection and configuration validation.
4
+ Referenced by SKILL.md during pre-flight when `PLATFORM == azdo`.
5
+
6
+ ## AzDO Tooling Detection
7
+
8
+ When `PLATFORM == azdo`, determine which tooling is available. Set `AZDO_MODE`
9
+ for use in all subsequent phases:
10
+
11
+ ```bash
12
+ if az devops -h &>/dev/null; then
13
+ AZDO_MODE="cli"
14
+ else
15
+ AZDO_MODE="rest"
16
+ fi
17
+ ```
18
+
19
+ - **`cli`**: Use `az repos` / `az pipelines` commands (preferred)
20
+ - **`rest`**: Use Azure DevOps REST API via `curl`. Requires a PAT (personal
21
+ access token) in `AZURE_DEVOPS_EXT_PAT` or `AZDO_PAT` env var. If no PAT
22
+ is found, prompt the user to either install the CLI or set the env var.
23
+
24
+ Report in pre-flight:
25
+ - ✅ `az devops cli` — version found
26
+ - ⚠️ `az devops cli` — not found → using REST API fallback
27
+ - ❌ `az devops cli` — not found, no PAT configured → halt with setup instructions
28
+
29
+ ## AzDO Configuration Validation
30
+
31
+ When `PLATFORM == azdo`, extract organization and project from the remote URL
32
+ and validate they are usable. These values are needed by every `az repos` /
33
+ `az pipelines` command and every REST API call.
34
+
35
+ ```bash
36
+ # Extract org and project from remote URL patterns:
37
+ # https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
38
+ # https://{ORG}@dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
39
+ # {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}
40
+
41
+ REMOTE_URL=$(git remote get-url origin 2>/dev/null)
42
+
43
+ if echo "$REMOTE_URL" | grep -q 'dev\.azure\.com'; then
44
+ AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/\([^/]*\)/.*|\1|p')
45
+ AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/[^/]*/\([^/]*\)/.*|\1|p')
46
+ AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
47
+ elif echo "$REMOTE_URL" | grep -q 'vs-ssh\.visualstudio\.com'; then
48
+ AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*vs-ssh\.visualstudio\.com:v3/\([^/]*\)/.*|\1|p')
49
+ AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*vs-ssh\.visualstudio\.com:v3/[^/]*/\([^/]*\)/.*|\1|p')
50
+ AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
51
+ elif echo "$REMOTE_URL" | grep -q 'visualstudio\.com'; then
52
+ AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*//\([^.]*\)\.visualstudio\.com.*|\1|p')
53
+ AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*/\([^/]*\)/_git/.*|\1|p')
54
+ AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
55
+ fi
56
+
57
+ if [ -z "$AZDO_ORG" ] || [ -z "$AZDO_PROJECT" ]; then
58
+ echo "❌ Could not extract organization/project from remote URL"
59
+ echo " Remote: $REMOTE_URL"
60
+ echo ""
61
+ echo "Ensure the remote URL follows one of these formats:"
62
+ echo " https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}"
63
+ echo " https://{ORG}.visualstudio.com/{PROJECT}/_git/{REPO}"
64
+ echo " {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}"
65
+ # HALT — cannot proceed without org/project context
66
+ fi
67
+ ```
68
+
69
+ When `AZDO_MODE == cli`, also configure the defaults so commands work correctly:
70
+ ```bash
71
+ az devops configure --defaults organization="$AZDO_ORG_URL" project="$AZDO_PROJECT"
72
+ ```
73
+
74
+ When `AZDO_MODE == rest`, store these for API calls:
75
+ - Base URL: `$AZDO_ORG_URL/$AZDO_PROJECT/_apis`
76
+ - Auth header: `Authorization: Basic $(echo -n ":$PAT" | base64)`
77
+
78
+ Report in pre-flight:
79
+ - ✅ `azdo context` — org: `{AZDO_ORG}`, project: `{AZDO_PROJECT}`
80
+ - ❌ `azdo context` — could not parse from remote URL → halt with instructions
81
+
82
+ Pass `{AZDO_MODE}`, `{AZDO_ORG}`, `{AZDO_PROJECT}`, `{AZDO_ORG_URL}` into
83
+ all phase prompts alongside `{PLATFORM}`.
@@ -124,84 +124,9 @@ For each applicable row, in order:
124
124
  - **fallback**: notify user with Detail, continue with degraded behavior
125
125
  5. After all checks: summarize what's available and what's degraded
126
126
 
127
- ### AzDO Tooling Detection
128
-
129
- When `PLATFORM == azdo`, determine which tooling is available. Set `AZDO_MODE`
130
- for use in all subsequent phases:
131
-
132
- ```bash
133
- if az devops -h &>/dev/null; then
134
- AZDO_MODE="cli"
135
- else
136
- AZDO_MODE="rest"
137
- fi
138
- ```
139
-
140
- - **`cli`**: Use `az repos` / `az pipelines` commands (preferred)
141
- - **`rest`**: Use Azure DevOps REST API via `curl`. Requires a PAT (personal
142
- access token) in `AZURE_DEVOPS_EXT_PAT` or `AZDO_PAT` env var. If no PAT
143
- is found, prompt the user to either install the CLI or set the env var.
144
-
145
- Report in pre-flight:
146
- - ✅ `az devops cli` — version found
147
- - ⚠️ `az devops cli` — not found → using REST API fallback
148
- - ❌ `az devops cli` — not found, no PAT configured → halt with setup instructions
149
-
150
- ### AzDO Configuration Validation
151
-
152
- When `PLATFORM == azdo`, extract organization and project from the remote URL
153
- and validate they are usable. These values are needed by every `az repos` /
154
- `az pipelines` command and every REST API call.
155
-
156
- ```bash
157
- # Extract org and project from remote URL patterns:
158
- # https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
159
- # https://{ORG}@dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
160
- # {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}
161
-
162
- REMOTE_URL=$(git remote get-url origin 2>/dev/null)
163
-
164
- if echo "$REMOTE_URL" | grep -q 'dev\.azure\.com'; then
165
- AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/\([^/]*\)/.*|\1|p')
166
- AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/[^/]*/\([^/]*\)/.*|\1|p')
167
- AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
168
- elif echo "$REMOTE_URL" | grep -q 'vs-ssh\.visualstudio\.com'; then
169
- AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*vs-ssh\.visualstudio\.com:v3/\([^/]*\)/.*|\1|p')
170
- AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*vs-ssh\.visualstudio\.com:v3/[^/]*/\([^/]*\)/.*|\1|p')
171
- AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
172
- elif echo "$REMOTE_URL" | grep -q 'visualstudio\.com'; then
173
- AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*//\([^.]*\)\.visualstudio\.com.*|\1|p')
174
- AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*/\([^/]*\)/_git/.*|\1|p')
175
- AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
176
- fi
177
-
178
- if [ -z "$AZDO_ORG" ] || [ -z "$AZDO_PROJECT" ]; then
179
- echo "❌ Could not extract organization/project from remote URL"
180
- echo " Remote: $REMOTE_URL"
181
- echo ""
182
- echo "Ensure the remote URL follows one of these formats:"
183
- echo " https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}"
184
- echo " https://{ORG}.visualstudio.com/{PROJECT}/_git/{REPO}"
185
- echo " {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}"
186
- # HALT — cannot proceed without org/project context
187
- fi
188
- ```
189
-
190
- When `AZDO_MODE == cli`, also configure the defaults so commands work correctly:
191
- ```bash
192
- az devops configure --defaults organization="$AZDO_ORG_URL" project="$AZDO_PROJECT"
193
- ```
194
-
195
- When `AZDO_MODE == rest`, store these for API calls:
196
- - Base URL: `$AZDO_ORG_URL/$AZDO_PROJECT/_apis`
197
- - Auth header: `Authorization: Basic $(echo -n ":$PAT" | base64)`
198
-
199
- Report in pre-flight:
200
- - ✅ `azdo context` — org: `{AZDO_ORG}`, project: `{AZDO_PROJECT}`
201
- - ❌ `azdo context` — could not parse from remote URL → halt with instructions
202
-
203
- Pass `{AZDO_MODE}`, `{AZDO_ORG}`, `{AZDO_PROJECT}`, `{AZDO_ORG_URL}` into
204
- all phase prompts alongside `{PLATFORM}`.
127
+ When `PLATFORM == azdo`, follow `references/azdo-platform.md` for tooling
128
+ detection (`AZDO_MODE`) and configuration validation (`AZDO_ORG`, `AZDO_PROJECT`).
129
+ Pass these variables into all phase prompts alongside `{PLATFORM}`.
205
130
 
206
131
  ---
207
132
 
@@ -247,160 +172,16 @@ Read the full interview flow from `references/interview-guide.md#interview-quest
247
172
  The interview covers these topics in order. Skip questions where detection provided
248
173
  high-confidence answers (but confirm with the user).
249
174
 
250
- ### 2.1 Cloud Provider
251
-
252
- ```
253
- Which cloud provider(s) will host your infrastructure?
254
-
255
- Options:
256
- 1. Azure (Recommended if Azure signals detected)
257
- 2. AWS
258
- 3. Google Cloud
259
- 4. Multi-cloud
260
- 5. Self-hosted / VPS (Dokku, Coolify, CapRover)
261
- ```
262
-
263
- If /dock has already run, infer from the deployment targets chosen there.
264
-
265
- ### 2.2 — IaC Tool
266
-
267
- Suggest based on cloud provider:
268
- - Azure → Bicep (native) or Terraform (universal)
269
- - AWS → Terraform or CDK
270
- - GCP → Terraform or Pulumi
271
- - Multi-cloud → Terraform
272
- - Self-hosted → Terraform (for VPS provisioning) or skip IaC
273
-
274
- ```
275
- Which Infrastructure as Code tool do you want to use?
276
-
277
- Options:
278
- 1. Terraform (Recommended — universal, multi-cloud)
279
- 2. Bicep (Azure-native, simpler syntax)
280
- 3. Pulumi (code-first, TypeScript/Python/Go)
281
- 4. AWS CDK (AWS-native, TypeScript/Python)
282
- ```
283
-
284
- ### 2.3 — Infrastructure Components
285
-
286
- Present a checklist based on detected needs. The goal is to provision everything
287
- /dock needs to deploy to, plus supporting services.
175
+ Topics covered (full prompts and options in `references/interview-guide.md`):
288
176
 
289
- ```
290
- Which infrastructure components do you need?
291
-
292
- Container platform:
293
- [x] Container registry (required for /dock)
294
- [ ] Kubernetes cluster (AKS/EKS/GKE)
295
- [ ] Serverless containers (Container Apps/Fargate/Cloud Run)
296
- [ ] Self-hosted PaaS (Dokku/Coolify/CapRover on VPS)
297
-
298
- Data:
299
- [ ] Managed database (PostgreSQL, MySQL, SQL Server, etc.)
300
- [ ] Cache (Redis, Memcached)
301
- [ ] Object storage (S3, Blob Storage, GCS)
302
- [ ] Message queue (SQS, Service Bus, Pub/Sub)
303
-
304
- Networking:
305
- [ ] DNS zone
306
- [ ] CDN / Front Door
307
- [ ] Virtual network / VPC
308
- [ ] Load balancer (if not using platform-managed)
309
- [ ] API Gateway
310
-
311
- Security:
312
- [ ] Key Vault / Secrets Manager
313
- [ ] Managed identity / IAM roles
314
- [ ] SSL/TLS certificates
315
-
316
- Monitoring:
317
- [ ] Log aggregation (Application Insights, CloudWatch, Cloud Logging)
318
- [ ] Metrics / dashboards
319
- [ ] Alerts
320
- ```
321
-
322
- Auto-check components if /dock detection or the codebase signals them:
323
- - Dockerfile found → container registry checked
324
- - Database migrations found → managed database checked
325
- - Redis client in deps → cache checked
326
- - S3/Blob SDK in deps → object storage checked
327
-
328
- ### 2.4 — Environment Topology
329
-
330
- Align with /dock's environments if it has run. Otherwise ask:
331
-
332
- ```
333
- How many environments do you need?
334
-
335
- Options:
336
- 1. Simple: dev + prod (Recommended for starting out)
337
- 2. Standard: dev + staging + prod
338
- 3. Custom: define your own
339
- ```
340
-
341
- Each environment gets its own IaC state and variable set. Resource sizing
342
- scales with the environment tier (dev=small, staging=medium, prod=large).
343
-
344
- ### 2.5 — State Management
345
-
346
- Where to store IaC state (critical for team collaboration):
347
-
348
- **Terraform:**
349
- ```
350
- Where should Terraform state be stored?
351
-
352
- Options:
353
- 1. Azure Blob Storage (Recommended for Azure)
354
- 2. AWS S3 + DynamoDB (Recommended for AWS)
355
- 3. Google Cloud Storage (Recommended for GCP)
356
- 4. Terraform Cloud
357
- 5. Local (not recommended for teams)
358
- ```
359
-
360
- **Bicep:** No state management needed (Azure Resource Manager handles it).
361
-
362
- **Pulumi:** Pulumi Cloud (default) or self-managed backend.
363
-
364
- **CDK:** CloudFormation handles state.
365
-
366
- ### 2.6 — CI/CD for Infrastructure
367
-
368
- ```
369
- How should infrastructure changes be applied?
370
-
371
- Options:
372
- 1. Plan on PR, apply on merge (Recommended)
373
- 2. Plan on PR, manual apply via approval
374
- 3. Plan and apply on merge (no PR preview)
375
- ```
376
-
377
- All options generate a pipeline. Option 1 is the default and safest for teams.
378
-
379
- ### 2.7 — Naming Convention
380
-
381
- ```
382
- What naming convention should resources use?
383
-
384
- Options:
385
- 1. Azure CAF style: {resource-type}-{project}-{env}-{region} (Recommended)
386
- 2. Simple: {project}-{resource}-{env}
387
- 3. Custom prefix: {user-defined}
388
- ```
389
-
390
- ### 2.8 — Integration with /dock
391
-
392
- If /dock artifacts exist, ask:
393
- ```
394
- I found /dock deployment config. Should /keel provision the infrastructure
395
- those pipelines deploy to?
396
-
397
- Detected targets:
398
- dev: {platform}
399
- staging: {platform}
400
- prod: {platform}
401
-
402
- I'll provision: container registry, {platform}-specific compute, networking.
403
- ```
177
+ 1. **Cloud Provider** — Azure, AWS, GCP, Multi-cloud, Self-hosted. Infer from /dock if it has run.
178
+ 2. **IaC Tool** Suggest by cloud: Azure→Bicep/Terraform, AWS→Terraform/CDK, GCP→Terraform/Pulumi, Multi-cloud→Terraform.
179
+ 3. **Infrastructure Components** — Checklist: container platform, data (DB, cache, storage, queues), networking, security, monitoring. Auto-check from codebase signals (Dockerfile→registry, migrations→DB, Redis client→cache).
180
+ 4. **Environment Topology** — Simple (dev+prod), Standard (dev+staging+prod), or Custom. Align with /dock if it has run.
181
+ 5. **State Management** Terraform: cloud storage per provider. Bicep: ARM handles it. Pulumi: Pulumi Cloud. CDK: CloudFormation.
182
+ 6. **CI/CD Strategy** Plan on PR + apply on merge (recommended), manual apply, or auto-apply.
183
+ 7. **Naming Convention** CAF style, simple, or custom prefix.
184
+ 8. **Integration with /dock** — If /dock artifacts exist, offer to provision their deployment targets.
404
185
 
405
186
  **If `--skip-interview`**: Use detected defaults + sensible defaults.
406
187
 
@@ -0,0 +1,83 @@
1
+ # Azure DevOps Platform Support
2
+
3
+ Shared procedures for AzDO tooling detection and configuration validation.
4
+ Referenced by SKILL.md during pre-flight when `PLATFORM == azdo`.
5
+
6
+ ## AzDO Tooling Detection
7
+
8
+ When `PLATFORM == azdo`, determine which tooling is available. Set `AZDO_MODE`
9
+ for use in all subsequent phases:
10
+
11
+ ```bash
12
+ if az devops -h &>/dev/null; then
13
+ AZDO_MODE="cli"
14
+ else
15
+ AZDO_MODE="rest"
16
+ fi
17
+ ```
18
+
19
+ - **`cli`**: Use `az repos` / `az pipelines` commands (preferred)
20
+ - **`rest`**: Use Azure DevOps REST API via `curl`. Requires a PAT (personal
21
+ access token) in `AZURE_DEVOPS_EXT_PAT` or `AZDO_PAT` env var. If no PAT
22
+ is found, prompt the user to either install the CLI or set the env var.
23
+
24
+ Report in pre-flight:
25
+ - ✅ `az devops cli` — version found
26
+ - ⚠️ `az devops cli` — not found → using REST API fallback
27
+ - ❌ `az devops cli` — not found, no PAT configured → halt with setup instructions
28
+
29
+ ## AzDO Configuration Validation
30
+
31
+ When `PLATFORM == azdo`, extract organization and project from the remote URL
32
+ and validate they are usable. These values are needed by every `az repos` /
33
+ `az pipelines` command and every REST API call.
34
+
35
+ ```bash
36
+ # Extract org and project from remote URL patterns:
37
+ # https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
38
+ # https://{ORG}@dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
39
+ # {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}
40
+
41
+ REMOTE_URL=$(git remote get-url origin 2>/dev/null)
42
+
43
+ if echo "$REMOTE_URL" | grep -q 'dev\.azure\.com'; then
44
+ AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/\([^/]*\)/.*|\1|p')
45
+ AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/[^/]*/\([^/]*\)/.*|\1|p')
46
+ AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
47
+ elif echo "$REMOTE_URL" | grep -q 'vs-ssh\.visualstudio\.com'; then
48
+ AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*vs-ssh\.visualstudio\.com:v3/\([^/]*\)/.*|\1|p')
49
+ AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*vs-ssh\.visualstudio\.com:v3/[^/]*/\([^/]*\)/.*|\1|p')
50
+ AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
51
+ elif echo "$REMOTE_URL" | grep -q 'visualstudio\.com'; then
52
+ AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*//\([^.]*\)\.visualstudio\.com.*|\1|p')
53
+ AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*/\([^/]*\)/_git/.*|\1|p')
54
+ AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
55
+ fi
56
+
57
+ if [ -z "$AZDO_ORG" ] || [ -z "$AZDO_PROJECT" ]; then
58
+ echo "❌ Could not extract organization/project from remote URL"
59
+ echo " Remote: $REMOTE_URL"
60
+ echo ""
61
+ echo "Ensure the remote URL follows one of these formats:"
62
+ echo " https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}"
63
+ echo " https://{ORG}.visualstudio.com/{PROJECT}/_git/{REPO}"
64
+ echo " {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}"
65
+ # HALT — cannot proceed without org/project context
66
+ fi
67
+ ```
68
+
69
+ When `AZDO_MODE == cli`, also configure the defaults so commands work correctly:
70
+ ```bash
71
+ az devops configure --defaults organization="$AZDO_ORG_URL" project="$AZDO_PROJECT"
72
+ ```
73
+
74
+ When `AZDO_MODE == rest`, store these for API calls:
75
+ - Base URL: `$AZDO_ORG_URL/$AZDO_PROJECT/_apis`
76
+ - Auth header: `Authorization: Basic $(echo -n ":$PAT" | base64)`
77
+
78
+ Report in pre-flight:
79
+ - ✅ `azdo context` — org: `{AZDO_ORG}`, project: `{AZDO_PROJECT}`
80
+ - ❌ `azdo context` — could not parse from remote URL → halt with instructions
81
+
82
+ Pass `{AZDO_MODE}`, `{AZDO_ORG}`, `{AZDO_PROJECT}`, `{AZDO_ORG_URL}` into
83
+ all phase prompts alongside `{PLATFORM}`.
@@ -1,5 +1,5 @@
1
1
  {
2
- "generated": "2026-03-12T15:57:08.604Z",
2
+ "generated": "2026-03-13T00:14:06.892Z",
3
3
  "count": 10,
4
4
  "skills": [
5
5
  {
@@ -36,7 +36,7 @@
36
36
  "name": "dock",
37
37
  "directory": "dock",
38
38
  "description": ">- Generate container-based release pipelines that build once and promote immutable artifacts through environments (dev → staging → prod). Detects your stack, interviews for infrastructure choices, then outputs deterministic CI/CD files (Dockerfile, workflows, deployment manifests) that run without an LLM. Use when setting up deployment pipelines, containerizing an app, creating release workflows, or connecting CI to container-friendly infrastructure (Azure Container Apps, AWS Fargate, Google Cloud Run, Kubernetes, Dokku, Coolify, CapRover, etc.).",
39
- "lines": 506,
39
+ "lines": 431,
40
40
  "hasScripts": false,
41
41
  "hasReferences": true,
42
42
  "hasAssets": false,
@@ -46,7 +46,7 @@
46
46
  "name": "keel",
47
47
  "directory": "keel",
48
48
  "description": ">- Generate Infrastructure as Code (IaC) pipelines that provision the cloud and container infrastructure your app deploys to. Interview-driven: detects your stack and cloud provider, then outputs deterministic IaC files (Terraform, Bicep, Pulumi, or CDK) plus CI/CD pipelines that plan on PR and apply on merge. Use when setting up cloud infrastructure, provisioning container registries, databases, networking, DNS, or any infrastructure that containers deploy onto. Designed to run before /dock — /keel lays the infrastructure, /dock deploys to it.",
49
- "lines": 638,
49
+ "lines": 419,
50
50
  "hasScripts": false,
51
51
  "hasReferences": true,
52
52
  "hasAssets": false,
@@ -76,7 +76,7 @@
76
76
  "name": "ship",
77
77
  "directory": "ship",
78
78
  "description": "\"Ship changes through the full PR lifecycle. Use after completing feature work to commit, push, create PR, wait for checks, and merge. Handles the entire workflow: syncs with main, creates feature branch if needed, groups commits logically with semantic messages, creates detailed PR, monitors CI, fixes issues, squash merges, and cleans up. Invoke when work is ready to ship.\"",
79
- "lines": 356,
79
+ "lines": 374,
80
80
  "hasScripts": false,
81
81
  "hasReferences": true,
82
82
  "hasAssets": false,
@@ -259,15 +259,21 @@ suggest the manual PR creation command. Do NOT revert the push.
259
259
 
260
260
  ---
261
261
 
262
- ## Stage 3: Wait for CI
262
+ ## Stage 3 + 4: CI Watch & Fix Loop
263
263
 
264
- Launch **Bash subagent** in the **background** (haiku just polling):
264
+ Run CI monitoring in the **foreground** so failures are caught and fixed
265
+ immediately. This stage loops: watch → detect failure → fix → push → watch again.
266
+
267
+ **Maximum 2 fix attempts.** If CI still fails after 2 rounds, report to user and stop.
268
+
269
+ ### Watch
270
+
271
+ Launch **Bash subagent** (haiku — polling):
265
272
 
266
273
  ```
267
274
  Task(
268
275
  subagent_type: "Bash",
269
276
  model: "haiku",
270
- run_in_background: true,
271
277
  description: "Monitor CI checks",
272
278
  prompt: <read from references/stage-prompts.md#stage-3>
273
279
  )
@@ -276,18 +282,14 @@ Task(
276
282
  Substitute `{PR_NUMBER}`, `{BRANCH}`, `{PLATFORM}`, `{AZDO_MODE}`,
277
283
  `{AZDO_ORG}`, `{AZDO_ORG_URL}`, `{AZDO_PROJECT}`, `{PAT}` into the prompt.
278
284
 
279
- While CI runs in the background, briefly inform the user:
280
- ```
281
- CI running for PR #{pr_number}... waiting for checks.
282
- ```
285
+ Briefly inform the user: `⏳ Watching CI for PR #{pr_number}...`
283
286
 
284
- When the background task completes, read the output file and parse CHECKS_REPORT.
287
+ Parse CHECKS_REPORT when the subagent returns.
285
288
 
286
- ---
289
+ ### Fix (if needed)
287
290
 
288
- ## Stage 4: Fix Failing Checks (if needed)
289
-
290
- If CHECKS_REPORT shows failures, launch **general-purpose subagent**:
291
+ If CHECKS_REPORT shows `some_failed`, **immediately** launch a fix subagent —
292
+ do not wait, do not ask the user:
291
293
 
292
294
  ```
293
295
  Task(
@@ -300,8 +302,24 @@ Task(
300
302
  Substitute `{PR_NUMBER}`, `{BRANCH}`, `{FAILING_CHECKS}`, `{PLATFORM}`,
301
303
  `{AZDO_MODE}`, `{AZDO_ORG}`, `{AZDO_ORG_URL}`, `{AZDO_PROJECT}`, `{PAT}` into the prompt.
302
304
 
303
- If fixed, return to Stage 3 (run CI watch again).
304
- If unable to fix after 2 attempts, report to user and stop.
305
+ The fix subagent MUST commit and push before returning. Once it returns,
306
+ **immediately loop back to Watch** to re-check CI.
307
+
308
+ ### Loop summary
309
+
310
+ ```
311
+ attempt = 0
312
+ while attempt < 2:
313
+ CHECKS = run_watch()
314
+ if CHECKS.status == "all_passed" or CHECKS.status == "no_checks":
315
+ break → proceed to Stage 5
316
+ attempt += 1
317
+ run_fix(CHECKS.failing_checks)
318
+ → loop back to watch
319
+
320
+ if attempt == 2 and still failing:
321
+ report failures to user, stop
322
+ ```
305
323
 
306
324
  ---
307
325
 
@@ -147,7 +147,8 @@ SHIP_REPORT:
147
147
  **Agent:** Bash (haiku, background)
148
148
 
149
149
  ```
150
- Monitor PR/pipeline status checks until complete.
150
+ Monitor PR/pipeline status checks until complete. Fail fast — stop polling the
151
+ moment any check fails so fixes can start immediately.
151
152
 
152
153
  Limit CHECKS_REPORT to 10 lines maximum.
153
154
 
@@ -159,8 +160,8 @@ BRANCH: {BRANCH}
159
160
 
160
161
  **If PLATFORM == github:**
161
162
 
162
- 1. **Wait for checks to complete**
163
- gh pr checks {PR_NUMBER} --watch
163
+ 1. **Wait for checks fail fast on first failure**
164
+ gh pr checks {PR_NUMBER} --watch --fail-fast
164
165
 
165
166
  2. **Report final status**
166
167
  gh pr checks {PR_NUMBER}
@@ -190,9 +191,9 @@ BRANCH: {BRANCH}
190
191
  ```
191
192
  If no policies exist either, report `no_checks`.
192
193
 
193
- 2. **Wait for runs to complete — with fail-fast** (max 30 minutes, check every 30s)
194
+ 2. **Wait for runs to complete — with fail-fast** (max 30 minutes, check every 15s)
194
195
  ```
195
- for i in $(seq 1 60); do
196
+ for i in $(seq 1 120); do
196
197
  # Check for failures FIRST — stop immediately if any run has failed
197
198
  FAILED=$(az pipelines runs list --branch "$BRANCH" --top 5 \
198
199
  --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
@@ -207,7 +208,7 @@ BRANCH: {BRANCH}
207
208
  --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
208
209
  --query "[?status=='inProgress'] | length(@)" -o tsv 2>/dev/null)
209
210
  if [ "$IN_PROGRESS" = "0" ] || [ -z "$IN_PROGRESS" ]; then break; fi
210
- sleep 30
211
+ sleep 15
211
212
  done
212
213
  ```
213
214
 
@@ -259,9 +260,9 @@ BRANCH: {BRANCH}
259
260
  ```
260
261
  If no evaluations exist either, report `no_checks`.
261
262
 
262
- 2. **Wait for runs to complete — with fail-fast** (max 30 minutes, check every 30s)
263
+ 2. **Wait for runs to complete — with fail-fast** (max 30 minutes, check every 15s)
263
264
  ```
264
- for i in $(seq 1 60); do
265
+ for i in $(seq 1 120); do
265
266
  BUILDS_JSON=$(curl -s -H "$AUTH" "$BUILDS_URL")
266
267
 
267
268
  # Check for failures FIRST
@@ -274,7 +275,7 @@ BRANCH: {BRANCH}
274
275
  # Check if anything still running
275
276
  IN_PROGRESS=$(echo "$BUILDS_JSON" | jq '[.value[] | select(.status=="inProgress")] | length')
276
277
  if [ "$IN_PROGRESS" = "0" ]; then break; fi
277
- sleep 30
278
+ sleep 15
278
279
  done
279
280
  ```
280
281