context-planning 0.7.0

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 (86) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +454 -0
  3. package/bin/commands/_helpers.js +53 -0
  4. package/bin/commands/_usage.js +67 -0
  5. package/bin/commands/capture.js +46 -0
  6. package/bin/commands/codebase-status.js +41 -0
  7. package/bin/commands/complete-milestone.js +57 -0
  8. package/bin/commands/config.js +70 -0
  9. package/bin/commands/doctor.js +139 -0
  10. package/bin/commands/gsd-import.js +90 -0
  11. package/bin/commands/inbox.js +81 -0
  12. package/bin/commands/index.js +33 -0
  13. package/bin/commands/init.js +87 -0
  14. package/bin/commands/install.js +43 -0
  15. package/bin/commands/scaffold-codebase.js +53 -0
  16. package/bin/commands/scaffold-milestone.js +58 -0
  17. package/bin/commands/scaffold-phase.js +65 -0
  18. package/bin/commands/status.js +42 -0
  19. package/bin/commands/statusline.js +108 -0
  20. package/bin/commands/tick.js +49 -0
  21. package/bin/commands/version.js +9 -0
  22. package/bin/commands/worktree.js +218 -0
  23. package/bin/commands/write-summary.js +54 -0
  24. package/bin/cp.cmd +2 -0
  25. package/bin/cp.js +54 -0
  26. package/commands/cp/capture.md +107 -0
  27. package/commands/cp/complete-milestone.md +166 -0
  28. package/commands/cp/execute-phase.md +220 -0
  29. package/commands/cp/map-codebase.md +211 -0
  30. package/commands/cp/new-milestone.md +136 -0
  31. package/commands/cp/new-project.md +132 -0
  32. package/commands/cp/plan-phase.md +195 -0
  33. package/commands/cp/progress.md +147 -0
  34. package/commands/cp/quick.md +104 -0
  35. package/commands/cp/resume.md +125 -0
  36. package/commands/cp/write-summary.md +33 -0
  37. package/docs/MIGRATION-v0.5.md +140 -0
  38. package/docs/architecture.md +189 -0
  39. package/docs/superpowers/plans/2026-05-20-v0-7-plan-16-01-design-md-infrastructure.md +1064 -0
  40. package/docs/superpowers/plans/2026-05-20-v0-7-plan-16-02-review-log-infrastructure.md +418 -0
  41. package/docs/superpowers/plans/2026-05-20-v0-7-plan-16-03-key-decisions-hard-block.md +295 -0
  42. package/docs/superpowers/specs/2026-05-20-generic-provider-harness-detection-design.md +380 -0
  43. package/docs/superpowers/specs/2026-05-20-v0-7-design-capture-design.md +400 -0
  44. package/docs/writing-providers.md +76 -0
  45. package/install/aider.js +204 -0
  46. package/install/claude.js +116 -0
  47. package/install/common.js +65 -0
  48. package/install/copilot.js +86 -0
  49. package/install/cursor.js +120 -0
  50. package/install/echo-provider.js +50 -0
  51. package/lib/codebase-mapper.js +169 -0
  52. package/lib/detect.js +280 -0
  53. package/lib/frontmatter.js +72 -0
  54. package/lib/gsd-compat.js +165 -0
  55. package/lib/import.js +543 -0
  56. package/lib/inbox.js +226 -0
  57. package/lib/lifecycle.js +929 -0
  58. package/lib/merge.js +157 -0
  59. package/lib/milestone.js +595 -0
  60. package/lib/paths.js +191 -0
  61. package/lib/provider.js +168 -0
  62. package/lib/roadmap.js +134 -0
  63. package/lib/state.js +99 -0
  64. package/lib/worktree.js +253 -0
  65. package/package.json +45 -0
  66. package/templates/DESIGN.md +78 -0
  67. package/templates/INBOX.md +13 -0
  68. package/templates/MILESTONE-CONTEXT.md +40 -0
  69. package/templates/MILESTONES.md +29 -0
  70. package/templates/PLAN.md +84 -0
  71. package/templates/PROJECT.md +43 -0
  72. package/templates/REVIEW-LOG.md +38 -0
  73. package/templates/ROADMAP.md +34 -0
  74. package/templates/STATE.md +78 -0
  75. package/templates/SUMMARY.md +75 -0
  76. package/templates/codebase/ARCHITECTURE.md +30 -0
  77. package/templates/codebase/CONCERNS.md +30 -0
  78. package/templates/codebase/CONVENTIONS.md +30 -0
  79. package/templates/codebase/INTEGRATIONS.md +30 -0
  80. package/templates/codebase/STACK.md +26 -0
  81. package/templates/codebase/STRUCTURE.md +32 -0
  82. package/templates/codebase/TESTING.md +39 -0
  83. package/templates/config.json +173 -0
  84. package/templates/phase-PLAN.md +32 -0
  85. package/templates/quick-PLAN.md +24 -0
  86. package/templates/quick-SUMMARY.md +25 -0
@@ -0,0 +1,400 @@
1
+ ---
2
+ status: accepted
3
+ created: 2026-05-20
4
+ deciders: [user, copilot-cli (cp orchestrator)]
5
+ supersedes: []
6
+ superseded_by: null
7
+ target_milestone: v0.7 Design Capture
8
+ ---
9
+
10
+ # Design: v0.7 — Design Capture (cp ↔ SP)
11
+
12
+ ## Status
13
+
14
+ **Accepted** — 2026-05-20. Target milestone: **v0.7.0**, single phase (16), three plans (16-01 / 16-02 / 16-03).
15
+
16
+ ## Context
17
+
18
+ ### The gap
19
+
20
+ cp delegates the design / plan / execution loop to Superpowers (SP) and owns
21
+ the state layer (PROJECT / ROADMAP / STATE / phases / SUMMARY / MILESTONES).
22
+ After shipping v0.6 "Quality Wave", a retrospective on cp ↔ SP integration
23
+ surfaced three concrete capture gaps:
24
+
25
+ 1. **Design rationale is transient.** `cp-new-milestone` Step 3 delegates to
26
+ SP `brainstorming` and dumps the output into top-level
27
+ `.planning/MILESTONE-CONTEXT.md` — but that file is intentionally
28
+ transient (deleted/moved at `cp complete-milestone`). Architectural
29
+ rationale, rejected alternatives, and gray-area decisions disappear from
30
+ the repo when the milestone closes; only a compressed summary survives in
31
+ `MILESTONES.md`.
32
+
33
+ 2. **Subagent review chain is lost.** SP `subagent-driven-development`
34
+ dispatches fresh subagents per task with a two-stage review (spec
35
+ compliance, then code quality). When a reviewer rejects three approaches
36
+ before approving the fourth, that rejection history lives only in the
37
+ orchestrator's session transcript — never on disk. Code review feedback
38
+ that drove the final implementation is unrecoverable after context
39
+ reset.
40
+
41
+ 3. **`key-decisions` is silently optional.** `cp write-summary` accepts an
42
+ empty/missing `key-decisions` array without complaint. The schema is
43
+ *human-curated*: orchestrators routinely omit it under time pressure,
44
+ then the milestone roll-up has nothing to aggregate.
45
+
46
+ ### Constraints
47
+
48
+ - **No upstream SP changes.** The user explicitly does not want to fork or
49
+ PR against `obra/superpowers-marketplace`. All capture must happen on
50
+ the cp side — either at scaffold time, in cp CLI commands, or in cp's
51
+ own skill files that instruct the orchestrator.
52
+ - **No new SP coupling.** Existing SP skills (`brainstorming`,
53
+ `writing-plans`, `subagent-driven-development`) already accept
54
+ output-path overrides for the files they write — that's leveraged, but
55
+ no API surface beyond that is consumed.
56
+ - **Back-compat.** Existing `.planning/` trees with no `DESIGN.md` /
57
+ `REVIEW-LOG.md` continue to work; the aggregator skips silently.
58
+
59
+ ## Decision
60
+
61
+ Introduce a **three-tier persistent design-capture layer** parallel to the
62
+ existing state docs, owned by cp but written by SP-delegated agents:
63
+
64
+ | Tier | File | Captures | Written by |
65
+ |--------------|-------------------------------------------------------------|------------------------------------------------|----------------------------------------------------------------------------|
66
+ | Milestone | `.planning/milestones/<slug>/DESIGN.md` | Cross-phase architecture, milestone-wide ADRs | SP `brainstorming` via `/cp-new-milestone` Step 3 (path-override) |
67
+ | Phase | `.planning/phases/NN-slug/DESIGN.md` | Cross-plan decisions within a phase | SP `brainstorming` via `/cp-plan-phase` Step 3.5 (NEW, path-override) |
68
+ | Plan | `NN-MM-PLAN.md` `<objective>` block | Per-plan tactical rationale | Already exists — no change |
69
+
70
+ Plus:
71
+
72
+ - **`.planning/phases/NN-slug/REVIEW-LOG.md`** — phase-level, append-only
73
+ record of every subagent review verdict for every task. Populated by the
74
+ orchestrator following an explicit instruction in
75
+ `.github/skills/cp-execute-phase/SKILL.md` Step 4.5 (NEW). One file per
76
+ phase (not per plan) — append-only with plan-id-tagged entries.
77
+
78
+ - **`cp write-summary` validation hardened** — empty `key-decisions` /
79
+ `key_decisions` is now a hard block (exit code 2) with an actionable
80
+ error message pointing at the spec.
81
+
82
+ - **`templates/DESIGN.md` is the union** of classical ADR (Status, Context,
83
+ Decision, Consequences, References) and SP brainstorming output
84
+ (Architecture, Components, Data Flow, Error Handling, Testing,
85
+ Alternatives Considered, Open Questions). This is a deliberate superset
86
+ so neither audience loses information.
87
+
88
+ ## Consequences
89
+
90
+ ### Positive
91
+
92
+ - Design rationale survives milestone close. Future contributors (and
93
+ future LLM sessions with fresh context) can reconstruct *why* something
94
+ was built, not just *what*.
95
+ - Review history becomes inspectable. A new reviewer can grep
96
+ `REVIEW-LOG.md` to see "this approach was rejected three times — here's
97
+ why" before re-proposing the same solution.
98
+ - `key-decisions` becomes a real field. Empty-by-default is replaced by
99
+ must-fill-or-fail, forcing the orchestrator to record at least one
100
+ decision per plan.
101
+ - Existing files unchanged. `MILESTONE-CONTEXT.md` keeps being written
102
+ for back-compat but is now promoted into the milestone DESIGN.md at
103
+ close (transcript appendix) instead of deleted.
104
+ - No SP coupling. Path overrides + skill-level instructions only. SP can
105
+ update without breaking cp.
106
+
107
+ ### Negative
108
+
109
+ - File-count growth. Each phase grows from `PLAN.md + N×SUMMARY.md` to
110
+ `PLAN.md + DESIGN.md + REVIEW-LOG.md + N×SUMMARY.md`. For tiny phases
111
+ (1 plan, 1 task), DESIGN.md may be sparse — acceptable cost of a
112
+ predictable schema.
113
+ - Orchestrator burden. Plan 16-02's REVIEW-LOG capture depends on the
114
+ cp-execute-phase skill being followed faithfully. If an orchestrator
115
+ ignores Step 4.5, REVIEW-LOG.md stays empty. Mitigation: skill text is
116
+ explicit + the aggregator surfaces "Phase X had 0 review entries" so
117
+ the gap is visible at milestone close.
118
+ - Backfill cost. The 10 SUMMARY files written this session under
119
+ `.planning/phases/*/` predate the `key-decisions` hard-block and will
120
+ need a one-time backfill to keep dogfood tests green. Scoped to plan
121
+ 16-03.
122
+
123
+ ### Neutral
124
+
125
+ - Migration path for old projects: aggregator skips missing files
126
+ silently. No forced migration; new files appear at next scaffold.
127
+
128
+ ## Architecture
129
+
130
+ ```
131
+ ┌─────────────────────────────────────┐
132
+ │ /cp-new-milestone "<name>" │
133
+ └──────────────┬──────────────────────┘
134
+ │ Step 3: delegate to SP brainstorming
135
+ │ with path override
136
+
137
+ ┌──────────────────────────────────────────┐
138
+ │ SP brainstorming │
139
+ │ writes → milestones/<slug>/DESIGN.md │
140
+ │ also dumps → MILESTONE-CONTEXT.md │
141
+ └──────────────────────────────────────────┘
142
+
143
+ ┌─────────────────────────────────────┐
144
+ │ cp scaffold-phase N │
145
+ └──────────────┬──────────────────────┘
146
+ │ creates from templates
147
+
148
+ ┌──────────────────────────────────────────┐
149
+ │ phases/NN-slug/ │
150
+ │ PLAN.md (existing) │
151
+ │ DESIGN.md (NEW, empty) │
152
+ │ REVIEW-LOG.md (NEW, empty) │
153
+ └──────────────────────────────────────────┘
154
+
155
+ ┌─────────────────────────────────────┐
156
+ │ /cp-plan-phase N (Step 3.5 NEW) │
157
+ └──────────────┬──────────────────────┘
158
+ │ delegate to SP brainstorming
159
+ │ path → phases/NN-slug/DESIGN.md
160
+
161
+ (DESIGN.md filled)
162
+
163
+ │ Step 4: existing — delegate to SP writing-plans
164
+ │ DESIGN.md passed as context input
165
+
166
+ (PLAN.md <tasks> filled)
167
+
168
+ ┌─────────────────────────────────────┐
169
+ │ /cp-execute-phase N (Step 4.5 NEW) │
170
+ └──────────────┬──────────────────────┘
171
+ │ after each subagent review:
172
+ │ orchestrator appends entry
173
+
174
+ (REVIEW-LOG.md grows append-only)
175
+
176
+ ┌─────────────────────────────────────┐
177
+ │ cp write-summary (HARDENED) │
178
+ └──────────────┬──────────────────────┘
179
+ │ key-decisions empty? → exit 2
180
+
181
+ (NN-MM-SUMMARY.md written)
182
+
183
+ ┌─────────────────────────────────────┐
184
+ │ cp complete-milestone (EXTENDED) │
185
+ └──────────────┬──────────────────────┘
186
+ │ aggregator now folds:
187
+ │ phase DESIGN.md refs
188
+ │ REVIEW-LOG.md highlights
189
+ │ MILESTONE-CONTEXT.md → milestone DESIGN appendix
190
+
191
+ (MILESTONES.md + final DESIGN.md)
192
+ ```
193
+
194
+ ## Components
195
+
196
+ ### `templates/DESIGN.md` (NEW)
197
+
198
+ Union template combining ADR header (Status / Context / Decision /
199
+ Consequences / References) and SP brainstorming sections (Architecture /
200
+ Components / Data Flow / Error Handling / Testing / Alternatives Considered
201
+ / Open Questions). Frontmatter: `status`, `created`, `updated`,
202
+ `deciders`, `supersedes`, `superseded_by`, plus `phase` or `milestone`
203
+ key depending on tier.
204
+
205
+ ### `templates/REVIEW-LOG.md` (NEW)
206
+
207
+ Append-only Markdown with structured entries:
208
+
209
+ ```markdown
210
+ ## 2026-05-21T14:32 — 16-01
211
+ - **reviewer:** spec-reviewer
212
+ - **verdict:** ❌ rejected (issues fixed)
213
+ - **issues:**
214
+ - DESIGN.md template missing "Status" field
215
+ - Date placeholder not substituted
216
+ - **resolved-in:** abc1234
217
+ ```
218
+
219
+ ### `lib/paths.js` extensions (NEW helpers)
220
+
221
+ - `designFile(phaseNumOrSlug)` → `.planning/phases/NN-slug/DESIGN.md`
222
+ - `reviewLogFile(phaseNumOrSlug)` → `.planning/phases/NN-slug/REVIEW-LOG.md`
223
+ - `milestoneDesignFile(milestoneSlug)` → `.planning/milestones/<slug>/DESIGN.md`
224
+
225
+ ### `lib/lifecycle.js` extensions
226
+
227
+ - `writeSummary()` validates `key-decisions` non-empty; throws structured
228
+ error with exit code 2.
229
+ - `aggregateSummaries()` extended to:
230
+ - Read all phase DESIGN.md files; emit "Phase N design: see
231
+ phases/NN-slug/DESIGN.md" refs into the milestone DESIGN.md.
232
+ - Read all REVIEW-LOG.md files; count entries; surface "Phase N had M
233
+ review iterations across K tasks" in MILESTONES.md.
234
+ - Detect transient `MILESTONE-CONTEXT.md`; promote its content into the
235
+ milestone DESIGN.md as a "Brainstorm transcript" appendix; delete the
236
+ transient file.
237
+
238
+ ### `bin/commands/scaffold-phase.js` extension
239
+
240
+ After writing `PLAN.md`, also write `DESIGN.md` and `REVIEW-LOG.md` from
241
+ their respective templates with phase metadata pre-substituted.
242
+
243
+ ### `bin/commands/scaffold-milestone.js` extension
244
+
245
+ After writing milestone heading in ROADMAP.md, create
246
+ `.planning/milestones/<slug>/` directory with empty `DESIGN.md` scaffolded
247
+ from the milestone-flavored template.
248
+
249
+ ### `.github/skills/cp-*.md` updates
250
+
251
+ - `cp-new-milestone/SKILL.md` Step 3: delegate to SP brainstorming with
252
+ output path override `→ milestones/<slug>/DESIGN.md`. Keep
253
+ MILESTONE-CONTEXT.md as full transcript.
254
+ - `cp-plan-phase/SKILL.md` Step 3.5 (NEW, between current Step 3 and
255
+ Step 4): "Before delegating to writing-plans, delegate to brainstorming
256
+ with output path `→ phases/NN-slug/DESIGN.md`. Pass the phase Goal +
257
+ Success Criteria + Requirements as context. SP fills the DESIGN.md
258
+ template; you do NOT touch frontmatter keys cp populated (phase,
259
+ milestone, status, created)."
260
+ - `cp-execute-phase/SKILL.md` Step 4.5 (NEW): "After each subagent review
261
+ verdict (spec-reviewer, code-quality-reviewer, final-reviewer), append
262
+ an entry to `phases/NN-slug/REVIEW-LOG.md` in the documented format.
263
+ Even if the verdict is ✅ on the first try, log it — empty REVIEW-LOG
264
+ signals broken capture, not no-issues."
265
+ - `cp-execute-phase/SKILL.md` Step 6: "key-decisions REQUIRED. At least
266
+ one entry. Empty → `cp write-summary` exits 2."
267
+
268
+ ## Data Flow
269
+
270
+ ```
271
+ SP brainstorming output ──path-override──▶ milestones/<slug>/DESIGN.md
272
+ ──path-override──▶ phases/NN-slug/DESIGN.md
273
+
274
+ SP writing-plans ──reads──▶ phases/NN-slug/DESIGN.md (as context)
275
+ ──writes─▶ phases/NN-slug/NN-MM-PLAN.md <tasks>
276
+
277
+ SP subagent-driven-dev review verdict
278
+ ──(via orchestrator following skill)──▶ phases/NN-slug/REVIEW-LOG.md (append)
279
+
280
+ cp write-summary ──validates──▶ key-decisions array
281
+ ──writes────▶ phases/NN-slug/NN-MM-SUMMARY.md
282
+
283
+ cp complete-milestone
284
+ ──reads─────▶ ALL phases/*/DESIGN.md, REVIEW-LOG.md, *-SUMMARY.md
285
+ ──promotes──▶ .planning/MILESTONE-CONTEXT.md → milestone DESIGN appendix
286
+ ──writes────▶ milestones/<slug>/DESIGN.md (cross-refs + transcript)
287
+ ──writes────▶ .planning/MILESTONES.md (rolled-up)
288
+ ```
289
+
290
+ ## Error Handling
291
+
292
+ - **Missing template file:** scaffold fails atomically; no partial writes
293
+ (uses existing `lib/atomic-write`).
294
+ - **Empty `key-decisions`:** `cp write-summary` exits 2 with message
295
+ `Error: 'key-decisions' is required and must have ≥1 entry. See spec at docs/superpowers/specs/2026-05-20-v0-7-design-capture-design.md`.
296
+ - **Aggregator finds no DESIGN.md for a phase:** silently skips (back-compat).
297
+ - **Aggregator finds no REVIEW-LOG.md for a phase:** silently skips +
298
+ emits "Phase X had no review log (orchestrator did not capture)"
299
+ diagnostic in MILESTONES.md so the gap is visible.
300
+ - **MILESTONE-CONTEXT.md promotion failure:** logs error, leaves transient
301
+ file in place, continues with rest of aggregation. Non-blocking.
302
+ - **Existing `.planning/phases/*/SUMMARY.md` with empty key-decisions:**
303
+ one-time backfill in plan 16-03 (this session's 10 dogfood SUMMARYs);
304
+ documented in the migration notes.
305
+
306
+ ## Testing Strategy
307
+
308
+ - **Unit (extends `test/unit-libs.js` or new `test/unit-design.js`)**
309
+ - `designFile()` / `reviewLogFile()` / `milestoneDesignFile()` path helpers
310
+ - `aggregateSummaries()` correctly folds DESIGN refs + REVIEW-LOG counts
311
+ - `aggregateSummaries()` correctly promotes MILESTONE-CONTEXT.md
312
+ - `writeSummary()` rejects empty `key-decisions` (positive + negative case)
313
+ - Back-compat: aggregator on phase with no DESIGN/REVIEW-LOG produces
314
+ sane output (no crash, no spurious refs)
315
+ - **CLI dry-run (extends existing `dryrun-*.js` files)**
316
+ - `cp scaffold-phase --dry-run` previews DESIGN.md + REVIEW-LOG.md creation
317
+ - `cp scaffold-milestone --dry-run` previews milestone DESIGN.md
318
+ - `cp complete-milestone --dry-run` previews promotion + cross-refs
319
+ - **Coverage:** maintain 85% lines / 75% branches gate from v0.6.
320
+
321
+ ## Alternatives Considered
322
+
323
+ ### Option A — Upstream PR against `obra/superpowers-marketplace`
324
+
325
+ **Pros:** Cleanest integration; SP itself emits REVIEW-LOG entries; no
326
+ orchestrator burden.
327
+
328
+ **Cons:** Depends on upstream maintainer accepting (could be weeks/months);
329
+ cp v0.7 release blocks on external dependency; couples cp release cadence
330
+ to SP.
331
+
332
+ **Verdict:** Rejected. User explicitly requires no SP changes.
333
+
334
+ ### Option B — Per-plan DESIGN.md (`NN-MM-DESIGN.md`)
335
+
336
+ **Pros:** Granular; each plan owns its design rationale; matches existing
337
+ per-plan PLAN.md / SUMMARY.md pattern.
338
+
339
+ **Cons:** 3× file count growth; SP brainstorming per plan is heavy; mostly
340
+ duplicates `<objective>` block already in PLAN.md; misses cross-plan
341
+ architecture decisions.
342
+
343
+ **Verdict:** Rejected. Plan-level rationale stays in PLAN.md `<objective>`.
344
+
345
+ ### Option C — DESIGN at phase level only (skip milestone tier)
346
+
347
+ **Pros:** Simpler — one new tier instead of two.
348
+
349
+ **Cons:** Doesn't fix the core gap (transient MILESTONE-CONTEXT.md loses
350
+ cross-phase design); milestone-wide architectural decisions have no home.
351
+
352
+ **Verdict:** Rejected. Three-tier is the correct scope.
353
+
354
+ ### Option D — REVIEW-LOG.md captured at SUMMARY-time, not real-time
355
+
356
+ (Reviews collected into a `reviews:` array passed to `cp write-summary`
357
+ at end-of-plan, not appended task-by-task.)
358
+
359
+ **Pros:** No mid-execution writes; single file (SUMMARY.md, no new type);
360
+ simpler skill change.
361
+
362
+ **Cons:** Reviews lose timestamp granularity; context-reset mid-plan loses
363
+ all prior reviews; harder to grep "what was rejected" across a long phase.
364
+
365
+ **Verdict:** Rejected. Append-only real-time wins on durability.
366
+
367
+ ### Option E — Soft warning for empty key-decisions (instead of hard block)
368
+
369
+ **Pros:** Less friction; orchestrator can still ship if they really meant
370
+ zero decisions.
371
+
372
+ **Cons:** "Soft" = will be ignored. Hard block is what changes behavior.
373
+
374
+ **Verdict:** Rejected. Hard block, exit code 2.
375
+
376
+ ## Open Questions
377
+
378
+ - [ ] Should milestone-tier DESIGN.md frontmatter expose a `phases:` array
379
+ linking back to each phase that contributed? (Deferred to v0.8 if so.)
380
+ - [ ] Should `cp progress` / `cp status` surface "DESIGN.md exists/empty"
381
+ as a phase-level signal? (Deferred to v0.8.)
382
+ - [ ] If a phase has no DESIGN.md at execute-time, should `/cp-execute-phase`
383
+ warn or block? (Plan 16-01 starts with warn; revisit after one milestone of
384
+ dogfooding.)
385
+
386
+ ## References
387
+
388
+ - `.planning/PROJECT.md` — project Core Value and current state
389
+ - `.planning/ROADMAP.md` — v0.7 milestone block (will be appended by `cp scaffold-milestone`)
390
+ - `.github/skills/cp-new-milestone/SKILL.md` — Step 3 (delegate to brainstorming)
391
+ - `.github/skills/cp-plan-phase/SKILL.md` — Step 3 (current) and Step 3.5 (new)
392
+ - `.github/skills/cp-execute-phase/SKILL.md` — Step 4 (current) and Steps 4.5 + 6 (changes)
393
+ - `lib/lifecycle.js` — `writeSummary()`, `aggregateSummaries()`
394
+ - `lib/paths.js` — path helper conventions
395
+ - `bin/commands/scaffold-phase.js`, `bin/commands/scaffold-milestone.js`
396
+ - SP brainstorming skill output-path-override convention
397
+ (`~/.copilot/installed-plugins/superpowers-marketplace/superpowers/skills/brainstorming/SKILL.md`)
398
+ - SP subagent-driven-development verdict format
399
+ (`~/.copilot/installed-plugins/superpowers-marketplace/superpowers/skills/subagent-driven-development/SKILL.md`)
400
+ - v0.6 retrospective conversation (this session) — original gap identification
@@ -0,0 +1,76 @@
1
+ # Writing a custom provider
2
+
3
+ A "provider" tells `cp` how to look up a skill for each workflow role.
4
+ Providers are defined in `.planning/cp-config.json`:
5
+
6
+ ```json
7
+ {
8
+ "workflow_provider": "my-provider",
9
+ "providers": {
10
+ "my-provider": {
11
+ "description": "...",
12
+ "detect": {
13
+ "any_of": [".claude/plugins/my-thing", "some/sentinel/path"]
14
+ },
15
+ "skills": {
16
+ "brainstorm": "my-brainstorm-skill",
17
+ "plan": "my-plan-skill",
18
+ "execute": "my-execute-skill",
19
+ "review": "my-review-skill",
20
+ "finish": "my-finish-skill",
21
+ "worktree": "my-worktree-skill",
22
+ "tdd": "my-tdd-skill",
23
+ "debug": "my-debug-skill",
24
+ "verify": "my-verify-skill"
25
+ }
26
+ }
27
+ }
28
+ }
29
+ ```
30
+
31
+ ## Required roles
32
+
33
+ Only `brainstorm`, `plan`, and `execute` are strictly required. The
34
+ others enrich the workflow but cp will skip them gracefully if absent.
35
+
36
+ | Role | When cp invokes it |
37
+ |---|---|
38
+ | `brainstorm` | `/cp-new-project`, `/cp-new-milestone` — refine intent |
39
+ | `plan` | `/cp-plan-phase`, `/cp-quick` — produce a task list |
40
+ | `execute` | `/cp-execute-phase`, `/cp-quick` — do the work |
41
+ | `execute_simple` | optional, lighter alternative to `execute` |
42
+ | `review` | between tasks if your provider supports it |
43
+ | `finish` | when a milestone/phase ships |
44
+ | `worktree` | create an isolated branch before risky work |
45
+ | `tdd` | during execute, if test-driven cycle is desired |
46
+ | `debug` | when verification fails |
47
+ | `verify` | confirm Success Criteria after execute |
48
+
49
+ ## Detection
50
+
51
+ `cp` uses `detect.any_of` paths to decide whether a provider is "installed".
52
+ A path can be:
53
+
54
+ - Project-relative (e.g. `.github/skills/brainstorming`)
55
+ - User-home-relative (e.g. `.claude/plugins/my-thing`)
56
+
57
+ The first match counts. If none match, cp falls back to the `manual` provider
58
+ when `behavior.fall_back_to_manual_if_provider_missing` is `true`.
59
+
60
+ You can also force detection with `"detect": { "always": true }` (this is
61
+ what the built-in `manual` provider does).
62
+
63
+ ## The `manual` provider
64
+
65
+ `manual` has no `skills` mappings. When cp resolves a role to `manual`, the
66
+ command-markdown's inline fallback prompts are used. This is the lowest
67
+ common denominator — everything still works, just without the polish of a
68
+ real workflow plugin.
69
+
70
+ ## Adding a provider
71
+
72
+ 1. Edit `.planning/cp-config.json` and add your entry under `providers`.
73
+ 2. Optionally set `workflow_provider` to your new entry.
74
+ 3. Run `cp doctor` to confirm the detection passes.
75
+
76
+ There is no code to write — providers are pure config.
@@ -0,0 +1,204 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Installer for Aider.
5
+ *
6
+ * Aider is the weakest "integration" target of the lot: there is NO
7
+ * extension mechanism for slash commands or rules. What Aider DOES support
8
+ * is read-only context files via `read:` in `.aider.conf.yml` or the
9
+ * `--read` flag. cp leverages that.
10
+ *
11
+ * Layout:
12
+ * .aider/CP-CONTEXT.md — read-only briefing on cp's slash commands
13
+ * (lists each cp-<name> with a one-line
14
+ * description so Aider can invoke `cp <name>`
15
+ * via shell when the user asks).
16
+ * .aider/cp-commands/<name>.md — full body of each cp slash command, in
17
+ * case the user wants to attach one
18
+ * individually via `/read .aider/cp-commands/<name>.md`.
19
+ * .aider.conf.yml — appends `read:` entry for CP-CONTEXT.md
20
+ * (creates the file if missing; idempotent).
21
+ *
22
+ * v0.4.2.
23
+ */
24
+
25
+ const fs = require('fs');
26
+ const path = require('path');
27
+ const YAML = require('yaml');
28
+ const { listCommandFiles, writeFileSafe, homeDir } = require('./common');
29
+
30
+ const CP_CONFIG_MARK_START = '# >>> context-planning (cp) — managed by cp installer';
31
+ const CP_CONFIG_MARK_END = '# <<< context-planning (cp)';
32
+ const CP_READ_ENTRY = '.aider/CP-CONTEXT.md';
33
+
34
+ function buildContextBriefing(commandFiles) {
35
+ const lines = [
36
+ '# context-planning (cp) — Aider briefing',
37
+ '',
38
+ '> This file is loaded into Aider chat context. It tells you what `cp`',
39
+ '> can do; invoke `cp` via shell (`!cp <subcommand>`) when the user asks.',
40
+ '',
41
+ '## What cp is',
42
+ '',
43
+ '`cp` (context-planning) owns the **state layer** in `.planning/` —',
44
+ '`PROJECT.md`, `ROADMAP.md`, `STATE.md`, `MILESTONES.md`, plus per-phase',
45
+ 'directories with `PLAN.md` + `SUMMARY.md`. It does NOT do the actual',
46
+ 'workflow work itself; that\'s your job (or a configured workflow provider\'s).',
47
+ '',
48
+ 'Whenever the user says "make a new milestone", "plan a phase", "tick',
49
+ 'plan 02-03", etc, run the matching `cp` subcommand and then proceed',
50
+ 'with the underlying work in chat.',
51
+ '',
52
+ '## Available cp slash-command flows',
53
+ '',
54
+ 'Each row below maps a user request to the corresponding `cp` shell',
55
+ 'invocation. Full per-command instructions are in',
56
+ '`.aider/cp-commands/<name>.md` — load one with `/read` when you want',
57
+ 'the full body.',
58
+ '',
59
+ '| Command | Shell | What cp does (state) |',
60
+ '|--------------------|------------------------------------|-----------------------|',
61
+ ];
62
+ for (const { name } of commandFiles) {
63
+ lines.push(`| \`/cp-${name}\`${' '.repeat(Math.max(0, 14 - name.length))} | \`cp ${name}\`${' '.repeat(Math.max(0, 30 - name.length))} | see \`.aider/cp-commands/${name}.md\` |`);
64
+ }
65
+ lines.push('');
66
+ lines.push('## CLI cheat-sheet (no slash-command needed)');
67
+ lines.push('');
68
+ lines.push('```bash');
69
+ lines.push('cp init # scaffold .planning/');
70
+ lines.push('cp status # "you are here"');
71
+ lines.push('cp statusline # one-liner for shell prompts');
72
+ lines.push('cp tick <plan-id> # mark a plan done in ROADMAP + PLAN.md');
73
+ lines.push('cp write-summary <id> --from <json>');
74
+ lines.push('cp scaffold-milestone <name>');
75
+ lines.push('cp scaffold-phase <N> --name <name> [--plans <count>]');
76
+ lines.push('cp capture "<text>" # append to .planning/INBOX.md');
77
+ lines.push('cp inbox [--tick <N> --note <dest>]');
78
+ lines.push('cp complete-milestone # close out: aggregate, collapse, reset');
79
+ lines.push('```');
80
+ lines.push('');
81
+ lines.push('## Rules');
82
+ lines.push('');
83
+ lines.push('- Only invoke cp when the user explicitly asks. Don\'t apply cp workflows unbidden.');
84
+ lines.push('- After completing a plan, ALWAYS run `cp tick <plan-id>` and `cp write-summary <plan-id>`.');
85
+ lines.push('- `cp` auto-commits its state edits scoped to `.planning/` only — won\'t sweep your dirty source files into a "cp:" commit.');
86
+ lines.push('');
87
+ return lines.join('\n') + '\n';
88
+ }
89
+
90
+ /**
91
+ * Patch (or create) `.aider.conf.yml` so its top-level `read:` list contains
92
+ * `.aider/CP-CONTEXT.md`. Parses with the `yaml` module to preserve any
93
+ * existing user keys and `read:` entries (v0.4.4 — was regex-based fenced
94
+ * block in v0.4.2 and silently overrode user `read:` values).
95
+ *
96
+ * Migrates legacy fenced blocks written by v0.4.2/v0.4.3: strips the
97
+ * `# >>> context-planning (cp) ...` block, parses what remains as YAML,
98
+ * then re-adds the entry to the proper `read:` list.
99
+ *
100
+ * Returns one of:
101
+ * { status: 'created', path } — file did not exist
102
+ * { status: 'updated', path } — added our entry to the read: list
103
+ * { status: 'migrated', path } — converted a legacy fenced block
104
+ * { status: 'identical', path } — our entry already present, no change
105
+ */
106
+ function patchAiderConfig(repoRoot /* , force unused */) {
107
+ const conf = path.join(repoRoot, '.aider.conf.yml');
108
+ const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
109
+ const reLegacy = new RegExp(
110
+ `${escapeRe(CP_CONFIG_MARK_START)}[\\s\\S]*?${escapeRe(CP_CONFIG_MARK_END)}\\n?`,
111
+ 'g'
112
+ );
113
+
114
+ const fileExisted = fs.existsSync(conf);
115
+ const original = fileExisted ? fs.readFileSync(conf, 'utf8') : '';
116
+ let body = original;
117
+ const hadLegacyFence = reLegacy.test(body);
118
+ if (hadLegacyFence) body = body.replace(reLegacy, '');
119
+
120
+ let doc;
121
+ try { doc = body.trim() ? YAML.parse(body) : {}; }
122
+ catch (e) { throw new Error(`could not parse .aider.conf.yml: ${e.message}`); }
123
+ if (doc == null || typeof doc !== 'object' || Array.isArray(doc)) doc = {};
124
+
125
+ let reads = doc.read;
126
+ if (typeof reads === 'string') reads = [reads];
127
+ if (!Array.isArray(reads)) reads = [];
128
+ const wasPresent = reads.includes(CP_READ_ENTRY);
129
+ if (!wasPresent) reads.push(CP_READ_ENTRY);
130
+ doc.read = reads;
131
+
132
+ const next = YAML.stringify(doc);
133
+ if (fileExisted && next === original) return { status: 'identical', path: conf };
134
+ fs.writeFileSync(conf, next);
135
+ if (!fileExisted) return { status: 'created', path: conf };
136
+ if (hadLegacyFence) return { status: 'migrated', path: conf };
137
+ if (wasPresent) return { status: 'identical', path: conf };
138
+ return { status: 'updated', path: conf };
139
+ }
140
+
141
+ function install({ pluginRoot, repoRoot, force = false }) {
142
+ const target = process.env.CP_INSTALL_SCOPE === 'user'
143
+ ? path.join(homeDir(), '.aider')
144
+ : path.join(repoRoot, '.aider');
145
+
146
+ console.log(`Installing cp briefing for Aider into:`);
147
+ console.log(` ${target}`);
148
+
149
+ const commandFiles = listCommandFiles(pluginRoot);
150
+
151
+ // 1. Briefing file
152
+ const briefingPath = path.join(target, 'CP-CONTEXT.md');
153
+ const briefing = buildContextBriefing(commandFiles);
154
+ const userModified = [];
155
+ let written = 0;
156
+ let identical = 0;
157
+ const r0 = writeFileSafe(briefingPath, briefing, { force });
158
+ if (r0.status === 'written') { console.log(` + CP-CONTEXT.md`); written++; }
159
+ else if (r0.status === 'identical') { console.log(` = CP-CONTEXT.md (unchanged)`); identical++; }
160
+ else if (r0.status === 'user-modified') { console.log(` ! CP-CONTEXT.md (LOCALLY MODIFIED — kept)`); userModified.push('CP-CONTEXT.md'); }
161
+
162
+ // 2. Per-command files
163
+ for (const { name, src } of commandFiles) {
164
+ const dest = path.join(target, 'cp-commands', `${name}.md`);
165
+ const body = fs.readFileSync(src, 'utf8');
166
+ const r = writeFileSafe(dest, body, { force });
167
+ if (r.status === 'written') { console.log(` + cp-commands/${name}.md`); written++; }
168
+ else if (r.status === 'identical') { console.log(` = cp-commands/${name}.md (unchanged)`); identical++; }
169
+ else if (r.status === 'user-modified') { console.log(` ! cp-commands/${name}.md (LOCALLY MODIFIED — kept)`); userModified.push(`cp-commands/${name}.md`); }
170
+ }
171
+
172
+ // 3. Patch .aider.conf.yml
173
+ let confResult;
174
+ try { confResult = patchAiderConfig(repoRoot, force); }
175
+ catch (e) { confResult = { status: 'error', error: e.message }; }
176
+ if (confResult.status === 'error') {
177
+ console.log(`\n⚠ Could not patch .aider.conf.yml: ${confResult.error}`);
178
+ console.log(` Add this line manually to your aider config:`);
179
+ console.log(` read:`);
180
+ console.log(` - .aider/CP-CONTEXT.md`);
181
+ } else {
182
+ const rel = path.relative(repoRoot, confResult.path);
183
+ console.log(`\nAider config: ${rel} (${confResult.status})`);
184
+ }
185
+
186
+ console.log(`\nInstalled: ${written} written, ${identical} unchanged${userModified.length ? `, ${userModified.length} kept (locally modified)` : ''}.`);
187
+ if (userModified.length > 0) {
188
+ console.log(`\n⚠ The following files exist on disk with local modifications and were NOT overwritten:`);
189
+ for (const f of userModified) console.log(` - ${f}`);
190
+ console.log(` Re-run with \`cp install aider --force\` to overwrite them.`);
191
+ }
192
+ console.log(`\nNext steps:`);
193
+ console.log(` 1. Restart aider so it picks up the new \`read:\` entry.`);
194
+ console.log(` 2. In a project directory: cp init`);
195
+ console.log(` 3. Ask Aider: "use cp to make a new milestone called 'my first'"`);
196
+ console.log(` Aider will run \`cp scaffold-milestone\` (or similar) via shell.`);
197
+ console.log(` Note: Aider has no per-project slash command mechanism. cp's slash`);
198
+ console.log(` commands are installed as read-only context files; invocations`);
199
+ console.log(` happen via \`cp <subcommand>\` shell calls from the chat.`);
200
+
201
+ return { written, identical, userModified, configResult: confResult };
202
+ }
203
+
204
+ module.exports = { install, buildContextBriefing, patchAiderConfig };