@opengsd/gsd-core 1.3.0-rc.1 → 1.3.1

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 (521) hide show
  1. package/README.ja-JP.md +44 -790
  2. package/README.ko-KR.md +41 -778
  3. package/README.md +39 -180
  4. package/README.pt-BR.md +45 -413
  5. package/README.zh-CN.md +43 -761
  6. package/agents/gsd-ai-researcher.md +1 -1
  7. package/agents/gsd-debugger.md +8 -8
  8. package/agents/gsd-domain-researcher.md +14 -1
  9. package/agents/gsd-eval-auditor.md +1 -1
  10. package/agents/gsd-eval-planner.md +1 -1
  11. package/agents/gsd-executor.md +21 -8
  12. package/agents/gsd-framework-selector.md +1 -1
  13. package/agents/gsd-intel-updater.md +4 -4
  14. package/agents/gsd-phase-researcher.md +18 -5
  15. package/agents/gsd-plan-checker.md +3 -3
  16. package/agents/gsd-planner.md +36 -23
  17. package/agents/gsd-project-researcher.md +13 -0
  18. package/agents/gsd-research-synthesizer.md +6 -2
  19. package/agents/gsd-roadmapper.md +6 -6
  20. package/agents/gsd-ui-researcher.md +15 -2
  21. package/agents/gsd-user-profiler.md +2 -2
  22. package/agents/gsd-verifier.md +7 -7
  23. package/bin/install.js +169 -59
  24. package/commands/gsd/add-tests.md +1 -1
  25. package/commands/gsd/ai-integration-phase.md +3 -3
  26. package/commands/gsd/audit-fix.md +1 -1
  27. package/commands/gsd/audit-milestone.md +1 -1
  28. package/commands/gsd/audit-uat.md +1 -1
  29. package/commands/gsd/autonomous.md +2 -2
  30. package/commands/gsd/capture.md +6 -6
  31. package/commands/gsd/cleanup.md +1 -1
  32. package/commands/gsd/code-review.md +1 -1
  33. package/commands/gsd/complete-milestone.md +2 -2
  34. package/commands/gsd/config.md +3 -3
  35. package/commands/gsd/debug.md +1 -1
  36. package/commands/gsd/discuss-phase.md +5 -4
  37. package/commands/gsd/docs-update.md +1 -1
  38. package/commands/gsd/eval-review.md +2 -2
  39. package/commands/gsd/execute-phase.md +2 -2
  40. package/commands/gsd/explore.md +1 -1
  41. package/commands/gsd/extract-learnings.md +2 -2
  42. package/commands/gsd/fast.md +1 -1
  43. package/commands/gsd/forensics.md +1 -1
  44. package/commands/gsd/graphify.md +9 -9
  45. package/commands/gsd/health.md +1 -1
  46. package/commands/gsd/help.md +2 -2
  47. package/commands/gsd/import.md +5 -5
  48. package/commands/gsd/inbox.md +1 -1
  49. package/commands/gsd/ingest-docs.md +4 -4
  50. package/commands/gsd/manager.md +3 -3
  51. package/commands/gsd/map-codebase.md +1 -1
  52. package/commands/gsd/milestone-summary.md +1 -1
  53. package/commands/gsd/mvp-phase.md +4 -4
  54. package/commands/gsd/new-milestone.md +5 -5
  55. package/commands/gsd/new-project.md +5 -5
  56. package/commands/gsd/pause-work.md +2 -2
  57. package/commands/gsd/phase.md +4 -4
  58. package/commands/gsd/plan-phase.md +2 -2
  59. package/commands/gsd/plan-review-convergence.md +4 -4
  60. package/commands/gsd/pr-branch.md +1 -1
  61. package/commands/gsd/profile-user.md +2 -2
  62. package/commands/gsd/progress.md +4 -4
  63. package/commands/gsd/quick.md +1 -1
  64. package/commands/gsd/resume-work.md +1 -1
  65. package/commands/gsd/review.md +1 -1
  66. package/commands/gsd/secure-phase.md +1 -1
  67. package/commands/gsd/settings.md +1 -1
  68. package/commands/gsd/ship.md +2 -2
  69. package/commands/gsd/sketch.md +7 -7
  70. package/commands/gsd/spec-phase.md +2 -2
  71. package/commands/gsd/spike.md +3 -3
  72. package/commands/gsd/stats.md +1 -1
  73. package/commands/gsd/surface.md +4 -4
  74. package/commands/gsd/thread.md +1 -1
  75. package/commands/gsd/ui-phase.md +2 -2
  76. package/commands/gsd/ui-review.md +2 -2
  77. package/commands/gsd/ultraplan-phase.md +2 -2
  78. package/commands/gsd/undo.md +3 -3
  79. package/commands/gsd/update.md +3 -3
  80. package/commands/gsd/validate-phase.md +1 -1
  81. package/commands/gsd/verify-work.md +2 -2
  82. package/commands/gsd/workspace.md +4 -4
  83. package/{get-shit-done → gsd-core}/bin/check-latest-version.cjs +1 -1
  84. package/{get-shit-done → gsd-core}/bin/gsd-tools.cjs +13 -3
  85. package/gsd-core/bin/lib/active-workstream-store.cjs +291 -0
  86. package/gsd-core/bin/lib/adr-parser.cjs +399 -0
  87. package/gsd-core/bin/lib/agent-command-router.cjs +68 -0
  88. package/gsd-core/bin/lib/artifacts.cjs +51 -0
  89. package/gsd-core/bin/lib/audit.cjs +743 -0
  90. package/gsd-core/bin/lib/check-command-router.cjs +342 -0
  91. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +81 -0
  92. package/gsd-core/bin/lib/clock.cjs +95 -0
  93. package/gsd-core/bin/lib/clusters.cjs +128 -0
  94. package/gsd-core/bin/lib/code-review-flags.cjs +59 -0
  95. package/gsd-core/bin/lib/command-aliases.cjs +809 -0
  96. package/gsd-core/bin/lib/command-arg-projection.cjs +55 -0
  97. package/gsd-core/bin/lib/command-routing-hub.cjs +300 -0
  98. package/gsd-core/bin/lib/commands.cjs +1202 -0
  99. package/gsd-core/bin/lib/config-schema.cjs +29 -0
  100. package/{get-shit-done → gsd-core}/bin/lib/config-types.cjs +1 -1
  101. package/gsd-core/bin/lib/config.cjs +714 -0
  102. package/{get-shit-done → gsd-core}/bin/lib/configuration.cjs +76 -85
  103. package/gsd-core/bin/lib/context-utilization.cjs +48 -0
  104. package/gsd-core/bin/lib/core.cjs +2007 -0
  105. package/{get-shit-done → gsd-core}/bin/lib/decisions.cjs +9 -7
  106. package/gsd-core/bin/lib/docs.cjs +252 -0
  107. package/gsd-core/bin/lib/drift.cjs +364 -0
  108. package/gsd-core/bin/lib/fallow-runner.cjs +115 -0
  109. package/gsd-core/bin/lib/frontmatter.cjs +442 -0
  110. package/gsd-core/bin/lib/gap-checker.cjs +257 -0
  111. package/gsd-core/bin/lib/graphify.cjs +496 -0
  112. package/gsd-core/bin/lib/gsd2-import.cjs +456 -0
  113. package/gsd-core/bin/lib/init-command-router.cjs +62 -0
  114. package/gsd-core/bin/lib/init.cjs +1799 -0
  115. package/gsd-core/bin/lib/install-profiles.cjs +526 -0
  116. package/gsd-core/bin/lib/installer-migration-authoring.cjs +122 -0
  117. package/gsd-core/bin/lib/installer-migration-report.cjs +347 -0
  118. package/gsd-core/bin/lib/installer-migrations/000-first-time-baseline.cjs +218 -0
  119. package/gsd-core/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +48 -0
  120. package/gsd-core/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +94 -0
  121. package/gsd-core/bin/lib/installer-migrations/003-rename-get-shit-done-to-gsd-core.cjs +108 -0
  122. package/gsd-core/bin/lib/installer-migrations.cjs +823 -0
  123. package/gsd-core/bin/lib/intel.cjs +607 -0
  124. package/gsd-core/bin/lib/learnings.cjs +270 -0
  125. package/gsd-core/bin/lib/legacy-cleanup.cjs +253 -0
  126. package/gsd-core/bin/lib/milestone.cjs +373 -0
  127. package/gsd-core/bin/lib/model-catalog.cjs +154 -0
  128. package/gsd-core/bin/lib/model-profiles.cjs +24 -0
  129. package/gsd-core/bin/lib/observability/event.cjs +51 -0
  130. package/gsd-core/bin/lib/observability/logger.cjs +146 -0
  131. package/{get-shit-done → gsd-core}/bin/lib/observability/redaction.cjs +19 -21
  132. package/{get-shit-done → gsd-core}/bin/lib/package-identity.cjs +5 -1
  133. package/gsd-core/bin/lib/phase-command-router.cjs +189 -0
  134. package/gsd-core/bin/lib/phase-lifecycle.cjs +74 -0
  135. package/gsd-core/bin/lib/phase.cjs +1307 -0
  136. package/gsd-core/bin/lib/phases-command-router.cjs +43 -0
  137. package/{get-shit-done → gsd-core}/bin/lib/plan-scan.cjs +18 -24
  138. package/gsd-core/bin/lib/planning-workspace.cjs +245 -0
  139. package/gsd-core/bin/lib/profile-output.cjs +1120 -0
  140. package/gsd-core/bin/lib/profile-pipeline.cjs +517 -0
  141. package/gsd-core/bin/lib/project-root.cjs +119 -0
  142. package/gsd-core/bin/lib/prompt-budget.cjs +305 -0
  143. package/gsd-core/bin/lib/review-reviewer-selection.cjs +121 -0
  144. package/gsd-core/bin/lib/roadmap-command-router.cjs +166 -0
  145. package/gsd-core/bin/lib/roadmap-upgrade.cjs +491 -0
  146. package/gsd-core/bin/lib/roadmap.cjs +600 -0
  147. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +254 -0
  148. package/gsd-core/bin/lib/runtime-homes.cjs +169 -0
  149. package/gsd-core/bin/lib/runtime-name-policy.cjs +96 -0
  150. package/gsd-core/bin/lib/runtime-slash.cjs +119 -0
  151. package/{get-shit-done → gsd-core}/bin/lib/schema-detect.cjs +20 -26
  152. package/gsd-core/bin/lib/secrets.cjs +34 -0
  153. package/gsd-core/bin/lib/security.cjs +407 -0
  154. package/{get-shit-done → gsd-core}/bin/lib/semver-compare.cjs +1 -1
  155. package/gsd-core/bin/lib/shell-command-projection.cjs +524 -0
  156. package/gsd-core/bin/lib/state-command-router.cjs +160 -0
  157. package/{get-shit-done → gsd-core}/bin/lib/state-document.cjs +78 -78
  158. package/gsd-core/bin/lib/state.cjs +2010 -0
  159. package/gsd-core/bin/lib/surface.cjs +406 -0
  160. package/gsd-core/bin/lib/task-command-router.cjs +85 -0
  161. package/gsd-core/bin/lib/template.cjs +237 -0
  162. package/gsd-core/bin/lib/uat.cjs +297 -0
  163. package/gsd-core/bin/lib/ui-safety-gate.cjs +98 -0
  164. package/gsd-core/bin/lib/update-context.cjs +218 -0
  165. package/gsd-core/bin/lib/validate-command-router.cjs +91 -0
  166. package/gsd-core/bin/lib/validate.cjs +112 -0
  167. package/gsd-core/bin/lib/verify-command-router.cjs +44 -0
  168. package/gsd-core/bin/lib/verify.cjs +1451 -0
  169. package/{get-shit-done → gsd-core}/bin/lib/workstream-inventory-builder.cjs +19 -12
  170. package/gsd-core/bin/lib/workstream-inventory.cjs +147 -0
  171. package/{get-shit-done → gsd-core}/bin/lib/workstream-name-policy.cjs +28 -31
  172. package/gsd-core/bin/lib/workstream.cjs +380 -0
  173. package/gsd-core/bin/lib/worktree-safety.cjs +912 -0
  174. package/{get-shit-done → gsd-core}/bin/shared/config-schema.manifest.json +5 -0
  175. package/{get-shit-done → gsd-core}/references/artifact-types.md +1 -1
  176. package/{get-shit-done → gsd-core}/references/few-shot-examples/plan-checker.md +2 -2
  177. package/{get-shit-done → gsd-core}/references/few-shot-examples/verifier.md +12 -12
  178. package/{get-shit-done → gsd-core}/references/model-profile-resolution.md +1 -1
  179. package/{get-shit-done → gsd-core}/references/mvp-concepts.md +1 -1
  180. package/{get-shit-done → gsd-core}/references/planner-graphify-auto-update.md +2 -2
  181. package/{get-shit-done → gsd-core}/references/planner-mvp-mode.md +1 -1
  182. package/{get-shit-done → gsd-core}/references/verification-patterns.md +1 -1
  183. package/gsd-core/references/worktree-branch-check.md +38 -0
  184. package/{get-shit-done → gsd-core}/references/worktree-path-safety.md +4 -26
  185. package/{get-shit-done → gsd-core}/templates/README.md +2 -2
  186. package/{get-shit-done → gsd-core}/templates/codebase/structure.md +10 -10
  187. package/{get-shit-done → gsd-core}/templates/copilot-instructions.md +1 -1
  188. package/{get-shit-done → gsd-core}/templates/phase-prompt.md +10 -10
  189. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -0
  190. package/{get-shit-done → gsd-core}/workflows/add-backlog.md +1 -1
  191. package/{get-shit-done → gsd-core}/workflows/add-phase.md +1 -1
  192. package/{get-shit-done → gsd-core}/workflows/add-tests.md +1 -1
  193. package/{get-shit-done → gsd-core}/workflows/add-todo.md +1 -1
  194. package/{get-shit-done → gsd-core}/workflows/ai-integration-phase.md +4 -4
  195. package/{get-shit-done → gsd-core}/workflows/audit-fix.md +1 -1
  196. package/{get-shit-done → gsd-core}/workflows/audit-milestone.md +1 -1
  197. package/{get-shit-done → gsd-core}/workflows/audit-uat.md +1 -1
  198. package/{get-shit-done → gsd-core}/workflows/autonomous.md +4 -4
  199. package/{get-shit-done → gsd-core}/workflows/check-todos.md +1 -1
  200. package/{get-shit-done → gsd-core}/workflows/cleanup.md +1 -1
  201. package/{get-shit-done → gsd-core}/workflows/code-review-fix.md +1 -1
  202. package/{get-shit-done → gsd-core}/workflows/code-review.md +4 -4
  203. package/{get-shit-done → gsd-core}/workflows/complete-milestone.md +2 -2
  204. package/{get-shit-done → gsd-core}/workflows/debug.md +1 -1
  205. package/{get-shit-done → gsd-core}/workflows/diagnose-issues.md +4 -2
  206. package/{get-shit-done → gsd-core}/workflows/discovery-phase.md +5 -5
  207. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/advisor.md +4 -4
  208. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/auto.md +1 -1
  209. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/chain.md +1 -1
  210. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/power.md +1 -1
  211. package/{get-shit-done → gsd-core}/workflows/discuss-phase-assumptions.md +2 -2
  212. package/{get-shit-done → gsd-core}/workflows/discuss-phase.md +6 -6
  213. package/{get-shit-done → gsd-core}/workflows/do.md +1 -1
  214. package/{get-shit-done → gsd-core}/workflows/docs-update.md +1 -1
  215. package/{get-shit-done → gsd-core}/workflows/edit-phase.md +1 -1
  216. package/{get-shit-done → gsd-core}/workflows/eval-review.md +2 -2
  217. package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/codebase-drift-gate.md +15 -2
  218. package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/post-merge-gate.md +1 -1
  219. package/{get-shit-done → gsd-core}/workflows/execute-phase.md +68 -46
  220. package/{get-shit-done → gsd-core}/workflows/execute-plan.md +8 -8
  221. package/{get-shit-done → gsd-core}/workflows/explore.md +3 -3
  222. package/{get-shit-done → gsd-core}/workflows/extract-learnings.md +1 -1
  223. package/{get-shit-done → gsd-core}/workflows/forensics.md +1 -1
  224. package/{get-shit-done → gsd-core}/workflows/graduation.md +1 -1
  225. package/{get-shit-done → gsd-core}/workflows/health.md +1 -1
  226. package/{get-shit-done → gsd-core}/workflows/help/modes/full.md +1 -1
  227. package/{get-shit-done → gsd-core}/workflows/import.md +1 -1
  228. package/{get-shit-done → gsd-core}/workflows/ingest-docs.md +3 -3
  229. package/{get-shit-done → gsd-core}/workflows/insert-phase.md +1 -1
  230. package/{get-shit-done → gsd-core}/workflows/list-workspaces.md +1 -1
  231. package/{get-shit-done → gsd-core}/workflows/manager.md +1 -1
  232. package/{get-shit-done → gsd-core}/workflows/map-codebase.md +1 -1
  233. package/{get-shit-done → gsd-core}/workflows/milestone-summary.md +1 -1
  234. package/{get-shit-done → gsd-core}/workflows/mvp-phase.md +7 -7
  235. package/{get-shit-done → gsd-core}/workflows/new-milestone.md +3 -3
  236. package/{get-shit-done → gsd-core}/workflows/new-project.md +6 -6
  237. package/{get-shit-done → gsd-core}/workflows/new-workspace.md +1 -1
  238. package/{get-shit-done → gsd-core}/workflows/next.md +1 -1
  239. package/{get-shit-done → gsd-core}/workflows/pause-work.md +1 -1
  240. package/{get-shit-done → gsd-core}/workflows/plan-milestone-gaps.md +1 -1
  241. package/{get-shit-done → gsd-core}/workflows/plan-phase.md +15 -15
  242. package/{get-shit-done → gsd-core}/workflows/plan-review-convergence.md +7 -7
  243. package/{get-shit-done → gsd-core}/workflows/plant-seed.md +1 -1
  244. package/{get-shit-done → gsd-core}/workflows/profile-user.md +11 -11
  245. package/{get-shit-done → gsd-core}/workflows/progress.md +1 -1
  246. package/{get-shit-done → gsd-core}/workflows/quick.md +2 -26
  247. package/{get-shit-done → gsd-core}/workflows/reapply-patches.md +2 -2
  248. package/{get-shit-done → gsd-core}/workflows/remove-phase.md +1 -1
  249. package/{get-shit-done → gsd-core}/workflows/remove-workspace.md +1 -1
  250. package/{get-shit-done → gsd-core}/workflows/resume-project.md +2 -2
  251. package/{get-shit-done → gsd-core}/workflows/review.md +1 -1
  252. package/{get-shit-done → gsd-core}/workflows/scan.md +1 -1
  253. package/{get-shit-done → gsd-core}/workflows/secure-phase.md +3 -3
  254. package/{get-shit-done → gsd-core}/workflows/settings-advanced.md +1 -1
  255. package/{get-shit-done → gsd-core}/workflows/settings-integrations.md +2 -2
  256. package/{get-shit-done → gsd-core}/workflows/settings.md +1 -1
  257. package/{get-shit-done → gsd-core}/workflows/ship.md +56 -4
  258. package/{get-shit-done → gsd-core}/workflows/sketch-wrap-up.md +1 -1
  259. package/{get-shit-done → gsd-core}/workflows/sketch.md +5 -5
  260. package/{get-shit-done → gsd-core}/workflows/spec-phase.md +2 -2
  261. package/{get-shit-done → gsd-core}/workflows/spike-wrap-up.md +1 -1
  262. package/{get-shit-done → gsd-core}/workflows/spike.md +1 -1
  263. package/{get-shit-done → gsd-core}/workflows/stats.md +1 -1
  264. package/{get-shit-done → gsd-core}/workflows/sync-skills.md +3 -3
  265. package/{get-shit-done → gsd-core}/workflows/thread.md +1 -1
  266. package/{get-shit-done → gsd-core}/workflows/transition.md +2 -2
  267. package/{get-shit-done → gsd-core}/workflows/ui-phase.md +3 -3
  268. package/{get-shit-done → gsd-core}/workflows/ui-review.md +2 -2
  269. package/{get-shit-done → gsd-core}/workflows/ultraplan-phase.md +1 -1
  270. package/{get-shit-done → gsd-core}/workflows/undo.md +2 -2
  271. package/{get-shit-done → gsd-core}/workflows/update.md +41 -16
  272. package/{get-shit-done → gsd-core}/workflows/validate-phase.md +3 -3
  273. package/{get-shit-done → gsd-core}/workflows/verify-phase.md +4 -4
  274. package/{get-shit-done → gsd-core}/workflows/verify-work.md +5 -5
  275. package/hooks/dist/gsd-check-update-worker.js +16 -3
  276. package/hooks/dist/gsd-check-update.js +7 -5
  277. package/hooks/dist/gsd-context-monitor.js +2 -2
  278. package/hooks/dist/gsd-statusline.js +39 -21
  279. package/hooks/dist/gsd-update-banner.js +6 -2
  280. package/hooks/dist/managed-hooks-registry.cjs +35 -0
  281. package/hooks/gsd-check-update-worker.js +16 -3
  282. package/hooks/gsd-check-update.js +7 -5
  283. package/hooks/gsd-context-monitor.js +2 -2
  284. package/hooks/gsd-statusline.js +39 -21
  285. package/hooks/gsd-update-banner.js +6 -2
  286. package/package.json +9 -6
  287. package/scripts/affected-tests-lib.cjs +1 -1
  288. package/scripts/base64-scan.sh +12 -0
  289. package/scripts/build-hooks.js +4 -1
  290. package/scripts/changeset/cli.cjs +2 -2
  291. package/scripts/changeset/github-release-notes.cjs +1 -1
  292. package/scripts/changeset/lint.cjs +1 -1
  293. package/scripts/check-alias-drift.cjs +8 -8
  294. package/scripts/check-env.cjs +5 -1
  295. package/scripts/ci-test-scope.cjs +25 -10
  296. package/scripts/command-contract-helpers.cjs +1 -1
  297. package/scripts/fix-slash-commands.cjs +5 -5
  298. package/scripts/gen-inventory-manifest.cjs +3 -3
  299. package/scripts/generate-package-identity.cjs +28 -7
  300. package/scripts/lib/allowlist-ratchet.cjs +136 -0
  301. package/scripts/lint-command-contract.cjs +1 -1
  302. package/scripts/lint-legacy-dir-name.cjs +156 -0
  303. package/scripts/lint-package-identity-drift.cjs +8 -8
  304. package/scripts/lint-pr-check-project-dir.cjs +0 -1
  305. package/scripts/lint-shell-command-projection-drift.cjs +1 -1
  306. package/scripts/lint-skill-deps.cjs +1 -1
  307. package/scripts/lint-test-file-count.allowlist.json +129 -32
  308. package/scripts/lint-test-file-count.cjs +85 -30
  309. package/scripts/mutation-matrix.cjs +219 -0
  310. package/scripts/prompt-injection-scan.sh +5 -1
  311. package/scripts/release-notes/format-github-release-notes.cjs +256 -0
  312. package/scripts/release-tarball-smoke.cjs +9 -9
  313. package/scripts/run-tests.cjs +11 -3
  314. package/scripts/strip-prose-atrefs.cjs +2 -2
  315. package/scripts/sync-runtime-launcher.cjs +2 -2
  316. package/scripts/verify-npm-publish.cjs +252 -0
  317. package/get-shit-done/bin/lib/active-workstream-store.cjs +0 -302
  318. package/get-shit-done/bin/lib/adr-parser.cjs +0 -394
  319. package/get-shit-done/bin/lib/agent-command-router.cjs +0 -65
  320. package/get-shit-done/bin/lib/artifacts.cjs +0 -53
  321. package/get-shit-done/bin/lib/audit.cjs +0 -755
  322. package/get-shit-done/bin/lib/check-command-router.cjs +0 -333
  323. package/get-shit-done/bin/lib/cjs-command-router-adapter.cjs +0 -118
  324. package/get-shit-done/bin/lib/clock.cjs +0 -96
  325. package/get-shit-done/bin/lib/clusters.cjs +0 -135
  326. package/get-shit-done/bin/lib/code-review-flags.cjs +0 -74
  327. package/get-shit-done/bin/lib/command-aliases.cjs +0 -831
  328. package/get-shit-done/bin/lib/command-arg-projection.cjs +0 -62
  329. package/get-shit-done/bin/lib/command-routing-hub.cjs +0 -388
  330. package/get-shit-done/bin/lib/commands.cjs +0 -1292
  331. package/get-shit-done/bin/lib/config-schema.cjs +0 -31
  332. package/get-shit-done/bin/lib/config.cjs +0 -728
  333. package/get-shit-done/bin/lib/context-utilization.cjs +0 -47
  334. package/get-shit-done/bin/lib/core.cjs +0 -2513
  335. package/get-shit-done/bin/lib/docs.cjs +0 -270
  336. package/get-shit-done/bin/lib/drift.cjs +0 -388
  337. package/get-shit-done/bin/lib/fallow-runner.cjs +0 -109
  338. package/get-shit-done/bin/lib/frontmatter.cjs +0 -389
  339. package/get-shit-done/bin/lib/gap-checker.cjs +0 -254
  340. package/get-shit-done/bin/lib/graphify.cjs +0 -592
  341. package/get-shit-done/bin/lib/gsd2-import.cjs +0 -514
  342. package/get-shit-done/bin/lib/init-command-router.cjs +0 -58
  343. package/get-shit-done/bin/lib/init.cjs +0 -2112
  344. package/get-shit-done/bin/lib/install-profiles.cjs +0 -603
  345. package/get-shit-done/bin/lib/installer-migration-authoring.cjs +0 -117
  346. package/get-shit-done/bin/lib/installer-migration-report.cjs +0 -355
  347. package/get-shit-done/bin/lib/installer-migrations/000-first-time-baseline.cjs +0 -220
  348. package/get-shit-done/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +0 -41
  349. package/get-shit-done/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +0 -80
  350. package/get-shit-done/bin/lib/installer-migrations.cjs +0 -778
  351. package/get-shit-done/bin/lib/intel.cjs +0 -708
  352. package/get-shit-done/bin/lib/learnings.cjs +0 -421
  353. package/get-shit-done/bin/lib/milestone.cjs +0 -372
  354. package/get-shit-done/bin/lib/model-catalog.cjs +0 -229
  355. package/get-shit-done/bin/lib/model-profiles.cjs +0 -31
  356. package/get-shit-done/bin/lib/observability/event.cjs +0 -82
  357. package/get-shit-done/bin/lib/observability/logger.cjs +0 -174
  358. package/get-shit-done/bin/lib/phase-command-router.cjs +0 -191
  359. package/get-shit-done/bin/lib/phase-lifecycle.cjs +0 -79
  360. package/get-shit-done/bin/lib/phase.cjs +0 -1607
  361. package/get-shit-done/bin/lib/phases-command-router.cjs +0 -39
  362. package/get-shit-done/bin/lib/planning-workspace.cjs +0 -238
  363. package/get-shit-done/bin/lib/profile-output.cjs +0 -1141
  364. package/get-shit-done/bin/lib/profile-pipeline.cjs +0 -539
  365. package/get-shit-done/bin/lib/project-root.cjs +0 -112
  366. package/get-shit-done/bin/lib/prompt-budget.cjs +0 -399
  367. package/get-shit-done/bin/lib/review-reviewer-selection.cjs +0 -126
  368. package/get-shit-done/bin/lib/roadmap-command-router.cjs +0 -162
  369. package/get-shit-done/bin/lib/roadmap-upgrade.cjs +0 -569
  370. package/get-shit-done/bin/lib/roadmap.cjs +0 -651
  371. package/get-shit-done/bin/lib/runtime-artifact-layout.cjs +0 -301
  372. package/get-shit-done/bin/lib/runtime-homes.cjs +0 -222
  373. package/get-shit-done/bin/lib/runtime-name-policy.cjs +0 -83
  374. package/get-shit-done/bin/lib/runtime-slash.cjs +0 -112
  375. package/get-shit-done/bin/lib/secrets.cjs +0 -32
  376. package/get-shit-done/bin/lib/security.cjs +0 -600
  377. package/get-shit-done/bin/lib/shell-command-projection.cjs +0 -535
  378. package/get-shit-done/bin/lib/state-command-router.cjs +0 -252
  379. package/get-shit-done/bin/lib/state.cjs +0 -2073
  380. package/get-shit-done/bin/lib/surface.cjs +0 -470
  381. package/get-shit-done/bin/lib/task-command-router.cjs +0 -81
  382. package/get-shit-done/bin/lib/template.cjs +0 -228
  383. package/get-shit-done/bin/lib/uat.cjs +0 -289
  384. package/get-shit-done/bin/lib/ui-safety-gate.cjs +0 -111
  385. package/get-shit-done/bin/lib/update-context.cjs +0 -209
  386. package/get-shit-done/bin/lib/validate-command-router.cjs +0 -83
  387. package/get-shit-done/bin/lib/validate.cjs +0 -118
  388. package/get-shit-done/bin/lib/verify-command-router.cjs +0 -40
  389. package/get-shit-done/bin/lib/verify.cjs +0 -1614
  390. package/get-shit-done/bin/lib/workstream-inventory.cjs +0 -146
  391. package/get-shit-done/bin/lib/workstream.cjs +0 -389
  392. package/get-shit-done/bin/lib/worktree-safety.cjs +0 -985
  393. package/get-shit-done/workflows/_runtime-launcher.snippet.sh +0 -1
  394. package/scripts/lint-no-source-grep-extras.cjs +0 -81
  395. package/scripts/lint-no-source-grep.cjs +0 -174
  396. /package/{get-shit-done → gsd-core}/bin/shared/config-defaults.manifest.json +0 -0
  397. /package/{get-shit-done → gsd-core}/bin/shared/model-catalog.json +0 -0
  398. /package/{get-shit-done → gsd-core}/bin/shared/runtime-aliases.manifest.json +0 -0
  399. /package/{get-shit-done → gsd-core}/bin/verify-reapply-patches.cjs +0 -0
  400. /package/{get-shit-done → gsd-core}/contexts/dev.md +0 -0
  401. /package/{get-shit-done → gsd-core}/contexts/research.md +0 -0
  402. /package/{get-shit-done → gsd-core}/contexts/review.md +0 -0
  403. /package/{get-shit-done → gsd-core}/references/agent-contracts.md +0 -0
  404. /package/{get-shit-done → gsd-core}/references/ai-evals.md +0 -0
  405. /package/{get-shit-done → gsd-core}/references/ai-frameworks.md +0 -0
  406. /package/{get-shit-done → gsd-core}/references/autonomous-smart-discuss.md +0 -0
  407. /package/{get-shit-done → gsd-core}/references/checkpoints.md +0 -0
  408. /package/{get-shit-done → gsd-core}/references/common-bug-patterns.md +0 -0
  409. /package/{get-shit-done → gsd-core}/references/context-budget.md +0 -0
  410. /package/{get-shit-done → gsd-core}/references/continuation-format.md +0 -0
  411. /package/{get-shit-done → gsd-core}/references/debugger-philosophy.md +0 -0
  412. /package/{get-shit-done → gsd-core}/references/decimal-phase-calculation.md +0 -0
  413. /package/{get-shit-done → gsd-core}/references/doc-conflict-engine.md +0 -0
  414. /package/{get-shit-done → gsd-core}/references/domain-probes.md +0 -0
  415. /package/{get-shit-done → gsd-core}/references/execute-mvp-tdd.md +0 -0
  416. /package/{get-shit-done → gsd-core}/references/executor-examples.md +0 -0
  417. /package/{get-shit-done → gsd-core}/references/gate-prompts.md +0 -0
  418. /package/{get-shit-done → gsd-core}/references/gates.md +0 -0
  419. /package/{get-shit-done → gsd-core}/references/git-integration.md +0 -0
  420. /package/{get-shit-done → gsd-core}/references/git-planning-commit.md +0 -0
  421. /package/{get-shit-done → gsd-core}/references/ios-scaffold.md +0 -0
  422. /package/{get-shit-done → gsd-core}/references/mandatory-initial-read.md +0 -0
  423. /package/{get-shit-done → gsd-core}/references/model-profiles.md +0 -0
  424. /package/{get-shit-done → gsd-core}/references/phase-argument-parsing.md +0 -0
  425. /package/{get-shit-done → gsd-core}/references/planner-antipatterns.md +0 -0
  426. /package/{get-shit-done → gsd-core}/references/planner-chunked.md +0 -0
  427. /package/{get-shit-done → gsd-core}/references/planner-gap-closure.md +0 -0
  428. /package/{get-shit-done → gsd-core}/references/planner-human-verify-mode.md +0 -0
  429. /package/{get-shit-done → gsd-core}/references/planner-interface-context.md +0 -0
  430. /package/{get-shit-done → gsd-core}/references/planner-reviews.md +0 -0
  431. /package/{get-shit-done → gsd-core}/references/planner-revision.md +0 -0
  432. /package/{get-shit-done → gsd-core}/references/planner-source-audit.md +0 -0
  433. /package/{get-shit-done → gsd-core}/references/planning-config.md +0 -0
  434. /package/{get-shit-done → gsd-core}/references/project-skills-discovery.md +0 -0
  435. /package/{get-shit-done → gsd-core}/references/questioning.md +0 -0
  436. /package/{get-shit-done → gsd-core}/references/revision-loop.md +0 -0
  437. /package/{get-shit-done → gsd-core}/references/scout-codebase.md +0 -0
  438. /package/{get-shit-done → gsd-core}/references/skeleton-template.md +0 -0
  439. /package/{get-shit-done → gsd-core}/references/sketch-interactivity.md +0 -0
  440. /package/{get-shit-done → gsd-core}/references/sketch-theme-system.md +0 -0
  441. /package/{get-shit-done → gsd-core}/references/sketch-tooling.md +0 -0
  442. /package/{get-shit-done → gsd-core}/references/sketch-variant-patterns.md +0 -0
  443. /package/{get-shit-done → gsd-core}/references/spidr-splitting.md +0 -0
  444. /package/{get-shit-done → gsd-core}/references/tdd.md +0 -0
  445. /package/{get-shit-done → gsd-core}/references/thinking-models-debug.md +0 -0
  446. /package/{get-shit-done → gsd-core}/references/thinking-models-execution.md +0 -0
  447. /package/{get-shit-done → gsd-core}/references/thinking-models-planning.md +0 -0
  448. /package/{get-shit-done → gsd-core}/references/thinking-models-research.md +0 -0
  449. /package/{get-shit-done → gsd-core}/references/thinking-models-verification.md +0 -0
  450. /package/{get-shit-done → gsd-core}/references/thinking-partner.md +0 -0
  451. /package/{get-shit-done → gsd-core}/references/ui-brand.md +0 -0
  452. /package/{get-shit-done → gsd-core}/references/universal-anti-patterns.md +0 -0
  453. /package/{get-shit-done → gsd-core}/references/user-profiling.md +0 -0
  454. /package/{get-shit-done → gsd-core}/references/user-story-template.md +0 -0
  455. /package/{get-shit-done → gsd-core}/references/verification-overrides.md +0 -0
  456. /package/{get-shit-done → gsd-core}/references/verify-mvp-mode.md +0 -0
  457. /package/{get-shit-done → gsd-core}/references/workstream-flag.md +0 -0
  458. /package/{get-shit-done → gsd-core}/templates/AI-SPEC.md +0 -0
  459. /package/{get-shit-done → gsd-core}/templates/DEBUG.md +0 -0
  460. /package/{get-shit-done → gsd-core}/templates/SECURITY.md +0 -0
  461. /package/{get-shit-done → gsd-core}/templates/UAT.md +0 -0
  462. /package/{get-shit-done → gsd-core}/templates/UI-SPEC.md +0 -0
  463. /package/{get-shit-done → gsd-core}/templates/VALIDATION.md +0 -0
  464. /package/{get-shit-done → gsd-core}/templates/claude-md.md +0 -0
  465. /package/{get-shit-done → gsd-core}/templates/codebase/architecture.md +0 -0
  466. /package/{get-shit-done → gsd-core}/templates/codebase/concerns.md +0 -0
  467. /package/{get-shit-done → gsd-core}/templates/codebase/conventions.md +0 -0
  468. /package/{get-shit-done → gsd-core}/templates/codebase/integrations.md +0 -0
  469. /package/{get-shit-done → gsd-core}/templates/codebase/stack.md +0 -0
  470. /package/{get-shit-done → gsd-core}/templates/codebase/testing.md +0 -0
  471. /package/{get-shit-done → gsd-core}/templates/config.json +0 -0
  472. /package/{get-shit-done → gsd-core}/templates/context.md +0 -0
  473. /package/{get-shit-done → gsd-core}/templates/continue-here.md +0 -0
  474. /package/{get-shit-done → gsd-core}/templates/debug-subagent-prompt.md +0 -0
  475. /package/{get-shit-done → gsd-core}/templates/dev-preferences.md +0 -0
  476. /package/{get-shit-done → gsd-core}/templates/discovery.md +0 -0
  477. /package/{get-shit-done → gsd-core}/templates/discussion-log.md +0 -0
  478. /package/{get-shit-done → gsd-core}/templates/milestone-archive.md +0 -0
  479. /package/{get-shit-done → gsd-core}/templates/milestone.md +0 -0
  480. /package/{get-shit-done → gsd-core}/templates/planner-subagent-prompt.md +0 -0
  481. /package/{get-shit-done → gsd-core}/templates/project.md +0 -0
  482. /package/{get-shit-done → gsd-core}/templates/requirements.md +0 -0
  483. /package/{get-shit-done → gsd-core}/templates/research-project/ARCHITECTURE.md +0 -0
  484. /package/{get-shit-done → gsd-core}/templates/research-project/FEATURES.md +0 -0
  485. /package/{get-shit-done → gsd-core}/templates/research-project/PITFALLS.md +0 -0
  486. /package/{get-shit-done → gsd-core}/templates/research-project/STACK.md +0 -0
  487. /package/{get-shit-done → gsd-core}/templates/research-project/SUMMARY.md +0 -0
  488. /package/{get-shit-done → gsd-core}/templates/research.md +0 -0
  489. /package/{get-shit-done → gsd-core}/templates/retrospective.md +0 -0
  490. /package/{get-shit-done → gsd-core}/templates/roadmap.md +0 -0
  491. /package/{get-shit-done → gsd-core}/templates/spec.md +0 -0
  492. /package/{get-shit-done → gsd-core}/templates/state.md +0 -0
  493. /package/{get-shit-done → gsd-core}/templates/summary-complex.md +0 -0
  494. /package/{get-shit-done → gsd-core}/templates/summary-minimal.md +0 -0
  495. /package/{get-shit-done → gsd-core}/templates/summary-standard.md +0 -0
  496. /package/{get-shit-done → gsd-core}/templates/summary.md +0 -0
  497. /package/{get-shit-done → gsd-core}/templates/user-profile.md +0 -0
  498. /package/{get-shit-done → gsd-core}/templates/user-setup.md +0 -0
  499. /package/{get-shit-done → gsd-core}/templates/verification-report.md +0 -0
  500. /package/{get-shit-done → gsd-core}/workflows/analyze-dependencies.md +0 -0
  501. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/all.md +0 -0
  502. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/analyze.md +0 -0
  503. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/batch.md +0 -0
  504. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/default.md +0 -0
  505. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/text.md +0 -0
  506. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/checkpoint.json +0 -0
  507. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/context.md +0 -0
  508. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/discussion-log.md +0 -0
  509. /package/{get-shit-done → gsd-core}/workflows/discuss-phase-power.md +0 -0
  510. /package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/per-plan-worktree-gate.md +0 -0
  511. /package/{get-shit-done → gsd-core}/workflows/fast.md +0 -0
  512. /package/{get-shit-done → gsd-core}/workflows/help/modes/brief.md +0 -0
  513. /package/{get-shit-done → gsd-core}/workflows/help/modes/default.md +0 -0
  514. /package/{get-shit-done → gsd-core}/workflows/help/modes/topic.md +0 -0
  515. /package/{get-shit-done → gsd-core}/workflows/help.md +0 -0
  516. /package/{get-shit-done → gsd-core}/workflows/inbox.md +0 -0
  517. /package/{get-shit-done → gsd-core}/workflows/list-phase-assumptions.md +0 -0
  518. /package/{get-shit-done → gsd-core}/workflows/node-repair.md +0 -0
  519. /package/{get-shit-done → gsd-core}/workflows/note.md +0 -0
  520. /package/{get-shit-done → gsd-core}/workflows/pr-branch.md +0 -0
  521. /package/{get-shit-done → gsd-core}/workflows/session-report.md +0 -0
@@ -0,0 +1,491 @@
1
+ "use strict";
2
+ /**
3
+ * Roadmap Upgrade — Migration tool for converting legacy 'Phase N' phase IDs
4
+ * to milestone-prefixed 'Phase M-NN' form.
5
+ *
6
+ * ADR-457 build-at-publish: the hand-written bin/lib/roadmap-upgrade.cjs collapsed
7
+ * to a TypeScript source of truth. Behaviour is preserved byte-for-behaviour
8
+ * from the prior hand-written .cjs; only types are added.
9
+ */
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ const node_fs_1 = __importDefault(require("node:fs"));
14
+ const node_path_1 = __importDefault(require("node:path"));
15
+ const node_child_process_1 = require("node:child_process");
16
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
17
+ const planningWorkspace = require("./planning-workspace.cjs");
18
+ const { planningDir } = planningWorkspace;
19
+ // ─── Regex helpers ────────────────────────────────────────────────────────────
20
+ // Matches legacy phase headings: ### Phase N: Name (also decimal: Phase 2.1:)
21
+ // Captures: (hashes)(spaces)(phase-number)(rest-of-line)
22
+ const LEGACY_PHASE_HEADING_RE = /^(#{2,4})\s*(?:\[[^\]]+\]\s*)?Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:(.*)/i;
23
+ // Matches already-migrated phase headings: ### Phase M-NN: Name
24
+ const MIGRATED_PHASE_HEADING_RE = /^#{2,4}\s*(?:\[[^\]]+\]\s*)?Phase\s+\d+-\d{2}\s*:/i;
25
+ // Matches milestone section headings: ## v1.0, ## Roadmap v2.0, ## ✅ v1.0, ## [GSD] v1.0, etc.
26
+ // The optional bracket-token prefix (e.g., [GSD]) must be tested before the emoji group.
27
+ const MILESTONE_HEADING_RE = /^##\s+(?:\[[^\]]+\]\s+|Roadmap\s+|[✅🚧]\s*)?v(\d+)\.(\d+)(?:\s|:)/iu;
28
+ // Matches checklist phase references: - [ ] **Phase N:** or - [x] **Phase N:** (also decimal)
29
+ const CHECKLIST_PHASE_RE = /^(\s*-\s*\[[ x]\]\s*\*{0,2})Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:/gi;
30
+ // ─── Pure computation helpers ─────────────────────────────────────────────────
31
+ /**
32
+ * Parse the ROADMAP.md content and build a list of phase entries with their
33
+ * enclosing milestone major version.
34
+ *
35
+ * Returns an array of:
36
+ * { lineIndex, headingLine, milestoneInt, legacyPhaseNum, phaseName }
37
+ */
38
+ function parseRoadmapPhases(lines) {
39
+ const results = [];
40
+ let currentMilestoneInt = null;
41
+ for (let i = 0; i < lines.length; i++) {
42
+ const line = lines[i];
43
+ const milestoneMatch = line.match(MILESTONE_HEADING_RE);
44
+ if (milestoneMatch) {
45
+ currentMilestoneInt = parseInt(milestoneMatch[1], 10);
46
+ continue;
47
+ }
48
+ if (MIGRATED_PHASE_HEADING_RE.test(line)) {
49
+ // Already-migrated heading found — caller will detect this
50
+ results.push({ lineIndex: i, headingLine: line, alreadyMigrated: true });
51
+ continue;
52
+ }
53
+ const phaseMatch = line.match(LEGACY_PHASE_HEADING_RE);
54
+ if (phaseMatch) {
55
+ results.push({
56
+ lineIndex: i,
57
+ headingLine: line,
58
+ milestoneInt: currentMilestoneInt,
59
+ legacyPhaseNum: phaseMatch[2],
60
+ phaseName: phaseMatch[3].trim(),
61
+ hashes: phaseMatch[1],
62
+ alreadyMigrated: false,
63
+ });
64
+ }
65
+ }
66
+ return results;
67
+ }
68
+ /**
69
+ * Assign sub-indices within each milestone, building a per-entry mapping.
70
+ *
71
+ * Input: array from parseRoadmapPhases (non-migrated entries only).
72
+ * Returns: Map<lineIndex, { newId, milestoneInt, subIndex }>
73
+ *
74
+ * Keyed by `lineIndex` (the unique position of the heading line in ROADMAP.md)
75
+ * so that identical legacy phase numbers in different milestones (e.g., two
76
+ * `Phase 1` headings in v1.0 and v2.0) each get their own correct M-NN ID
77
+ * instead of the later milestone's mapping overwriting the earlier one.
78
+ *
79
+ * Sub-indices are 1-based and sequential within each milestone.
80
+ */
81
+ function assignSubIndices(phaseEntries) {
82
+ const milestoneCounters = new Map(); // milestoneInt → counter
83
+ const mapping = new Map(); // lineIndex → { newId, milestoneInt, subIndex }
84
+ for (const entry of phaseEntries) {
85
+ if (entry.alreadyMigrated)
86
+ continue;
87
+ const m = entry.milestoneInt;
88
+ if (m === null || m === undefined)
89
+ continue;
90
+ const counter = (milestoneCounters.get(m) || 0) + 1;
91
+ milestoneCounters.set(m, counter);
92
+ const subIndex = String(counter).padStart(2, '0');
93
+ const newId = `${m}-${subIndex}`;
94
+ mapping.set(entry.lineIndex, { newId, milestoneInt: m, subIndex: counter, legacyPhaseNum: entry.legacyPhaseNum });
95
+ }
96
+ return mapping;
97
+ }
98
+ /**
99
+ * Read a phase directory name and return its numeric token (stripping project_code prefix).
100
+ * e.g. "GSD-01-setup" → "01", "01-setup" → "01", "02-implement" → "02", "02.1-hotfix" → "02.1"
101
+ */
102
+ function extractPhaseNumFromDir(dirName) {
103
+ // Strip optional project_code prefix: "GSD-01-setup" → "01-setup"
104
+ const stripped = dirName.replace(/^[A-Z]{1,6}-(?=\d)/i, '');
105
+ // Matches: digits + optional letter + optional decimal suffix, followed by '-' or end.
106
+ // e.g. "02.1-hotfix" → "02.1", "01-setup" → "01"
107
+ const m = stripped.match(/^(\d+[A-Z]?(?:\.\d+)*)(?:-|$)/i);
108
+ return m ? m[1] : null;
109
+ }
110
+ /**
111
+ * Build the new directory name from old name and new phase ID.
112
+ * old: "01-setup" newId: "1-02" projectCode: "GSD" → "GSD-01-02-setup"
113
+ * old: "01-setup" newId: "1-02" projectCode: null → "01-02-setup"
114
+ * old: "GSD-01-setup" newId: "1-02" projectCode: "GSD" → "GSD-01-02-setup"
115
+ */
116
+ function buildNewDirName(oldDirName, newId, projectCode) {
117
+ // Strip existing project_code prefix
118
+ const stripped = oldDirName.replace(/^[A-Z]{1,6}-(?=\d)/i, '');
119
+ // Extract slug: everything after "NN-" (the old phase num, including decimal like 02.1)
120
+ const slugMatch = stripped.match(/^\d+[A-Z]?(?:\.\d+)*-(.*)/i);
121
+ const slug = slugMatch ? slugMatch[1] : stripped;
122
+ // Build M-NN prefix (zero-pad both parts)
123
+ const [milestoneStr, subStr] = newId.split('-');
124
+ const milestoneInt = parseInt(milestoneStr, 10);
125
+ const paddedMilestone = String(milestoneInt).padStart(2, '0');
126
+ const newBase = slug ? `${paddedMilestone}-${subStr}-${slug}` : `${paddedMilestone}-${subStr}`;
127
+ return projectCode ? `${projectCode}-${newBase}` : newBase;
128
+ }
129
+ /**
130
+ * Read project_code from config.json if present.
131
+ */
132
+ function readProjectCode(configPath) {
133
+ try {
134
+ const raw = node_fs_1.default.readFileSync(configPath, 'utf8');
135
+ const parsed = JSON.parse(raw);
136
+ return typeof parsed['project_code'] === 'string' ? parsed['project_code'] : null;
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ }
142
+ // ─── computeMigrationPlan ─────────────────────────────────────────────────────
143
+ /**
144
+ * Compute a migration plan without touching the filesystem.
145
+ */
146
+ function computeMigrationPlan(cwd, options = {}) {
147
+ void options;
148
+ const pDir = planningDir(cwd);
149
+ const roadmapPath = node_path_1.default.join(pDir, 'ROADMAP.md');
150
+ const configPath = node_path_1.default.join(pDir, 'config.json');
151
+ const phasesDir = node_path_1.default.join(pDir, 'phases');
152
+ // ── Check config for existing convention ─────────────────────────────────
153
+ let configData = {};
154
+ try {
155
+ configData = JSON.parse(node_fs_1.default.readFileSync(configPath, 'utf8'));
156
+ }
157
+ catch { /* config may not exist */ }
158
+ if (configData['phase_id_convention'] === 'milestone-prefixed') {
159
+ return { alreadyMigrated: true, phases: [], roadmapEdits: [], crossRefEdits: [] };
160
+ }
161
+ const projectCode = typeof configData['project_code'] === 'string' ? configData['project_code'] : null;
162
+ // ── Read ROADMAP.md ───────────────────────────────────────────────────────
163
+ let roadmapContent = '';
164
+ try {
165
+ roadmapContent = node_fs_1.default.readFileSync(roadmapPath, 'utf8');
166
+ }
167
+ catch {
168
+ throw new Error(`ROADMAP.md not found at ${roadmapPath}`);
169
+ }
170
+ const lines = roadmapContent.split('\n');
171
+ const parsedPhases = parseRoadmapPhases(lines);
172
+ // Check for any already-migrated headings
173
+ const hasAnyMigrated = parsedPhases.some(e => e.alreadyMigrated);
174
+ if (hasAnyMigrated) {
175
+ return { alreadyMigrated: true, phases: [], roadmapEdits: [], crossRefEdits: [] };
176
+ }
177
+ const legacyPhases = parsedPhases.filter(e => !e.alreadyMigrated);
178
+ const idMapping = assignSubIndices(legacyPhases);
179
+ // Secondary lookup: (milestoneInt, normalizedLegacyNum) → newId
180
+ // Used for directory renames and checklist rewrites where line position is unknown.
181
+ // For simplicity, each milestone gets its own Map from legacy num → newId.
182
+ const milestoneIdMap = new Map(); // milestoneInt → Map<normalizedLegacyNum, newId>
183
+ for (const [, entry] of idMapping) {
184
+ if (!milestoneIdMap.has(entry.milestoneInt)) {
185
+ milestoneIdMap.set(entry.milestoneInt, new Map());
186
+ }
187
+ const mMap = milestoneIdMap.get(entry.milestoneInt);
188
+ const legacyNum = entry.legacyPhaseNum;
189
+ // Register integer forms (covers plain numeric and letter-suffix IDs)
190
+ const intPart = parseInt(legacyNum, 10);
191
+ const paddedLegacy = String(intPart).padStart(2, '0');
192
+ const unpaddedLegacy = String(intPart);
193
+ mMap.set(paddedLegacy, entry.newId);
194
+ mMap.set(unpaddedLegacy, entry.newId);
195
+ // Also register the original form and padded-integer+decimal form
196
+ // so decimal IDs like "2.1" / "02.1" round-trip correctly.
197
+ mMap.set(legacyNum, entry.newId);
198
+ const dotIdx = legacyNum.indexOf('.');
199
+ if (dotIdx !== -1) {
200
+ const decimalSuffix = legacyNum.slice(dotIdx); // e.g. ".1"
201
+ mMap.set(paddedLegacy + decimalSuffix, entry.newId);
202
+ mMap.set(unpaddedLegacy + decimalSuffix, entry.newId);
203
+ }
204
+ }
205
+ // ── Read existing phase directories ───────────────────────────────────────
206
+ let existingDirs = [];
207
+ try {
208
+ existingDirs = node_fs_1.default.readdirSync(phasesDir).filter(d => {
209
+ try {
210
+ return node_fs_1.default.statSync(node_path_1.default.join(phasesDir, d)).isDirectory();
211
+ }
212
+ catch {
213
+ return false;
214
+ }
215
+ });
216
+ }
217
+ catch { /* phases dir may not exist */ }
218
+ // ── Build phase rename pairs ───────────────────────────────────────────────
219
+ // Flat ordered list of (legacyPhaseNum, newId) in ROADMAP order, for dir matching.
220
+ const orderedMappings = [...idMapping.values()].map(e => ({
221
+ legacyPhaseNum: e.legacyPhaseNum,
222
+ newId: e.newId,
223
+ milestoneInt: e.milestoneInt,
224
+ _used: false,
225
+ }));
226
+ // Note: if the same legacy phase number appears in multiple milestones (the exact legacy
227
+ // ambiguity this tool is designed to resolve), directories are matched in ROADMAP document
228
+ // order — the first ROADMAP occurrence of a given number claims the first matching disk dir.
229
+ // This is the only unambiguous assignment strategy for flat dirs that carry no milestone
230
+ // context. The dry-run output shows the complete rename plan so users can review before
231
+ // applying with --apply.
232
+ const phases = [];
233
+ for (const dirName of existingDirs) {
234
+ const phaseNum = extractPhaseNumFromDir(dirName);
235
+ if (!phaseNum)
236
+ continue;
237
+ const intPart = parseInt(phaseNum, 10);
238
+ const paddedPhaseNum = String(intPart).padStart(2, '0');
239
+ const unpaddedPhaseNum = String(intPart);
240
+ // For decimal IDs like "02.1", also try "2.1"
241
+ const dotIdx = phaseNum.indexOf('.');
242
+ const decimalUnpadded = dotIdx !== -1 ? unpaddedPhaseNum + phaseNum.slice(dotIdx) : null;
243
+ // Find the first unused mapping whose legacy number matches (exact, padded, unpadded, or decimal)
244
+ const found = orderedMappings.find(m => !m._used && (m.legacyPhaseNum === phaseNum ||
245
+ m.legacyPhaseNum === paddedPhaseNum ||
246
+ m.legacyPhaseNum === unpaddedPhaseNum ||
247
+ (decimalUnpadded && m.legacyPhaseNum === decimalUnpadded)));
248
+ if (!found)
249
+ continue;
250
+ found._used = true;
251
+ const newDirName = buildNewDirName(dirName, found.newId, projectCode);
252
+ if (newDirName !== dirName) {
253
+ phases.push({
254
+ oldId: phaseNum,
255
+ newId: found.newId,
256
+ oldDir: dirName,
257
+ newDir: newDirName,
258
+ });
259
+ }
260
+ }
261
+ // ── Build ROADMAP.md line edits ────────────────────────────────────────────
262
+ const roadmapEdits = [];
263
+ for (const entry of legacyPhases) {
264
+ // Use lineIndex as the canonical key (not legacyPhaseNum, which may collide across milestones)
265
+ const mapping = idMapping.get(entry.lineIndex);
266
+ if (!mapping)
267
+ continue;
268
+ // Rewrite heading line: "### Phase N: Name" → "### Phase M-NN: Name"
269
+ const oldLine = lines[entry.lineIndex];
270
+ const newLine = oldLine.replace(/^(#{2,4}\s*(?:\[[^\]]+\]\s*)?Phase\s+)\d+[A-Z]?(?:\.\d+)*(\s*:)/i, `$1${mapping.newId}$2`);
271
+ if (newLine !== oldLine) {
272
+ roadmapEdits.push({ lineIndex: entry.lineIndex, from: oldLine, to: newLine });
273
+ }
274
+ }
275
+ // Rewrite checklist lines in ROADMAP.md — use milestone context to resolve collisions.
276
+ let currentChecklistMilestone = null;
277
+ for (let i = 0; i < lines.length; i++) {
278
+ const line = lines[i];
279
+ // Track enclosing milestone section for context-aware lookup
280
+ const milestoneHeadingMatch = line.match(MILESTONE_HEADING_RE);
281
+ if (milestoneHeadingMatch) {
282
+ currentChecklistMilestone = parseInt(milestoneHeadingMatch[1], 10);
283
+ }
284
+ // Already in roadmapEdits? skip
285
+ if (roadmapEdits.some(e => e.lineIndex === i))
286
+ continue;
287
+ // Match checklist items: "- [ ] **Phase N:**" or "- [x] Phase N:" (also decimal)
288
+ const checklistMatch = line.match(/^(\s*-\s*\[[ x]\]\s*\*{0,2}Phase\s+)(\d+[A-Z]?(?:\.\d+)*)(\s*[:\s*])/i);
289
+ if (checklistMatch) {
290
+ const legacyNum = checklistMatch[2];
291
+ const cIntPart = parseInt(legacyNum, 10);
292
+ const paddedLegacy = String(cIntPart).padStart(2, '0');
293
+ const unpaddedLegacy = String(cIntPart);
294
+ const cDotIdx = legacyNum.indexOf('.');
295
+ const paddedLegacyDecimal = cDotIdx !== -1 ? paddedLegacy + legacyNum.slice(cDotIdx) : null;
296
+ // Prefer milestone-context lookup (avoids collision across milestones)
297
+ let newId;
298
+ if (currentChecklistMilestone !== null && milestoneIdMap.has(currentChecklistMilestone)) {
299
+ const mMap = milestoneIdMap.get(currentChecklistMilestone);
300
+ newId = mMap.get(legacyNum) || mMap.get(paddedLegacy) || mMap.get(unpaddedLegacy);
301
+ if (!newId && paddedLegacyDecimal)
302
+ newId = mMap.get(paddedLegacyDecimal);
303
+ }
304
+ if (!newId) {
305
+ // Fallback: use ordered flat list (no milestone collision in this roadmap)
306
+ const found = orderedMappings.find(m => m.legacyPhaseNum === legacyNum ||
307
+ m.legacyPhaseNum === paddedLegacy ||
308
+ m.legacyPhaseNum === unpaddedLegacy ||
309
+ (paddedLegacyDecimal && m.legacyPhaseNum === paddedLegacyDecimal));
310
+ if (found)
311
+ newId = found.newId;
312
+ }
313
+ if (newId) {
314
+ const newLine = line.replace(/^(\s*-\s*\[[ x]\]\s*\*{0,2}Phase\s+)\d+[A-Z]?(?:\.\d+)*(\s*[:\s*])/i, `$1${newId}$2`);
315
+ if (newLine !== line) {
316
+ roadmapEdits.push({ lineIndex: i, from: line, to: newLine });
317
+ }
318
+ }
319
+ }
320
+ }
321
+ // ── Build cross-ref edits for STATE.md and PROJECT.md ────────────────────
322
+ const crossRefEdits = [];
323
+ const crossRefFiles = ['STATE.md', 'PROJECT.md'];
324
+ for (const fileName of crossRefFiles) {
325
+ const filePath = node_path_1.default.join(pDir, fileName);
326
+ if (!node_fs_1.default.existsSync(filePath))
327
+ continue;
328
+ const fileContent = node_fs_1.default.readFileSync(filePath, 'utf8');
329
+ // Iterate using orderedMappings (ROADMAP order) — idMapping is now keyed by lineIndex.
330
+ for (const m of orderedMappings) {
331
+ const legacyNum = m.legacyPhaseNum;
332
+ const xIntPart = parseInt(legacyNum, 10);
333
+ const paddedNum = String(xIntPart).padStart(2, '0');
334
+ const unpaddedNum = String(xIntPart);
335
+ // Decimal suffix (e.g. ".1" from "2.1") — preserve in cross-ref patterns
336
+ const xDotIdx = legacyNum.indexOf('.');
337
+ const decimalSuffix = xDotIdx !== -1 ? legacyNum.slice(xDotIdx) : '';
338
+ // Rewrite project_code-prefixed references: "GSD-01-" → "GSD-01-02-"
339
+ if (projectCode) {
340
+ const [milestoneStr, subStr] = m.newId.split('-');
341
+ const paddedMilestone = String(parseInt(milestoneStr, 10)).padStart(2, '0');
342
+ const prefixedNew = `${projectCode}-${paddedMilestone}-${subStr}-`;
343
+ // Try both padded and original forms as old prefix
344
+ for (const oldNum of new Set([paddedNum + decimalSuffix, unpaddedNum + decimalSuffix, paddedNum, unpaddedNum])) {
345
+ const prefixedOld = `${projectCode}-${oldNum}-`;
346
+ if (fileContent.includes(prefixedOld)) {
347
+ crossRefEdits.push({ file: fileName, from: prefixedOld, to: prefixedNew });
348
+ }
349
+ }
350
+ }
351
+ // Rewrite prose references: "Phase 1:" → "Phase 1-01:", "Phase 2.1:" → "Phase 1-02:"
352
+ const proseOldPatterns = new Set([
353
+ `Phase ${unpaddedNum}${decimalSuffix}:`,
354
+ `Phase ${paddedNum}${decimalSuffix}:`,
355
+ `Phase ${legacyNum}:`,
356
+ ]);
357
+ for (const proseOld of proseOldPatterns) {
358
+ if (fileContent.includes(proseOld)) {
359
+ const proseNew = `Phase ${m.newId}:`;
360
+ crossRefEdits.push({ file: fileName, from: proseOld, to: proseNew });
361
+ }
362
+ }
363
+ }
364
+ }
365
+ return {
366
+ alreadyMigrated: false,
367
+ phases,
368
+ roadmapEdits,
369
+ crossRefEdits,
370
+ };
371
+ }
372
+ // ─── applyMigration ───────────────────────────────────────────────────────────
373
+ /**
374
+ * Apply the migration plan computed by computeMigrationPlan().
375
+ *
376
+ * @param cwd
377
+ * @param plan
378
+ * @param options
379
+ * @param options.dryRun - Print plan and exit without mutating. (default true)
380
+ */
381
+ function applyMigration(cwd, plan, options = {}) {
382
+ const dryRun = options.dryRun !== false; // default true
383
+ if (plan.alreadyMigrated) {
384
+ return { alreadyMigrated: true };
385
+ }
386
+ if (dryRun) {
387
+ process.stdout.write(JSON.stringify(plan, null, 2) + '\n');
388
+ return { dryRun: true };
389
+ }
390
+ // ── Real run: verify clean working tree ───────────────────────────────────
391
+ let gitStatus;
392
+ try {
393
+ gitStatus = (0, node_child_process_1.execSync)('git status --porcelain', { cwd, encoding: 'utf8' });
394
+ }
395
+ catch (err) {
396
+ throw new Error(`git status failed: ${err.message}`);
397
+ }
398
+ if (gitStatus.trim().length > 0) {
399
+ throw new Error('Working tree is dirty. Commit or stash changes before migrating.');
400
+ }
401
+ // Capture HEAD sha for rollback
402
+ let headSha;
403
+ try {
404
+ headSha = (0, node_child_process_1.execSync)('git rev-parse HEAD', { cwd, encoding: 'utf8' }).trim();
405
+ }
406
+ catch (err) {
407
+ throw new Error(`git rev-parse HEAD failed: ${err.message}`);
408
+ }
409
+ const pDir = planningDir(cwd);
410
+ const phasesDir = node_path_1.default.join(pDir, 'phases');
411
+ const roadmapPath = node_path_1.default.join(pDir, 'ROADMAP.md');
412
+ const configPath = node_path_1.default.join(pDir, 'config.json');
413
+ const renamedDirs = [];
414
+ const editedFiles = [];
415
+ try {
416
+ // 1. Rename phase directories
417
+ for (const phaseEntry of plan.phases) {
418
+ const oldPath = node_path_1.default.join(phasesDir, phaseEntry.oldDir);
419
+ const newPath = node_path_1.default.join(phasesDir, phaseEntry.newDir);
420
+ if (node_fs_1.default.existsSync(oldPath)) {
421
+ node_fs_1.default.renameSync(oldPath, newPath);
422
+ renamedDirs.push(`${phaseEntry.oldDir} → ${phaseEntry.newDir}`);
423
+ }
424
+ }
425
+ // 2. Rewrite ROADMAP.md phase headings
426
+ if (plan.roadmapEdits.length > 0) {
427
+ const roadmapContent = node_fs_1.default.readFileSync(roadmapPath, 'utf8');
428
+ const lines = roadmapContent.split('\n');
429
+ // Sort edits by lineIndex to apply in order
430
+ const sortedEdits = [...plan.roadmapEdits].sort((a, b) => a.lineIndex - b.lineIndex);
431
+ for (const edit of sortedEdits) {
432
+ if (lines[edit.lineIndex] === edit.from) {
433
+ lines[edit.lineIndex] = edit.to;
434
+ }
435
+ }
436
+ node_fs_1.default.writeFileSync(roadmapPath, lines.join('\n'), 'utf8');
437
+ editedFiles.push('ROADMAP.md');
438
+ }
439
+ // 3. Rewrite cross-refs in STATE.md and PROJECT.md
440
+ const crossRefsByFile = new Map();
441
+ for (const edit of plan.crossRefEdits) {
442
+ if (!crossRefsByFile.has(edit.file)) {
443
+ crossRefsByFile.set(edit.file, []);
444
+ }
445
+ crossRefsByFile.get(edit.file).push(edit);
446
+ }
447
+ for (const [fileName, edits] of crossRefsByFile) {
448
+ const filePath = node_path_1.default.join(pDir, fileName);
449
+ if (!node_fs_1.default.existsSync(filePath))
450
+ continue;
451
+ let content = node_fs_1.default.readFileSync(filePath, 'utf8');
452
+ let changed = false;
453
+ for (const edit of edits) {
454
+ if (content.includes(edit.from)) {
455
+ // Replace all occurrences
456
+ content = content.split(edit.from).join(edit.to);
457
+ changed = true;
458
+ }
459
+ }
460
+ if (changed) {
461
+ node_fs_1.default.writeFileSync(filePath, content, 'utf8');
462
+ editedFiles.push(fileName);
463
+ }
464
+ }
465
+ // 4. Update config.json: set phase_id_convention to 'milestone-prefixed'
466
+ let configData = {};
467
+ try {
468
+ configData = JSON.parse(node_fs_1.default.readFileSync(configPath, 'utf8'));
469
+ }
470
+ catch { /* config may not exist yet */ }
471
+ configData['phase_id_convention'] = 'milestone-prefixed';
472
+ node_fs_1.default.writeFileSync(configPath, JSON.stringify(configData, null, 2) + '\n', 'utf8');
473
+ editedFiles.push('config.json');
474
+ }
475
+ catch (err) {
476
+ // Rollback via git reset --hard + git clean
477
+ try {
478
+ (0, node_child_process_1.execSync)(`git reset --hard ${headSha}`, { cwd, stdio: 'pipe' });
479
+ (0, node_child_process_1.execSync)('git clean -fd .planning/phases/', { cwd, stdio: 'pipe' });
480
+ }
481
+ catch {
482
+ // Swallow rollback errors — surface original error
483
+ }
484
+ throw new Error(`Migration failed (rolled back to ${headSha}): ${err.message}`);
485
+ }
486
+ return { applied: true, renamedDirs, editedFiles };
487
+ }
488
+ module.exports = {
489
+ computeMigrationPlan,
490
+ applyMigration,
491
+ };