@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.
- package/.claude-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/skills/dock/SKILL.md +3 -78
- package/skills/dock/references/azdo-platform.md +83 -0
- package/skills/keel/SKILL.md +12 -231
- package/skills/keel/references/azdo-platform.md +83 -0
- package/skills/manifest.json +4 -4
- package/skills/ship/SKILL.md +32 -14
- package/skills/ship/references/stage-prompts.md +10 -9
package/package.json
CHANGED
package/skills/dock/SKILL.md
CHANGED
|
@@ -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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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}`.
|
package/skills/keel/SKILL.md
CHANGED
|
@@ -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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
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
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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}`.
|
package/skills/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generated": "2026-03-
|
|
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":
|
|
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":
|
|
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":
|
|
79
|
+
"lines": 374,
|
|
80
80
|
"hasScripts": false,
|
|
81
81
|
"hasReferences": true,
|
|
82
82
|
"hasAssets": false,
|
package/skills/ship/SKILL.md
CHANGED
|
@@ -259,15 +259,21 @@ suggest the manual PR creation command. Do NOT revert the push.
|
|
|
259
259
|
|
|
260
260
|
---
|
|
261
261
|
|
|
262
|
-
## Stage 3:
|
|
262
|
+
## Stage 3 + 4: CI Watch & Fix Loop
|
|
263
263
|
|
|
264
|
-
|
|
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
|
-
|
|
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
|
-
|
|
287
|
+
Parse CHECKS_REPORT when the subagent returns.
|
|
285
288
|
|
|
286
|
-
|
|
289
|
+
### Fix (if needed)
|
|
287
290
|
|
|
288
|
-
|
|
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
|
-
|
|
304
|
-
|
|
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
|
|
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
|
|
194
|
+
2. **Wait for runs to complete — with fail-fast** (max 30 minutes, check every 15s)
|
|
194
195
|
```
|
|
195
|
-
for i in $(seq 1
|
|
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
|
|
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
|
|
263
|
+
2. **Wait for runs to complete — with fail-fast** (max 30 minutes, check every 15s)
|
|
263
264
|
```
|
|
264
|
-
for i in $(seq 1
|
|
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
|
|
278
|
+
sleep 15
|
|
278
279
|
done
|
|
279
280
|
```
|
|
280
281
|
|