@ikunin/sprintpilot 2.2.31 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +228 -415
  2. package/_Sprintpilot/Sprintpilot.md +76 -8
  3. package/_Sprintpilot/bin/autopilot.js +734 -68
  4. package/_Sprintpilot/lib/orchestrator/action-ledger.js +208 -0
  5. package/_Sprintpilot/lib/orchestrator/adapt.js +93 -15
  6. package/_Sprintpilot/lib/orchestrator/profile-rules.js +7 -16
  7. package/_Sprintpilot/lib/orchestrator/sprint-plan.js +488 -0
  8. package/_Sprintpilot/lib/orchestrator/state-store.js +9 -5
  9. package/_Sprintpilot/lib/orchestrator/user-command-applier.js +78 -0
  10. package/_Sprintpilot/lib/orchestrator/user-commands.js +114 -0
  11. package/_Sprintpilot/lib/orchestrator/verify.js +10 -17
  12. package/_Sprintpilot/manifest.yaml +4 -3
  13. package/_Sprintpilot/modules/autopilot/profiles/_base.yaml +18 -4
  14. package/_Sprintpilot/modules/git/config.yaml +15 -9
  15. package/_Sprintpilot/modules/ma/config.yaml +29 -27
  16. package/_Sprintpilot/scripts/dispatch-layer.js +12 -15
  17. package/_Sprintpilot/scripts/infer-dependencies.js +706 -254
  18. package/_Sprintpilot/scripts/log-timing.js +6 -10
  19. package/_Sprintpilot/scripts/merge-shards.js +21 -23
  20. package/_Sprintpilot/scripts/post-green-gates.js +3 -1
  21. package/_Sprintpilot/scripts/resolve-dag.js +452 -280
  22. package/_Sprintpilot/scripts/sprint-plan.js +1068 -0
  23. package/_Sprintpilot/scripts/state-shard.js +13 -5
  24. package/_Sprintpilot/scripts/summarize-timings.js +2 -3
  25. package/_Sprintpilot/skills/sprint-autopilot-on/SKILL.md +30 -2
  26. package/_Sprintpilot/skills/sprint-autopilot-on/workflow.orchestrator.md +36 -10
  27. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/architecture-mapper.md +10 -8
  28. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/concerns-hunter.md +11 -9
  29. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/integration-mapper.md +11 -9
  30. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/quality-assessor.md +10 -8
  31. package/_Sprintpilot/skills/sprintpilot-codebase-map/agents/stack-analyzer.md +11 -9
  32. package/_Sprintpilot/skills/sprintpilot-codebase-map/workflow.md +1 -1
  33. package/_Sprintpilot/skills/sprintpilot-dependency-graph/SKILL.md +63 -0
  34. package/_Sprintpilot/skills/sprintpilot-dependency-graph/workflow.md +227 -0
  35. package/_Sprintpilot/skills/sprintpilot-plan-sprint/SKILL.md +67 -0
  36. package/_Sprintpilot/skills/sprintpilot-plan-sprint/workflow.md +435 -0
  37. package/_Sprintpilot/skills/sprintpilot-sprint-progress/SKILL.md +53 -0
  38. package/_Sprintpilot/skills/sprintpilot-sprint-progress/workflow.md +169 -0
  39. package/lib/commands/install.js +186 -12
  40. package/package.json +1 -1
  41. package/_Sprintpilot/skills/sprintpilot-code-review/SKILL.md +0 -6
  42. package/_Sprintpilot/skills/sprintpilot-code-review/agents/acceptance-auditor.md +0 -51
  43. package/_Sprintpilot/skills/sprintpilot-code-review/agents/blind-hunter.md +0 -39
  44. package/_Sprintpilot/skills/sprintpilot-code-review/agents/edge-case-hunter.md +0 -46
  45. package/_Sprintpilot/skills/sprintpilot-code-review/workflow.md +0 -111
  46. package/_Sprintpilot/skills/sprintpilot-party-mode/SKILL.md +0 -6
  47. package/_Sprintpilot/skills/sprintpilot-party-mode/workflow.md +0 -138
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: sprintpilot-plan-sprint
3
+ description: 'Build (or refresh) the Sprintpilot sprint plan at _bmad-output/implementation-artifacts/sprint-plan.yaml. Infers per-epic + cross-epic dependencies from epics.md + architecture.md + sprint-status.yaml, presents the DAG, lets the user curate which stories belong in the active plan, and persists the result. Triggered by /sprintpilot-plan-sprint, by the autopilot when a stale plan is detected, or by `replan_sprint` mid-flight. Replaces the manual `infer-dependencies.js` workflow for end users.'
4
+ ---
5
+
6
+ ## STOP — read this entire file before doing anything
7
+
8
+ This skill writes the authoritative sprint plan at
9
+ `_bmad-output/implementation-artifacts/sprint-plan.yaml`. The plan
10
+ controls which story Sprintpilot runs next and in what order, with
11
+ dependency-aware priorities and optional external-tracker links.
12
+
13
+ Follow **`./workflow.md`** verbatim. The 14 steps it lists are not
14
+ suggestions — each one shells out to a primitive (`infer-dependencies.js`,
15
+ `resolve-dag.js`, `sprint-plan.js`) that validates inputs and updates
16
+ the plan atomically. Skipping a step or reordering them produces an
17
+ inconsistent plan that downstream phases (autopilot queue resolver,
18
+ reorder validator) will reject.
19
+
20
+ ### Never improvise
21
+
22
+ - Never infer dependencies in chat — always pipe LLM JSON through
23
+ `node _Sprintpilot/scripts/infer-dependencies.js dry-run --epic <id>`
24
+ (or `--cross-epic`) first. The script enforces schema, unknown-key,
25
+ self-dep, cross-epic-isolation, missing-rationale, and cycle checks.
26
+ Hand-edited envelopes that bypass dry-run leave a plan that fails
27
+ validation on the next read.
28
+ - Never write directly to `sprint-plan.yaml` — route every mutation
29
+ through `node _Sprintpilot/scripts/sprint-plan.js` so atomic write,
30
+ schema validation, and `generated`/`auto_inferred_at` stamping happen.
31
+ - Never call an LLM "to plan the sprint" outside this skill. The skill
32
+ IS the LLM-driving layer; scripts never call models.
33
+
34
+ ### Invocation modes
35
+
36
+ The skill responds to three callers:
37
+
38
+ 1. **User-direct:** `/sprintpilot-plan-sprint` with no arguments.
39
+ Build a plan from scratch (or refresh existing one).
40
+ 2. **Auto-derive:** the autopilot emits
41
+ `invoke_skill: sprintpilot-plan-sprint` with
42
+ `template_slots: { auto: true, reason, missing_keys?, removed_keys? }`
43
+ when a plan is missing/stale and the user opted in via
44
+ `autopilot.auto_plan_on_start: true`.
45
+ 3. **Replan:** the autopilot emits the same action with
46
+ `template_slots: { replan: true, reason }` after the user issued
47
+ `user_input { kind: 'replan_sprint' }` mid-flight.
48
+
49
+ In every mode the skill follows the same 14-step workflow — only the
50
+ "present results" tone differs (auto/replan modes assume the user wants
51
+ a brief summary; user-direct mode is more conversational).
52
+
53
+ ### When NOT to invoke
54
+
55
+ - BMad's `sprint-status.yaml` is missing → run `bmad-sprint-planning`
56
+ first; this skill has no work to do.
57
+ - `epics.md` or `architecture.md` missing in
58
+ `_bmad-output/planning-artifacts/` → halt with a clear message
59
+ asking the user to run `bmad-create-epics-and-stories` and
60
+ `bmad-create-architecture` first.
61
+ - The user only wants to see the existing DAG without editing →
62
+ use `node _Sprintpilot/scripts/resolve-dag.js render` directly;
63
+ no need to invoke this full skill.
64
+
65
+ ---
66
+
67
+ Follow the instructions in ./workflow.md.
@@ -0,0 +1,435 @@
1
+ # Sprintpilot — Sprint Plan Generation
2
+
3
+ ## Purpose
4
+
5
+ Build (or refresh) `_bmad-output/implementation-artifacts/sprint-plan.yaml`
6
+ — the authoritative sprint plan that drives autopilot story selection,
7
+ DAG-aware reordering, and external-tracker integration. Infers per-epic
8
+ + cross-epic dependencies via piped LLM envelopes (validated server-side
9
+ by `infer-dependencies.js`), lets the user curate which stories belong
10
+ in the active plan, and persists everything atomically.
11
+
12
+ ## Prerequisites
13
+
14
+ | Artifact | Path | Required |
15
+ |---|---|---|
16
+ | BMad sprint-status | `_bmad-output/implementation-artifacts/sprint-status.yaml` | yes |
17
+ | BMad epics | `_bmad-output/planning-artifacts/epics.md` | yes |
18
+ | BMad architecture | `_bmad-output/planning-artifacts/architecture.md` | yes |
19
+
20
+ If any required prerequisite is missing, halt with a `user_prompt`
21
+ naming the missing file and the BMad skill that produces it
22
+ (`bmad-sprint-planning`, `bmad-create-epics-and-stories`,
23
+ `bmad-create-architecture`). Do NOT attempt the workflow without them.
24
+
25
+ ## Outputs
26
+
27
+ | File | Location | Purpose |
28
+ |------|----------|---------|
29
+ | `sprint-plan.yaml` | `_bmad-output/implementation-artifacts/` | Authoritative plan (read by autopilot + resolve-dag) |
30
+ | `sprint-plan-dag.mmd` | `_bmad-output/implementation-artifacts/` | Rendered mermaid DAG (refreshed on every plan write) |
31
+ | Archived legacy | `.archive/dependencies.yaml.migrated` | If a pre-v2.3.0 `_Sprintpilot/sprints/dependencies.yaml` existed |
32
+
33
+ ## Conventions used below
34
+
35
+ - `<root>` = the project root passed via `--project-root` (or `cwd`).
36
+ - All scripts live under `_Sprintpilot/scripts/` — invoke via `node <path>`.
37
+ - LLM envelopes are JSON; you produce them, the script validates them.
38
+ - On any 3-iteration validation failure (per-epic OR cross-epic), the
39
+ skill writes `_bmad-output/implementation-artifacts/sprint-plan.yaml.partial`
40
+ with the last attempted envelope + errors header, writes the sentinel
41
+ `.sprint-plan-validation-failed`, and halts with a `user_prompt`
42
+ asking the user to inspect the partial.
43
+
44
+ ---
45
+
46
+ ## Step 1 — Load Inputs
47
+
48
+ <action>Verify the three required artifacts exist:
49
+ - `_bmad-output/implementation-artifacts/sprint-status.yaml`
50
+ - `_bmad-output/planning-artifacts/epics.md`
51
+ - `_bmad-output/planning-artifacts/architecture.md`
52
+
53
+ If any is missing, halt with a `user_prompt` naming what's missing.</action>
54
+
55
+ <action>Read each into memory. Parse epics.md for the list of epic IDs.
56
+ Parse sprint-status.yaml for the list of story keys under
57
+ `development_status:` (or `stories:` for the alternate shape).</action>
58
+
59
+ <action>Read the existing plan if present:
60
+ ```
61
+ node _Sprintpilot/scripts/sprint-plan.js read --project-root <root>
62
+ ```
63
+ Note: `exists: true/false` + the full plan body when present. Used by
64
+ Step 3 to compute staleness and decide which epics need re-inference.</action>
65
+
66
+ ---
67
+
68
+ ## Step 2 — Migrate Legacy Dependencies (One-Shot)
69
+
70
+ <action>Check whether a pre-v2.3.0 sidecar exists at
71
+ `_Sprintpilot/sprints/dependencies.yaml`. If it does AND `sprint-plan.yaml`
72
+ is absent OR has an empty `dependencies.stories` block, run the
73
+ one-shot migration:
74
+ ```
75
+ node _Sprintpilot/scripts/infer-dependencies.js migrate --project-root <root>
76
+ ```
77
+ The migrate command imports the legacy `stories:` + `overrides:` blocks
78
+ into the new plan, drops the legacy `epics:` block with a warning,
79
+ and moves the old file to `.archive/dependencies.yaml.migrated`.
80
+
81
+ If `migrated: false` and `reason: 'no_legacy_file'` — proceed silently.
82
+ If `migrated: false` for any other reason — surface the message in a
83
+ `user_prompt` and ask whether to continue with a fresh plan.</action>
84
+
85
+ ---
86
+
87
+ ## Step 3 — Staleness Check
88
+
89
+ <action>Compute which epics need re-inference. The cheap way is to
90
+ ask the orchestrator helper:
91
+ ```
92
+ node -e "
93
+ const m = require('./_Sprintpilot/lib/orchestrator/sprint-plan.js');
94
+ console.log(JSON.stringify(m.planStaleness({projectRoot: process.cwd()})));
95
+ "
96
+ ```
97
+ Returns `{ stale: bool, reason, missing_keys?, removed_keys? }`.
98
+
99
+ Decision matrix:
100
+
101
+ | stale | reason | action |
102
+ |---|---|---|
103
+ | false | — | Skip Step 4 entirely (plan is fresh). Go to Step 5 unless invoked via /sprintpilot-plan-sprint with a "rebuild from scratch" intent. |
104
+ | true | `missing` | Run Step 4 for EVERY epic in epics.md. |
105
+ | true | `migration_needed` | Step 2 should have handled this — re-check; if still missing, run Step 4 for every epic. |
106
+ | true | `added_stories` | Run Step 4 only for the epics whose stories appear in `missing_keys`. |
107
+ | true | `removed_stories` | Run Step 4 for the epics affected (a missing story means the per-epic graph for that epic is stale). |
108
+ | true | `corrupt` | Halt with a `user_prompt` showing the corruption error + offering archive+regenerate. |
109
+
110
+ For hand-authored plans (no AUTO-INFERRED marker AND user-direct invocation
111
+ of /sprintpilot-plan-sprint without explicit "rebuild" intent), confirm
112
+ with a `user_prompt` before regenerating: "An existing plan has hand
113
+ edits in the `dependencies` block. Proceed with regeneration (loses the
114
+ edits) or skip per-epic inference and just refresh DAG render?"</action>
115
+
116
+ ---
117
+
118
+ ## Step 4 — Per-Epic Inference
119
+
120
+ <action>For each epic that needs (re-)inference, run a tight loop:
121
+
122
+ 1. Generate the prompt:
123
+ ```
124
+ node _Sprintpilot/scripts/infer-dependencies.js scaffold-prompt --epic <id> --project-root <root>
125
+ ```
126
+ Stdout is the literal prompt — feed it back to yourself in chat as
127
+ the "next user message" to infer the dependencies. Read the four
128
+ files the prompt names; do not improvise based on memory.
129
+
130
+ 2. Produce a JSON envelope of the EXACT shape:
131
+ ```json
132
+ {
133
+ "version": 1,
134
+ "epic": "<id>",
135
+ "dependencies": { "<story-key>": ["<dep-key>", ...] },
136
+ "rationale": { "<story-key>": "1 sentence quoting the AC/file/architecture line" }
137
+ }
138
+ ```
139
+ Stories with NO inbound deps are omitted from `dependencies`. Every
140
+ listed key needs a non-empty rationale. Cross-epic edges go through
141
+ Step 5 — don't put them here.
142
+
143
+ 3. Validate via dry-run:
144
+ ```
145
+ echo '<envelope>' | node _Sprintpilot/scripts/infer-dependencies.js dry-run --epic <id> --project-root <root>
146
+ ```
147
+ On `valid: true`, proceed. On `valid: false`, the response carries
148
+ an `errors[]` array — fix the envelope and retry. Max 3 iterations
149
+ per epic. On 3rd failure, save the partial + sentinel and halt
150
+ (see "Conventions" above).
151
+
152
+ 4. Commit the envelope:
153
+ ```
154
+ echo '<envelope>' | node _Sprintpilot/scripts/infer-dependencies.js write --epic <id> --project-root <root>
155
+ ```
156
+ `wrote: true, edges_inferred, edges_added, edges_removed` confirms
157
+ success. The script writes into `plan.dependencies.stories.*` while
158
+ preserving entries for other epics and the `overrides:` block.</action>
159
+
160
+ ---
161
+
162
+ ## Step 5 — Cross-Epic Detection
163
+
164
+ <action>Now that per-epic edges are in place, ask the LLM whether
165
+ any edges cross epic boundaries:
166
+
167
+ 1. Generate the cross-epic prompt:
168
+ ```
169
+ node _Sprintpilot/scripts/infer-dependencies.js scaffold-prompt --cross-epic --project-root <root>
170
+ ```
171
+
172
+ 2. Produce a JSON envelope:
173
+ ```json
174
+ {
175
+ "version": 1,
176
+ "cross_epic_deps": [
177
+ { "from_story": "<key>", "to_story": "<key>", "rationale": "<≤200 chars>" }
178
+ ]
179
+ }
180
+ ```
181
+ `from_story` depends on `to_story`. Both keys must belong to
182
+ DIFFERENT epics. If no cross-epic deps detected, send
183
+ `cross_epic_deps: []`.
184
+
185
+ 3. Validate via dry-run:
186
+ ```
187
+ echo '<envelope>' | node _Sprintpilot/scripts/infer-dependencies.js dry-run --cross-epic --project-root <root>
188
+ ```
189
+ Validator checks: keys exist in sprint-status, from/to epics differ,
190
+ rationale present (≤200 chars), no duplicate of per-epic edges,
191
+ no cycle in the combined graph. Max 3 iterations.
192
+
193
+ 4. Present each surviving edge to the user with its rationale:
194
+ ```
195
+ Cross-epic edge detected:
196
+ 2-1-foo depends on 1-3-add-auth
197
+ Rationale: needs auth context from 1-3 before integration
198
+ [a] accept [r] reject [s] skip remaining edges
199
+ ```
200
+ Accept-all, reject-all, or per-edge. Rejected edges drop out;
201
+ accepted edges go through to write.
202
+
203
+ 5. Commit accepted edges:
204
+ ```
205
+ echo '<accepted envelope>' | node _Sprintpilot/scripts/infer-dependencies.js write-cross-epic --project-root <root>
206
+ ```</action>
207
+
208
+ ---
209
+
210
+ ## Step 6 — Issue Tracker Setup (Optional)
211
+
212
+ <action>Ask the user (single user_prompt):
213
+ > "Do you want to link stories to an external issue tracker
214
+ > (Jira / Linear / GitHub / GitLab)? [y/N]"
215
+
216
+ On `n` or skip — proceed to Step 7 without writing the `issue_tracker:`
217
+ block.
218
+
219
+ On `y` — collect:
220
+ - `provider`: one of `jira`, `linear`, `github`, `gitlab`
221
+ - `base_url`: full URL prefix (e.g., `https://co.atlassian.net`)
222
+ - `project_key`: the tracker's project key (e.g., `PROJ` for Jira)
223
+
224
+ Then call the sprint-plan primitive. Currently the simplest path is
225
+ to read the plan, set `plan.issue_tracker = { provider, base_url, project_key }`,
226
+ and write the whole plan back via `node _Sprintpilot/scripts/sprint-plan.js write`
227
+ (piping the modified plan to stdin). The script validates schema and writes
228
+ atomically.</action>
229
+
230
+ ---
231
+
232
+ ## Step 7 — Issue ID Capture (Optional)
233
+
234
+ <action>Ask the user (single user_prompt):
235
+ > "Capture external issue IDs for each epic/story? [Y]es / [n]o
236
+ > / [s]kip remaining for this epic / [p]attern (sequential IDs)"
237
+
238
+ On `n` — proceed to Step 8 without setting any `issue_id` fields.
239
+
240
+ On `Y` — loop through epics and stories. For each entity:
241
+ > "Issue ID for epic 1 (or skip)?"
242
+ > "Issue ID for story 1-3-add-auth (or skip)?"
243
+
244
+ `p` mode prompts once for a prefix (e.g., `PROJ-`) + starting number;
245
+ the skill assigns sequential IDs (`PROJ-100`, `PROJ-101`, …).
246
+
247
+ **Validation rules** — `setIssueId` rejects these inputs (re-prompt if
248
+ they appear; don't retry the same value):
249
+ - Any of: `[ ] < > | ; & \n \r` or ASCII control characters
250
+ - Any Unicode RTL/LTR override marks (`‪`–`‮`, `⁦`–`⁩`)
251
+ - Length > 200 chars
252
+
253
+ Legitimate tracker IDs from Jira (`PROJ-101`), Linear (`LIN-42`),
254
+ GitHub (`org/repo#123`), and GitLab don't contain any of these. If a
255
+ user enters something like `PROJ;101` or pastes a URL with embedded
256
+ brackets, the validator throws — show the error and ask for a clean
257
+ ID. Don't loop on the same broken input.
258
+
259
+ For each captured ID, update the plan via read → mutate → write. The
260
+ relevant primitive is `setIssueId(entity_key, issue_id, { projectRoot })`
261
+ in `sprint-plan.js`; from this skill the simplest path is to bulk-edit
262
+ the plan in memory and write it once at the end of the loop.
263
+
264
+ Bulk skip options ensure this step doesn't become tedious on sprints
265
+ with many stories.</action>
266
+
267
+ ---
268
+
269
+ ## Step 8 — Finalize Dependencies in Plan
270
+
271
+ <action>By this point Steps 4 + 5 have written `plan.dependencies.stories`
272
+ and `plan.cross_epic_deps`. Step 6/7 may have edited `issue_tracker`
273
+ and per-entity `issue_id`. Re-read the plan once to confirm:
274
+ ```
275
+ node _Sprintpilot/scripts/sprint-plan.js read --project-root <root>
276
+ ```
277
+ The plan should validate cleanly. If `exists: true, error: ...` →
278
+ something went wrong; halt with the error.</action>
279
+
280
+ ---
281
+
282
+ ## Step 9 — Build the Sprint-Wide DAG
283
+
284
+ <action>Compute the topological layering for presentation:
285
+ ```
286
+ node _Sprintpilot/scripts/resolve-dag.js graph --project-root <root>
287
+ ```
288
+ Returns `{ nodes, edges, layers, width, cycle }`. If `cycle.length > 0`,
289
+ the combined intra + cross-epic graph has a cycle (validator should
290
+ have caught this earlier; if reached, halt with the offending nodes
291
+ and ask the user to remove the bad edge).</action>
292
+
293
+ ---
294
+
295
+ ## Step 10 — Present the DAG
296
+
297
+ <action>Render a text-mode topological tree to the user:
298
+ ```
299
+ Layer 1 (parallel-eligible width: <N>):
300
+ - 1-1-bootstrap
301
+ - 2-1-foo ← cross-epic upstream of 1-3
302
+ Layer 2:
303
+ - 1-2-models
304
+ Layer 3:
305
+ - 1-3-add-auth (depends on: 1-1, 1-2, 2-1)
306
+ ...
307
+ ```
308
+
309
+ Highlight cross-epic edges with `←` or `cross-epic →` annotations.
310
+ Show summary stats: total stories, total epics, max layer width
311
+ (indicates parallel potential for v2.4.0), count of missing issue IDs.</action>
312
+
313
+ <action>Also write the mermaid DAG file for visual review:
314
+ ```
315
+ node _Sprintpilot/scripts/resolve-dag.js render --format mermaid --project-root <root>
316
+ ```
317
+ Report the path to the user:
318
+ > "DAG rendered to `_bmad-output/implementation-artifacts/sprint-plan-dag.mmd`
319
+ > — preview in any markdown viewer (GitHub, VS Code with Mermaid Preview, etc.)."</action>
320
+
321
+ ---
322
+
323
+ ## Step 11 — Curation
324
+
325
+ <action>Ask the user which stories belong in this sprint plan:
326
+ > "Which stories do you want to run in this sprint?
327
+ > Default: ALL non-done stories.
328
+ > [Enter] accept default [e] edit selection [a:KEY] add [r:KEY] remove"
329
+
330
+ `Default: ALL non-done` means every story in sprint-status whose
331
+ status is not `done`. Excluded stories carry `plan_status: excluded`
332
+ in the plan — they remain visible in the file for context (e.g., as
333
+ upstreams of included stories) but are NOT picked by the queue resolver.</action>
334
+
335
+ <action>On `e` (edit), present a numbered list with `[x]` for included
336
+ and `[ ]` for excluded; the user toggles entries by number.</action>
337
+
338
+ ---
339
+
340
+ ## Step 12 — Validate Selection
341
+
342
+ <action>For each story marked included, every transitive upstream
343
+ (intra-epic AND cross-epic) must be either ALSO included OR already
344
+ done in sprint-status. Compute via the orchestrator helper:
345
+ ```
346
+ node -e "
347
+ const m = require('./_Sprintpilot/lib/orchestrator/sprint-plan.js');
348
+ const plan = require('./_Sprintpilot/scripts/sprint-plan.js').read({projectRoot: process.cwd()});
349
+ const proposed = [/* user-selected keys */];
350
+ console.log(JSON.stringify(m.validateOrdering(proposed, plan, {projectRoot: process.cwd()})));
351
+ "
352
+ ```
353
+ Returns `{ valid, violations: [{story, upstream, suggestion}] }`.
354
+
355
+ On `valid: false`, present each violation:
356
+ > "Story `1-3-add-auth` (included) depends on `1-1-bootstrap` which is
357
+ > not in the plan and not done. Options:
358
+ > [a] add `1-1-bootstrap` to the plan
359
+ > [r] remove `1-3-add-auth` from the plan
360
+ > [x] exclude `1-3-add-auth` (keeps it visible but won't run)"
361
+
362
+ Loop until `valid: true`. Excluded stories carry `plan_status: excluded`
363
+ and the validator treats them as terminal.</action>
364
+
365
+ ---
366
+
367
+ ## Step 13 — Write Plan
368
+
369
+ <action>Build the final plan object in memory:
370
+ - `schema_version: 1`
371
+ - `source: 'skill' | 'auto' | 'cli'` (use `auto` when invoked via
372
+ `template_slots.auto: true`, `skill` otherwise)
373
+ - `plan_id`: keep existing if re-running; generate fresh on first
374
+ curation
375
+ - `epics: []` — per-epic metadata captured in Step 1 (id, title)
376
+ - `stories: []` — per-story entries with `key`, `epic`, `title`,
377
+ `plan_status` (`pending` for included, `excluded` for excluded),
378
+ `issue_id` (from Step 7), `priority` (1-indexed in topological order),
379
+ `upstream` (denormalized from `plan.dependencies.stories.<key>.depends_on`),
380
+ `cross_epic_upstream` (denormalized from `plan.cross_epic_deps`),
381
+ `added_by: 'skill'`, `added_at`
382
+ - `dependencies`, `cross_epic_deps`, `overrides`, `notes` — preserved
383
+ from Steps 4-7
384
+ - `status.last_run_outcome: 'success'`, `status.last_run_at: <now>`,
385
+ `status.last_error: null`
386
+
387
+ Pipe to write:
388
+ ```
389
+ echo '<plan-json>' | node _Sprintpilot/scripts/sprint-plan.js write --project-root <root>
390
+ ```
391
+ The script validates schema, stamps `generated`, and atomically writes
392
+ via tmp+rename.</action>
393
+
394
+ <action>Re-render the DAG to reflect any curation changes:
395
+ ```
396
+ node _Sprintpilot/scripts/resolve-dag.js render --format mermaid --project-root <root>
397
+ ```</action>
398
+
399
+ ---
400
+
401
+ ## Step 14 — Report
402
+
403
+ <action>Summarize what was written:
404
+ > "Sprint plan written to
405
+ > `_bmad-output/implementation-artifacts/sprint-plan.yaml`.
406
+ >
407
+ > - **N** stories planned (M epics)
408
+ > - **X** cross-epic edges
409
+ > - **Y** stories excluded (kept for context)
410
+ > - **Z** stories without issue IDs
411
+ >
412
+ > First 5 in execution order:
413
+ > 1. 1-1-bootstrap
414
+ > 2. 1-2-models
415
+ > 3. ...
416
+ >
417
+ > Run `/sprint-autopilot-on` to begin execution, or
418
+ > `/sprintpilot-plan-sprint` again to refine."</action>
419
+
420
+ <action>If invoked via `template_slots.auto: true` or `replan: true`,
421
+ keep the summary shorter (1-2 sentences) and return cleanly so the
422
+ autopilot session resumes; do not block on confirmation.</action>
423
+
424
+ ---
425
+
426
+ ## Failure modes
427
+
428
+ | Symptom | Recovery |
429
+ |---|---|
430
+ | Prerequisite artifact missing | Halt with `user_prompt` naming the missing file + the BMad skill that produces it. |
431
+ | 3 consecutive validation failures (per-epic OR cross-epic) | Save `sprint-plan.yaml.partial` + `.sprint-plan-validation-failed` sentinel; halt asking the user to inspect. |
432
+ | Cycle in combined intra+cross graph | Halt with the offending nodes; ask the user to remove or re-rationalize the bad edge. |
433
+ | Plan write fails (disk full, permission) | The atomic tmp+rename is all-or-nothing — no torn state. Halt with the error message. |
434
+ | `sprint-plan.yaml` corrupt on entry to Step 3 | Offer archive+regenerate via `user_prompt`. |
435
+ | Skill invoked but `sprint-status.yaml` is empty | No stories to plan; halt and ask the user to run `bmad-sprint-planning` first. |
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: sprintpilot-sprint-progress
3
+ description: 'Synthesize current sprint execution progress with LLM-layered judgment. Reads sprint-plan.yaml, sprint-status.yaml, and the autopilot ledger via `autopilot progress`; highlights stalls, repeated verify failures, retry loops, and stuck phases; suggests the next action (continue, narrow to a specific story, reorder, replan, abort). Use when you want a quick health check between autopilot sessions without scrolling through the raw ledger.'
4
+ ---
5
+
6
+ ## STOP — read this entire file before doing anything
7
+
8
+ This skill is a **read-only diagnostic**. It does not change sprint-plan.yaml,
9
+ sprint-status.yaml, or any persisted autopilot state. The goal is to produce
10
+ a concise human-readable summary of where execution stands and what (if
11
+ anything) the user should do about it.
12
+
13
+ Follow **`./workflow.md`** verbatim. The three steps it lists are:
14
+
15
+ 1. Collect the structured snapshot via `autopilot progress --json`.
16
+ 2. Pull recent ledger entries for halt / verify / step context.
17
+ 3. Synthesize a brief progress report with LLM judgment + one
18
+ recommended next action.
19
+
20
+ ### Never improvise
21
+
22
+ - **No file writes.** This skill is observational. If the user wants to
23
+ reorder, add stories, mark something skipped, or replan — point them
24
+ at the appropriate user_input command or `/sprintpilot-plan-sprint`.
25
+ Don't try to fix things from this skill.
26
+ - **No state interpretation beyond what's in the ledger.** Don't
27
+ speculate about why a verify failed — just report what the ledger
28
+ says and recommend the user look at the relevant file.
29
+ - **No long-form output by default.** Default mode is ≤15 lines. If
30
+ the user asks for more detail, narrow to a story and read its
31
+ recent step events.
32
+
33
+ ### When to invoke
34
+
35
+ - Between autopilot sessions to check whether anything halted that
36
+ needs intervention.
37
+ - When you (the LLM) just finished a long batch of stories and want
38
+ to know if anything's stuck before suggesting next moves.
39
+ - When the user asks "how's the sprint going?" / "where are we?" /
40
+ "is autopilot stuck?".
41
+
42
+ ### When NOT to invoke
43
+
44
+ - For machine-readable output: call
45
+ `node _Sprintpilot/bin/autopilot.js progress --json` directly. This
46
+ skill adds LLM synthesis on top — pure JSON consumers don't need it.
47
+ - For full sprint reports: that's `bmad-sprint-status` (BMad-native,
48
+ reads sprint-status.yaml only).
49
+ - For build / deploy / CI status: not this skill's domain.
50
+
51
+ ---
52
+
53
+ Follow the instructions in ./workflow.md.