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,523 @@
1
+ /**
2
+ * Roadmap — Roadmap parsing and update operations
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { escapeRegex, normalizePhaseName, planningPaths, withPlanningLock, output, error, findPhaseInternal, stripShippedMilestones, extractCurrentMilestone, replaceInCurrentMilestone, phaseTokenMatches, atomicWriteFileSync } = require('./core.cjs');
8
+
9
+ /**
10
+ * Search for a phase header (and its section) within the given content string.
11
+ * Returns a result object if found (either a full match or a malformed_roadmap
12
+ * checklist-only match), or null if the phase is not present at all.
13
+ */
14
+ function searchPhaseInContent(content, escapedPhase, phaseNum) {
15
+ // Match "## Phase X:", "### Phase X:", or "#### Phase X:" with optional name
16
+ const phasePattern = new RegExp(
17
+ `#{2,4}\\s*Phase\\s+${escapedPhase}:\\s*([^\\n]+)`,
18
+ 'i'
19
+ );
20
+ const headerMatch = content.match(phasePattern);
21
+
22
+ if (!headerMatch) {
23
+ // Fallback: check if phase exists in summary list but missing detail section
24
+ const checklistPattern = new RegExp(
25
+ `-\\s*\\[[ x]\\]\\s*\\*\\*Phase\\s+${escapedPhase}:\\s*([^*]+)\\*\\*`,
26
+ 'i'
27
+ );
28
+ const checklistMatch = content.match(checklistPattern);
29
+
30
+ if (checklistMatch) {
31
+ return {
32
+ found: false,
33
+ phase_number: phaseNum,
34
+ phase_name: checklistMatch[1].trim(),
35
+ error: 'malformed_roadmap',
36
+ message: `Phase ${phaseNum} exists in summary list but missing "### Phase ${phaseNum}:" detail section. ROADMAP.md needs both formats.`
37
+ };
38
+ }
39
+
40
+ return null;
41
+ }
42
+
43
+ const phaseName = headerMatch[1].trim();
44
+ const headerIndex = headerMatch.index;
45
+
46
+ // Find the end of this section (next ## or ### phase header, or end of file)
47
+ const restOfContent = content.slice(headerIndex);
48
+ const nextHeaderMatch = restOfContent.match(/\n#{2,4}\s+Phase\s+\d/i);
49
+ const sectionEnd = nextHeaderMatch
50
+ ? headerIndex + nextHeaderMatch.index
51
+ : content.length;
52
+
53
+ const section = content.slice(headerIndex, sectionEnd).trim();
54
+
55
+ // Extract goal if present (supports both **Goal:** and **Goal**: formats)
56
+ const goalMatch = section.match(/\*\*Goal(?::\*\*|\*\*:)\s*([^\n]+)/i);
57
+ const goal = goalMatch ? goalMatch[1].trim() : null;
58
+
59
+ // Extract success criteria as structured array
60
+ const criteriaMatch = section.match(/\*\*Success Criteria\*\*[^\n]*:\s*\n((?:\s*\d+\.\s*[^\n]+\n?)+)/i);
61
+ const success_criteria = criteriaMatch
62
+ ? criteriaMatch[1].trim().split('\n').map(line => line.replace(/^\s*\d+\.\s*/, '').trim()).filter(Boolean)
63
+ : [];
64
+
65
+ return {
66
+ found: true,
67
+ phase_number: phaseNum,
68
+ phase_name: phaseName,
69
+ goal,
70
+ success_criteria,
71
+ section,
72
+ };
73
+ }
74
+
75
+ function cmdRoadmapGetPhase(cwd, phaseNum, raw) {
76
+ const roadmapPath = planningPaths(cwd).roadmap;
77
+
78
+ if (!fs.existsSync(roadmapPath)) {
79
+ output({ found: false, error: 'ROADMAP.md not found' }, raw, '');
80
+ return;
81
+ }
82
+
83
+ try {
84
+ const rawContent = fs.readFileSync(roadmapPath, 'utf-8');
85
+ const milestoneContent = extractCurrentMilestone(rawContent, cwd);
86
+
87
+ // Escape special regex chars in phase number, handle decimal
88
+ const escapedPhase = escapeRegex(phaseNum);
89
+
90
+ // Search the current milestone slice first, then fall back to full roadmap.
91
+ // A malformed_roadmap result (checklist-only) from the milestone should not
92
+ // block finding a full header match in the wider roadmap content.
93
+ const fullContent = stripShippedMilestones(rawContent);
94
+ const milestoneResult = searchPhaseInContent(milestoneContent, escapedPhase, phaseNum);
95
+ const result = (milestoneResult && !milestoneResult.error)
96
+ ? milestoneResult
97
+ : searchPhaseInContent(fullContent, escapedPhase, phaseNum) || milestoneResult;
98
+
99
+ if (!result) {
100
+ output({ found: false, phase_number: phaseNum }, raw, '');
101
+ return;
102
+ }
103
+
104
+ if (result.error) {
105
+ output(result, raw, '');
106
+ return;
107
+ }
108
+
109
+ output(result, raw, result.section);
110
+ } catch (e) {
111
+ error('Failed to read ROADMAP.md: ' + e.message);
112
+ }
113
+ }
114
+
115
+ function cmdRoadmapAnalyze(cwd, raw) {
116
+ const roadmapPath = planningPaths(cwd).roadmap;
117
+
118
+ if (!fs.existsSync(roadmapPath)) {
119
+ output({ error: 'ROADMAP.md not found', milestones: [], phases: [], current_phase: null }, raw);
120
+ return;
121
+ }
122
+
123
+ const rawContent = fs.readFileSync(roadmapPath, 'utf-8');
124
+ const content = extractCurrentMilestone(rawContent, cwd);
125
+ const phasesDir = planningPaths(cwd).phases;
126
+
127
+ // Extract all phase headings: ## Phase N: Name or ### Phase N: Name
128
+ const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:\s*([^\n]+)/gi;
129
+ const phases = [];
130
+ let match;
131
+
132
+ // Build phase directory lookup once (O(1) readdir instead of O(N) per phase)
133
+ const _phaseDirNames = (() => {
134
+ try {
135
+ return fs.readdirSync(phasesDir, { withFileTypes: true })
136
+ .filter(e => e.isDirectory())
137
+ .map(e => e.name);
138
+ } catch { return []; }
139
+ })();
140
+
141
+ while ((match = phasePattern.exec(content)) !== null) {
142
+ const phaseNum = match[1];
143
+ const phaseName = match[2].replace(/\(INSERTED\)/i, '').trim();
144
+
145
+ // Extract goal from the section
146
+ const sectionStart = match.index;
147
+ const restOfContent = content.slice(sectionStart);
148
+ const nextHeader = restOfContent.match(/\n#{2,4}\s+Phase\s+\d/i);
149
+ const sectionEnd = nextHeader ? sectionStart + nextHeader.index : content.length;
150
+ const section = content.slice(sectionStart, sectionEnd);
151
+
152
+ const goalMatch = section.match(/\*\*Goal(?::\*\*|\*\*:)\s*([^\n]+)/i);
153
+ const goal = goalMatch ? goalMatch[1].trim() : null;
154
+
155
+ const dependsMatch = section.match(/\*\*Depends on(?::\*\*|\*\*:)\s*([^\n]+)/i);
156
+ const depends_on = dependsMatch ? dependsMatch[1].trim() : null;
157
+
158
+ // Check completion on disk
159
+ const normalized = normalizePhaseName(phaseNum);
160
+ let diskStatus = 'no_directory';
161
+ let planCount = 0;
162
+ let summaryCount = 0;
163
+ let hasContext = false;
164
+ let hasResearch = false;
165
+
166
+ try {
167
+ const dirMatch = _phaseDirNames.find(d => phaseTokenMatches(d, normalized));
168
+
169
+ if (dirMatch) {
170
+ const phaseFiles = fs.readdirSync(path.join(phasesDir, dirMatch));
171
+ planCount = phaseFiles.filter(f => f.endsWith('-PLAN.md') || f === 'PLAN.md').length;
172
+ summaryCount = phaseFiles.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md').length;
173
+ hasContext = phaseFiles.some(f => f.endsWith('-CONTEXT.md') || f === 'CONTEXT.md');
174
+ hasResearch = phaseFiles.some(f => f.endsWith('-RESEARCH.md') || f === 'RESEARCH.md');
175
+
176
+ if (summaryCount >= planCount && planCount > 0) diskStatus = 'complete';
177
+ else if (summaryCount > 0) diskStatus = 'partial';
178
+ else if (planCount > 0) diskStatus = 'planned';
179
+ else if (hasResearch) diskStatus = 'researched';
180
+ else if (hasContext) diskStatus = 'discussed';
181
+ else diskStatus = 'empty';
182
+ }
183
+ } catch { /* intentionally empty */ }
184
+
185
+ // Check ROADMAP checkbox status
186
+ const checkboxPattern = new RegExp(`-\\s*\\[(x| )\\]\\s*.*Phase\\s+${escapeRegex(phaseNum)}[:\\s]`, 'i');
187
+ const checkboxMatch = content.match(checkboxPattern);
188
+ const roadmapComplete = checkboxMatch ? checkboxMatch[1] === 'x' : false;
189
+
190
+ // If roadmap marks phase complete, trust that over disk file structure.
191
+ // Phases completed before GSD tracking (or via external tools) may lack
192
+ // the standard PLAN/SUMMARY pairs but are still done.
193
+ if (roadmapComplete && diskStatus !== 'complete') {
194
+ diskStatus = 'complete';
195
+ }
196
+
197
+ phases.push({
198
+ number: phaseNum,
199
+ name: phaseName,
200
+ goal,
201
+ depends_on,
202
+ plan_count: planCount,
203
+ summary_count: summaryCount,
204
+ has_context: hasContext,
205
+ has_research: hasResearch,
206
+ disk_status: diskStatus,
207
+ roadmap_complete: roadmapComplete,
208
+ });
209
+ }
210
+
211
+ // Extract milestone info
212
+ const milestones = [];
213
+ const milestonePattern = /##\s*(.*v(\d+(?:\.\d+)+)[^(\n]*)/gi;
214
+ let mMatch;
215
+ while ((mMatch = milestonePattern.exec(content)) !== null) {
216
+ milestones.push({
217
+ heading: mMatch[1].trim(),
218
+ version: 'v' + mMatch[2],
219
+ });
220
+ }
221
+
222
+ // Find current and next phase
223
+ const currentPhase = phases.find(p => p.disk_status === 'planned' || p.disk_status === 'partial') || null;
224
+ const nextPhase = phases.find(p => p.disk_status === 'empty' || p.disk_status === 'no_directory' || p.disk_status === 'discussed' || p.disk_status === 'researched') || null;
225
+
226
+ // Aggregated stats
227
+ const totalPlans = phases.reduce((sum, p) => sum + p.plan_count, 0);
228
+ const totalSummaries = phases.reduce((sum, p) => sum + p.summary_count, 0);
229
+ const completedPhases = phases.filter(p => p.disk_status === 'complete').length;
230
+
231
+ // Detect phases in summary list without detail sections (malformed ROADMAP)
232
+ const checklistPattern = /-\s*\[[ x]\]\s*\*\*Phase\s+(\d+[A-Z]?(?:\.\d+)*)/gi;
233
+ const checklistPhases = new Set();
234
+ let checklistMatch;
235
+ while ((checklistMatch = checklistPattern.exec(content)) !== null) {
236
+ checklistPhases.add(checklistMatch[1]);
237
+ }
238
+ const detailPhases = new Set(phases.map(p => p.number));
239
+ const missingDetails = [...checklistPhases].filter(p => !detailPhases.has(p));
240
+
241
+ const result = {
242
+ milestones,
243
+ phases,
244
+ phase_count: phases.length,
245
+ completed_phases: completedPhases,
246
+ total_plans: totalPlans,
247
+ total_summaries: totalSummaries,
248
+ progress_percent: totalPlans > 0 ? Math.min(100, Math.round((totalSummaries / totalPlans) * 100)) : 0,
249
+ current_phase: currentPhase ? currentPhase.number : null,
250
+ next_phase: nextPhase ? nextPhase.number : null,
251
+ missing_phase_details: missingDetails.length > 0 ? missingDetails : null,
252
+ };
253
+
254
+ output(result, raw);
255
+ }
256
+
257
+ function cmdRoadmapUpdatePlanProgress(cwd, phaseNum, raw) {
258
+ if (!phaseNum) {
259
+ error('phase number required for roadmap update-plan-progress');
260
+ }
261
+
262
+ const roadmapPath = planningPaths(cwd).roadmap;
263
+
264
+ const phaseInfo = findPhaseInternal(cwd, phaseNum);
265
+ if (!phaseInfo) {
266
+ error(`Phase ${phaseNum} not found`);
267
+ }
268
+
269
+ const planCount = phaseInfo.plans.length;
270
+ const summaryCount = phaseInfo.summaries.length;
271
+
272
+ if (planCount === 0) {
273
+ output({ updated: false, reason: 'No plans found', plan_count: 0, summary_count: 0 }, raw, 'no plans');
274
+ return;
275
+ }
276
+
277
+ const isComplete = summaryCount >= planCount;
278
+ const status = isComplete ? 'Complete' : summaryCount > 0 ? 'In Progress' : 'Planned';
279
+ const today = new Date().toISOString().split('T')[0];
280
+
281
+ if (!fs.existsSync(roadmapPath)) {
282
+ output({ updated: false, reason: 'ROADMAP.md not found', plan_count: planCount, summary_count: summaryCount }, raw, 'no roadmap');
283
+ return;
284
+ }
285
+
286
+ // Wrap entire read-modify-write in lock to prevent concurrent corruption
287
+ withPlanningLock(cwd, () => {
288
+ let roadmapContent = fs.readFileSync(roadmapPath, 'utf-8');
289
+ const phaseEscaped = escapeRegex(phaseNum);
290
+
291
+ // Progress table row: update Plans/Status/Date columns (handles 4 or 5 column tables)
292
+ const tableRowPattern = new RegExp(
293
+ `^(\\|\\s*${phaseEscaped}\\.?\\s[^|]*(?:\\|[^\\n]*))$`,
294
+ 'im'
295
+ );
296
+ const dateField = isComplete ? ` ${today} ` : ' ';
297
+ roadmapContent = roadmapContent.replace(tableRowPattern, (fullRow) => {
298
+ const cells = fullRow.split('|').slice(1, -1); // drop leading/trailing empty from split
299
+ if (cells.length === 5) {
300
+ // 5-col: Phase | Milestone | Plans | Status | Completed
301
+ cells[2] = ` ${summaryCount}/${planCount} `;
302
+ cells[3] = ` ${status.padEnd(11)}`;
303
+ cells[4] = dateField;
304
+ } else if (cells.length === 4) {
305
+ // 4-col: Phase | Plans | Status | Completed
306
+ cells[1] = ` ${summaryCount}/${planCount} `;
307
+ cells[2] = ` ${status.padEnd(11)}`;
308
+ cells[3] = dateField;
309
+ }
310
+ return '|' + cells.join('|') + '|';
311
+ });
312
+
313
+ // Update plan count in phase detail section
314
+ const planCountPattern = new RegExp(
315
+ `(#{2,4}\\s*Phase\\s+${phaseEscaped}[\\s\\S]*?\\*\\*Plans:\\*\\*\\s*)[^\\n]+`,
316
+ 'i'
317
+ );
318
+ const planCountText = isComplete
319
+ ? `${summaryCount}/${planCount} plans complete`
320
+ : `${summaryCount}/${planCount} plans executed`;
321
+ roadmapContent = replaceInCurrentMilestone(roadmapContent, planCountPattern, `$1${planCountText}`);
322
+
323
+ // If complete: check checkbox
324
+ if (isComplete) {
325
+ const checkboxPattern = new RegExp(
326
+ `(-\\s*\\[)[ ](\\]\\s*.*Phase\\s+${phaseEscaped}[:\\s][^\\n]*)`,
327
+ 'i'
328
+ );
329
+ roadmapContent = replaceInCurrentMilestone(roadmapContent, checkboxPattern, `$1x$2 (completed ${today})`);
330
+ }
331
+
332
+ // Mark completed plan checkboxes (e.g. "- [ ] 50-01-PLAN.md", "- [ ] 50-01:", or "- [ ] **50-01**")
333
+ for (const summaryFile of phaseInfo.summaries) {
334
+ const planId = summaryFile.replace('-SUMMARY.md', '').replace('SUMMARY.md', '');
335
+ if (!planId) continue;
336
+ const planEscaped = escapeRegex(planId);
337
+ const planCheckboxPattern = new RegExp(
338
+ `(-\\s*\\[) (\\]\\s*(?:\\*\\*)?${planEscaped}(?:\\*\\*)?)`,
339
+ 'i'
340
+ );
341
+ roadmapContent = roadmapContent.replace(planCheckboxPattern, '$1x$2');
342
+ }
343
+
344
+ atomicWriteFileSync(roadmapPath, roadmapContent, 'utf-8');
345
+ });
346
+ output({
347
+ updated: true,
348
+ phase: phaseNum,
349
+ plan_count: planCount,
350
+ summary_count: summaryCount,
351
+ status,
352
+ complete: isComplete,
353
+ }, raw, `${summaryCount}/${planCount} ${status}`);
354
+ }
355
+
356
+ /**
357
+ * Annotate the ROADMAP.md plan list for a phase with wave dependency notes
358
+ * and a cross-cutting constraints subsection derived from PLAN frontmatter.
359
+ *
360
+ * Wave dependency notes: "Wave 2 — blocked on Wave 1 completion" inserted as
361
+ * bold headers before each wave group in the plan checklist.
362
+ *
363
+ * Cross-cutting constraints: must_haves.truths strings that appear in 2+ plans
364
+ * are surfaced in a "Cross-cutting constraints" subsection below the plan list.
365
+ *
366
+ * The operation is idempotent: if wave headers already exist in the section
367
+ * the function returns without modifying the file.
368
+ */
369
+ function cmdRoadmapAnnotateDependencies(cwd, phaseNum, raw) {
370
+ if (!phaseNum) {
371
+ error('phase number required for roadmap annotate-dependencies');
372
+ }
373
+
374
+ const roadmapPath = planningPaths(cwd).roadmap;
375
+ if (!fs.existsSync(roadmapPath)) {
376
+ output({ updated: false, reason: 'ROADMAP.md not found' }, raw, 'no roadmap');
377
+ return;
378
+ }
379
+
380
+ const phaseInfo = findPhaseInternal(cwd, phaseNum);
381
+ if (!phaseInfo || phaseInfo.plans.length === 0) {
382
+ output({ updated: false, reason: 'no plans found for phase', phase: phaseNum }, raw, 'no plans');
383
+ return;
384
+ }
385
+
386
+ const { extractFrontmatter, parseMustHavesBlock } = require('./frontmatter.cjs');
387
+
388
+ // Read each PLAN.md and extract wave + must_haves.truths
389
+ const planData = [];
390
+ for (const planFile of phaseInfo.plans) {
391
+ const planPath = path.join(path.resolve(cwd, phaseInfo.directory), planFile);
392
+ try {
393
+ const content = fs.readFileSync(planPath, 'utf-8');
394
+ const fm = extractFrontmatter(content);
395
+ const wave = parseInt(fm.wave, 10) || 1;
396
+ const planId = planFile.replace(/-PLAN\.md$/i, '').replace(/PLAN\.md$/i, '');
397
+ const truths = parseMustHavesBlock(content, 'truths') || [];
398
+ planData.push({ planFile, planId, wave, truths });
399
+ } catch { /* skip unreadable plans */ }
400
+ }
401
+
402
+ if (planData.length === 0) {
403
+ output({ updated: false, reason: 'could not read plan frontmatter' }, raw, 'no frontmatter');
404
+ return;
405
+ }
406
+
407
+ // Group plans by wave (sorted)
408
+ const waveGroups = new Map();
409
+ for (const p of planData) {
410
+ if (!waveGroups.has(p.wave)) waveGroups.set(p.wave, []);
411
+ waveGroups.get(p.wave).push(p);
412
+ }
413
+ const waves = [...waveGroups.keys()].sort((a, b) => a - b);
414
+
415
+ // Find cross-cutting truths: appear in 2+ plans (de-duplicated, case-insensitive)
416
+ const truthCounts = new Map();
417
+ for (const { truths } of planData) {
418
+ const seen = new Set();
419
+ for (const t of truths) {
420
+ const key = t.trim().toLowerCase();
421
+ if (!key || seen.has(key)) continue;
422
+ seen.add(key);
423
+ truthCounts.set(key, (truthCounts.get(key) || { count: 0, text: t.trim() }));
424
+ truthCounts.get(key).count++;
425
+ }
426
+ }
427
+ const crossCuttingTruths = [...truthCounts.values()]
428
+ .filter(v => v.count >= 2)
429
+ .map(v => v.text);
430
+
431
+ // Patch ROADMAP.md
432
+ let updated = false;
433
+ withPlanningLock(cwd, () => {
434
+ let content = fs.readFileSync(roadmapPath, 'utf-8');
435
+
436
+ // Find the phase section
437
+ const phaseEscaped = escapeRegex(phaseNum);
438
+ const phaseHeaderPattern = new RegExp(`(#{2,4}\\s*Phase\\s+${phaseEscaped}:[^\\n]*)`, 'i');
439
+ const phaseMatch = content.match(phaseHeaderPattern);
440
+ if (!phaseMatch) return;
441
+
442
+ const phaseStart = phaseMatch.index;
443
+ const restAfterHeader = content.slice(phaseStart);
444
+ const nextPhaseOffset = restAfterHeader.slice(1).search(/\n#{2,4}\s+Phase\s+\d/i);
445
+ const phaseEnd = nextPhaseOffset >= 0 ? phaseStart + 1 + nextPhaseOffset : content.length;
446
+ const phaseSection = content.slice(phaseStart, phaseEnd);
447
+
448
+ // Idempotency: skip if annotation markers already present
449
+ if (
450
+ /\*\*Wave\s+\d+/i.test(phaseSection) ||
451
+ /\*\*Cross-cutting constraints:\*\*/i.test(phaseSection)
452
+ ) return;
453
+
454
+ // Find the Plans: section within the phase section
455
+ const plansBlockMatch = phaseSection.match(/(Plans:\s*\n)((?:\s*-\s*\[[ x]\][^\n]*\n?)*)/i);
456
+ if (!plansBlockMatch) return;
457
+
458
+ const plansHeader = plansBlockMatch[1];
459
+ const existingList = plansBlockMatch[2];
460
+ const listLines = existingList.split('\n').filter(l => /^\s*-\s*\[/.test(l));
461
+
462
+ if (listLines.length === 0) return;
463
+
464
+ // Build wave-annotated plan list
465
+ const linesByWave = new Map();
466
+ for (const line of listLines) {
467
+ // Match plan ID from line: "- [ ] 01-01-PLAN.md — ..." or "- [ ] 01-01: ..."
468
+ const idMatch = line.match(/\[\s*[x ]\s*\]\s*([\w-]+?)(?:-PLAN\.md|\.md|:|\s—)/i);
469
+ const planId = idMatch ? idMatch[1] : null;
470
+ const planEntry = planId ? planData.find(p => p.planId === planId) : null;
471
+ const wave = planEntry ? planEntry.wave : 1;
472
+ if (!linesByWave.has(wave)) linesByWave.set(wave, []);
473
+ linesByWave.get(wave).push(line);
474
+ }
475
+
476
+ const annotatedLines = [];
477
+ const sortedWaves = [...linesByWave.keys()].sort((a, b) => a - b);
478
+ for (let i = 0; i < sortedWaves.length; i++) {
479
+ const w = sortedWaves[i];
480
+ const waveLines = linesByWave.get(w);
481
+ if (sortedWaves.length > 1) {
482
+ const dep = i > 0 ? ` *(blocked on Wave ${sortedWaves[i - 1]} completion)*` : '';
483
+ annotatedLines.push(`**Wave ${w}**${dep}`);
484
+ }
485
+ annotatedLines.push(...waveLines);
486
+ if (i < sortedWaves.length - 1) annotatedLines.push('');
487
+ }
488
+
489
+ // Append cross-cutting constraints subsection if any found
490
+ if (crossCuttingTruths.length > 0) {
491
+ annotatedLines.push('');
492
+ annotatedLines.push('**Cross-cutting constraints:**');
493
+ for (const t of crossCuttingTruths) {
494
+ annotatedLines.push(`- ${t}`);
495
+ }
496
+ }
497
+
498
+ const newListBlock = annotatedLines.join('\n') + '\n';
499
+ const newPhaseSection = phaseSection.replace(
500
+ plansBlockMatch[0],
501
+ plansHeader + newListBlock
502
+ );
503
+
504
+ const nextContent = content.slice(0, phaseStart) + newPhaseSection + content.slice(phaseEnd);
505
+ if (nextContent === content) return;
506
+ atomicWriteFileSync(roadmapPath, nextContent);
507
+ updated = true;
508
+ });
509
+
510
+ output({
511
+ updated,
512
+ phase: phaseNum,
513
+ waves: waves.length,
514
+ cross_cutting_constraints: crossCuttingTruths.length,
515
+ }, raw, updated ? `annotated ${waves.length} wave(s), ${crossCuttingTruths.length} constraint(s)` : 'skipped (already annotated or no plan list)');
516
+ }
517
+
518
+ module.exports = {
519
+ cmdRoadmapGetPhase,
520
+ cmdRoadmapAnalyze,
521
+ cmdRoadmapUpdatePlanProgress,
522
+ cmdRoadmapAnnotateDependencies,
523
+ };