@opengsd/get-shit-done-redux 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 (1466) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja-JP.md +870 -0
  3. package/README.ko-KR.md +861 -0
  4. package/README.md +300 -0
  5. package/README.pt-BR.md +492 -0
  6. package/README.zh-CN.md +842 -0
  7. package/agents/gsd-advisor-researcher.md +127 -0
  8. package/agents/gsd-ai-researcher.md +133 -0
  9. package/agents/gsd-assumptions-analyzer.md +105 -0
  10. package/agents/gsd-code-fixer.md +668 -0
  11. package/agents/gsd-code-reviewer.md +387 -0
  12. package/agents/gsd-codebase-mapper.md +853 -0
  13. package/agents/gsd-debug-session-manager.md +314 -0
  14. package/agents/gsd-debugger.md +1452 -0
  15. package/agents/gsd-doc-classifier.md +168 -0
  16. package/agents/gsd-doc-synthesizer.md +204 -0
  17. package/agents/gsd-doc-verifier.md +217 -0
  18. package/agents/gsd-doc-writer.md +615 -0
  19. package/agents/gsd-domain-researcher.md +153 -0
  20. package/agents/gsd-eval-auditor.md +191 -0
  21. package/agents/gsd-eval-planner.md +154 -0
  22. package/agents/gsd-executor.md +774 -0
  23. package/agents/gsd-framework-selector.md +160 -0
  24. package/agents/gsd-integration-checker.md +470 -0
  25. package/agents/gsd-intel-updater.md +342 -0
  26. package/agents/gsd-nyquist-auditor.md +203 -0
  27. package/agents/gsd-pattern-mapper.md +335 -0
  28. package/agents/gsd-phase-researcher.md +928 -0
  29. package/agents/gsd-plan-checker.md +978 -0
  30. package/agents/gsd-planner.md +1278 -0
  31. package/agents/gsd-project-researcher.md +677 -0
  32. package/agents/gsd-research-synthesizer.md +247 -0
  33. package/agents/gsd-roadmapper.md +688 -0
  34. package/agents/gsd-security-auditor.md +155 -0
  35. package/agents/gsd-ui-auditor.md +495 -0
  36. package/agents/gsd-ui-checker.md +309 -0
  37. package/agents/gsd-ui-researcher.md +380 -0
  38. package/agents/gsd-user-profiler.md +171 -0
  39. package/agents/gsd-verifier.md +917 -0
  40. package/bin/gsd-sdk.js +37 -0
  41. package/bin/install.js +11468 -0
  42. package/bin/lib/ui-safety-gate.cjs +107 -0
  43. package/commands/gsd/add-tests.md +42 -0
  44. package/commands/gsd/ai-integration-phase.md +37 -0
  45. package/commands/gsd/audit-fix.md +34 -0
  46. package/commands/gsd/audit-milestone.md +37 -0
  47. package/commands/gsd/audit-uat.md +24 -0
  48. package/commands/gsd/autonomous.md +46 -0
  49. package/commands/gsd/capture.md +62 -0
  50. package/commands/gsd/cleanup.md +24 -0
  51. package/commands/gsd/code-review.md +59 -0
  52. package/commands/gsd/complete-milestone.md +143 -0
  53. package/commands/gsd/config.md +58 -0
  54. package/commands/gsd/debug.md +52 -0
  55. package/commands/gsd/discuss-phase.md +76 -0
  56. package/commands/gsd/docs-update.md +49 -0
  57. package/commands/gsd/eval-review.md +33 -0
  58. package/commands/gsd/execute-phase.md +64 -0
  59. package/commands/gsd/explore.md +27 -0
  60. package/commands/gsd/extract-learnings.md +23 -0
  61. package/commands/gsd/fast.md +31 -0
  62. package/commands/gsd/forensics.md +57 -0
  63. package/commands/gsd/graphify.md +199 -0
  64. package/commands/gsd/health.md +31 -0
  65. package/commands/gsd/help.md +28 -0
  66. package/commands/gsd/import.md +41 -0
  67. package/commands/gsd/inbox.md +39 -0
  68. package/commands/gsd/ingest-docs.md +42 -0
  69. package/commands/gsd/manager.md +45 -0
  70. package/commands/gsd/map-codebase.md +83 -0
  71. package/commands/gsd/milestone-summary.md +51 -0
  72. package/commands/gsd/mvp-phase.md +45 -0
  73. package/commands/gsd/new-milestone.md +45 -0
  74. package/commands/gsd/new-project.md +47 -0
  75. package/commands/gsd/ns-context.md +23 -0
  76. package/commands/gsd/ns-ideate.md +24 -0
  77. package/commands/gsd/ns-manage.md +29 -0
  78. package/commands/gsd/ns-project.md +22 -0
  79. package/commands/gsd/ns-review.md +26 -0
  80. package/commands/gsd/ns-workflow.md +28 -0
  81. package/commands/gsd/pause-work.md +43 -0
  82. package/commands/gsd/phase.md +56 -0
  83. package/commands/gsd/plan-phase.md +62 -0
  84. package/commands/gsd/plan-review-convergence.md +59 -0
  85. package/commands/gsd/pr-branch.md +26 -0
  86. package/commands/gsd/profile-user.md +46 -0
  87. package/commands/gsd/progress.md +46 -0
  88. package/commands/gsd/quick.md +174 -0
  89. package/commands/gsd/resume-work.md +30 -0
  90. package/commands/gsd/review-backlog.md +63 -0
  91. package/commands/gsd/review.md +41 -0
  92. package/commands/gsd/secure-phase.md +36 -0
  93. package/commands/gsd/settings.md +29 -0
  94. package/commands/gsd/ship.md +24 -0
  95. package/commands/gsd/sketch.md +60 -0
  96. package/commands/gsd/spec-phase.md +63 -0
  97. package/commands/gsd/spike.md +57 -0
  98. package/commands/gsd/stats.md +19 -0
  99. package/commands/gsd/surface.md +155 -0
  100. package/commands/gsd/thread.md +24 -0
  101. package/commands/gsd/ui-phase.md +35 -0
  102. package/commands/gsd/ui-review.md +33 -0
  103. package/commands/gsd/ultraplan-phase.md +34 -0
  104. package/commands/gsd/undo.md +35 -0
  105. package/commands/gsd/update.md +48 -0
  106. package/commands/gsd/validate-phase.md +36 -0
  107. package/commands/gsd/verify-work.md +39 -0
  108. package/commands/gsd/workspace.md +52 -0
  109. package/commands/gsd/workstreams.md +70 -0
  110. package/get-shit-done/bin/check-latest-version.cjs +104 -0
  111. package/get-shit-done/bin/gsd-tools.cjs +1630 -0
  112. package/get-shit-done/bin/lib/active-workstream-store.cjs +85 -0
  113. package/get-shit-done/bin/lib/adr-parser.cjs +394 -0
  114. package/get-shit-done/bin/lib/artifacts.cjs +53 -0
  115. package/get-shit-done/bin/lib/audit.cjs +755 -0
  116. package/get-shit-done/bin/lib/cjs-command-router-adapter.cjs +39 -0
  117. package/get-shit-done/bin/lib/cjs-sdk-bridge.cjs +136 -0
  118. package/get-shit-done/bin/lib/clusters.cjs +135 -0
  119. package/get-shit-done/bin/lib/code-review-flags.cjs +74 -0
  120. package/get-shit-done/bin/lib/command-aliases.generated.cjs +824 -0
  121. package/get-shit-done/bin/lib/command-routing-hub.cjs +239 -0
  122. package/get-shit-done/bin/lib/commands.cjs +1035 -0
  123. package/get-shit-done/bin/lib/config-schema.cjs +31 -0
  124. package/get-shit-done/bin/lib/config.cjs +704 -0
  125. package/get-shit-done/bin/lib/configuration.generated.cjs +253 -0
  126. package/get-shit-done/bin/lib/context-utilization.cjs +47 -0
  127. package/get-shit-done/bin/lib/core.cjs +1922 -0
  128. package/get-shit-done/bin/lib/decisions.cjs +19 -0
  129. package/get-shit-done/bin/lib/decisions.generated.cjs +121 -0
  130. package/get-shit-done/bin/lib/docs.cjs +270 -0
  131. package/get-shit-done/bin/lib/drift.cjs +388 -0
  132. package/get-shit-done/bin/lib/fallow-runner.cjs +109 -0
  133. package/get-shit-done/bin/lib/frontmatter.cjs +389 -0
  134. package/get-shit-done/bin/lib/gap-checker.cjs +205 -0
  135. package/get-shit-done/bin/lib/graphify.cjs +592 -0
  136. package/get-shit-done/bin/lib/gsd2-import.cjs +514 -0
  137. package/get-shit-done/bin/lib/init-command-router.cjs +174 -0
  138. package/get-shit-done/bin/lib/init.cjs +2096 -0
  139. package/get-shit-done/bin/lib/install-profiles.cjs +603 -0
  140. package/get-shit-done/bin/lib/installer-migration-authoring.cjs +117 -0
  141. package/get-shit-done/bin/lib/installer-migration-report.cjs +354 -0
  142. package/get-shit-done/bin/lib/installer-migrations/000-first-time-baseline.cjs +220 -0
  143. package/get-shit-done/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +41 -0
  144. package/get-shit-done/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +80 -0
  145. package/get-shit-done/bin/lib/installer-migrations.cjs +776 -0
  146. package/get-shit-done/bin/lib/intel.cjs +643 -0
  147. package/get-shit-done/bin/lib/learnings.cjs +379 -0
  148. package/get-shit-done/bin/lib/milestone.cjs +314 -0
  149. package/get-shit-done/bin/lib/model-catalog.cjs +136 -0
  150. package/get-shit-done/bin/lib/model-profiles.cjs +25 -0
  151. package/get-shit-done/bin/lib/phase-command-router.cjs +226 -0
  152. package/get-shit-done/bin/lib/phase.cjs +1490 -0
  153. package/get-shit-done/bin/lib/phases-command-router.cjs +97 -0
  154. package/get-shit-done/bin/lib/plan-scan.cjs +26 -0
  155. package/get-shit-done/bin/lib/plan-scan.generated.cjs +97 -0
  156. package/get-shit-done/bin/lib/planning-workspace.cjs +415 -0
  157. package/get-shit-done/bin/lib/profile-output.cjs +1130 -0
  158. package/get-shit-done/bin/lib/profile-pipeline.cjs +539 -0
  159. package/get-shit-done/bin/lib/project-root.generated.cjs +117 -0
  160. package/get-shit-done/bin/lib/prompt-budget.cjs +399 -0
  161. package/get-shit-done/bin/lib/review-reviewer-selection.cjs +125 -0
  162. package/get-shit-done/bin/lib/roadmap-command-router.cjs +99 -0
  163. package/get-shit-done/bin/lib/roadmap.cjs +642 -0
  164. package/get-shit-done/bin/lib/runtime-artifact-layout.cjs +301 -0
  165. package/get-shit-done/bin/lib/runtime-homes.cjs +185 -0
  166. package/get-shit-done/bin/lib/runtime-slash.cjs +109 -0
  167. package/get-shit-done/bin/lib/schema-detect.cjs +21 -0
  168. package/get-shit-done/bin/lib/schema-detect.generated.cjs +170 -0
  169. package/get-shit-done/bin/lib/secrets.cjs +20 -0
  170. package/get-shit-done/bin/lib/secrets.generated.cjs +37 -0
  171. package/get-shit-done/bin/lib/security.cjs +504 -0
  172. package/get-shit-done/bin/lib/shell-command-projection.cjs +552 -0
  173. package/get-shit-done/bin/lib/state-command-router.cjs +346 -0
  174. package/get-shit-done/bin/lib/state-document.cjs +12 -0
  175. package/get-shit-done/bin/lib/state-document.generated.cjs +127 -0
  176. package/get-shit-done/bin/lib/state.cjs +1940 -0
  177. package/get-shit-done/bin/lib/surface.cjs +430 -0
  178. package/get-shit-done/bin/lib/template.cjs +228 -0
  179. package/get-shit-done/bin/lib/uat.cjs +289 -0
  180. package/get-shit-done/bin/lib/validate-command-router.cjs +129 -0
  181. package/get-shit-done/bin/lib/verify-command-router.cjs +122 -0
  182. package/get-shit-done/bin/lib/verify.cjs +1458 -0
  183. package/get-shit-done/bin/lib/workstream-inventory-builder.generated.cjs +79 -0
  184. package/get-shit-done/bin/lib/workstream-inventory.cjs +132 -0
  185. package/get-shit-done/bin/lib/workstream-name-policy.cjs +19 -0
  186. package/get-shit-done/bin/lib/workstream-name-policy.generated.cjs +61 -0
  187. package/get-shit-done/bin/lib/workstream.cjs +374 -0
  188. package/get-shit-done/bin/lib/worktree-safety.cjs +985 -0
  189. package/get-shit-done/bin/verify-reapply-patches.cjs +336 -0
  190. package/get-shit-done/contexts/dev.md +21 -0
  191. package/get-shit-done/contexts/research.md +22 -0
  192. package/get-shit-done/contexts/review.md +23 -0
  193. package/get-shit-done/references/agent-contracts.md +79 -0
  194. package/get-shit-done/references/ai-evals.md +156 -0
  195. package/get-shit-done/references/ai-frameworks.md +186 -0
  196. package/get-shit-done/references/artifact-types.md +131 -0
  197. package/get-shit-done/references/autonomous-smart-discuss.md +277 -0
  198. package/get-shit-done/references/checkpoints.md +814 -0
  199. package/get-shit-done/references/common-bug-patterns.md +114 -0
  200. package/get-shit-done/references/context-budget.md +85 -0
  201. package/get-shit-done/references/continuation-format.md +253 -0
  202. package/get-shit-done/references/debugger-philosophy.md +76 -0
  203. package/get-shit-done/references/decimal-phase-calculation.md +64 -0
  204. package/get-shit-done/references/doc-conflict-engine.md +91 -0
  205. package/get-shit-done/references/domain-probes.md +125 -0
  206. package/get-shit-done/references/execute-mvp-tdd.md +81 -0
  207. package/get-shit-done/references/executor-examples.md +110 -0
  208. package/get-shit-done/references/few-shot-examples/plan-checker.md +73 -0
  209. package/get-shit-done/references/few-shot-examples/verifier.md +109 -0
  210. package/get-shit-done/references/gate-prompts.md +100 -0
  211. package/get-shit-done/references/gates.md +70 -0
  212. package/get-shit-done/references/git-integration.md +298 -0
  213. package/get-shit-done/references/git-planning-commit.md +40 -0
  214. package/get-shit-done/references/ios-scaffold.md +123 -0
  215. package/get-shit-done/references/mandatory-initial-read.md +2 -0
  216. package/get-shit-done/references/model-profile-resolution.md +38 -0
  217. package/get-shit-done/references/model-profiles.md +245 -0
  218. package/get-shit-done/references/mvp-concepts.md +49 -0
  219. package/get-shit-done/references/phase-argument-parsing.md +61 -0
  220. package/get-shit-done/references/planner-antipatterns.md +89 -0
  221. package/get-shit-done/references/planner-chunked.md +49 -0
  222. package/get-shit-done/references/planner-gap-closure.md +62 -0
  223. package/get-shit-done/references/planner-graphify-auto-update.md +67 -0
  224. package/get-shit-done/references/planner-human-verify-mode.md +57 -0
  225. package/get-shit-done/references/planner-mvp-mode.md +53 -0
  226. package/get-shit-done/references/planner-reviews.md +39 -0
  227. package/get-shit-done/references/planner-revision.md +87 -0
  228. package/get-shit-done/references/planner-source-audit.md +73 -0
  229. package/get-shit-done/references/planning-config.md +471 -0
  230. package/get-shit-done/references/project-skills-discovery.md +19 -0
  231. package/get-shit-done/references/questioning.md +162 -0
  232. package/get-shit-done/references/revision-loop.md +97 -0
  233. package/get-shit-done/references/scout-codebase.md +51 -0
  234. package/get-shit-done/references/skeleton-template.md +48 -0
  235. package/get-shit-done/references/sketch-interactivity.md +41 -0
  236. package/get-shit-done/references/sketch-theme-system.md +94 -0
  237. package/get-shit-done/references/sketch-tooling.md +45 -0
  238. package/get-shit-done/references/sketch-variant-patterns.md +81 -0
  239. package/get-shit-done/references/spidr-splitting.md +69 -0
  240. package/get-shit-done/references/tdd.md +330 -0
  241. package/get-shit-done/references/thinking-models-debug.md +44 -0
  242. package/get-shit-done/references/thinking-models-execution.md +50 -0
  243. package/get-shit-done/references/thinking-models-planning.md +62 -0
  244. package/get-shit-done/references/thinking-models-research.md +50 -0
  245. package/get-shit-done/references/thinking-models-verification.md +55 -0
  246. package/get-shit-done/references/thinking-partner.md +96 -0
  247. package/get-shit-done/references/ui-brand.md +160 -0
  248. package/get-shit-done/references/universal-anti-patterns.md +63 -0
  249. package/get-shit-done/references/user-profiling.md +681 -0
  250. package/get-shit-done/references/user-story-template.md +58 -0
  251. package/get-shit-done/references/verification-overrides.md +227 -0
  252. package/get-shit-done/references/verification-patterns.md +612 -0
  253. package/get-shit-done/references/verify-mvp-mode.md +85 -0
  254. package/get-shit-done/references/workstream-flag.md +111 -0
  255. package/get-shit-done/references/worktree-path-safety.md +89 -0
  256. package/get-shit-done/templates/AI-SPEC.md +246 -0
  257. package/get-shit-done/templates/DEBUG.md +169 -0
  258. package/get-shit-done/templates/README.md +77 -0
  259. package/get-shit-done/templates/SECURITY.md +61 -0
  260. package/get-shit-done/templates/UAT.md +265 -0
  261. package/get-shit-done/templates/UI-SPEC.md +100 -0
  262. package/get-shit-done/templates/VALIDATION.md +76 -0
  263. package/get-shit-done/templates/claude-md.md +145 -0
  264. package/get-shit-done/templates/codebase/architecture.md +255 -0
  265. package/get-shit-done/templates/codebase/concerns.md +310 -0
  266. package/get-shit-done/templates/codebase/conventions.md +307 -0
  267. package/get-shit-done/templates/codebase/integrations.md +280 -0
  268. package/get-shit-done/templates/codebase/stack.md +186 -0
  269. package/get-shit-done/templates/codebase/structure.md +285 -0
  270. package/get-shit-done/templates/codebase/testing.md +480 -0
  271. package/get-shit-done/templates/config.json +62 -0
  272. package/get-shit-done/templates/context.md +352 -0
  273. package/get-shit-done/templates/continue-here.md +78 -0
  274. package/get-shit-done/templates/copilot-instructions.md +7 -0
  275. package/get-shit-done/templates/debug-subagent-prompt.md +91 -0
  276. package/get-shit-done/templates/dev-preferences.md +21 -0
  277. package/get-shit-done/templates/discovery.md +146 -0
  278. package/get-shit-done/templates/discussion-log.md +63 -0
  279. package/get-shit-done/templates/milestone-archive.md +123 -0
  280. package/get-shit-done/templates/milestone.md +115 -0
  281. package/get-shit-done/templates/phase-prompt.md +610 -0
  282. package/get-shit-done/templates/planner-subagent-prompt.md +117 -0
  283. package/get-shit-done/templates/project.md +186 -0
  284. package/get-shit-done/templates/requirements.md +231 -0
  285. package/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
  286. package/get-shit-done/templates/research-project/FEATURES.md +147 -0
  287. package/get-shit-done/templates/research-project/PITFALLS.md +200 -0
  288. package/get-shit-done/templates/research-project/STACK.md +120 -0
  289. package/get-shit-done/templates/research-project/SUMMARY.md +170 -0
  290. package/get-shit-done/templates/research.md +592 -0
  291. package/get-shit-done/templates/retrospective.md +54 -0
  292. package/get-shit-done/templates/roadmap.md +202 -0
  293. package/get-shit-done/templates/spec.md +307 -0
  294. package/get-shit-done/templates/state.md +184 -0
  295. package/get-shit-done/templates/summary-complex.md +59 -0
  296. package/get-shit-done/templates/summary-minimal.md +41 -0
  297. package/get-shit-done/templates/summary-standard.md +48 -0
  298. package/get-shit-done/templates/summary.md +248 -0
  299. package/get-shit-done/templates/user-profile.md +146 -0
  300. package/get-shit-done/templates/user-setup.md +311 -0
  301. package/get-shit-done/templates/verification-report.md +322 -0
  302. package/get-shit-done/workflows/add-backlog.md +101 -0
  303. package/get-shit-done/workflows/add-phase.md +123 -0
  304. package/get-shit-done/workflows/add-tests.md +365 -0
  305. package/get-shit-done/workflows/add-todo.md +171 -0
  306. package/get-shit-done/workflows/ai-integration-phase.md +305 -0
  307. package/get-shit-done/workflows/analyze-dependencies.md +96 -0
  308. package/get-shit-done/workflows/audit-fix.md +188 -0
  309. package/get-shit-done/workflows/audit-milestone.md +368 -0
  310. package/get-shit-done/workflows/audit-uat.md +120 -0
  311. package/get-shit-done/workflows/autonomous.md +805 -0
  312. package/get-shit-done/workflows/check-todos.md +190 -0
  313. package/get-shit-done/workflows/cleanup.md +165 -0
  314. package/get-shit-done/workflows/code-review-fix.md +512 -0
  315. package/get-shit-done/workflows/code-review.md +666 -0
  316. package/get-shit-done/workflows/complete-milestone.md +865 -0
  317. package/get-shit-done/workflows/debug.md +242 -0
  318. package/get-shit-done/workflows/diagnose-issues.md +251 -0
  319. package/get-shit-done/workflows/discovery-phase.md +291 -0
  320. package/get-shit-done/workflows/discuss-phase/modes/advisor.md +175 -0
  321. package/get-shit-done/workflows/discuss-phase/modes/all.md +28 -0
  322. package/get-shit-done/workflows/discuss-phase/modes/analyze.md +44 -0
  323. package/get-shit-done/workflows/discuss-phase/modes/auto.md +56 -0
  324. package/get-shit-done/workflows/discuss-phase/modes/batch.md +52 -0
  325. package/get-shit-done/workflows/discuss-phase/modes/chain.md +97 -0
  326. package/get-shit-done/workflows/discuss-phase/modes/default.md +141 -0
  327. package/get-shit-done/workflows/discuss-phase/modes/power.md +44 -0
  328. package/get-shit-done/workflows/discuss-phase/modes/text.md +55 -0
  329. package/get-shit-done/workflows/discuss-phase/templates/checkpoint.json +18 -0
  330. package/get-shit-done/workflows/discuss-phase/templates/context.md +136 -0
  331. package/get-shit-done/workflows/discuss-phase/templates/discussion-log.md +50 -0
  332. package/get-shit-done/workflows/discuss-phase-assumptions.md +685 -0
  333. package/get-shit-done/workflows/discuss-phase-power.md +291 -0
  334. package/get-shit-done/workflows/discuss-phase.md +499 -0
  335. package/get-shit-done/workflows/do.md +122 -0
  336. package/get-shit-done/workflows/docs-update.md +1172 -0
  337. package/get-shit-done/workflows/edit-phase.md +305 -0
  338. package/get-shit-done/workflows/eval-review.md +166 -0
  339. package/get-shit-done/workflows/execute-phase/steps/codebase-drift-gate.md +81 -0
  340. package/get-shit-done/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
  341. package/get-shit-done/workflows/execute-phase/steps/post-merge-gate.md +116 -0
  342. package/get-shit-done/workflows/execute-phase.md +1717 -0
  343. package/get-shit-done/workflows/execute-plan.md +536 -0
  344. package/get-shit-done/workflows/explore.md +154 -0
  345. package/get-shit-done/workflows/extract-learnings.md +253 -0
  346. package/get-shit-done/workflows/fast.md +124 -0
  347. package/get-shit-done/workflows/forensics.md +289 -0
  348. package/get-shit-done/workflows/graduation.md +206 -0
  349. package/get-shit-done/workflows/health.md +234 -0
  350. package/get-shit-done/workflows/help/modes/brief.md +22 -0
  351. package/get-shit-done/workflows/help/modes/default.md +50 -0
  352. package/get-shit-done/workflows/help/modes/full.md +784 -0
  353. package/get-shit-done/workflows/help/modes/topic.md +74 -0
  354. package/get-shit-done/workflows/help.md +24 -0
  355. package/get-shit-done/workflows/import.md +264 -0
  356. package/get-shit-done/workflows/inbox.md +387 -0
  357. package/get-shit-done/workflows/ingest-docs.md +339 -0
  358. package/get-shit-done/workflows/insert-phase.md +162 -0
  359. package/get-shit-done/workflows/list-phase-assumptions.md +178 -0
  360. package/get-shit-done/workflows/list-workspaces.md +67 -0
  361. package/get-shit-done/workflows/manager.md +403 -0
  362. package/get-shit-done/workflows/map-codebase.md +454 -0
  363. package/get-shit-done/workflows/milestone-summary.md +234 -0
  364. package/get-shit-done/workflows/mvp-phase.md +232 -0
  365. package/get-shit-done/workflows/new-milestone.md +645 -0
  366. package/get-shit-done/workflows/new-project.md +1487 -0
  367. package/get-shit-done/workflows/new-workspace.md +250 -0
  368. package/get-shit-done/workflows/next.md +231 -0
  369. package/get-shit-done/workflows/node-repair.md +92 -0
  370. package/get-shit-done/workflows/note.md +158 -0
  371. package/get-shit-done/workflows/pause-work.md +254 -0
  372. package/get-shit-done/workflows/plan-milestone-gaps.md +291 -0
  373. package/get-shit-done/workflows/plan-phase.md +1800 -0
  374. package/get-shit-done/workflows/plan-review-convergence.md +340 -0
  375. package/get-shit-done/workflows/plant-seed.md +240 -0
  376. package/get-shit-done/workflows/pr-branch.md +157 -0
  377. package/get-shit-done/workflows/profile-user.md +463 -0
  378. package/get-shit-done/workflows/progress.md +660 -0
  379. package/get-shit-done/workflows/quick.md +1049 -0
  380. package/get-shit-done/workflows/reapply-patches.md +426 -0
  381. package/get-shit-done/workflows/remove-phase.md +166 -0
  382. package/get-shit-done/workflows/remove-workspace.md +118 -0
  383. package/get-shit-done/workflows/resume-project.md +342 -0
  384. package/get-shit-done/workflows/review.md +633 -0
  385. package/get-shit-done/workflows/scan.md +115 -0
  386. package/get-shit-done/workflows/secure-phase.md +190 -0
  387. package/get-shit-done/workflows/session-report.md +146 -0
  388. package/get-shit-done/workflows/settings-advanced.md +590 -0
  389. package/get-shit-done/workflows/settings-integrations.md +292 -0
  390. package/get-shit-done/workflows/settings.md +545 -0
  391. package/get-shit-done/workflows/ship.md +366 -0
  392. package/get-shit-done/workflows/sketch-wrap-up.md +296 -0
  393. package/get-shit-done/workflows/sketch.md +371 -0
  394. package/get-shit-done/workflows/spec-phase.md +262 -0
  395. package/get-shit-done/workflows/spike-wrap-up.md +317 -0
  396. package/get-shit-done/workflows/spike.md +463 -0
  397. package/get-shit-done/workflows/stats.md +90 -0
  398. package/get-shit-done/workflows/sync-skills.md +182 -0
  399. package/get-shit-done/workflows/thread.md +232 -0
  400. package/get-shit-done/workflows/transition.md +704 -0
  401. package/get-shit-done/workflows/ui-phase.md +338 -0
  402. package/get-shit-done/workflows/ui-review.md +203 -0
  403. package/get-shit-done/workflows/ultraplan-phase.md +209 -0
  404. package/get-shit-done/workflows/undo.md +314 -0
  405. package/get-shit-done/workflows/update.md +664 -0
  406. package/get-shit-done/workflows/validate-phase.md +189 -0
  407. package/get-shit-done/workflows/verify-phase.md +554 -0
  408. package/get-shit-done/workflows/verify-work.md +791 -0
  409. package/hooks/dist/gsd-check-update-worker.js +117 -0
  410. package/hooks/dist/gsd-check-update.js +64 -0
  411. package/hooks/dist/gsd-context-monitor.js +192 -0
  412. package/hooks/dist/gsd-graphify-update.sh +158 -0
  413. package/hooks/dist/gsd-phase-boundary.sh +47 -0
  414. package/hooks/dist/gsd-prompt-guard.js +97 -0
  415. package/hooks/dist/gsd-read-guard.js +101 -0
  416. package/hooks/dist/gsd-read-injection-scanner.js +152 -0
  417. package/hooks/dist/gsd-session-state.sh +59 -0
  418. package/hooks/dist/gsd-statusline.js +537 -0
  419. package/hooks/dist/gsd-update-banner.js +134 -0
  420. package/hooks/dist/gsd-validate-commit.sh +57 -0
  421. package/hooks/dist/gsd-workflow-guard.js +94 -0
  422. package/hooks/dist/lib/git-cmd.js +150 -0
  423. package/hooks/dist/lib/gsd-graphify-rebuild.sh +65 -0
  424. package/hooks/gsd-check-update-worker.js +117 -0
  425. package/hooks/gsd-check-update.js +64 -0
  426. package/hooks/gsd-context-monitor.js +192 -0
  427. package/hooks/gsd-graphify-update.sh +158 -0
  428. package/hooks/gsd-phase-boundary.sh +47 -0
  429. package/hooks/gsd-prompt-guard.js +97 -0
  430. package/hooks/gsd-read-guard.js +101 -0
  431. package/hooks/gsd-read-injection-scanner.js +152 -0
  432. package/hooks/gsd-session-state.sh +59 -0
  433. package/hooks/gsd-statusline.js +537 -0
  434. package/hooks/gsd-update-banner.js +134 -0
  435. package/hooks/gsd-validate-commit.sh +57 -0
  436. package/hooks/gsd-workflow-guard.js +94 -0
  437. package/hooks/lib/git-cmd.js +150 -0
  438. package/hooks/lib/gsd-graphify-rebuild.sh +65 -0
  439. package/package.json +98 -0
  440. package/scripts/audit-workflow-script-paths.cjs +73 -0
  441. package/scripts/base64-scan.sh +262 -0
  442. package/scripts/build-hooks.js +227 -0
  443. package/scripts/changeset/cli.cjs +408 -0
  444. package/scripts/changeset/github-release-notes.cjs +198 -0
  445. package/scripts/changeset/lint.cjs +110 -0
  446. package/scripts/changeset/new.cjs +137 -0
  447. package/scripts/changeset/parse.cjs +114 -0
  448. package/scripts/changeset/render.cjs +34 -0
  449. package/scripts/changeset/serialize.cjs +130 -0
  450. package/scripts/command-contract-helpers.cjs +64 -0
  451. package/scripts/diff-touches-shipped-paths.cjs +147 -0
  452. package/scripts/fix-slash-commands.cjs +147 -0
  453. package/scripts/gen-inventory-manifest.cjs +109 -0
  454. package/scripts/lint-command-contract.cjs +108 -0
  455. package/scripts/lint-descriptions.cjs +83 -0
  456. package/scripts/lint-docs-required.cjs +222 -0
  457. package/scripts/lint-no-source-grep-extras.cjs +81 -0
  458. package/scripts/lint-no-source-grep.cjs +174 -0
  459. package/scripts/lint-pr-check-project-dir.cjs +98 -0
  460. package/scripts/lint-shared-module-handsync.cjs +331 -0
  461. package/scripts/lint-shell-command-projection-drift.cjs +57 -0
  462. package/scripts/lint-skill-deps.cjs +180 -0
  463. package/scripts/lint-test-file-count.allowlist.json +35 -0
  464. package/scripts/lint-test-file-count.cjs +190 -0
  465. package/scripts/pr-template-policy.cjs +268 -0
  466. package/scripts/prompt-injection-scan.sh +203 -0
  467. package/scripts/release-tarball-smoke.cjs +677 -0
  468. package/scripts/run-tests.cjs +178 -0
  469. package/scripts/secret-scan.sh +229 -0
  470. package/scripts/shared-module-handsync-allowlist.json +145 -0
  471. package/scripts/strip-prose-atrefs.cjs +106 -0
  472. package/scripts/sync-rulesets.sh +34 -0
  473. package/scripts/verify-tarball-sdk-dist.sh +69 -0
  474. package/sdk/dist/cli-transport.d.ts +19 -0
  475. package/sdk/dist/cli-transport.d.ts.map +1 -0
  476. package/sdk/dist/cli-transport.js +104 -0
  477. package/sdk/dist/cli-transport.js.map +1 -0
  478. package/sdk/dist/cli.d.ts +46 -0
  479. package/sdk/dist/cli.d.ts.map +1 -0
  480. package/sdk/dist/cli.js +511 -0
  481. package/sdk/dist/cli.js.map +1 -0
  482. package/sdk/dist/config.d.ts +108 -0
  483. package/sdk/dist/config.d.ts.map +1 -0
  484. package/sdk/dist/config.js +116 -0
  485. package/sdk/dist/config.js.map +1 -0
  486. package/sdk/dist/configuration/index.d.ts +85 -0
  487. package/sdk/dist/configuration/index.d.ts.map +1 -0
  488. package/sdk/dist/configuration/index.js +257 -0
  489. package/sdk/dist/configuration/index.js.map +1 -0
  490. package/sdk/dist/context-engine.d.ts +49 -0
  491. package/sdk/dist/context-engine.d.ts.map +1 -0
  492. package/sdk/dist/context-engine.js +142 -0
  493. package/sdk/dist/context-engine.js.map +1 -0
  494. package/sdk/dist/context-truncation.d.ts +33 -0
  495. package/sdk/dist/context-truncation.d.ts.map +1 -0
  496. package/sdk/dist/context-truncation.js +197 -0
  497. package/sdk/dist/context-truncation.js.map +1 -0
  498. package/sdk/dist/errors.d.ts +46 -0
  499. package/sdk/dist/errors.d.ts.map +1 -0
  500. package/sdk/dist/errors.js +64 -0
  501. package/sdk/dist/errors.js.map +1 -0
  502. package/sdk/dist/event-stream.d.ts +53 -0
  503. package/sdk/dist/event-stream.d.ts.map +1 -0
  504. package/sdk/dist/event-stream.js +321 -0
  505. package/sdk/dist/event-stream.js.map +1 -0
  506. package/sdk/dist/golden/capture.d.ts +15 -0
  507. package/sdk/dist/golden/capture.d.ts.map +1 -0
  508. package/sdk/dist/golden/capture.js +67 -0
  509. package/sdk/dist/golden/capture.js.map +1 -0
  510. package/sdk/dist/golden/golden-integration-covered.d.ts +6 -0
  511. package/sdk/dist/golden/golden-integration-covered.d.ts.map +1 -0
  512. package/sdk/dist/golden/golden-integration-covered.js +30 -0
  513. package/sdk/dist/golden/golden-integration-covered.js.map +1 -0
  514. package/sdk/dist/golden/golden-mutation-covered.d.ts +7 -0
  515. package/sdk/dist/golden/golden-mutation-covered.d.ts.map +1 -0
  516. package/sdk/dist/golden/golden-mutation-covered.js +17 -0
  517. package/sdk/dist/golden/golden-mutation-covered.js.map +1 -0
  518. package/sdk/dist/golden/golden-policy.d.ts +10 -0
  519. package/sdk/dist/golden/golden-policy.d.ts.map +1 -0
  520. package/sdk/dist/golden/golden-policy.js +98 -0
  521. package/sdk/dist/golden/golden-policy.js.map +1 -0
  522. package/sdk/dist/golden/init-golden-normalize.d.ts +8 -0
  523. package/sdk/dist/golden/init-golden-normalize.d.ts.map +1 -0
  524. package/sdk/dist/golden/init-golden-normalize.js +14 -0
  525. package/sdk/dist/golden/init-golden-normalize.js.map +1 -0
  526. package/sdk/dist/golden/read-only-golden-rows.d.ts +20 -0
  527. package/sdk/dist/golden/read-only-golden-rows.d.ts.map +1 -0
  528. package/sdk/dist/golden/read-only-golden-rows.js +67 -0
  529. package/sdk/dist/golden/read-only-golden-rows.js.map +1 -0
  530. package/sdk/dist/golden/registry-canonical-commands.d.ts +6 -0
  531. package/sdk/dist/golden/registry-canonical-commands.d.ts.map +1 -0
  532. package/sdk/dist/golden/registry-canonical-commands.js +30 -0
  533. package/sdk/dist/golden/registry-canonical-commands.js.map +1 -0
  534. package/sdk/dist/gsd-tools-error.d.ts +23 -0
  535. package/sdk/dist/gsd-tools-error.d.ts.map +1 -0
  536. package/sdk/dist/gsd-tools-error.js +29 -0
  537. package/sdk/dist/gsd-tools-error.js.map +1 -0
  538. package/sdk/dist/gsd-tools.d.ts +97 -0
  539. package/sdk/dist/gsd-tools.d.ts.map +1 -0
  540. package/sdk/dist/gsd-tools.js +168 -0
  541. package/sdk/dist/gsd-tools.js.map +1 -0
  542. package/sdk/dist/gsd-transport-policy.d.ts +10 -0
  543. package/sdk/dist/gsd-transport-policy.d.ts.map +1 -0
  544. package/sdk/dist/gsd-transport-policy.js +32 -0
  545. package/sdk/dist/gsd-transport-policy.js.map +1 -0
  546. package/sdk/dist/gsd-transport.d.ts +39 -0
  547. package/sdk/dist/gsd-transport.d.ts.map +1 -0
  548. package/sdk/dist/gsd-transport.js +78 -0
  549. package/sdk/dist/gsd-transport.js.map +1 -0
  550. package/sdk/dist/index.d.ts +127 -0
  551. package/sdk/dist/index.d.ts.map +1 -0
  552. package/sdk/dist/index.js +300 -0
  553. package/sdk/dist/index.js.map +1 -0
  554. package/sdk/dist/init-runner.d.ts +90 -0
  555. package/sdk/dist/init-runner.d.ts.map +1 -0
  556. package/sdk/dist/init-runner.js +613 -0
  557. package/sdk/dist/init-runner.js.map +1 -0
  558. package/sdk/dist/logger.d.ts +50 -0
  559. package/sdk/dist/logger.d.ts.map +1 -0
  560. package/sdk/dist/logger.js +70 -0
  561. package/sdk/dist/logger.js.map +1 -0
  562. package/sdk/dist/model-catalog.d.ts +31 -0
  563. package/sdk/dist/model-catalog.d.ts.map +1 -0
  564. package/sdk/dist/model-catalog.js +31 -0
  565. package/sdk/dist/model-catalog.js.map +1 -0
  566. package/sdk/dist/phase-prompt.d.ts +72 -0
  567. package/sdk/dist/phase-prompt.d.ts.map +1 -0
  568. package/sdk/dist/phase-prompt.js +213 -0
  569. package/sdk/dist/phase-prompt.js.map +1 -0
  570. package/sdk/dist/phase-runner.d.ts +145 -0
  571. package/sdk/dist/phase-runner.d.ts.map +1 -0
  572. package/sdk/dist/phase-runner.js +1206 -0
  573. package/sdk/dist/phase-runner.js.map +1 -0
  574. package/sdk/dist/plan-parser.d.ts +55 -0
  575. package/sdk/dist/plan-parser.d.ts.map +1 -0
  576. package/sdk/dist/plan-parser.js +389 -0
  577. package/sdk/dist/plan-parser.js.map +1 -0
  578. package/sdk/dist/planning-journal.d.ts +64 -0
  579. package/sdk/dist/planning-journal.d.ts.map +1 -0
  580. package/sdk/dist/planning-journal.js +88 -0
  581. package/sdk/dist/planning-journal.js.map +1 -0
  582. package/sdk/dist/planning-runtime.d.ts +67 -0
  583. package/sdk/dist/planning-runtime.d.ts.map +1 -0
  584. package/sdk/dist/planning-runtime.js +58 -0
  585. package/sdk/dist/planning-runtime.js.map +1 -0
  586. package/sdk/dist/project-root/index.d.ts +46 -0
  587. package/sdk/dist/project-root/index.d.ts.map +1 -0
  588. package/sdk/dist/project-root/index.js +138 -0
  589. package/sdk/dist/project-root/index.js.map +1 -0
  590. package/sdk/dist/prompt-builder.d.ts +44 -0
  591. package/sdk/dist/prompt-builder.d.ts.map +1 -0
  592. package/sdk/dist/prompt-builder.js +180 -0
  593. package/sdk/dist/prompt-builder.js.map +1 -0
  594. package/sdk/dist/prompt-sanitizer.d.ts +35 -0
  595. package/sdk/dist/prompt-sanitizer.d.ts.map +1 -0
  596. package/sdk/dist/prompt-sanitizer.js +101 -0
  597. package/sdk/dist/prompt-sanitizer.js.map +1 -0
  598. package/sdk/dist/query/active-workstream-store.d.ts +7 -0
  599. package/sdk/dist/query/active-workstream-store.d.ts.map +1 -0
  600. package/sdk/dist/query/active-workstream-store.js +56 -0
  601. package/sdk/dist/query/active-workstream-store.js.map +1 -0
  602. package/sdk/dist/query/agent-failure-classifier.d.ts +38 -0
  603. package/sdk/dist/query/agent-failure-classifier.d.ts.map +1 -0
  604. package/sdk/dist/query/agent-failure-classifier.js +83 -0
  605. package/sdk/dist/query/agent-failure-classifier.js.map +1 -0
  606. package/sdk/dist/query/audit-open.d.ts +46 -0
  607. package/sdk/dist/query/audit-open.d.ts.map +1 -0
  608. package/sdk/dist/query/audit-open.js +662 -0
  609. package/sdk/dist/query/audit-open.js.map +1 -0
  610. package/sdk/dist/query/check-auto-mode.d.ts +13 -0
  611. package/sdk/dist/query/check-auto-mode.d.ts.map +1 -0
  612. package/sdk/dist/query/check-auto-mode.js +40 -0
  613. package/sdk/dist/query/check-auto-mode.js.map +1 -0
  614. package/sdk/dist/query/check-completion.d.ts +10 -0
  615. package/sdk/dist/query/check-completion.d.ts.map +1 -0
  616. package/sdk/dist/query/check-completion.js +157 -0
  617. package/sdk/dist/query/check-completion.js.map +1 -0
  618. package/sdk/dist/query/check-decision-coverage.d.ts +33 -0
  619. package/sdk/dist/query/check-decision-coverage.d.ts.map +1 -0
  620. package/sdk/dist/query/check-decision-coverage.js +472 -0
  621. package/sdk/dist/query/check-decision-coverage.js.map +1 -0
  622. package/sdk/dist/query/check-gates.d.ts +10 -0
  623. package/sdk/dist/query/check-gates.d.ts.map +1 -0
  624. package/sdk/dist/query/check-gates.js +89 -0
  625. package/sdk/dist/query/check-gates.js.map +1 -0
  626. package/sdk/dist/query/check-ship-ready.d.ts +17 -0
  627. package/sdk/dist/query/check-ship-ready.d.ts.map +1 -0
  628. package/sdk/dist/query/check-ship-ready.js +121 -0
  629. package/sdk/dist/query/check-ship-ready.js.map +1 -0
  630. package/sdk/dist/query/check-verification-status.d.ts +10 -0
  631. package/sdk/dist/query/check-verification-status.d.ts.map +1 -0
  632. package/sdk/dist/query/check-verification-status.js +142 -0
  633. package/sdk/dist/query/check-verification-status.js.map +1 -0
  634. package/sdk/dist/query/command-aliases.generated.d.ts +31 -0
  635. package/sdk/dist/query/command-aliases.generated.d.ts.map +1 -0
  636. package/sdk/dist/query/command-aliases.generated.js +133 -0
  637. package/sdk/dist/query/command-aliases.generated.js.map +1 -0
  638. package/sdk/dist/query/command-catalog.d.ts +9 -0
  639. package/sdk/dist/query/command-catalog.d.ts.map +1 -0
  640. package/sdk/dist/query/command-catalog.js +17 -0
  641. package/sdk/dist/query/command-catalog.js.map +1 -0
  642. package/sdk/dist/query/command-definition.d.ts +19 -0
  643. package/sdk/dist/query/command-definition.d.ts.map +1 -0
  644. package/sdk/dist/query/command-definition.js +44 -0
  645. package/sdk/dist/query/command-definition.js.map +1 -0
  646. package/sdk/dist/query/command-family-handlers.d.ts +3 -0
  647. package/sdk/dist/query/command-family-handlers.d.ts.map +1 -0
  648. package/sdk/dist/query/command-family-handlers.js +101 -0
  649. package/sdk/dist/query/command-family-handlers.js.map +1 -0
  650. package/sdk/dist/query/command-manifest.d.ts +2 -0
  651. package/sdk/dist/query/command-manifest.d.ts.map +1 -0
  652. package/sdk/dist/query/command-manifest.init.d.ts +6 -0
  653. package/sdk/dist/query/command-manifest.init.d.ts.map +1 -0
  654. package/sdk/dist/query/command-manifest.init.js +23 -0
  655. package/sdk/dist/query/command-manifest.init.js.map +1 -0
  656. package/sdk/dist/query/command-manifest.js +17 -0
  657. package/sdk/dist/query/command-manifest.js.map +1 -0
  658. package/sdk/dist/query/command-manifest.non-family.d.ts +9 -0
  659. package/sdk/dist/query/command-manifest.non-family.d.ts.map +1 -0
  660. package/sdk/dist/query/command-manifest.non-family.js +60 -0
  661. package/sdk/dist/query/command-manifest.non-family.js.map +1 -0
  662. package/sdk/dist/query/command-manifest.phase.d.ts +6 -0
  663. package/sdk/dist/query/command-manifest.phase.d.ts.map +1 -0
  664. package/sdk/dist/query/command-manifest.phase.js +16 -0
  665. package/sdk/dist/query/command-manifest.phase.js.map +1 -0
  666. package/sdk/dist/query/command-manifest.phases.d.ts +7 -0
  667. package/sdk/dist/query/command-manifest.phases.d.ts.map +1 -0
  668. package/sdk/dist/query/command-manifest.phases.js +10 -0
  669. package/sdk/dist/query/command-manifest.phases.js.map +1 -0
  670. package/sdk/dist/query/command-manifest.roadmap.d.ts +6 -0
  671. package/sdk/dist/query/command-manifest.roadmap.d.ts.map +1 -0
  672. package/sdk/dist/query/command-manifest.roadmap.js +10 -0
  673. package/sdk/dist/query/command-manifest.roadmap.js.map +1 -0
  674. package/sdk/dist/query/command-manifest.state.d.ts +9 -0
  675. package/sdk/dist/query/command-manifest.state.d.ts.map +1 -0
  676. package/sdk/dist/query/command-manifest.state.js +30 -0
  677. package/sdk/dist/query/command-manifest.state.js.map +1 -0
  678. package/sdk/dist/query/command-manifest.types.d.ts +12 -0
  679. package/sdk/dist/query/command-manifest.types.d.ts.map +1 -0
  680. package/sdk/dist/query/command-manifest.types.js +2 -0
  681. package/sdk/dist/query/command-manifest.types.js.map +1 -0
  682. package/sdk/dist/query/command-manifest.validate.d.ts +6 -0
  683. package/sdk/dist/query/command-manifest.validate.d.ts.map +1 -0
  684. package/sdk/dist/query/command-manifest.validate.js +10 -0
  685. package/sdk/dist/query/command-manifest.validate.js.map +1 -0
  686. package/sdk/dist/query/command-manifest.verify.d.ts +6 -0
  687. package/sdk/dist/query/command-manifest.verify.d.ts.map +1 -0
  688. package/sdk/dist/query/command-manifest.verify.js +16 -0
  689. package/sdk/dist/query/command-manifest.verify.js.map +1 -0
  690. package/sdk/dist/query/command-static-catalog-domain.d.ts +3 -0
  691. package/sdk/dist/query/command-static-catalog-domain.d.ts.map +1 -0
  692. package/sdk/dist/query/command-static-catalog-domain.js +110 -0
  693. package/sdk/dist/query/command-static-catalog-domain.js.map +1 -0
  694. package/sdk/dist/query/command-static-catalog-foundation.d.ts +7 -0
  695. package/sdk/dist/query/command-static-catalog-foundation.d.ts.map +1 -0
  696. package/sdk/dist/query/command-static-catalog-foundation.js +106 -0
  697. package/sdk/dist/query/command-static-catalog-foundation.js.map +1 -0
  698. package/sdk/dist/query/command-topology.d.ts +32 -0
  699. package/sdk/dist/query/command-topology.d.ts.map +1 -0
  700. package/sdk/dist/query/command-topology.js +66 -0
  701. package/sdk/dist/query/command-topology.js.map +1 -0
  702. package/sdk/dist/query/commands-list.d.ts +14 -0
  703. package/sdk/dist/query/commands-list.d.ts.map +1 -0
  704. package/sdk/dist/query/commands-list.js +18 -0
  705. package/sdk/dist/query/commands-list.js.map +1 -0
  706. package/sdk/dist/query/commit.d.ts +179 -0
  707. package/sdk/dist/query/commit.d.ts.map +1 -0
  708. package/sdk/dist/query/commit.js +632 -0
  709. package/sdk/dist/query/commit.js.map +1 -0
  710. package/sdk/dist/query/config-gates.d.ts +12 -0
  711. package/sdk/dist/query/config-gates.d.ts.map +1 -0
  712. package/sdk/dist/query/config-gates.js +66 -0
  713. package/sdk/dist/query/config-gates.js.map +1 -0
  714. package/sdk/dist/query/config-mutation.d.ts +86 -0
  715. package/sdk/dist/query/config-mutation.d.ts.map +1 -0
  716. package/sdk/dist/query/config-mutation.js +602 -0
  717. package/sdk/dist/query/config-mutation.js.map +1 -0
  718. package/sdk/dist/query/config-query.d.ts +57 -0
  719. package/sdk/dist/query/config-query.d.ts.map +1 -0
  720. package/sdk/dist/query/config-query.js +277 -0
  721. package/sdk/dist/query/config-query.js.map +1 -0
  722. package/sdk/dist/query/config-schema.d.ts +19 -0
  723. package/sdk/dist/query/config-schema.d.ts.map +1 -0
  724. package/sdk/dist/query/config-schema.js +26 -0
  725. package/sdk/dist/query/config-schema.js.map +1 -0
  726. package/sdk/dist/query/decisions.d.ts +58 -0
  727. package/sdk/dist/query/decisions.d.ts.map +1 -0
  728. package/sdk/dist/query/decisions.js +165 -0
  729. package/sdk/dist/query/decisions.js.map +1 -0
  730. package/sdk/dist/query/detect-custom-files.d.ts +11 -0
  731. package/sdk/dist/query/detect-custom-files.d.ts.map +1 -0
  732. package/sdk/dist/query/detect-custom-files.js +89 -0
  733. package/sdk/dist/query/detect-custom-files.js.map +1 -0
  734. package/sdk/dist/query/detect-phase-type.d.ts +9 -0
  735. package/sdk/dist/query/detect-phase-type.d.ts.map +1 -0
  736. package/sdk/dist/query/detect-phase-type.js +124 -0
  737. package/sdk/dist/query/detect-phase-type.js.map +1 -0
  738. package/sdk/dist/query/docs-init.d.ts +26 -0
  739. package/sdk/dist/query/docs-init.d.ts.map +1 -0
  740. package/sdk/dist/query/docs-init.js +231 -0
  741. package/sdk/dist/query/docs-init.js.map +1 -0
  742. package/sdk/dist/query/fallow-audit.d.ts +44 -0
  743. package/sdk/dist/query/fallow-audit.d.ts.map +1 -0
  744. package/sdk/dist/query/fallow-audit.js +44 -0
  745. package/sdk/dist/query/fallow-audit.js.map +1 -0
  746. package/sdk/dist/query/frontmatter-mutation.d.ts +77 -0
  747. package/sdk/dist/query/frontmatter-mutation.d.ts.map +1 -0
  748. package/sdk/dist/query/frontmatter-mutation.js +299 -0
  749. package/sdk/dist/query/frontmatter-mutation.js.map +1 -0
  750. package/sdk/dist/query/frontmatter.d.ts +93 -0
  751. package/sdk/dist/query/frontmatter.d.ts.map +1 -0
  752. package/sdk/dist/query/frontmatter.js +364 -0
  753. package/sdk/dist/query/frontmatter.js.map +1 -0
  754. package/sdk/dist/query/helpers.d.ts +194 -0
  755. package/sdk/dist/query/helpers.d.ts.map +1 -0
  756. package/sdk/dist/query/helpers.js +540 -0
  757. package/sdk/dist/query/helpers.js.map +1 -0
  758. package/sdk/dist/query/index.d.ts +8 -0
  759. package/sdk/dist/query/index.d.ts.map +1 -0
  760. package/sdk/dist/query/index.js +6 -0
  761. package/sdk/dist/query/index.js.map +1 -0
  762. package/sdk/dist/query/init-complex.d.ts +47 -0
  763. package/sdk/dist/query/init-complex.d.ts.map +1 -0
  764. package/sdk/dist/query/init-complex.js +735 -0
  765. package/sdk/dist/query/init-complex.js.map +1 -0
  766. package/sdk/dist/query/init.d.ts +106 -0
  767. package/sdk/dist/query/init.d.ts.map +1 -0
  768. package/sdk/dist/query/init.js +1228 -0
  769. package/sdk/dist/query/init.js.map +1 -0
  770. package/sdk/dist/query/intel.d.ts +43 -0
  771. package/sdk/dist/query/intel.d.ts.map +1 -0
  772. package/sdk/dist/query/intel.js +416 -0
  773. package/sdk/dist/query/intel.js.map +1 -0
  774. package/sdk/dist/query/mutation-event-decorator.d.ts +5 -0
  775. package/sdk/dist/query/mutation-event-decorator.d.ts.map +1 -0
  776. package/sdk/dist/query/mutation-event-decorator.js +28 -0
  777. package/sdk/dist/query/mutation-event-decorator.js.map +1 -0
  778. package/sdk/dist/query/mutation-event-mapper.d.ts +4 -0
  779. package/sdk/dist/query/mutation-event-mapper.d.ts.map +1 -0
  780. package/sdk/dist/query/mutation-event-mapper.js +70 -0
  781. package/sdk/dist/query/mutation-event-mapper.js.map +1 -0
  782. package/sdk/dist/query/mvp.d.ts +113 -0
  783. package/sdk/dist/query/mvp.d.ts.map +1 -0
  784. package/sdk/dist/query/mvp.js +225 -0
  785. package/sdk/dist/query/mvp.js.map +1 -0
  786. package/sdk/dist/query/phase-filesystem-adapter.d.ts +4 -0
  787. package/sdk/dist/query/phase-filesystem-adapter.d.ts.map +1 -0
  788. package/sdk/dist/query/phase-filesystem-adapter.js +33 -0
  789. package/sdk/dist/query/phase-filesystem-adapter.js.map +1 -0
  790. package/sdk/dist/query/phase-lifecycle-policy.d.ts +34 -0
  791. package/sdk/dist/query/phase-lifecycle-policy.d.ts.map +1 -0
  792. package/sdk/dist/query/phase-lifecycle-policy.js +138 -0
  793. package/sdk/dist/query/phase-lifecycle-policy.js.map +1 -0
  794. package/sdk/dist/query/phase-lifecycle.d.ts +116 -0
  795. package/sdk/dist/query/phase-lifecycle.d.ts.map +1 -0
  796. package/sdk/dist/query/phase-lifecycle.js +1823 -0
  797. package/sdk/dist/query/phase-lifecycle.js.map +1 -0
  798. package/sdk/dist/query/phase-list-queries.d.ts +20 -0
  799. package/sdk/dist/query/phase-list-queries.d.ts.map +1 -0
  800. package/sdk/dist/query/phase-list-queries.js +129 -0
  801. package/sdk/dist/query/phase-list-queries.js.map +1 -0
  802. package/sdk/dist/query/phase-ready.d.ts +9 -0
  803. package/sdk/dist/query/phase-ready.d.ts.map +1 -0
  804. package/sdk/dist/query/phase-ready.js +132 -0
  805. package/sdk/dist/query/phase-ready.js.map +1 -0
  806. package/sdk/dist/query/phase-roadmap-mutation.d.ts +25 -0
  807. package/sdk/dist/query/phase-roadmap-mutation.d.ts.map +1 -0
  808. package/sdk/dist/query/phase-roadmap-mutation.js +76 -0
  809. package/sdk/dist/query/phase-roadmap-mutation.js.map +1 -0
  810. package/sdk/dist/query/phase-uat-passed.d.ts +46 -0
  811. package/sdk/dist/query/phase-uat-passed.d.ts.map +1 -0
  812. package/sdk/dist/query/phase-uat-passed.js +238 -0
  813. package/sdk/dist/query/phase-uat-passed.js.map +1 -0
  814. package/sdk/dist/query/phase.d.ts +104 -0
  815. package/sdk/dist/query/phase.d.ts.map +1 -0
  816. package/sdk/dist/query/phase.js +617 -0
  817. package/sdk/dist/query/phase.js.map +1 -0
  818. package/sdk/dist/query/pipeline.d.ts +53 -0
  819. package/sdk/dist/query/pipeline.d.ts.map +1 -0
  820. package/sdk/dist/query/pipeline.js +198 -0
  821. package/sdk/dist/query/pipeline.js.map +1 -0
  822. package/sdk/dist/query/plan-scan.d.ts +14 -0
  823. package/sdk/dist/query/plan-scan.d.ts.map +1 -0
  824. package/sdk/dist/query/plan-scan.js +70 -0
  825. package/sdk/dist/query/plan-scan.js.map +1 -0
  826. package/sdk/dist/query/plan-task-structure.d.ts +9 -0
  827. package/sdk/dist/query/plan-task-structure.d.ts.map +1 -0
  828. package/sdk/dist/query/plan-task-structure.js +59 -0
  829. package/sdk/dist/query/plan-task-structure.js.map +1 -0
  830. package/sdk/dist/query/profile-extract-messages.d.ts +40 -0
  831. package/sdk/dist/query/profile-extract-messages.d.ts.map +1 -0
  832. package/sdk/dist/query/profile-extract-messages.js +195 -0
  833. package/sdk/dist/query/profile-extract-messages.js.map +1 -0
  834. package/sdk/dist/query/profile-output.d.ts +11 -0
  835. package/sdk/dist/query/profile-output.d.ts.map +1 -0
  836. package/sdk/dist/query/profile-output.js +873 -0
  837. package/sdk/dist/query/profile-output.js.map +1 -0
  838. package/sdk/dist/query/profile-questionnaire-data.d.ts +21 -0
  839. package/sdk/dist/query/profile-questionnaire-data.d.ts.map +1 -0
  840. package/sdk/dist/query/profile-questionnaire-data.js +171 -0
  841. package/sdk/dist/query/profile-questionnaire-data.js.map +1 -0
  842. package/sdk/dist/query/profile-sample.d.ts +22 -0
  843. package/sdk/dist/query/profile-sample.d.ts.map +1 -0
  844. package/sdk/dist/query/profile-sample.js +136 -0
  845. package/sdk/dist/query/profile-sample.js.map +1 -0
  846. package/sdk/dist/query/profile-scan-sessions.d.ts +49 -0
  847. package/sdk/dist/query/profile-scan-sessions.d.ts.map +1 -0
  848. package/sdk/dist/query/profile-scan-sessions.js +137 -0
  849. package/sdk/dist/query/profile-scan-sessions.js.map +1 -0
  850. package/sdk/dist/query/profile.d.ts +61 -0
  851. package/sdk/dist/query/profile.d.ts.map +1 -0
  852. package/sdk/dist/query/profile.js +307 -0
  853. package/sdk/dist/query/profile.js.map +1 -0
  854. package/sdk/dist/query/progress.d.ts +77 -0
  855. package/sdk/dist/query/progress.d.ts.map +1 -0
  856. package/sdk/dist/query/progress.js +481 -0
  857. package/sdk/dist/query/progress.js.map +1 -0
  858. package/sdk/dist/query/prompt-budget.d.ts +14 -0
  859. package/sdk/dist/query/prompt-budget.d.ts.map +1 -0
  860. package/sdk/dist/query/prompt-budget.js +417 -0
  861. package/sdk/dist/query/prompt-budget.js.map +1 -0
  862. package/sdk/dist/query/query-cli-adapter.d.ts +8 -0
  863. package/sdk/dist/query/query-cli-adapter.d.ts.map +1 -0
  864. package/sdk/dist/query/query-cli-adapter.js +32 -0
  865. package/sdk/dist/query/query-cli-adapter.js.map +1 -0
  866. package/sdk/dist/query/query-cli-output.d.ts +9 -0
  867. package/sdk/dist/query/query-cli-output.d.ts.map +1 -0
  868. package/sdk/dist/query/query-cli-output.js +28 -0
  869. package/sdk/dist/query/query-cli-output.js.map +1 -0
  870. package/sdk/dist/query/query-command-diagnosis.d.ts +6 -0
  871. package/sdk/dist/query/query-command-diagnosis.d.ts.map +1 -0
  872. package/sdk/dist/query/query-command-diagnosis.js +6 -0
  873. package/sdk/dist/query/query-command-diagnosis.js.map +1 -0
  874. package/sdk/dist/query/query-command-resolution-strategy.d.ts +29 -0
  875. package/sdk/dist/query/query-command-resolution-strategy.d.ts.map +1 -0
  876. package/sdk/dist/query/query-command-resolution-strategy.js +103 -0
  877. package/sdk/dist/query/query-command-resolution-strategy.js.map +1 -0
  878. package/sdk/dist/query/query-command-semantics.d.ts +7 -0
  879. package/sdk/dist/query/query-command-semantics.d.ts.map +1 -0
  880. package/sdk/dist/query/query-command-semantics.js +7 -0
  881. package/sdk/dist/query/query-command-semantics.js.map +1 -0
  882. package/sdk/dist/query/query-dispatch-contract.d.ts +21 -0
  883. package/sdk/dist/query/query-dispatch-contract.d.ts.map +1 -0
  884. package/sdk/dist/query/query-dispatch-contract.js +2 -0
  885. package/sdk/dist/query/query-dispatch-contract.js.map +1 -0
  886. package/sdk/dist/query/query-dispatch-error-mapper.d.ts +6 -0
  887. package/sdk/dist/query/query-dispatch-error-mapper.d.ts.map +1 -0
  888. package/sdk/dist/query/query-dispatch-error-mapper.js +6 -0
  889. package/sdk/dist/query/query-dispatch-error-mapper.js.map +1 -0
  890. package/sdk/dist/query/query-dispatch-formatting.d.ts +6 -0
  891. package/sdk/dist/query/query-dispatch-formatting.d.ts.map +1 -0
  892. package/sdk/dist/query/query-dispatch-formatting.js +6 -0
  893. package/sdk/dist/query/query-dispatch-formatting.js.map +1 -0
  894. package/sdk/dist/query/query-dispatch-observability.d.ts +2 -0
  895. package/sdk/dist/query/query-dispatch-observability.d.ts.map +1 -0
  896. package/sdk/dist/query/query-dispatch-observability.js +7 -0
  897. package/sdk/dist/query/query-dispatch-observability.js.map +1 -0
  898. package/sdk/dist/query/query-dispatch.d.ts +48 -0
  899. package/sdk/dist/query/query-dispatch.d.ts.map +1 -0
  900. package/sdk/dist/query/query-dispatch.js +175 -0
  901. package/sdk/dist/query/query-dispatch.js.map +1 -0
  902. package/sdk/dist/query/query-error-details-schema.d.ts +19 -0
  903. package/sdk/dist/query/query-error-details-schema.d.ts.map +1 -0
  904. package/sdk/dist/query/query-error-details-schema.js +10 -0
  905. package/sdk/dist/query/query-error-details-schema.js.map +1 -0
  906. package/sdk/dist/query/query-error-taxonomy.d.ts +38 -0
  907. package/sdk/dist/query/query-error-taxonomy.d.ts.map +1 -0
  908. package/sdk/dist/query/query-error-taxonomy.js +74 -0
  909. package/sdk/dist/query/query-error-taxonomy.js.map +1 -0
  910. package/sdk/dist/query/query-fallback-bridge-adapter.d.ts +14 -0
  911. package/sdk/dist/query/query-fallback-bridge-adapter.d.ts.map +1 -0
  912. package/sdk/dist/query/query-fallback-bridge-adapter.js +33 -0
  913. package/sdk/dist/query/query-fallback-bridge-adapter.js.map +1 -0
  914. package/sdk/dist/query/query-fallback-executor.d.ts +11 -0
  915. package/sdk/dist/query/query-fallback-executor.d.ts.map +1 -0
  916. package/sdk/dist/query/query-fallback-executor.js +31 -0
  917. package/sdk/dist/query/query-fallback-executor.js.map +1 -0
  918. package/sdk/dist/query/query-fallback-output-classifier.d.ts +6 -0
  919. package/sdk/dist/query/query-fallback-output-classifier.d.ts.map +1 -0
  920. package/sdk/dist/query/query-fallback-output-classifier.js +27 -0
  921. package/sdk/dist/query/query-fallback-output-classifier.js.map +1 -0
  922. package/sdk/dist/query/query-fallback-policy.d.ts +6 -0
  923. package/sdk/dist/query/query-fallback-policy.d.ts.map +1 -0
  924. package/sdk/dist/query/query-fallback-policy.js +7 -0
  925. package/sdk/dist/query/query-fallback-policy.js.map +1 -0
  926. package/sdk/dist/query/query-native-dispatch-adapter.d.ts +7 -0
  927. package/sdk/dist/query/query-native-dispatch-adapter.d.ts.map +1 -0
  928. package/sdk/dist/query/query-native-dispatch-adapter.js +6 -0
  929. package/sdk/dist/query/query-native-dispatch-adapter.js.map +1 -0
  930. package/sdk/dist/query/query-policy-capability.d.ts +10 -0
  931. package/sdk/dist/query/query-policy-capability.d.ts.map +1 -0
  932. package/sdk/dist/query/query-policy-capability.js +17 -0
  933. package/sdk/dist/query/query-policy-capability.js.map +1 -0
  934. package/sdk/dist/query/query-runtime-context.d.ts +19 -0
  935. package/sdk/dist/query/query-runtime-context.d.ts.map +1 -0
  936. package/sdk/dist/query/query-runtime-context.js +31 -0
  937. package/sdk/dist/query/query-runtime-context.js.map +1 -0
  938. package/sdk/dist/query/query-unknown-command-hints.d.ts +2 -0
  939. package/sdk/dist/query/query-unknown-command-hints.d.ts.map +1 -0
  940. package/sdk/dist/query/query-unknown-command-hints.js +6 -0
  941. package/sdk/dist/query/query-unknown-command-hints.js.map +1 -0
  942. package/sdk/dist/query/registry-assembly-descriptor.d.ts +12 -0
  943. package/sdk/dist/query/registry-assembly-descriptor.d.ts.map +1 -0
  944. package/sdk/dist/query/registry-assembly-descriptor.js +61 -0
  945. package/sdk/dist/query/registry-assembly-descriptor.js.map +1 -0
  946. package/sdk/dist/query/registry-assembly-invariants.d.ts +30 -0
  947. package/sdk/dist/query/registry-assembly-invariants.d.ts.map +1 -0
  948. package/sdk/dist/query/registry-assembly-invariants.js +77 -0
  949. package/sdk/dist/query/registry-assembly-invariants.js.map +1 -0
  950. package/sdk/dist/query/registry-assembly.d.ts +10 -0
  951. package/sdk/dist/query/registry-assembly.d.ts.map +1 -0
  952. package/sdk/dist/query/registry-assembly.js +53 -0
  953. package/sdk/dist/query/registry-assembly.js.map +1 -0
  954. package/sdk/dist/query/registry.d.ts +90 -0
  955. package/sdk/dist/query/registry.d.ts.map +1 -0
  956. package/sdk/dist/query/registry.js +129 -0
  957. package/sdk/dist/query/registry.js.map +1 -0
  958. package/sdk/dist/query/requirements-extract-from-plans.d.ts +9 -0
  959. package/sdk/dist/query/requirements-extract-from-plans.d.ts.map +1 -0
  960. package/sdk/dist/query/requirements-extract-from-plans.js +76 -0
  961. package/sdk/dist/query/requirements-extract-from-plans.js.map +1 -0
  962. package/sdk/dist/query/roadmap-update-plan-progress.d.ts +11 -0
  963. package/sdk/dist/query/roadmap-update-plan-progress.d.ts.map +1 -0
  964. package/sdk/dist/query/roadmap-update-plan-progress.js +124 -0
  965. package/sdk/dist/query/roadmap-update-plan-progress.js.map +1 -0
  966. package/sdk/dist/query/roadmap.d.ts +160 -0
  967. package/sdk/dist/query/roadmap.d.ts.map +1 -0
  968. package/sdk/dist/query/roadmap.js +982 -0
  969. package/sdk/dist/query/roadmap.js.map +1 -0
  970. package/sdk/dist/query/route-next-action.d.ts +9 -0
  971. package/sdk/dist/query/route-next-action.d.ts.map +1 -0
  972. package/sdk/dist/query/route-next-action.js +318 -0
  973. package/sdk/dist/query/route-next-action.js.map +1 -0
  974. package/sdk/dist/query/schema-detect.d.ts +21 -0
  975. package/sdk/dist/query/schema-detect.d.ts.map +1 -0
  976. package/sdk/dist/query/schema-detect.js +146 -0
  977. package/sdk/dist/query/schema-detect.js.map +1 -0
  978. package/sdk/dist/query/secrets.d.ts +27 -0
  979. package/sdk/dist/query/secrets.d.ts.map +1 -0
  980. package/sdk/dist/query/secrets.js +42 -0
  981. package/sdk/dist/query/secrets.js.map +1 -0
  982. package/sdk/dist/query/skill-manifest.d.ts +50 -0
  983. package/sdk/dist/query/skill-manifest.d.ts.map +1 -0
  984. package/sdk/dist/query/skill-manifest.js +171 -0
  985. package/sdk/dist/query/skill-manifest.js.map +1 -0
  986. package/sdk/dist/query/skills.d.ts +27 -0
  987. package/sdk/dist/query/skills.d.ts.map +1 -0
  988. package/sdk/dist/query/skills.js +137 -0
  989. package/sdk/dist/query/skills.js.map +1 -0
  990. package/sdk/dist/query/state-document.d.ts +14 -0
  991. package/sdk/dist/query/state-document.d.ts.map +1 -0
  992. package/sdk/dist/query/state-document.js +110 -0
  993. package/sdk/dist/query/state-document.js.map +1 -0
  994. package/sdk/dist/query/state-mutation.d.ts +224 -0
  995. package/sdk/dist/query/state-mutation.d.ts.map +1 -0
  996. package/sdk/dist/query/state-mutation.js +1635 -0
  997. package/sdk/dist/query/state-mutation.js.map +1 -0
  998. package/sdk/dist/query/state-project-load.d.ts +23 -0
  999. package/sdk/dist/query/state-project-load.d.ts.map +1 -0
  1000. package/sdk/dist/query/state-project-load.js +75 -0
  1001. package/sdk/dist/query/state-project-load.js.map +1 -0
  1002. package/sdk/dist/query/state.d.ts +78 -0
  1003. package/sdk/dist/query/state.d.ts.map +1 -0
  1004. package/sdk/dist/query/state.js +443 -0
  1005. package/sdk/dist/query/state.js.map +1 -0
  1006. package/sdk/dist/query/summary.d.ts +18 -0
  1007. package/sdk/dist/query/summary.d.ts.map +1 -0
  1008. package/sdk/dist/query/summary.js +249 -0
  1009. package/sdk/dist/query/summary.js.map +1 -0
  1010. package/sdk/dist/query/template.d.ts +46 -0
  1011. package/sdk/dist/query/template.d.ts.map +1 -0
  1012. package/sdk/dist/query/template.js +210 -0
  1013. package/sdk/dist/query/template.js.map +1 -0
  1014. package/sdk/dist/query/uat.d.ts +42 -0
  1015. package/sdk/dist/query/uat.d.ts.map +1 -0
  1016. package/sdk/dist/query/uat.js +339 -0
  1017. package/sdk/dist/query/uat.js.map +1 -0
  1018. package/sdk/dist/query/utils.d.ts +59 -0
  1019. package/sdk/dist/query/utils.d.ts.map +1 -0
  1020. package/sdk/dist/query/utils.js +74 -0
  1021. package/sdk/dist/query/utils.js.map +1 -0
  1022. package/sdk/dist/query/validate.d.ts +67 -0
  1023. package/sdk/dist/query/validate.d.ts.map +1 -0
  1024. package/sdk/dist/query/validate.js +1001 -0
  1025. package/sdk/dist/query/validate.js.map +1 -0
  1026. package/sdk/dist/query/verify.d.ts +98 -0
  1027. package/sdk/dist/query/verify.d.ts.map +1 -0
  1028. package/sdk/dist/query/verify.js +593 -0
  1029. package/sdk/dist/query/verify.js.map +1 -0
  1030. package/sdk/dist/query/websearch.d.ts +24 -0
  1031. package/sdk/dist/query/websearch.d.ts.map +1 -0
  1032. package/sdk/dist/query/websearch.js +68 -0
  1033. package/sdk/dist/query/websearch.js.map +1 -0
  1034. package/sdk/dist/query/workspace.d.ts +62 -0
  1035. package/sdk/dist/query/workspace.d.ts.map +1 -0
  1036. package/sdk/dist/query/workspace.js +104 -0
  1037. package/sdk/dist/query/workspace.js.map +1 -0
  1038. package/sdk/dist/query/workstream-inventory.d.ts +24 -0
  1039. package/sdk/dist/query/workstream-inventory.d.ts.map +1 -0
  1040. package/sdk/dist/query/workstream-inventory.js +120 -0
  1041. package/sdk/dist/query/workstream-inventory.js.map +1 -0
  1042. package/sdk/dist/query/workstream.d.ts +35 -0
  1043. package/sdk/dist/query/workstream.d.ts.map +1 -0
  1044. package/sdk/dist/query/workstream.js +298 -0
  1045. package/sdk/dist/query/workstream.js.map +1 -0
  1046. package/sdk/dist/query/worktree.d.ts +9 -0
  1047. package/sdk/dist/query/worktree.d.ts.map +1 -0
  1048. package/sdk/dist/query/worktree.js +79 -0
  1049. package/sdk/dist/query/worktree.js.map +1 -0
  1050. package/sdk/dist/query-command-executor.d.ts +22 -0
  1051. package/sdk/dist/query-command-executor.d.ts.map +1 -0
  1052. package/sdk/dist/query-command-executor.js +22 -0
  1053. package/sdk/dist/query-command-executor.js.map +1 -0
  1054. package/sdk/dist/query-execution-policy.d.ts +24 -0
  1055. package/sdk/dist/query-execution-policy.d.ts.map +1 -0
  1056. package/sdk/dist/query-execution-policy.js +27 -0
  1057. package/sdk/dist/query-execution-policy.js.map +1 -0
  1058. package/sdk/dist/query-failure-classification.d.ts +9 -0
  1059. package/sdk/dist/query-failure-classification.d.ts.map +1 -0
  1060. package/sdk/dist/query-failure-classification.js +32 -0
  1061. package/sdk/dist/query-failure-classification.js.map +1 -0
  1062. package/sdk/dist/query-gsd-tools-path.d.ts +2 -0
  1063. package/sdk/dist/query-gsd-tools-path.d.ts.map +1 -0
  1064. package/sdk/dist/query-gsd-tools-path.js +2 -0
  1065. package/sdk/dist/query-gsd-tools-path.js.map +1 -0
  1066. package/sdk/dist/query-gsd-tools-runtime.d.ts +20 -0
  1067. package/sdk/dist/query-gsd-tools-runtime.d.ts.map +1 -0
  1068. package/sdk/dist/query-gsd-tools-runtime.js +47 -0
  1069. package/sdk/dist/query-gsd-tools-runtime.js.map +1 -0
  1070. package/sdk/dist/query-hotpath-methods.d.ts +19 -0
  1071. package/sdk/dist/query-hotpath-methods.d.ts.map +1 -0
  1072. package/sdk/dist/query-hotpath-methods.js +34 -0
  1073. package/sdk/dist/query-hotpath-methods.js.map +1 -0
  1074. package/sdk/dist/query-native-direct-adapter.d.ts +20 -0
  1075. package/sdk/dist/query-native-direct-adapter.d.ts.map +1 -0
  1076. package/sdk/dist/query-native-direct-adapter.js +52 -0
  1077. package/sdk/dist/query-native-direct-adapter.js.map +1 -0
  1078. package/sdk/dist/query-native-hotpath-adapter.d.ts +15 -0
  1079. package/sdk/dist/query-native-hotpath-adapter.d.ts.map +1 -0
  1080. package/sdk/dist/query-native-hotpath-adapter.js +32 -0
  1081. package/sdk/dist/query-native-hotpath-adapter.js.map +1 -0
  1082. package/sdk/dist/query-raw-output-projection.d.ts +6 -0
  1083. package/sdk/dist/query-raw-output-projection.d.ts.map +1 -0
  1084. package/sdk/dist/query-raw-output-projection.js +86 -0
  1085. package/sdk/dist/query-raw-output-projection.js.map +1 -0
  1086. package/sdk/dist/query-runtime-bridge.d.ts +61 -0
  1087. package/sdk/dist/query-runtime-bridge.d.ts.map +1 -0
  1088. package/sdk/dist/query-runtime-bridge.js +144 -0
  1089. package/sdk/dist/query-runtime-bridge.js.map +1 -0
  1090. package/sdk/dist/query-subprocess-adapter.d.ts +18 -0
  1091. package/sdk/dist/query-subprocess-adapter.d.ts.map +1 -0
  1092. package/sdk/dist/query-subprocess-adapter.js +92 -0
  1093. package/sdk/dist/query-subprocess-adapter.js.map +1 -0
  1094. package/sdk/dist/query-tools-error-factory.d.ts +16 -0
  1095. package/sdk/dist/query-tools-error-factory.d.ts.map +1 -0
  1096. package/sdk/dist/query-tools-error-factory.js +33 -0
  1097. package/sdk/dist/query-tools-error-factory.js.map +1 -0
  1098. package/sdk/dist/research-gate.d.ts +24 -0
  1099. package/sdk/dist/research-gate.d.ts.map +1 -0
  1100. package/sdk/dist/research-gate.js +70 -0
  1101. package/sdk/dist/research-gate.js.map +1 -0
  1102. package/sdk/dist/runtime-bridge-sync/index.d.ts +96 -0
  1103. package/sdk/dist/runtime-bridge-sync/index.d.ts.map +1 -0
  1104. package/sdk/dist/runtime-bridge-sync/index.js +109 -0
  1105. package/sdk/dist/runtime-bridge-sync/index.js.map +1 -0
  1106. package/sdk/dist/runtime-bridge-sync/worker.d.ts +2 -0
  1107. package/sdk/dist/runtime-bridge-sync/worker.d.ts.map +1 -0
  1108. package/sdk/dist/runtime-bridge-sync/worker.js +180 -0
  1109. package/sdk/dist/runtime-bridge-sync/worker.js.map +1 -0
  1110. package/sdk/dist/runtime-gate.d.ts +14 -0
  1111. package/sdk/dist/runtime-gate.d.ts.map +1 -0
  1112. package/sdk/dist/runtime-gate.js +48 -0
  1113. package/sdk/dist/runtime-gate.js.map +1 -0
  1114. package/sdk/dist/sdk-package-compatibility.d.ts +38 -0
  1115. package/sdk/dist/sdk-package-compatibility.d.ts.map +1 -0
  1116. package/sdk/dist/sdk-package-compatibility.js +90 -0
  1117. package/sdk/dist/sdk-package-compatibility.js.map +1 -0
  1118. package/sdk/dist/session-runner.d.ts +40 -0
  1119. package/sdk/dist/session-runner.d.ts.map +1 -0
  1120. package/sdk/dist/session-runner.js +274 -0
  1121. package/sdk/dist/session-runner.js.map +1 -0
  1122. package/sdk/dist/tool-scoping.d.ts +31 -0
  1123. package/sdk/dist/tool-scoping.d.ts.map +1 -0
  1124. package/sdk/dist/tool-scoping.js +54 -0
  1125. package/sdk/dist/tool-scoping.js.map +1 -0
  1126. package/sdk/dist/types.d.ts +794 -0
  1127. package/sdk/dist/types.d.ts.map +1 -0
  1128. package/sdk/dist/types.js +77 -0
  1129. package/sdk/dist/types.js.map +1 -0
  1130. package/sdk/dist/workstream-inventory/builder.d.ts +88 -0
  1131. package/sdk/dist/workstream-inventory/builder.d.ts.map +1 -0
  1132. package/sdk/dist/workstream-inventory/builder.js +84 -0
  1133. package/sdk/dist/workstream-inventory/builder.js.map +1 -0
  1134. package/sdk/dist/workstream-name-policy.d.ts +37 -0
  1135. package/sdk/dist/workstream-name-policy.d.ts.map +1 -0
  1136. package/sdk/dist/workstream-name-policy.js +53 -0
  1137. package/sdk/dist/workstream-name-policy.js.map +1 -0
  1138. package/sdk/dist/workstream-utils.d.ts +23 -0
  1139. package/sdk/dist/workstream-utils.d.ts.map +1 -0
  1140. package/sdk/dist/workstream-utils.js +34 -0
  1141. package/sdk/dist/workstream-utils.js.map +1 -0
  1142. package/sdk/dist/ws-transport.d.ts +32 -0
  1143. package/sdk/dist/ws-transport.d.ts.map +1 -0
  1144. package/sdk/dist/ws-transport.js +84 -0
  1145. package/sdk/dist/ws-transport.js.map +1 -0
  1146. package/sdk/package-lock.json +2530 -0
  1147. package/sdk/package.json +77 -0
  1148. package/sdk/prompts/templates/project.md +186 -0
  1149. package/sdk/prompts/templates/requirements.md +231 -0
  1150. package/sdk/prompts/templates/research-project/ARCHITECTURE.md +204 -0
  1151. package/sdk/prompts/templates/research-project/FEATURES.md +147 -0
  1152. package/sdk/prompts/templates/research-project/PITFALLS.md +200 -0
  1153. package/sdk/prompts/templates/research-project/STACK.md +120 -0
  1154. package/sdk/prompts/templates/research-project/SUMMARY.md +170 -0
  1155. package/sdk/prompts/templates/roadmap.md +202 -0
  1156. package/sdk/prompts/templates/state.md +175 -0
  1157. package/sdk/shared/config-defaults.manifest.json +75 -0
  1158. package/sdk/shared/config-schema.manifest.json +151 -0
  1159. package/sdk/shared/model-catalog.json +122 -0
  1160. package/sdk/src/assembled-prompts.test.ts +349 -0
  1161. package/sdk/src/bug-3589-planning-paths-validation.test.ts +89 -0
  1162. package/sdk/src/bug-3591-gsdtools-runtime-workstream.test.ts +179 -0
  1163. package/sdk/src/cli-transport.test.ts +388 -0
  1164. package/sdk/src/cli-transport.ts +130 -0
  1165. package/sdk/src/cli.test.ts +426 -0
  1166. package/sdk/src/cli.ts +589 -0
  1167. package/sdk/src/config.test.ts +277 -0
  1168. package/sdk/src/config.ts +202 -0
  1169. package/sdk/src/configuration/index.test.ts +318 -0
  1170. package/sdk/src/configuration/index.ts +325 -0
  1171. package/sdk/src/context-engine.test.ts +295 -0
  1172. package/sdk/src/context-engine.ts +170 -0
  1173. package/sdk/src/context-truncation.test.ts +163 -0
  1174. package/sdk/src/context-truncation.ts +233 -0
  1175. package/sdk/src/e2e.integration.test.ts +181 -0
  1176. package/sdk/src/errors.ts +72 -0
  1177. package/sdk/src/event-stream.test.ts +661 -0
  1178. package/sdk/src/event-stream.ts +441 -0
  1179. package/sdk/src/golden/capture.ts +95 -0
  1180. package/sdk/src/golden/fixtures/generate-slug.golden.json +1 -0
  1181. package/sdk/src/golden/fixtures/profile-sample-sessions/demo-project/sample.jsonl +3 -0
  1182. package/sdk/src/golden/fixtures/summary-extract-sample.md +26 -0
  1183. package/sdk/src/golden/fixtures/uat-render-checkpoint-sample.md +15 -0
  1184. package/sdk/src/golden/golden-integration-covered.ts +30 -0
  1185. package/sdk/src/golden/golden-mutation-covered.ts +17 -0
  1186. package/sdk/src/golden/golden-policy.test.ts +8 -0
  1187. package/sdk/src/golden/golden-policy.ts +120 -0
  1188. package/sdk/src/golden/golden.integration.test.ts +1031 -0
  1189. package/sdk/src/golden/init-golden-normalize.ts +15 -0
  1190. package/sdk/src/golden/read-only-golden-rows.ts +77 -0
  1191. package/sdk/src/golden/read-only-parity.integration.test.ts +133 -0
  1192. package/sdk/src/golden/registry-canonical-commands.ts +31 -0
  1193. package/sdk/src/gsd-tools-error.test.ts +21 -0
  1194. package/sdk/src/gsd-tools-error.ts +65 -0
  1195. package/sdk/src/gsd-tools.test.ts +472 -0
  1196. package/sdk/src/gsd-tools.ts +237 -0
  1197. package/sdk/src/gsd-transport-policy.test.ts +34 -0
  1198. package/sdk/src/gsd-transport-policy.ts +48 -0
  1199. package/sdk/src/gsd-transport.test.ts +299 -0
  1200. package/sdk/src/gsd-transport.ts +118 -0
  1201. package/sdk/src/index.ts +366 -0
  1202. package/sdk/src/init-e2e.integration.test.ts +138 -0
  1203. package/sdk/src/init-runner.test.ts +740 -0
  1204. package/sdk/src/init-runner.ts +734 -0
  1205. package/sdk/src/lifecycle-e2e.integration.test.ts +258 -0
  1206. package/sdk/src/logger.test.ts +149 -0
  1207. package/sdk/src/logger.ts +113 -0
  1208. package/sdk/src/milestone-runner.test.ts +421 -0
  1209. package/sdk/src/model-catalog.ts +70 -0
  1210. package/sdk/src/phase-prompt.ts +259 -0
  1211. package/sdk/src/phase-runner.integration.test.ts +377 -0
  1212. package/sdk/src/phase-runner.test.ts +3660 -0
  1213. package/sdk/src/phase-runner.ts +1442 -0
  1214. package/sdk/src/plan-parser.test.ts +579 -0
  1215. package/sdk/src/plan-parser.ts +431 -0
  1216. package/sdk/src/planning-journal.test.ts +70 -0
  1217. package/sdk/src/planning-journal.ts +153 -0
  1218. package/sdk/src/planning-runtime.test.ts +29 -0
  1219. package/sdk/src/planning-runtime.ts +100 -0
  1220. package/sdk/src/project-root/index.test.ts +186 -0
  1221. package/sdk/src/project-root/index.ts +144 -0
  1222. package/sdk/src/prompt-builder.test.ts +318 -0
  1223. package/sdk/src/prompt-builder.ts +218 -0
  1224. package/sdk/src/prompt-sanitizer.test.ts +260 -0
  1225. package/sdk/src/prompt-sanitizer.ts +116 -0
  1226. package/sdk/src/query/QUERY-HANDLERS.md +349 -0
  1227. package/sdk/src/query/active-workstream-store.ts +50 -0
  1228. package/sdk/src/query/agent-failure-classifier.test.ts +157 -0
  1229. package/sdk/src/query/agent-failure-classifier.ts +105 -0
  1230. package/sdk/src/query/audit-open.ts +722 -0
  1231. package/sdk/src/query/check-auto-mode.test.ts +77 -0
  1232. package/sdk/src/query/check-auto-mode.ts +49 -0
  1233. package/sdk/src/query/check-completion.test.ts +113 -0
  1234. package/sdk/src/query/check-completion.ts +182 -0
  1235. package/sdk/src/query/check-decision-coverage.test.ts +519 -0
  1236. package/sdk/src/query/check-decision-coverage.ts +554 -0
  1237. package/sdk/src/query/check-gates.test.ts +103 -0
  1238. package/sdk/src/query/check-gates.ts +112 -0
  1239. package/sdk/src/query/check-ship-ready.test.ts +303 -0
  1240. package/sdk/src/query/check-ship-ready.ts +136 -0
  1241. package/sdk/src/query/check-verification-status.test.ts +143 -0
  1242. package/sdk/src/query/check-verification-status.ts +160 -0
  1243. package/sdk/src/query/command-aliases.generated.ts +154 -0
  1244. package/sdk/src/query/command-catalog.ts +31 -0
  1245. package/sdk/src/query/command-definition.test.ts +47 -0
  1246. package/sdk/src/query/command-definition.ts +70 -0
  1247. package/sdk/src/query/command-family-handlers.ts +123 -0
  1248. package/sdk/src/query/command-manifest.init.ts +24 -0
  1249. package/sdk/src/query/command-manifest.non-family.ts +86 -0
  1250. package/sdk/src/query/command-manifest.phase.ts +17 -0
  1251. package/sdk/src/query/command-manifest.phases.ts +11 -0
  1252. package/sdk/src/query/command-manifest.roadmap.ts +11 -0
  1253. package/sdk/src/query/command-manifest.state.ts +31 -0
  1254. package/sdk/src/query/command-manifest.ts +17 -0
  1255. package/sdk/src/query/command-manifest.types.ts +13 -0
  1256. package/sdk/src/query/command-manifest.validate.ts +11 -0
  1257. package/sdk/src/query/command-manifest.verify.ts +17 -0
  1258. package/sdk/src/query/command-resolution.test.ts +70 -0
  1259. package/sdk/src/query/command-seam-coverage.test.ts +118 -0
  1260. package/sdk/src/query/command-static-catalog-domain.ts +111 -0
  1261. package/sdk/src/query/command-static-catalog-foundation.ts +111 -0
  1262. package/sdk/src/query/command-topology.test.ts +28 -0
  1263. package/sdk/src/query/command-topology.ts +114 -0
  1264. package/sdk/src/query/commands-list.test.ts +36 -0
  1265. package/sdk/src/query/commands-list.ts +19 -0
  1266. package/sdk/src/query/commit.test.ts +485 -0
  1267. package/sdk/src/query/commit.ts +717 -0
  1268. package/sdk/src/query/config-gates.test.ts +89 -0
  1269. package/sdk/src/query/config-gates.ts +69 -0
  1270. package/sdk/src/query/config-mutation.test.ts +598 -0
  1271. package/sdk/src/query/config-mutation.ts +705 -0
  1272. package/sdk/src/query/config-query.test.ts +472 -0
  1273. package/sdk/src/query/config-query.ts +314 -0
  1274. package/sdk/src/query/config-schema.ts +35 -0
  1275. package/sdk/src/query/decisions.test.ts +221 -0
  1276. package/sdk/src/query/decisions.ts +196 -0
  1277. package/sdk/src/query/decomposed-handlers.test.ts +431 -0
  1278. package/sdk/src/query/detect-custom-files.test.ts +115 -0
  1279. package/sdk/src/query/detect-custom-files.ts +96 -0
  1280. package/sdk/src/query/detect-phase-type.test.ts +105 -0
  1281. package/sdk/src/query/detect-phase-type.ts +141 -0
  1282. package/sdk/src/query/docs-init.ts +258 -0
  1283. package/sdk/src/query/fallow-audit.ts +88 -0
  1284. package/sdk/src/query/frontmatter-array.test.ts +14 -0
  1285. package/sdk/src/query/frontmatter-mutation.test.ts +259 -0
  1286. package/sdk/src/query/frontmatter-mutation.ts +328 -0
  1287. package/sdk/src/query/frontmatter.test.ts +326 -0
  1288. package/sdk/src/query/frontmatter.ts +395 -0
  1289. package/sdk/src/query/helpers.test.ts +615 -0
  1290. package/sdk/src/query/helpers.ts +566 -0
  1291. package/sdk/src/query/index-thin-seam.test.ts +16 -0
  1292. package/sdk/src/query/index.ts +9 -0
  1293. package/sdk/src/query/init-complex.test.ts +788 -0
  1294. package/sdk/src/query/init-complex.ts +815 -0
  1295. package/sdk/src/query/init-workstream-milestone-op.test.ts +321 -0
  1296. package/sdk/src/query/init.test.ts +791 -0
  1297. package/sdk/src/query/init.ts +1335 -0
  1298. package/sdk/src/query/intel.test.ts +90 -0
  1299. package/sdk/src/query/intel.ts +404 -0
  1300. package/sdk/src/query/mutation-event-decorator.test.ts +45 -0
  1301. package/sdk/src/query/mutation-event-decorator.ts +37 -0
  1302. package/sdk/src/query/mutation-event-mapper.test.ts +33 -0
  1303. package/sdk/src/query/mutation-event-mapper.ts +102 -0
  1304. package/sdk/src/query/mvp.test.ts +335 -0
  1305. package/sdk/src/query/mvp.ts +292 -0
  1306. package/sdk/src/query/normalize-query-command.test.ts +102 -0
  1307. package/sdk/src/query/phase-filesystem-adapter.ts +35 -0
  1308. package/sdk/src/query/phase-lifecycle-policy.ts +171 -0
  1309. package/sdk/src/query/phase-lifecycle.test.ts +1971 -0
  1310. package/sdk/src/query/phase-lifecycle.ts +2210 -0
  1311. package/sdk/src/query/phase-list-queries.test.ts +88 -0
  1312. package/sdk/src/query/phase-list-queries.ts +152 -0
  1313. package/sdk/src/query/phase-ready.test.ts +65 -0
  1314. package/sdk/src/query/phase-ready.ts +159 -0
  1315. package/sdk/src/query/phase-roadmap-mutation.ts +82 -0
  1316. package/sdk/src/query/phase-uat-passed.test.ts +593 -0
  1317. package/sdk/src/query/phase-uat-passed.ts +297 -0
  1318. package/sdk/src/query/phase.test.ts +693 -0
  1319. package/sdk/src/query/phase.ts +741 -0
  1320. package/sdk/src/query/pipeline.test.ts +169 -0
  1321. package/sdk/src/query/pipeline.ts +243 -0
  1322. package/sdk/src/query/plan-scan.test.ts +35 -0
  1323. package/sdk/src/query/plan-scan.ts +82 -0
  1324. package/sdk/src/query/plan-task-structure.test.ts +65 -0
  1325. package/sdk/src/query/plan-task-structure.ts +63 -0
  1326. package/sdk/src/query/policy-convergence.test.ts +28 -0
  1327. package/sdk/src/query/profile-extract-messages.ts +247 -0
  1328. package/sdk/src/query/profile-output.ts +929 -0
  1329. package/sdk/src/query/profile-questionnaire-data.ts +181 -0
  1330. package/sdk/src/query/profile-sample.ts +184 -0
  1331. package/sdk/src/query/profile-scan-sessions.ts +174 -0
  1332. package/sdk/src/query/profile.test.ts +136 -0
  1333. package/sdk/src/query/profile.ts +337 -0
  1334. package/sdk/src/query/progress.test.ts +156 -0
  1335. package/sdk/src/query/progress.ts +566 -0
  1336. package/sdk/src/query/prompt-budget.ts +556 -0
  1337. package/sdk/src/query/query-cli-adapter.test.ts +79 -0
  1338. package/sdk/src/query/query-cli-adapter.ts +39 -0
  1339. package/sdk/src/query/query-cli-output.test.ts +33 -0
  1340. package/sdk/src/query/query-cli-output.ts +35 -0
  1341. package/sdk/src/query/query-command-diagnosis.test.ts +22 -0
  1342. package/sdk/src/query/query-command-diagnosis.ts +5 -0
  1343. package/sdk/src/query/query-command-resolution-strategy.test.ts +34 -0
  1344. package/sdk/src/query/query-command-resolution-strategy.ts +121 -0
  1345. package/sdk/src/query/query-command-semantics.test.ts +22 -0
  1346. package/sdk/src/query/query-command-semantics.ts +22 -0
  1347. package/sdk/src/query/query-dispatch-contract.ts +30 -0
  1348. package/sdk/src/query/query-dispatch-error-mapper.ts +5 -0
  1349. package/sdk/src/query/query-dispatch-formatting.ts +5 -0
  1350. package/sdk/src/query/query-dispatch-observability.ts +6 -0
  1351. package/sdk/src/query/query-dispatch.test.ts +699 -0
  1352. package/sdk/src/query/query-dispatch.ts +243 -0
  1353. package/sdk/src/query/query-error-details-schema.ts +29 -0
  1354. package/sdk/src/query/query-error-taxonomy.test.ts +39 -0
  1355. package/sdk/src/query/query-error-taxonomy.ts +117 -0
  1356. package/sdk/src/query/query-fallback-bridge-adapter.test.ts +32 -0
  1357. package/sdk/src/query/query-fallback-bridge-adapter.ts +54 -0
  1358. package/sdk/src/query/query-fallback-executor.test.ts +82 -0
  1359. package/sdk/src/query/query-fallback-executor.ts +44 -0
  1360. package/sdk/src/query/query-fallback-output-classifier.test.ts +36 -0
  1361. package/sdk/src/query/query-fallback-output-classifier.ts +31 -0
  1362. package/sdk/src/query/query-fallback-policy.test.ts +13 -0
  1363. package/sdk/src/query/query-fallback-policy.ts +11 -0
  1364. package/sdk/src/query/query-native-dispatch-adapter.ts +16 -0
  1365. package/sdk/src/query/query-policy-capability.test.ts +10 -0
  1366. package/sdk/src/query/query-policy-capability.ts +26 -0
  1367. package/sdk/src/query/query-policy-snapshot.test.ts +9 -0
  1368. package/sdk/src/query/query-registry-capability.test.ts +14 -0
  1369. package/sdk/src/query/query-runtime-context.ts +44 -0
  1370. package/sdk/src/query/query-unknown-command-hints.test.ts +9 -0
  1371. package/sdk/src/query/query-unknown-command-hints.ts +5 -0
  1372. package/sdk/src/query/registry-assembly-descriptor.ts +87 -0
  1373. package/sdk/src/query/registry-assembly-invariants.ts +127 -0
  1374. package/sdk/src/query/registry-assembly.test.ts +138 -0
  1375. package/sdk/src/query/registry-assembly.ts +78 -0
  1376. package/sdk/src/query/registry.test.ts +208 -0
  1377. package/sdk/src/query/registry.ts +142 -0
  1378. package/sdk/src/query/requirements-extract-from-plans.test.ts +58 -0
  1379. package/sdk/src/query/requirements-extract-from-plans.ts +86 -0
  1380. package/sdk/src/query/roadmap-update-plan-progress.test.ts +233 -0
  1381. package/sdk/src/query/roadmap-update-plan-progress.ts +159 -0
  1382. package/sdk/src/query/roadmap.test.ts +1250 -0
  1383. package/sdk/src/query/roadmap.ts +1131 -0
  1384. package/sdk/src/query/route-next-action.test.ts +61 -0
  1385. package/sdk/src/query/route-next-action.ts +345 -0
  1386. package/sdk/src/query/schema-detect.ts +189 -0
  1387. package/sdk/src/query/secrets.test.ts +66 -0
  1388. package/sdk/src/query/secrets.ts +43 -0
  1389. package/sdk/src/query/skill-manifest.test.ts +62 -0
  1390. package/sdk/src/query/skill-manifest.ts +216 -0
  1391. package/sdk/src/query/skills.test.ts +234 -0
  1392. package/sdk/src/query/skills.ts +143 -0
  1393. package/sdk/src/query/state-document.test.ts +197 -0
  1394. package/sdk/src/query/state-document.ts +129 -0
  1395. package/sdk/src/query/state-mutation.test.ts +1210 -0
  1396. package/sdk/src/query/state-mutation.ts +1814 -0
  1397. package/sdk/src/query/state-project-load.ts +80 -0
  1398. package/sdk/src/query/state.test.ts +616 -0
  1399. package/sdk/src/query/state.ts +476 -0
  1400. package/sdk/src/query/sub-repos-root.integration.test.ts +79 -0
  1401. package/sdk/src/query/summary.test.ts +95 -0
  1402. package/sdk/src/query/summary.ts +296 -0
  1403. package/sdk/src/query/template.test.ts +180 -0
  1404. package/sdk/src/query/template.ts +242 -0
  1405. package/sdk/src/query/uat.test.ts +77 -0
  1406. package/sdk/src/query/uat.ts +365 -0
  1407. package/sdk/src/query/utils.test.ts +82 -0
  1408. package/sdk/src/query/utils.ts +106 -0
  1409. package/sdk/src/query/validate.test.ts +924 -0
  1410. package/sdk/src/query/validate.ts +1054 -0
  1411. package/sdk/src/query/verify.test.ts +414 -0
  1412. package/sdk/src/query/verify.ts +656 -0
  1413. package/sdk/src/query/websearch.test.ts +31 -0
  1414. package/sdk/src/query/websearch.ts +82 -0
  1415. package/sdk/src/query/workspace.test.ts +120 -0
  1416. package/sdk/src/query/workspace.ts +145 -0
  1417. package/sdk/src/query/workstream-inventory.ts +143 -0
  1418. package/sdk/src/query/workstream.test.ts +153 -0
  1419. package/sdk/src/query/workstream.ts +324 -0
  1420. package/sdk/src/query/worktree.ts +84 -0
  1421. package/sdk/src/query-command-executor.ts +31 -0
  1422. package/sdk/src/query-execution-policy.test.ts +52 -0
  1423. package/sdk/src/query-execution-policy.ts +46 -0
  1424. package/sdk/src/query-failure-classification.test.ts +23 -0
  1425. package/sdk/src/query-failure-classification.ts +42 -0
  1426. package/sdk/src/query-gsd-tools-path.ts +1 -0
  1427. package/sdk/src/query-gsd-tools-runtime.ts +89 -0
  1428. package/sdk/src/query-hotpath-methods.ts +48 -0
  1429. package/sdk/src/query-native-direct-adapter.test.ts +35 -0
  1430. package/sdk/src/query-native-direct-adapter.ts +70 -0
  1431. package/sdk/src/query-native-hotpath-adapter.test.ts +43 -0
  1432. package/sdk/src/query-native-hotpath-adapter.ts +45 -0
  1433. package/sdk/src/query-raw-output-projection.test.ts +39 -0
  1434. package/sdk/src/query-raw-output-projection.ts +93 -0
  1435. package/sdk/src/query-runtime-bridge.test.ts +150 -0
  1436. package/sdk/src/query-runtime-bridge.ts +215 -0
  1437. package/sdk/src/query-runtime-seam-coverage.test.ts +20 -0
  1438. package/sdk/src/query-subprocess-adapter.test.ts +84 -0
  1439. package/sdk/src/query-subprocess-adapter.ts +146 -0
  1440. package/sdk/src/query-tools-error-factory.test.ts +35 -0
  1441. package/sdk/src/query-tools-error-factory.ts +76 -0
  1442. package/sdk/src/research-gate.test.ts +190 -0
  1443. package/sdk/src/research-gate.ts +94 -0
  1444. package/sdk/src/runtime-bridge-options.test.ts +33 -0
  1445. package/sdk/src/runtime-bridge-sync/index.test.ts +164 -0
  1446. package/sdk/src/runtime-bridge-sync/index.ts +154 -0
  1447. package/sdk/src/runtime-bridge-sync/projectdir-regression.test.ts +150 -0
  1448. package/sdk/src/runtime-bridge-sync/worker.ts +224 -0
  1449. package/sdk/src/runtime-gate.test.ts +84 -0
  1450. package/sdk/src/runtime-gate.ts +52 -0
  1451. package/sdk/src/sdk-package-compatibility.test.ts +97 -0
  1452. package/sdk/src/sdk-package-compatibility.ts +141 -0
  1453. package/sdk/src/session-runner.test.ts +164 -0
  1454. package/sdk/src/session-runner.ts +327 -0
  1455. package/sdk/src/tool-scoping.test.ts +160 -0
  1456. package/sdk/src/tool-scoping.ts +61 -0
  1457. package/sdk/src/types.ts +927 -0
  1458. package/sdk/src/workflow-agent-skills-consistency.test.ts +98 -0
  1459. package/sdk/src/workstream-inventory/builder.test.ts +241 -0
  1460. package/sdk/src/workstream-inventory/builder.ts +170 -0
  1461. package/sdk/src/workstream-name-policy.ts +57 -0
  1462. package/sdk/src/workstream-utils.ts +36 -0
  1463. package/sdk/src/ws-flag.test.ts +285 -0
  1464. package/sdk/src/ws-transport.test.ts +161 -0
  1465. package/sdk/src/ws-transport.ts +93 -0
  1466. package/sdk/tsconfig.json +20 -0
@@ -0,0 +1,1823 @@
1
+ /**
2
+ * Phase lifecycle handlers — add, insert, scaffold operations.
3
+ *
4
+ * Ported from get-shit-done/bin/lib/phase.cjs and commands.cjs.
5
+ * Provides phaseAdd (append phase), phaseAddBatch (append multiple phases),
6
+ * phaseInsert (decimal phase insertion), and phaseScaffold (template file/directory creation).
7
+ *
8
+ * Shared helpers replaceInCurrentMilestone and readModifyWriteRoadmapMd
9
+ * are exported for use by downstream handlers (phaseComplete in Plan 03).
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { phaseAdd, phaseInsert, phaseScaffold } from './phase-lifecycle.js';
14
+ *
15
+ * await phaseAdd(['New Feature'], '/project');
16
+ * await phaseInsert(['10', 'Urgent Fix'], '/project');
17
+ * await phaseScaffold(['context', '9'], '/project');
18
+ * ```
19
+ */
20
+ import { readFile, writeFile, mkdir, readdir, rename, rm } from 'node:fs/promises';
21
+ import { existsSync } from 'node:fs';
22
+ import { join, relative } from 'node:path';
23
+ import { GSDError, ErrorClassification } from '../errors.js';
24
+ import { escapeRegex, normalizeMd, normalizePhaseName, comparePhaseNum, phaseTokenMatches, toPosixPath, planningPaths, } from './helpers.js';
25
+ import { extractFrontmatter } from './frontmatter.js';
26
+ import { extractCurrentMilestone, phaseMarkdownRegexSource } from './roadmap.js';
27
+ import { getMilestonePhaseFilter } from './state.js';
28
+ import { isCanonicalPlanFile, describeNonCanonicalPlans } from './phase.js';
29
+ import { acquireStateLock, readModifyWriteStateMdFull, releaseStateLock, stateReplaceField, } from './state-mutation.js';
30
+ import { stateExtractField, stateReplaceFieldWithFallback } from './state-document.js';
31
+ import { assertNoNullBytes, assertSafePhaseDirName, assertSafeProjectCode, buildPhaseRoadmapEntry, collectDecimalSuffixesFromDirNames, collectDecimalSuffixesFromRoadmap, computeNextDecimalPhase, computeNextSequentialPhaseId, computePhaseDirectory, extractOneLinerFromBody, generatePhaseSlug, parseMultiwordArg, } from './phase-lifecycle-policy.js';
32
+ import { archiveDirectories, ensureDirectoryWithGitkeep, listDirectories, } from './phase-filesystem-adapter.js';
33
+ import { readModifyWriteRoadmapMd, replaceInCurrentMilestone, } from './phase-roadmap-mutation.js';
34
+ export { readModifyWriteRoadmapMd, replaceInCurrentMilestone };
35
+ // ─── Milestone-scoped directory helpers (#3816) ───────────────────────────
36
+ /**
37
+ * Read the current milestone identifier from STATE.md.
38
+ * Returns null on any error (absent, unreadable, or no `milestone:` field).
39
+ */
40
+ async function readCurrentMilestoneFromState(projectDir, workstream) {
41
+ try {
42
+ const statePath = planningPaths(projectDir, workstream).state;
43
+ const content = await readFile(statePath, 'utf-8');
44
+ const m = content.match(/^milestone:\s*(.+)$/m);
45
+ if (!m)
46
+ return null;
47
+ return m[1].trim().replace(/^["']|["']$/g, '');
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ /**
54
+ * Resolve the phases directory for a `phase.add` / `phase.add-batch` write.
55
+ *
56
+ * When the project uses a milestone-scoped layout (`.planning/milestones/
57
+ * <milestone>-phases/` already exists on disk), return that path so newly
58
+ * created phase directories land in the correct location alongside existing
59
+ * phases (#3816 fix for Symptom 3a).
60
+ *
61
+ * Falls back to the flat `.planning/phases/` path for all other projects.
62
+ */
63
+ async function resolveWritePhasesDir(projectDir, workstream) {
64
+ const flatPhasesDir = planningPaths(projectDir, workstream).phases;
65
+ try {
66
+ const milestone = await readCurrentMilestoneFromState(projectDir, workstream);
67
+ if (!milestone)
68
+ return flatPhasesDir;
69
+ const milestoneScopedDir = join(projectDir, '.planning', 'milestones', `${milestone}-phases`);
70
+ if (existsSync(milestoneScopedDir)) {
71
+ return milestoneScopedDir;
72
+ }
73
+ }
74
+ catch { /* fall through to flat layout */ }
75
+ return flatPhasesDir;
76
+ }
77
+ /**
78
+ * Find the insertion point for a new phase entry in the ROADMAP.md content.
79
+ *
80
+ * #3816 fix for Symptom 3b: the previous implementation used
81
+ * `lastIndexOf('\n---')` which would place a new phase AFTER the Backlog
82
+ * section when Backlog precedes the trailing `---`. The new implementation
83
+ * inserts at the end of the active milestone section (just before the next
84
+ * `## Backlog` / `## Planned` / etc. heading, or before the trailing `---`).
85
+ *
86
+ * Returns the index at which the new phase entry should be inserted.
87
+ */
88
+ function findPhaseInsertionPoint(rawContent) {
89
+ // Look for the next top-level (## or ###) section that marks the end of the
90
+ // active phases list: Backlog, Planned milestones, or similar.
91
+ // Matches lines starting with ## or ### that are NOT the trailing `---`.
92
+ // We insert BEFORE this heading.
93
+ const backlogBoundaryRe = /\n(#{2,3}\s+(?:Backlog|Planned|Shipped|Archived)\b[^\n]*)/i;
94
+ const boundaryMatch = rawContent.match(backlogBoundaryRe);
95
+ if (boundaryMatch && boundaryMatch.index !== undefined) {
96
+ return boundaryMatch.index;
97
+ }
98
+ // Fallback: insert before the last `\n---` separator (original behaviour for
99
+ // ROADMAPs without a Backlog section).
100
+ const lastSeparator = rawContent.lastIndexOf('\n---');
101
+ if (lastSeparator > 0)
102
+ return lastSeparator;
103
+ return rawContent.length;
104
+ }
105
+ // ─── phaseAdd handler ───────────────────────────────────────────────────
106
+ /**
107
+ * Query handler for phase.add.
108
+ *
109
+ * Port of cmdPhaseAdd from phase.cjs lines 312-392.
110
+ * Creates a new phase directory with .gitkeep, appends a phase section
111
+ * to ROADMAP.md before the last "---" separator.
112
+ *
113
+ * @param args - description (required), optional customId, optional --dry-run flag.
114
+ * Recognized flags: --dry-run (compute result without writing to disk).
115
+ * Any other --flag argument is rejected with a validation error.
116
+ * @param projectDir - Project root directory
117
+ * @returns QueryResult with { phase_number, padded, name, slug, directory, naming_mode }
118
+ * In --dry-run mode also includes { dry_run: true, roadmap_entry: string }
119
+ */
120
+ export const phaseAdd = async (args, projectDir, workstream) => {
121
+ // ── Flag parsing ────────────────────────────────────────────────────────
122
+ // Mirrors the CJS phase add router (phase-command-router.cjs): recognise
123
+ // --dry-run and --id <value>; reject every other --flag; ignore --raw so it
124
+ // never leaks into the description; join the remaining positional tokens
125
+ // with a single space so multi-word descriptions like `phase add User
126
+ // Dashboard` produce description "User Dashboard". customId comes from the
127
+ // --id flag, never from positional[1].
128
+ let dryRun = false;
129
+ let customIdArg = null;
130
+ const positional = [];
131
+ for (let i = 0; i < args.length; i++) {
132
+ const arg = args[i];
133
+ if (arg === '--raw') {
134
+ // CJS router strips --raw before invoking the handler; preserve parity
135
+ // so a stray --raw never poisons the description.
136
+ continue;
137
+ }
138
+ if (arg === '--dry-run') {
139
+ dryRun = true;
140
+ continue;
141
+ }
142
+ if (arg === '--id') {
143
+ const id = args[i + 1];
144
+ if (!id || id.startsWith('--')) {
145
+ throw new GSDError('--id requires a value', ErrorClassification.Validation);
146
+ }
147
+ customIdArg = id;
148
+ i++;
149
+ continue;
150
+ }
151
+ if (arg.startsWith('--')) {
152
+ throw new GSDError(`phase add does not support ${arg}`, ErrorClassification.Validation);
153
+ }
154
+ positional.push(arg);
155
+ }
156
+ const description = positional.join(' ').trim();
157
+ if (!description) {
158
+ throw new GSDError('description required for phase add', ErrorClassification.Validation);
159
+ }
160
+ assertNoNullBytes(description, 'description');
161
+ const configPath = planningPaths(projectDir, workstream).config;
162
+ let config = {};
163
+ try {
164
+ config = JSON.parse(await readFile(configPath, 'utf-8'));
165
+ }
166
+ catch { /* use defaults */ }
167
+ const slug = generatePhaseSlug(description);
168
+ // customId always comes from the --id flag; positional tokens are reserved
169
+ // for the description (which is joined above).
170
+ const customId = customIdArg;
171
+ // Optional project code prefix (e.g., 'CK' -> 'CK-01-foundation')
172
+ const projectCode = config.project_code || '';
173
+ assertSafeProjectCode(projectCode);
174
+ const prefix = projectCode ? `${projectCode}-` : '';
175
+ // ── Helper: compute newPhaseId / dirName / computedPhaseEntry from raw ROADMAP content ──
176
+ // Extracted as a local async function so it can be called both inside the
177
+ // roadmap lock (non-dry-run) and outside (dry-run, where no write occurs and
178
+ // there is no race condition to guard against).
179
+ const computePhaseFields = async (rawRoadmapContent) => {
180
+ const milestoneContent = await extractCurrentMilestone(rawRoadmapContent, projectDir);
181
+ // #3816: use milestone-scoped directory if it exists, otherwise flat layout
182
+ const phasesDir = await resolveWritePhasesDir(projectDir, workstream);
183
+ const dirNames = await listDirectories(phasesDir);
184
+ const nextSequentialPhaseId = computeNextSequentialPhaseId(milestoneContent, dirNames);
185
+ const { phaseId: resolvedPhaseId, dirName: resolvedDirName } = computePhaseDirectory(config.phase_naming, slug, prefix, nextSequentialPhaseId, customId || undefined);
186
+ if (!resolvedDirName) {
187
+ throw new GSDError('Phase directory name was not computed', ErrorClassification.Execution);
188
+ }
189
+ if (resolvedPhaseId === '') {
190
+ throw new GSDError('Phase ID was not computed', ErrorClassification.Execution);
191
+ }
192
+ const resolvedEntry = buildPhaseRoadmapEntry(resolvedPhaseId, description, config.phase_naming);
193
+ return { resolvedPhaseId, resolvedDirName, resolvedEntry };
194
+ };
195
+ let newPhaseId = '';
196
+ let dirName = '';
197
+ let computedPhaseEntry = '';
198
+ if (dryRun) {
199
+ // Dry-run: no write, no race condition — compute outside the lock.
200
+ const roadmapPath = planningPaths(projectDir, workstream).roadmap;
201
+ let rawRoadmapContent = '';
202
+ try {
203
+ rawRoadmapContent = await readFile(roadmapPath, 'utf-8');
204
+ }
205
+ catch { /* ROADMAP.md may not exist yet */ }
206
+ const { resolvedPhaseId, resolvedDirName, resolvedEntry } = await computePhaseFields(rawRoadmapContent);
207
+ newPhaseId = resolvedPhaseId;
208
+ dirName = resolvedDirName;
209
+ computedPhaseEntry = resolvedEntry;
210
+ }
211
+ else {
212
+ // Real write path: hold the roadmap lock across the entire read → compute → write
213
+ // cycle so that two concurrent phase.add calls cannot both observe the same
214
+ // maxPhase and produce duplicate phase IDs.
215
+ await readModifyWriteRoadmapMd(projectDir, async (roadmapRaw) => {
216
+ const { resolvedPhaseId, resolvedDirName, resolvedEntry } = await computePhaseFields(roadmapRaw);
217
+ newPhaseId = resolvedPhaseId;
218
+ dirName = resolvedDirName;
219
+ computedPhaseEntry = resolvedEntry;
220
+ // #3816: resolve to milestone-scoped dir if it exists
221
+ const phasesWriteDir = await resolveWritePhasesDir(projectDir, workstream);
222
+ const dirPath = join(phasesWriteDir, dirName);
223
+ // Create directory with .gitkeep so git tracks empty folders
224
+ await ensureDirectoryWithGitkeep(dirPath);
225
+ // #3816: insert before Backlog/Planned boundary, not after last `---`
226
+ const insertIdx = findPhaseInsertionPoint(roadmapRaw);
227
+ return roadmapRaw.slice(0, insertIdx) + computedPhaseEntry + roadmapRaw.slice(insertIdx);
228
+ }, workstream);
229
+ }
230
+ const result = {
231
+ phase_number: typeof newPhaseId === 'number' ? newPhaseId : String(newPhaseId),
232
+ padded: typeof newPhaseId === 'number' ? String(newPhaseId).padStart(2, '0') : String(newPhaseId),
233
+ name: description,
234
+ slug,
235
+ // #3816: result.directory must reflect the actual write location
236
+ directory: toPosixPath(relative(projectDir, join(await resolveWritePhasesDir(projectDir, workstream), dirName))),
237
+ naming_mode: config.phase_naming || 'sequential',
238
+ };
239
+ if (dryRun) {
240
+ result.dry_run = true;
241
+ result.roadmap_entry = computedPhaseEntry;
242
+ }
243
+ return { data: result };
244
+ };
245
+ // ─── phaseAddBatch handler ────────────────────────────────────────────────
246
+ /**
247
+ * Query handler for phase.add-batch.
248
+ *
249
+ * Port of cmdPhaseAddBatch from phase.cjs lines 411-478.
250
+ * Appends multiple phases in one locked ROADMAP pass (sequential or custom naming).
251
+ *
252
+ * @param args - Either `--descriptions` followed by a JSON array string, or one description per arg (`--raw` ignored)
253
+ */
254
+ export const phaseAddBatch = async (args, projectDir, workstream) => {
255
+ let descriptions;
256
+ const descIdx = args.indexOf('--descriptions');
257
+ if (descIdx !== -1) {
258
+ // CJS router parity (phase-command-router.cjs): a dangling --descriptions
259
+ // or one whose value is another flag must surface the same JSON-array error
260
+ // string, not silently fall through to positional parsing or throw a
261
+ // different "valid JSON" variant.
262
+ const rawValue = args[descIdx + 1];
263
+ if (rawValue === undefined || rawValue.startsWith('--')) {
264
+ throw new GSDError('--descriptions must be a JSON array', ErrorClassification.Validation);
265
+ }
266
+ let parsed;
267
+ try {
268
+ parsed = JSON.parse(rawValue);
269
+ }
270
+ catch {
271
+ throw new GSDError('--descriptions must be a JSON array', ErrorClassification.Validation);
272
+ }
273
+ if (!Array.isArray(parsed)) {
274
+ throw new GSDError('--descriptions must be a JSON array', ErrorClassification.Validation);
275
+ }
276
+ descriptions = parsed.map((x) => String(x));
277
+ }
278
+ else {
279
+ descriptions = args.filter((a) => a !== '--raw');
280
+ }
281
+ if (descriptions.length === 0) {
282
+ throw new GSDError('descriptions array required for phase add-batch', ErrorClassification.Validation);
283
+ }
284
+ for (const d of descriptions) {
285
+ assertNoNullBytes(d, 'description');
286
+ if (!d.trim()) {
287
+ throw new GSDError('description must be non-empty', ErrorClassification.Validation);
288
+ }
289
+ }
290
+ const roadmapPath = planningPaths(projectDir, workstream).roadmap;
291
+ if (!existsSync(roadmapPath)) {
292
+ throw new GSDError('ROADMAP.md not found', ErrorClassification.Validation);
293
+ }
294
+ let config = {};
295
+ try {
296
+ config = JSON.parse(await readFile(planningPaths(projectDir, workstream).config, 'utf-8'));
297
+ }
298
+ catch { /* use defaults */ }
299
+ const projectCode = config.project_code || '';
300
+ assertSafeProjectCode(projectCode);
301
+ const prefix = projectCode ? `${projectCode}-` : '';
302
+ const added = [];
303
+ await readModifyWriteRoadmapMd(projectDir, async (initialContent) => {
304
+ let rawContent = initialContent;
305
+ const content = await extractCurrentMilestone(rawContent, projectDir);
306
+ let maxPhase = 0;
307
+ // #3816: resolve to milestone-scoped dir if it exists for the whole batch
308
+ const phasesWriteDir = await resolveWritePhasesDir(projectDir, workstream);
309
+ if (config.phase_naming !== 'custom') {
310
+ const dirNames = await listDirectories(phasesWriteDir);
311
+ maxPhase = computeNextSequentialPhaseId(content, dirNames) - 1;
312
+ }
313
+ for (const description of descriptions) {
314
+ const slug = generatePhaseSlug(description);
315
+ let newPhaseId;
316
+ let dirName;
317
+ if (config.phase_naming === 'custom') {
318
+ // Match CJS cmdPhaseAddBatch: slug.toUpperCase().replace(/-/g, '-') (identity on hyphens)
319
+ newPhaseId = slug.toUpperCase();
320
+ dirName = `${prefix}${newPhaseId}-${slug}`;
321
+ }
322
+ else {
323
+ maxPhase += 1;
324
+ newPhaseId = maxPhase;
325
+ dirName = `${prefix}${String(newPhaseId).padStart(2, '0')}-${slug}`;
326
+ }
327
+ assertSafePhaseDirName(dirName);
328
+ // #3816: use resolved milestone-scoped dir for directory creation
329
+ const dirPath = join(phasesWriteDir, dirName);
330
+ await ensureDirectoryWithGitkeep(dirPath);
331
+ const phaseEntry = buildPhaseRoadmapEntry(newPhaseId, description, config.phase_naming);
332
+ // #3816: insert before Backlog/Planned boundary, not after last `---`
333
+ const insertIdx = findPhaseInsertionPoint(rawContent);
334
+ rawContent = rawContent.slice(0, insertIdx) + phaseEntry + rawContent.slice(insertIdx);
335
+ added.push({
336
+ phase_number: typeof newPhaseId === 'number' ? newPhaseId : String(newPhaseId),
337
+ padded: typeof newPhaseId === 'number' ? String(newPhaseId).padStart(2, '0') : String(newPhaseId),
338
+ name: description,
339
+ slug,
340
+ // #3816: result.directory reflects the actual write location
341
+ directory: toPosixPath(relative(projectDir, join(phasesWriteDir, dirName))),
342
+ naming_mode: config.phase_naming || 'sequential',
343
+ });
344
+ }
345
+ return rawContent;
346
+ }, workstream);
347
+ return { data: { phases: added, count: added.length } };
348
+ };
349
+ // ─── phaseInsert handler ────────────────────────────────────────────────
350
+ /**
351
+ * Query handler for phase.insert.
352
+ *
353
+ * Port of cmdPhaseInsert from phase.cjs lines 394-492.
354
+ * Creates a decimal phase directory after a target phase, inserting
355
+ * the phase section in ROADMAP.md after the target.
356
+ *
357
+ * @param args - args[0]: afterPhase (required), args[1]: description (required)
358
+ * @param projectDir - Project root directory
359
+ * @returns QueryResult with { phase_number, after_phase, name, slug, directory }
360
+ */
361
+ export const phaseInsert = async (args, projectDir, workstream) => {
362
+ // CJS router parity (phase-command-router.cjs): explicitly reject
363
+ // --dry-run (insert is destructive on disk + roadmap and has no preview
364
+ // path), strip --raw, and join all positional args after `afterPhase` into
365
+ // a single space-delimited description so `phase insert 1 Fix Critical Bug`
366
+ // produces description "Fix Critical Bug" instead of just "Fix".
367
+ const positional = [];
368
+ for (const arg of args) {
369
+ if (arg === '--dry-run') {
370
+ throw new GSDError('phase insert does not support --dry-run', ErrorClassification.Validation);
371
+ }
372
+ if (arg === '--raw')
373
+ continue;
374
+ if (arg.startsWith('--')) {
375
+ throw new GSDError(`phase insert does not support ${arg}`, ErrorClassification.Validation);
376
+ }
377
+ positional.push(arg);
378
+ }
379
+ const afterPhase = positional[0];
380
+ const description = positional.slice(1).join(' ').trim();
381
+ if (!afterPhase || !description) {
382
+ throw new GSDError('after-phase and description required for phase insert', ErrorClassification.Validation);
383
+ }
384
+ assertNoNullBytes(afterPhase, 'afterPhase');
385
+ assertNoNullBytes(description, 'description');
386
+ const slug = generatePhaseSlug(description);
387
+ let decimalPhase = '';
388
+ let dirName = '';
389
+ await readModifyWriteRoadmapMd(projectDir, async (rawContent) => {
390
+ const content = await extractCurrentMilestone(rawContent, projectDir);
391
+ // Normalize input then strip leading zeros for flexible matching
392
+ const normalizedAfter = normalizePhaseName(afterPhase);
393
+ const unpadded = normalizedAfter.replace(/^0+/, '');
394
+ const afterPhaseEscaped = unpadded.replace(/\./g, '\\.');
395
+ const targetPattern = new RegExp(`#{2,4}\\s*Phase\\s+0*${afterPhaseEscaped}:`, 'i');
396
+ const headingMatch = targetPattern.test(content);
397
+ // #3815: also recognise the checked-bullet phase format used by projects
398
+ // that list phases as `- [ ] **Phase N: name**` or `- [ ] Phase N: name`
399
+ // (both bold and plain variants). This mirrors the patterns already used
400
+ // by phaseRemove / phaseComplete so insert is consistent with its siblings.
401
+ //
402
+ // Bullet-style is only used when there are NO heading-style phases at all in
403
+ // the milestone content. If the ROADMAP mixes headings + bullets (hybrid
404
+ // format), a bullet-only match means the detail section is missing — that
405
+ // is the #3098 case and must continue to produce the "missing a detail
406
+ // section" error. Only a purely bullet-style ROADMAP (zero heading-style
407
+ // phase entries in the milestone) goes through the bullet insert path.
408
+ const bulletPattern = new RegExp(`-\\s*\\[[ x]\\]\\s*(?:\\*\\*)?Phase\\s+0*${afterPhaseEscaped}[:\\s]`, 'i');
409
+ const anyHeadingPattern = /#{2,4}\s*Phase\s+\d/i;
410
+ const roadmapHasHeadingPhases = anyHeadingPattern.test(content);
411
+ const isBulletStyle = !headingMatch && bulletPattern.test(content) && !roadmapHasHeadingPhases;
412
+ if (!headingMatch && !isBulletStyle) {
413
+ // Bug #3098 parity: when the ROADMAP uses heading-style phases and only
414
+ // the summary checklist exists for this phase (no `### Phase N:` detail
415
+ // section), point the user at the missing detail section rather than
416
+ // implying the phase is absent.
417
+ const checklistPattern = new RegExp(`-\\s*\\[[ x]\\]\\s*(?:\\*\\*)?Phase\\s+0*${afterPhaseEscaped}[:\\s]`, 'i');
418
+ if (checklistPattern.test(content)) {
419
+ throw new GSDError(`Phase ${afterPhase} exists in roadmap summary but is missing a detail section (### Phase ${afterPhase}: ...).`, ErrorClassification.Validation);
420
+ }
421
+ throw new GSDError(`Phase ${afterPhase} not found in ROADMAP.md`, ErrorClassification.Validation);
422
+ }
423
+ // Calculate next decimal by scanning both directories AND ROADMAP.md entries
424
+ const phasesDir = planningPaths(projectDir, workstream).phases;
425
+ const normalizedBase = normalizePhaseName(afterPhase);
426
+ const decimalSet = new Set();
427
+ try {
428
+ const dirs = await listDirectories(phasesDir);
429
+ for (const suffix of collectDecimalSuffixesFromDirNames(normalizedBase, dirs)) {
430
+ decimalSet.add(suffix);
431
+ }
432
+ }
433
+ catch { /* intentionally empty */ }
434
+ // Also scan ROADMAP.md content for decimal entries
435
+ for (const suffix of collectDecimalSuffixesFromRoadmap(normalizedBase, rawContent)) {
436
+ decimalSet.add(suffix);
437
+ }
438
+ decimalPhase = computeNextDecimalPhase(normalizedBase, decimalSet).next;
439
+ // Optional project code prefix
440
+ let insertConfig = {};
441
+ try {
442
+ insertConfig = JSON.parse(await readFile(planningPaths(projectDir, workstream).config, 'utf-8'));
443
+ }
444
+ catch { /* use defaults */ }
445
+ const projectCode = insertConfig.project_code || '';
446
+ assertSafeProjectCode(projectCode);
447
+ const pfx = projectCode ? `${projectCode}-` : '';
448
+ dirName = `${pfx}${decimalPhase}-${slug}`;
449
+ assertSafePhaseDirName(dirName);
450
+ const dirPath = join(phasesDir, dirName);
451
+ // Create directory with .gitkeep
452
+ await ensureDirectoryWithGitkeep(dirPath);
453
+ if (isBulletStyle) {
454
+ // #3815: Insert in checked-bullet format, mirroring the style of the
455
+ // surrounding entries. Detect whether the matched bullet uses bold
456
+ // (`**Phase N: …**`) to preserve file-internal format consistency.
457
+ const boldBulletPattern = new RegExp(`-\\s*\\[[ x]\\]\\s*\\*\\*Phase\\s+0*${afterPhaseEscaped}:`, 'i');
458
+ const useBold = boldBulletPattern.test(content);
459
+ const phaseLabel = useBold
460
+ ? `**Phase ${decimalPhase}: ${description}**`
461
+ : `Phase ${decimalPhase}: ${description}`;
462
+ const bulletEntry = `\n- [ ] ${phaseLabel}`;
463
+ // Locate the target bullet line in the raw content
464
+ const targetBulletPattern = new RegExp(`(-\\s*\\[[ x]\\]\\s*(?:\\*\\*)?Phase\\s+0*${afterPhaseEscaped}[:\\s][^\\n]*)`, 'i');
465
+ const bulletMatchResult = rawContent.match(targetBulletPattern);
466
+ if (!bulletMatchResult) {
467
+ throw new GSDError(`Could not find Phase ${afterPhase} bullet line`, ErrorClassification.Execution);
468
+ }
469
+ const bulletLineEnd = rawContent.indexOf(bulletMatchResult[0]) + bulletMatchResult[0].length;
470
+ // Find where the next phase bullet starts (or use end of content)
471
+ const afterBullet = rawContent.slice(bulletLineEnd);
472
+ const nextBulletMatch = afterBullet.match(/\n-\s*\[[ x]\]\s*(?:\*\*)?Phase\s+\d/i);
473
+ let insertIdx;
474
+ if (nextBulletMatch && nextBulletMatch.index !== undefined) {
475
+ insertIdx = bulletLineEnd + nextBulletMatch.index;
476
+ }
477
+ else {
478
+ insertIdx = bulletLineEnd;
479
+ }
480
+ return rawContent.slice(0, insertIdx) + bulletEntry + rawContent.slice(insertIdx);
481
+ }
482
+ // Heading-style insert (original path)
483
+ // Build phase entry
484
+ const phaseEntry = `\n### Phase ${decimalPhase}: ${description} (INSERTED)\n\n**Goal:** [Urgent work - to be planned]\n**Requirements**: TBD\n**Depends on:** Phase ${afterPhase}\n**Plans:** 0 plans\n\nPlans:\n- [ ] TBD (run /gsd-plan-phase ${decimalPhase} to break down)\n`;
485
+ // Insert after the target phase section
486
+ const headerPattern = new RegExp(`(#{2,4}\\s*Phase\\s+0*${afterPhaseEscaped}:[^\\n]*\\n)`, 'i');
487
+ const headerMatch = rawContent.match(headerPattern);
488
+ if (!headerMatch) {
489
+ throw new GSDError(`Could not find Phase ${afterPhase} header`, ErrorClassification.Execution);
490
+ }
491
+ const headerIdx = rawContent.indexOf(headerMatch[0]);
492
+ const afterHeader = rawContent.slice(headerIdx + headerMatch[0].length);
493
+ const nextPhaseMatch = afterHeader.match(/\n#{2,4}\s+Phase\s+\d/i);
494
+ let insertIdx;
495
+ if (nextPhaseMatch && nextPhaseMatch.index !== undefined) {
496
+ insertIdx = headerIdx + headerMatch[0].length + nextPhaseMatch.index;
497
+ }
498
+ else {
499
+ insertIdx = rawContent.length;
500
+ }
501
+ return rawContent.slice(0, insertIdx) + phaseEntry + rawContent.slice(insertIdx);
502
+ }, workstream);
503
+ if (!decimalPhase) {
504
+ throw new GSDError('Decimal phase was not computed', ErrorClassification.Execution);
505
+ }
506
+ if (!dirName) {
507
+ throw new GSDError('Phase directory name was not computed', ErrorClassification.Execution);
508
+ }
509
+ const result = {
510
+ phase_number: decimalPhase,
511
+ after_phase: afterPhase,
512
+ name: description,
513
+ slug,
514
+ directory: toPosixPath(relative(projectDir, join(planningPaths(projectDir, workstream).phases, dirName))),
515
+ };
516
+ return { data: result };
517
+ };
518
+ // ─── phaseScaffold handler ──────────────────────────────────────────────
519
+ /**
520
+ * Internal helper: find phase directory matching a phase identifier.
521
+ *
522
+ * Reuses the same logic as findPhase handler but returns just the directory info.
523
+ */
524
+ async function findPhaseDir(projectDir, phase, workstream) {
525
+ const phasesDir = planningPaths(projectDir, workstream).phases;
526
+ const normalized = normalizePhaseName(phase);
527
+ const dirs = await listDirectories(phasesDir);
528
+ const match = dirs.find((d) => phaseTokenMatches(d, normalized));
529
+ if (!match)
530
+ return null;
531
+ // Extract phase name from directory
532
+ const dirMatch = match.match(/^(?:[A-Z]{1,6}-)?\d+[A-Z]?(?:\.\d+)*-(.+)/i);
533
+ const phaseName = dirMatch ? dirMatch[1] : null;
534
+ return {
535
+ dirPath: join(phasesDir, match),
536
+ dirName: match,
537
+ phaseName,
538
+ };
539
+ }
540
+ /**
541
+ * Query handler for phase.scaffold.
542
+ *
543
+ * Port of cmdScaffold from commands.cjs lines 750-806.
544
+ * Creates template files (context, uat, verification) or phase directories.
545
+ *
546
+ * @param args - Positional `[type, phase, name?]` **or** gsd-tools style
547
+ * `[type, '--phase', N, '--name', title]` (name may be multiple words).
548
+ * @param projectDir - Project root directory
549
+ * @returns QueryResult with { created, path } or { created: false, reason: 'already_exists' }
550
+ */
551
+ function normalizeScaffoldArgs(args) {
552
+ const type = args[0];
553
+ if (!type || !args.includes('--phase')) {
554
+ return args;
555
+ }
556
+ const phaseIdx = args.indexOf('--phase');
557
+ const phase = phaseIdx !== -1 && args[phaseIdx + 1] && !args[phaseIdx + 1].startsWith('--')
558
+ ? args[phaseIdx + 1]
559
+ : '';
560
+ const nameIdx = args.indexOf('--name');
561
+ let name;
562
+ if (nameIdx !== -1) {
563
+ const tail = args.slice(nameIdx + 1);
564
+ const stop = tail.findIndex(a => a.startsWith('--'));
565
+ const parts = stop === -1 ? tail : tail.slice(0, stop);
566
+ name = parts.join(' ').trim() || undefined;
567
+ }
568
+ return [type, phase, ...(name !== undefined && name !== '' ? [name] : [])];
569
+ }
570
+ export const phaseScaffold = async (args, projectDir, workstream) => {
571
+ const normalized = normalizeScaffoldArgs(args);
572
+ const type = normalized[0];
573
+ const phase = normalized[1];
574
+ const name = normalized[2] || undefined;
575
+ if (!type) {
576
+ throw new GSDError('type required for scaffold', ErrorClassification.Validation);
577
+ }
578
+ const validTypes = new Set(['context', 'uat', 'verification', 'phase-dir']);
579
+ if (!validTypes.has(type)) {
580
+ throw new GSDError(`Unknown scaffold type: ${type}. Available: context, uat, verification, phase-dir`, ErrorClassification.Validation);
581
+ }
582
+ if (phase) {
583
+ assertNoNullBytes(phase, 'phase');
584
+ }
585
+ if (name) {
586
+ assertNoNullBytes(name, 'name');
587
+ }
588
+ const padded = phase ? normalizePhaseName(phase) : '00';
589
+ const today = new Date().toISOString().split('T')[0];
590
+ // Handle phase-dir type separately
591
+ if (type === 'phase-dir') {
592
+ if (!phase || !name) {
593
+ throw new GSDError('phase and name required for phase-dir scaffold', ErrorClassification.Validation);
594
+ }
595
+ const slug = generatePhaseSlug(name);
596
+ // #3287: apply project_code prefix to stay consistent with phase.add/phase.insert
597
+ let scaffoldConfig = {};
598
+ try {
599
+ scaffoldConfig = JSON.parse(await readFile(planningPaths(projectDir, workstream).config, 'utf-8'));
600
+ }
601
+ catch { /* use defaults */ }
602
+ const scaffoldProjectCode = scaffoldConfig.project_code || '';
603
+ assertSafeProjectCode(scaffoldProjectCode);
604
+ const scaffoldPrefix = scaffoldProjectCode ? `${scaffoldProjectCode}-` : '';
605
+ const dirNameNew = `${scaffoldPrefix}${padded}-${slug}`;
606
+ assertSafePhaseDirName(dirNameNew, 'scaffold phase directory');
607
+ const phasesParent = planningPaths(projectDir, workstream).phases;
608
+ await mkdir(phasesParent, { recursive: true });
609
+ const dirPath = join(phasesParent, dirNameNew);
610
+ await ensureDirectoryWithGitkeep(dirPath);
611
+ return {
612
+ data: {
613
+ created: true,
614
+ directory: toPosixPath(relative(projectDir, dirPath)),
615
+ path: dirPath,
616
+ },
617
+ };
618
+ }
619
+ // For context/uat/verification types, find the phase directory
620
+ const phaseInfo = phase ? await findPhaseDir(projectDir, phase, workstream) : null;
621
+ if (phase && !phaseInfo) {
622
+ throw new GSDError(`Phase ${phase} directory not found`, ErrorClassification.Blocked);
623
+ }
624
+ const phaseDir = phaseInfo.dirPath;
625
+ const phaseName = name || phaseInfo?.phaseName || 'Unnamed';
626
+ let filePath;
627
+ let content;
628
+ switch (type) {
629
+ case 'context': {
630
+ filePath = join(phaseDir, `${padded}-CONTEXT.md`);
631
+ content = `---\nphase: "${padded}"\nname: "${phaseName}"\ncreated: ${today}\n---\n\n# Phase ${phase}: ${phaseName} — Context\n\n## Decisions\n\n_Decisions will be captured during /gsd-discuss-phase ${phase}_\n\n## Discretion Areas\n\n_Areas where the executor can use judgment_\n\n## Deferred Ideas\n\n_Ideas to consider later_\n`;
632
+ break;
633
+ }
634
+ case 'uat': {
635
+ filePath = join(phaseDir, `${padded}-UAT.md`);
636
+ content = `---\nphase: "${padded}"\nname: "${phaseName}"\ncreated: ${today}\nstatus: pending\n---\n\n# Phase ${phase}: ${phaseName} — User Acceptance Testing\n\n## Test Results\n\n| # | Test | Status | Notes |\n|---|------|--------|-------|\n\n## Summary\n\n_Pending UAT_\n`;
637
+ break;
638
+ }
639
+ case 'verification': {
640
+ filePath = join(phaseDir, `${padded}-VERIFICATION.md`);
641
+ content = `---\nphase: "${padded}"\nname: "${phaseName}"\ncreated: ${today}\nstatus: pending\n---\n\n# Phase ${phase}: ${phaseName} — Verification\n\n## Goal-Backward Verification\n\n**Phase Goal:** [From ROADMAP.md]\n\n## Checks\n\n| # | Requirement | Status | Evidence |\n|---|------------|--------|----------|\n\n## Result\n\n_Pending verification_\n`;
642
+ break;
643
+ }
644
+ default:
645
+ throw new GSDError(`Unknown scaffold type: ${type}`, ErrorClassification.Validation);
646
+ }
647
+ // Check if file already exists
648
+ if (existsSync(filePath)) {
649
+ return {
650
+ data: {
651
+ created: false,
652
+ reason: 'already_exists',
653
+ path: filePath,
654
+ },
655
+ };
656
+ }
657
+ await writeFile(filePath, content, 'utf-8');
658
+ const relPath = toPosixPath(relative(projectDir, filePath));
659
+ return { data: { created: true, path: relPath } };
660
+ };
661
+ // ─── renameDecimalPhases ───────────────────────────────────────────────
662
+ /**
663
+ * Renumber sibling decimal phases after a decimal phase is removed.
664
+ *
665
+ * Port of renameDecimalPhases from phase.cjs lines 499-524.
666
+ * e.g. removing 06.2 -> 06.3 becomes 06.2, 06.4 becomes 06.3, etc.
667
+ * Renames directories AND files inside them that contain the old phase ID.
668
+ *
669
+ * CRITICAL: Sorted in DESCENDING order to avoid rename conflicts.
670
+ *
671
+ * @param phasesDir - Path to the phases directory
672
+ * @param baseInt - The integer part of the decimal phase (e.g. "06")
673
+ * @param removedDecimal - The decimal part that was removed (e.g. 2 for 06.2)
674
+ * @returns { renamedDirs, renamedFiles }
675
+ */
676
+ async function renameDecimalPhases(phasesDir, baseInt, removedDecimal) {
677
+ const renamedDirs = [];
678
+ const renamedFiles = [];
679
+ const decPattern = new RegExp(`^${escapeRegex(baseInt)}\\.(\\d+)-(.+)$`);
680
+ const entries = await readdir(phasesDir, { withFileTypes: true });
681
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
682
+ const toRename = dirs
683
+ .map(dir => {
684
+ const m = dir.match(decPattern);
685
+ return m ? { dir, oldDecimal: parseInt(m[1], 10), slug: m[2] } : null;
686
+ })
687
+ .filter((item) => item !== null && item.oldDecimal > removedDecimal)
688
+ .sort((a, b) => b.oldDecimal - a.oldDecimal); // DESCENDING to avoid conflicts
689
+ for (const item of toRename) {
690
+ const newDecimal = item.oldDecimal - 1;
691
+ const oldPhaseId = `${baseInt}.${item.oldDecimal}`;
692
+ const newPhaseId = `${baseInt}.${newDecimal}`;
693
+ const newDirName = `${baseInt}.${newDecimal}-${item.slug}`;
694
+ await rename(join(phasesDir, item.dir), join(phasesDir, newDirName));
695
+ renamedDirs.push({ from: item.dir, to: newDirName });
696
+ // Rename files inside that contain the old phase ID
697
+ const files = await readdir(join(phasesDir, newDirName));
698
+ for (const f of files) {
699
+ if (f.includes(oldPhaseId)) {
700
+ const newFileName = f.replace(oldPhaseId, newPhaseId);
701
+ await rename(join(phasesDir, newDirName, f), join(phasesDir, newDirName, newFileName));
702
+ renamedFiles.push({ from: f, to: newFileName });
703
+ }
704
+ }
705
+ }
706
+ return { renamedDirs, renamedFiles };
707
+ }
708
+ // ─── renameIntegerPhases ───────────────────────────────────────────────
709
+ /**
710
+ * Renumber all integer phases after a removed integer phase.
711
+ *
712
+ * Port of renameIntegerPhases from phase.cjs lines 531-564.
713
+ * e.g. removing phase 5 -> phase 6 becomes 5, phase 7 becomes 6, etc.
714
+ * Handles letter suffixes (12A) and decimals (6.1).
715
+ *
716
+ * CRITICAL: Sorted in DESCENDING order to avoid rename conflicts.
717
+ *
718
+ * @param phasesDir - Path to the phases directory
719
+ * @param removedInt - The integer phase number that was removed
720
+ * @returns { renamedDirs, renamedFiles }
721
+ */
722
+ async function renameIntegerPhases(phasesDir, removedInt) {
723
+ const renamedDirs = [];
724
+ const renamedFiles = [];
725
+ const entries = await readdir(phasesDir, { withFileTypes: true });
726
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
727
+ const toRename = dirs
728
+ .map(dir => {
729
+ const m = dir.match(/^(\d+)([A-Z])?(?:\.(\d+))?-(.+)$/i);
730
+ if (!m)
731
+ return null;
732
+ const dirInt = parseInt(m[1], 10);
733
+ // CJS parity: skip backlog phases (999.x). These are parked ideas with a
734
+ // numbering convention that lives outside the active sequence; renumbering
735
+ // them would clobber the convention and corrupt downstream lookups.
736
+ // (bug-2434)
737
+ if (dirInt <= removedInt || dirInt >= 999)
738
+ return null;
739
+ return {
740
+ dir,
741
+ oldInt: dirInt,
742
+ letter: m[2] ? m[2].toUpperCase() : '',
743
+ decimal: m[3] !== undefined ? parseInt(m[3], 10) : null,
744
+ slug: m[4],
745
+ };
746
+ })
747
+ .filter((item) => item !== null)
748
+ .sort((a, b) => a.oldInt !== b.oldInt
749
+ ? b.oldInt - a.oldInt
750
+ : (b.decimal ?? 0) - (a.decimal ?? 0)); // DESCENDING
751
+ for (const item of toRename) {
752
+ const newInt = item.oldInt - 1;
753
+ const newPadded = String(newInt).padStart(2, '0');
754
+ const oldPadded = String(item.oldInt).padStart(2, '0');
755
+ const letterSuffix = item.letter || '';
756
+ const decimalSuffix = item.decimal !== null ? `.${item.decimal}` : '';
757
+ const oldPrefix = `${oldPadded}${letterSuffix}${decimalSuffix}`;
758
+ const newPrefix = `${newPadded}${letterSuffix}${decimalSuffix}`;
759
+ const newDirName = `${newPrefix}-${item.slug}`;
760
+ await rename(join(phasesDir, item.dir), join(phasesDir, newDirName));
761
+ renamedDirs.push({ from: item.dir, to: newDirName });
762
+ // Rename files that start with the old prefix
763
+ const files = await readdir(join(phasesDir, newDirName));
764
+ for (const f of files) {
765
+ if (f.startsWith(oldPrefix)) {
766
+ const newFileName = newPrefix + f.slice(oldPrefix.length);
767
+ await rename(join(phasesDir, newDirName, f), join(phasesDir, newDirName, newFileName));
768
+ renamedFiles.push({ from: f, to: newFileName });
769
+ }
770
+ }
771
+ }
772
+ return { renamedDirs, renamedFiles };
773
+ }
774
+ // ─── updateRoadmapAfterPhaseRemoval ────────────────────────────────────
775
+ /**
776
+ * Decrement integer phase number while skipping non-renumbered ranges. Mirrors
777
+ * `decrementRoadmapPhaseNumber` in phase.cjs lines 860-864.
778
+ *
779
+ * Skips when:
780
+ * • not an integer
781
+ * • num <= removedInt (already-renumbered phases stay put)
782
+ * • num >= 999 (backlog/parked-idea numbering range)
783
+ *
784
+ * Returns the original raw string when the guards trip so the regex pass
785
+ * leaves dates and unrelated numerics intact.
786
+ */
787
+ function decrementRoadmapPhaseNumber(raw, removedInt) {
788
+ const num = parseInt(raw, 10);
789
+ if (!Number.isInteger(num) || num <= removedInt || num >= 999)
790
+ return raw;
791
+ return String(num - 1);
792
+ }
793
+ /**
794
+ * Decrement integer or decimal phase token (e.g. "5" or "5.2"). Mirrors
795
+ * `decrementRoadmapPhaseToken` in phase.cjs lines 866-872 — preserves the
796
+ * decimal suffix when present and applies the same guards.
797
+ */
798
+ function decrementRoadmapPhaseToken(raw, removedInt) {
799
+ const match = String(raw).match(/^(\d+)(\.\d+)?$/);
800
+ if (!match)
801
+ return raw;
802
+ const num = parseInt(match[1], 10);
803
+ if (!Number.isInteger(num) || num <= removedInt || num >= 999)
804
+ return raw;
805
+ return `${num - 1}${match[2] || ''}`;
806
+ }
807
+ /**
808
+ * Decrement zero-padded phase number while preserving the original pad width.
809
+ * Mirrors `decrementRoadmapPaddedPhaseNumber` in phase.cjs lines 874-878.
810
+ */
811
+ function decrementRoadmapPaddedPhaseNumber(raw, removedInt) {
812
+ const num = parseInt(raw, 10);
813
+ if (!Number.isInteger(num) || num <= removedInt || num >= 999)
814
+ return raw;
815
+ return String(num - 1).padStart(raw.length, '0');
816
+ }
817
+ /**
818
+ * Remove a phase section from ROADMAP.md and renumber subsequent integer phases.
819
+ *
820
+ * Port of updateRoadmapAfterPhaseRemoval from phase.cjs lines 880-922.
821
+ * Uses readModifyWriteRoadmapMd for atomic writes.
822
+ *
823
+ * The renumbering pass uses **5 targeted regex replacements** (not a loop)
824
+ * because the loop approach is dangerous:
825
+ * • It can match YYYY-MM-DD substrings and corrupt dates (bug-2435).
826
+ * • It can rename backlog phases (999.x) that should stay frozen (bug-2434).
827
+ * • It can renumber the same phase multiple times if the regex matches
828
+ * overlap (bug-3355 — phase 7 → 6 → 5 → ...).
829
+ *
830
+ * The CJS pattern uses negative lookbehind/ahead on the padded-prefix regex
831
+ * to skip dates and decrement helpers that guard against `num >= 999`. Keep
832
+ * this implementation byte-for-byte in lockstep with phase.cjs:880-922 —
833
+ * deviations are how the three bugs above slipped in.
834
+ *
835
+ * @param projectDir - Project root directory
836
+ * @param targetPhase - Phase identifier that was removed
837
+ * @param isDecimal - Whether the removed phase was a decimal phase
838
+ * @param removedInt - The integer part of the removed phase
839
+ */
840
+ async function updateRoadmapAfterPhaseRemoval(projectDir, targetPhase, isDecimal, removedInt, workstream) {
841
+ await readModifyWriteRoadmapMd(projectDir, (content) => {
842
+ const escaped = escapeRegex(targetPhase);
843
+ // Remove the phase section (header + body until next phase header or end).
844
+ //
845
+ // #3601: the end-of-section lookahead is DEPTH-AWARE. The named capture
846
+ // (?<h>#{2,4}) records the hash count of the header being removed and the
847
+ // lookahead requires the same depth via \k<h>(?!#). Two contracts are
848
+ // preserved:
849
+ //
850
+ // (#3601 case) Remove `### Phase 2:` and stop at `### Phase 2.1:` —
851
+ // Phase 2.1 is a peer-level decimal phase (depth 3) and must survive.
852
+ //
853
+ // (#3355 case) Remove `### Phase 27:` and CONTINUE past
854
+ // `#### Phase 27.1:` (depth 4 — child of Phase 27) until the next
855
+ // depth-3 header. The child decimal is part of the integer phase
856
+ // being removed.
857
+ //
858
+ // The `(?!#)` negative lookahead after the backreference prevents the
859
+ // depth-3 match from being satisfied by a depth-4+ header that starts
860
+ // with the same three hashes. `[^\n:]+` accepts numeric, decimal, AND
861
+ // custom phase IDs (PROJ-42) as terminators.
862
+ content = content.replace(new RegExp(`\\n?(?<h>#{2,4})\\s*Phase\\s+${escaped}\\s*:[\\s\\S]*?(?=\\n\\k<h>(?!#)\\s+Phase\\s+[^\\n:]+\\s*:|$)`, 'i'), '');
863
+ // Remove checkbox lines referencing the phase
864
+ content = content.replace(new RegExp(`\\n?-\\s*\\[[ x]\\]\\s*.*Phase\\s+${escaped}[:\\s][^\\n]*`, 'gi'), '');
865
+ // Remove table rows referencing the phase
866
+ content = content.replace(new RegExp(`\\n?\\|\\s*${escaped}\\.?\\s[^|]*\\|[^\\n]*`, 'gi'), '');
867
+ if (!isDecimal) {
868
+ // Phase headers: ### Phase N: / ### Phase N.M:
869
+ content = content.replace(/(#{2,4}\s*Phase\s+)(\d+(?:\.\d+)?)(\s*:)/gi, (_match, prefix, num, suffix) => `${prefix}${decrementRoadmapPhaseToken(num, removedInt)}${suffix}`);
870
+ // Checkbox-list summary references: `- [ ] Phase N:`
871
+ content = content.replace(/(-\s*\[[ x]\]\s*.*?Phase\s+)(\d+)(\s*:|\s+)/gi, (_match, prefix, num, suffix) => `${prefix}${decrementRoadmapPhaseNumber(num, removedInt)}${suffix}`);
872
+ // Table-row phase numbers: `| N. ` — bare integer in a cell.
873
+ content = content.replace(/(\|\s*)(\d+)(\.\s)/g, (_match, prefix, num, suffix) => `${prefix}${decrementRoadmapPhaseNumber(num, removedInt)}${suffix}`);
874
+ // Padded plan references: NN-NN (optionally followed by an arbitrary
875
+ // kebab-case slug, then -PLAN.md / -SUMMARY.md).
876
+ //
877
+ // #2435: negative lookbehind `(?<![0-9-])` and negative lookahead
878
+ // `(?![0-9-])` exclude YYYY-MM-DD substrings.
879
+ //
880
+ // #3602: the original pattern only allowed a compact `-(PLAN|SUMMARY).md`
881
+ // immediately after the plan number; a slug between the number and the
882
+ // `-PLAN.md` / `-SUMMARY.md` suffix (e.g.
883
+ // `07-01-cherry-pick-foundation-PLAN.md`) made the lookahead fail and
884
+ // left the stale `07-01-` prefix in ROADMAP text while the on-disk file
885
+ // was already renumbered to `06-01-…`. The slug segment
886
+ // `(?:-[A-Za-z][A-Za-z0-9-]*)*` allows any number of kebab-case tokens
887
+ // before the canonical PLAN/SUMMARY suffix.
888
+ content = content.replace(/(?<![0-9-])(\d{2})-(\d{2})(?=(?:(?:-[A-Za-z][A-Za-z0-9-]*)*-(?:PLAN|SUMMARY)\.md)?(?![0-9-]))/g, (_match, phaseNum, planNum) => `${decrementRoadmapPaddedPhaseNumber(phaseNum, removedInt)}-${planNum}`);
889
+ // Depends-on references — two bold-colon variants in the wild.
890
+ content = content.replace(/(\*\*Depends on\*\*\s*:\s*Phase\s+)(\d+(?:\.\d+)?)\b/gi, (_match, prefix, num) => `${prefix}${decrementRoadmapPhaseToken(num, removedInt)}`);
891
+ content = content.replace(/(Depends on:\*\*\s*Phase\s+)(\d+(?:\.\d+)?)\b/gi, (_match, prefix, num) => `${prefix}${decrementRoadmapPhaseToken(num, removedInt)}`);
892
+ }
893
+ return content;
894
+ }, workstream);
895
+ }
896
+ // ─── phaseRemove handler ───────────────────────────────────────────────
897
+ /**
898
+ * Query handler for phase.remove.
899
+ *
900
+ * Port of cmdPhaseRemove from phase.cjs lines 597-661.
901
+ * Deletes phase directory, renumbers subsequent phases on disk,
902
+ * updates ROADMAP.md (removes section + renumbers), and decrements
903
+ * STATE.md total_phases count.
904
+ *
905
+ * @param args - args[0]: targetPhase (required), args[1]: '--force' (optional)
906
+ * @param projectDir - Project root directory
907
+ * @returns QueryResult with { removed, directory_deleted, renamed_directories, renamed_files, roadmap_updated, state_updated }
908
+ */
909
+ export const phaseRemove = async (args, projectDir, workstream) => {
910
+ let force = false;
911
+ const positional = [];
912
+ for (const token of args) {
913
+ if (token === '--force') {
914
+ force = true;
915
+ continue;
916
+ }
917
+ if (token.startsWith('--')) {
918
+ throw new GSDError(`phase remove does not support ${token}`, ErrorClassification.Validation);
919
+ }
920
+ positional.push(token);
921
+ }
922
+ if (positional.length > 1) {
923
+ throw new GSDError('phase remove accepts exactly one phase number', ErrorClassification.Validation);
924
+ }
925
+ const targetPhase = positional[0];
926
+ if (!targetPhase) {
927
+ throw new GSDError('phase number required for phase remove', ErrorClassification.Validation);
928
+ }
929
+ assertNoNullBytes(targetPhase, 'targetPhase');
930
+ const paths = planningPaths(projectDir, workstream);
931
+ const phasesDir = paths.phases;
932
+ if (!existsSync(paths.roadmap)) {
933
+ throw new GSDError('ROADMAP.md not found', ErrorClassification.Validation);
934
+ }
935
+ const normalized = normalizePhaseName(targetPhase);
936
+ const isDecimal = targetPhase.includes('.');
937
+ // Find target directory
938
+ const entries = await readdir(phasesDir, { withFileTypes: true });
939
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
940
+ const targetDir = dirs.find(d => phaseTokenMatches(d, normalized)) ?? null;
941
+ if (!targetDir) {
942
+ throw new GSDError(`Phase ${targetPhase} not found`, ErrorClassification.Validation);
943
+ }
944
+ // Guard against removing executed work
945
+ if (!force) {
946
+ const files = await readdir(join(phasesDir, targetDir));
947
+ const summaries = files.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md');
948
+ if (summaries.length > 0) {
949
+ throw new GSDError(`Phase ${targetPhase} has ${summaries.length} executed plan(s). Use --force to remove anyway.`, ErrorClassification.Validation);
950
+ }
951
+ }
952
+ // Delete directory
953
+ await rm(join(phasesDir, targetDir), { recursive: true, force: true });
954
+ // Renumber subsequent phases on disk
955
+ let renamedDirs = [];
956
+ let renamedFiles = [];
957
+ try {
958
+ let renamed;
959
+ if (isDecimal) {
960
+ const parts = normalized.split('.');
961
+ if (parts.length < 2 || !parts[1]) {
962
+ throw new GSDError(`Invalid decimal phase identifier: ${targetPhase}`, ErrorClassification.Validation);
963
+ }
964
+ const decimalPart = parseInt(parts[1], 10);
965
+ if (isNaN(decimalPart)) {
966
+ throw new GSDError(`Invalid decimal part in phase: ${targetPhase}`, ErrorClassification.Validation);
967
+ }
968
+ renamed = await renameDecimalPhases(phasesDir, parts[0], decimalPart);
969
+ }
970
+ else {
971
+ renamed = await renameIntegerPhases(phasesDir, parseInt(normalized, 10));
972
+ }
973
+ renamedDirs = renamed.renamedDirs;
974
+ renamedFiles = renamed.renamedFiles;
975
+ }
976
+ catch { /* intentionally empty — renaming is best-effort */ }
977
+ // Update ROADMAP.md
978
+ await updateRoadmapAfterPhaseRemoval(projectDir, targetPhase, isDecimal, parseInt(normalized, 10), workstream);
979
+ // Update STATE.md: decrement total_phases
980
+ let stateUpdated = false;
981
+ const statePath = paths.state;
982
+ if (existsSync(statePath)) {
983
+ const lockPath = await acquireStateLock(statePath);
984
+ try {
985
+ let stateContent = await readFile(statePath, 'utf-8');
986
+ // Decrement total_phases in frontmatter
987
+ const totalPhasesMatch = stateContent.match(/total_phases:\s*(\d+)/);
988
+ if (totalPhasesMatch) {
989
+ const oldTotal = parseInt(totalPhasesMatch[1], 10);
990
+ stateContent = stateContent.replace(/total_phases:\s*\d+/, `total_phases: ${oldTotal - 1}`);
991
+ }
992
+ // Decrement "of N" pattern in body (e.g., "Plan: 2 of 3")
993
+ const ofMatch = stateContent.match(/(\bof\s+)(\d+)(\s*(?:\(|phases?))/i);
994
+ if (ofMatch) {
995
+ stateContent = stateContent.replace(/(\bof\s+)(\d+)(\s*(?:\(|phases?))/i, `$1${parseInt(ofMatch[2], 10) - 1}$3`);
996
+ }
997
+ // Also try stateReplaceField for "Total Phases" field
998
+ const totalRaw = stateExtractField(stateContent, 'Total Phases');
999
+ if (totalRaw) {
1000
+ const replaced = stateReplaceField(stateContent, 'Total Phases', String(parseInt(totalRaw, 10) - 1));
1001
+ if (replaced)
1002
+ stateContent = replaced;
1003
+ }
1004
+ await writeFile(statePath, stateContent, 'utf-8');
1005
+ stateUpdated = true;
1006
+ }
1007
+ finally {
1008
+ await releaseStateLock(lockPath);
1009
+ }
1010
+ }
1011
+ return {
1012
+ data: {
1013
+ removed: targetPhase,
1014
+ directory_deleted: targetDir,
1015
+ renamed_directories: renamedDirs,
1016
+ renamed_files: renamedFiles,
1017
+ roadmap_updated: true,
1018
+ state_updated: stateUpdated,
1019
+ },
1020
+ };
1021
+ };
1022
+ // ─── updatePerformanceMetricsSection ───────────────────────────────────────
1023
+ /**
1024
+ * Update the Performance Metrics section in STATE.md content.
1025
+ *
1026
+ * Port of updatePerformanceMetricsSection from state.cjs lines 1125-1156.
1027
+ * Updates "Total plans completed" counter and upserts a row in the By Phase table.
1028
+ *
1029
+ * @param content - STATE.md content
1030
+ * @param phaseNum - Phase number being completed
1031
+ * @param planCount - Total number of plans in the phase
1032
+ * @param summaryCount - Number of completed summaries
1033
+ * @returns Modified content
1034
+ */
1035
+ function updatePerformanceMetricsSection(content, phaseNum, planCount, summaryCount) {
1036
+ // Update Velocity: Total plans completed
1037
+ const totalMatch = content.match(/Total plans completed:\s*(\d+|\[N\])/);
1038
+ const prevTotal = totalMatch && totalMatch[1] !== '[N]' ? parseInt(totalMatch[1], 10) : 0;
1039
+ const newTotal = prevTotal + summaryCount;
1040
+ content = content.replace(/Total plans completed:\s*(\d+|\[N\])/, `Total plans completed: ${newTotal}`);
1041
+ // Update By Phase table — upsert row for this phase
1042
+ const byPhaseTablePattern = /(\|\s*Phase\s*\|\s*Plans\s*\|\s*Total\s*\|\s*Avg\/Plan\s*\|[ \t]*\n\|(?:[- :\t]+\|)+[ \t]*\n)((?:[ \t]*\|[^\n]*\n)*)(?=\n|$)/i;
1043
+ const byPhaseMatch = content.match(byPhaseTablePattern);
1044
+ if (byPhaseMatch) {
1045
+ let tableBody = byPhaseMatch[2].trim();
1046
+ const phaseRowPattern = new RegExp(`^\\|\\s*${escapeRegex(String(phaseNum))}\\s*\\|.*$`, 'm');
1047
+ const newRow = `| ${phaseNum} | ${summaryCount} | - | - |`;
1048
+ if (phaseRowPattern.test(tableBody)) {
1049
+ // Update existing row
1050
+ tableBody = tableBody.replace(new RegExp(`^\\|\\s*${escapeRegex(String(phaseNum))}\\s*\\|.*$`, 'm'), newRow);
1051
+ }
1052
+ else {
1053
+ // Remove placeholder row and add new row
1054
+ tableBody = tableBody.replace(/^\|\s*-\s*\|\s*-\s*\|\s*-\s*\|\s*-\s*\|$/m, '').trim();
1055
+ tableBody = tableBody ? tableBody + '\n' + newRow : newRow;
1056
+ }
1057
+ content = content.replace(byPhaseTablePattern, `$1${tableBody}\n`);
1058
+ }
1059
+ return content;
1060
+ }
1061
+ // ─── phaseComplete handler ────────────────────────────────────────────────
1062
+ /**
1063
+ * Query handler for phase.complete.
1064
+ *
1065
+ * Port of cmdPhaseComplete from phase.cjs lines 663-932.
1066
+ * Marks a phase as done — updates ROADMAP.md (checkbox, progress table,
1067
+ * plan count, plan checkboxes), REQUIREMENTS.md (requirement checkboxes,
1068
+ * traceability table), and STATE.md (current phase, status, progress,
1069
+ * performance metrics) atomically with per-file locks.
1070
+ *
1071
+ * @param args - args[0]: phaseNum (required)
1072
+ * @param projectDir - Project root directory
1073
+ * @returns QueryResult with completion details and warnings
1074
+ */
1075
+ export const phaseComplete = async (args, projectDir, workstream) => {
1076
+ const phaseNum = args[0];
1077
+ if (!phaseNum) {
1078
+ throw new GSDError('phase number required for phase complete', ErrorClassification.Validation);
1079
+ }
1080
+ assertNoNullBytes(phaseNum, 'phaseNum');
1081
+ const paths = planningPaths(projectDir, workstream);
1082
+ const today = new Date().toISOString().split('T')[0];
1083
+ // Step A: Validate phase exists and get info
1084
+ const phaseInfo = await findPhaseDir(projectDir, phaseNum, workstream);
1085
+ if (!phaseInfo) {
1086
+ throw new GSDError(`Phase ${phaseNum} not found`, ErrorClassification.Validation);
1087
+ }
1088
+ const phaseDir = phaseInfo.dirPath;
1089
+ let phaseFiles;
1090
+ try {
1091
+ phaseFiles = await readdir(phaseDir);
1092
+ }
1093
+ catch {
1094
+ phaseFiles = [];
1095
+ }
1096
+ const plans = phaseFiles.filter(f => f.endsWith('-PLAN.md') || f === 'PLAN.md');
1097
+ const summaries = phaseFiles.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md');
1098
+ const planCount = plans.length;
1099
+ const summaryCount = summaries.length;
1100
+ let requirementsUpdated = false;
1101
+ // Step B: Check for verification warnings (non-blocking)
1102
+ const warnings = [];
1103
+ for (const file of phaseFiles.filter(f => f.includes('-UAT') && f.endsWith('.md'))) {
1104
+ try {
1105
+ const content = await readFile(join(phaseDir, file), 'utf-8');
1106
+ if (/result: pending/.test(content))
1107
+ warnings.push(`${file}: has pending tests`);
1108
+ if (/result: blocked/.test(content))
1109
+ warnings.push(`${file}: has blocked tests`);
1110
+ if (/status: partial/.test(content))
1111
+ warnings.push(`${file}: testing incomplete (partial)`);
1112
+ if (/status: diagnosed/.test(content))
1113
+ warnings.push(`${file}: has diagnosed gaps`);
1114
+ }
1115
+ catch { /* intentionally empty */ }
1116
+ }
1117
+ for (const file of phaseFiles.filter(f => f.includes('-VERIFICATION') && f.endsWith('.md'))) {
1118
+ try {
1119
+ const content = await readFile(join(phaseDir, file), 'utf-8');
1120
+ if (/status: human_needed/.test(content))
1121
+ warnings.push(`${file}: needs human verification`);
1122
+ if (/status: gaps_found/.test(content))
1123
+ warnings.push(`${file}: has unresolved gaps`);
1124
+ }
1125
+ catch { /* intentionally empty */ }
1126
+ }
1127
+ // Step C: Update ROADMAP.md atomically
1128
+ if (existsSync(paths.roadmap)) {
1129
+ await readModifyWriteRoadmapMd(projectDir, async (roadmapContent) => {
1130
+ // Padding-tolerant fragment so a padded input like "02.7" still matches
1131
+ // un-padded ROADMAP prose ("### Phase 2.7:"). CJS routes every phase-
1132
+ // number ROADMAP regex through phaseMarkdownRegexSource (#3537) —
1133
+ // mirror that contract here so phase.complete with the padded form
1134
+ // produces the same ROADMAP as the un-padded form.
1135
+ const phaseEscaped = phaseMarkdownRegexSource(phaseNum);
1136
+ // Checkbox: - [ ] Phase N: -> - [x] Phase N: (...completed DATE)
1137
+ // CJS parity (phase.cjs): direct replace, NOT scoped through
1138
+ // replaceInCurrentMilestone. Same reasoning as the plan-count
1139
+ // update below — milestone wrapped in <details> would otherwise be
1140
+ // skipped (bug-2005).
1141
+ const checkboxPattern = new RegExp(`(-\\s*\\[)[ ](\\]\\s*.*Phase\\s+${phaseEscaped}[:\\s][^\\n]*)`, 'i');
1142
+ roadmapContent = roadmapContent.replace(checkboxPattern, `$1x$2 (completed ${today})`);
1143
+ // Progress table: update Status to Complete, add date
1144
+ const tableRowPattern = new RegExp(`^(\\|\\s*${phaseEscaped}\\.?\\s[^|]*(?:\\|[^\\n]*))$`, 'im');
1145
+ roadmapContent = roadmapContent.replace(tableRowPattern, (fullRow) => {
1146
+ const cells = fullRow.split('|').slice(1, -1);
1147
+ if (cells.length === 5) {
1148
+ cells[2] = ` ${summaryCount}/${planCount} `;
1149
+ cells[3] = ' Complete ';
1150
+ cells[4] = ` ${today} `;
1151
+ }
1152
+ else if (cells.length === 4) {
1153
+ cells[1] = ` ${summaryCount}/${planCount} `;
1154
+ cells[2] = ' Complete ';
1155
+ cells[3] = ` ${today} `;
1156
+ }
1157
+ return '|' + cells.join('|') + '|';
1158
+ });
1159
+ // Update plan count in phase section.
1160
+ // CJS parity (phase.cjs:1076-1083): direct replace, NOT scoped through
1161
+ // replaceInCurrentMilestone. Scoping to "after last </details>" fails
1162
+ // when the current milestone itself is wrapped in <details open>...
1163
+ // </details> — there's no content after the close tag, so the regex
1164
+ // never matches and **Plans:** stays at 0/N (bug-2005).
1165
+ const planCountPattern = new RegExp(`(#{2,4}\\s*Phase\\s+${phaseEscaped}(?:(?!\\n#{2,4})[\\s\\S])*?\\*\\*Plans:\\*\\*[ \\t]*)[^\\n]+`, 'i');
1166
+ roadmapContent = roadmapContent.replace(planCountPattern, `$1${summaryCount}/${planCount} plans complete`);
1167
+ // Mark completed plan checkboxes
1168
+ for (const summaryFile of summaries) {
1169
+ const planId = summaryFile.replace('-SUMMARY.md', '').replace('SUMMARY.md', '');
1170
+ if (!planId)
1171
+ continue;
1172
+ const planEscaped = escapeRegex(planId);
1173
+ const planCheckboxPattern = new RegExp(`(-\\s*\\[) (\\]\\s*(?:\\*\\*)?${planEscaped}(?:\\*\\*)?)`, 'i');
1174
+ roadmapContent = roadmapContent.replace(planCheckboxPattern, '$1x$2');
1175
+ }
1176
+ // Step D: Update REQUIREMENTS.md
1177
+ const reqPath = paths.requirements;
1178
+ if (existsSync(reqPath)) {
1179
+ const currentMilestoneRoadmap = await extractCurrentMilestone(roadmapContent, projectDir);
1180
+ const phaseSectionMatch = currentMilestoneRoadmap.match(new RegExp(`(#{2,4}\\s*Phase\\s+${phaseEscaped}[:\\s][\\s\\S]*?)(?=#{2,4}\\s*Phase\\s+|$)`, 'i'));
1181
+ const sectionText = phaseSectionMatch ? phaseSectionMatch[1] : '';
1182
+ const reqMatch = sectionText.match(/\*\*Requirements\*?\*?:?\s*([^\n]+)/i);
1183
+ let reqContent = await readFile(reqPath, 'utf-8');
1184
+ let reqContentChanged = false;
1185
+ if (reqMatch) {
1186
+ const reqIds = reqMatch[1].replace(/[[\]]/g, '').split(/[,\s]+/).map(r => r.trim()).filter(Boolean);
1187
+ for (const reqId of reqIds) {
1188
+ const reqEscaped = escapeRegex(reqId);
1189
+ const before = reqContent;
1190
+ // Update checkbox: - [ ] **REQ-ID** -> - [x] **REQ-ID**
1191
+ reqContent = reqContent.replace(new RegExp(`(-\\s*\\[)[ ](\\]\\s*\\*\\*${reqEscaped}\\*\\*)`, 'gi'), '$1x$2');
1192
+ // Update traceability table: Pending/In Progress -> Complete
1193
+ reqContent = reqContent.replace(new RegExp(`(\\|\\s*${reqEscaped}\\s*\\|[^|]+\\|)\\s*(?:Pending|In Progress)\\s*(\\|)`, 'gi'), '$1 Complete $2');
1194
+ if (reqContent !== before)
1195
+ reqContentChanged = true;
1196
+ }
1197
+ }
1198
+ // Bug #2526 parity (phase.cjs:1140-1167): independent of whether the
1199
+ // roadmap declared a Requirements: line, scan the REQUIREMENTS.md
1200
+ // body for `**REQ-ID**` references and compare against the IDs that
1201
+ // actually appear in the Traceability table. Surface every body
1202
+ // ID that has no traceability row so the operator can keep the
1203
+ // table in sync.
1204
+ const bodyReqIds = [];
1205
+ const bodyReqPattern = /\*\*([A-Z][A-Z0-9]*-\d+)\*\*/g;
1206
+ let bodyMatch;
1207
+ while ((bodyMatch = bodyReqPattern.exec(reqContent)) !== null) {
1208
+ if (!bodyReqIds.includes(bodyMatch[1]))
1209
+ bodyReqIds.push(bodyMatch[1]);
1210
+ }
1211
+ const traceabilityHeadingMatch = reqContent.match(/^#{1,6}\s+Traceability\b/im);
1212
+ const traceabilitySection = traceabilityHeadingMatch
1213
+ ? reqContent.slice(traceabilityHeadingMatch.index)
1214
+ : '';
1215
+ const tableReqIds = new Set();
1216
+ const tableRowPattern = /^\|\s*([A-Z][A-Z0-9]*-\d+)\s*\|/gm;
1217
+ let tableMatch;
1218
+ while ((tableMatch = tableRowPattern.exec(traceabilitySection)) !== null) {
1219
+ tableReqIds.add(tableMatch[1]);
1220
+ }
1221
+ const unregistered = bodyReqIds.filter((id) => !tableReqIds.has(id));
1222
+ if (unregistered.length > 0) {
1223
+ warnings.push(`REQUIREMENTS.md: ${unregistered.length} REQ-ID(s) found in body but missing from Traceability table: ${unregistered.join(', ')} — add them manually to keep traceability in sync`);
1224
+ }
1225
+ if (reqContentChanged) {
1226
+ await writeFile(reqPath, reqContent, 'utf-8');
1227
+ requirementsUpdated = true;
1228
+ }
1229
+ }
1230
+ return roadmapContent;
1231
+ }, workstream);
1232
+ }
1233
+ // Step E: Find next phase — filesystem first, then ROADMAP.md fallback
1234
+ let nextPhaseNum = null;
1235
+ let nextPhaseName = null;
1236
+ let isLastPhase = true;
1237
+ // Tracks whether the completed phase belongs to the primary milestone in STATE.md.
1238
+ // When false (parallel-milestone case, Bug #2676), the milestone filter is bypassed
1239
+ // for next-phase detection so phases from the same secondary milestone are visible.
1240
+ let completedPhaseInPrimaryMilestone = true;
1241
+ try {
1242
+ const isDirInMilestone = await getMilestonePhaseFilter(projectDir, workstream);
1243
+ const entries = await readdir(paths.phases, { withFileTypes: true });
1244
+ const allDirs = entries.filter(e => e.isDirectory()).map(e => e.name);
1245
+ // Guard: if the completed phase's directory is not in the current-milestone filter
1246
+ // set, the filter was built from a different (primary) milestone in STATE.md.
1247
+ // In that case skip the filter so we can find the true next phase on disk.
1248
+ // This handles parallel-milestone workflows where STATE.md's `milestone:` field
1249
+ // points at the primary milestone but the phase being completed belongs to a
1250
+ // secondary in-flight milestone. (Bug #2676)
1251
+ const completedDirInFilter = allDirs.some((d) => {
1252
+ const dm = d.match(/^(\d+[A-Z]?(?:\.\d+)*)-?/i);
1253
+ return dm && comparePhaseNum(dm[1], phaseNum) === 0 && isDirInMilestone(d);
1254
+ });
1255
+ completedPhaseInPrimaryMilestone = completedDirInFilter;
1256
+ const effectiveFilter = completedDirInFilter ? isDirInMilestone : (_d) => true;
1257
+ const dirs = allDirs
1258
+ .filter(effectiveFilter)
1259
+ .sort((a, b) => comparePhaseNum(a, b));
1260
+ for (const dir of dirs) {
1261
+ const dm = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)-?(.*)/i);
1262
+ if (dm) {
1263
+ // Bug #2129 parity: skip backlog phases (999.x). They are parked
1264
+ // ideas with reserved numbering, not part of the active sequence.
1265
+ // Without this, completing phase 2 in a project that has a 999.1
1266
+ // backlog directory would jump next_phase to 999.1 instead of the
1267
+ // intended Phase 3 from ROADMAP.
1268
+ if (/^999(?:\.|$)/.test(dm[1]))
1269
+ continue;
1270
+ if (comparePhaseNum(dm[1], phaseNum) > 0) {
1271
+ nextPhaseNum = dm[1];
1272
+ nextPhaseName = dm[2] || null;
1273
+ isLastPhase = false;
1274
+ break;
1275
+ }
1276
+ }
1277
+ }
1278
+ }
1279
+ catch { /* intentionally empty */ }
1280
+ // Fallback: check ROADMAP.md for phases not yet scaffolded.
1281
+ // When the completed phase is from a parallel (non-primary) milestone, scan the
1282
+ // full ROADMAP rather than the primary-milestone slice so 41.3 is visible when
1283
+ // completing 41.2 for a secondary milestone. (Bug #2676)
1284
+ if (isLastPhase && existsSync(paths.roadmap)) {
1285
+ try {
1286
+ const roadmapContent = await readFile(paths.roadmap, 'utf-8');
1287
+ const roadmapForPhases = completedPhaseInPrimaryMilestone
1288
+ ? await extractCurrentMilestone(roadmapContent, projectDir)
1289
+ : roadmapContent;
1290
+ const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:\s*([^\n]+)/gi;
1291
+ let pm;
1292
+ while ((pm = phasePattern.exec(roadmapForPhases)) !== null) {
1293
+ if (comparePhaseNum(pm[1], phaseNum) > 0) {
1294
+ nextPhaseNum = pm[1];
1295
+ nextPhaseName = pm[2].replace(/\(INSERTED\)/i, '').trim().toLowerCase().replace(/\s+/g, '-');
1296
+ isLastPhase = false;
1297
+ break;
1298
+ }
1299
+ }
1300
+ }
1301
+ catch { /* intentionally empty */ }
1302
+ }
1303
+ // Step F: Update STATE.md atomically
1304
+ let stateUpdated = false;
1305
+ if (existsSync(paths.state)) {
1306
+ const lockPath = await acquireStateLock(paths.state);
1307
+ try {
1308
+ const rawState = await readFile(paths.state, 'utf-8');
1309
+ // Split into frontmatter and body to prevent field replacement from
1310
+ // matching YAML keys (e.g., `status:` in frontmatter vs `Status:` in body).
1311
+ // Pattern 11: Strip frontmatter before modifier (from Phase 11 decisions).
1312
+ const fmMatch = rawState.match(/^(---\r?\n[\s\S]*?\r?\n---)\s*/);
1313
+ let frontmatter = fmMatch ? fmMatch[1] : '';
1314
+ let body = fmMatch ? rawState.slice(fmMatch[0].length) : rawState;
1315
+ // Update Current Phase — preserve "X of Y (Name)" compound format
1316
+ const phaseValue = nextPhaseNum || phaseNum;
1317
+ const existingPhaseField = stateExtractField(body, 'Current Phase')
1318
+ || stateExtractField(body, 'Phase');
1319
+ let newPhaseValue = String(phaseValue);
1320
+ if (existingPhaseField) {
1321
+ const totalMatch = existingPhaseField.match(/of\s+(\d+)/);
1322
+ const nameMatch = existingPhaseField.match(/\(([^)]+)\)/);
1323
+ if (totalMatch) {
1324
+ const total = totalMatch[1];
1325
+ const nameStr = nextPhaseName
1326
+ ? ` (${nextPhaseName.replace(/-/g, ' ')})`
1327
+ : (nameMatch ? ` (${nameMatch[1]})` : '');
1328
+ newPhaseValue = `${phaseValue} of ${total}${nameStr}`;
1329
+ }
1330
+ }
1331
+ body = stateReplaceFieldWithFallback(body, 'Current Phase', 'Phase', newPhaseValue);
1332
+ // Update Status
1333
+ body = stateReplaceFieldWithFallback(body, 'Status', null, isLastPhase ? 'Milestone complete' : 'Ready to plan');
1334
+ // Update Current Plan
1335
+ body = stateReplaceFieldWithFallback(body, 'Current Plan', 'Plan', 'Not started');
1336
+ // Update Last Activity
1337
+ body = stateReplaceFieldWithFallback(body, 'Last Activity', 'Last activity', today);
1338
+ // Update Performance Metrics section (operates on body only)
1339
+ body = updatePerformanceMetricsSection(body, phaseNum, planCount, summaryCount);
1340
+ // ── Root cause 1 fix: derive completed_phases from ROADMAP, not blind increment ──
1341
+ // Read the freshly-updated ROADMAP (after Step C) to count Complete rows.
1342
+ // This makes phase.complete idempotent: running it twice on the same phase
1343
+ // produces the same completed_phases value.
1344
+ let derivedCompletedPhases = null;
1345
+ let derivedTotalPhases = null;
1346
+ let derivedTotalPlans = null;
1347
+ if (existsSync(paths.roadmap)) {
1348
+ try {
1349
+ const freshRoadmap = await readFile(paths.roadmap, 'utf-8');
1350
+ // Count Complete rows in the progress table (Status column = "Complete")
1351
+ const tableCompletePattern = /\|\s*\d+[A-Z]?\S*\s*\|[^|]*\|\s*Complete\s*\|/gi;
1352
+ const completeMatches = freshRoadmap.match(tableCompletePattern);
1353
+ derivedCompletedPhases = completeMatches ? completeMatches.length : null;
1354
+ // Count total phase rows in progress table (header + separator + data rows)
1355
+ // Identify the progress table by looking for Phase|Plans|Status|Completed header
1356
+ const progressTableMatch = freshRoadmap.match(/\|\s*Phase\s*\|\s*Plans\s*\|\s*Status\s*\|\s*Completed\s*\|(.*\n)*?(?:\n|$)/i);
1357
+ if (progressTableMatch) {
1358
+ const tableText = progressTableMatch[0];
1359
+ const dataRowPattern = /^\|\s*\d+[A-Z]?\S*\s*\|/gm;
1360
+ const dataRows = tableText.match(dataRowPattern);
1361
+ derivedTotalPhases = dataRows ? dataRows.length : null;
1362
+ }
1363
+ // Sum plan counts from M/N or 0/N columns in the progress table
1364
+ let totalPlansSum = 0;
1365
+ const planCellPattern = /\|\s*\d+[A-Z]?\S*\s*\|\s*(\d+)\/(\d+)\s*\|/gi;
1366
+ let pm;
1367
+ while ((pm = planCellPattern.exec(freshRoadmap)) !== null) {
1368
+ totalPlansSum += parseInt(pm[2], 10);
1369
+ }
1370
+ if (totalPlansSum > 0)
1371
+ derivedTotalPlans = totalPlansSum;
1372
+ }
1373
+ catch { /* intentionally empty — fall through to existing values */ }
1374
+ }
1375
+ // Count completed plans from all SUMMARY files across phase dirs
1376
+ let derivedCompletedPlans = null;
1377
+ try {
1378
+ const phaseEntries = await readdir(paths.phases, { withFileTypes: true });
1379
+ let summaryTotal = 0;
1380
+ for (const entry of phaseEntries) {
1381
+ if (!entry.isDirectory())
1382
+ continue;
1383
+ try {
1384
+ const files = await readdir(join(paths.phases, entry.name));
1385
+ summaryTotal += files.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md').length;
1386
+ }
1387
+ catch { /* intentionally empty */ }
1388
+ }
1389
+ derivedCompletedPlans = summaryTotal;
1390
+ }
1391
+ catch { /* intentionally empty */ }
1392
+ // ── Root cause 2 fix: update all stale frontmatter fields ──
1393
+ // completed_phases — derived from ROADMAP (idempotent)
1394
+ if (derivedCompletedPhases !== null && frontmatter.includes('completed_phases:')) {
1395
+ frontmatter = frontmatter.replace(/completed_phases:\s*\d+/, `completed_phases: ${derivedCompletedPhases}`);
1396
+ }
1397
+ // total_phases — keep in sync with ROADMAP
1398
+ if (derivedTotalPhases !== null && frontmatter.includes('total_phases:')) {
1399
+ frontmatter = frontmatter.replace(/total_phases:\s*\d+/, `total_phases: ${derivedTotalPhases}`);
1400
+ }
1401
+ // total_plans — derived from ROADMAP plan column sums
1402
+ if (derivedTotalPlans !== null && frontmatter.includes('total_plans:')) {
1403
+ frontmatter = frontmatter.replace(/total_plans:\s*\d+/, `total_plans: ${derivedTotalPlans}`);
1404
+ }
1405
+ // completed_plans — count of SUMMARY files on disk
1406
+ if (derivedCompletedPlans !== null && frontmatter.includes('completed_plans:')) {
1407
+ frontmatter = frontmatter.replace(/completed_plans:\s*\d+/, `completed_plans: ${derivedCompletedPlans}`);
1408
+ }
1409
+ // percent — recompute from fresh derived values
1410
+ const effectiveCompleted = derivedCompletedPhases ?? parseInt(frontmatter.match(/completed_phases:\s*(\d+)/)?.[1] ?? '0', 10);
1411
+ const effectiveTotal = derivedTotalPhases ?? parseInt(frontmatter.match(/total_phases:\s*(\d+)/)?.[1] ?? '0', 10);
1412
+ if (effectiveTotal > 0 && frontmatter.includes('percent:')) {
1413
+ const newPercent = Math.round((effectiveCompleted / effectiveTotal) * 100);
1414
+ frontmatter = frontmatter.replace(/(percent:\s*)\d+/, `$1${newPercent}`);
1415
+ }
1416
+ // last_updated — refresh to current timestamp
1417
+ const nowIso = new Date().toISOString();
1418
+ if (frontmatter.includes('last_updated:')) {
1419
+ frontmatter = frontmatter.replace(/last_updated:\s*\S+/, `last_updated: ${nowIso}`);
1420
+ }
1421
+ // stopped_at — set to phase completion message
1422
+ const stoppedAtValue = isLastPhase
1423
+ ? `Milestone complete (Phase ${phaseNum} was final phase)`
1424
+ : `Phase ${phaseNum} complete (${summaryCount}/${planCount}) — ready to discuss Phase ${nextPhaseNum}`;
1425
+ if (frontmatter.includes('stopped_at:')) {
1426
+ frontmatter = frontmatter.replace(/stopped_at:\s*.+/, `stopped_at: ${stoppedAtValue}`);
1427
+ }
1428
+ else {
1429
+ // Insert stopped_at before closing ---
1430
+ frontmatter = frontmatter.replace(/(---\s*)$/, `stopped_at: ${stoppedAtValue}\n$1`);
1431
+ }
1432
+ // ── Root cause 2 fix: update body Current focus ──
1433
+ const focusValue = isLastPhase
1434
+ ? 'Milestone complete'
1435
+ : (nextPhaseName
1436
+ ? `Phase ${nextPhaseNum} — ${nextPhaseName.replace(/-/g, ' ')}`
1437
+ : `Phase ${nextPhaseNum}`);
1438
+ const focusPattern = /(\*\*Current focus:\*\*\s*).*/i;
1439
+ if (focusPattern.test(body)) {
1440
+ body = body.replace(focusPattern, (_m, prefix) => `${prefix}${focusValue}`);
1441
+ }
1442
+ // Update frontmatter status field
1443
+ frontmatter = frontmatter.replace(/status:\s*.+/, `status: ${isLastPhase ? 'milestone_complete' : 'ready_to_plan'}`);
1444
+ // Reassemble and write
1445
+ const stateContent = frontmatter + '\n\n' + body;
1446
+ await writeFile(paths.state, stateContent, 'utf-8');
1447
+ stateUpdated = true;
1448
+ }
1449
+ finally {
1450
+ await releaseStateLock(lockPath);
1451
+ }
1452
+ }
1453
+ // Step F2: Auto-prune STATE.md decisions when `workflow.auto_prune_state`
1454
+ // is true. Mirrors CJS cmdPhaseComplete (bin/lib/phase.cjs:1378-1390) which
1455
+ // calls cmdStatePrune({keepRecent:'3', dryRun:false, silent:true}). Without
1456
+ // this, completing phase N with auto_prune_state=true leaves stale [Phase
1457
+ // 1..N-3] decisions in STATE.md forever. (#2087)
1458
+ let autoPruned = false;
1459
+ try {
1460
+ if (existsSync(paths.config)) {
1461
+ const rawConfig = JSON.parse(await readFile(paths.config, 'utf-8'));
1462
+ const wf = rawConfig.workflow;
1463
+ if (wf && wf.auto_prune_state === true && existsSync(paths.state)) {
1464
+ const { statePrune } = await import('./state-mutation.js');
1465
+ await statePrune(['--keep-recent', '3', '--silent'], projectDir, workstream);
1466
+ autoPruned = true;
1467
+ }
1468
+ }
1469
+ }
1470
+ catch { /* best-effort, matches CJS */ }
1471
+ // Step G: Return result
1472
+ return {
1473
+ data: {
1474
+ completed_phase: phaseNum,
1475
+ phase_name: phaseInfo.phaseName,
1476
+ plans_executed: `${summaryCount}/${planCount}`,
1477
+ next_phase: nextPhaseNum,
1478
+ next_phase_name: nextPhaseName,
1479
+ is_last_phase: isLastPhase,
1480
+ date: today,
1481
+ roadmap_updated: existsSync(paths.roadmap),
1482
+ state_updated: stateUpdated,
1483
+ requirements_updated: requirementsUpdated,
1484
+ auto_pruned: autoPruned,
1485
+ warnings,
1486
+ has_warnings: warnings.length > 0,
1487
+ },
1488
+ };
1489
+ };
1490
+ // ─── phasesClear handler ──────────────────────────────────────────────────
1491
+ /**
1492
+ * Query handler for phases.clear.
1493
+ *
1494
+ * Port of cmdPhasesClear from milestone.cjs lines 250-277.
1495
+ * Deletes all phase directories except 999.x backlog phases.
1496
+ * Requires --confirm flag to proceed.
1497
+ *
1498
+ * @param args - args[0]: '--confirm' to proceed (optional)
1499
+ * @param projectDir - Project root directory
1500
+ * @returns QueryResult with { cleared: count }
1501
+ */
1502
+ export const phasesClear = async (args, projectDir, workstream) => {
1503
+ const phasesDir = planningPaths(projectDir, workstream).phases;
1504
+ const confirm = Array.isArray(args) && args.includes('--confirm');
1505
+ let cleared = 0;
1506
+ if (existsSync(phasesDir)) {
1507
+ const entries = await readdir(phasesDir, { withFileTypes: true });
1508
+ const dirs = entries.filter(e => e.isDirectory() && !/^999(?:\.|$)/.test(e.name));
1509
+ if (dirs.length > 0 && !confirm) {
1510
+ throw new GSDError(`phases clear would delete ${dirs.length} phase director${dirs.length === 1 ? 'y' : 'ies'}. ` +
1511
+ `Pass --confirm to proceed.`, ErrorClassification.Validation);
1512
+ }
1513
+ for (const entry of dirs) {
1514
+ await rm(join(phasesDir, entry.name), { recursive: true, force: true });
1515
+ cleared++;
1516
+ }
1517
+ }
1518
+ return { data: { cleared } };
1519
+ };
1520
+ // ─── phasesArchive handler ────────────────────────────────────────────────
1521
+ /**
1522
+ * Query handler for phases.archive.
1523
+ *
1524
+ * Extracted from cmdMilestoneComplete, milestone.cjs lines 210-227.
1525
+ * Moves milestone phase directories to milestones/{version}-phases/.
1526
+ *
1527
+ * @param args - args[0]: version string (e.g., "v3.0")
1528
+ * @param projectDir - Project root directory
1529
+ * @returns QueryResult with { archived: count, version, archive_directory }
1530
+ */
1531
+ export const phasesList = async (args, projectDir, workstream) => {
1532
+ const paths = planningPaths(projectDir, workstream);
1533
+ const phasesDir = paths.phases;
1534
+ const typeIdx = args.indexOf('--type');
1535
+ const phaseIdx = args.indexOf('--phase');
1536
+ const type = typeIdx !== -1 ? args[typeIdx + 1] : null;
1537
+ const phase = phaseIdx !== -1 ? args[phaseIdx + 1] : null;
1538
+ const includeArchived = args.includes('--include-archived');
1539
+ if (!existsSync(phasesDir)) {
1540
+ return { data: type ? { files: [], count: 0 } : { directories: [], count: 0 } };
1541
+ }
1542
+ const entries = await readdir(phasesDir, { withFileTypes: true });
1543
+ let dirs = entries.filter(e => e.isDirectory()).map(e => e.name);
1544
+ if (includeArchived) {
1545
+ const milestonesDir = join(paths.planning, 'milestones');
1546
+ if (existsSync(milestonesDir)) {
1547
+ const milestoneEntries = await readdir(milestonesDir, { withFileTypes: true });
1548
+ for (const mDir of milestoneEntries.filter(e => e.isDirectory() && e.name.endsWith('-phases'))) {
1549
+ const milestone = mDir.name.replace(/-phases$/, '');
1550
+ const archivedEntries = await readdir(join(milestonesDir, mDir.name), { withFileTypes: true });
1551
+ for (const a of archivedEntries.filter(e => e.isDirectory())) {
1552
+ dirs.push(`${a.name} [${milestone}]`);
1553
+ }
1554
+ }
1555
+ }
1556
+ }
1557
+ dirs.sort((a, b) => comparePhaseNum(a, b));
1558
+ if (phase) {
1559
+ const normalized = normalizePhaseName(phase);
1560
+ const match = dirs.find(d => phaseTokenMatches(d, normalized));
1561
+ if (!match) {
1562
+ return { data: { files: [], count: 0, phase_dir: null, error: 'Phase not found' } };
1563
+ }
1564
+ dirs = [match];
1565
+ }
1566
+ if (type) {
1567
+ const files = [];
1568
+ const warnings = [];
1569
+ for (const dir of dirs) {
1570
+ const dirPath = join(phasesDir, dir);
1571
+ if (!existsSync(dirPath))
1572
+ continue;
1573
+ const dirFiles = await readdir(dirPath);
1574
+ let filtered;
1575
+ if (type === 'plans') {
1576
+ filtered = dirFiles.filter(isCanonicalPlanFile);
1577
+ // #2893 parity — surface plan-shaped files the canonical filter
1578
+ // rejected so callers (executor init, etc.) don't silently see zero
1579
+ // plans. Per-dir prefix mirrors phase.cjs:120.
1580
+ const w = describeNonCanonicalPlans(dirFiles, filtered);
1581
+ if (w)
1582
+ warnings.push(`${dir}: ${w}`);
1583
+ }
1584
+ else if (type === 'summaries') {
1585
+ filtered = dirFiles.filter(f => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md');
1586
+ }
1587
+ else {
1588
+ filtered = dirFiles;
1589
+ }
1590
+ files.push(...filtered.sort());
1591
+ }
1592
+ const result = {
1593
+ files,
1594
+ count: files.length,
1595
+ phase_dir: phase ? dirs[0]?.replace(/^\d+(?:\.\d+)*-?/, '') : null,
1596
+ };
1597
+ if (warnings.length)
1598
+ result['warning'] = warnings.join(' | ');
1599
+ return { data: result };
1600
+ }
1601
+ return { data: { directories: dirs, count: dirs.length } };
1602
+ };
1603
+ export const phaseNextDecimal = async (args, projectDir, workstream) => {
1604
+ const basePhase = args[0];
1605
+ if (!basePhase) {
1606
+ throw new GSDError('base phase number required', ErrorClassification.Validation);
1607
+ }
1608
+ assertNoNullBytes(basePhase, 'basePhase');
1609
+ const paths = planningPaths(projectDir, workstream);
1610
+ const phasesDir = paths.phases;
1611
+ const normalized = normalizePhaseName(basePhase);
1612
+ const decimalSet = new Set();
1613
+ let baseExists = false;
1614
+ const dirNames = await listDirectories(phasesDir);
1615
+ baseExists = dirNames.some((d) => phaseTokenMatches(d, normalized));
1616
+ for (const suffix of collectDecimalSuffixesFromDirNames(normalized, dirNames)) {
1617
+ decimalSet.add(suffix);
1618
+ }
1619
+ const roadmapPath = paths.roadmap;
1620
+ if (existsSync(roadmapPath)) {
1621
+ try {
1622
+ const roadmapContent = await readFile(roadmapPath, 'utf-8');
1623
+ for (const suffix of collectDecimalSuffixesFromRoadmap(normalized, roadmapContent)) {
1624
+ decimalSet.add(suffix);
1625
+ }
1626
+ }
1627
+ catch { /* ROADMAP.md read failure is non-fatal */ }
1628
+ }
1629
+ const { next: nextDecimal, existing: existingDecimals } = computeNextDecimalPhase(normalized, decimalSet);
1630
+ return {
1631
+ data: {
1632
+ found: baseExists,
1633
+ base_phase: normalized,
1634
+ next: nextDecimal,
1635
+ existing: existingDecimals,
1636
+ },
1637
+ };
1638
+ };
1639
+ export const phasesArchive = async (args, projectDir, workstream) => {
1640
+ const version = args[0];
1641
+ if (!version) {
1642
+ throw new GSDError('version required for phases archive', ErrorClassification.Validation);
1643
+ }
1644
+ assertNoNullBytes(version, 'version');
1645
+ const paths = planningPaths(projectDir, workstream);
1646
+ const phasesDir = paths.phases;
1647
+ const isDirInMilestone = await getMilestonePhaseFilter(projectDir, workstream);
1648
+ const archiveDir = join(paths.planning, 'milestones', `${version}-phases`);
1649
+ const archivedCount = await archiveDirectories(phasesDir, archiveDir, (dirName) => isDirInMilestone(dirName));
1650
+ return {
1651
+ data: {
1652
+ archived: archivedCount,
1653
+ version,
1654
+ archive_directory: toPosixPath(relative(projectDir, archiveDir)),
1655
+ },
1656
+ };
1657
+ };
1658
+ // ─── milestoneComplete ────────────────────────────────────────────────────
1659
+ /**
1660
+ * Query handler for `milestone.complete` — port of `cmdMilestoneComplete` from `milestone.cjs`.
1661
+ */
1662
+ export const milestoneComplete = async (args, projectDir, workstream) => {
1663
+ const version = args[0];
1664
+ if (!version) {
1665
+ throw new GSDError('version required for milestone complete (e.g., v1.0)', ErrorClassification.Validation);
1666
+ }
1667
+ // #3259: defense-in-depth — reject --help / -h as a version value before
1668
+ // any disk write, regardless of whether the dispatcher guard intercepted first.
1669
+ if (version === '--help' || version === '-h') {
1670
+ throw new GSDError(`"${version}" is not a valid milestone version; see \`gsd-sdk query --help\` for command list`, ErrorClassification.Validation);
1671
+ }
1672
+ assertNoNullBytes(version, 'version');
1673
+ const nameOpt = parseMultiwordArg(args, 'name');
1674
+ const archivePhases = args.includes('--archive-phases');
1675
+ const paths = planningPaths(projectDir, workstream);
1676
+ const roadmapPath = paths.roadmap;
1677
+ const reqPath = paths.requirements;
1678
+ const statePath = paths.state;
1679
+ const milestonesPath = join(paths.planning, 'MILESTONES.md');
1680
+ const archiveDir = join(paths.planning, 'milestones');
1681
+ const phasesDir = paths.phases;
1682
+ const today = new Date().toISOString().split('T')[0];
1683
+ const milestoneName = nameOpt || version;
1684
+ await mkdir(archiveDir, { recursive: true });
1685
+ const isDirInMilestone = await getMilestonePhaseFilter(projectDir, workstream);
1686
+ let phaseCount = 0;
1687
+ let totalPlans = 0;
1688
+ let totalTasks = 0;
1689
+ const accomplishments = [];
1690
+ try {
1691
+ const dirs = (await listDirectories(phasesDir)).sort();
1692
+ for (const dir of dirs) {
1693
+ if (!isDirInMilestone(dir))
1694
+ continue;
1695
+ phaseCount++;
1696
+ const phaseFiles = await readdir(join(phasesDir, dir));
1697
+ const plans = phaseFiles.filter((f) => f.endsWith('-PLAN.md') || f === 'PLAN.md');
1698
+ const summaries = phaseFiles.filter((f) => f.endsWith('-SUMMARY.md') || f === 'SUMMARY.md');
1699
+ totalPlans += plans.length;
1700
+ for (const s of summaries) {
1701
+ try {
1702
+ const content = await readFile(join(phasesDir, dir, s), 'utf-8');
1703
+ const fm = extractFrontmatter(content);
1704
+ const oneLiner = fm['one-liner'] || extractOneLinerFromBody(content);
1705
+ if (oneLiner) {
1706
+ accomplishments.push(oneLiner);
1707
+ }
1708
+ const tasksFieldMatch = content.match(/\*\*Tasks:\*\*\s*(\d+)/);
1709
+ if (tasksFieldMatch) {
1710
+ totalTasks += parseInt(tasksFieldMatch[1], 10);
1711
+ }
1712
+ else {
1713
+ const xmlTaskMatches = content.match(/<task[\s>]/gi) || [];
1714
+ const mdTaskMatches = content.match(/##\s*Task\s*\d+/gi) || [];
1715
+ totalTasks += xmlTaskMatches.length || mdTaskMatches.length;
1716
+ }
1717
+ }
1718
+ catch {
1719
+ /* intentionally empty */
1720
+ }
1721
+ }
1722
+ }
1723
+ }
1724
+ catch {
1725
+ /* intentionally empty */
1726
+ }
1727
+ if (existsSync(roadmapPath)) {
1728
+ const roadmapContent = await readFile(roadmapPath, 'utf-8');
1729
+ await writeFile(join(archiveDir, `${version}-ROADMAP.md`), roadmapContent, 'utf-8');
1730
+ }
1731
+ if (existsSync(reqPath)) {
1732
+ const reqContent = await readFile(reqPath, 'utf-8');
1733
+ const archiveHeader = `# Requirements Archive: ${version} ${milestoneName}\n\n` +
1734
+ `**Archived:** ${today}\n**Status:** SHIPPED\n\n` +
1735
+ `For current requirements, see \`.planning/REQUIREMENTS.md\`.\n\n---\n\n`;
1736
+ await writeFile(join(archiveDir, `${version}-REQUIREMENTS.md`), archiveHeader + reqContent, 'utf-8');
1737
+ }
1738
+ const auditFile = join(projectDir, '.planning', `${version}-MILESTONE-AUDIT.md`);
1739
+ if (existsSync(auditFile)) {
1740
+ await rename(auditFile, join(archiveDir, `${version}-MILESTONE-AUDIT.md`));
1741
+ }
1742
+ const accomplishmentsList = accomplishments.map((a) => `- ${a}`).join('\n');
1743
+ const milestoneEntry = `## ${version} ${milestoneName} (Shipped: ${today})\n\n` +
1744
+ `**Phases completed:** ${phaseCount} phases, ${totalPlans} plans, ${totalTasks} tasks\n\n` +
1745
+ `**Key accomplishments:**\n${accomplishmentsList || '- (none recorded)'}\n\n---\n\n`;
1746
+ if (existsSync(milestonesPath)) {
1747
+ const existing = await readFile(milestonesPath, 'utf-8');
1748
+ if (!existing.trim()) {
1749
+ await writeFile(milestonesPath, normalizeMd(`# Milestones\n\n${milestoneEntry}`), 'utf-8');
1750
+ }
1751
+ else {
1752
+ const headerMatch = existing.match(/^(#{1,3}\s+[^\n]*\n\n?)/);
1753
+ if (headerMatch) {
1754
+ const header = headerMatch[1];
1755
+ const rest = existing.slice(header.length);
1756
+ await writeFile(milestonesPath, normalizeMd(header + milestoneEntry + rest), 'utf-8');
1757
+ }
1758
+ else {
1759
+ await writeFile(milestonesPath, normalizeMd(milestoneEntry + existing), 'utf-8');
1760
+ }
1761
+ }
1762
+ }
1763
+ else {
1764
+ await writeFile(milestonesPath, normalizeMd(`# Milestones\n\n${milestoneEntry}`), 'utf-8');
1765
+ }
1766
+ if (existsSync(statePath)) {
1767
+ await readModifyWriteStateMdFull(projectDir, (stateContent) => {
1768
+ let next = stateReplaceFieldWithFallback(stateContent, 'Status', null, `${version} milestone complete`);
1769
+ next = stateReplaceFieldWithFallback(next, 'Last Activity', 'Last activity', today);
1770
+ next = stateReplaceFieldWithFallback(next, 'Last Activity Description', null, `${version} milestone completed and archived`);
1771
+ const positionPattern = /(##\s*Current Position\s*\n)([\s\S]*?)(?=\n##|$)/i;
1772
+ const closedPositionBody = `\nPhase: Milestone ${version} complete\n` +
1773
+ `Plan: —\n` +
1774
+ `Status: Awaiting next milestone\n` +
1775
+ `Last activity: ${today} — Milestone ${version} completed and archived\n\n`;
1776
+ if (positionPattern.test(next)) {
1777
+ next = next.replace(positionPattern, (_m, header) => `${header}${closedPositionBody}`);
1778
+ }
1779
+ else {
1780
+ next = `${next.trimEnd()}\n\n## Current Position\n${closedPositionBody}`;
1781
+ }
1782
+ const operatorPattern = /(##\s*Operator Next Steps\s*\n)([\s\S]*?)(?=\n##|$)/i;
1783
+ if (operatorPattern.test(next)) {
1784
+ next = next.replace(operatorPattern, `$1\n- Start the next milestone with /gsd-new-milestone\n\n`);
1785
+ }
1786
+ else {
1787
+ next = `${next.trimEnd()}\n\n## Operator Next Steps\n\n- Start the next milestone with /gsd-new-milestone\n`;
1788
+ }
1789
+ return next;
1790
+ }, workstream);
1791
+ }
1792
+ let phasesArchived = false;
1793
+ if (archivePhases) {
1794
+ try {
1795
+ const phaseArchiveDir = join(archiveDir, `${version}-phases`);
1796
+ const archivedCount = await archiveDirectories(phasesDir, phaseArchiveDir, (dirName) => isDirInMilestone(dirName));
1797
+ phasesArchived = archivedCount > 0;
1798
+ }
1799
+ catch {
1800
+ /* intentionally empty */
1801
+ }
1802
+ }
1803
+ return {
1804
+ data: {
1805
+ version,
1806
+ name: milestoneName,
1807
+ date: today,
1808
+ phases: phaseCount,
1809
+ plans: totalPlans,
1810
+ tasks: totalTasks,
1811
+ accomplishments,
1812
+ archived: {
1813
+ roadmap: existsSync(join(archiveDir, `${version}-ROADMAP.md`)),
1814
+ requirements: existsSync(join(archiveDir, `${version}-REQUIREMENTS.md`)),
1815
+ audit: existsSync(join(archiveDir, `${version}-MILESTONE-AUDIT.md`)),
1816
+ phases: phasesArchived,
1817
+ },
1818
+ milestones_updated: true,
1819
+ state_updated: existsSync(statePath),
1820
+ },
1821
+ };
1822
+ };
1823
+ //# sourceMappingURL=phase-lifecycle.js.map