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,337 @@
1
+ /**
2
+ * Profile and learnings query handlers — session scanning, questionnaire,
3
+ * profile generation, and knowledge store management.
4
+ *
5
+ * Ported from get-shit-done/bin/lib/profile-pipeline.cjs, profile-output.cjs,
6
+ * and learnings.cjs.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { scanSessions, profileQuestionnaire } from './profile.js';
11
+ *
12
+ * await scanSessions([], '/project');
13
+ * // { data: { projects: [...], project_count: 5, session_count: 42 } }
14
+ *
15
+ * await profileQuestionnaire([], '/project');
16
+ * // { data: { mode: 'interactive', questions: [...] } } — same shape as gsd-tools.cjs
17
+ * ```
18
+ */
19
+
20
+ import { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from 'node:fs';
21
+ import { join, basename, resolve } from 'node:path';
22
+ import { homedir } from 'node:os';
23
+ import { createHash, randomBytes } from 'node:crypto';
24
+
25
+ import { planningPaths } from './helpers.js';
26
+ import { GSDError, ErrorClassification } from '../errors.js';
27
+ import type { QueryHandler } from './utils.js';
28
+ import { buildScanSessionsProjects, getScanSessionsRoot } from './profile-scan-sessions.js';
29
+ import { runExtractMessages } from './profile-extract-messages.js';
30
+ import { runProfileSample } from './profile-sample.js';
31
+ import {
32
+ PROFILING_QUESTIONS,
33
+ generateClaudeInstruction,
34
+ isAmbiguousAnswer,
35
+ } from './profile-questionnaire-data.js';
36
+
37
+ // ─── Learnings — ~/.gsd/knowledge/ knowledge store ───────────────────────
38
+
39
+ const STORE_DIR = join(homedir(), '.gsd', 'knowledge');
40
+
41
+ function ensureStore(): void {
42
+ if (!existsSync(STORE_DIR)) mkdirSync(STORE_DIR, { recursive: true });
43
+ }
44
+
45
+ function learningsWrite(entry: { source_project: string; learning: string; context?: string; tags?: string[] }): { created: boolean; id: string } {
46
+ ensureStore();
47
+ const hash = createHash('sha256').update(entry.learning + '\n' + entry.source_project).digest('hex');
48
+ for (const file of readdirSync(STORE_DIR).filter(f => f.endsWith('.json'))) {
49
+ try {
50
+ const r = JSON.parse(readFileSync(join(STORE_DIR, file), 'utf-8'));
51
+ if (r.content_hash === hash) return { created: false, id: r.id };
52
+ } catch { /* skip */ }
53
+ }
54
+ const id = `${Date.now().toString(36)}-${randomBytes(4).toString('hex')}`;
55
+ const record = { id, source_project: entry.source_project, date: new Date().toISOString(), context: entry.context ?? '', learning: entry.learning, tags: entry.tags ?? [], content_hash: hash };
56
+ writeFileSync(join(STORE_DIR, `${id}.json`), JSON.stringify(record, null, 2), 'utf-8');
57
+ return { created: true, id };
58
+ }
59
+
60
+ function learningsList(): Array<Record<string, unknown>> {
61
+ if (!existsSync(STORE_DIR)) return [];
62
+ const results: Array<Record<string, unknown>> = [];
63
+ for (const file of readdirSync(STORE_DIR).filter(f => f.endsWith('.json'))) {
64
+ try {
65
+ const record = JSON.parse(readFileSync(join(STORE_DIR, file), 'utf-8'));
66
+ results.push(record);
67
+ } catch { /* skip */ }
68
+ }
69
+ results.sort((a, b) => new Date(b.date as string).getTime() - new Date(a.date as string).getTime());
70
+ return results;
71
+ }
72
+
73
+ /**
74
+ * List all entries in the global learnings store (`~/.gsd/knowledge/`).
75
+ *
76
+ * Port of `cmdLearningsList` from learnings.cjs.
77
+ */
78
+ export const learningsListHandler: QueryHandler = async () => {
79
+ const learnings = learningsList();
80
+ return { data: { learnings, count: learnings.length } };
81
+ };
82
+
83
+ /**
84
+ * Query learnings from the global knowledge store, optionally filtered by tag.
85
+ *
86
+ * Port of `cmdLearningsQuery` from learnings.cjs lines 316-323.
87
+ * Called by gsd-planner agent to inject prior learnings into plan generation.
88
+ *
89
+ * Args: --tag <tag> [--limit N]
90
+ */
91
+ export const learningsQuery: QueryHandler = async (args) => {
92
+ const tagIdx = args.indexOf('--tag');
93
+ const tag = tagIdx !== -1 ? args[tagIdx + 1] : null;
94
+ const limitIdx = args.indexOf('--limit');
95
+ const limit = limitIdx !== -1 ? parseInt(args[limitIdx + 1], 10) : undefined;
96
+
97
+ let results = learningsList();
98
+ if (tag) {
99
+ results = results.filter(r => Array.isArray(r.tags) && (r.tags as string[]).includes(tag));
100
+ }
101
+ if (limit && limit > 0) {
102
+ results = results.slice(0, limit);
103
+ }
104
+ return { data: { learnings: results, count: results.length, tag } };
105
+ };
106
+
107
+ export const learningsCopy: QueryHandler = async (_args, projectDir) => {
108
+ const paths = planningPaths(projectDir);
109
+ const learningsPath = join(paths.planning, 'LEARNINGS.md');
110
+ if (!existsSync(learningsPath)) {
111
+ return { data: { copied: false, total: 0, created: 0, skipped: 0, reason: 'No LEARNINGS.md found' } };
112
+ }
113
+ const content = readFileSync(learningsPath, 'utf-8');
114
+ const sourceProject = basename(resolve(projectDir));
115
+ const sections = content.split(/^## /m).slice(1);
116
+ let created = 0; let skipped = 0;
117
+
118
+ for (const section of sections) {
119
+ const lines = section.trim().split('\n');
120
+ const title = lines[0].trim();
121
+ const body = lines.slice(1).join('\n').trim();
122
+ if (!body) continue;
123
+ const tags = title.toLowerCase().split(/\s+/).filter(w => w.length > 2);
124
+ const result = learningsWrite({ source_project: sourceProject, learning: body, context: title, tags });
125
+ if (result.created) created++; else skipped++;
126
+ }
127
+ return { data: { copied: true, total: created + skipped, created, skipped } };
128
+ };
129
+
130
+ /**
131
+ * Prune learnings older than duration (e.g. `90d`). Port of `learningsPrune` from learnings.cjs.
132
+ */
133
+ function learningsPruneStore(olderThan: string): { removed: number; kept: number } {
134
+ const match = /^(\d+)d$/.exec(olderThan);
135
+ if (!match) {
136
+ throw new Error(`Invalid duration format: "${olderThan}" — expected format like "90d"`);
137
+ }
138
+ const days = parseInt(match[1], 10);
139
+ const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
140
+ if (!existsSync(STORE_DIR)) return { removed: 0, kept: 0 };
141
+ const files = readdirSync(STORE_DIR).filter(f => f.endsWith('.json'));
142
+ let removed = 0;
143
+ let kept = 0;
144
+ for (const file of files) {
145
+ const filePath = join(STORE_DIR, file);
146
+ let record: Record<string, unknown> | null = null;
147
+ try {
148
+ record = JSON.parse(readFileSync(filePath, 'utf-8')) as Record<string, unknown>;
149
+ } catch {
150
+ continue;
151
+ }
152
+ if (!record?.date) continue;
153
+ const recordDate = new Date(record.date as string);
154
+ if (recordDate < cutoff) {
155
+ unlinkSync(filePath);
156
+ removed++;
157
+ } else {
158
+ kept++;
159
+ }
160
+ }
161
+ return { removed, kept };
162
+ }
163
+
164
+ /** Port of `cmdLearningsPrune`. */
165
+ export const learningsPrune: QueryHandler = async (args) => {
166
+ const olderIdx = args.indexOf('--older-than');
167
+ const olderThan = olderIdx !== -1 ? args[olderIdx + 1] : null;
168
+ if (!olderThan) {
169
+ throw new GSDError('Usage: learnings prune --older-than <duration>', ErrorClassification.Validation);
170
+ }
171
+ try {
172
+ return { data: learningsPruneStore(olderThan) };
173
+ } catch (e) {
174
+ const msg = e instanceof Error ? e.message : String(e);
175
+ throw new GSDError(msg, ErrorClassification.Validation);
176
+ }
177
+ };
178
+
179
+ /** Port of `cmdLearningsDelete`. */
180
+ export const learningsDelete: QueryHandler = async (args) => {
181
+ const id = args[0];
182
+ if (!id) {
183
+ throw new GSDError('Usage: learnings delete <id>', ErrorClassification.Validation);
184
+ }
185
+ if (!/^[a-z0-9]+-[a-f0-9]+$/.test(id)) {
186
+ throw new GSDError(`Invalid learning ID: "${id}"`, ErrorClassification.Validation);
187
+ }
188
+ const filePath = join(STORE_DIR, `${id}.json`);
189
+ if (!existsSync(filePath)) {
190
+ return { data: { id, deleted: false } };
191
+ }
192
+ unlinkSync(filePath);
193
+ return { data: { id, deleted: true } };
194
+ };
195
+
196
+ // ─── extractMessages — session message extraction for profiling ───────────
197
+
198
+ /**
199
+ * Extract user messages from Claude Code session files for a given project.
200
+ *
201
+ * Port of `cmdExtractMessages` from profile-pipeline.cjs — JSON matches `gsd-tools extract-messages`
202
+ * (`output_file` JSONL + metadata). Uses `--session` (CJS); `--session-id` is accepted as an alias.
203
+ *
204
+ * @param args - args[0]: project name/keyword (required), `--session <id>`, `--limit N`, `--path <dir>`
205
+ */
206
+ export const extractMessages: QueryHandler = async (args) => {
207
+ const pathIdx = args.indexOf('--path');
208
+ const overridePath = pathIdx !== -1 ? args[pathIdx + 1] : null;
209
+ const sessionIdx =
210
+ args.indexOf('--session') !== -1 ? args.indexOf('--session') : args.indexOf('--session-id');
211
+ const sessionId = sessionIdx !== -1 ? args[sessionIdx + 1]! : null;
212
+ const limitIdx = args.indexOf('--limit');
213
+ const limit = limitIdx !== -1 ? (parseInt(args[limitIdx + 1]!, 10) || null) : null;
214
+ const projectArg = args[0];
215
+ if (!projectArg || projectArg.startsWith('--')) {
216
+ throw new GSDError(
217
+ 'Usage: gsd-tools extract-messages <project> [--session <id>] [--limit N] [--path <dir>]\nRun scan-sessions first to see available projects.',
218
+ ErrorClassification.Validation,
219
+ );
220
+ }
221
+ const data = await runExtractMessages(projectArg, { sessionId, limit }, overridePath ?? null);
222
+ return { data };
223
+ };
224
+
225
+ // ─── Profile — session scanning and profile generation ────────────────────
226
+
227
+ export const scanSessions: QueryHandler = async (args) => {
228
+ const pathIdx = args.indexOf('--path');
229
+ const overridePath = pathIdx !== -1 ? args[pathIdx + 1] : null;
230
+ const verboseFlag = args.includes('--verbose');
231
+
232
+ if (getScanSessionsRoot(overridePath) === null) {
233
+ const searchedPath = overridePath || '~/.claude/projects';
234
+ throw new GSDError(
235
+ `No Claude Code sessions found at ${searchedPath}.${overridePath ? '' : ' Is Claude Code installed?'}`,
236
+ ErrorClassification.Validation,
237
+ );
238
+ }
239
+
240
+ const projects = buildScanSessionsProjects(overridePath, { verbose: verboseFlag });
241
+ return { data: projects };
242
+ };
243
+
244
+ /**
245
+ * Multi-project session sampling for profiling — port of `cmdProfileSample` (`profile-pipeline.cjs`).
246
+ * JSON matches `gsd-tools profile-sample` (`output_file` JSONL + metadata).
247
+ */
248
+ export const profileSample: QueryHandler = async (args) => {
249
+ const pathIdx = args.indexOf('--path');
250
+ const overridePath = pathIdx !== -1 ? args[pathIdx + 1] : null;
251
+ const limitIdx = args.indexOf('--limit');
252
+ const limit = limitIdx !== -1 ? parseInt(args[limitIdx + 1]!, 10) : 150;
253
+ const maxPerIdx = args.indexOf('--max-per-project');
254
+ const maxPerProject = maxPerIdx !== -1 ? parseInt(args[maxPerIdx + 1]!, 10) : null;
255
+ const maxCharsIdx = args.indexOf('--max-chars');
256
+ const maxChars = maxCharsIdx !== -1 ? parseInt(args[maxCharsIdx + 1]!, 10) : 500;
257
+ const data = await runProfileSample(overridePath ?? null, {
258
+ limit,
259
+ maxPerProject,
260
+ maxChars,
261
+ });
262
+ return { data };
263
+ };
264
+
265
+ /**
266
+ * Profile questionnaire — port of `cmdProfileQuestionnaire` from profile-output.cjs.
267
+ * Interactive: `{ mode: 'interactive', questions }` (options omit `rating`).
268
+ * With `--answers a,b,c,...` (8 comma-separated values, order matches questions): full analysis object (includes volatile `analyzed_at`).
269
+ */
270
+ export const profileQuestionnaire: QueryHandler = async (args, _projectDir) => {
271
+ const answersIdx = args.indexOf('--answers');
272
+ const answersStr = answersIdx !== -1 ? args[answersIdx + 1] : null;
273
+
274
+ if (!answersStr) {
275
+ const questionsOutput = {
276
+ mode: 'interactive' as const,
277
+ questions: PROFILING_QUESTIONS.map((q) => ({
278
+ dimension: q.dimension,
279
+ header: q.header,
280
+ context: q.context,
281
+ question: q.question,
282
+ options: q.options.map((o) => ({ label: o.label, value: o.value })),
283
+ })),
284
+ };
285
+ return { data: questionsOutput };
286
+ }
287
+
288
+ const answerValues = answersStr.split(',').map((a) => a.trim());
289
+ if (answerValues.length !== PROFILING_QUESTIONS.length) {
290
+ throw new GSDError(
291
+ `Expected ${PROFILING_QUESTIONS.length} answers (comma-separated), got ${answerValues.length}`,
292
+ ErrorClassification.Validation,
293
+ );
294
+ }
295
+
296
+ const dimensions: Record<string, unknown> = {};
297
+ const analysis: Record<string, unknown> = {
298
+ profile_version: '1.0',
299
+ analyzed_at: new Date().toISOString(),
300
+ data_source: 'questionnaire',
301
+ projects_analyzed: [] as unknown[],
302
+ messages_analyzed: 0,
303
+ message_threshold: 'questionnaire',
304
+ sensitive_excluded: [] as unknown[],
305
+ dimensions,
306
+ };
307
+
308
+ for (let i = 0; i < PROFILING_QUESTIONS.length; i++) {
309
+ const question = PROFILING_QUESTIONS[i]!;
310
+ const answerValue = answerValues[i]!;
311
+ const selectedOption = question.options.find((o) => o.value === answerValue);
312
+ if (!selectedOption) {
313
+ throw new GSDError(
314
+ `Invalid answer "${answerValue}" for ${question.dimension}. Valid values: ${question.options.map((o) => o.value).join(', ')}`,
315
+ ErrorClassification.Validation,
316
+ );
317
+ }
318
+ const ambiguous = isAmbiguousAnswer(question.dimension, answerValue);
319
+ dimensions[question.dimension] = {
320
+ rating: selectedOption.rating,
321
+ confidence: ambiguous ? 'LOW' : 'MEDIUM',
322
+ evidence_count: 1,
323
+ cross_project_consistent: null,
324
+ evidence: [
325
+ {
326
+ signal: 'Self-reported via questionnaire',
327
+ quote: selectedOption.label,
328
+ project: 'N/A (questionnaire)',
329
+ },
330
+ ],
331
+ summary: `Developer self-reported as ${selectedOption.rating} for ${question.header.toLowerCase()}.`,
332
+ claude_instruction: generateClaudeInstruction(question.dimension, selectedOption.rating),
333
+ };
334
+ }
335
+
336
+ return { data: analysis };
337
+ };
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Unit tests for progress query handlers.
3
+ *
4
+ * Tests progressJson and determinePhaseStatus.
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
8
+ import { mkdtemp, writeFile, mkdir, rm } from 'node:fs/promises';
9
+ import { join } from 'node:path';
10
+ import { tmpdir } from 'node:os';
11
+
12
+ import { progressJson, determinePhaseStatus } from './progress.js';
13
+
14
+ // ─── Helpers ──────────────────────────────────────────────────────────────
15
+
16
+ let tmpDir: string;
17
+
18
+ beforeEach(async () => {
19
+ tmpDir = await mkdtemp(join(tmpdir(), 'progress-test-'));
20
+ await mkdir(join(tmpDir, '.planning', 'phases'), { recursive: true });
21
+ });
22
+
23
+ afterEach(async () => {
24
+ await rm(tmpDir, { recursive: true, force: true });
25
+ });
26
+
27
+ // ─── determinePhaseStatus ─────────────────────────────────────────────────
28
+
29
+ describe('determinePhaseStatus', () => {
30
+ it('returns Pending when no plans', async () => {
31
+ const phaseDir = join(tmpDir, '.planning', 'phases', '01-test');
32
+ await mkdir(phaseDir, { recursive: true });
33
+ const status = await determinePhaseStatus(0, 0, phaseDir);
34
+ expect(status).toBe('Pending');
35
+ });
36
+
37
+ it('returns Planned when plans but no summaries', async () => {
38
+ const phaseDir = join(tmpDir, '.planning', 'phases', '01-test');
39
+ await mkdir(phaseDir, { recursive: true });
40
+ const status = await determinePhaseStatus(3, 0, phaseDir);
41
+ expect(status).toBe('Planned');
42
+ });
43
+
44
+ it('returns In Progress when some summaries', async () => {
45
+ const phaseDir = join(tmpDir, '.planning', 'phases', '01-test');
46
+ await mkdir(phaseDir, { recursive: true });
47
+ const status = await determinePhaseStatus(3, 1, phaseDir);
48
+ expect(status).toBe('In Progress');
49
+ });
50
+
51
+ it('returns Executed when all summaries but no VERIFICATION.md', async () => {
52
+ const phaseDir = join(tmpDir, '.planning', 'phases', '01-test');
53
+ await mkdir(phaseDir, { recursive: true });
54
+ const status = await determinePhaseStatus(3, 3, phaseDir);
55
+ expect(status).toBe('Executed');
56
+ });
57
+
58
+ it('returns Complete when VERIFICATION.md has status: passed', async () => {
59
+ const phaseDir = join(tmpDir, '.planning', 'phases', '01-test');
60
+ await mkdir(phaseDir, { recursive: true });
61
+ await writeFile(join(phaseDir, 'VERIFICATION.md'), '---\nstatus: passed\n---\n');
62
+ const status = await determinePhaseStatus(3, 3, phaseDir);
63
+ expect(status).toBe('Complete');
64
+ });
65
+
66
+ it('returns Needs Review when VERIFICATION.md has status: human_needed', async () => {
67
+ const phaseDir = join(tmpDir, '.planning', 'phases', '01-test');
68
+ await mkdir(phaseDir, { recursive: true });
69
+ await writeFile(join(phaseDir, 'VERIFICATION.md'), '---\nstatus: human_needed\n---\n');
70
+ const status = await determinePhaseStatus(3, 3, phaseDir);
71
+ expect(status).toBe('Needs Review');
72
+ });
73
+
74
+ it('returns Executed when VERIFICATION.md has status: gaps_found', async () => {
75
+ const phaseDir = join(tmpDir, '.planning', 'phases', '01-test');
76
+ await mkdir(phaseDir, { recursive: true });
77
+ await writeFile(join(phaseDir, 'VERIFICATION.md'), '---\nstatus: gaps_found\n---\n');
78
+ const status = await determinePhaseStatus(3, 3, phaseDir);
79
+ expect(status).toBe('Executed');
80
+ });
81
+
82
+ it('returns Executed when VERIFICATION.md has unrecognized status', async () => {
83
+ const phaseDir = join(tmpDir, '.planning', 'phases', '01-test');
84
+ await mkdir(phaseDir, { recursive: true });
85
+ await writeFile(join(phaseDir, 'VERIFICATION.md'), '---\nstatus: unknown\n---\n');
86
+ const status = await determinePhaseStatus(3, 3, phaseDir);
87
+ expect(status).toBe('Executed');
88
+ });
89
+ });
90
+
91
+ // ─── progressJson ─────────────────────────────────────────────────────────
92
+
93
+ describe('progressJson', () => {
94
+ it('returns progress data with phases', async () => {
95
+ // Create ROADMAP.md for milestone info
96
+ await writeFile(join(tmpDir, '.planning', 'ROADMAP.md'), '## v1.0: First Milestone\n');
97
+
98
+ // Create phase directories with plans/summaries
99
+ const phase1 = join(tmpDir, '.planning', 'phases', '01-foundation');
100
+ const phase2 = join(tmpDir, '.planning', 'phases', '02-features');
101
+ await mkdir(phase1, { recursive: true });
102
+ await mkdir(phase2, { recursive: true });
103
+
104
+ await writeFile(join(phase1, '01-01-PLAN.md'), '');
105
+ await writeFile(join(phase1, '01-01-SUMMARY.md'), '');
106
+ await writeFile(join(phase2, '02-01-PLAN.md'), '');
107
+
108
+ const result = await progressJson([], tmpDir);
109
+ const data = result.data as Record<string, unknown>;
110
+
111
+ expect(data.milestone_version).toBe('v1.0');
112
+ expect(data.milestone_name).toBe('First Milestone');
113
+ expect(data.total_plans).toBe(2);
114
+ expect(data.total_summaries).toBe(1);
115
+ expect(data.percent).toBe(50);
116
+
117
+ const phases = data.phases as Array<Record<string, unknown>>;
118
+ expect(phases.length).toBe(2);
119
+
120
+ // Phase 1: 1 plan, 1 summary (dir name 01-foundation => number '01')
121
+ expect(phases[0].number).toBe('01');
122
+ expect(phases[0].name).toBe('foundation');
123
+ expect(phases[0].plans).toBe(1);
124
+ expect(phases[0].summaries).toBe(1);
125
+
126
+ // Phase 2: 1 plan, 0 summaries (dir name 02-features => number '02')
127
+ expect(phases[1].number).toBe('02');
128
+ expect(phases[1].plans).toBe(1);
129
+ expect(phases[1].summaries).toBe(0);
130
+ expect(phases[1].status).toBe('Planned');
131
+ });
132
+
133
+ it('returns 0 percent when no plans', async () => {
134
+ await writeFile(join(tmpDir, '.planning', 'ROADMAP.md'), '## v1.0: Milestone\n');
135
+ const result = await progressJson([], tmpDir);
136
+ const data = result.data as Record<string, unknown>;
137
+ expect(data.percent).toBe(0);
138
+ expect(data.total_plans).toBe(0);
139
+ });
140
+
141
+ it('sorts phases by comparePhaseNum order', async () => {
142
+ await writeFile(join(tmpDir, '.planning', 'ROADMAP.md'), '## v1.0: Milestone\n');
143
+
144
+ const phase10 = join(tmpDir, '.planning', 'phases', '10-later');
145
+ const phase2 = join(tmpDir, '.planning', 'phases', '02-early');
146
+ await mkdir(phase10, { recursive: true });
147
+ await mkdir(phase2, { recursive: true });
148
+
149
+ const result = await progressJson([], tmpDir);
150
+ const data = result.data as Record<string, unknown>;
151
+ const phases = data.phases as Array<Record<string, unknown>>;
152
+
153
+ expect(phases[0].number).toBe('02');
154
+ expect(phases[1].number).toBe('10');
155
+ });
156
+ });