gsd-opencode 1.22.1 → 1.30.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 (156) hide show
  1. package/agents/gsd-advisor-researcher.md +112 -0
  2. package/agents/gsd-assumptions-analyzer.md +110 -0
  3. package/agents/gsd-codebase-mapper.md +0 -2
  4. package/agents/gsd-debugger.md +118 -2
  5. package/agents/gsd-executor.md +24 -4
  6. package/agents/gsd-integration-checker.md +0 -2
  7. package/agents/gsd-nyquist-auditor.md +0 -2
  8. package/agents/gsd-phase-researcher.md +150 -5
  9. package/agents/gsd-plan-checker.md +70 -5
  10. package/agents/gsd-planner.md +49 -4
  11. package/agents/gsd-project-researcher.md +28 -3
  12. package/agents/gsd-research-synthesizer.md +0 -2
  13. package/agents/gsd-roadmapper.md +29 -2
  14. package/agents/gsd-ui-auditor.md +445 -0
  15. package/agents/gsd-ui-checker.md +305 -0
  16. package/agents/gsd-ui-researcher.md +368 -0
  17. package/agents/gsd-user-profiler.md +173 -0
  18. package/agents/gsd-verifier.md +123 -4
  19. package/commands/gsd/gsd-add-backlog.md +76 -0
  20. package/commands/gsd/gsd-audit-uat.md +24 -0
  21. package/commands/gsd/gsd-autonomous.md +41 -0
  22. package/commands/gsd/gsd-debug.md +5 -0
  23. package/commands/gsd/gsd-discuss-phase.md +10 -36
  24. package/commands/gsd/gsd-do.md +30 -0
  25. package/commands/gsd/gsd-execute-phase.md +20 -2
  26. package/commands/gsd/gsd-fast.md +30 -0
  27. package/commands/gsd/gsd-forensics.md +56 -0
  28. package/commands/gsd/gsd-list-workspaces.md +19 -0
  29. package/commands/gsd/gsd-manager.md +39 -0
  30. package/commands/gsd/gsd-milestone-summary.md +51 -0
  31. package/commands/gsd/gsd-new-workspace.md +44 -0
  32. package/commands/gsd/gsd-next.md +24 -0
  33. package/commands/gsd/gsd-note.md +34 -0
  34. package/commands/gsd/gsd-plan-phase.md +3 -1
  35. package/commands/gsd/gsd-plant-seed.md +28 -0
  36. package/commands/gsd/gsd-pr-branch.md +25 -0
  37. package/commands/gsd/gsd-profile-user.md +46 -0
  38. package/commands/gsd/gsd-quick.md +4 -2
  39. package/commands/gsd/gsd-reapply-patches.md +9 -8
  40. package/commands/gsd/gsd-remove-workspace.md +26 -0
  41. package/commands/gsd/gsd-research-phase.md +5 -0
  42. package/commands/gsd/gsd-review-backlog.md +61 -0
  43. package/commands/gsd/gsd-review.md +37 -0
  44. package/commands/gsd/gsd-session-report.md +19 -0
  45. package/commands/gsd/gsd-set-profile.md +24 -23
  46. package/commands/gsd/gsd-ship.md +23 -0
  47. package/commands/gsd/gsd-stats.md +18 -0
  48. package/commands/gsd/gsd-thread.md +127 -0
  49. package/commands/gsd/gsd-ui-phase.md +34 -0
  50. package/commands/gsd/gsd-ui-review.md +32 -0
  51. package/commands/gsd/gsd-workstreams.md +66 -0
  52. package/get-shit-done/bin/gsd-tools.cjs +410 -84
  53. package/get-shit-done/bin/lib/commands.cjs +429 -18
  54. package/get-shit-done/bin/lib/config.cjs +318 -45
  55. package/get-shit-done/bin/lib/core.cjs +822 -84
  56. package/get-shit-done/bin/lib/frontmatter.cjs +78 -41
  57. package/get-shit-done/bin/lib/init.cjs +836 -104
  58. package/get-shit-done/bin/lib/milestone.cjs +44 -33
  59. package/get-shit-done/bin/lib/model-profiles.cjs +68 -0
  60. package/get-shit-done/bin/lib/phase.cjs +293 -306
  61. package/get-shit-done/bin/lib/profile-output.cjs +952 -0
  62. package/get-shit-done/bin/lib/profile-pipeline.cjs +539 -0
  63. package/get-shit-done/bin/lib/roadmap.cjs +55 -24
  64. package/get-shit-done/bin/lib/security.cjs +382 -0
  65. package/get-shit-done/bin/lib/state.cjs +363 -53
  66. package/get-shit-done/bin/lib/template.cjs +2 -2
  67. package/get-shit-done/bin/lib/uat.cjs +282 -0
  68. package/get-shit-done/bin/lib/verify.cjs +104 -36
  69. package/get-shit-done/bin/lib/workstream.cjs +491 -0
  70. package/get-shit-done/references/checkpoints.md +12 -10
  71. package/get-shit-done/references/decimal-phase-calculation.md +2 -3
  72. package/get-shit-done/references/git-integration.md +47 -0
  73. package/get-shit-done/references/model-profile-resolution.md +2 -0
  74. package/get-shit-done/references/model-profiles.md +62 -16
  75. package/get-shit-done/references/phase-argument-parsing.md +2 -2
  76. package/get-shit-done/references/planning-config.md +3 -1
  77. package/get-shit-done/references/user-profiling.md +681 -0
  78. package/get-shit-done/references/workstream-flag.md +58 -0
  79. package/get-shit-done/templates/UAT.md +21 -3
  80. package/get-shit-done/templates/UI-SPEC.md +100 -0
  81. package/get-shit-done/templates/claude-md.md +122 -0
  82. package/get-shit-done/templates/config.json +10 -3
  83. package/get-shit-done/templates/context.md +61 -6
  84. package/get-shit-done/templates/dev-preferences.md +21 -0
  85. package/get-shit-done/templates/discussion-log.md +63 -0
  86. package/get-shit-done/templates/phase-prompt.md +46 -5
  87. package/get-shit-done/templates/project.md +2 -0
  88. package/get-shit-done/templates/state.md +2 -2
  89. package/get-shit-done/templates/user-profile.md +146 -0
  90. package/get-shit-done/workflows/add-phase.md +2 -2
  91. package/get-shit-done/workflows/add-tests.md +4 -4
  92. package/get-shit-done/workflows/add-todo.md +3 -3
  93. package/get-shit-done/workflows/audit-milestone.md +13 -5
  94. package/get-shit-done/workflows/audit-uat.md +109 -0
  95. package/get-shit-done/workflows/autonomous.md +891 -0
  96. package/get-shit-done/workflows/check-todos.md +2 -2
  97. package/get-shit-done/workflows/cleanup.md +4 -4
  98. package/get-shit-done/workflows/complete-milestone.md +9 -6
  99. package/get-shit-done/workflows/diagnose-issues.md +15 -3
  100. package/get-shit-done/workflows/discovery-phase.md +3 -3
  101. package/get-shit-done/workflows/discuss-phase-assumptions.md +653 -0
  102. package/get-shit-done/workflows/discuss-phase.md +411 -38
  103. package/get-shit-done/workflows/do.md +104 -0
  104. package/get-shit-done/workflows/execute-phase.md +405 -18
  105. package/get-shit-done/workflows/execute-plan.md +77 -12
  106. package/get-shit-done/workflows/fast.md +105 -0
  107. package/get-shit-done/workflows/forensics.md +265 -0
  108. package/get-shit-done/workflows/health.md +28 -6
  109. package/get-shit-done/workflows/help.md +124 -7
  110. package/get-shit-done/workflows/insert-phase.md +2 -2
  111. package/get-shit-done/workflows/list-phase-assumptions.md +2 -2
  112. package/get-shit-done/workflows/list-workspaces.md +56 -0
  113. package/get-shit-done/workflows/manager.md +362 -0
  114. package/get-shit-done/workflows/map-codebase.md +74 -13
  115. package/get-shit-done/workflows/milestone-summary.md +223 -0
  116. package/get-shit-done/workflows/new-milestone.md +120 -18
  117. package/get-shit-done/workflows/new-project.md +178 -39
  118. package/get-shit-done/workflows/new-workspace.md +237 -0
  119. package/get-shit-done/workflows/next.md +97 -0
  120. package/get-shit-done/workflows/node-repair.md +92 -0
  121. package/get-shit-done/workflows/note.md +156 -0
  122. package/get-shit-done/workflows/pause-work.md +62 -8
  123. package/get-shit-done/workflows/plan-milestone-gaps.md +4 -5
  124. package/get-shit-done/workflows/plan-phase.md +332 -33
  125. package/get-shit-done/workflows/plant-seed.md +169 -0
  126. package/get-shit-done/workflows/pr-branch.md +129 -0
  127. package/get-shit-done/workflows/profile-user.md +450 -0
  128. package/get-shit-done/workflows/progress.md +145 -20
  129. package/get-shit-done/workflows/quick.md +205 -49
  130. package/get-shit-done/workflows/remove-phase.md +2 -2
  131. package/get-shit-done/workflows/remove-workspace.md +90 -0
  132. package/get-shit-done/workflows/research-phase.md +11 -3
  133. package/get-shit-done/workflows/resume-project.md +35 -16
  134. package/get-shit-done/workflows/review.md +228 -0
  135. package/get-shit-done/workflows/session-report.md +146 -0
  136. package/get-shit-done/workflows/set-profile.md +2 -2
  137. package/get-shit-done/workflows/settings.md +79 -10
  138. package/get-shit-done/workflows/ship.md +228 -0
  139. package/get-shit-done/workflows/stats.md +60 -0
  140. package/get-shit-done/workflows/transition.md +147 -20
  141. package/get-shit-done/workflows/ui-phase.md +302 -0
  142. package/get-shit-done/workflows/ui-review.md +165 -0
  143. package/get-shit-done/workflows/update.md +108 -25
  144. package/get-shit-done/workflows/validate-phase.md +15 -8
  145. package/get-shit-done/workflows/verify-phase.md +16 -5
  146. package/get-shit-done/workflows/verify-work.md +72 -18
  147. package/package.json +1 -1
  148. package/skills/gsd-audit-milestone/SKILL.md +29 -0
  149. package/skills/gsd-cleanup/SKILL.md +19 -0
  150. package/skills/gsd-complete-milestone/SKILL.md +131 -0
  151. package/skills/gsd-discuss-phase/SKILL.md +54 -0
  152. package/skills/gsd-execute-phase/SKILL.md +49 -0
  153. package/skills/gsd-plan-phase/SKILL.md +37 -0
  154. package/skills/gsd-ui-phase/SKILL.md +24 -0
  155. package/skills/gsd-ui-review/SKILL.md +24 -0
  156. package/skills/gsd-verify-work/SKILL.md +30 -0
@@ -4,9 +4,9 @@
4
4
 
5
5
  const fs = require('fs');
6
6
  const path = require('path');
7
- const { escapeRegex, getMilestonePhaseFilter, output, error } = require('./core.cjs');
7
+ const { escapeRegex, getMilestonePhaseFilter, extractOneLinerFromBody, normalizeMd, planningPaths, output, error } = require('./core.cjs');
8
8
  const { extractFrontmatter } = require('./frontmatter.cjs');
9
- const { writeStateMd } = require('./state.cjs');
9
+ const { writeStateMd, stateReplaceFieldWithFallback } = require('./state.cjs');
10
10
 
11
11
  function cmdRequirementsMarkComplete(cwd, reqIdsRaw, raw) {
12
12
  if (!reqIdsRaw || reqIdsRaw.length === 0) {
@@ -25,7 +25,7 @@ function cmdRequirementsMarkComplete(cwd, reqIdsRaw, raw) {
25
25
  error('no valid requirement IDs found');
26
26
  }
27
27
 
28
- const reqPath = path.join(cwd, '.planning', 'REQUIREMENTS.md');
28
+ const reqPath = planningPaths(cwd).requirements;
29
29
  if (!fs.existsSync(reqPath)) {
30
30
  output({ updated: false, reason: 'REQUIREMENTS.md not found', ids: reqIds }, raw, 'no requirements file');
31
31
  return;
@@ -33,6 +33,7 @@ function cmdRequirementsMarkComplete(cwd, reqIdsRaw, raw) {
33
33
 
34
34
  let reqContent = fs.readFileSync(reqPath, 'utf-8');
35
35
  const updated = [];
36
+ const alreadyComplete = [];
36
37
  const notFound = [];
37
38
 
38
39
  for (const reqId of reqIds) {
@@ -60,7 +61,14 @@ function cmdRequirementsMarkComplete(cwd, reqIdsRaw, raw) {
60
61
  if (found) {
61
62
  updated.push(reqId);
62
63
  } else {
63
- notFound.push(reqId);
64
+ // Check if already complete before declaring not_found
65
+ const doneCheckbox = new RegExp(`-\\s*\\[x\\]\\s*\\*\\*${reqEscaped}\\*\\*`, 'gi');
66
+ const doneTable = new RegExp(`\\|\\s*${reqEscaped}\\s*\\|[^|]+\\|\\s*Complete\\s*\\|`, 'gi');
67
+ if (doneCheckbox.test(reqContent) || doneTable.test(reqContent)) {
68
+ alreadyComplete.push(reqId);
69
+ } else {
70
+ notFound.push(reqId);
71
+ }
64
72
  }
65
73
  }
66
74
 
@@ -71,6 +79,7 @@ function cmdRequirementsMarkComplete(cwd, reqIdsRaw, raw) {
71
79
  output({
72
80
  updated: updated.length > 0,
73
81
  marked_complete: updated,
82
+ already_complete: alreadyComplete,
74
83
  not_found: notFound,
75
84
  total: reqIds.length,
76
85
  }, raw, `${updated.length}/${reqIds.length} requirements marked complete`);
@@ -81,12 +90,12 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
81
90
  error('version required for milestone complete (e.g., v1.0)');
82
91
  }
83
92
 
84
- const roadmapPath = path.join(cwd, '.planning', 'ROADMAP.md');
85
- const reqPath = path.join(cwd, '.planning', 'REQUIREMENTS.md');
86
- const statePath = path.join(cwd, '.planning', 'STATE.md');
93
+ const roadmapPath = planningPaths(cwd).roadmap;
94
+ const reqPath = planningPaths(cwd).requirements;
95
+ const statePath = planningPaths(cwd).state;
87
96
  const milestonesPath = path.join(cwd, '.planning', 'MILESTONES.md');
88
97
  const archiveDir = path.join(cwd, '.planning', 'milestones');
89
- const phasesDir = path.join(cwd, '.planning', 'phases');
98
+ const phasesDir = planningPaths(cwd).phases;
90
99
  const today = new Date().toISOString().split('T')[0];
91
100
  const milestoneName = options.name || version;
92
101
 
@@ -122,16 +131,24 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
122
131
  try {
123
132
  const content = fs.readFileSync(path.join(phasesDir, dir, s), 'utf-8');
124
133
  const fm = extractFrontmatter(content);
125
- if (fm['one-liner']) {
126
- accomplishments.push(fm['one-liner']);
134
+ const oneLiner = fm['one-liner'] || extractOneLinerFromBody(content);
135
+ if (oneLiner) {
136
+ accomplishments.push(oneLiner);
137
+ }
138
+ // Count tasks: prefer **Tasks:** N from Performance section,
139
+ // then <task XML tags, then ## task N markdown headers
140
+ const tasksFieldMatch = content.match(/\*\*Tasks:\*\*\s*(\d+)/);
141
+ if (tasksFieldMatch) {
142
+ totalTasks += parseInt(tasksFieldMatch[1], 10);
143
+ } else {
144
+ const xmlTaskMatches = content.match(/<task[\s>]/gi) || [];
145
+ const mdTaskMatches = content.match(/##\s*task\s*\d+/gi) || [];
146
+ totalTasks += xmlTaskMatches.length || mdTaskMatches.length;
127
147
  }
128
- // Count tasks
129
- const taskMatches = content.match(/##\s*task\s*\d+/gi) || [];
130
- totalTasks += taskMatches.length;
131
- } catch {}
148
+ } catch { /* intentionally empty */ }
132
149
  }
133
150
  }
134
- } catch {}
151
+ } catch { /* intentionally empty */ }
135
152
 
136
153
  // Archive ROADMAP.md
137
154
  if (fs.existsSync(roadmapPath)) {
@@ -160,38 +177,32 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
160
177
  const existing = fs.readFileSync(milestonesPath, 'utf-8');
161
178
  if (!existing.trim()) {
162
179
  // Empty file — treat like new
163
- fs.writeFileSync(milestonesPath, `# Milestones\n\n${milestoneEntry}`, 'utf-8');
180
+ fs.writeFileSync(milestonesPath, normalizeMd(`# Milestones\n\n${milestoneEntry}`), 'utf-8');
164
181
  } else {
165
182
  // Insert after the header line(s) for reverse chronological order (newest first)
166
183
  const headerMatch = existing.match(/^(#{1,3}\s+[^\n]*\n\n?)/);
167
184
  if (headerMatch) {
168
185
  const header = headerMatch[1];
169
186
  const rest = existing.slice(header.length);
170
- fs.writeFileSync(milestonesPath, header + milestoneEntry + rest, 'utf-8');
187
+ fs.writeFileSync(milestonesPath, normalizeMd(header + milestoneEntry + rest), 'utf-8');
171
188
  } else {
172
189
  // No recognizable header — prepend the entry
173
- fs.writeFileSync(milestonesPath, milestoneEntry + existing, 'utf-8');
190
+ fs.writeFileSync(milestonesPath, normalizeMd(milestoneEntry + existing), 'utf-8');
174
191
  }
175
192
  }
176
193
  } else {
177
- fs.writeFileSync(milestonesPath, `# Milestones\n\n${milestoneEntry}`, 'utf-8');
194
+ fs.writeFileSync(milestonesPath, normalizeMd(`# Milestones\n\n${milestoneEntry}`), 'utf-8');
178
195
  }
179
196
 
180
- // Update STATE.md
197
+ // Update STATE.md — use shared helpers that handle both **bold:** and plain Field: formats
181
198
  if (fs.existsSync(statePath)) {
182
199
  let stateContent = fs.readFileSync(statePath, 'utf-8');
183
- stateContent = stateContent.replace(
184
- /(\*\*Status:\*\*\s*).*/,
185
- `$1${version} milestone complete`
186
- );
187
- stateContent = stateContent.replace(
188
- /(\*\*Last Activity:\*\*\s*).*/,
189
- `$1${today}`
190
- );
191
- stateContent = stateContent.replace(
192
- /(\*\*Last Activity Description:\*\*\s*).*/,
193
- `$1${version} milestone completed and archived`
194
- );
200
+
201
+ stateContent = stateReplaceFieldWithFallback(stateContent, 'Status', null, `${version} milestone complete`);
202
+ stateContent = stateReplaceFieldWithFallback(stateContent, 'Last Activity', 'Last activity', today);
203
+ stateContent = stateReplaceFieldWithFallback(stateContent, 'Last Activity Description', null,
204
+ `${version} milestone completed and archived`);
205
+
195
206
  writeStateMd(statePath, stateContent, cwd);
196
207
  }
197
208
 
@@ -211,7 +222,7 @@ function cmdMilestoneComplete(cwd, version, options, raw) {
211
222
  archivedCount++;
212
223
  }
213
224
  phasesArchived = archivedCount > 0;
214
- } catch {}
225
+ } catch { /* intentionally empty */ }
215
226
  }
216
227
 
217
228
  const result = {
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Mapping of GSD agent to model for each profile.
3
+ *
4
+ * Should be in sync with the profiles table in `get-shit-done/references/model-profiles.md`. But
5
+ * possibly worth making this the single source of truth at some point, and removing the markdown
6
+ * reference table in favor of programmatically determining the model to use for an agent (which
7
+ * would be faster, use fewer tokens, and be less error-prone).
8
+ */
9
+ const MODEL_PROFILES = {
10
+ 'gsd-planner': { quality: 'opus', balanced: 'opus', budget: 'sonnet' },
11
+ 'gsd-roadmapper': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
12
+ 'gsd-executor': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
13
+ 'gsd-phase-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
14
+ 'gsd-project-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
15
+ 'gsd-research-synthesizer': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
16
+ 'gsd-debugger': { quality: 'opus', balanced: 'sonnet', budget: 'sonnet' },
17
+ 'gsd-codebase-mapper': { quality: 'sonnet', balanced: 'haiku', budget: 'haiku' },
18
+ 'gsd-verifier': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
19
+ 'gsd-plan-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
20
+ 'gsd-integration-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
21
+ 'gsd-nyquist-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
22
+ 'gsd-ui-researcher': { quality: 'opus', balanced: 'sonnet', budget: 'haiku' },
23
+ 'gsd-ui-checker': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
24
+ 'gsd-ui-auditor': { quality: 'sonnet', balanced: 'sonnet', budget: 'haiku' },
25
+ };
26
+ const VALID_PROFILES = Object.keys(MODEL_PROFILES['gsd-planner']);
27
+
28
+ /**
29
+ * Formats the agent-to-model mapping as a human-readable table (in string format).
30
+ *
31
+ * @param {Object<string, string>} agentToModelMap - A mapping from agent to model
32
+ * @returns {string} A formatted table string
33
+ */
34
+ function formatAgentToModelMapAsTable(agentToModelMap) {
35
+ const agentWidth = Math.max('Agent'.length, ...Object.keys(agentToModelMap).map((a) => a.length));
36
+ const modelWidth = Math.max(
37
+ 'Model'.length,
38
+ ...Object.values(agentToModelMap).map((m) => m.length)
39
+ );
40
+ const sep = '─'.repeat(agentWidth + 2) + '┼' + '─'.repeat(modelWidth + 2);
41
+ const header = ' ' + 'Agent'.padEnd(agentWidth) + ' │ ' + 'Model'.padEnd(modelWidth);
42
+ let agentToModelTable = header + '\n' + sep + '\n';
43
+ for (const [agent, model] of Object.entries(agentToModelMap)) {
44
+ agentToModelTable += ' ' + agent.padEnd(agentWidth) + ' │ ' + model.padEnd(modelWidth) + '\n';
45
+ }
46
+ return agentToModelTable;
47
+ }
48
+
49
+ /**
50
+ * Returns a mapping from agent to model for the given model profile.
51
+ *
52
+ * @param {string} normalizedProfile - The normalized (lowercase and trimmed) profile name
53
+ * @returns {Object<string, string>} A mapping from agent to model for the given profile
54
+ */
55
+ function getAgentToModelMapForProfile(normalizedProfile) {
56
+ const agentToModelMap = {};
57
+ for (const [agent, profileToModelMap] of Object.entries(MODEL_PROFILES)) {
58
+ agentToModelMap[agent] = profileToModelMap[normalizedProfile];
59
+ }
60
+ return agentToModelMap;
61
+ }
62
+
63
+ module.exports = {
64
+ MODEL_PROFILES,
65
+ VALID_PROFILES,
66
+ formatAgentToModelMapAsTable,
67
+ getAgentToModelMapForProfile,
68
+ };