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,482 @@
1
+ /**
2
+ * Shared query helpers — cross-cutting utility functions used across query modules.
3
+ *
4
+ * Ported from get-shit-done/bin/lib/core.cjs and state.cjs.
5
+ * Provides phase name normalization, path handling, regex escaping,
6
+ * and STATE.md field extraction.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { normalizePhaseName, planningPaths } from './helpers.js';
11
+ *
12
+ * normalizePhaseName('9'); // '09'
13
+ * normalizePhaseName('CK-01'); // '01'
14
+ *
15
+ * const paths = planningPaths('/project');
16
+ * // { planning: '/project/.planning', state: '/project/.planning/STATE.md', ... }
17
+ * ```
18
+ */
19
+
20
+ import { join, dirname, relative, resolve, isAbsolute, normalize } from 'node:path';
21
+ import { realpath } from 'node:fs/promises';
22
+ import { homedir } from 'node:os';
23
+ import { GSDError, ErrorClassification } from '../errors.js';
24
+
25
+ // ─── Runtime-aware agents directory resolution ─────────────────────────────
26
+
27
+ /**
28
+ * Supported GSD runtimes. Kept in sync with `bin/install.js:getGlobalDir()`.
29
+ */
30
+ export const SUPPORTED_RUNTIMES = [
31
+ 'claude', 'opencode', 'kilo', 'gemini', 'codex', 'copilot', 'antigravity',
32
+ 'cursor', 'windsurf', 'augment', 'trae', 'qwen', 'codebuddy', 'cline',
33
+ ] as const;
34
+
35
+ export type Runtime = (typeof SUPPORTED_RUNTIMES)[number];
36
+
37
+ function expandTilde(p: string): string {
38
+ return p.startsWith('~/') || p === '~' ? join(homedir(), p.slice(1)) : p;
39
+ }
40
+
41
+ /**
42
+ * Resolve the per-runtime config directory, mirroring
43
+ * `bin/install.js:getGlobalDir()`. Agents live at `<configDir>/agents`.
44
+ */
45
+ export function getRuntimeConfigDir(runtime: Runtime): string {
46
+ switch (runtime) {
47
+ case 'claude':
48
+ return process.env.CLAUDE_CONFIG_DIR
49
+ ? expandTilde(process.env.CLAUDE_CONFIG_DIR)
50
+ : join(homedir(), '.claude');
51
+ case 'opencode':
52
+ if (process.env.OPENCODE_CONFIG_DIR) return expandTilde(process.env.OPENCODE_CONFIG_DIR);
53
+ if (process.env.OPENCODE_CONFIG) return dirname(expandTilde(process.env.OPENCODE_CONFIG));
54
+ if (process.env.XDG_CONFIG_HOME) return join(expandTilde(process.env.XDG_CONFIG_HOME), 'opencode');
55
+ return join(homedir(), '.config', 'opencode');
56
+ case 'kilo':
57
+ if (process.env.KILO_CONFIG_DIR) return expandTilde(process.env.KILO_CONFIG_DIR);
58
+ if (process.env.KILO_CONFIG) return dirname(expandTilde(process.env.KILO_CONFIG));
59
+ if (process.env.XDG_CONFIG_HOME) return join(expandTilde(process.env.XDG_CONFIG_HOME), 'kilo');
60
+ return join(homedir(), '.config', 'kilo');
61
+ case 'gemini':
62
+ return process.env.GEMINI_CONFIG_DIR ? expandTilde(process.env.GEMINI_CONFIG_DIR) : join(homedir(), '.gemini');
63
+ case 'codex':
64
+ return process.env.CODEX_HOME ? expandTilde(process.env.CODEX_HOME) : join(homedir(), '.codex');
65
+ case 'copilot':
66
+ return process.env.COPILOT_CONFIG_DIR ? expandTilde(process.env.COPILOT_CONFIG_DIR) : join(homedir(), '.copilot');
67
+ case 'antigravity':
68
+ return process.env.ANTIGRAVITY_CONFIG_DIR ? expandTilde(process.env.ANTIGRAVITY_CONFIG_DIR) : join(homedir(), '.gemini', 'antigravity');
69
+ case 'cursor':
70
+ return process.env.CURSOR_CONFIG_DIR ? expandTilde(process.env.CURSOR_CONFIG_DIR) : join(homedir(), '.cursor');
71
+ case 'windsurf':
72
+ return process.env.WINDSURF_CONFIG_DIR ? expandTilde(process.env.WINDSURF_CONFIG_DIR) : join(homedir(), '.codeium', 'windsurf');
73
+ case 'augment':
74
+ return process.env.AUGMENT_CONFIG_DIR ? expandTilde(process.env.AUGMENT_CONFIG_DIR) : join(homedir(), '.augment');
75
+ case 'trae':
76
+ return process.env.TRAE_CONFIG_DIR ? expandTilde(process.env.TRAE_CONFIG_DIR) : join(homedir(), '.trae');
77
+ case 'qwen':
78
+ return process.env.QWEN_CONFIG_DIR ? expandTilde(process.env.QWEN_CONFIG_DIR) : join(homedir(), '.qwen');
79
+ case 'codebuddy':
80
+ return process.env.CODEBUDDY_CONFIG_DIR ? expandTilde(process.env.CODEBUDDY_CONFIG_DIR) : join(homedir(), '.codebuddy');
81
+ case 'cline':
82
+ return process.env.CLINE_CONFIG_DIR ? expandTilde(process.env.CLINE_CONFIG_DIR) : join(homedir(), '.cline');
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Detect the invoking runtime using issue #2402 precedence:
88
+ * 1. `GSD_RUNTIME` env var
89
+ * 2. `config.runtime` field (from `.planning/config.json` when loaded)
90
+ * 3. Fallback to `'claude'`
91
+ *
92
+ * Unknown values fall through to the next tier rather than throwing, so
93
+ * stale env values don't hard-block workflows.
94
+ */
95
+ export function detectRuntime(config?: { runtime?: unknown }): Runtime {
96
+ const envValue = process.env.GSD_RUNTIME;
97
+ if (envValue && (SUPPORTED_RUNTIMES as readonly string[]).includes(envValue)) {
98
+ return envValue as Runtime;
99
+ }
100
+ const configValue = config?.runtime;
101
+ if (typeof configValue === 'string' && (SUPPORTED_RUNTIMES as readonly string[]).includes(configValue)) {
102
+ return configValue as Runtime;
103
+ }
104
+ return 'claude';
105
+ }
106
+
107
+ /**
108
+ * Resolve the GSD agents directory for a given runtime.
109
+ *
110
+ * Precedence:
111
+ * 1. `GSD_AGENTS_DIR` — explicit SDK override (wins over runtime selection)
112
+ * 2. `<getRuntimeConfigDir(runtime)>/agents` — installer-parity default
113
+ *
114
+ * Defaults to Claude when no runtime is passed, matching prior behavior
115
+ * (see `init-runner.ts`, which is Claude-only by design).
116
+ */
117
+ export function resolveAgentsDir(runtime: Runtime = 'claude'): string {
118
+ if (process.env.GSD_AGENTS_DIR) return process.env.GSD_AGENTS_DIR;
119
+ return join(getRuntimeConfigDir(runtime), 'agents');
120
+ }
121
+
122
+ // ─── Types ──────────────────────────────────────────────────────────────────
123
+
124
+ /** Paths to common .planning files. */
125
+ export interface PlanningPaths {
126
+ planning: string;
127
+ state: string;
128
+ roadmap: string;
129
+ project: string;
130
+ config: string;
131
+ phases: string;
132
+ requirements: string;
133
+ }
134
+
135
+ // ─── escapeRegex ────────────────────────────────────────────────────────────
136
+
137
+ /**
138
+ * Escape regex special characters in a string.
139
+ *
140
+ * @param value - String to escape
141
+ * @returns String with regex special characters escaped
142
+ */
143
+ export function escapeRegex(value: string): string {
144
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
145
+ }
146
+
147
+ // ─── normalizePhaseName ─────────────────────────────────────────────────────
148
+
149
+ /**
150
+ * Normalize a phase identifier to a canonical form.
151
+ *
152
+ * Strips optional project code prefix (e.g., 'CK-01' -> '01'),
153
+ * pads numeric part to 2 digits, preserves letter suffix and decimal parts.
154
+ *
155
+ * @param phase - Phase identifier string
156
+ * @returns Normalized phase name
157
+ */
158
+ export function normalizePhaseName(phase: string): string {
159
+ const str = String(phase);
160
+ // Strip optional project_code prefix (e.g., 'CK-01' -> '01')
161
+ const stripped = str.replace(/^[A-Z]{1,6}-(?=\d)/, '');
162
+ // Standard numeric phases: 1, 01, 12A, 12.1
163
+ const match = stripped.match(/^(\d+)([A-Z])?((?:\.\d+)*)/i);
164
+ if (match) {
165
+ const padded = match[1].padStart(2, '0');
166
+ const letter = match[2] ? match[2].toUpperCase() : '';
167
+ const decimal = match[3] || '';
168
+ return padded + letter + decimal;
169
+ }
170
+ // Custom phase IDs (e.g. PROJ-42, AUTH-101): return as-is
171
+ return str;
172
+ }
173
+
174
+ // ─── comparePhaseNum ────────────────────────────────────────────────────────
175
+
176
+ /**
177
+ * Compare two phase directory names for sorting.
178
+ *
179
+ * Handles numeric, letter-suffixed, and decimal phases.
180
+ * Falls back to string comparison for custom IDs.
181
+ *
182
+ * @param a - First phase directory name
183
+ * @param b - Second phase directory name
184
+ * @returns Negative if a < b, positive if a > b, 0 if equal
185
+ */
186
+ export function comparePhaseNum(a: string, b: string): number {
187
+ // Strip optional project_code prefix before comparing
188
+ const sa = String(a).replace(/^[A-Z]{1,6}-/, '');
189
+ const sb = String(b).replace(/^[A-Z]{1,6}-/, '');
190
+ const pa = sa.match(/^(\d+)([A-Z])?((?:\.\d+)*)/i);
191
+ const pb = sb.match(/^(\d+)([A-Z])?((?:\.\d+)*)/i);
192
+ // If either is non-numeric (custom ID), fall back to string comparison
193
+ if (!pa || !pb) return String(a).localeCompare(String(b));
194
+ const intDiff = parseInt(pa[1], 10) - parseInt(pb[1], 10);
195
+ if (intDiff !== 0) return intDiff;
196
+ // No letter sorts before letter: 12 < 12A < 12B
197
+ const la = (pa[2] || '').toUpperCase();
198
+ const lb = (pb[2] || '').toUpperCase();
199
+ if (la !== lb) {
200
+ if (!la) return -1;
201
+ if (!lb) return 1;
202
+ return la < lb ? -1 : 1;
203
+ }
204
+ // Segment-by-segment decimal comparison: 12A < 12A.1 < 12A.1.2 < 12A.2
205
+ const aDecParts = pa[3] ? pa[3].slice(1).split('.').map(p => parseInt(p, 10)) : [];
206
+ const bDecParts = pb[3] ? pb[3].slice(1).split('.').map(p => parseInt(p, 10)) : [];
207
+ const maxLen = Math.max(aDecParts.length, bDecParts.length);
208
+ if (aDecParts.length === 0 && bDecParts.length > 0) return -1;
209
+ if (bDecParts.length === 0 && aDecParts.length > 0) return 1;
210
+ for (let i = 0; i < maxLen; i++) {
211
+ const av = Number.isFinite(aDecParts[i]) ? aDecParts[i] : 0;
212
+ const bv = Number.isFinite(bDecParts[i]) ? bDecParts[i] : 0;
213
+ if (av !== bv) return av - bv;
214
+ }
215
+ return 0;
216
+ }
217
+
218
+ // ─── extractPhaseToken ──────────────────────────────────────────────────────
219
+
220
+ /**
221
+ * Extract the phase token from a directory name.
222
+ *
223
+ * Supports: '01-name', '1009A-name', '999.6-name', 'CK-01-name', 'PROJ-42-name'.
224
+ *
225
+ * @param dirName - Directory name to extract token from
226
+ * @returns The token portion (e.g. '01', '1009A', '999.6', 'PROJ-42')
227
+ */
228
+ export function extractPhaseToken(dirName: string): string {
229
+ // Try project-code-prefixed numeric: CK-01-name -> CK-01
230
+ const codePrefixed = dirName.match(/^([A-Z]{1,6}-\d+[A-Z]?(?:\.\d+)*)(?:-|$)/i);
231
+ if (codePrefixed) return codePrefixed[1];
232
+ // Try plain numeric: 01-name, 1009A-name, 999.6-name
233
+ const numeric = dirName.match(/^(\d+[A-Z]?(?:\.\d+)*)(?:-|$)/i);
234
+ if (numeric) return numeric[1];
235
+ // Custom IDs: PROJ-42-name -> everything before the last segment that looks like a name
236
+ const custom = dirName.match(/^([A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*)(?:-[a-z]|$)/i);
237
+ if (custom) return custom[1];
238
+ return dirName;
239
+ }
240
+
241
+ // ─── phaseTokenMatches ──────────────────────────────────────────────────────
242
+
243
+ /**
244
+ * Check if a directory name's phase token matches the normalized phase exactly.
245
+ *
246
+ * Case-insensitive comparison for the token portion.
247
+ *
248
+ * @param dirName - Directory name to check
249
+ * @param normalized - Normalized phase name to match against
250
+ * @returns True if the directory matches the phase
251
+ */
252
+ export function phaseTokenMatches(dirName: string, normalized: string): boolean {
253
+ const token = extractPhaseToken(dirName);
254
+ if (token.toUpperCase() === normalized.toUpperCase()) return true;
255
+ // Strip optional project_code prefix from dir and retry
256
+ const stripped = dirName.replace(/^[A-Z]{1,6}-(?=\d)/i, '');
257
+ if (stripped !== dirName) {
258
+ const strippedToken = extractPhaseToken(stripped);
259
+ if (strippedToken.toUpperCase() === normalized.toUpperCase()) return true;
260
+ }
261
+ return false;
262
+ }
263
+
264
+ // ─── toPosixPath ────────────────────────────────────────────────────────────
265
+
266
+ /**
267
+ * Convert a path to POSIX format (forward slashes).
268
+ *
269
+ * @param p - Path to convert
270
+ * @returns Path with all separators as forward slashes
271
+ */
272
+ export function toPosixPath(p: string): string {
273
+ return p.split('\\').join('/');
274
+ }
275
+
276
+ // ─── stateExtractField ──────────────────────────────────────────────────────
277
+
278
+ /**
279
+ * Extract a field value from STATE.md content.
280
+ *
281
+ * Supports both **bold:** and plain: formats, case-insensitive.
282
+ *
283
+ * @param content - STATE.md content string
284
+ * @param fieldName - Field name to extract
285
+ * @returns The field value, or null if not found
286
+ */
287
+ export function stateExtractField(content: string, fieldName: string): string | null {
288
+ const escaped = escapeRegex(fieldName);
289
+ // Horizontal whitespace only after ':' so YAML blocks like `progress:\n total:` do not
290
+ // match as `Progress:` with a multi-line "value" (parity with STATE.md body fields).
291
+ const boldPattern = new RegExp(`\\*\\*${escaped}:\\*\\*[ \\t]*(.+)`, 'i');
292
+ const boldMatch = content.match(boldPattern);
293
+ if (boldMatch) return boldMatch[1].trim();
294
+ const plainPattern = new RegExp(`^${escaped}:[ \\t]*(.+)`, 'im');
295
+ const plainMatch = content.match(plainPattern);
296
+ return plainMatch ? plainMatch[1].trim() : null;
297
+ }
298
+
299
+ // ─── normalizeMd ───────────────────────────────────────────────────────────
300
+
301
+ /**
302
+ * Normalize markdown content for consistent formatting.
303
+ *
304
+ * Port of `normalizeMd` from core.cjs lines 434-529.
305
+ * Applies: CRLF normalization, blank lines around headings/fences/lists,
306
+ * blank line collapsing (3+ to 2), terminal newline.
307
+ *
308
+ * @param content - Markdown content to normalize
309
+ * @returns Normalized markdown string
310
+ */
311
+ export function normalizeMd(content: string): string {
312
+ if (!content || typeof content !== 'string') return content;
313
+
314
+ // Normalize line endings to LF
315
+ let text = content.replace(/\r\n/g, '\n');
316
+
317
+ const lines = text.split('\n');
318
+ const result: string[] = [];
319
+
320
+ // Pre-compute fence state in a single O(n) pass
321
+ const fenceRegex = /^```/;
322
+ const insideFence = new Array<boolean>(lines.length);
323
+ let fenceOpen = false;
324
+ for (let i = 0; i < lines.length; i++) {
325
+ if (fenceRegex.test(lines[i].trimEnd())) {
326
+ if (fenceOpen) {
327
+ insideFence[i] = false;
328
+ fenceOpen = false;
329
+ } else {
330
+ insideFence[i] = false;
331
+ fenceOpen = true;
332
+ }
333
+ } else {
334
+ insideFence[i] = fenceOpen;
335
+ }
336
+ }
337
+
338
+ for (let i = 0; i < lines.length; i++) {
339
+ const line = lines[i];
340
+ const prev = i > 0 ? lines[i - 1] : '';
341
+ const prevTrimmed = prev.trimEnd();
342
+ const trimmed = line.trimEnd();
343
+ const isFenceLine = fenceRegex.test(trimmed);
344
+
345
+ // MD022: Blank line before headings (skip first line and frontmatter delimiters)
346
+ if (/^#{1,6}\s/.test(trimmed) && i > 0 && prevTrimmed !== '' && prevTrimmed !== '---') {
347
+ result.push('');
348
+ }
349
+
350
+ // MD031: Blank line before fenced code blocks (opening fences only)
351
+ if (isFenceLine && i > 0 && prevTrimmed !== '' && !insideFence[i] && (i === 0 || !insideFence[i - 1] || isFenceLine)) {
352
+ if (i === 0 || !insideFence[i - 1]) {
353
+ result.push('');
354
+ }
355
+ }
356
+
357
+ // MD032: Blank line before lists
358
+ if (/^(\s*[-*+]\s|\s*\d+\.\s)/.test(line) && i > 0 &&
359
+ prevTrimmed !== '' && !/^(\s*[-*+]\s|\s*\d+\.\s)/.test(prev) &&
360
+ prevTrimmed !== '---') {
361
+ result.push('');
362
+ }
363
+
364
+ result.push(line);
365
+
366
+ // MD022: Blank line after headings
367
+ if (/^#{1,6}\s/.test(trimmed) && i < lines.length - 1) {
368
+ const next = lines[i + 1];
369
+ if (next !== undefined && next.trimEnd() !== '') {
370
+ result.push('');
371
+ }
372
+ }
373
+
374
+ // MD031: Blank line after closing fenced code blocks
375
+ if (/^```\s*$/.test(trimmed) && i > 0 && insideFence[i - 1] && i < lines.length - 1) {
376
+ const next = lines[i + 1];
377
+ if (next !== undefined && next.trimEnd() !== '') {
378
+ result.push('');
379
+ }
380
+ }
381
+
382
+ // MD032: Blank line after last list item in a block
383
+ if (/^(\s*[-*+]\s|\s*\d+\.\s)/.test(line) && i < lines.length - 1) {
384
+ const next = lines[i + 1];
385
+ if (next !== undefined && next.trimEnd() !== '' &&
386
+ !/^(\s*[-*+]\s|\s*\d+\.\s)/.test(next) &&
387
+ !/^\s/.test(next)) {
388
+ result.push('');
389
+ }
390
+ }
391
+ }
392
+
393
+ text = result.join('\n');
394
+
395
+ // MD012: Collapse 3+ consecutive blank lines to 2
396
+ text = text.replace(/\n{3,}/g, '\n\n');
397
+
398
+ // MD047: Ensure file ends with exactly one newline
399
+ text = text.replace(/\n*$/, '\n');
400
+
401
+ return text;
402
+ }
403
+
404
+ // ─── planningPaths ──────────────────────────────────────────────────────────
405
+
406
+ /**
407
+ * Get common .planning file paths for a project directory.
408
+ *
409
+ * Simplified version (no workstream/project env vars).
410
+ * All paths returned in POSIX format.
411
+ *
412
+ * @param projectDir - Root project directory
413
+ * @returns Object with paths to common .planning files
414
+ */
415
+ export function planningPaths(projectDir: string): PlanningPaths {
416
+ const base = join(projectDir, '.planning');
417
+ return {
418
+ planning: toPosixPath(base),
419
+ state: toPosixPath(join(base, 'STATE.md')),
420
+ roadmap: toPosixPath(join(base, 'ROADMAP.md')),
421
+ project: toPosixPath(join(base, 'PROJECT.md')),
422
+ config: toPosixPath(join(base, 'config.json')),
423
+ phases: toPosixPath(join(base, 'phases')),
424
+ requirements: toPosixPath(join(base, 'REQUIREMENTS.md')),
425
+ };
426
+ }
427
+
428
+ // ─── resolvePathUnderProject ───────────────────────────────────────────────
429
+
430
+ /**
431
+ * Resolve a user-supplied path against the project and ensure it cannot escape
432
+ * the real project root (prefix checks are insufficient; symlinks are handled
433
+ * via realpath).
434
+ *
435
+ * @param projectDir - Project root directory
436
+ * @param userPath - Relative or absolute path from user input
437
+ * @returns Canonical resolved path within the project
438
+ */
439
+ export async function resolvePathUnderProject(projectDir: string, userPath: string): Promise<string> {
440
+ const projectReal = await realpath(projectDir);
441
+ const candidate = isAbsolute(userPath) ? normalize(userPath) : resolve(projectReal, userPath);
442
+ let realCandidate: string;
443
+ try {
444
+ realCandidate = await realpath(candidate);
445
+ } catch {
446
+ realCandidate = candidate;
447
+ }
448
+ const rel = relative(projectReal, realCandidate);
449
+ if (rel.startsWith('..') || (isAbsolute(rel) && rel.length > 0)) {
450
+ throw new GSDError('path escapes project directory', ErrorClassification.Validation);
451
+ }
452
+ return realCandidate;
453
+ }
454
+
455
+ // ─── sanitizeForDisplay (security.cjs) ───────────────────────────────────────
456
+
457
+ /** Port of `sanitizeForPrompt` from `security.cjs`. */
458
+ export function sanitizeForPrompt(text: string): string {
459
+ let sanitized = text;
460
+ sanitized = sanitized.replace(/[\u200B-\u200F\u2028-\u202F\uFEFF\u00AD]/g, '');
461
+ sanitized = sanitized.replace(
462
+ /<(\/?)(?:system|assistant|human)>/gi,
463
+ (_, slash: string) => `<${slash || ''}system-text>`,
464
+ );
465
+ sanitized = sanitized.replace(/\[(SYSTEM|INST)\]/gi, '[$1-TEXT]');
466
+ sanitized = sanitized.replace(/<<\s*SYS\s*>>/gi, '«SYS-TEXT»');
467
+ return sanitized;
468
+ }
469
+
470
+ /** Port of `sanitizeForDisplay` from `security.cjs` (matches CLI JSON). */
471
+ export function sanitizeForDisplay(text: string): string {
472
+ let sanitized = sanitizeForPrompt(text);
473
+ const protocolLeakPatterns = [
474
+ /^\s*(?:assistant|user|system)\s+to=[^:\s]+:[^\n]+$/i,
475
+ /^\s*<\|(?:assistant|user|system)[^|]*\|>\s*$/i,
476
+ ];
477
+ sanitized = sanitized
478
+ .split('\n')
479
+ .filter(line => !protocolLeakPatterns.some(pattern => pattern.test(line)))
480
+ .join('\n');
481
+ return sanitized;
482
+ }