@slamb2k/mad-skills 2.0.24 → 2.0.26

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.24",
4
+ "version": "2.0.26",
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.24",
3
+ "version": "2.0.26",
4
4
  "description": "Claude Code skills collection — full lifecycle development tools",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: build
3
3
  description: Context-isolated feature development pipeline. Takes a detailed design/plan as argument and executes the full feature-dev lifecycle (explore, question, architect, implement, review, ship) inside subagents so the primary conversation stays compact. Use when you have a well-defined plan and want autonomous execution with minimal context window consumption.
4
- argument-hint: <detailed design/plan to implement> [--skip-questions] [--skip-review] [--no-ship] [--parallel-impl]
5
- allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Agent, AskUserQuestion
4
+ argument-hint: <plan text or spec file path> [--skip-questions] [--skip-review] [--no-ship] [--parallel-impl]
5
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Agent, AskUserQuestion, TaskCreate, TaskUpdate, TaskGet, TaskList
6
6
  ---
7
7
 
8
8
  # Build - Context-Isolated Feature Development
@@ -103,16 +103,14 @@ For each row, in order:
103
103
 
104
104
  1. Capture **PLAN** (the user's argument) and **FLAGS**
105
105
  2. **Load project context** — invoke `/prime` to load domain-specific context
106
- (CLAUDE.md, goals, specs, memory). If /prime is unavailable, fall back to
107
- manually scanning CLAUDE.md and goals/ directory.
106
+ (CLAUDE.md, specs, memory). If /prime is unavailable, fall back to
107
+ manually scanning CLAUDE.md and specs/ directory.
108
108
  3. Detect project type using `references/project-detection.md` to populate
109
109
  **PROJECT_CONFIG** (language, test_runner, test_setup)
110
- 3. Check for outstanding questions from previous work:
110
+ 3. Check for outstanding items from previous work:
111
+ - Query persistent tasks via `TaskList` for incomplete items
111
112
  - Search CLAUDE.md for a "Known Issues" or "Open Questions" section
112
- - Search `goals/` for files containing "open_question" or "unresolved"
113
- - Search memory (if available) for recent items of type "task" or
114
- "open_question" that are unresolved
115
- - Check for `DEBRIEF_ITEMS` in any recent build logs
113
+ - Search memory (if available) for recent unresolved items
116
114
  4. If outstanding items found, present via AskUserQuestion:
117
115
  ```
118
116
  "Found {count} outstanding items from previous work:"
@@ -125,7 +123,23 @@ For each row, in order:
125
123
  Items marked "incorporate" get appended to the PLAN as additional
126
124
  requirements for Stage 1 to explore.
127
125
  - **"No, proceed with the build"** → continue normally
128
- 5. Create a task list tracking all stages
126
+ ---
127
+
128
+ ## Plan Resolution
129
+
130
+ Before Stage 1, resolve the PLAN argument into content:
131
+
132
+ 1. **File detection** — If the argument contains `/` or ends with
133
+ `.md`, `.yaml`, `.json`, or `.txt`, treat it as a file path:
134
+ - Try reading the path as-is
135
+ - If not found, try `specs/{arg}`
136
+ - If found, use file content as PLAN
137
+ - If not found at any location, treat the original argument as free-form text
138
+ 2. **Free-form text** — If not a file path (or file not found), use the argument
139
+ verbatim as PLAN
140
+ 3. **Display** — In the Input box, show the resolved source:
141
+ - File: `Plan: {file path} ({line count} lines)`
142
+ - Text: `Plan: inline ({word count} words)`
129
143
 
130
144
  ---
131
145
 
@@ -303,8 +317,9 @@ Invoke the `/ship` skill:
303
317
  Options:
304
318
  - **"Fix now"** → create a task list of resolution activities for
305
319
  each item; present for user confirmation, then work through them
306
- - **"Create tasks for future sessions"** → create persistent tasks via
307
- `TaskCreate` for each item, or append to CLAUDE.md as Known Issues
320
+ - **"Create tasks for future sessions"** → use `TaskCreate` for each
321
+ item as a persistent task, with category as prefix and suggested
322
+ action as description
308
323
  - **"Note and continue"** → acknowledge items without formal tracking;
309
324
  log to memory (if exists) or as source file comments. No further action.
310
325
  - **"Let me choose per item"** → present each individually with full
@@ -337,7 +352,7 @@ Invoke the `/ship` skill:
337
352
  │ Findings addressed: {count fixed} / {count found}
338
353
 
339
354
  │ 📊 Debrief: {count resolved} / {count surfaced}
340
- │ {list of created goals/tasks}
355
+ │ {list of created tasks}
341
356
 
342
357
  │ 🔗 Links
343
358
  │ PR: {pr_url}
@@ -385,9 +385,10 @@ Options:
385
385
  for user confirmation, then work through them.
386
386
 
387
387
  - "Create tasks for future sessions"
388
- → For each item, create a persistent task via TaskCreate with the
389
- suggested_action as the task description, or append to CLAUDE.md
390
- as a "Known Issues" section. Group by category, not one per item.
388
+ → For each item, use TaskCreate to create a persistent task with:
389
+ title: "[{category}] {summary}"
390
+ description: "{description}\n\nEvidence: {evidence}\nSuggested action: {suggested_action}"
391
+ Format: one task per item for granular tracking.
391
392
 
392
393
  - "Note and continue"
393
394
  → Acknowledge items without formal tracking. Log to memory (if memory
@@ -398,8 +399,9 @@ Options:
398
399
  → Present each item individually via AskUserQuestion. Show the full
399
400
  `description`, `evidence`, and `impact` fields so the user has
400
401
  enough context to decide. Options per item:
401
- "Fix now" / "Add to goals" / "Explain more" / "Note and continue"
402
+ "Fix now" / "Create task" / "Explain more" / "Note and continue"
402
403
  - "Fix now": launch a general-purpose subagent to resolve
404
+ - "Create task": use TaskCreate to persist for future sessions
403
405
  - "Explain more": read the relevant source files/reports cited in
404
406
  `evidence`, summarise the context, then re-present the same item
405
407
  with the expanded explanation
@@ -17,6 +17,14 @@
17
17
  { "type": "semantic", "value": "Describes a multi-stage development lifecycle that includes exploration, architecture design, implementation, code review, and shipping, with stages running in isolated subagents" }
18
18
  ]
19
19
  },
20
+ {
21
+ "name": "file-path-detection",
22
+ "prompt": "Build specs/user-auth.md",
23
+ "assertions": [
24
+ { "type": "contains", "value": "██" },
25
+ { "type": "semantic", "value": "Detects that the argument is a file path (contains / or ends with .md) and attempts to read it as a spec file rather than treating it as literal plan text. Shows the resolved file path in the Input display." }
26
+ ]
27
+ },
20
28
  {
21
29
  "name": "flag-handling",
22
30
  "prompt": "Build --skip-questions --no-ship: Refactor the auth module to use middleware pattern",
@@ -1,5 +1,5 @@
1
1
  {
2
- "generated": "2026-03-11T04:28:37.105Z",
2
+ "generated": "2026-03-12T03:25:58.495Z",
3
3
  "count": 10,
4
4
  "skills": [
5
5
  {
@@ -16,7 +16,7 @@
16
16
  "name": "build",
17
17
  "directory": "build",
18
18
  "description": "Context-isolated feature development pipeline. Takes a detailed design/plan as argument and executes the full feature-dev lifecycle (explore, question, architect, implement, review, ship) inside subagents so the primary conversation stays compact. Use when you have a well-defined plan and want autonomous execution with minimal context window consumption.",
19
- "lines": 363,
19
+ "lines": 378,
20
20
  "hasScripts": false,
21
21
  "hasReferences": true,
22
22
  "hasAssets": false,
@@ -55,7 +55,7 @@
55
55
  {
56
56
  "name": "prime",
57
57
  "directory": "prime",
58
- "description": "\"Load project context before implementing features or making architectural decisions. Invoke proactively at the start of significant work on any project. Scans CLAUDE.md, README, goals/, specs/, docs/, and source structure to build a context summary. Supports optional domain hints to focus on specific areas of the codebase. Use when you need project conventions, architecture understanding, or domain context before coding.\"",
58
+ "description": "\"Load project context before implementing features or making architectural decisions. Invoke proactively at the start of significant work on any project. Scans CLAUDE.md, README, specs/, docs/, and source structure to build a context summary. Supports optional domain hints to focus on specific areas of the codebase. Use when you need project conventions, architecture understanding, or domain context before coding.\"",
59
59
  "lines": 148,
60
60
  "hasScripts": false,
61
61
  "hasReferences": true,
@@ -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": 262,
79
+ "lines": 356,
80
80
  "hasScripts": false,
81
81
  "hasReferences": true,
82
82
  "hasAssets": false,
@@ -85,8 +85,8 @@
85
85
  {
86
86
  "name": "speccy",
87
87
  "directory": "speccy",
88
- "description": "Deep-dive interview skill for creating comprehensive specifications. Reviews existing code and docs, then interviews the user through multiple rounds of targeted questions covering technical implementation, UI/UX, concerns, and tradeoffs. Produces a structured spec via create-specification. Use when starting a new feature, system, or major change that needs a spec.",
89
- "lines": 232,
88
+ "description": "Deep-dive interview skill for creating comprehensive specifications. Reviews existing code and docs, then interviews the user through multiple rounds of targeted questions covering technical implementation, UI/UX, concerns, and tradeoffs. Produces a structured spec in specs/. Use when starting a new feature, system, or major change that needs a spec.",
89
+ "lines": 241,
90
90
  "hasScripts": false,
91
91
  "hasReferences": true,
92
92
  "hasAssets": false,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: prime
3
- description: "Load project context before implementing features or making architectural decisions. Invoke proactively at the start of significant work on any project. Scans CLAUDE.md, README, goals/, specs/, docs/, and source structure to build a context summary. Supports optional domain hints to focus on specific areas of the codebase. Use when you need project conventions, architecture understanding, or domain context before coding."
3
+ description: "Load project context before implementing features or making architectural decisions. Invoke proactively at the start of significant work on any project. Scans CLAUDE.md, README, specs/, docs/, and source structure to build a context summary. Supports optional domain hints to focus on specific areas of the codebase. Use when you need project conventions, architecture understanding, or domain context before coding."
4
4
  argument-hint: "[domain hints: comma-separated directory or topic names to focus on]"
5
5
  allowed-tools: Read, Glob, Grep, LS, Agent
6
6
  ---
@@ -66,7 +66,7 @@ subagent — the primary thread only sees a structured PRIME_REPORT.
66
66
 
67
67
  Extract domain hints from the request (comma-separated). These are directory
68
68
  names or topic keywords to focus the context scan on. If no domain specified,
69
- load core context only (CLAUDE.md, README, goals/, specs/).
69
+ load core context only (CLAUDE.md, README, specs/).
70
70
 
71
71
  ## Step 2: Load Context via Subagent
72
72
 
@@ -92,7 +92,7 @@ Limit PRIME_REPORT to 30 lines maximum.
92
92
 
93
93
  1. CLAUDE.md — Project conventions, architecture, instructions
94
94
  2. README.md — Project overview, setup, usage
95
- 3. goals/ or specs/ — Project goals, specs, roadmap (scan directory if present)
95
+ 3. specs/ — Project specifications and roadmap (scan directory if present)
96
96
  4. docs/ — Documentation directory (scan if present)
97
97
 
98
98
  If a file is missing, record as NOT FOUND and continue.
@@ -72,51 +72,140 @@ Parse optional flags from the request:
72
72
 
73
73
  ---
74
74
 
75
+ ## Platform Detection
76
+
77
+ Detect the hosting platform **before** pre-flight so dependency checks are
78
+ platform-specific:
79
+
80
+ ```bash
81
+ REMOTE_URL=$(git remote get-url origin 2>/dev/null)
82
+ if echo "$REMOTE_URL" | grep -qiE 'dev\.azure\.com|visualstudio\.com'; then
83
+ PLATFORM="azdo"
84
+ elif echo "$REMOTE_URL" | grep -qi 'github\.com'; then
85
+ PLATFORM="github"
86
+ else
87
+ PLATFORM="github" # default fallback
88
+ fi
89
+ ```
90
+
91
+ Pass `{PLATFORM}` into all stage prompts. Each stage uses the appropriate
92
+ CLI tool: `gh` for GitHub, `az repos`/`az pipelines` for Azure DevOps.
93
+
94
+ ---
95
+
75
96
  ## Pre-flight
76
97
 
77
- Before starting, check all dependencies in this table:
98
+ Before starting, check all dependencies in this table. The table contains
99
+ **all** dependencies — some are platform-conditional (see notes after table).
78
100
 
79
101
  | Dependency | Type | Check | Required | Resolution | Detail |
80
102
  |-----------|------|-------|----------|------------|--------|
81
103
  | git | cli | `git --version` | yes | stop | Install from https://git-scm.com |
82
104
  | gh | cli | `gh --version` | yes | url | https://cli.github.com |
83
- | ship-analyzer | agent | `~/.claude/agents/ship-analyzer.md` | no | fallback | Uses general-purpose agent |
84
-
85
- For each row, in order:
86
- 1. Run the Check command (for cli/npm) or test file existence (for agent/skill)
87
- 2. If found: continue silently
88
- 3. If missing: apply Resolution strategy
105
+ | az devops | cli | `az devops -h 2>/dev/null` | no | fallback | Falls back to REST API with PAT; see AzDO tooling below |
106
+ | ship-analyzer | agent | `~/.claude/agents/ship-analyzer.md` or `~/.claude/plugins/marketplaces/slamb2k/agents/ship-analyzer.md` | no | fallback | Uses general-purpose agent |
107
+
108
+ **Platform-conditional rules:**
109
+ - **`gh`**: Only required when `PLATFORM == github`. Skip for AzDO repos.
110
+ - **`az devops`**: Only checked when `PLATFORM == azdo`. Skip for GitHub repos.
111
+
112
+ For each applicable row, in order:
113
+ 1. Skip rows that don't apply to the detected `{PLATFORM}`
114
+ 2. Run the Check command (for cli/npm) or test file existence (for agent/skill)
115
+ 3. If found: continue silently
116
+ 4. If missing: apply Resolution strategy
89
117
  - **stop**: notify user with Detail, halt execution
90
118
  - **url**: notify user with Detail (install link), halt execution
91
119
  - **install**: notify user, run the command in Detail, continue if successful
92
120
  - **ask**: notify user, offer to run command in Detail, continue either way (or halt if required)
93
121
  - **fallback**: notify user with Detail, continue with degraded behavior
94
- 4. After all checks: summarize what's available and what's degraded
122
+ 5. After all checks: summarize what's available and what's degraded
95
123
 
96
- Read `default_branch` and `remote` from Stage 1's SYNC_REPORT. These are
97
- substituted into all stage prompts as `{REMOTE}` and `{DEFAULT_BRANCH}`.
98
-
99
- ### Platform Detection
124
+ ### AzDO Tooling Detection
100
125
 
101
- After sync, detect the hosting platform from the remote URL:
126
+ When `PLATFORM == azdo`, determine which tooling is available. Set `AZDO_MODE`
127
+ for use in all subsequent stages:
102
128
 
103
129
  ```bash
104
- REMOTE_URL=$(git remote get-url {REMOTE} 2>/dev/null)
105
- if echo "$REMOTE_URL" | grep -qiE 'dev\.azure\.com|visualstudio\.com'; then
106
- PLATFORM="azdo"
107
- elif echo "$REMOTE_URL" | grep -qi 'github\.com'; then
108
- PLATFORM="github"
130
+ if az devops -h &>/dev/null; then
131
+ AZDO_MODE="cli"
109
132
  else
110
- PLATFORM="github" # default fallback
133
+ AZDO_MODE="rest"
111
134
  fi
112
135
  ```
113
136
 
114
- Pass `{PLATFORM}` into all stage prompts. Each stage uses the appropriate
115
- CLI tool: `gh` for GitHub, `az repos`/`az pipelines` for Azure DevOps.
137
+ - **`cli`**: Use `az repos` / `az pipelines` commands (preferred)
138
+ - **`rest`**: Use Azure DevOps REST API via `curl`. Requires a PAT (personal
139
+ access token) in `AZURE_DEVOPS_EXT_PAT` or `AZDO_PAT` env var. If no PAT
140
+ is found, prompt the user to either install the CLI or set the env var.
141
+
142
+ Report in pre-flight:
143
+ - ✅ `az devops cli` — version found
144
+ - ⚠️ `az devops cli` — not found → using REST API fallback
145
+ - ❌ `az devops cli` — not found, no PAT configured → halt with setup instructions
146
+
147
+ ### AzDO Configuration Validation
148
+
149
+ When `PLATFORM == azdo`, extract organization and project from the remote URL
150
+ and validate they are usable. These values are needed by every `az repos` /
151
+ `az pipelines` command and every REST API call.
152
+
153
+ ```bash
154
+ # Extract org and project from remote URL patterns:
155
+ # https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
156
+ # https://{ORG}@dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
157
+ # {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}
158
+
159
+ REMOTE_URL=$(git remote get-url origin 2>/dev/null)
160
+
161
+ if echo "$REMOTE_URL" | grep -q 'dev\.azure\.com'; then
162
+ # HTTPS format: https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
163
+ # Also handles: https://{ORG}@dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}
164
+ AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/\([^/]*\)/.*|\1|p')
165
+ AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*dev\.azure\.com/[^/]*/\([^/]*\)/.*|\1|p')
166
+ AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
167
+ elif echo "$REMOTE_URL" | grep -q 'vs-ssh\.visualstudio\.com'; then
168
+ # SSH format: {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}
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
+ # Legacy HTTPS format: https://{ORG}.visualstudio.com/{PROJECT}/_git/{REPO}
174
+ AZDO_ORG=$(echo "$REMOTE_URL" | sed -n 's|.*//\([^.]*\)\.visualstudio\.com.*|\1|p')
175
+ AZDO_PROJECT=$(echo "$REMOTE_URL" | sed -n 's|.*/\([^/]*\)/_git/.*|\1|p')
176
+ AZDO_ORG_URL="https://dev.azure.com/$AZDO_ORG"
177
+ fi
116
178
 
117
- > **Azure DevOps prerequisite:** The `az devops` extension must be installed
118
- > and configured (`az devops configure --defaults organization=... project=...`).
119
- > If `az repos` commands fail, report the setup requirement to the user.
179
+ if [ -z "$AZDO_ORG" ] || [ -z "$AZDO_PROJECT" ]; then
180
+ echo "❌ Could not extract organization/project from remote URL"
181
+ echo " Remote: $REMOTE_URL"
182
+ echo ""
183
+ echo "Ensure the remote URL follows one of these formats:"
184
+ echo " https://dev.azure.com/{ORG}/{PROJECT}/_git/{REPO}"
185
+ echo " https://{ORG}.visualstudio.com/{PROJECT}/_git/{REPO}"
186
+ echo " {ORG}@vs-ssh.visualstudio.com:v3/{ORG}/{PROJECT}/{REPO}"
187
+ # HALT — cannot proceed without org/project context
188
+ fi
189
+ ```
190
+
191
+ When `AZDO_MODE == cli`, also configure the defaults so commands work correctly:
192
+ ```bash
193
+ az devops configure --defaults organization="$AZDO_ORG_URL" project="$AZDO_PROJECT"
194
+ ```
195
+
196
+ When `AZDO_MODE == rest`, store these for API calls:
197
+ - Base URL: `$AZDO_ORG_URL/$AZDO_PROJECT/_apis`
198
+ - Auth header: `Authorization: Basic $(echo -n ":$PAT" | base64)`
199
+
200
+ Report in pre-flight:
201
+ - ✅ `azdo context` — org: `{AZDO_ORG}`, project: `{AZDO_PROJECT}`
202
+ - ❌ `azdo context` — could not parse from remote URL → halt with instructions
203
+
204
+ Pass `{AZDO_MODE}`, `{AZDO_ORG}`, `{AZDO_PROJECT}`, `{AZDO_ORG_URL}` into
205
+ all stage prompts alongside `{PLATFORM}`.
206
+
207
+ Read `default_branch` and `remote` from Stage 1's SYNC_REPORT. These are
208
+ substituted into all stage prompts as `{REMOTE}` and `{DEFAULT_BRANCH}`.
120
209
 
121
210
  ---
122
211
 
@@ -155,14 +244,16 @@ Task(
155
244
  > **Fallback:** If `ship-analyzer` is not available, use `subagent_type: "general-purpose"`.
156
245
 
157
246
  Substitute `{USER_INTENT}`, `{FILES_TO_INCLUDE}`, `{FILES_TO_EXCLUDE}`,
158
- `{REMOTE}`, `{DEFAULT_BRANCH}`, `{PLATFORM}` into the prompt.
247
+ `{REMOTE}`, `{DEFAULT_BRANCH}`, `{PLATFORM}`, `{AZDO_MODE}`, `{AZDO_ORG}`,
248
+ `{AZDO_PROJECT}`, `{AZDO_ORG_URL}`, `{PAT}` into the prompt.
159
249
 
160
250
  Parse SHIP_REPORT. Abort if failed.
161
251
 
162
252
  **Rollback:** If push succeeds but PR creation fails, report the error and
163
253
  suggest the manual PR creation command. Do NOT revert the push.
164
254
  - GitHub: `gh pr create --head {branch}`
165
- - Azure DevOps: `az repos pr create --source-branch {branch} --target-branch {DEFAULT_BRANCH}`
255
+ - Azure DevOps (cli): `az repos pr create --source-branch {branch} --target-branch {DEFAULT_BRANCH} --org {AZDO_ORG_URL} --project {AZDO_PROJECT}`
256
+ - Azure DevOps (rest): Create PR via `{AZDO_ORG_URL}/{AZDO_PROJECT}/_apis/git/repositories/{repo}/pullrequests?api-version=7.0`
166
257
 
167
258
  **If `--pr-only` flag: Stop here and report PR URL to user.**
168
259
 
@@ -182,7 +273,8 @@ Task(
182
273
  )
183
274
  ```
184
275
 
185
- Substitute `{PR_NUMBER}` into the prompt.
276
+ Substitute `{PR_NUMBER}`, `{BRANCH}`, `{PLATFORM}`, `{AZDO_MODE}`,
277
+ `{AZDO_ORG}`, `{AZDO_ORG_URL}`, `{AZDO_PROJECT}`, `{PAT}` into the prompt.
186
278
 
187
279
  While CI runs in the background, briefly inform the user:
188
280
  ```
@@ -205,7 +297,8 @@ Task(
205
297
  )
206
298
  ```
207
299
 
208
- Substitute `{PR_NUMBER}`, `{BRANCH}`, `{FAILING_CHECKS}` into the prompt.
300
+ Substitute `{PR_NUMBER}`, `{BRANCH}`, `{FAILING_CHECKS}`, `{PLATFORM}`,
301
+ `{AZDO_MODE}`, `{AZDO_ORG}`, `{AZDO_ORG_URL}`, `{AZDO_PROJECT}`, `{PAT}` into the prompt.
209
302
 
210
303
  If fixed, return to Stage 3 (run CI watch again).
211
304
  If unable to fix after 2 attempts, report to user and stop.
@@ -225,7 +318,8 @@ Task(
225
318
  )
226
319
  ```
227
320
 
228
- Substitute `{PR_NUMBER}`, `{REMOTE}`, `{DEFAULT_BRANCH}`, merge/branch flags.
321
+ Substitute `{PR_NUMBER}`, `{REMOTE}`, `{DEFAULT_BRANCH}`, `{PLATFORM}`,
322
+ `{AZDO_MODE}`, `{AZDO_ORG_URL}`, `{AZDO_PROJECT}`, `{PAT}`, merge/branch flags.
229
323
 
230
324
  Parse LAND_REPORT.
231
325
 
@@ -4,6 +4,8 @@ Subagent prompts for each ship stage. The orchestrator reads these and
4
4
  substitutes template variables before launching each subagent.
5
5
 
6
6
  `{PLATFORM}` is either `github` or `azdo` (detected from remote URL).
7
+ `{AZDO_MODE}` is `cli` or `rest` (only relevant when PLATFORM == azdo).
8
+ `{AZDO_ORG}`, `{AZDO_PROJECT}`, `{AZDO_ORG_URL}` provide AzDO context.
7
9
 
8
10
  ---
9
11
 
@@ -69,7 +71,7 @@ FILES TO EXCLUDE: {FILES_TO_EXCLUDE}
69
71
  EOF
70
72
  )"
71
73
 
72
- **If PLATFORM == azdo:**
74
+ **If PLATFORM == azdo AND AZDO_MODE == cli:**
73
75
  az repos pr create \
74
76
  --title "<type>: <concise title>" \
75
77
  --description "$(cat <<'EOF'
@@ -85,20 +87,38 @@ FILES TO EXCLUDE: {FILES_TO_EXCLUDE}
85
87
  )" \
86
88
  --source-branch "$BRANCH" \
87
89
  --target-branch "{DEFAULT_BRANCH}" \
90
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
88
91
  --output json
89
92
 
93
+ **If PLATFORM == azdo AND AZDO_MODE == rest:**
94
+ REPO_NAME=$(basename -s .git "$(git remote get-url origin)")
95
+ AUTH="Authorization: Basic $(echo -n ":{PAT}" | base64)"
96
+ PR_JSON=$(curl -s -X POST \
97
+ -H "$AUTH" \
98
+ -H "Content-Type: application/json" \
99
+ "{AZDO_ORG_URL}/{AZDO_PROJECT}/_apis/git/repositories/$REPO_NAME/pullrequests?api-version=7.0" \
100
+ -d "{\"sourceRefName\": \"refs/heads/$BRANCH\", \"targetRefName\": \"refs/heads/{DEFAULT_BRANCH}\", \"title\": \"<type>: <concise title>\", \"description\": \"## Summary\\n<1-3 sentences>\\n\\n## Changes\\n<bullets>\\n\\n## Testing\\n- [ ] <steps>\"}")
101
+
90
102
  6. **Gather info**
91
103
 
92
104
  **If PLATFORM == github:**
93
105
  PR_URL=$(gh pr view --json url -q .url)
94
106
  PR_NUMBER=$(gh pr view --json number -q .number)
95
107
 
96
- **If PLATFORM == azdo:**
108
+ **If PLATFORM == azdo AND AZDO_MODE == cli:**
97
109
  # If az repos pr create returned JSON, parse it directly:
98
110
  PR_NUMBER=$(echo "$PR_JSON" | jq -r '.pullRequestId')
99
111
  # Otherwise list to find it:
100
- PR_NUMBER=$(az repos pr list --source-branch "$BRANCH" --status active --query '[0].pullRequestId' -o tsv)
101
- PR_URL=$(az repos pr show --id $PR_NUMBER --query 'repository.webUrl' -o tsv)/pullrequest/$PR_NUMBER
112
+ PR_NUMBER=$(az repos pr list --source-branch "$BRANCH" --status active \
113
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
114
+ --query '[0].pullRequestId' -o tsv)
115
+ PR_URL="{AZDO_ORG_URL}/{AZDO_PROJECT}/_git/$(basename -s .git "$(git remote get-url origin)")/pullrequest/$PR_NUMBER"
116
+
117
+ **If PLATFORM == azdo AND AZDO_MODE == rest:**
118
+ # Parse from the create response JSON:
119
+ PR_NUMBER=$(echo "$PR_JSON" | jq -r '.pullRequestId')
120
+ REPO_NAME=$(basename -s .git "$(git remote get-url origin)")
121
+ PR_URL="{AZDO_ORG_URL}/{AZDO_PROJECT}/_git/$REPO_NAME/pullrequest/$PR_NUMBER"
102
122
 
103
123
  COMMITS=$(git log {REMOTE}/{DEFAULT_BRANCH}..HEAD --oneline)
104
124
  DIFF_STAT=$(git diff {REMOTE}/{DEFAULT_BRANCH} --shortstat)
@@ -145,14 +165,16 @@ BRANCH: {BRANCH}
145
165
  2. **Report final status**
146
166
  gh pr checks {PR_NUMBER}
147
167
 
148
- **If PLATFORM == azdo:**
168
+ **If PLATFORM == azdo AND AZDO_MODE == cli:**
149
169
 
150
170
  1. **Wait for CI to start** (pipelines may take time to trigger after PR creation)
151
171
  Poll until at least one run appears (max 2 minutes, check every 15s):
152
172
  ```
153
173
  RUNS_FOUND=false
154
174
  for i in $(seq 1 8); do
155
- RUN_COUNT=$(az pipelines runs list --branch "$BRANCH" --top 5 --query "length(@)" -o tsv 2>/dev/null)
175
+ RUN_COUNT=$(az pipelines runs list --branch "$BRANCH" --top 5 \
176
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
177
+ --query "length(@)" -o tsv 2>/dev/null)
156
178
  if [ -n "$RUN_COUNT" ] && [ "$RUN_COUNT" != "0" ]; then
157
179
  RUNS_FOUND=true
158
180
  break
@@ -162,27 +184,101 @@ BRANCH: {BRANCH}
162
184
  ```
163
185
  If no runs appear after 2 minutes, also check PR policy evaluations:
164
186
  ```
165
- az repos pr policy list --id {PR_NUMBER} --query "[].{name:configuration.type.displayName, status:status}" -o table
187
+ az repos pr policy list --id {PR_NUMBER} \
188
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
189
+ --query "[].{name:configuration.type.displayName, status:status}" -o table
166
190
  ```
167
191
  If no policies exist either, report `no_checks`.
168
192
 
169
- 2. **Wait for runs to complete** (max 30 minutes, check every 30s)
193
+ 2. **Wait for runs to complete — with fail-fast** (max 30 minutes, check every 30s)
170
194
  ```
171
195
  for i in $(seq 1 60); do
172
- IN_PROGRESS=$(az pipelines runs list --branch "$BRANCH" --top 5 --query "[?status=='inProgress'] | length(@)" -o tsv)
196
+ # Check for failures FIRST stop immediately if any run has failed
197
+ FAILED=$(az pipelines runs list --branch "$BRANCH" --top 5 \
198
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
199
+ --query "[?result=='failed'] | length(@)" -o tsv 2>/dev/null)
200
+ if [ -n "$FAILED" ] && [ "$FAILED" != "0" ]; then
201
+ echo "CI failure detected — stopping wait"
202
+ break
203
+ fi
204
+
205
+ # Then check if anything is still running
206
+ IN_PROGRESS=$(az pipelines runs list --branch "$BRANCH" --top 5 \
207
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
208
+ --query "[?status=='inProgress'] | length(@)" -o tsv 2>/dev/null)
173
209
  if [ "$IN_PROGRESS" = "0" ] || [ -z "$IN_PROGRESS" ]; then break; fi
174
210
  sleep 30
175
211
  done
176
212
  ```
177
213
 
178
- 3. **Report final status**
179
- Check both pipeline runs and PR policy evaluations:
214
+ 3. **Determine final status**
215
+ Query both pipeline runs and PR policy evaluations:
216
+ ```
217
+ az pipelines runs list --branch "$BRANCH" --top 5 \
218
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
219
+ --query "[].{name:definition.name, status:status, result:result}" -o table
220
+ az repos pr policy list --id {PR_NUMBER} \
221
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
222
+ --query "[].{name:configuration.type.displayName, status:status}" -o table
223
+ ```
224
+
225
+ **Map results to CHECKS_REPORT status:**
226
+ - Any pipeline with `result == "failed"` → `some_failed`
227
+ - Any policy with `status == "rejected"` → `some_failed`
228
+ - All pipelines `result == "succeeded"` AND no rejected policies → `all_passed`
229
+ - Pipelines still `inProgress` after timeout → `pending`
230
+ - No pipelines and no policies found → `no_checks`
231
+
232
+ **IMPORTANT:** Do NOT report `all_passed` if any run has `result == "failed"`.
233
+ Do NOT continue waiting once a failure is detected — report `some_failed`
234
+ immediately with the failing check names.
235
+
236
+ **If PLATFORM == azdo AND AZDO_MODE == rest:**
237
+
238
+ 1. **Wait for CI to start** (max 2 minutes, check every 15s)
239
+ ```
240
+ REPO_NAME=$(basename -s .git "$(git remote get-url origin)")
241
+ AUTH="Authorization: Basic $(echo -n ":{PAT}" | base64)"
242
+ BUILDS_URL="{AZDO_ORG_URL}/{AZDO_PROJECT}/_apis/build/builds?branchName=refs/heads/$BRANCH&\$top=5&api-version=7.0"
243
+
244
+ RUNS_FOUND=false
245
+ for i in $(seq 1 8); do
246
+ RUN_COUNT=$(curl -s -H "$AUTH" "$BUILDS_URL" | jq '.value | length')
247
+ if [ -n "$RUN_COUNT" ] && [ "$RUN_COUNT" != "0" ]; then
248
+ RUNS_FOUND=true
249
+ break
250
+ fi
251
+ sleep 15
252
+ done
253
+ ```
254
+ If no runs appear, check PR policy evaluations via REST:
255
+ ```
256
+ EVALS=$(curl -s -H "$AUTH" \
257
+ "{AZDO_ORG_URL}/{AZDO_PROJECT}/_apis/policy/evaluations?artifactId=vstfs:///CodeReview/CodeReviewId/{AZDO_PROJECT}/{PR_NUMBER}&api-version=7.0")
258
+ EVAL_COUNT=$(echo "$EVALS" | jq '.value | length')
259
+ ```
260
+ If no evaluations exist either, report `no_checks`.
261
+
262
+ 2. **Wait for runs to complete — with fail-fast** (max 30 minutes, check every 30s)
180
263
  ```
181
- az pipelines runs list --branch "$BRANCH" --top 5 --query "[].{name:definition.name, status:status, result:result}" -o table
182
- az repos pr policy list --id {PR_NUMBER} --query "[].{name:configuration.type.displayName, status:status}" -o table
264
+ for i in $(seq 1 60); do
265
+ BUILDS_JSON=$(curl -s -H "$AUTH" "$BUILDS_URL")
266
+
267
+ # Check for failures FIRST
268
+ FAILED=$(echo "$BUILDS_JSON" | jq '[.value[] | select(.result=="failed")] | length')
269
+ if [ "$FAILED" != "0" ]; then
270
+ echo "CI failure detected — stopping wait"
271
+ break
272
+ fi
273
+
274
+ # Check if anything still running
275
+ IN_PROGRESS=$(echo "$BUILDS_JSON" | jq '[.value[] | select(.status=="inProgress")] | length')
276
+ if [ "$IN_PROGRESS" = "0" ]; then break; fi
277
+ sleep 30
278
+ done
183
279
  ```
184
- A policy status of `approved` or `queued` with no `rejected` means passed.
185
- A pipeline result of `succeeded` means passed; `failed` means failed.
280
+
281
+ 3. **Determine final status** same mapping rules as CLI mode above.
186
282
 
187
283
  ## Output Format
188
284
 
@@ -216,14 +312,29 @@ FAILING CHECKS: {FAILING_CHECKS}
216
312
  gh run list --branch {BRANCH} --status failure --json databaseId --jq '.[0].databaseId'
217
313
  gh run view <run-id> --log-failed
218
314
 
219
- **If PLATFORM == azdo:**
220
- RUN_ID=$(az pipelines runs list --branch {BRANCH} --top 1 --query "[?result=='failed'].id | [0]" -o tsv)
221
- az pipelines runs show --id $RUN_ID --output json
315
+ **If PLATFORM == azdo AND AZDO_MODE == cli:**
316
+ RUN_ID=$(az pipelines runs list --branch {BRANCH} --top 1 \
317
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
318
+ --query "[?result=='failed'].id | [0]" -o tsv)
319
+ az pipelines runs show --id $RUN_ID \
320
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" --output json
222
321
  # Get timeline for detailed step failures:
223
322
  az devops invoke --area build --resource timeline \
224
- --route-parameters project=$(az devops configure -l --query '[?name==`project`].value' -o tsv) buildId=$RUN_ID \
323
+ --route-parameters project="{AZDO_PROJECT}" buildId=$RUN_ID \
324
+ --org "{AZDO_ORG_URL}" \
225
325
  --api-version 7.0 --query "records[?result=='failed'].{name:name, log:log.url}" -o table
226
326
 
327
+ **If PLATFORM == azdo AND AZDO_MODE == rest:**
328
+ AUTH="Authorization: Basic $(echo -n ":{PAT}" | base64)"
329
+ # Get failed build ID
330
+ RUN_ID=$(curl -s -H "$AUTH" \
331
+ "{AZDO_ORG_URL}/{AZDO_PROJECT}/_apis/build/builds?branchName=refs/heads/{BRANCH}&resultFilter=failed&\$top=1&api-version=7.0" \
332
+ | jq -r '.value[0].id')
333
+ # Get timeline for step-level failures
334
+ curl -s -H "$AUTH" \
335
+ "{AZDO_ORG_URL}/{AZDO_PROJECT}/_apis/build/builds/$RUN_ID/timeline?api-version=7.0" \
336
+ | jq '.records[] | select(.result=="failed") | {name, log: .log.url}'
337
+
227
338
  2. **Analyze and fix**
228
339
  Read the relevant source files, understand the failures, fix the code.
229
340
 
@@ -267,33 +378,80 @@ BRANCH_FLAGS: {--delete-branch (default) | omit if --keep-branch}
267
378
  **If PLATFORM == github:**
268
379
  gh pr merge {PR_NUMBER} {MERGE_FLAGS} {BRANCH_FLAGS}
269
380
 
270
- **If PLATFORM == azdo:**
381
+ **If PLATFORM == azdo AND AZDO_MODE == cli:**
271
382
  # 1. Verify all policies pass before attempting merge
272
- REJECTED=$(az repos pr policy list --id {PR_NUMBER} --query "[?status=='rejected'] | length(@)" -o tsv 2>/dev/null)
383
+ REJECTED=$(az repos pr policy list --id {PR_NUMBER} \
384
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
385
+ --query "[?status=='rejected'] | length(@)" -o tsv 2>/dev/null)
273
386
  if [ -n "$REJECTED" ] && [ "$REJECTED" != "0" ]; then
274
387
  echo "ERROR: $REJECTED PR policies are rejected — cannot merge"
275
- az repos pr policy list --id {PR_NUMBER} --query "[?status=='rejected'].{name:configuration.type.displayName, status:status}" -o table
276
- # Report failure
388
+ az repos pr policy list --id {PR_NUMBER} \
389
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
390
+ --query "[?status=='rejected'].{name:configuration.type.displayName, status:status}" -o table
277
391
  exit 1
278
392
  fi
279
393
 
280
- # 2. Complete the PR with merge strategy
281
- MERGE_STRATEGY="squash" # default; use "noFastForward" if --no-squash
282
- DELETE_BRANCH="true" # default; use "false" if --keep-branch
394
+ # 2. Resolve merge strategy from flags
395
+ if echo "{MERGE_FLAGS}" | grep -q "\-\-merge"; then
396
+ SQUASH_FLAG="false"
397
+ else
398
+ SQUASH_FLAG="true"
399
+ fi
400
+ if echo "{BRANCH_FLAGS}" | grep -q "\-\-keep-branch"; then
401
+ DELETE_FLAG="false"
402
+ else
403
+ DELETE_FLAG="true"
404
+ fi
283
405
 
406
+ # 3. Complete the PR
284
407
  az repos pr update --id {PR_NUMBER} --status completed \
285
- --squash $( [ "$MERGE_STRATEGY" = "squash" ] && echo "true" || echo "false" ) \
286
- --delete-source-branch $DELETE_BRANCH
408
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
409
+ --squash "$SQUASH_FLAG" \
410
+ --delete-source-branch "$DELETE_FLAG"
411
+ MERGE_RC=$?
287
412
 
288
- # 3. If merge fails (e.g. policies still evaluating), wait and retry once
289
- if [ $? -ne 0 ]; then
413
+ # 4. If merge fails (e.g. policies still evaluating), wait and retry once
414
+ if [ $MERGE_RC -ne 0 ]; then
290
415
  echo "Merge failed, waiting 30s for policies to finalize..."
291
416
  sleep 30
292
417
  az repos pr update --id {PR_NUMBER} --status completed \
293
- --squash $( [ "$MERGE_STRATEGY" = "squash" ] && echo "true" || echo "false" ) \
294
- --delete-source-branch $DELETE_BRANCH
418
+ --org "{AZDO_ORG_URL}" --project "{AZDO_PROJECT}" \
419
+ --squash "$SQUASH_FLAG" \
420
+ --delete-source-branch "$DELETE_FLAG"
295
421
  fi
296
422
 
423
+ **If PLATFORM == azdo AND AZDO_MODE == rest:**
424
+ AUTH="Authorization: Basic $(echo -n ":{PAT}" | base64)"
425
+ REPO_NAME=$(basename -s .git "$(git remote get-url origin)")
426
+ PR_API="{AZDO_ORG_URL}/{AZDO_PROJECT}/_apis/git/repositories/$REPO_NAME/pullrequests/{PR_NUMBER}"
427
+
428
+ # 1. Check for rejected policy evaluations
429
+ EVALS=$(curl -s -H "$AUTH" \
430
+ "{AZDO_ORG_URL}/{AZDO_PROJECT}/_apis/policy/evaluations?artifactId=vstfs:///CodeReview/CodeReviewId/{AZDO_PROJECT}/{PR_NUMBER}&api-version=7.0")
431
+ REJECTED=$(echo "$EVALS" | jq '[.value[] | select(.status=="rejected")] | length')
432
+ if [ "$REJECTED" != "0" ]; then
433
+ echo "ERROR: PR has rejected policy evaluations — cannot merge"
434
+ echo "$EVALS" | jq '.value[] | select(.status=="rejected") | {name: .configuration.type.displayName, status}'
435
+ exit 1
436
+ fi
437
+
438
+ # 2. Resolve merge strategy from flags
439
+ if echo "{MERGE_FLAGS}" | grep -q "\-\-merge"; then
440
+ MERGE_STRATEGY="noFastForward"
441
+ else
442
+ MERGE_STRATEGY="squash"
443
+ fi
444
+ if echo "{BRANCH_FLAGS}" | grep -q "\-\-keep-branch"; then
445
+ DELETE_BRANCH="false"
446
+ else
447
+ DELETE_BRANCH="true"
448
+ fi
449
+
450
+ # 3. Complete the PR
451
+ curl -s -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
452
+ "$PR_API?api-version=7.0" \
453
+ -d "{\"status\": \"completed\", \"completionOptions\": {\"mergeStrategy\": \"$MERGE_STRATEGY\", \"deleteSourceBranch\": $DELETE_BRANCH}}"
454
+
297
455
  2. **Sync local repository**
298
456
  Invoke `/sync` to checkout {DEFAULT_BRANCH}, pull latest changes, restore
299
457
  any stashed work, and clean up merged branches. This replaces manual git
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: speccy
3
- description: Deep-dive interview skill for creating comprehensive specifications. Reviews existing code and docs, then interviews the user through multiple rounds of targeted questions covering technical implementation, UI/UX, concerns, and tradeoffs. Produces a structured spec via create-specification. Use when starting a new feature, system, or major change that needs a spec.
3
+ description: Deep-dive interview skill for creating comprehensive specifications. Reviews existing code and docs, then interviews the user through multiple rounds of targeted questions covering technical implementation, UI/UX, concerns, and tradeoffs. Produces a structured spec in specs/. Use when starting a new feature, system, or major change that needs a spec.
4
4
  argument-hint: Goal, feature, or high-level description to specify
5
- allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Agent, AskUserQuestion
5
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Agent, AskUserQuestion, Skill
6
6
  ---
7
7
 
8
8
  # Speccy - Interview-Driven Specification Builder
@@ -60,10 +60,11 @@ Status icons: ✅ done · ❌ failed · ⚠️ degraded · ⏳ working · ⏭️
60
60
  ---
61
61
 
62
62
  Interview the user through multiple rounds of targeted questions to build
63
- a comprehensive specification. Then hand off to the `create-specification`
64
- skill to produce the final structured spec document.
63
+ a comprehensive specification, then write it directly using the spec template
64
+ in `references/spec-template.md`.
65
65
 
66
66
  Interview prompts and question guidelines: `references/interview-guide.md`
67
+ Spec template and writing guidelines: `references/spec-template.md`
67
68
 
68
69
  ## Pre-flight
69
70
 
@@ -71,15 +72,12 @@ Before starting, check all dependencies in this table:
71
72
 
72
73
  | Dependency | Type | Check | Required | Resolution | Detail |
73
74
  |-----------|------|-------|----------|------------|--------|
74
- | create-specification | skill | `~/.claude/skills/create-specification/SKILL.md` or `~/.agents/skills/create-specification/SKILL.md` | yes | ask | This skill is needed to format the final spec. Install with: `npx skills add slamb2k/mad-skills --skill create-specification` |
75
75
  | prime | skill | `~/.claude/skills/prime/SKILL.md` or `~/.claude/plugins/marketplaces/slamb2k/skills/prime/SKILL.md` | no | fallback | Context loading; falls back to manual project scan |
76
76
 
77
77
  For each row, in order:
78
78
  1. Test file existence (check both paths for symlinked skills)
79
79
  2. If found: continue silently
80
80
  3. If missing: apply Resolution strategy
81
- - **ask**: Notify user the skill is missing, offer to install it. If they
82
- decline, halt execution — the final spec cannot be produced without it.
83
81
  4. After all checks: proceed to context gathering
84
82
 
85
83
  ---
@@ -90,12 +88,12 @@ Before asking any questions, build a thorough understanding of the project:
90
88
 
91
89
  1. **Capture GOAL** — the user's argument describing what needs to be specified
92
90
  2. **Load project context** — invoke `/prime` to load domain-specific context
93
- (CLAUDE.md, goals, specs, memory). If /prime is unavailable, fall back to
91
+ (CLAUDE.md, specs, memory). If /prime is unavailable, fall back to
94
92
  the manual scan below.
95
93
  3. **Scan the project** (skip items already loaded by /prime):
96
94
  - Read `CLAUDE.md` if present (project conventions, structure, domain)
97
- - Read spec directory: `specs/` for existing specifications
98
- - Scan existing specs and design docs for context
95
+ - Scan `specs/` directory for existing specifications
96
+ - Scan existing design docs for context
99
97
  - Read relevant source code that relates to the GOAL
100
98
  - Check memory for prior decisions or open questions related to the GOAL
101
99
  3. **Identify knowledge gaps** — what must you learn from the user to write
@@ -163,19 +161,26 @@ proceeding to spec generation.
163
161
 
164
162
  Once the interview is complete and decisions are confirmed:
165
163
 
166
- 1. **Invoke the `create-specification` skill** using the Skill tool:
164
+ 1. **Create `specs/` directory** if it doesn't exist:
167
165
  ```
168
- Skill(skill: "create-specification")
166
+ mkdir -p specs
169
167
  ```
170
168
 
171
- 2. **Provide the full context** to the skill as input:
172
- - The original GOAL
173
- - All decisions from the interview rounds
174
- - Any relevant code/architecture context discovered in Stage 1
175
- - The spec purpose should match the GOAL description
169
+ 2. **Read the spec template** from `references/spec-template.md`
176
170
 
177
- 3. The `create-specification` skill will handle formatting, naming, and
178
- saving the spec file according to its own template and conventions.
171
+ 3. **Generate the spec** by filling the template with:
172
+ - The original GOAL as the introduction and purpose
173
+ - All decisions from the interview rounds, mapped to the appropriate sections
174
+ - Code/architecture context discovered in Stage 1
175
+ - Acceptance criteria derived from requirements decisions
176
+ - Test strategy aligned with the project's existing patterns
177
+
178
+ 4. **Write the spec file** to `specs/{name}.md` where `{name}` is a
179
+ kebab-case slug derived from the GOAL (e.g., `specs/user-auth.md`,
180
+ `specs/payment-integration.md`). Use the Write tool directly.
181
+
182
+ 5. The `specs/` directory is the standard location — `/build` and `/prime`
183
+ both scan it automatically.
179
184
 
180
185
  ---
181
186
 
@@ -201,6 +206,10 @@ After the spec is created, report to the user:
201
206
  │ 🔗 Links
202
207
  │ Spec: {spec file path}
203
208
 
209
+ │ ⚡ Next steps
210
+ │ 1. Review the spec: {path}
211
+ │ 2. Run `/build {spec path}` to implement (reads the file automatically)
212
+
204
213
  └─────────────────────────────────────────────────
205
214
  ```
206
215
 
@@ -0,0 +1,113 @@
1
+ # Specification Template
2
+
3
+ Use this template when generating the final specification document in Stage 3.
4
+ Fill every section with content from the interview decisions and project context.
5
+ Omit sections that are genuinely not applicable, but err on the side of inclusion.
6
+
7
+ ## Writing Guidelines
8
+
9
+ - Use precise, explicit, and unambiguous language
10
+ - Clearly distinguish between requirements, constraints, and recommendations
11
+ - Use structured formatting (headings, lists, tables) for easy parsing
12
+ - Avoid idioms, metaphors, or context-dependent references
13
+ - Define all acronyms and domain-specific terms
14
+ - Include examples and edge cases where applicable
15
+ - Ensure the document is self-contained and does not rely on external context
16
+
17
+ ## File Naming
18
+
19
+ Save to `specs/{slug}.md` where `{slug}` is a kebab-case name derived from
20
+ the GOAL. Examples: `specs/user-auth.md`, `specs/payment-integration.md`.
21
+
22
+ ## Template
23
+
24
+ ```md
25
+ ---
26
+ title: [Concise Title Describing the Specification's Focus]
27
+ version: 1.0
28
+ date_created: [YYYY-MM-DD]
29
+ last_updated: [YYYY-MM-DD]
30
+ tags: [e.g., infrastructure, process, design, app, schema, tool, data, architecture]
31
+ ---
32
+
33
+ # Introduction
34
+
35
+ [A short concise introduction to the specification and the goal it is intended to achieve.]
36
+
37
+ ## 1. Purpose & Scope
38
+
39
+ [Clear, concise description of the specification's purpose and scope. State the intended audience and any assumptions.]
40
+
41
+ ## 2. Definitions
42
+
43
+ [List and define all acronyms, abbreviations, and domain-specific terms used in this specification.]
44
+
45
+ ## 3. Requirements, Constraints & Guidelines
46
+
47
+ [Explicitly list all requirements, constraints, rules, and guidelines. Use bullet points or tables for clarity.]
48
+
49
+ - **REQ-001**: [Functional requirement]
50
+ - **SEC-001**: [Security requirement]
51
+ - **CON-001**: [Constraint]
52
+ - **GUD-001**: [Guideline]
53
+ - **PAT-001**: [Pattern to follow]
54
+
55
+ ## 4. Interfaces & Data Contracts
56
+
57
+ [Describe the interfaces, APIs, data contracts, or integration points. Use tables or code blocks for schemas and examples.]
58
+
59
+ ## 5. Acceptance Criteria
60
+
61
+ [Define clear, testable acceptance criteria for each requirement using Given-When-Then format where appropriate.]
62
+
63
+ - **AC-001**: Given [context], When [action], Then [expected outcome]
64
+ - **AC-002**: The system shall [specific behavior] when [condition]
65
+
66
+ ## 6. Test Automation Strategy
67
+
68
+ [Define the testing approach, frameworks, and automation requirements.]
69
+
70
+ - **Test Levels**: Unit, Integration, End-to-End
71
+ - **Frameworks**: [appropriate for the project's stack]
72
+ - **Test Data Management**: [approach for test data creation and cleanup]
73
+ - **CI/CD Integration**: [automated testing in pipelines]
74
+ - **Coverage Requirements**: [minimum code coverage thresholds]
75
+ - **Performance Testing**: [approach for load and performance testing]
76
+
77
+ ## 7. Rationale & Context
78
+
79
+ [Explain the reasoning behind the requirements, constraints, and guidelines. Provide context for design decisions.]
80
+
81
+ ## 8. Dependencies & External Integrations
82
+
83
+ [Define external systems, services, and architectural dependencies. Focus on what is needed rather than how it's implemented.]
84
+
85
+ ### External Systems
86
+ - **EXT-001**: [External system name] - [Purpose and integration type]
87
+
88
+ ### Third-Party Services
89
+ - **SVC-001**: [Service name] - [Required capabilities and SLA requirements]
90
+
91
+ ### Infrastructure Dependencies
92
+ - **INF-001**: [Infrastructure component] - [Requirements and constraints]
93
+
94
+ ### Data Dependencies
95
+ - **DAT-001**: [External data source] - [Format, frequency, and access requirements]
96
+
97
+ ### Technology Platform Dependencies
98
+ - **PLT-001**: [Platform/runtime requirement] - [Version constraints and rationale]
99
+
100
+ **Note**: Focus on architectural and business dependencies, not specific package implementations.
101
+
102
+ ## 9. Examples & Edge Cases
103
+
104
+ [Code snippets or data examples demonstrating correct application, including edge cases.]
105
+
106
+ ## 10. Validation Criteria
107
+
108
+ [List the criteria or tests that must be satisfied for compliance with this specification.]
109
+
110
+ ## 11. Related Specifications / Further Reading
111
+
112
+ [Links to related specs or relevant external documentation.]
113
+ ```