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,253 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * lib/worktree.js — pure helpers for `cp worktree {create,list,remove}`.
5
+ *
6
+ * The cp worktree workflow is intentionally minimal: cp wraps `git worktree`
7
+ * with sensible defaults (sibling-directory layout, `cp/<slug>` branch name)
8
+ * and records a row per worktree in `.planning/WORKTREES.md` for traceability
9
+ * across phases and resumption.
10
+ *
11
+ * If the configured workflow provider (default: Superpowers) is installed
12
+ * AND its `worktree` role resolves to a skill (e.g.
13
+ * `using-git-worktrees`), `cmdWorktree` in bin/cp.js prints a hand-off
14
+ * line so the harness knows to invoke that skill. The cp-native behaviour
15
+ * still runs as a fallback / non-delegated path.
16
+ *
17
+ * v0.4.3.
18
+ */
19
+
20
+ const fs = require('fs');
21
+ const path = require('path');
22
+ const os = require('os');
23
+ const { spawnSync, execSync } = require('child_process');
24
+ const { planningDir } = require('./paths');
25
+
26
+ const WORKTREES_FILENAME = 'WORKTREES.md';
27
+
28
+ /** Conservative slug: lowercase, alphanumeric + hyphen only. */
29
+ function slugify(name) {
30
+ if (typeof name !== 'string') throw new Error('slugify: name must be a string');
31
+ const out = name
32
+ .toLowerCase()
33
+ .replace(/[_\s]+/g, '-')
34
+ .replace(/[^a-z0-9-]/g, '')
35
+ .replace(/-+/g, '-')
36
+ .replace(/^-|-$/g, '');
37
+ if (out.length === 0) throw new Error(`slugify: "${name}" produced an empty slug`);
38
+ return out;
39
+ }
40
+
41
+ /**
42
+ * Default sibling location for a worktree: `<parent-of-repo>/<repo-name>-<slug>`.
43
+ *
44
+ * /work/projects/myrepo → /work/projects/myrepo-cool-feature
45
+ *
46
+ * The user can override with --path; this is just the default.
47
+ */
48
+ function defaultWorktreePath(repoRoot, slug) {
49
+ const parent = path.dirname(repoRoot);
50
+ const base = path.basename(repoRoot);
51
+ return path.join(parent, `${base}-${slug}`);
52
+ }
53
+
54
+ function defaultBranchName(slug) {
55
+ return `cp/${slug}`;
56
+ }
57
+
58
+ /**
59
+ * Parse the output of `git worktree list --porcelain` into objects:
60
+ * { path, head, branch, bare, detached, locked, prunable }
61
+ *
62
+ * Tolerates the slight differences in older git versions.
63
+ */
64
+ function parseGitWorktreeList(raw) {
65
+ const trees = [];
66
+ let cur = null;
67
+ for (const rawLine of raw.split(/\r?\n/)) {
68
+ const line = rawLine.replace(/\r$/, '');
69
+ if (line === '') {
70
+ if (cur) { trees.push(cur); cur = null; }
71
+ continue;
72
+ }
73
+ if (line.startsWith('worktree ')) {
74
+ if (cur) trees.push(cur);
75
+ cur = { path: line.slice('worktree '.length), branch: null };
76
+ continue;
77
+ }
78
+ if (!cur) continue;
79
+ if (line.startsWith('HEAD ')) cur.head = line.slice('HEAD '.length);
80
+ else if (line.startsWith('branch ')) cur.branch = line.slice('branch '.length).replace(/^refs\/heads\//, '');
81
+ else if (line === 'bare') cur.bare = true;
82
+ else if (line === 'detached') cur.detached = true;
83
+ else if (line.startsWith('locked')) cur.locked = true;
84
+ else if (line.startsWith('prunable')) cur.prunable = true;
85
+ }
86
+ if (cur) trees.push(cur);
87
+ return trees;
88
+ }
89
+
90
+ /**
91
+ * Render the WORKTREES.md registry from an array of `{ path, branch, slug,
92
+ * phase?, created, notes? }` entries. Stable order: created ascending.
93
+ */
94
+ function renderWorktreesDoc(entries) {
95
+ const lines = [
96
+ '# Worktrees',
97
+ '',
98
+ '> cp-managed git worktrees for this project. Use `cp worktree create`',
99
+ '> to add an entry. Each row pairs a sibling worktree directory with a',
100
+ '> short slug and (optionally) a phase number for traceability.',
101
+ '',
102
+ '| Slug | Branch | Path | Phase | Created | Notes |',
103
+ '|------|--------|------|-------|---------|-------|',
104
+ ];
105
+ const sorted = entries.slice().sort((a, b) => String(a.created).localeCompare(String(b.created)));
106
+ for (const e of sorted) {
107
+ lines.push(`| ${e.slug} | ${e.branch} | ${e.path} | ${e.phase || '—'} | ${e.created} | ${e.notes || ''} |`);
108
+ }
109
+ lines.push('');
110
+ return lines.join('\n');
111
+ }
112
+
113
+ /**
114
+ * Parse WORKTREES.md back to an array of registry entries. Tolerates extra
115
+ * narrative the user added before/after the table.
116
+ */
117
+ function parseWorktreesDoc(content) {
118
+ if (typeof content !== 'string' || content.length === 0) return [];
119
+ const entries = [];
120
+ for (const line of content.split(/\r?\n/)) {
121
+ if (!line.startsWith('|')) continue;
122
+ if (/^\|\s*-+\s*\|/.test(line)) continue; // separator row
123
+ if (/^\|\s*Slug\s*\|/i.test(line)) continue; // header row
124
+ const cells = line.split('|').slice(1, -1).map((c) => c.trim());
125
+ if (cells.length < 5) continue;
126
+ const [slug, branch, p, phase, created, notes = ''] = cells;
127
+ if (!slug || slug === '—') continue;
128
+ entries.push({
129
+ slug, branch, path: p,
130
+ phase: phase && phase !== '—' ? phase : null,
131
+ created, notes,
132
+ });
133
+ }
134
+ return entries;
135
+ }
136
+
137
+ /** Path to .planning/WORKTREES.md (does not require the file to exist). */
138
+ function worktreesPath(root) {
139
+ return path.join(planningDir(root), WORKTREES_FILENAME);
140
+ }
141
+
142
+ /**
143
+ * Compute the action list to add an entry to .planning/WORKTREES.md.
144
+ * Returns `{ actions, entry, alreadyPresent }`. Uses the lifecycle.writeBatch
145
+ * action shape so the caller can scope its commit and atomic-write through
146
+ * the same pipeline as every other cp lifecycle op.
147
+ */
148
+ function addRegistryEntry(root, entry) {
149
+ const p = worktreesPath(root);
150
+ const existing = fs.existsSync(p) ? fs.readFileSync(p, 'utf8') : '';
151
+ const entries = parseWorktreesDoc(existing);
152
+ const alreadyPresent = entries.some((e) => e.slug === entry.slug);
153
+ if (!alreadyPresent) entries.push(entry);
154
+ const after = renderWorktreesDoc(entries);
155
+ return {
156
+ actions: [{ kind: 'write', path: p, after, label: 'add-worktree-entry' }],
157
+ entry,
158
+ alreadyPresent,
159
+ };
160
+ }
161
+
162
+ /**
163
+ * Compute the action list to remove an entry from .planning/WORKTREES.md by slug.
164
+ * Returns `{ actions, removed }` where `removed` is the entry that was removed
165
+ * (or null if no such slug).
166
+ */
167
+ function removeRegistryEntry(root, slug) {
168
+ const p = worktreesPath(root);
169
+ if (!fs.existsSync(p)) return { actions: [], removed: null };
170
+ const entries = parseWorktreesDoc(fs.readFileSync(p, 'utf8'));
171
+ const removed = entries.find((e) => e.slug === slug) || null;
172
+ if (!removed) return { actions: [], removed: null };
173
+ const remaining = entries.filter((e) => e.slug !== slug);
174
+ const after = renderWorktreesDoc(remaining);
175
+ return {
176
+ actions: [{ kind: 'write', path: p, after, label: 'remove-worktree-entry' }],
177
+ removed,
178
+ };
179
+ }
180
+
181
+ /** Read current registry. Returns an array of entries (possibly empty). */
182
+ function listRegistry(root) {
183
+ const p = worktreesPath(root);
184
+ if (!fs.existsSync(p)) return [];
185
+ return parseWorktreesDoc(fs.readFileSync(p, 'utf8'));
186
+ }
187
+
188
+ function isoDay(d = new Date()) {
189
+ const pad = (n) => String(n).padStart(2, '0');
190
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
191
+ }
192
+
193
+ /**
194
+ * Shell out to `git worktree add <path> -b <branch> [<from>]`.
195
+ * Returns the raw spawnSync result (`{ status, stdout, stderr, error }`).
196
+ * The CLI layer owns printing and exit codes; this function is the only
197
+ * place where `git worktree add` is invoked.
198
+ *
199
+ * v0.4.4 — extracted from bin/cp.js so the shell-out lives next to the rest
200
+ * of the worktree lib (matches the pattern in lib/lifecycle.js).
201
+ */
202
+ function runGitWorktreeAdd(root, { worktreePath, branch, from } = {}) {
203
+ const args = ['worktree', 'add', worktreePath, '-b', branch];
204
+ if (from) args.push(from);
205
+ return spawnSync('git', args, { cwd: root, encoding: 'utf8' });
206
+ }
207
+
208
+ /**
209
+ * Shell out to `git worktree remove [--force] <path>`. Returns the raw
210
+ * spawnSync result. v0.4.4.
211
+ */
212
+ function runGitWorktreeRemove(root, { worktreePath, force } = {}) {
213
+ const args = ['worktree', 'remove'];
214
+ if (force) args.push('--force');
215
+ args.push(worktreePath);
216
+ return spawnSync('git', args, { cwd: root, encoding: 'utf8' });
217
+ }
218
+
219
+ /**
220
+ * Shell out to `git worktree list --porcelain` and parse the output.
221
+ * Returns an array of `{ path, head, branch, ... }` objects. Swallows
222
+ * errors (returns `[]`) so callers can use it for best-effort
223
+ * cross-referencing without crashing in non-git contexts. v0.4.4.
224
+ */
225
+ function listGitWorktrees(root) {
226
+ try {
227
+ const raw = execSync('git worktree list --porcelain', {
228
+ cwd: root,
229
+ stdio: ['ignore', 'pipe', 'ignore'],
230
+ }).toString();
231
+ return parseGitWorktreeList(raw);
232
+ } catch {
233
+ return [];
234
+ }
235
+ }
236
+
237
+ module.exports = {
238
+ WORKTREES_FILENAME,
239
+ worktreesPath,
240
+ slugify,
241
+ defaultWorktreePath,
242
+ defaultBranchName,
243
+ parseGitWorktreeList,
244
+ renderWorktreesDoc,
245
+ parseWorktreesDoc,
246
+ addRegistryEntry,
247
+ removeRegistryEntry,
248
+ listRegistry,
249
+ isoDay,
250
+ runGitWorktreeAdd,
251
+ runGitWorktreeRemove,
252
+ listGitWorktrees,
253
+ };
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "context-planning",
3
+ "version": "0.7.0",
4
+ "description": "Lightweight stateful context-management plugin that delegates dev workflow to Superpowers (or any compatible provider).",
5
+ "bin": {
6
+ "cp": "bin/cp.js",
7
+ "cplan": "bin/cp.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "commands",
12
+ "install",
13
+ "lib",
14
+ "templates",
15
+ "docs",
16
+ "README.md"
17
+ ],
18
+ "keywords": [
19
+ "ai",
20
+ "context",
21
+ "planning",
22
+ "milestone",
23
+ "superpowers",
24
+ "copilot-cli",
25
+ "claude-code"
26
+ ],
27
+ "license": "MIT",
28
+ "engines": {
29
+ "node": ">=18.0.0"
30
+ },
31
+ "scripts": {
32
+ "install:copilot": "node bin/cp.js install copilot",
33
+ "install:claude": "node bin/cp.js install claude",
34
+ "doctor": "node bin/cp.js doctor",
35
+ "test": "node test/roundtrip-gsd.js && node test/dryrun-progress.js && node test/dryrun-complete-milestone.js && node test/dryrun-gsd-import.js && node test/dryrun-resume.js && node test/unit-libs.js && node test/unit-detect.js && node test/unit-merge.js && node test/dryrun-doctor.js && node test/dryrun-config-refresh.js && node test/unit-lifecycle.js && node test/unit-codebase.js && node test/unit-atomic.js && node test/unit-gitcommit.js && node test/unit-v034.js && node test/unit-inbox.js && node test/unit-statusline.js && node test/unit-installers.js && node test/unit-worktree.js && node test/unit-design.js",
36
+ "coverage": "c8 --reporter=text --reporter=html npm test",
37
+ "coverage:ci": "c8 --reporter=text --reporter=lcov --reporter=json-summary --check-coverage --lines 85 --branches 75 npm test"
38
+ },
39
+ "dependencies": {
40
+ "yaml": "^2.9.0"
41
+ },
42
+ "devDependencies": {
43
+ "c8": "^10.1.3"
44
+ }
45
+ }
@@ -0,0 +1,78 @@
1
+ ---
2
+ # Tier marker: cp scaffold substitutes one of:
3
+ # phase: "{{PHASE_NUM}}" (for phase-tier DESIGN.md)
4
+ # milestone_slug: "{{MILESTONE_SLUG}}" (for milestone-tier DESIGN.md)
5
+ {{TIER_KEY}}
6
+ milestone: {{MILESTONE_NAME}}
7
+ status: proposed
8
+ created: {{DATE}}
9
+ updated: {{DATE}}
10
+ deciders: []
11
+ supersedes: []
12
+ superseded_by: null
13
+ ---
14
+
15
+ # Design: {{TITLE}}
16
+
17
+ ## Status
18
+
19
+ {Proposed | Accepted on YYYY-MM-DD | Superseded by …}
20
+
21
+ ## Context
22
+
23
+ <!-- Forces driving this design: constraints, prior decisions, requirements. -->
24
+
25
+ ## Decision
26
+
27
+ <!-- What we decided. Short, declarative. -->
28
+
29
+ ## Consequences
30
+
31
+ ### Positive
32
+ -
33
+
34
+ ### Negative
35
+ -
36
+
37
+ ### Neutral
38
+ -
39
+
40
+ ---
41
+
42
+ ## Architecture
43
+
44
+ <!-- Boxes-and-lines, ASCII diagrams welcome. -->
45
+
46
+ ## Components
47
+
48
+ <!-- Each unit: name, purpose, public interface, dependencies. -->
49
+
50
+ ## Data Flow
51
+
52
+ <!-- How data moves through the components. -->
53
+
54
+ ## Error Handling
55
+
56
+ <!-- Failure modes and recovery. -->
57
+
58
+ ## Testing Strategy
59
+
60
+ <!-- Unit / integration / e2e split, coverage targets. -->
61
+
62
+ ## Alternatives Considered
63
+
64
+ ### Option A — <name>
65
+
66
+ **Pros:**
67
+
68
+ **Cons:**
69
+
70
+ **Verdict:** rejected because…
71
+
72
+ ## Open Questions
73
+
74
+ - [ ]
75
+
76
+ ## References
77
+
78
+ -
@@ -0,0 +1,13 @@
1
+ # Inbox
2
+
3
+ Quick captures awaiting triage. Use `cp capture "..."` to add an item,
4
+ `cp inbox` to list, and the `/cp-capture` slash command to process them
5
+ interactively (route each to a quick task, phase, seed, or discard).
6
+
7
+ ## Open
8
+
9
+ <!-- new items get appended here as: `- [ ] [YYYY-MM-DDTHH:mm] <text>` -->
10
+
11
+ ## Triaged
12
+
13
+ <!-- triaged items move here as: `- [x] [YYYY-MM-DDTHH:mm] → <destination>: <text>` -->
@@ -0,0 +1,40 @@
1
+ # Milestone Context: {{MILESTONE_NAME}}
2
+
3
+ <!--
4
+ Transient document written by /cp-new-milestone after the workflow provider's
5
+ `brainstorm` skill returns its design. Consumed by /cp-plan-phase and then
6
+ typically deleted (or moved to .planning/milestones/{slug}/) once all phases
7
+ in the milestone are planned.
8
+
9
+ This is the same name and role as GSD's MILESTONE-CONTEXT.md, so a GSD
10
+ workflow can pick up the same file.
11
+ -->
12
+
13
+ ## Goals
14
+
15
+ <!-- The specific outcomes this milestone delivers, in the user's words. -->
16
+
17
+ ## In Scope
18
+
19
+ - {feature/change 1}
20
+ - {feature/change 2}
21
+
22
+ ## Out of Scope
23
+
24
+ - {explicit exclusion 1} — {why}
25
+
26
+ ## Constraints
27
+
28
+ - {tech/timeline/compat constraint}
29
+
30
+ ## Proposed Phase Breakdown
31
+
32
+ <!-- The brainstorm skill's recommended phase split. /cp-new-milestone uses
33
+ this to populate ROADMAP.md. -->
34
+
35
+ 1. **Phase N: {name}** — {one-line goal}
36
+ 2. **Phase N+1: {name}** — {one-line goal}
37
+
38
+ ## Decisions Captured
39
+
40
+ - {decision} — {rationale}
@@ -0,0 +1,29 @@
1
+ # Project Milestones: {{PROJECT_NAME}}
2
+
3
+ <!-- Entries in reverse chronological order — newest first.
4
+ Append a block via /cp-complete-milestone. -->
5
+
6
+ <!-- Template per milestone:
7
+
8
+ ## v[X.Y] [Name] (Shipped: YYYY-MM-DD)
9
+
10
+ **Delivered:** [One sentence describing what shipped]
11
+
12
+ **Phases completed:** [X-Y] ([Z] plans total)
13
+
14
+ **Key accomplishments:**
15
+ - [Major achievement 1]
16
+ - [Major achievement 2]
17
+ - [Major achievement 3]
18
+
19
+ **Stats:**
20
+ - [X] files created/modified
21
+ - [Y] lines of code (primary language)
22
+ - [Z] phases, [N] plans
23
+
24
+ **Git range:** `feat(XX-XX)` → `feat(YY-YY)`
25
+
26
+ **What's next:** [Brief description of next milestone goals]
27
+
28
+ ---
29
+ -->
@@ -0,0 +1,84 @@
1
+ ---
2
+ phase: {{PHASE_DIR}}
3
+ plan: {{PLAN_NUM_PADDED}}
4
+ type: execute
5
+ wave: {{WAVE}}
6
+ depends_on: []
7
+ files_modified: []
8
+ autonomous: true
9
+ requirements: []
10
+ user_setup: []
11
+
12
+ # Goal-backward verification (derived during planning, verified after execution)
13
+ must_haves:
14
+ truths: []
15
+ artifacts: []
16
+ key_links: []
17
+ ---
18
+
19
+ <objective>
20
+ {{OBJECTIVE}}
21
+
22
+ Purpose: {{PURPOSE}}
23
+ Output: {{OUTPUT}}
24
+ </objective>
25
+
26
+ <execution_context>
27
+ @.planning/config.json
28
+ </execution_context>
29
+
30
+ <context>
31
+ @.planning/PROJECT.md
32
+ @.planning/ROADMAP.md
33
+ @.planning/STATE.md
34
+
35
+ <!--
36
+ Only reference prior plan SUMMARYs if genuinely needed:
37
+ - This plan uses types/exports from prior plan
38
+ - Prior plan made a decision that affects this plan
39
+ Do NOT reflexively chain summaries together.
40
+ -->
41
+ </context>
42
+
43
+ <tasks>
44
+
45
+ <!--
46
+ This section is owned by the workflow provider (configured: {{PROVIDER}},
47
+ plan skill: {{PLAN_SKILL}}). The provider replaces this comment with one
48
+ <task>…</task> block per actionable step. Each task should be 2-5 minutes,
49
+ file-scoped, and have a measurable verify/acceptance criterion.
50
+
51
+ GSD-compatible task shape:
52
+
53
+ <task type="auto">
54
+ <name>Task N: action-oriented name</name>
55
+ <files>path/to/file.ext</files>
56
+ <read_first>path/to/reference.ext</read_first>
57
+ <action>What to do, with concrete values</action>
58
+ <verify>Command or check that proves it worked</verify>
59
+ <acceptance_criteria>
60
+ - Grep-verifiable condition
61
+ </acceptance_criteria>
62
+ <done>Measurable acceptance criteria</done>
63
+ </task>
64
+ -->
65
+
66
+ </tasks>
67
+
68
+ <verification>
69
+ Before declaring plan complete:
70
+ - [ ] {test command}
71
+ - [ ] {build / type check passes}
72
+ - [ ] {behavior verification}
73
+ </verification>
74
+
75
+ <success_criteria>
76
+ - All tasks completed
77
+ - All verification checks pass
78
+ - No errors or warnings introduced
79
+ - {plan-specific criteria}
80
+ </success_criteria>
81
+
82
+ <output>
83
+ After completion, create `.planning/phases/{{PHASE_DIR}}/{{PHASE_PLAN_PREFIX}}-SUMMARY.md`
84
+ </output>
@@ -0,0 +1,43 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ ## What This Is
4
+
5
+ <!-- 2-3 sentences. What does this product do and who is it for? -->
6
+
7
+ ## Core Value
8
+
9
+ <!-- The ONE thing that matters most. If everything else fails, this must work. -->
10
+
11
+ ## Requirements
12
+
13
+ ### Validated
14
+ <!-- Shipped and confirmed valuable. Format: `- ✓ {requirement} — {milestone}` -->
15
+
16
+ (None yet — ship to validate)
17
+
18
+ ### Active
19
+ <!-- Current scope. Building toward these. -->
20
+
21
+ - [ ] {Requirement 1}
22
+
23
+ ### Out of Scope
24
+ <!-- Explicit boundaries. Always include reasoning. -->
25
+
26
+ (None yet)
27
+
28
+ ## Context
29
+
30
+ <!-- Background that informs implementation: stack, prior work, user feedback, known issues. -->
31
+
32
+ ## Constraints
33
+
34
+ <!-- Hard limits. Format: `- **{Type}**: {What} — {Why}` -->
35
+
36
+ ## Key Decisions
37
+
38
+ | Decision | Rationale | Outcome |
39
+ |----------|-----------|---------|
40
+ | | | |
41
+
42
+ ---
43
+ *Last updated: {{DATE}} after {{TRIGGER}}*
@@ -0,0 +1,38 @@
1
+ ---
2
+ phase: "{{PHASE_NUM}}"
3
+ milestone: {{MILESTONE_NAME}}
4
+ created: {{DATE}}
5
+ schema_version: 1
6
+ ---
7
+
8
+ # Review Log: Phase {{PHASE_NUM}} — {{TITLE}}
9
+
10
+ Append-only log of subagent review cycles during execution. Each entry is
11
+ written by the cp-execute-phase orchestrator after a review round
12
+ (spec-compliance or code-quality). The cp aggregator counts entries when
13
+ rolling up the milestone summary.
14
+
15
+ ## How to append
16
+
17
+ The orchestrator (cp-execute-phase Step 4.5) appends a block per review:
18
+
19
+ ```
20
+ ## YYYY-MM-DD HH:MM — Plan NN-MM Task N — <reviewer-role>
21
+
22
+ **Verdict:** approved | rejected | needs-revision
23
+
24
+ **Findings:**
25
+
26
+ - <finding>
27
+
28
+ **Resolution:**
29
+
30
+ <what changed; commit SHA if applied>
31
+
32
+ ---
33
+ ```
34
+
35
+ ## Entries
36
+
37
+ <!-- orchestrator appends below this marker; do not delete the marker -->
38
+ <!-- REVIEW-LOG-ENTRIES-BELOW -->
@@ -0,0 +1,34 @@
1
+ # Roadmap: {{PROJECT_NAME}}
2
+
3
+ ## Overview
4
+
5
+ <!-- One paragraph: the journey from here to shipped. -->
6
+
7
+ ## Phases
8
+
9
+ <!--
10
+ Milestone heading shape (parsed by lib/milestone.js findMilestoneInRoadmap):
11
+ ### 🚧 v0.1 — name (In Progress) (active)
12
+ ### 📋 v0.2 — name (Planned) (queued)
13
+ ### ✅ v0.1 — name (Shipped YYYY-MM-DD) — wraps a <details> block after close-out
14
+
15
+ Phase heading shape (must follow a milestone heading):
16
+ ### Phase 1: name
17
+ ### Phase 2.1: name (decimal = urgent insert between integers)
18
+
19
+ After /cp-complete-milestone the milestone heading is replaced with a collapsed
20
+ <details><summary>...</summary>...</details> block; phase headings remain inside.
21
+
22
+ Start your first milestone with:
23
+ cp scaffold-milestone "v0.1 — <your milestone name>"
24
+ cp scaffold-phase 1 --name "<phase name>" --plans <count>
25
+ -->
26
+
27
+ ## Progress
28
+
29
+ **Execution Order:**
30
+ Phases execute in numeric order (decimal phases like 2.1 are urgent inserts between integers).
31
+
32
+ | Phase | Milestone | Plans Complete | Status | Completed |
33
+ |-------|-----------|----------------|--------|-----------|
34
+ | *(none yet — run `cp scaffold-phase 1 --name <name> --plans <count>`)* | | | | |