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,538 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { mkdtemp, mkdir, writeFile, rm } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { PromptFactory, extractBlock, extractSteps, PHASE_WORKFLOW_MAP } from './phase-prompt.js';
6
+ import { PhaseType } from './types.js';
7
+ import type { ContextFiles, ParsedPlan, PlanFrontmatter } from './types.js';
8
+
9
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
10
+
11
+ async function createTempDir(): Promise<string> {
12
+ return mkdtemp(join(tmpdir(), 'gsd-prompt-'));
13
+ }
14
+
15
+ function makeWorkflowContent(purpose: string, steps: string[]): string {
16
+ const stepBlocks = steps
17
+ .map((s, i) => `<step name="step_${i + 1}">\n${s}\n</step>`)
18
+ .join('\n\n');
19
+ return `<purpose>\n${purpose}\n</purpose>\n\n<process>\n${stepBlocks}\n</process>`;
20
+ }
21
+
22
+ function makeAgentDef(name: string, tools: string, role: string): string {
23
+ return `---\nname: ${name}\ntools: ${tools}\n---\n\n<role>\n${role}\n</role>`;
24
+ }
25
+
26
+ function makeParsedPlan(overrides?: Partial<ParsedPlan>): ParsedPlan {
27
+ return {
28
+ frontmatter: {
29
+ phase: 'execute',
30
+ plan: 'test-plan',
31
+ type: 'feature',
32
+ wave: 1,
33
+ depends_on: [],
34
+ files_modified: [],
35
+ autonomous: true,
36
+ requirements: [],
37
+ must_haves: { truths: [], artifacts: [], key_links: [] },
38
+ } as PlanFrontmatter,
39
+ objective: 'Test objective',
40
+ execution_context: [],
41
+ context_refs: [],
42
+ tasks: [],
43
+ raw: '',
44
+ ...overrides,
45
+ };
46
+ }
47
+
48
+ // ─── extractBlock tests ──────────────────────────────────────────────────────
49
+
50
+ describe('extractBlock', () => {
51
+ it('extracts content from a simple block', () => {
52
+ const content = '<purpose>\nDo the thing.\n</purpose>';
53
+ expect(extractBlock(content, 'purpose')).toBe('Do the thing.');
54
+ });
55
+
56
+ it('extracts content from block with attributes', () => {
57
+ const content = '<step name="init" priority="first">\nLoad context.\n</step>';
58
+ expect(extractBlock(content, 'step')).toBe('Load context.');
59
+ });
60
+
61
+ it('returns empty string for missing block', () => {
62
+ const content = '<purpose>Something</purpose>';
63
+ expect(extractBlock(content, 'role')).toBe('');
64
+ });
65
+
66
+ it('extracts multiline content', () => {
67
+ const content = '<role>\nLine 1\nLine 2\nLine 3\n</role>';
68
+ expect(extractBlock(content, 'role')).toBe('Line 1\nLine 2\nLine 3');
69
+ });
70
+ });
71
+
72
+ describe('extractSteps', () => {
73
+ it('extracts multiple steps from process content', () => {
74
+ const process = `
75
+ <step name="init">Initialize</step>
76
+ <step name="execute">Run tasks</step>
77
+ <step name="verify">Check results</step>`;
78
+
79
+ const steps = extractSteps(process);
80
+ expect(steps).toHaveLength(3);
81
+ expect(steps[0]).toEqual({ name: 'init', content: 'Initialize' });
82
+ expect(steps[1]).toEqual({ name: 'execute', content: 'Run tasks' });
83
+ expect(steps[2]).toEqual({ name: 'verify', content: 'Check results' });
84
+ });
85
+
86
+ it('returns empty array for no steps', () => {
87
+ expect(extractSteps('no steps here')).toEqual([]);
88
+ });
89
+
90
+ it('handles steps with priority attributes', () => {
91
+ const process = '<step name="init" priority="first">\nDo first.\n</step>';
92
+ const steps = extractSteps(process);
93
+ expect(steps).toHaveLength(1);
94
+ expect(steps[0].name).toBe('init');
95
+ expect(steps[0].content).toBe('Do first.');
96
+ });
97
+ });
98
+
99
+ // ─── PromptFactory tests ─────────────────────────────────────────────────────
100
+
101
+ describe('PromptFactory', () => {
102
+ let tempDir: string;
103
+ let workflowsDir: string;
104
+ let agentsDir: string;
105
+
106
+ beforeEach(async () => {
107
+ tempDir = await createTempDir();
108
+ workflowsDir = join(tempDir, 'workflows');
109
+ agentsDir = join(tempDir, 'agents');
110
+ await mkdir(workflowsDir, { recursive: true });
111
+ await mkdir(agentsDir, { recursive: true });
112
+ });
113
+
114
+ afterEach(async () => {
115
+ await rm(tempDir, { recursive: true, force: true });
116
+ });
117
+
118
+ function makeFactory(): PromptFactory {
119
+ // sdkPromptsDir points to a non-existent temp subdir so real sdk/prompts/ files
120
+ // don't interfere — tests control exactly which files exist on disk.
121
+ return new PromptFactory({
122
+ gsdInstallDir: tempDir,
123
+ agentsDir,
124
+ sdkPromptsDir: join(tempDir, 'sdk-prompts-does-not-exist'),
125
+ });
126
+ }
127
+
128
+ describe('buildPrompt', () => {
129
+ it('assembles research prompt with role + purpose + process + context', async () => {
130
+ await writeFile(
131
+ join(workflowsDir, 'research-phase.md'),
132
+ makeWorkflowContent('Research the phase.', ['Gather info', 'Analyze findings']),
133
+ );
134
+ await writeFile(
135
+ join(agentsDir, 'gsd-phase-researcher.md'),
136
+ makeAgentDef('gsd-phase-researcher', 'Read, Grep, Bash', 'You are a researcher.'),
137
+ );
138
+
139
+ const factory = makeFactory();
140
+ const contextFiles: ContextFiles = {
141
+ state: '# State\nproject: test',
142
+ roadmap: '# Roadmap\nphases listed',
143
+ };
144
+
145
+ const prompt = await factory.buildPrompt(PhaseType.Research, null, contextFiles);
146
+
147
+ expect(prompt).toContain('## Role');
148
+ expect(prompt).toContain('You are a researcher.');
149
+ expect(prompt).toContain('## Purpose');
150
+ expect(prompt).toContain('Research the phase.');
151
+ expect(prompt).toContain('## Process');
152
+ expect(prompt).toContain('Gather info');
153
+ expect(prompt).toContain('## Context');
154
+ expect(prompt).toContain('# State');
155
+ expect(prompt).toContain('# Roadmap');
156
+ expect(prompt).toContain('## Phase Instructions');
157
+
158
+ // Cache-friendly ordering (#1614): stable prefix before variable context
159
+ const phaseInstrIdx = prompt.indexOf('## Phase Instructions');
160
+ const contextIdx = prompt.indexOf('## Context');
161
+ expect(phaseInstrIdx).toBeLessThan(contextIdx);
162
+ });
163
+
164
+ it('assembles plan prompt with all context files', async () => {
165
+ await writeFile(
166
+ join(workflowsDir, 'plan-phase.md'),
167
+ makeWorkflowContent('Plan the implementation.', ['Break down tasks']),
168
+ );
169
+ await writeFile(
170
+ join(agentsDir, 'gsd-planner.md'),
171
+ makeAgentDef('gsd-planner', 'Read, Write, Bash', 'You are a planner.'),
172
+ );
173
+
174
+ const factory = makeFactory();
175
+ const contextFiles: ContextFiles = {
176
+ state: '# State',
177
+ roadmap: '# Roadmap',
178
+ context: '# Context',
179
+ research: '# Research',
180
+ requirements: '# Requirements',
181
+ };
182
+
183
+ const prompt = await factory.buildPrompt(PhaseType.Plan, null, contextFiles);
184
+
185
+ expect(prompt).toContain('You are a planner.');
186
+ expect(prompt).toContain('Plan the implementation.');
187
+ expect(prompt).toContain('# State');
188
+ expect(prompt).toContain('# Research');
189
+ expect(prompt).toContain('# Requirements');
190
+ expect(prompt).toContain('executable plans');
191
+ });
192
+
193
+ it('delegates execute phase with plan to buildExecutorPrompt', async () => {
194
+ await writeFile(
195
+ join(agentsDir, 'gsd-executor.md'),
196
+ makeAgentDef('gsd-executor', 'Read, Write, Edit, Bash', 'You are an executor.'),
197
+ );
198
+
199
+ const factory = makeFactory();
200
+ const plan = makeParsedPlan({ objective: 'Build the auth system' });
201
+ const contextFiles: ContextFiles = { state: '# State' };
202
+
203
+ const prompt = await factory.buildPrompt(PhaseType.Execute, plan, contextFiles);
204
+
205
+ // buildExecutorPrompt produces structured output with ## Objective
206
+ expect(prompt).toContain('## Objective');
207
+ expect(prompt).toContain('Build the auth system');
208
+ expect(prompt).toContain('## Role');
209
+ expect(prompt).toContain('You are an executor.');
210
+ });
211
+
212
+ it('handles execute phase without plan (non-delegation path)', async () => {
213
+ await writeFile(
214
+ join(workflowsDir, 'execute-plan.md'),
215
+ makeWorkflowContent('Execute the plan.', ['Run tasks']),
216
+ );
217
+ await writeFile(
218
+ join(agentsDir, 'gsd-executor.md'),
219
+ makeAgentDef('gsd-executor', 'Read, Write, Edit, Bash', 'You are an executor.'),
220
+ );
221
+
222
+ const factory = makeFactory();
223
+ const contextFiles: ContextFiles = { state: '# State' };
224
+
225
+ const prompt = await factory.buildPrompt(PhaseType.Execute, null, contextFiles);
226
+
227
+ // Falls through to general assembly path
228
+ expect(prompt).toContain('## Role');
229
+ expect(prompt).toContain('You are an executor.');
230
+ expect(prompt).toContain('## Purpose');
231
+ expect(prompt).toContain('Execute the plan.');
232
+ });
233
+
234
+ it('assembles verify prompt with phase instructions', async () => {
235
+ await writeFile(
236
+ join(workflowsDir, 'verify-phase.md'),
237
+ makeWorkflowContent('Verify phase goals.', ['Check artifacts', 'Run tests']),
238
+ );
239
+ await writeFile(
240
+ join(agentsDir, 'gsd-verifier.md'),
241
+ makeAgentDef('gsd-verifier', 'Read, Bash, Grep', 'You are a verifier.'),
242
+ );
243
+
244
+ const factory = makeFactory();
245
+ const contextFiles: ContextFiles = {
246
+ state: '# State',
247
+ roadmap: '# Roadmap',
248
+ requirements: '# Requirements',
249
+ };
250
+
251
+ const prompt = await factory.buildPrompt(PhaseType.Verify, null, contextFiles);
252
+
253
+ expect(prompt).toContain('You are a verifier.');
254
+ expect(prompt).toContain('Verify phase goals.');
255
+ expect(prompt).toContain('goal achievement');
256
+ });
257
+
258
+ it('assembles discuss prompt without agent role (no dedicated agent)', async () => {
259
+ await writeFile(
260
+ join(workflowsDir, 'discuss-phase.md'),
261
+ makeWorkflowContent('Discuss implementation decisions.', ['Identify areas']),
262
+ );
263
+
264
+ const factory = makeFactory();
265
+ const contextFiles: ContextFiles = { state: '# State' };
266
+
267
+ const prompt = await factory.buildPrompt(PhaseType.Discuss, null, contextFiles);
268
+
269
+ // Discuss has no agent, so no Role section
270
+ expect(prompt).not.toContain('## Role');
271
+ expect(prompt).toContain('## Purpose');
272
+ expect(prompt).toContain('Discuss implementation decisions.');
273
+ expect(prompt).toContain('## Phase Instructions');
274
+ expect(prompt).toContain('Extract implementation decisions');
275
+ });
276
+
277
+ it('handles missing workflow file gracefully', async () => {
278
+ // No workflow files on disk
279
+ await writeFile(
280
+ join(agentsDir, 'gsd-phase-researcher.md'),
281
+ makeAgentDef('gsd-phase-researcher', 'Read, Bash', 'You are a researcher.'),
282
+ );
283
+
284
+ const factory = makeFactory();
285
+ const contextFiles: ContextFiles = { state: '# State' };
286
+
287
+ const prompt = await factory.buildPrompt(PhaseType.Research, null, contextFiles);
288
+
289
+ // Should still produce a prompt with role and context
290
+ expect(prompt).toContain('## Role');
291
+ expect(prompt).toContain('## Context');
292
+ expect(prompt).not.toContain('## Purpose');
293
+ });
294
+
295
+ it('handles missing agent def gracefully', async () => {
296
+ await writeFile(
297
+ join(workflowsDir, 'research-phase.md'),
298
+ makeWorkflowContent('Research the phase.', ['Gather info']),
299
+ );
300
+ // No agent file on disk
301
+
302
+ const factory = makeFactory();
303
+ const contextFiles: ContextFiles = { state: '# State' };
304
+
305
+ const prompt = await factory.buildPrompt(PhaseType.Research, null, contextFiles);
306
+
307
+ expect(prompt).not.toContain('## Role');
308
+ expect(prompt).toContain('## Purpose');
309
+ expect(prompt).toContain('Research the phase.');
310
+ });
311
+
312
+ it('omits empty context section when no files provided', async () => {
313
+ await writeFile(
314
+ join(workflowsDir, 'discuss-phase.md'),
315
+ makeWorkflowContent('Discuss things.', ['Talk']),
316
+ );
317
+
318
+ const factory = makeFactory();
319
+ const contextFiles: ContextFiles = {};
320
+
321
+ const prompt = await factory.buildPrompt(PhaseType.Discuss, null, contextFiles);
322
+
323
+ expect(prompt).not.toContain('## Context');
324
+ });
325
+ });
326
+
327
+ describe('loadWorkflowFile', () => {
328
+ it('loads existing workflow file', async () => {
329
+ await writeFile(
330
+ join(workflowsDir, 'research-phase.md'),
331
+ 'workflow content',
332
+ );
333
+
334
+ const factory = makeFactory();
335
+ const content = await factory.loadWorkflowFile(PhaseType.Research);
336
+ expect(content).toBe('workflow content');
337
+ });
338
+
339
+ it('returns undefined for missing workflow file', async () => {
340
+ const factory = makeFactory();
341
+ const content = await factory.loadWorkflowFile(PhaseType.Research);
342
+ expect(content).toBeUndefined();
343
+ });
344
+ });
345
+
346
+ describe('loadAgentDef', () => {
347
+ it('loads agent def from agents dir', async () => {
348
+ await writeFile(
349
+ join(agentsDir, 'gsd-executor.md'),
350
+ 'agent content',
351
+ );
352
+
353
+ const factory = makeFactory();
354
+ const content = await factory.loadAgentDef(PhaseType.Execute);
355
+ expect(content).toBe('agent content');
356
+ });
357
+
358
+ it('returns undefined for phases with no agent (discuss)', async () => {
359
+ const factory = makeFactory();
360
+ const content = await factory.loadAgentDef(PhaseType.Discuss);
361
+ expect(content).toBeUndefined();
362
+ });
363
+
364
+ it('falls back to project agents dir', async () => {
365
+ const projectAgentsDir = join(tempDir, 'project-agents');
366
+ await mkdir(projectAgentsDir, { recursive: true });
367
+ await writeFile(
368
+ join(projectAgentsDir, 'gsd-executor.md'),
369
+ 'project agent content',
370
+ );
371
+
372
+ const factory = new PromptFactory({
373
+ gsdInstallDir: tempDir,
374
+ agentsDir,
375
+ projectAgentsDir,
376
+ sdkPromptsDir: join(tempDir, 'sdk-prompts-does-not-exist'),
377
+ });
378
+
379
+ const content = await factory.loadAgentDef(PhaseType.Execute);
380
+ expect(content).toBe('project agent content');
381
+ });
382
+
383
+ it('prefers user agents dir over project agents dir', async () => {
384
+ const projectAgentsDir = join(tempDir, 'project-agents');
385
+ await mkdir(projectAgentsDir, { recursive: true });
386
+ await writeFile(join(agentsDir, 'gsd-executor.md'), 'user agent');
387
+ await writeFile(join(projectAgentsDir, 'gsd-executor.md'), 'project agent');
388
+
389
+ const factory = new PromptFactory({
390
+ gsdInstallDir: tempDir,
391
+ agentsDir,
392
+ projectAgentsDir,
393
+ sdkPromptsDir: join(tempDir, 'sdk-prompts-does-not-exist'),
394
+ });
395
+
396
+ const content = await factory.loadAgentDef(PhaseType.Execute);
397
+ expect(content).toBe('user agent');
398
+ });
399
+ });
400
+
401
+ // ─── Headless prompt loading ─────────────────────────────────────────────
402
+
403
+ describe('headless prompt loading', () => {
404
+ it('loadWorkflowFile prefers sdkPromptsDir over GSD-1 workflowsDir', async () => {
405
+ const sdkDir = join(tempDir, 'sdk-prompts');
406
+ await mkdir(join(sdkDir, 'workflows'), { recursive: true });
407
+
408
+ // Write both: GSD-1 original and SDK headless version
409
+ await writeFile(join(workflowsDir, 'research-phase.md'), 'GSD-1 original');
410
+ await writeFile(join(sdkDir, 'workflows', 'research-phase.md'), 'SDK headless version');
411
+
412
+ const factory = new PromptFactory({
413
+ gsdInstallDir: tempDir,
414
+ agentsDir,
415
+ sdkPromptsDir: sdkDir,
416
+ });
417
+
418
+ const content = await factory.loadWorkflowFile(PhaseType.Research);
419
+ expect(content).toBe('SDK headless version');
420
+ });
421
+
422
+ it('loadWorkflowFile falls back to GSD-1 when sdkPromptsDir file missing', async () => {
423
+ const sdkDir = join(tempDir, 'sdk-prompts');
424
+ await mkdir(join(sdkDir, 'workflows'), { recursive: true });
425
+
426
+ // Only GSD-1 original exists, no SDK version
427
+ await writeFile(join(workflowsDir, 'research-phase.md'), 'GSD-1 original');
428
+
429
+ const factory = new PromptFactory({
430
+ gsdInstallDir: tempDir,
431
+ agentsDir,
432
+ sdkPromptsDir: sdkDir,
433
+ });
434
+
435
+ const content = await factory.loadWorkflowFile(PhaseType.Research);
436
+ expect(content).toBe('GSD-1 original');
437
+ });
438
+
439
+ it('loadAgentDef prefers sdkPromptsDir over user agents dir', async () => {
440
+ const sdkDir = join(tempDir, 'sdk-prompts');
441
+ await mkdir(join(sdkDir, 'agents'), { recursive: true });
442
+
443
+ // Write both: user agent and SDK headless agent
444
+ await writeFile(join(agentsDir, 'gsd-executor.md'), 'user agent');
445
+ await writeFile(join(sdkDir, 'agents', 'gsd-executor.md'), 'SDK headless agent');
446
+
447
+ const factory = new PromptFactory({
448
+ gsdInstallDir: tempDir,
449
+ agentsDir,
450
+ sdkPromptsDir: sdkDir,
451
+ });
452
+
453
+ const content = await factory.loadAgentDef(PhaseType.Execute);
454
+ expect(content).toBe('SDK headless agent');
455
+ });
456
+
457
+ it('loadAgentDef falls back to user agents when sdkPromptsDir file missing', async () => {
458
+ const sdkDir = join(tempDir, 'sdk-prompts');
459
+ await mkdir(join(sdkDir, 'agents'), { recursive: true });
460
+
461
+ // Only user agent exists, no SDK version
462
+ await writeFile(join(agentsDir, 'gsd-executor.md'), 'user agent');
463
+
464
+ const factory = new PromptFactory({
465
+ gsdInstallDir: tempDir,
466
+ agentsDir,
467
+ sdkPromptsDir: sdkDir,
468
+ });
469
+
470
+ const content = await factory.loadAgentDef(PhaseType.Execute);
471
+ expect(content).toBe('user agent');
472
+ });
473
+
474
+ it('buildPrompt sanitizes interactive patterns from output', async () => {
475
+ // Use separate lines so non-interactive content survives stripping
476
+ await writeFile(
477
+ join(workflowsDir, 'research-phase.md'),
478
+ makeWorkflowContent('Research the codebase thoroughly.', [
479
+ 'Gather data from the project.\nAskUserQuestion("what?")\nAnalyze findings.',
480
+ 'Run the analysis.\n/gsd:analyze --deep\nDocument results.',
481
+ ]),
482
+ );
483
+ await writeFile(
484
+ join(agentsDir, 'gsd-phase-researcher.md'),
485
+ makeAgentDef('gsd-phase-researcher', 'Read, Bash', 'You are a researcher.\nSTOP and wait for user input.\nBe thorough.'),
486
+ );
487
+
488
+ const factory = makeFactory();
489
+ const contextFiles: ContextFiles = { state: '# State' };
490
+
491
+ const prompt = await factory.buildPrompt(PhaseType.Research, null, contextFiles);
492
+
493
+ // Interactive patterns should be stripped by sanitizePrompt()
494
+ expect(prompt).not.toContain('AskUserQuestion');
495
+ expect(prompt).not.toContain('/gsd:');
496
+ expect(prompt).not.toMatch(/\bSTOP\s+and\s+wait/);
497
+
498
+ // Non-interactive content on separate lines should remain
499
+ expect(prompt).toContain('You are a researcher.');
500
+ expect(prompt).toContain('Be thorough.');
501
+ expect(prompt).toContain('Gather data from the project.');
502
+ expect(prompt).toContain('Analyze findings.');
503
+ });
504
+
505
+ it('buildPrompt with execute+plan sanitizes output from buildExecutorPrompt', async () => {
506
+ await writeFile(
507
+ join(agentsDir, 'gsd-executor.md'),
508
+ makeAgentDef('gsd-executor', 'Read, Write, Edit, Bash', 'You are an executor.\nSTOP and wait for user.\nExecute thoroughly.'),
509
+ );
510
+
511
+ const factory = makeFactory();
512
+ const plan = makeParsedPlan({ objective: 'Build the auth system' });
513
+ const contextFiles: ContextFiles = { state: '# State' };
514
+
515
+ const prompt = await factory.buildPrompt(PhaseType.Execute, plan, contextFiles);
516
+
517
+ // Objective should remain (no interactive pattern on that line)
518
+ expect(prompt).toContain('Build the auth system');
519
+ // The role's STOP directive should be stripped
520
+ expect(prompt).not.toMatch(/\bSTOP\s+and\s+wait/);
521
+ // Non-interactive role content should remain
522
+ expect(prompt).toContain('You are an executor.');
523
+ });
524
+ });
525
+ });
526
+
527
+ describe('PHASE_WORKFLOW_MAP', () => {
528
+ it('maps all phase types to workflow filenames', () => {
529
+ for (const phase of Object.values(PhaseType)) {
530
+ expect(PHASE_WORKFLOW_MAP[phase]).toBeDefined();
531
+ expect(PHASE_WORKFLOW_MAP[phase]).toMatch(/\.md$/);
532
+ }
533
+ });
534
+
535
+ it('execute phase maps to execute-plan.md (not execute-phase.md)', () => {
536
+ expect(PHASE_WORKFLOW_MAP[PhaseType.Execute]).toBe('execute-plan.md');
537
+ });
538
+ });