@m3hti/commit-genie 3.2.0 → 3.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 (160) hide show
  1. package/.claude/agents/gsd-codebase-mapper.md +764 -0
  2. package/.claude/agents/gsd-debugger.md +1246 -0
  3. package/.claude/agents/gsd-executor.md +469 -0
  4. package/.claude/agents/gsd-integration-checker.md +443 -0
  5. package/.claude/agents/gsd-phase-researcher.md +546 -0
  6. package/.claude/agents/gsd-plan-checker.md +690 -0
  7. package/.claude/agents/gsd-planner.md +1275 -0
  8. package/.claude/agents/gsd-project-researcher.md +621 -0
  9. package/.claude/agents/gsd-research-synthesizer.md +239 -0
  10. package/.claude/agents/gsd-roadmapper.md +642 -0
  11. package/.claude/agents/gsd-verifier.md +573 -0
  12. package/.claude/commands/gsd/add-phase.md +43 -0
  13. package/.claude/commands/gsd/add-tests.md +41 -0
  14. package/.claude/commands/gsd/add-todo.md +47 -0
  15. package/.claude/commands/gsd/audit-milestone.md +36 -0
  16. package/.claude/commands/gsd/check-todos.md +45 -0
  17. package/.claude/commands/gsd/cleanup.md +18 -0
  18. package/.claude/commands/gsd/complete-milestone.md +136 -0
  19. package/.claude/commands/gsd/debug.md +167 -0
  20. package/.claude/commands/gsd/discuss-phase.md +83 -0
  21. package/.claude/commands/gsd/execute-phase.md +41 -0
  22. package/.claude/commands/gsd/health.md +22 -0
  23. package/.claude/commands/gsd/help.md +22 -0
  24. package/.claude/commands/gsd/insert-phase.md +32 -0
  25. package/.claude/commands/gsd/join-discord.md +18 -0
  26. package/.claude/commands/gsd/list-phase-assumptions.md +46 -0
  27. package/.claude/commands/gsd/map-codebase.md +71 -0
  28. package/.claude/commands/gsd/new-milestone.md +44 -0
  29. package/.claude/commands/gsd/new-project.md +42 -0
  30. package/.claude/commands/gsd/new-project.md.bak +1041 -0
  31. package/.claude/commands/gsd/pause-work.md +38 -0
  32. package/.claude/commands/gsd/plan-milestone-gaps.md +34 -0
  33. package/.claude/commands/gsd/plan-phase.md +45 -0
  34. package/.claude/commands/gsd/progress.md +24 -0
  35. package/.claude/commands/gsd/quick.md +41 -0
  36. package/.claude/commands/gsd/reapply-patches.md +110 -0
  37. package/.claude/commands/gsd/remove-phase.md +31 -0
  38. package/.claude/commands/gsd/research-phase.md +189 -0
  39. package/.claude/commands/gsd/resume-work.md +40 -0
  40. package/.claude/commands/gsd/set-profile.md +34 -0
  41. package/.claude/commands/gsd/settings.md +36 -0
  42. package/.claude/commands/gsd/update.md +37 -0
  43. package/.claude/commands/gsd/verify-work.md +38 -0
  44. package/.claude/get-shit-done/VERSION +1 -0
  45. package/.claude/get-shit-done/bin/gsd-tools.cjs +588 -0
  46. package/.claude/get-shit-done/bin/lib/commands.cjs +553 -0
  47. package/.claude/get-shit-done/bin/lib/config.cjs +162 -0
  48. package/.claude/get-shit-done/bin/lib/core.cjs +411 -0
  49. package/.claude/get-shit-done/bin/lib/frontmatter.cjs +299 -0
  50. package/.claude/get-shit-done/bin/lib/init.cjs +710 -0
  51. package/.claude/get-shit-done/bin/lib/milestone.cjs +216 -0
  52. package/.claude/get-shit-done/bin/lib/phase.cjs +871 -0
  53. package/.claude/get-shit-done/bin/lib/roadmap.cjs +298 -0
  54. package/.claude/get-shit-done/bin/lib/state.cjs +679 -0
  55. package/.claude/get-shit-done/bin/lib/template.cjs +222 -0
  56. package/.claude/get-shit-done/bin/lib/verify.cjs +773 -0
  57. package/.claude/get-shit-done/references/checkpoints.md +776 -0
  58. package/.claude/get-shit-done/references/continuation-format.md +249 -0
  59. package/.claude/get-shit-done/references/decimal-phase-calculation.md +65 -0
  60. package/.claude/get-shit-done/references/git-integration.md +248 -0
  61. package/.claude/get-shit-done/references/git-planning-commit.md +38 -0
  62. package/.claude/get-shit-done/references/model-profile-resolution.md +34 -0
  63. package/.claude/get-shit-done/references/model-profiles.md +92 -0
  64. package/.claude/get-shit-done/references/phase-argument-parsing.md +61 -0
  65. package/.claude/get-shit-done/references/planning-config.md +196 -0
  66. package/.claude/get-shit-done/references/questioning.md +145 -0
  67. package/.claude/get-shit-done/references/tdd.md +263 -0
  68. package/.claude/get-shit-done/references/ui-brand.md +160 -0
  69. package/.claude/get-shit-done/references/verification-patterns.md +612 -0
  70. package/.claude/get-shit-done/templates/DEBUG.md +164 -0
  71. package/.claude/get-shit-done/templates/UAT.md +247 -0
  72. package/.claude/get-shit-done/templates/VALIDATION.md +76 -0
  73. package/.claude/get-shit-done/templates/codebase/architecture.md +255 -0
  74. package/.claude/get-shit-done/templates/codebase/concerns.md +310 -0
  75. package/.claude/get-shit-done/templates/codebase/conventions.md +307 -0
  76. package/.claude/get-shit-done/templates/codebase/integrations.md +280 -0
  77. package/.claude/get-shit-done/templates/codebase/stack.md +186 -0
  78. package/.claude/get-shit-done/templates/codebase/structure.md +285 -0
  79. package/.claude/get-shit-done/templates/codebase/testing.md +480 -0
  80. package/.claude/get-shit-done/templates/config.json +37 -0
  81. package/.claude/get-shit-done/templates/context.md +283 -0
  82. package/.claude/get-shit-done/templates/continue-here.md +78 -0
  83. package/.claude/get-shit-done/templates/debug-subagent-prompt.md +91 -0
  84. package/.claude/get-shit-done/templates/discovery.md +146 -0
  85. package/.claude/get-shit-done/templates/milestone-archive.md +123 -0
  86. package/.claude/get-shit-done/templates/milestone.md +115 -0
  87. package/.claude/get-shit-done/templates/phase-prompt.md +569 -0
  88. package/.claude/get-shit-done/templates/planner-subagent-prompt.md +117 -0
  89. package/.claude/get-shit-done/templates/project.md +184 -0
  90. package/.claude/get-shit-done/templates/requirements.md +231 -0
  91. package/.claude/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
  92. package/.claude/get-shit-done/templates/research-project/FEATURES.md +147 -0
  93. package/.claude/get-shit-done/templates/research-project/PITFALLS.md +200 -0
  94. package/.claude/get-shit-done/templates/research-project/STACK.md +120 -0
  95. package/.claude/get-shit-done/templates/research-project/SUMMARY.md +170 -0
  96. package/.claude/get-shit-done/templates/research.md +552 -0
  97. package/.claude/get-shit-done/templates/retrospective.md +54 -0
  98. package/.claude/get-shit-done/templates/roadmap.md +202 -0
  99. package/.claude/get-shit-done/templates/state.md +176 -0
  100. package/.claude/get-shit-done/templates/summary-complex.md +59 -0
  101. package/.claude/get-shit-done/templates/summary-minimal.md +41 -0
  102. package/.claude/get-shit-done/templates/summary-standard.md +48 -0
  103. package/.claude/get-shit-done/templates/summary.md +248 -0
  104. package/.claude/get-shit-done/templates/user-setup.md +311 -0
  105. package/.claude/get-shit-done/templates/verification-report.md +322 -0
  106. package/.claude/get-shit-done/workflows/add-phase.md +111 -0
  107. package/.claude/get-shit-done/workflows/add-tests.md +350 -0
  108. package/.claude/get-shit-done/workflows/add-todo.md +157 -0
  109. package/.claude/get-shit-done/workflows/audit-milestone.md +297 -0
  110. package/.claude/get-shit-done/workflows/check-todos.md +176 -0
  111. package/.claude/get-shit-done/workflows/cleanup.md +152 -0
  112. package/.claude/get-shit-done/workflows/complete-milestone.md +763 -0
  113. package/.claude/get-shit-done/workflows/diagnose-issues.md +219 -0
  114. package/.claude/get-shit-done/workflows/discovery-phase.md +289 -0
  115. package/.claude/get-shit-done/workflows/discuss-phase.md +542 -0
  116. package/.claude/get-shit-done/workflows/execute-phase.md +449 -0
  117. package/.claude/get-shit-done/workflows/execute-plan.md +448 -0
  118. package/.claude/get-shit-done/workflows/health.md +156 -0
  119. package/.claude/get-shit-done/workflows/help.md +489 -0
  120. package/.claude/get-shit-done/workflows/insert-phase.md +129 -0
  121. package/.claude/get-shit-done/workflows/list-phase-assumptions.md +178 -0
  122. package/.claude/get-shit-done/workflows/map-codebase.md +315 -0
  123. package/.claude/get-shit-done/workflows/new-milestone.md +382 -0
  124. package/.claude/get-shit-done/workflows/new-project.md +1116 -0
  125. package/.claude/get-shit-done/workflows/pause-work.md +122 -0
  126. package/.claude/get-shit-done/workflows/plan-milestone-gaps.md +274 -0
  127. package/.claude/get-shit-done/workflows/plan-phase.md +569 -0
  128. package/.claude/get-shit-done/workflows/progress.md +381 -0
  129. package/.claude/get-shit-done/workflows/quick.md +453 -0
  130. package/.claude/get-shit-done/workflows/remove-phase.md +154 -0
  131. package/.claude/get-shit-done/workflows/research-phase.md +73 -0
  132. package/.claude/get-shit-done/workflows/resume-project.md +306 -0
  133. package/.claude/get-shit-done/workflows/set-profile.md +80 -0
  134. package/.claude/get-shit-done/workflows/settings.md +213 -0
  135. package/.claude/get-shit-done/workflows/transition.md +544 -0
  136. package/.claude/get-shit-done/workflows/update.md +219 -0
  137. package/.claude/get-shit-done/workflows/verify-phase.md +242 -0
  138. package/.claude/get-shit-done/workflows/verify-work.md +569 -0
  139. package/.claude/gsd-file-manifest.json +144 -0
  140. package/.claude/hooks/gsd-check-update.js +62 -0
  141. package/.claude/hooks/gsd-context-monitor.js +122 -0
  142. package/.claude/hooks/gsd-statusline.js +108 -0
  143. package/.claude/package.json +1 -0
  144. package/.claude/settings.json +49 -0
  145. package/dist/commands/generate.d.ts.map +1 -1
  146. package/dist/commands/generate.js +18 -8
  147. package/dist/commands/generate.js.map +1 -1
  148. package/dist/services/analyzerService.d.ts.map +1 -1
  149. package/dist/services/analyzerService.js +10 -0
  150. package/dist/services/analyzerService.js.map +1 -1
  151. package/dist/services/descriptionGenerator.d.ts.map +1 -1
  152. package/dist/services/descriptionGenerator.js +56 -14
  153. package/dist/services/descriptionGenerator.js.map +1 -1
  154. package/dist/services/fileContentAnalyzer.js +136 -17
  155. package/dist/services/fileContentAnalyzer.js.map +1 -1
  156. package/dist/services/fileContentAnalyzer.test.js +64 -0
  157. package/dist/services/fileContentAnalyzer.test.js.map +1 -1
  158. package/dist/services/semanticAnalyzer.js +20 -0
  159. package/dist/services/semanticAnalyzer.js.map +1 -1
  160. package/package.json +1 -1
@@ -0,0 +1,710 @@
1
+ /**
2
+ * Init — Compound init commands for workflow bootstrapping
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { execSync } = require('child_process');
8
+ const { loadConfig, resolveModelInternal, findPhaseInternal, getRoadmapPhaseInternal, pathExistsInternal, generateSlugInternal, getMilestoneInfo, normalizePhaseName, output, error } = require('./core.cjs');
9
+
10
+ function cmdInitExecutePhase(cwd, phase, raw) {
11
+ if (!phase) {
12
+ error('phase required for init execute-phase');
13
+ }
14
+
15
+ const config = loadConfig(cwd);
16
+ const phaseInfo = findPhaseInternal(cwd, phase);
17
+ const milestone = getMilestoneInfo(cwd);
18
+
19
+ const roadmapPhase = getRoadmapPhaseInternal(cwd, phase);
20
+ const reqMatch = roadmapPhase?.section?.match(/^\*\*Requirements\*\*:[^\S\n]*([^\n]*)$/m);
21
+ const reqExtracted = reqMatch
22
+ ? reqMatch[1].replace(/[\[\]]/g, '').split(',').map(s => s.trim()).filter(Boolean).join(', ')
23
+ : null;
24
+ const phase_req_ids = (reqExtracted && reqExtracted !== 'TBD') ? reqExtracted : null;
25
+
26
+ const result = {
27
+ // Models
28
+ executor_model: resolveModelInternal(cwd, 'gsd-executor'),
29
+ verifier_model: resolveModelInternal(cwd, 'gsd-verifier'),
30
+
31
+ // Config flags
32
+ commit_docs: config.commit_docs,
33
+ parallelization: config.parallelization,
34
+ branching_strategy: config.branching_strategy,
35
+ phase_branch_template: config.phase_branch_template,
36
+ milestone_branch_template: config.milestone_branch_template,
37
+ verifier_enabled: config.verifier,
38
+
39
+ // Phase info
40
+ phase_found: !!phaseInfo,
41
+ phase_dir: phaseInfo?.directory || null,
42
+ phase_number: phaseInfo?.phase_number || null,
43
+ phase_name: phaseInfo?.phase_name || null,
44
+ phase_slug: phaseInfo?.phase_slug || null,
45
+ phase_req_ids,
46
+
47
+ // Plan inventory
48
+ plans: phaseInfo?.plans || [],
49
+ summaries: phaseInfo?.summaries || [],
50
+ incomplete_plans: phaseInfo?.incomplete_plans || [],
51
+ plan_count: phaseInfo?.plans?.length || 0,
52
+ incomplete_count: phaseInfo?.incomplete_plans?.length || 0,
53
+
54
+ // Branch name (pre-computed)
55
+ branch_name: config.branching_strategy === 'phase' && phaseInfo
56
+ ? config.phase_branch_template
57
+ .replace('{phase}', phaseInfo.phase_number)
58
+ .replace('{slug}', phaseInfo.phase_slug || 'phase')
59
+ : config.branching_strategy === 'milestone'
60
+ ? config.milestone_branch_template
61
+ .replace('{milestone}', milestone.version)
62
+ .replace('{slug}', generateSlugInternal(milestone.name) || 'milestone')
63
+ : null,
64
+
65
+ // Milestone info
66
+ milestone_version: milestone.version,
67
+ milestone_name: milestone.name,
68
+ milestone_slug: generateSlugInternal(milestone.name),
69
+
70
+ // File existence
71
+ state_exists: pathExistsInternal(cwd, '.planning/STATE.md'),
72
+ roadmap_exists: pathExistsInternal(cwd, '.planning/ROADMAP.md'),
73
+ config_exists: pathExistsInternal(cwd, '.planning/config.json'),
74
+ // File paths
75
+ state_path: '.planning/STATE.md',
76
+ roadmap_path: '.planning/ROADMAP.md',
77
+ config_path: '.planning/config.json',
78
+ };
79
+
80
+ output(result, raw);
81
+ }
82
+
83
+ function cmdInitPlanPhase(cwd, phase, raw) {
84
+ if (!phase) {
85
+ error('phase required for init plan-phase');
86
+ }
87
+
88
+ const config = loadConfig(cwd);
89
+ const phaseInfo = findPhaseInternal(cwd, phase);
90
+
91
+ const roadmapPhase = getRoadmapPhaseInternal(cwd, phase);
92
+ const reqMatch = roadmapPhase?.section?.match(/^\*\*Requirements\*\*:[^\S\n]*([^\n]*)$/m);
93
+ const reqExtracted = reqMatch
94
+ ? reqMatch[1].replace(/[\[\]]/g, '').split(',').map(s => s.trim()).filter(Boolean).join(', ')
95
+ : null;
96
+ const phase_req_ids = (reqExtracted && reqExtracted !== 'TBD') ? reqExtracted : null;
97
+
98
+ const result = {
99
+ // Models
100
+ researcher_model: resolveModelInternal(cwd, 'gsd-phase-researcher'),
101
+ planner_model: resolveModelInternal(cwd, 'gsd-planner'),
102
+ checker_model: resolveModelInternal(cwd, 'gsd-plan-checker'),
103
+
104
+ // Workflow flags
105
+ research_enabled: config.research,
106
+ plan_checker_enabled: config.plan_checker,
107
+ nyquist_validation_enabled: config.nyquist_validation,
108
+ commit_docs: config.commit_docs,
109
+
110
+ // Phase info
111
+ phase_found: !!phaseInfo,
112
+ phase_dir: phaseInfo?.directory || null,
113
+ phase_number: phaseInfo?.phase_number || null,
114
+ phase_name: phaseInfo?.phase_name || null,
115
+ phase_slug: phaseInfo?.phase_slug || null,
116
+ padded_phase: phaseInfo?.phase_number?.padStart(2, '0') || null,
117
+ phase_req_ids,
118
+
119
+ // Existing artifacts
120
+ has_research: phaseInfo?.has_research || false,
121
+ has_context: phaseInfo?.has_context || false,
122
+ has_plans: (phaseInfo?.plans?.length || 0) > 0,
123
+ plan_count: phaseInfo?.plans?.length || 0,
124
+
125
+ // Environment
126
+ planning_exists: pathExistsInternal(cwd, '.planning'),
127
+ roadmap_exists: pathExistsInternal(cwd, '.planning/ROADMAP.md'),
128
+
129
+ // File paths
130
+ state_path: '.planning/STATE.md',
131
+ roadmap_path: '.planning/ROADMAP.md',
132
+ requirements_path: '.planning/REQUIREMENTS.md',
133
+ };
134
+
135
+ if (phaseInfo?.directory) {
136
+ // Find *-CONTEXT.md in phase directory
137
+ const phaseDirFull = path.join(cwd, phaseInfo.directory);
138
+ try {
139
+ const files = fs.readdirSync(phaseDirFull);
140
+ const contextFile = files.find(f => f.endsWith('-CONTEXT.md') || f === 'CONTEXT.md');
141
+ if (contextFile) {
142
+ result.context_path = path.join(phaseInfo.directory, contextFile);
143
+ }
144
+ const researchFile = files.find(f => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
145
+ if (researchFile) {
146
+ result.research_path = path.join(phaseInfo.directory, researchFile);
147
+ }
148
+ const verificationFile = files.find(f => f.endsWith('-VERIFICATION.md') || f === 'VERIFICATION.md');
149
+ if (verificationFile) {
150
+ result.verification_path = path.join(phaseInfo.directory, verificationFile);
151
+ }
152
+ const uatFile = files.find(f => f.endsWith('-UAT.md') || f === 'UAT.md');
153
+ if (uatFile) {
154
+ result.uat_path = path.join(phaseInfo.directory, uatFile);
155
+ }
156
+ } catch {}
157
+ }
158
+
159
+ output(result, raw);
160
+ }
161
+
162
+ function cmdInitNewProject(cwd, raw) {
163
+ const config = loadConfig(cwd);
164
+
165
+ // Detect Brave Search API key availability
166
+ const homedir = require('os').homedir();
167
+ const braveKeyFile = path.join(homedir, '.gsd', 'brave_api_key');
168
+ const hasBraveSearch = !!(process.env.BRAVE_API_KEY || fs.existsSync(braveKeyFile));
169
+
170
+ // Detect existing code
171
+ let hasCode = false;
172
+ let hasPackageFile = false;
173
+ try {
174
+ const files = execSync('find . -maxdepth 3 \\( -name "*.ts" -o -name "*.js" -o -name "*.py" -o -name "*.go" -o -name "*.rs" -o -name "*.swift" -o -name "*.java" \\) 2>/dev/null | grep -v node_modules | grep -v .git | head -5', {
175
+ cwd,
176
+ encoding: 'utf-8',
177
+ stdio: ['pipe', 'pipe', 'pipe'],
178
+ });
179
+ hasCode = files.trim().length > 0;
180
+ } catch {}
181
+
182
+ hasPackageFile = pathExistsInternal(cwd, 'package.json') ||
183
+ pathExistsInternal(cwd, 'requirements.txt') ||
184
+ pathExistsInternal(cwd, 'Cargo.toml') ||
185
+ pathExistsInternal(cwd, 'go.mod') ||
186
+ pathExistsInternal(cwd, 'Package.swift');
187
+
188
+ const result = {
189
+ // Models
190
+ researcher_model: resolveModelInternal(cwd, 'gsd-project-researcher'),
191
+ synthesizer_model: resolveModelInternal(cwd, 'gsd-research-synthesizer'),
192
+ roadmapper_model: resolveModelInternal(cwd, 'gsd-roadmapper'),
193
+
194
+ // Config
195
+ commit_docs: config.commit_docs,
196
+
197
+ // Existing state
198
+ project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
199
+ has_codebase_map: pathExistsInternal(cwd, '.planning/codebase'),
200
+ planning_exists: pathExistsInternal(cwd, '.planning'),
201
+
202
+ // Brownfield detection
203
+ has_existing_code: hasCode,
204
+ has_package_file: hasPackageFile,
205
+ is_brownfield: hasCode || hasPackageFile,
206
+ needs_codebase_map: (hasCode || hasPackageFile) && !pathExistsInternal(cwd, '.planning/codebase'),
207
+
208
+ // Git state
209
+ has_git: pathExistsInternal(cwd, '.git'),
210
+
211
+ // Enhanced search
212
+ brave_search_available: hasBraveSearch,
213
+
214
+ // File paths
215
+ project_path: '.planning/PROJECT.md',
216
+ };
217
+
218
+ output(result, raw);
219
+ }
220
+
221
+ function cmdInitNewMilestone(cwd, raw) {
222
+ const config = loadConfig(cwd);
223
+ const milestone = getMilestoneInfo(cwd);
224
+
225
+ const result = {
226
+ // Models
227
+ researcher_model: resolveModelInternal(cwd, 'gsd-project-researcher'),
228
+ synthesizer_model: resolveModelInternal(cwd, 'gsd-research-synthesizer'),
229
+ roadmapper_model: resolveModelInternal(cwd, 'gsd-roadmapper'),
230
+
231
+ // Config
232
+ commit_docs: config.commit_docs,
233
+ research_enabled: config.research,
234
+
235
+ // Current milestone
236
+ current_milestone: milestone.version,
237
+ current_milestone_name: milestone.name,
238
+
239
+ // File existence
240
+ project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
241
+ roadmap_exists: pathExistsInternal(cwd, '.planning/ROADMAP.md'),
242
+ state_exists: pathExistsInternal(cwd, '.planning/STATE.md'),
243
+
244
+ // File paths
245
+ project_path: '.planning/PROJECT.md',
246
+ roadmap_path: '.planning/ROADMAP.md',
247
+ state_path: '.planning/STATE.md',
248
+ };
249
+
250
+ output(result, raw);
251
+ }
252
+
253
+ function cmdInitQuick(cwd, description, raw) {
254
+ const config = loadConfig(cwd);
255
+ const now = new Date();
256
+ const slug = description ? generateSlugInternal(description)?.substring(0, 40) : null;
257
+
258
+ // Find next quick task number
259
+ const quickDir = path.join(cwd, '.planning', 'quick');
260
+ let nextNum = 1;
261
+ try {
262
+ const existing = fs.readdirSync(quickDir)
263
+ .filter(f => /^\d+-/.test(f))
264
+ .map(f => parseInt(f.split('-')[0], 10))
265
+ .filter(n => !isNaN(n));
266
+ if (existing.length > 0) {
267
+ nextNum = Math.max(...existing) + 1;
268
+ }
269
+ } catch {}
270
+
271
+ const result = {
272
+ // Models
273
+ planner_model: resolveModelInternal(cwd, 'gsd-planner'),
274
+ executor_model: resolveModelInternal(cwd, 'gsd-executor'),
275
+ checker_model: resolveModelInternal(cwd, 'gsd-plan-checker'),
276
+ verifier_model: resolveModelInternal(cwd, 'gsd-verifier'),
277
+
278
+ // Config
279
+ commit_docs: config.commit_docs,
280
+
281
+ // Quick task info
282
+ next_num: nextNum,
283
+ slug: slug,
284
+ description: description || null,
285
+
286
+ // Timestamps
287
+ date: now.toISOString().split('T')[0],
288
+ timestamp: now.toISOString(),
289
+
290
+ // Paths
291
+ quick_dir: '.planning/quick',
292
+ task_dir: slug ? `.planning/quick/${nextNum}-${slug}` : null,
293
+
294
+ // File existence
295
+ roadmap_exists: pathExistsInternal(cwd, '.planning/ROADMAP.md'),
296
+ planning_exists: pathExistsInternal(cwd, '.planning'),
297
+
298
+ };
299
+
300
+ output(result, raw);
301
+ }
302
+
303
+ function cmdInitResume(cwd, raw) {
304
+ const config = loadConfig(cwd);
305
+
306
+ // Check for interrupted agent
307
+ let interruptedAgentId = null;
308
+ try {
309
+ interruptedAgentId = fs.readFileSync(path.join(cwd, '.planning', 'current-agent-id.txt'), 'utf-8').trim();
310
+ } catch {}
311
+
312
+ const result = {
313
+ // File existence
314
+ state_exists: pathExistsInternal(cwd, '.planning/STATE.md'),
315
+ roadmap_exists: pathExistsInternal(cwd, '.planning/ROADMAP.md'),
316
+ project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
317
+ planning_exists: pathExistsInternal(cwd, '.planning'),
318
+
319
+ // File paths
320
+ state_path: '.planning/STATE.md',
321
+ roadmap_path: '.planning/ROADMAP.md',
322
+ project_path: '.planning/PROJECT.md',
323
+
324
+ // Agent state
325
+ has_interrupted_agent: !!interruptedAgentId,
326
+ interrupted_agent_id: interruptedAgentId,
327
+
328
+ // Config
329
+ commit_docs: config.commit_docs,
330
+ };
331
+
332
+ output(result, raw);
333
+ }
334
+
335
+ function cmdInitVerifyWork(cwd, phase, raw) {
336
+ if (!phase) {
337
+ error('phase required for init verify-work');
338
+ }
339
+
340
+ const config = loadConfig(cwd);
341
+ const phaseInfo = findPhaseInternal(cwd, phase);
342
+
343
+ const result = {
344
+ // Models
345
+ planner_model: resolveModelInternal(cwd, 'gsd-planner'),
346
+ checker_model: resolveModelInternal(cwd, 'gsd-plan-checker'),
347
+
348
+ // Config
349
+ commit_docs: config.commit_docs,
350
+
351
+ // Phase info
352
+ phase_found: !!phaseInfo,
353
+ phase_dir: phaseInfo?.directory || null,
354
+ phase_number: phaseInfo?.phase_number || null,
355
+ phase_name: phaseInfo?.phase_name || null,
356
+
357
+ // Existing artifacts
358
+ has_verification: phaseInfo?.has_verification || false,
359
+ };
360
+
361
+ output(result, raw);
362
+ }
363
+
364
+ function cmdInitPhaseOp(cwd, phase, raw) {
365
+ const config = loadConfig(cwd);
366
+ let phaseInfo = findPhaseInternal(cwd, phase);
367
+
368
+ // Fallback to ROADMAP.md if no directory exists (e.g., Plans: TBD)
369
+ if (!phaseInfo) {
370
+ const roadmapPhase = getRoadmapPhaseInternal(cwd, phase);
371
+ if (roadmapPhase?.found) {
372
+ const phaseName = roadmapPhase.phase_name;
373
+ phaseInfo = {
374
+ found: true,
375
+ directory: null,
376
+ phase_number: roadmapPhase.phase_number,
377
+ phase_name: phaseName,
378
+ phase_slug: phaseName ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') : null,
379
+ plans: [],
380
+ summaries: [],
381
+ incomplete_plans: [],
382
+ has_research: false,
383
+ has_context: false,
384
+ has_verification: false,
385
+ };
386
+ }
387
+ }
388
+
389
+ const result = {
390
+ // Config
391
+ commit_docs: config.commit_docs,
392
+ brave_search: config.brave_search,
393
+
394
+ // Phase info
395
+ phase_found: !!phaseInfo,
396
+ phase_dir: phaseInfo?.directory || null,
397
+ phase_number: phaseInfo?.phase_number || null,
398
+ phase_name: phaseInfo?.phase_name || null,
399
+ phase_slug: phaseInfo?.phase_slug || null,
400
+ padded_phase: phaseInfo?.phase_number?.padStart(2, '0') || null,
401
+
402
+ // Existing artifacts
403
+ has_research: phaseInfo?.has_research || false,
404
+ has_context: phaseInfo?.has_context || false,
405
+ has_plans: (phaseInfo?.plans?.length || 0) > 0,
406
+ has_verification: phaseInfo?.has_verification || false,
407
+ plan_count: phaseInfo?.plans?.length || 0,
408
+
409
+ // File existence
410
+ roadmap_exists: pathExistsInternal(cwd, '.planning/ROADMAP.md'),
411
+ planning_exists: pathExistsInternal(cwd, '.planning'),
412
+
413
+ // File paths
414
+ state_path: '.planning/STATE.md',
415
+ roadmap_path: '.planning/ROADMAP.md',
416
+ requirements_path: '.planning/REQUIREMENTS.md',
417
+ };
418
+
419
+ if (phaseInfo?.directory) {
420
+ const phaseDirFull = path.join(cwd, phaseInfo.directory);
421
+ try {
422
+ const files = fs.readdirSync(phaseDirFull);
423
+ const contextFile = files.find(f => f.endsWith('-CONTEXT.md') || f === 'CONTEXT.md');
424
+ if (contextFile) {
425
+ result.context_path = path.join(phaseInfo.directory, contextFile);
426
+ }
427
+ const researchFile = files.find(f => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
428
+ if (researchFile) {
429
+ result.research_path = path.join(phaseInfo.directory, researchFile);
430
+ }
431
+ const verificationFile = files.find(f => f.endsWith('-VERIFICATION.md') || f === 'VERIFICATION.md');
432
+ if (verificationFile) {
433
+ result.verification_path = path.join(phaseInfo.directory, verificationFile);
434
+ }
435
+ const uatFile = files.find(f => f.endsWith('-UAT.md') || f === 'UAT.md');
436
+ if (uatFile) {
437
+ result.uat_path = path.join(phaseInfo.directory, uatFile);
438
+ }
439
+ } catch {}
440
+ }
441
+
442
+ output(result, raw);
443
+ }
444
+
445
+ function cmdInitTodos(cwd, area, raw) {
446
+ const config = loadConfig(cwd);
447
+ const now = new Date();
448
+
449
+ // List todos (reuse existing logic)
450
+ const pendingDir = path.join(cwd, '.planning', 'todos', 'pending');
451
+ let count = 0;
452
+ const todos = [];
453
+
454
+ try {
455
+ const files = fs.readdirSync(pendingDir).filter(f => f.endsWith('.md'));
456
+ for (const file of files) {
457
+ try {
458
+ const content = fs.readFileSync(path.join(pendingDir, file), 'utf-8');
459
+ const createdMatch = content.match(/^created:\s*(.+)$/m);
460
+ const titleMatch = content.match(/^title:\s*(.+)$/m);
461
+ const areaMatch = content.match(/^area:\s*(.+)$/m);
462
+ const todoArea = areaMatch ? areaMatch[1].trim() : 'general';
463
+
464
+ if (area && todoArea !== area) continue;
465
+
466
+ count++;
467
+ todos.push({
468
+ file,
469
+ created: createdMatch ? createdMatch[1].trim() : 'unknown',
470
+ title: titleMatch ? titleMatch[1].trim() : 'Untitled',
471
+ area: todoArea,
472
+ path: path.join('.planning', 'todos', 'pending', file),
473
+ });
474
+ } catch {}
475
+ }
476
+ } catch {}
477
+
478
+ const result = {
479
+ // Config
480
+ commit_docs: config.commit_docs,
481
+
482
+ // Timestamps
483
+ date: now.toISOString().split('T')[0],
484
+ timestamp: now.toISOString(),
485
+
486
+ // Todo inventory
487
+ todo_count: count,
488
+ todos,
489
+ area_filter: area || null,
490
+
491
+ // Paths
492
+ pending_dir: '.planning/todos/pending',
493
+ completed_dir: '.planning/todos/completed',
494
+
495
+ // File existence
496
+ planning_exists: pathExistsInternal(cwd, '.planning'),
497
+ todos_dir_exists: pathExistsInternal(cwd, '.planning/todos'),
498
+ pending_dir_exists: pathExistsInternal(cwd, '.planning/todos/pending'),
499
+ };
500
+
501
+ output(result, raw);
502
+ }
503
+
504
+ function cmdInitMilestoneOp(cwd, raw) {
505
+ const config = loadConfig(cwd);
506
+ const milestone = getMilestoneInfo(cwd);
507
+
508
+ // Count phases
509
+ let phaseCount = 0;
510
+ let completedPhases = 0;
511
+ const phasesDir = path.join(cwd, '.planning', 'phases');
512
+ try {
513
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
514
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
515
+ phaseCount = dirs.length;
516
+
517
+ // Count phases with summaries (completed)
518
+ for (const dir of dirs) {
519
+ try {
520
+ const phaseFiles = fs.readdirSync(path.join(phasesDir, dir));
521
+ const hasSummary = phaseFiles.some(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md');
522
+ if (hasSummary) completedPhases++;
523
+ } catch {}
524
+ }
525
+ } catch {}
526
+
527
+ // Check archive
528
+ const archiveDir = path.join(cwd, '.planning', 'archive');
529
+ let archivedMilestones = [];
530
+ try {
531
+ archivedMilestones = fs.readdirSync(archiveDir, { withFileTypes: true })
532
+ .filter(e => e.isDirectory())
533
+ .map(e => e.name);
534
+ } catch {}
535
+
536
+ const result = {
537
+ // Config
538
+ commit_docs: config.commit_docs,
539
+
540
+ // Current milestone
541
+ milestone_version: milestone.version,
542
+ milestone_name: milestone.name,
543
+ milestone_slug: generateSlugInternal(milestone.name),
544
+
545
+ // Phase counts
546
+ phase_count: phaseCount,
547
+ completed_phases: completedPhases,
548
+ all_phases_complete: phaseCount > 0 && phaseCount === completedPhases,
549
+
550
+ // Archive
551
+ archived_milestones: archivedMilestones,
552
+ archive_count: archivedMilestones.length,
553
+
554
+ // File existence
555
+ project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
556
+ roadmap_exists: pathExistsInternal(cwd, '.planning/ROADMAP.md'),
557
+ state_exists: pathExistsInternal(cwd, '.planning/STATE.md'),
558
+ archive_exists: pathExistsInternal(cwd, '.planning/archive'),
559
+ phases_dir_exists: pathExistsInternal(cwd, '.planning/phases'),
560
+ };
561
+
562
+ output(result, raw);
563
+ }
564
+
565
+ function cmdInitMapCodebase(cwd, raw) {
566
+ const config = loadConfig(cwd);
567
+
568
+ // Check for existing codebase maps
569
+ const codebaseDir = path.join(cwd, '.planning', 'codebase');
570
+ let existingMaps = [];
571
+ try {
572
+ existingMaps = fs.readdirSync(codebaseDir).filter(f => f.endsWith('.md'));
573
+ } catch {}
574
+
575
+ const result = {
576
+ // Models
577
+ mapper_model: resolveModelInternal(cwd, 'gsd-codebase-mapper'),
578
+
579
+ // Config
580
+ commit_docs: config.commit_docs,
581
+ search_gitignored: config.search_gitignored,
582
+ parallelization: config.parallelization,
583
+
584
+ // Paths
585
+ codebase_dir: '.planning/codebase',
586
+
587
+ // Existing maps
588
+ existing_maps: existingMaps,
589
+ has_maps: existingMaps.length > 0,
590
+
591
+ // File existence
592
+ planning_exists: pathExistsInternal(cwd, '.planning'),
593
+ codebase_dir_exists: pathExistsInternal(cwd, '.planning/codebase'),
594
+ };
595
+
596
+ output(result, raw);
597
+ }
598
+
599
+ function cmdInitProgress(cwd, raw) {
600
+ const config = loadConfig(cwd);
601
+ const milestone = getMilestoneInfo(cwd);
602
+
603
+ // Analyze phases
604
+ const phasesDir = path.join(cwd, '.planning', 'phases');
605
+ const phases = [];
606
+ let currentPhase = null;
607
+ let nextPhase = null;
608
+
609
+ try {
610
+ const entries = fs.readdirSync(phasesDir, { withFileTypes: true });
611
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort();
612
+
613
+ for (const dir of dirs) {
614
+ const match = dir.match(/^(\d+(?:\.\d+)*)-?(.*)/);
615
+ const phaseNumber = match ? match[1] : dir;
616
+ const phaseName = match && match[2] ? match[2] : null;
617
+
618
+ const phasePath = path.join(phasesDir, dir);
619
+ const phaseFiles = fs.readdirSync(phasePath);
620
+
621
+ const plans = phaseFiles.filter(f => f.endsWith('-PLAN.md') || f === 'PLAN.md');
622
+ const summaries = phaseFiles.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md');
623
+ const hasResearch = phaseFiles.some(f => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
624
+
625
+ const status = summaries.length >= plans.length && plans.length > 0 ? 'complete' :
626
+ plans.length > 0 ? 'in_progress' :
627
+ hasResearch ? 'researched' : 'pending';
628
+
629
+ const phaseInfo = {
630
+ number: phaseNumber,
631
+ name: phaseName,
632
+ directory: path.join('.planning', 'phases', dir),
633
+ status,
634
+ plan_count: plans.length,
635
+ summary_count: summaries.length,
636
+ has_research: hasResearch,
637
+ };
638
+
639
+ phases.push(phaseInfo);
640
+
641
+ // Find current (first incomplete with plans) and next (first pending)
642
+ if (!currentPhase && (status === 'in_progress' || status === 'researched')) {
643
+ currentPhase = phaseInfo;
644
+ }
645
+ if (!nextPhase && status === 'pending') {
646
+ nextPhase = phaseInfo;
647
+ }
648
+ }
649
+ } catch {}
650
+
651
+ // Check for paused work
652
+ let pausedAt = null;
653
+ try {
654
+ const state = fs.readFileSync(path.join(cwd, '.planning', 'STATE.md'), 'utf-8');
655
+ const pauseMatch = state.match(/\*\*Paused At:\*\*\s*(.+)/);
656
+ if (pauseMatch) pausedAt = pauseMatch[1].trim();
657
+ } catch {}
658
+
659
+ const result = {
660
+ // Models
661
+ executor_model: resolveModelInternal(cwd, 'gsd-executor'),
662
+ planner_model: resolveModelInternal(cwd, 'gsd-planner'),
663
+
664
+ // Config
665
+ commit_docs: config.commit_docs,
666
+
667
+ // Milestone
668
+ milestone_version: milestone.version,
669
+ milestone_name: milestone.name,
670
+
671
+ // Phase overview
672
+ phases,
673
+ phase_count: phases.length,
674
+ completed_count: phases.filter(p => p.status === 'complete').length,
675
+ in_progress_count: phases.filter(p => p.status === 'in_progress').length,
676
+
677
+ // Current state
678
+ current_phase: currentPhase,
679
+ next_phase: nextPhase,
680
+ paused_at: pausedAt,
681
+ has_work_in_progress: !!currentPhase,
682
+
683
+ // File existence
684
+ project_exists: pathExistsInternal(cwd, '.planning/PROJECT.md'),
685
+ roadmap_exists: pathExistsInternal(cwd, '.planning/ROADMAP.md'),
686
+ state_exists: pathExistsInternal(cwd, '.planning/STATE.md'),
687
+ // File paths
688
+ state_path: '.planning/STATE.md',
689
+ roadmap_path: '.planning/ROADMAP.md',
690
+ project_path: '.planning/PROJECT.md',
691
+ config_path: '.planning/config.json',
692
+ };
693
+
694
+ output(result, raw);
695
+ }
696
+
697
+ module.exports = {
698
+ cmdInitExecutePhase,
699
+ cmdInitPlanPhase,
700
+ cmdInitNewProject,
701
+ cmdInitNewMilestone,
702
+ cmdInitQuick,
703
+ cmdInitResume,
704
+ cmdInitVerifyWork,
705
+ cmdInitPhaseOp,
706
+ cmdInitTodos,
707
+ cmdInitMilestoneOp,
708
+ cmdInitMapCodebase,
709
+ cmdInitProgress,
710
+ };