gsd-remix 1.0.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 (554) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +939 -0
  3. package/README.zh-CN.md +876 -0
  4. package/agents/gsd-advisor-researcher.md +127 -0
  5. package/agents/gsd-ai-researcher.md +133 -0
  6. package/agents/gsd-assumptions-analyzer.md +105 -0
  7. package/agents/gsd-code-fixer.md +517 -0
  8. package/agents/gsd-code-reviewer.md +371 -0
  9. package/agents/gsd-codebase-mapper.md +781 -0
  10. package/agents/gsd-debug-session-manager.md +314 -0
  11. package/agents/gsd-debugger.md +1452 -0
  12. package/agents/gsd-doc-classifier.md +168 -0
  13. package/agents/gsd-doc-synthesizer.md +204 -0
  14. package/agents/gsd-doc-verifier.md +217 -0
  15. package/agents/gsd-doc-writer.md +615 -0
  16. package/agents/gsd-domain-researcher.md +153 -0
  17. package/agents/gsd-eval-auditor.md +191 -0
  18. package/agents/gsd-eval-planner.md +154 -0
  19. package/agents/gsd-executor.md +603 -0
  20. package/agents/gsd-framework-selector.md +160 -0
  21. package/agents/gsd-integration-checker.md +470 -0
  22. package/agents/gsd-intel-updater.md +334 -0
  23. package/agents/gsd-nyquist-auditor.md +203 -0
  24. package/agents/gsd-pattern-mapper.md +335 -0
  25. package/agents/gsd-phase-researcher.md +841 -0
  26. package/agents/gsd-plan-checker.md +978 -0
  27. package/agents/gsd-planner.md +1251 -0
  28. package/agents/gsd-project-researcher.md +677 -0
  29. package/agents/gsd-research-synthesizer.md +247 -0
  30. package/agents/gsd-roadmapper.md +688 -0
  31. package/agents/gsd-security-auditor.md +155 -0
  32. package/agents/gsd-ui-auditor.md +495 -0
  33. package/agents/gsd-ui-checker.md +309 -0
  34. package/agents/gsd-ui-researcher.md +380 -0
  35. package/agents/gsd-user-profiler.md +171 -0
  36. package/agents/gsd-verifier.md +830 -0
  37. package/bin/install.js +7062 -0
  38. package/commands/gsd/add-backlog.md +79 -0
  39. package/commands/gsd/add-phase.md +43 -0
  40. package/commands/gsd/add-tests.md +41 -0
  41. package/commands/gsd/add-todo.md +47 -0
  42. package/commands/gsd/ai-integration-phase.md +36 -0
  43. package/commands/gsd/analyze-dependencies.md +34 -0
  44. package/commands/gsd/audit-fix.md +33 -0
  45. package/commands/gsd/audit-milestone.md +36 -0
  46. package/commands/gsd/audit-uat.md +24 -0
  47. package/commands/gsd/autonomous.md +46 -0
  48. package/commands/gsd/check-todos.md +45 -0
  49. package/commands/gsd/cleanup.md +23 -0
  50. package/commands/gsd/code-review-fix.md +52 -0
  51. package/commands/gsd/code-review.md +55 -0
  52. package/commands/gsd/complete-milestone.md +136 -0
  53. package/commands/gsd/debug.md +263 -0
  54. package/commands/gsd/discuss-phase.md +69 -0
  55. package/commands/gsd/do.md +30 -0
  56. package/commands/gsd/docs-update.md +48 -0
  57. package/commands/gsd/eval-review.md +32 -0
  58. package/commands/gsd/execute-phase.md +63 -0
  59. package/commands/gsd/explore.md +27 -0
  60. package/commands/gsd/extract_learnings.md +22 -0
  61. package/commands/gsd/fast.md +30 -0
  62. package/commands/gsd/forensics.md +56 -0
  63. package/commands/gsd/from-gsd2.md +47 -0
  64. package/commands/gsd/graphify.md +201 -0
  65. package/commands/gsd/health.md +22 -0
  66. package/commands/gsd/help.md +24 -0
  67. package/commands/gsd/import.md +37 -0
  68. package/commands/gsd/inbox.md +38 -0
  69. package/commands/gsd/ingest-docs.md +42 -0
  70. package/commands/gsd/insert-phase.md +32 -0
  71. package/commands/gsd/intel.md +179 -0
  72. package/commands/gsd/join-discord.md +19 -0
  73. package/commands/gsd/list-phase-assumptions.md +46 -0
  74. package/commands/gsd/list-workspaces.md +19 -0
  75. package/commands/gsd/manager.md +40 -0
  76. package/commands/gsd/map-codebase.md +71 -0
  77. package/commands/gsd/milestone-summary.md +51 -0
  78. package/commands/gsd/new-milestone.md +44 -0
  79. package/commands/gsd/new-project.md +46 -0
  80. package/commands/gsd/new-workspace.md +44 -0
  81. package/commands/gsd/next.md +28 -0
  82. package/commands/gsd/note.md +34 -0
  83. package/commands/gsd/pause-work.md +38 -0
  84. package/commands/gsd/plan-milestone-gaps.md +34 -0
  85. package/commands/gsd/plan-phase.md +52 -0
  86. package/commands/gsd/plan-review-convergence.md +52 -0
  87. package/commands/gsd/plant-seed.md +28 -0
  88. package/commands/gsd/pr-branch.md +25 -0
  89. package/commands/gsd/profile-user.md +46 -0
  90. package/commands/gsd/progress.md +25 -0
  91. package/commands/gsd/quick.md +173 -0
  92. package/commands/gsd/reapply-patches.md +331 -0
  93. package/commands/gsd/remove-phase.md +31 -0
  94. package/commands/gsd/remove-workspace.md +26 -0
  95. package/commands/gsd/research-phase.md +195 -0
  96. package/commands/gsd/resume-work.md +40 -0
  97. package/commands/gsd/review-backlog.md +62 -0
  98. package/commands/gsd/review.md +40 -0
  99. package/commands/gsd/scan.md +26 -0
  100. package/commands/gsd/secure-phase.md +35 -0
  101. package/commands/gsd/session-report.md +19 -0
  102. package/commands/gsd/set-profile.md +12 -0
  103. package/commands/gsd/settings.md +36 -0
  104. package/commands/gsd/ship.md +23 -0
  105. package/commands/gsd/sketch-wrap-up.md +31 -0
  106. package/commands/gsd/sketch.md +49 -0
  107. package/commands/gsd/spec-phase.md +62 -0
  108. package/commands/gsd/spike-wrap-up.md +31 -0
  109. package/commands/gsd/spike.md +46 -0
  110. package/commands/gsd/stats.md +18 -0
  111. package/commands/gsd/sync-skills.md +19 -0
  112. package/commands/gsd/thread.md +227 -0
  113. package/commands/gsd/ui-phase.md +34 -0
  114. package/commands/gsd/ui-review.md +32 -0
  115. package/commands/gsd/ultraplan-phase.md +33 -0
  116. package/commands/gsd/undo.md +34 -0
  117. package/commands/gsd/update.md +37 -0
  118. package/commands/gsd/validate-phase.md +35 -0
  119. package/commands/gsd/verify-work.md +38 -0
  120. package/commands/gsd/workstreams.md +69 -0
  121. package/get-shit-done/bin/gsd-tools.cjs +1263 -0
  122. package/get-shit-done/bin/lib/artifacts.cjs +52 -0
  123. package/get-shit-done/bin/lib/audit.cjs +757 -0
  124. package/get-shit-done/bin/lib/commands.cjs +1023 -0
  125. package/get-shit-done/bin/lib/config-schema.cjs +79 -0
  126. package/get-shit-done/bin/lib/config.cjs +463 -0
  127. package/get-shit-done/bin/lib/core.cjs +1794 -0
  128. package/get-shit-done/bin/lib/docs.cjs +267 -0
  129. package/get-shit-done/bin/lib/frontmatter.cjs +379 -0
  130. package/get-shit-done/bin/lib/graphify.cjs +494 -0
  131. package/get-shit-done/bin/lib/gsd2-import.cjs +511 -0
  132. package/get-shit-done/bin/lib/init.cjs +1878 -0
  133. package/get-shit-done/bin/lib/intel.cjs +639 -0
  134. package/get-shit-done/bin/lib/learnings.cjs +378 -0
  135. package/get-shit-done/bin/lib/milestone.cjs +283 -0
  136. package/get-shit-done/bin/lib/model-profiles.cjs +71 -0
  137. package/get-shit-done/bin/lib/phase.cjs +1058 -0
  138. package/get-shit-done/bin/lib/profile-output.cjs +1080 -0
  139. package/get-shit-done/bin/lib/profile-pipeline.cjs +539 -0
  140. package/get-shit-done/bin/lib/roadmap.cjs +523 -0
  141. package/get-shit-done/bin/lib/schema-detect.cjs +238 -0
  142. package/get-shit-done/bin/lib/security.cjs +504 -0
  143. package/get-shit-done/bin/lib/state.cjs +1649 -0
  144. package/get-shit-done/bin/lib/template.cjs +226 -0
  145. package/get-shit-done/bin/lib/uat.cjs +288 -0
  146. package/get-shit-done/bin/lib/verify.cjs +1184 -0
  147. package/get-shit-done/bin/lib/workstream.cjs +495 -0
  148. package/get-shit-done/bin/repair-sdk.cjs +177 -0
  149. package/get-shit-done/contexts/dev.md +21 -0
  150. package/get-shit-done/contexts/research.md +22 -0
  151. package/get-shit-done/contexts/review.md +22 -0
  152. package/get-shit-done/references/agent-contracts.md +79 -0
  153. package/get-shit-done/references/ai-evals.md +156 -0
  154. package/get-shit-done/references/ai-frameworks.md +186 -0
  155. package/get-shit-done/references/artifact-types.md +131 -0
  156. package/get-shit-done/references/autonomous-smart-discuss.md +277 -0
  157. package/get-shit-done/references/checkpoints.md +808 -0
  158. package/get-shit-done/references/common-bug-patterns.md +114 -0
  159. package/get-shit-done/references/context-budget.md +49 -0
  160. package/get-shit-done/references/continuation-format.md +253 -0
  161. package/get-shit-done/references/debugger-philosophy.md +76 -0
  162. package/get-shit-done/references/decimal-phase-calculation.md +64 -0
  163. package/get-shit-done/references/doc-conflict-engine.md +91 -0
  164. package/get-shit-done/references/domain-probes.md +125 -0
  165. package/get-shit-done/references/executor-examples.md +110 -0
  166. package/get-shit-done/references/few-shot-examples/plan-checker.md +73 -0
  167. package/get-shit-done/references/few-shot-examples/verifier.md +109 -0
  168. package/get-shit-done/references/gate-prompts.md +100 -0
  169. package/get-shit-done/references/gates.md +70 -0
  170. package/get-shit-done/references/git-integration.md +295 -0
  171. package/get-shit-done/references/git-planning-commit.md +40 -0
  172. package/get-shit-done/references/ios-scaffold.md +123 -0
  173. package/get-shit-done/references/mandatory-initial-read.md +2 -0
  174. package/get-shit-done/references/model-profile-resolution.md +38 -0
  175. package/get-shit-done/references/model-profiles.md +145 -0
  176. package/get-shit-done/references/phase-argument-parsing.md +61 -0
  177. package/get-shit-done/references/planner-antipatterns.md +89 -0
  178. package/get-shit-done/references/planner-gap-closure.md +62 -0
  179. package/get-shit-done/references/planner-reviews.md +39 -0
  180. package/get-shit-done/references/planner-revision.md +87 -0
  181. package/get-shit-done/references/planner-source-audit.md +73 -0
  182. package/get-shit-done/references/planning-config.md +460 -0
  183. package/get-shit-done/references/project-skills-discovery.md +19 -0
  184. package/get-shit-done/references/questioning.md +162 -0
  185. package/get-shit-done/references/revision-loop.md +97 -0
  186. package/get-shit-done/references/sketch-interactivity.md +41 -0
  187. package/get-shit-done/references/sketch-theme-system.md +94 -0
  188. package/get-shit-done/references/sketch-tooling.md +45 -0
  189. package/get-shit-done/references/sketch-variant-patterns.md +81 -0
  190. package/get-shit-done/references/tdd.md +330 -0
  191. package/get-shit-done/references/thinking-models-debug.md +44 -0
  192. package/get-shit-done/references/thinking-models-execution.md +50 -0
  193. package/get-shit-done/references/thinking-models-planning.md +62 -0
  194. package/get-shit-done/references/thinking-models-research.md +50 -0
  195. package/get-shit-done/references/thinking-models-verification.md +55 -0
  196. package/get-shit-done/references/thinking-partner.md +96 -0
  197. package/get-shit-done/references/ui-brand.md +160 -0
  198. package/get-shit-done/references/universal-anti-patterns.md +63 -0
  199. package/get-shit-done/references/user-profiling.md +681 -0
  200. package/get-shit-done/references/verification-overrides.md +227 -0
  201. package/get-shit-done/references/verification-patterns.md +612 -0
  202. package/get-shit-done/references/workstream-flag.md +111 -0
  203. package/get-shit-done/templates/AI-SPEC.md +246 -0
  204. package/get-shit-done/templates/DEBUG.md +169 -0
  205. package/get-shit-done/templates/README.md +76 -0
  206. package/get-shit-done/templates/SECURITY.md +61 -0
  207. package/get-shit-done/templates/UAT.md +265 -0
  208. package/get-shit-done/templates/UI-SPEC.md +100 -0
  209. package/get-shit-done/templates/VALIDATION.md +76 -0
  210. package/get-shit-done/templates/claude-md.md +145 -0
  211. package/get-shit-done/templates/codebase/architecture.md +255 -0
  212. package/get-shit-done/templates/codebase/concerns.md +310 -0
  213. package/get-shit-done/templates/codebase/conventions.md +307 -0
  214. package/get-shit-done/templates/codebase/integrations.md +280 -0
  215. package/get-shit-done/templates/codebase/stack.md +186 -0
  216. package/get-shit-done/templates/codebase/structure.md +285 -0
  217. package/get-shit-done/templates/codebase/testing.md +480 -0
  218. package/get-shit-done/templates/config.json +56 -0
  219. package/get-shit-done/templates/context.md +352 -0
  220. package/get-shit-done/templates/continue-here.md +78 -0
  221. package/get-shit-done/templates/copilot-instructions.md +7 -0
  222. package/get-shit-done/templates/debug-subagent-prompt.md +91 -0
  223. package/get-shit-done/templates/dev-preferences.md +21 -0
  224. package/get-shit-done/templates/discovery.md +146 -0
  225. package/get-shit-done/templates/discussion-log.md +63 -0
  226. package/get-shit-done/templates/milestone-archive.md +123 -0
  227. package/get-shit-done/templates/milestone.md +115 -0
  228. package/get-shit-done/templates/phase-prompt.md +610 -0
  229. package/get-shit-done/templates/planner-subagent-prompt.md +117 -0
  230. package/get-shit-done/templates/project.md +186 -0
  231. package/get-shit-done/templates/requirements.md +231 -0
  232. package/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
  233. package/get-shit-done/templates/research-project/FEATURES.md +147 -0
  234. package/get-shit-done/templates/research-project/PITFALLS.md +200 -0
  235. package/get-shit-done/templates/research-project/STACK.md +120 -0
  236. package/get-shit-done/templates/research-project/SUMMARY.md +170 -0
  237. package/get-shit-done/templates/research.md +592 -0
  238. package/get-shit-done/templates/retrospective.md +54 -0
  239. package/get-shit-done/templates/roadmap.md +202 -0
  240. package/get-shit-done/templates/spec.md +307 -0
  241. package/get-shit-done/templates/state.md +184 -0
  242. package/get-shit-done/templates/summary-complex.md +59 -0
  243. package/get-shit-done/templates/summary-minimal.md +41 -0
  244. package/get-shit-done/templates/summary-standard.md +48 -0
  245. package/get-shit-done/templates/summary.md +248 -0
  246. package/get-shit-done/templates/user-profile.md +146 -0
  247. package/get-shit-done/templates/user-setup.md +311 -0
  248. package/get-shit-done/templates/verification-report.md +322 -0
  249. package/get-shit-done/workflows/add-phase.md +112 -0
  250. package/get-shit-done/workflows/add-tests.md +354 -0
  251. package/get-shit-done/workflows/add-todo.md +160 -0
  252. package/get-shit-done/workflows/ai-integration-phase.md +284 -0
  253. package/get-shit-done/workflows/analyze-dependencies.md +96 -0
  254. package/get-shit-done/workflows/audit-fix.md +175 -0
  255. package/get-shit-done/workflows/audit-milestone.md +340 -0
  256. package/get-shit-done/workflows/audit-uat.md +109 -0
  257. package/get-shit-done/workflows/autonomous.md +789 -0
  258. package/get-shit-done/workflows/check-todos.md +179 -0
  259. package/get-shit-done/workflows/cleanup.md +154 -0
  260. package/get-shit-done/workflows/code-review-fix.md +497 -0
  261. package/get-shit-done/workflows/code-review.md +515 -0
  262. package/get-shit-done/workflows/complete-milestone.md +847 -0
  263. package/get-shit-done/workflows/diagnose-issues.md +238 -0
  264. package/get-shit-done/workflows/discovery-phase.md +291 -0
  265. package/get-shit-done/workflows/discuss-phase-assumptions.md +670 -0
  266. package/get-shit-done/workflows/discuss-phase-power.md +308 -0
  267. package/get-shit-done/workflows/discuss-phase.md +1378 -0
  268. package/get-shit-done/workflows/do.md +110 -0
  269. package/get-shit-done/workflows/docs-update.md +1155 -0
  270. package/get-shit-done/workflows/eval-review.md +155 -0
  271. package/get-shit-done/workflows/execute-phase.md +1677 -0
  272. package/get-shit-done/workflows/execute-plan.md +533 -0
  273. package/get-shit-done/workflows/explore.md +141 -0
  274. package/get-shit-done/workflows/extract_learnings.md +242 -0
  275. package/get-shit-done/workflows/fast.md +105 -0
  276. package/get-shit-done/workflows/forensics.md +265 -0
  277. package/get-shit-done/workflows/graduation.md +195 -0
  278. package/get-shit-done/workflows/health.md +314 -0
  279. package/get-shit-done/workflows/help.md +667 -0
  280. package/get-shit-done/workflows/import.md +246 -0
  281. package/get-shit-done/workflows/inbox.md +387 -0
  282. package/get-shit-done/workflows/ingest-docs.md +328 -0
  283. package/get-shit-done/workflows/insert-phase.md +130 -0
  284. package/get-shit-done/workflows/list-phase-assumptions.md +178 -0
  285. package/get-shit-done/workflows/list-workspaces.md +56 -0
  286. package/get-shit-done/workflows/manager.md +365 -0
  287. package/get-shit-done/workflows/map-codebase.md +393 -0
  288. package/get-shit-done/workflows/milestone-summary.md +223 -0
  289. package/get-shit-done/workflows/new-milestone.md +611 -0
  290. package/get-shit-done/workflows/new-project.md +1391 -0
  291. package/get-shit-done/workflows/new-workspace.md +239 -0
  292. package/get-shit-done/workflows/next.md +220 -0
  293. package/get-shit-done/workflows/node-repair.md +92 -0
  294. package/get-shit-done/workflows/note.md +158 -0
  295. package/get-shit-done/workflows/pause-work.md +243 -0
  296. package/get-shit-done/workflows/plan-milestone-gaps.md +273 -0
  297. package/get-shit-done/workflows/plan-phase.md +1349 -0
  298. package/get-shit-done/workflows/plan-review-convergence.md +254 -0
  299. package/get-shit-done/workflows/plant-seed.md +172 -0
  300. package/get-shit-done/workflows/pr-branch.md +157 -0
  301. package/get-shit-done/workflows/profile-user.md +452 -0
  302. package/get-shit-done/workflows/progress.md +619 -0
  303. package/get-shit-done/workflows/quick.md +970 -0
  304. package/get-shit-done/workflows/remove-phase.md +155 -0
  305. package/get-shit-done/workflows/remove-workspace.md +92 -0
  306. package/get-shit-done/workflows/research-phase.md +89 -0
  307. package/get-shit-done/workflows/resume-project.md +326 -0
  308. package/get-shit-done/workflows/review.md +344 -0
  309. package/get-shit-done/workflows/scan.md +102 -0
  310. package/get-shit-done/workflows/secure-phase.md +166 -0
  311. package/get-shit-done/workflows/session-report.md +146 -0
  312. package/get-shit-done/workflows/settings.md +319 -0
  313. package/get-shit-done/workflows/ship.md +302 -0
  314. package/get-shit-done/workflows/sketch-wrap-up.md +283 -0
  315. package/get-shit-done/workflows/sketch.md +286 -0
  316. package/get-shit-done/workflows/spec-phase.md +262 -0
  317. package/get-shit-done/workflows/spike-wrap-up.md +281 -0
  318. package/get-shit-done/workflows/spike.md +362 -0
  319. package/get-shit-done/workflows/stats.md +60 -0
  320. package/get-shit-done/workflows/sync-skills.md +182 -0
  321. package/get-shit-done/workflows/transition.md +693 -0
  322. package/get-shit-done/workflows/ui-phase.md +323 -0
  323. package/get-shit-done/workflows/ui-review.md +190 -0
  324. package/get-shit-done/workflows/ultraplan-phase.md +189 -0
  325. package/get-shit-done/workflows/undo.md +314 -0
  326. package/get-shit-done/workflows/update.md +587 -0
  327. package/get-shit-done/workflows/validate-phase.md +176 -0
  328. package/get-shit-done/workflows/verify-phase.md +465 -0
  329. package/get-shit-done/workflows/verify-work.md +740 -0
  330. package/hooks/dist/gsd-check-update-worker.js +108 -0
  331. package/hooks/dist/gsd-check-update.js +64 -0
  332. package/hooks/dist/gsd-context-monitor.js +192 -0
  333. package/hooks/dist/gsd-phase-boundary.sh +28 -0
  334. package/hooks/dist/gsd-prompt-guard.js +97 -0
  335. package/hooks/dist/gsd-read-guard.js +82 -0
  336. package/hooks/dist/gsd-read-injection-scanner.js +152 -0
  337. package/hooks/dist/gsd-session-state.sh +34 -0
  338. package/hooks/dist/gsd-statusline.js +293 -0
  339. package/hooks/dist/gsd-validate-commit.sh +48 -0
  340. package/hooks/dist/gsd-workflow-guard.js +94 -0
  341. package/hooks/gsd-check-update-worker.js +108 -0
  342. package/hooks/gsd-check-update.js +64 -0
  343. package/hooks/gsd-context-monitor.js +192 -0
  344. package/hooks/gsd-phase-boundary.sh +28 -0
  345. package/hooks/gsd-prompt-guard.js +97 -0
  346. package/hooks/gsd-read-guard.js +82 -0
  347. package/hooks/gsd-read-injection-scanner.js +152 -0
  348. package/hooks/gsd-session-state.sh +34 -0
  349. package/hooks/gsd-statusline.js +293 -0
  350. package/hooks/gsd-validate-commit.sh +48 -0
  351. package/hooks/gsd-workflow-guard.js +94 -0
  352. package/package.json +59 -0
  353. package/scripts/base64-scan.sh +262 -0
  354. package/scripts/build-hooks.js +95 -0
  355. package/scripts/gen-inventory-manifest.cjs +109 -0
  356. package/scripts/prompt-injection-scan.sh +201 -0
  357. package/scripts/run-tests.cjs +33 -0
  358. package/scripts/secret-scan.sh +227 -0
  359. package/sdk/package-lock.json +1998 -0
  360. package/sdk/package.json +52 -0
  361. package/sdk/prompts/agents/gsd-executor.md +110 -0
  362. package/sdk/prompts/agents/gsd-phase-researcher.md +158 -0
  363. package/sdk/prompts/agents/gsd-plan-checker.md +160 -0
  364. package/sdk/prompts/agents/gsd-planner.md +214 -0
  365. package/sdk/prompts/agents/gsd-project-researcher.md +323 -0
  366. package/sdk/prompts/agents/gsd-research-synthesizer.md +237 -0
  367. package/sdk/prompts/agents/gsd-roadmapper.md +670 -0
  368. package/sdk/prompts/agents/gsd-verifier.md +159 -0
  369. package/sdk/prompts/templates/project.md +186 -0
  370. package/sdk/prompts/templates/requirements.md +231 -0
  371. package/sdk/prompts/templates/research-project/ARCHITECTURE.md +204 -0
  372. package/sdk/prompts/templates/research-project/FEATURES.md +147 -0
  373. package/sdk/prompts/templates/research-project/PITFALLS.md +200 -0
  374. package/sdk/prompts/templates/research-project/STACK.md +120 -0
  375. package/sdk/prompts/templates/research-project/SUMMARY.md +170 -0
  376. package/sdk/prompts/templates/roadmap.md +202 -0
  377. package/sdk/prompts/templates/state.md +175 -0
  378. package/sdk/prompts/workflows/discuss-phase.md +126 -0
  379. package/sdk/prompts/workflows/execute-plan.md +106 -0
  380. package/sdk/prompts/workflows/plan-phase.md +84 -0
  381. package/sdk/prompts/workflows/research-phase.md +45 -0
  382. package/sdk/prompts/workflows/verify-phase.md +142 -0
  383. package/sdk/src/assembled-prompts.test.ts +349 -0
  384. package/sdk/src/cli-transport.test.ts +388 -0
  385. package/sdk/src/cli-transport.ts +130 -0
  386. package/sdk/src/cli.test.ts +383 -0
  387. package/sdk/src/cli.ts +670 -0
  388. package/sdk/src/config.test.ts +168 -0
  389. package/sdk/src/config.ts +177 -0
  390. package/sdk/src/context-engine.test.ts +295 -0
  391. package/sdk/src/context-engine.ts +170 -0
  392. package/sdk/src/context-truncation.test.ts +163 -0
  393. package/sdk/src/context-truncation.ts +233 -0
  394. package/sdk/src/e2e.integration.test.ts +178 -0
  395. package/sdk/src/errors.ts +72 -0
  396. package/sdk/src/event-stream.test.ts +661 -0
  397. package/sdk/src/event-stream.ts +441 -0
  398. package/sdk/src/failure-memory.test.ts +457 -0
  399. package/sdk/src/failure-memory.ts +1324 -0
  400. package/sdk/src/golden/capture.ts +95 -0
  401. package/sdk/src/golden/fixtures/generate-slug.golden.json +1 -0
  402. package/sdk/src/golden/fixtures/profile-sample-sessions/demo-project/sample.jsonl +3 -0
  403. package/sdk/src/golden/fixtures/summary-extract-sample.md +26 -0
  404. package/sdk/src/golden/fixtures/uat-render-checkpoint-sample.md +15 -0
  405. package/sdk/src/golden/golden-integration-covered.ts +30 -0
  406. package/sdk/src/golden/golden-mutation-covered.ts +7 -0
  407. package/sdk/src/golden/golden-policy.test.ts +8 -0
  408. package/sdk/src/golden/golden-policy.ts +112 -0
  409. package/sdk/src/golden/golden.integration.test.ts +373 -0
  410. package/sdk/src/golden/init-golden-normalize.ts +15 -0
  411. package/sdk/src/golden/read-only-golden-rows.ts +77 -0
  412. package/sdk/src/golden/read-only-parity.integration.test.ts +125 -0
  413. package/sdk/src/golden/registry-canonical-commands.ts +31 -0
  414. package/sdk/src/gsd-tools.test.ts +409 -0
  415. package/sdk/src/gsd-tools.ts +595 -0
  416. package/sdk/src/headless-prompts.test.ts +159 -0
  417. package/sdk/src/index.ts +333 -0
  418. package/sdk/src/init-e2e.integration.test.ts +136 -0
  419. package/sdk/src/init-runner.test.ts +783 -0
  420. package/sdk/src/init-runner.ts +735 -0
  421. package/sdk/src/lifecycle-e2e.integration.test.ts +258 -0
  422. package/sdk/src/logger.test.ts +149 -0
  423. package/sdk/src/logger.ts +113 -0
  424. package/sdk/src/milestone-runner.test.ts +421 -0
  425. package/sdk/src/phase-prompt.test.ts +538 -0
  426. package/sdk/src/phase-prompt.ts +264 -0
  427. package/sdk/src/phase-runner-types.test.ts +421 -0
  428. package/sdk/src/phase-runner.integration.test.ts +377 -0
  429. package/sdk/src/phase-runner.test.ts +2333 -0
  430. package/sdk/src/phase-runner.ts +1203 -0
  431. package/sdk/src/plan-parser.test.ts +528 -0
  432. package/sdk/src/plan-parser.ts +427 -0
  433. package/sdk/src/prompt-builder.test.ts +306 -0
  434. package/sdk/src/prompt-builder.ts +193 -0
  435. package/sdk/src/prompt-sanitizer.test.ts +260 -0
  436. package/sdk/src/prompt-sanitizer.ts +71 -0
  437. package/sdk/src/query/QUERY-HANDLERS.md +317 -0
  438. package/sdk/src/query/audit-open.ts +722 -0
  439. package/sdk/src/query/check-auto-mode.test.ts +77 -0
  440. package/sdk/src/query/check-auto-mode.ts +50 -0
  441. package/sdk/src/query/check-completion.test.ts +113 -0
  442. package/sdk/src/query/check-completion.ts +182 -0
  443. package/sdk/src/query/check-gates.test.ts +103 -0
  444. package/sdk/src/query/check-gates.ts +112 -0
  445. package/sdk/src/query/check-ship-ready.test.ts +77 -0
  446. package/sdk/src/query/check-ship-ready.ts +103 -0
  447. package/sdk/src/query/check-verification-status.test.ts +143 -0
  448. package/sdk/src/query/check-verification-status.ts +160 -0
  449. package/sdk/src/query/commit.test.ts +202 -0
  450. package/sdk/src/query/commit.ts +301 -0
  451. package/sdk/src/query/config-gates.test.ts +89 -0
  452. package/sdk/src/query/config-gates.ts +69 -0
  453. package/sdk/src/query/config-mutation.test.ts +365 -0
  454. package/sdk/src/query/config-mutation.ts +497 -0
  455. package/sdk/src/query/config-query.test.ts +161 -0
  456. package/sdk/src/query/config-query.ts +190 -0
  457. package/sdk/src/query/context-history.test.ts +165 -0
  458. package/sdk/src/query/context-history.ts +467 -0
  459. package/sdk/src/query/decomposed-handlers.test.ts +365 -0
  460. package/sdk/src/query/detect-custom-files.ts +97 -0
  461. package/sdk/src/query/detect-phase-type.test.ts +105 -0
  462. package/sdk/src/query/detect-phase-type.ts +141 -0
  463. package/sdk/src/query/docs-init.ts +257 -0
  464. package/sdk/src/query/failure-capture.ts +58 -0
  465. package/sdk/src/query/frontmatter-array.test.ts +14 -0
  466. package/sdk/src/query/frontmatter-mutation.test.ts +259 -0
  467. package/sdk/src/query/frontmatter-mutation.ts +343 -0
  468. package/sdk/src/query/frontmatter.test.ts +281 -0
  469. package/sdk/src/query/frontmatter.ts +397 -0
  470. package/sdk/src/query/helpers.test.ts +426 -0
  471. package/sdk/src/query/helpers.ts +482 -0
  472. package/sdk/src/query/index.ts +586 -0
  473. package/sdk/src/query/init-complex.test.ts +232 -0
  474. package/sdk/src/query/init-complex.ts +578 -0
  475. package/sdk/src/query/init.test.ts +522 -0
  476. package/sdk/src/query/init.ts +1046 -0
  477. package/sdk/src/query/intel.test.ts +90 -0
  478. package/sdk/src/query/intel.ts +404 -0
  479. package/sdk/src/query/normalize-query-command.test.ts +50 -0
  480. package/sdk/src/query/normalize-query-command.ts +56 -0
  481. package/sdk/src/query/phase-lifecycle.test.ts +1126 -0
  482. package/sdk/src/query/phase-lifecycle.ts +1799 -0
  483. package/sdk/src/query/phase-list-queries.test.ts +88 -0
  484. package/sdk/src/query/phase-list-queries.ts +152 -0
  485. package/sdk/src/query/phase-ready.test.ts +65 -0
  486. package/sdk/src/query/phase-ready.ts +158 -0
  487. package/sdk/src/query/phase.test.ts +307 -0
  488. package/sdk/src/query/phase.ts +340 -0
  489. package/sdk/src/query/pipeline.test.ts +169 -0
  490. package/sdk/src/query/pipeline.ts +243 -0
  491. package/sdk/src/query/plan-execution-route.test.ts +166 -0
  492. package/sdk/src/query/plan-execution-route.ts +209 -0
  493. package/sdk/src/query/plan-task-structure.test.ts +65 -0
  494. package/sdk/src/query/plan-task-structure.ts +63 -0
  495. package/sdk/src/query/profile-extract-messages.ts +247 -0
  496. package/sdk/src/query/profile-output.ts +908 -0
  497. package/sdk/src/query/profile-questionnaire-data.ts +181 -0
  498. package/sdk/src/query/profile-sample.ts +184 -0
  499. package/sdk/src/query/profile-scan-sessions.ts +174 -0
  500. package/sdk/src/query/profile.test.ts +74 -0
  501. package/sdk/src/query/profile.ts +337 -0
  502. package/sdk/src/query/progress.test.ts +156 -0
  503. package/sdk/src/query/progress.ts +566 -0
  504. package/sdk/src/query/registry.test.ts +216 -0
  505. package/sdk/src/query/registry.ts +174 -0
  506. package/sdk/src/query/requirements-extract-from-plans.test.ts +58 -0
  507. package/sdk/src/query/requirements-extract-from-plans.ts +86 -0
  508. package/sdk/src/query/roadmap-update-plan-progress.ts +132 -0
  509. package/sdk/src/query/roadmap.test.ts +359 -0
  510. package/sdk/src/query/roadmap.ts +591 -0
  511. package/sdk/src/query/route-next-action.test.ts +61 -0
  512. package/sdk/src/query/route-next-action.ts +345 -0
  513. package/sdk/src/query/runtime-health.ts +7 -0
  514. package/sdk/src/query/schema-detect.ts +189 -0
  515. package/sdk/src/query/skill-manifest.ts +214 -0
  516. package/sdk/src/query/skills.test.ts +80 -0
  517. package/sdk/src/query/skills.ts +62 -0
  518. package/sdk/src/query/state-mutation.test.ts +450 -0
  519. package/sdk/src/query/state-mutation.ts +1444 -0
  520. package/sdk/src/query/state-project-load.ts +109 -0
  521. package/sdk/src/query/state.test.ts +347 -0
  522. package/sdk/src/query/state.ts +397 -0
  523. package/sdk/src/query/summary.test.ts +95 -0
  524. package/sdk/src/query/summary.ts +296 -0
  525. package/sdk/src/query/template.test.ts +180 -0
  526. package/sdk/src/query/template.ts +242 -0
  527. package/sdk/src/query/uat.test.ts +77 -0
  528. package/sdk/src/query/uat.ts +314 -0
  529. package/sdk/src/query/utils.test.ts +82 -0
  530. package/sdk/src/query/utils.ts +92 -0
  531. package/sdk/src/query/validate.test.ts +656 -0
  532. package/sdk/src/query/validate.ts +807 -0
  533. package/sdk/src/query/verify.test.ts +414 -0
  534. package/sdk/src/query/verify.ts +645 -0
  535. package/sdk/src/query/websearch.test.ts +31 -0
  536. package/sdk/src/query/websearch.ts +82 -0
  537. package/sdk/src/query/workspace.test.ts +119 -0
  538. package/sdk/src/query/workspace.ts +131 -0
  539. package/sdk/src/query/workstream.test.ts +51 -0
  540. package/sdk/src/query/workstream.ts +434 -0
  541. package/sdk/src/research-gate.test.ts +190 -0
  542. package/sdk/src/research-gate.ts +94 -0
  543. package/sdk/src/runtime-health.test.ts +176 -0
  544. package/sdk/src/runtime-health.ts +387 -0
  545. package/sdk/src/session-runner.test.ts +98 -0
  546. package/sdk/src/session-runner.ts +299 -0
  547. package/sdk/src/tool-scoping.test.ts +160 -0
  548. package/sdk/src/tool-scoping.ts +61 -0
  549. package/sdk/src/types.ts +917 -0
  550. package/sdk/src/workstream-utils.ts +33 -0
  551. package/sdk/src/ws-flag.test.ts +285 -0
  552. package/sdk/src/ws-transport.test.ts +161 -0
  553. package/sdk/src/ws-transport.ts +93 -0
  554. package/sdk/tsconfig.json +20 -0
@@ -0,0 +1,307 @@
1
+ /**
2
+ * Unit tests for phase query handlers.
3
+ *
4
+ * Tests findPhase and phasePlanIndex handlers.
5
+ * Uses temp directories with real .planning/ structures.
6
+ */
7
+
8
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
9
+ import { mkdtemp, writeFile, mkdir, rm } from 'node:fs/promises';
10
+ import { join } from 'node:path';
11
+ import { tmpdir } from 'node:os';
12
+ import { GSDError } from '../errors.js';
13
+
14
+ import { findPhase, phasePlanIndex } from './phase.js';
15
+
16
+ // ─── Fixtures ──────────────────────────────────────────────────────────────
17
+
18
+ const PLAN_01_CONTENT = `---
19
+ phase: 09-foundation
20
+ plan: 01
21
+ wave: 1
22
+ autonomous: true
23
+ files_modified:
24
+ - sdk/src/errors.ts
25
+ - sdk/src/errors.test.ts
26
+ ---
27
+
28
+ <objective>
29
+ Build error classification system.
30
+ </objective>
31
+
32
+ <tasks>
33
+ <task type="auto">
34
+ <name>Task 1: Create error types</name>
35
+ </task>
36
+ <task type="auto">
37
+ <name>Task 2: Add exit codes</name>
38
+ </task>
39
+ </tasks>
40
+ `;
41
+
42
+ const PLAN_02_CONTENT = `---
43
+ phase: 09-foundation
44
+ plan: 02
45
+ wave: 1
46
+ autonomous: false
47
+ files_modified:
48
+ - sdk/src/query/registry.ts
49
+ ---
50
+
51
+ <objective>
52
+ Build query registry.
53
+ </objective>
54
+
55
+ <tasks>
56
+ <task type="auto">
57
+ <name>Task 1: Registry class</name>
58
+ </task>
59
+ <task type="checkpoint:human-verify">
60
+ <name>Task 2: Verify registry</name>
61
+ </task>
62
+ </tasks>
63
+ `;
64
+
65
+ const PLAN_03_CONTENT = `---
66
+ phase: 09-foundation
67
+ plan: 03
68
+ wave: 2
69
+ autonomous: true
70
+ ---
71
+
72
+ <objective>
73
+ Golden file tests.
74
+ </objective>
75
+
76
+ <tasks>
77
+ <task type="auto">
78
+ <name>Task 1: Setup golden files</name>
79
+ </task>
80
+ </tasks>
81
+ `;
82
+
83
+ let tmpDir: string;
84
+
85
+ // ─── Setup / Teardown ──────────────────────────────────────────────────────
86
+
87
+ beforeEach(async () => {
88
+ tmpDir = await mkdtemp(join(tmpdir(), 'gsd-phase-test-'));
89
+ const planningDir = join(tmpDir, '.planning');
90
+ const phasesDir = join(planningDir, 'phases');
91
+
92
+ await mkdir(phasesDir, { recursive: true });
93
+
94
+ // Phase 09
95
+ const phase09 = join(phasesDir, '09-foundation');
96
+ await mkdir(phase09, { recursive: true });
97
+ await writeFile(join(phase09, '09-01-PLAN.md'), PLAN_01_CONTENT);
98
+ await writeFile(join(phase09, '09-01-SUMMARY.md'), 'Summary 1');
99
+ await writeFile(join(phase09, '09-02-PLAN.md'), PLAN_02_CONTENT);
100
+ await writeFile(join(phase09, '09-02-SUMMARY.md'), 'Summary 2');
101
+ await writeFile(join(phase09, '09-03-PLAN.md'), PLAN_03_CONTENT);
102
+ // No summary for plan 03 (incomplete)
103
+ await writeFile(join(phase09, '09-RESEARCH.md'), 'Research');
104
+ await writeFile(join(phase09, '09-CONTEXT.md'), 'Context');
105
+
106
+ // Phase 10
107
+ const phase10 = join(phasesDir, '10-read-only-queries');
108
+ await mkdir(phase10, { recursive: true });
109
+ await writeFile(join(phase10, '10-01-PLAN.md'), '---\nphase: 10\nplan: 01\n---\n<objective>\nPort helpers.\n</objective>\n<tasks>\n<task type="auto">\n <name>Task 1</name>\n</task>\n</tasks>');
110
+ });
111
+
112
+ afterEach(async () => {
113
+ await rm(tmpDir, { recursive: true, force: true });
114
+ });
115
+
116
+ // ─── findPhase ─────────────────────────────────────────────────────────────
117
+
118
+ describe('findPhase', () => {
119
+ it('finds existing phase by number', async () => {
120
+ const result = await findPhase(['9'], tmpDir);
121
+ const data = result.data as Record<string, unknown>;
122
+
123
+ expect(data.found).toBe(true);
124
+ expect(data.phase_number).toBe('09');
125
+ expect(data.phase_name).toBe('foundation');
126
+ });
127
+
128
+ it('returns posix-style directory path', async () => {
129
+ const result = await findPhase(['9'], tmpDir);
130
+ const data = result.data as Record<string, unknown>;
131
+
132
+ expect(data.directory).toBe('.planning/phases/09-foundation');
133
+ // No backslashes
134
+ expect((data.directory as string)).not.toContain('\\');
135
+ });
136
+
137
+ it('lists plans and summaries', async () => {
138
+ const result = await findPhase(['9'], tmpDir);
139
+ const data = result.data as Record<string, unknown>;
140
+
141
+ const plans = data.plans as string[];
142
+ const summaries = data.summaries as string[];
143
+
144
+ expect(plans.length).toBe(3);
145
+ expect(summaries.length).toBe(2);
146
+ expect(plans).toContain('09-01-PLAN.md');
147
+ expect(summaries).toContain('09-01-SUMMARY.md');
148
+ });
149
+
150
+ it('returns not found for nonexistent phase', async () => {
151
+ const result = await findPhase(['99'], tmpDir);
152
+ const data = result.data as Record<string, unknown>;
153
+
154
+ expect(data.found).toBe(false);
155
+ expect(data.directory).toBeNull();
156
+ expect(data.phase_number).toBeNull();
157
+ expect(data.plans).toEqual([]);
158
+ expect(data.summaries).toEqual([]);
159
+ });
160
+
161
+ it('throws GSDError with Validation classification when no args', async () => {
162
+ await expect(findPhase([], tmpDir)).rejects.toThrow(GSDError);
163
+ try {
164
+ await findPhase([], tmpDir);
165
+ } catch (err) {
166
+ expect((err as GSDError).classification).toBe('validation');
167
+ }
168
+ });
169
+
170
+ it('handles two-digit phase numbers', async () => {
171
+ const result = await findPhase(['10'], tmpDir);
172
+ const data = result.data as Record<string, unknown>;
173
+
174
+ expect(data.found).toBe(true);
175
+ expect(data.phase_number).toBe('10');
176
+ expect(data.phase_name).toBe('read-only-queries');
177
+ });
178
+
179
+ it('includes file stats (research, context)', async () => {
180
+ const result = await findPhase(['9'], tmpDir);
181
+ const data = result.data as Record<string, unknown>;
182
+
183
+ expect(data.has_research).toBe(true);
184
+ expect(data.has_context).toBe(true);
185
+ });
186
+
187
+ it('computes incomplete plans', async () => {
188
+ const result = await findPhase(['9'], tmpDir);
189
+ const data = result.data as Record<string, unknown>;
190
+ const incompletePlans = data.incomplete_plans as string[];
191
+
192
+ expect(incompletePlans.length).toBe(1);
193
+ expect(incompletePlans[0]).toBe('09-03-PLAN.md');
194
+ });
195
+
196
+ it('searches archived milestone phases', async () => {
197
+ // Create archived milestone directory
198
+ const archiveDir = join(tmpDir, '.planning', 'milestones', 'v1.0-phases', '01-setup');
199
+ await mkdir(archiveDir, { recursive: true });
200
+ await writeFile(join(archiveDir, '01-01-PLAN.md'), '---\nphase: 01\nplan: 01\n---\nPlan');
201
+ await writeFile(join(archiveDir, '01-01-SUMMARY.md'), 'Summary');
202
+
203
+ const result = await findPhase(['1'], tmpDir);
204
+ const data = result.data as Record<string, unknown>;
205
+
206
+ expect(data.found).toBe(true);
207
+ expect(data.archived).toBe('v1.0');
208
+ });
209
+ });
210
+
211
+ // ─── phasePlanIndex ────────────────────────────────────────────────────────
212
+
213
+ describe('phasePlanIndex', () => {
214
+ it('returns plan metadata for phase', async () => {
215
+ const result = await phasePlanIndex(['9'], tmpDir);
216
+ const data = result.data as Record<string, unknown>;
217
+
218
+ expect(data.phase).toBe('09');
219
+ const plans = data.plans as Array<Record<string, unknown>>;
220
+ expect(plans.length).toBe(3);
221
+ });
222
+
223
+ it('includes plan details (id, wave, autonomous, objective, task_count)', async () => {
224
+ const result = await phasePlanIndex(['9'], tmpDir);
225
+ const data = result.data as Record<string, unknown>;
226
+ const plans = data.plans as Array<Record<string, unknown>>;
227
+
228
+ const plan1 = plans.find(p => p.id === '09-01');
229
+ expect(plan1).toBeDefined();
230
+ expect(plan1!.wave).toBe(1);
231
+ expect(plan1!.autonomous).toBe(true);
232
+ expect(plan1!.objective).toBe('Build error classification system.');
233
+ expect(plan1!.task_count).toBe(2);
234
+ expect(plan1!.has_summary).toBe(true);
235
+ });
236
+
237
+ it('correctly counts XML task tags', async () => {
238
+ const result = await phasePlanIndex(['9'], tmpDir);
239
+ const data = result.data as Record<string, unknown>;
240
+ const plans = data.plans as Array<Record<string, unknown>>;
241
+
242
+ const plan1 = plans.find(p => p.id === '09-01');
243
+ expect(plan1!.task_count).toBe(2);
244
+
245
+ const plan2 = plans.find(p => p.id === '09-02');
246
+ expect(plan2!.task_count).toBe(2);
247
+
248
+ const plan3 = plans.find(p => p.id === '09-03');
249
+ expect(plan3!.task_count).toBe(1);
250
+ });
251
+
252
+ it('groups plans by wave', async () => {
253
+ const result = await phasePlanIndex(['9'], tmpDir);
254
+ const data = result.data as Record<string, unknown>;
255
+ const waves = data.waves as Record<string, string[]>;
256
+
257
+ expect(waves['1']).toContain('09-01');
258
+ expect(waves['1']).toContain('09-02');
259
+ expect(waves['2']).toContain('09-03');
260
+ });
261
+
262
+ it('identifies incomplete plans', async () => {
263
+ const result = await phasePlanIndex(['9'], tmpDir);
264
+ const data = result.data as Record<string, unknown>;
265
+ const incomplete = data.incomplete as string[];
266
+
267
+ expect(incomplete).toContain('09-03');
268
+ expect(incomplete).not.toContain('09-01');
269
+ });
270
+
271
+ it('detects has_checkpoints from non-autonomous plans', async () => {
272
+ const result = await phasePlanIndex(['9'], tmpDir);
273
+ const data = result.data as Record<string, unknown>;
274
+
275
+ // Plan 02 has autonomous: false
276
+ expect(data.has_checkpoints).toBe(true);
277
+ });
278
+
279
+ it('parses files_modified from frontmatter', async () => {
280
+ const result = await phasePlanIndex(['9'], tmpDir);
281
+ const data = result.data as Record<string, unknown>;
282
+ const plans = data.plans as Array<Record<string, unknown>>;
283
+
284
+ const plan1 = plans.find(p => p.id === '09-01');
285
+ const filesModified = plan1!.files_modified as string[];
286
+
287
+ expect(filesModified).toContain('sdk/src/errors.ts');
288
+ expect(filesModified).toContain('sdk/src/errors.test.ts');
289
+ });
290
+
291
+ it('throws GSDError with Validation classification when no args', async () => {
292
+ await expect(phasePlanIndex([], tmpDir)).rejects.toThrow(GSDError);
293
+ try {
294
+ await phasePlanIndex([], tmpDir);
295
+ } catch (err) {
296
+ expect((err as GSDError).classification).toBe('validation');
297
+ }
298
+ });
299
+
300
+ it('returns error for nonexistent phase', async () => {
301
+ const result = await phasePlanIndex(['99'], tmpDir);
302
+ const data = result.data as Record<string, unknown>;
303
+
304
+ expect(data.error).toBe('Phase not found');
305
+ expect(data.plans).toEqual([]);
306
+ });
307
+ });
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Phase finding and plan index query handlers.
3
+ *
4
+ * Ported from get-shit-done/bin/lib/phase.cjs and core.cjs.
5
+ * Provides find-phase (directory lookup with archived fallback)
6
+ * and phase-plan-index (plan metadata with wave grouping).
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { findPhase, phasePlanIndex } from './phase.js';
11
+ *
12
+ * const found = await findPhase(['9'], '/project');
13
+ * // { data: { found: true, directory: '.planning/phases/09-foundation', ... } }
14
+ *
15
+ * const index = await phasePlanIndex(['9'], '/project');
16
+ * // { data: { phase: '09', plans: [...], waves: { '1': [...] }, ... } }
17
+ * ```
18
+ */
19
+
20
+ import { readFile, readdir } from 'node:fs/promises';
21
+ import { join } from 'node:path';
22
+ import { GSDError, ErrorClassification } from '../errors.js';
23
+ import { extractFrontmatter } from './frontmatter.js';
24
+ import {
25
+ normalizePhaseName,
26
+ comparePhaseNum,
27
+ phaseTokenMatches,
28
+ toPosixPath,
29
+ planningPaths,
30
+ } from './helpers.js';
31
+ import type { QueryHandler } from './utils.js';
32
+
33
+ // ─── Types ─────────────────────────────────────────────────────────────────
34
+
35
+ interface PhaseInfo {
36
+ found: boolean;
37
+ directory: string | null;
38
+ phase_number: string | null;
39
+ phase_name: string | null;
40
+ phase_slug: string | null;
41
+ plans: string[];
42
+ summaries: string[];
43
+ incomplete_plans: string[];
44
+ has_research: boolean;
45
+ has_context: boolean;
46
+ has_verification: boolean;
47
+ has_reviews: boolean;
48
+ archived?: string;
49
+ }
50
+
51
+ // ─── Internal helpers ──────────────────────────────────────────────────────
52
+
53
+ /**
54
+ * Get file stats for a phase directory.
55
+ *
56
+ * Port of getPhaseFileStats from core.cjs lines 1461-1471.
57
+ */
58
+ async function getPhaseFileStats(phaseDir: string): Promise<{
59
+ plans: string[];
60
+ summaries: string[];
61
+ hasResearch: boolean;
62
+ hasContext: boolean;
63
+ hasVerification: boolean;
64
+ hasReviews: boolean;
65
+ }> {
66
+ const files = await readdir(phaseDir);
67
+ return {
68
+ plans: files.filter(f => f.endsWith('-PLAN.md') || f === 'PLAN.md'),
69
+ summaries: files.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md'),
70
+ hasResearch: files.some(f => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md'),
71
+ hasContext: files.some(f => f.endsWith('-CONTEXT.md') || f === 'CONTEXT.md'),
72
+ hasVerification: files.some(f => f.endsWith('-VERIFICATION.md') || f === 'VERIFICATION.md'),
73
+ hasReviews: files.some(f => f.endsWith('-REVIEWS.md') || f === 'REVIEWS.md'),
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Search for a phase directory matching the normalized name.
79
+ *
80
+ * Port of searchPhaseInDir from core.cjs lines 956-1000.
81
+ */
82
+ async function searchPhaseInDir(baseDir: string, relBase: string, normalized: string): Promise<PhaseInfo | null> {
83
+ try {
84
+ const entries = await readdir(baseDir, { withFileTypes: true });
85
+ const dirs = entries
86
+ .filter(e => e.isDirectory())
87
+ .map(e => e.name)
88
+ .sort((a, b) => comparePhaseNum(a, b));
89
+
90
+ const match = dirs.find(d => phaseTokenMatches(d, normalized));
91
+ if (!match) return null;
92
+
93
+ // Extract phase number and name
94
+ const dirMatch = match.match(/^(?:[A-Z]{1,6}-)(\d+[A-Z]?(?:\.\d+)*)-?(.*)/i)
95
+ || match.match(/^(\d+[A-Z]?(?:\.\d+)*)-?(.*)/i)
96
+ || match.match(/^([A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*)-(.+)/i)
97
+ || [null, match, null];
98
+ const phaseNumber = dirMatch ? dirMatch[1] : normalized;
99
+ const phaseName = dirMatch && dirMatch[2] ? dirMatch[2] : null;
100
+ const phaseDir = join(baseDir, match);
101
+
102
+ const { plans: unsortedPlans, summaries: unsortedSummaries, hasResearch, hasContext, hasVerification, hasReviews } = await getPhaseFileStats(phaseDir);
103
+ const plans = unsortedPlans.sort();
104
+ const summaries = unsortedSummaries.sort();
105
+
106
+ const completedPlanIds = new Set(
107
+ summaries.map(s => s.replace('-SUMMARY.md', '').replace('SUMMARY.md', ''))
108
+ );
109
+ const incompletePlans = plans.filter(p => {
110
+ const planId = p.replace('-PLAN.md', '').replace('PLAN.md', '');
111
+ return !completedPlanIds.has(planId);
112
+ });
113
+
114
+ return {
115
+ found: true,
116
+ directory: toPosixPath(join(relBase, match)),
117
+ phase_number: phaseNumber,
118
+ phase_name: phaseName,
119
+ phase_slug: phaseName ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') : null,
120
+ plans,
121
+ summaries,
122
+ incomplete_plans: incompletePlans,
123
+ has_research: hasResearch,
124
+ has_context: hasContext,
125
+ has_verification: hasVerification,
126
+ has_reviews: hasReviews,
127
+ };
128
+ } catch {
129
+ return null;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Extract objective text from plan content.
135
+ */
136
+ function extractObjective(content: string): string | null {
137
+ const m = content.match(/<objective>\s*\n?\s*(.+)/);
138
+ return m ? m[1].trim() : null;
139
+ }
140
+
141
+ // ─── Exported handlers ─────────────────────────────────────────────────────
142
+
143
+ /**
144
+ * Query handler for find-phase.
145
+ *
146
+ * Locates a phase directory by number/identifier, searching current phases
147
+ * first, then archived milestone phases.
148
+ *
149
+ * Port of cmdFindPhase from phase.cjs lines 152-196, combined with
150
+ * findPhaseInternal from core.cjs lines 1002-1038.
151
+ *
152
+ * @param args - args[0] is the phase identifier (required)
153
+ * @param projectDir - Project root directory
154
+ * @returns QueryResult with PhaseInfo
155
+ * @throws GSDError with Validation classification if phase identifier missing
156
+ */
157
+ export const findPhase: QueryHandler = async (args, projectDir) => {
158
+ const phase = args[0];
159
+ if (!phase) {
160
+ throw new GSDError('phase identifier required', ErrorClassification.Validation);
161
+ }
162
+
163
+ const phasesDir = planningPaths(projectDir).phases;
164
+ const normalized = normalizePhaseName(phase);
165
+
166
+ const notFound: PhaseInfo = {
167
+ found: false,
168
+ directory: null,
169
+ phase_number: null,
170
+ phase_name: null,
171
+ phase_slug: null,
172
+ plans: [],
173
+ summaries: [],
174
+ incomplete_plans: [],
175
+ has_research: false,
176
+ has_context: false,
177
+ has_verification: false,
178
+ has_reviews: false,
179
+ };
180
+
181
+ // Search current phases first
182
+ const relPhasesDir = '.planning/phases';
183
+ const current = await searchPhaseInDir(phasesDir, relPhasesDir, normalized);
184
+ if (current) return { data: current };
185
+
186
+ // Search archived milestone phases (newest first)
187
+ const milestonesDir = join(projectDir, '.planning', 'milestones');
188
+ try {
189
+ const milestoneEntries = await readdir(milestonesDir, { withFileTypes: true });
190
+ const archiveDirs = milestoneEntries
191
+ .filter(e => e.isDirectory() && /^v[\d.]+-phases$/.test(e.name))
192
+ .map(e => e.name)
193
+ .sort()
194
+ .reverse();
195
+
196
+ for (const archiveName of archiveDirs) {
197
+ const versionMatch = archiveName.match(/^(v[\d.]+)-phases$/);
198
+ const version = versionMatch ? versionMatch[1] : archiveName;
199
+ const archivePath = join(milestonesDir, archiveName);
200
+ const relBase = '.planning/milestones/' + archiveName;
201
+ const result = await searchPhaseInDir(archivePath, relBase, normalized);
202
+ if (result) {
203
+ result.archived = version;
204
+ return { data: result };
205
+ }
206
+ }
207
+ } catch { /* milestones dir doesn't exist */ }
208
+
209
+ return { data: notFound };
210
+ };
211
+
212
+ /**
213
+ * Query handler for phase-plan-index.
214
+ *
215
+ * Returns plan metadata with wave grouping for a specific phase.
216
+ *
217
+ * Port of cmdPhasePlanIndex from phase.cjs lines 203-310.
218
+ *
219
+ * @param args - args[0] is the phase identifier (required)
220
+ * @param projectDir - Project root directory
221
+ * @returns QueryResult with { phase, plans[], waves{}, incomplete[], has_checkpoints }
222
+ * @throws GSDError with Validation classification if phase identifier missing
223
+ */
224
+ export const phasePlanIndex: QueryHandler = async (args, projectDir) => {
225
+ const phase = args[0];
226
+ if (!phase) {
227
+ throw new GSDError('phase required for phase-plan-index', ErrorClassification.Validation);
228
+ }
229
+
230
+ const phasesDir = planningPaths(projectDir).phases;
231
+ const normalized = normalizePhaseName(phase);
232
+
233
+ // Find phase directory
234
+ let phaseDir: string | null = null;
235
+ try {
236
+ const entries = await readdir(phasesDir, { withFileTypes: true });
237
+ const dirs = entries
238
+ .filter(e => e.isDirectory())
239
+ .map(e => e.name)
240
+ .sort((a, b) => comparePhaseNum(a, b));
241
+ const match = dirs.find(d => phaseTokenMatches(d, normalized));
242
+ if (match) {
243
+ phaseDir = join(phasesDir, match);
244
+ }
245
+ } catch { /* phases dir doesn't exist */ }
246
+
247
+ if (!phaseDir) {
248
+ return {
249
+ data: {
250
+ phase: normalized,
251
+ error: 'Phase not found',
252
+ plans: [],
253
+ waves: {},
254
+ incomplete: [],
255
+ has_checkpoints: false,
256
+ },
257
+ };
258
+ }
259
+
260
+ // Get all files in phase directory
261
+ const phaseFiles = await readdir(phaseDir);
262
+ const planFiles = phaseFiles.filter(f => f.endsWith('-PLAN.md') || f === 'PLAN.md').sort();
263
+ const summaryFiles = phaseFiles.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md');
264
+
265
+ // Build set of plan IDs with summaries
266
+ const completedPlanIds = new Set(
267
+ summaryFiles.map(s => s.replace('-SUMMARY.md', '').replace('SUMMARY.md', ''))
268
+ );
269
+
270
+ const plans: Array<Record<string, unknown>> = [];
271
+ const waves: Record<string, string[]> = {};
272
+ const incomplete: string[] = [];
273
+ let hasCheckpoints = false;
274
+
275
+ for (const planFile of planFiles) {
276
+ const planId = planFile.replace('-PLAN.md', '').replace('PLAN.md', '');
277
+ const planPath = join(phaseDir, planFile);
278
+ const content = await readFile(planPath, 'utf-8');
279
+ const fm = extractFrontmatter(content);
280
+
281
+ // Count tasks: XML <task> tags (canonical) or ## Task N markdown (legacy)
282
+ const xmlTasks = content.match(/<task[\s>]/gi) || [];
283
+ const mdTasks = content.match(/##\s*Task\s*\d+/gi) || [];
284
+ const taskCount = xmlTasks.length || mdTasks.length;
285
+
286
+ // Parse wave as integer
287
+ const wave = parseInt(String(fm.wave), 10) || 1;
288
+
289
+ // Parse autonomous (default true if not specified)
290
+ let autonomous = true;
291
+ if (fm.autonomous !== undefined) {
292
+ autonomous = fm.autonomous === 'true' || fm.autonomous === true;
293
+ }
294
+
295
+ if (!autonomous) {
296
+ hasCheckpoints = true;
297
+ }
298
+
299
+ // Parse files_modified
300
+ let filesModified: string[] = [];
301
+ const fmFiles = (fm['files_modified'] || fm['files-modified']) as string | string[] | undefined;
302
+ if (fmFiles) {
303
+ filesModified = Array.isArray(fmFiles) ? fmFiles : [fmFiles];
304
+ }
305
+
306
+ const hasSummary = completedPlanIds.has(planId);
307
+ if (!hasSummary) {
308
+ incomplete.push(planId);
309
+ }
310
+
311
+ const plan = {
312
+ id: planId,
313
+ wave,
314
+ autonomous,
315
+ objective: extractObjective(content) || (fm.objective as string) || null,
316
+ files_modified: filesModified,
317
+ task_count: taskCount,
318
+ has_summary: hasSummary,
319
+ };
320
+
321
+ plans.push(plan);
322
+
323
+ // Group by wave
324
+ const waveKey = String(wave);
325
+ if (!waves[waveKey]) {
326
+ waves[waveKey] = [];
327
+ }
328
+ waves[waveKey].push(planId);
329
+ }
330
+
331
+ return {
332
+ data: {
333
+ phase: normalized,
334
+ plans,
335
+ waves,
336
+ incomplete,
337
+ has_checkpoints: hasCheckpoints,
338
+ },
339
+ };
340
+ };