@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
@@ -1,23 +1,32 @@
1
- 'use strict';
2
-
1
+ "use strict";
3
2
  /**
4
3
  * Workstream Inventory Builder — pure projection from pre-collected
5
4
  * filesystem data to typed WorkstreamInventory. No I/O. No async.
5
+ *
6
+ * ADR-457 build-at-publish: the hand-written
7
+ * bin/lib/workstream-inventory-builder.cjs collapsed to a TypeScript source
8
+ * of truth. Behaviour is preserved byte-for-behaviour from the prior
9
+ * hand-written .cjs; only types are added.
6
10
  */
7
-
8
- const path = require('path');
9
- const relative = path.relative;
10
-
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.isCompletedInventory = isCompletedInventory;
16
+ exports.buildWorkstreamInventory = buildWorkstreamInventory;
17
+ const node_path_1 = __importDefault(require("node:path"));
11
18
  // Internal helpers
12
19
  function toPosixPath(p) {
13
20
  return p.split('\\').join('/');
14
21
  }
15
-
16
22
  function isCompletedInventory(status) {
17
- const s = String(status ?? '').trim().toLowerCase();
23
+ const s = (typeof status === 'string'
24
+ ? status
25
+ : typeof status === 'number' || typeof status === 'boolean'
26
+ ? String(status)
27
+ : '').trim().toLowerCase();
18
28
  return /\bmilestone\s+complete\b/.test(s) || /\barchived\b/.test(s);
19
29
  }
20
-
21
30
  function buildWorkstreamInventory(inputs) {
22
31
  const { name, projectDir, workstreamDir, phaseDirNames, activeWorkstreamName, phaseFilesCounts, roadmapPhaseCount, stateProjection, filesExist, } = inputs;
23
32
  // Index counts by directory for O(1) lookup during sort/iteration
@@ -49,7 +58,7 @@ function buildWorkstreamInventory(inputs) {
49
58
  }
50
59
  return {
51
60
  name,
52
- path: toPosixPath(relative(projectDir, workstreamDir)),
61
+ path: toPosixPath(node_path_1.default.relative(projectDir, workstreamDir)),
53
62
  active: name === activeWorkstreamName,
54
63
  files: {
55
64
  roadmap: filesExist.roadmap,
@@ -70,5 +79,3 @@ function buildWorkstreamInventory(inputs) {
70
79
  : 0,
71
80
  };
72
81
  }
73
-
74
- module.exports = { buildWorkstreamInventory, isCompletedInventory };
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ /**
3
+ * Workstream Inventory Module
4
+ *
5
+ * Owns discovery and read-only projection of .planning/workstreams/* state.
6
+ * Command handlers should render outputs from this inventory instead of
7
+ * rescanning workstream directories directly.
8
+ *
9
+ * Pure projection logic lives in workstream-inventory-builder.cts.
10
+ * This module handles I/O orchestration only.
11
+ *
12
+ * ADR-457 build-at-publish: the hand-written bin/lib/workstream-inventory.cjs
13
+ * collapsed to a TypeScript source of truth. Behaviour is preserved byte-for-behaviour
14
+ * from the prior hand-written .cjs; only types are added.
15
+ */
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ const node_fs_1 = __importDefault(require("node:fs"));
20
+ const node_path_1 = __importDefault(require("node:path"));
21
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
22
+ const core = require("./core.cjs");
23
+ const { toPosixPath, readSubdirectories } = core;
24
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
25
+ const planScan = require("./plan-scan.cjs");
26
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
27
+ const planningWorkspace = require("./planning-workspace.cjs");
28
+ const { planningPaths, planningRoot, getActiveWorkstream } = planningWorkspace;
29
+ const state_document_cjs_1 = require("./state-document.cjs");
30
+ const workstream_inventory_builder_cjs_1 = require("./workstream-inventory-builder.cjs");
31
+ // ─── Implementation ───────────────────────────────────────────────────────────
32
+ function workstreamsRoot(cwd) {
33
+ return node_path_1.default.join(planningRoot(cwd), 'workstreams');
34
+ }
35
+ function countRoadmapPhases(roadmapPath, fallbackCount) {
36
+ try {
37
+ const roadmapContent = node_fs_1.default.readFileSync(roadmapPath, 'utf-8');
38
+ const matches = roadmapContent.match(/^#{2,4}\s+Phase\s+[\w][\w.-]*/gm);
39
+ return matches ? matches.length : fallbackCount;
40
+ }
41
+ catch {
42
+ return fallbackCount;
43
+ }
44
+ }
45
+ function countPhaseFiles(phaseDir) {
46
+ const scan = planScan(phaseDir);
47
+ return { planCount: scan.planCount, summaryCount: scan.summaryCount };
48
+ }
49
+ function readStateProjection(statePath) {
50
+ try {
51
+ const stateContent = node_fs_1.default.readFileSync(statePath, 'utf-8');
52
+ return {
53
+ status: (0, state_document_cjs_1.stateExtractField)(stateContent, 'Status') || 'unknown',
54
+ current_phase: (0, state_document_cjs_1.stateExtractField)(stateContent, 'Current Phase'),
55
+ last_activity: (0, state_document_cjs_1.stateExtractField)(stateContent, 'Last Activity'),
56
+ };
57
+ }
58
+ catch {
59
+ return {
60
+ status: 'unknown',
61
+ current_phase: null,
62
+ last_activity: null,
63
+ };
64
+ }
65
+ }
66
+ function sortWorkstreamInventories(inventories, activeWorkstreamName) {
67
+ return [...inventories].sort((a, b) => {
68
+ const aActive = a.name === activeWorkstreamName ? 1 : 0;
69
+ const bActive = b.name === activeWorkstreamName ? 1 : 0;
70
+ if (aActive !== bActive) {
71
+ return bActive - aActive;
72
+ }
73
+ return a.name.localeCompare(b.name);
74
+ });
75
+ }
76
+ function inspectWorkstream(cwd, name, options = {}) {
77
+ const wsDir = node_path_1.default.join(workstreamsRoot(cwd), name);
78
+ if (!node_fs_1.default.existsSync(wsDir))
79
+ return null;
80
+ const activeWorkstreamName = options.active === undefined ? getActiveWorkstream(cwd) : options.active;
81
+ const p = planningPaths(cwd, name);
82
+ const phaseDirNames = readSubdirectories(p.phases);
83
+ // Collect per-phase file counts
84
+ const phaseFilesCounts = phaseDirNames.map(dir => {
85
+ const counts = countPhaseFiles(node_path_1.default.join(p.phases, dir));
86
+ return { directory: dir, planCount: counts.planCount, summaryCount: counts.summaryCount };
87
+ });
88
+ return (0, workstream_inventory_builder_cjs_1.buildWorkstreamInventory)({
89
+ name,
90
+ projectDir: cwd,
91
+ workstreamDir: wsDir,
92
+ phaseDirNames,
93
+ activeWorkstreamName: activeWorkstreamName ?? '',
94
+ phaseFilesCounts,
95
+ roadmapPhaseCount: countRoadmapPhases(p.roadmap, phaseDirNames.length),
96
+ stateProjection: readStateProjection(p.state),
97
+ filesExist: {
98
+ roadmap: node_fs_1.default.existsSync(p.roadmap),
99
+ state: node_fs_1.default.existsSync(p.state),
100
+ requirements: node_fs_1.default.existsSync(p.requirements),
101
+ },
102
+ });
103
+ }
104
+ function listWorkstreamInventories(cwd) {
105
+ const wsRoot = workstreamsRoot(cwd);
106
+ if (!node_fs_1.default.existsSync(wsRoot)) {
107
+ return {
108
+ mode: 'flat',
109
+ active: null,
110
+ workstreams: [],
111
+ count: 0,
112
+ message: 'No workstreams — operating in flat mode',
113
+ };
114
+ }
115
+ const active = getActiveWorkstream(cwd);
116
+ const entries = node_fs_1.default.readdirSync(wsRoot, { withFileTypes: true });
117
+ const workstreams = [];
118
+ for (const entry of entries) {
119
+ if (!entry.isDirectory())
120
+ continue;
121
+ const inventory = inspectWorkstream(cwd, entry.name, { active });
122
+ if (inventory)
123
+ workstreams.push(inventory);
124
+ }
125
+ const ordered = sortWorkstreamInventories(workstreams, active);
126
+ return {
127
+ mode: 'workstream',
128
+ active,
129
+ workstreams: ordered,
130
+ count: ordered.length,
131
+ };
132
+ }
133
+ function getOtherActiveWorkstreamInventories(cwd, excludeWs) {
134
+ return listWorkstreamInventories(cwd).workstreams
135
+ .filter(inventory => inventory.name !== excludeWs)
136
+ .filter(inventory => !(0, workstream_inventory_builder_cjs_1.isCompletedInventory)(inventory.status));
137
+ }
138
+ module.exports = {
139
+ countPhaseFiles,
140
+ countRoadmapPhases,
141
+ getOtherActiveWorkstreamInventories,
142
+ inspectWorkstream,
143
+ isCompletedInventory: workstream_inventory_builder_cjs_1.isCompletedInventory,
144
+ listWorkstreamInventories,
145
+ sortWorkstreamInventories,
146
+ workstreamsRoot,
147
+ };
@@ -1,18 +1,36 @@
1
- 'use strict';
2
-
1
+ "use strict";
3
2
  /**
4
- * Canonical workstream name validation and slug normalization.
3
+ * Canonical workstream name validation and slug normalization
4
+ * (ADR-457 build-at-publish: the hand-written bin/lib/workstream-name-policy.cjs
5
+ * collapsed to a TypeScript source of truth). Behaviour is preserved
6
+ * byte-for-behaviour from the prior hand-written .cjs; only types are added.
7
+ *
5
8
  * Used by active-workstream-store.cjs, planning-workspace.cjs, workstream.cjs.
6
9
  */
7
-
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE = void 0;
12
+ exports.normalizeWorkstreamNameInput = normalizeWorkstreamNameInput;
13
+ exports.hasInvalidPathSegment = hasInvalidPathSegment;
14
+ exports.validateActiveWorkstreamName = validateActiveWorkstreamName;
15
+ exports.validateWorkstreamName = validateWorkstreamName;
16
+ exports.toWorkstreamSlug = toWorkstreamSlug;
17
+ exports.isValidActiveWorkstreamName = isValidActiveWorkstreamName;
18
+ exports.assertValidActiveWorkstreamName = assertValidActiveWorkstreamName;
19
+ exports.INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE = 'Invalid workstream name: must be alphanumeric, hyphens, underscores, or dots';
8
20
  const ACTIVE_WORKSTREAM_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
9
- const INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE = 'Invalid workstream name: must be alphanumeric, hyphens, underscores, or dots';
10
-
11
21
  function normalizeWorkstreamNameInput(name) {
12
- const value = String(name || '').trim();
22
+ const value = String(name ?? '').trim();
13
23
  return value || null;
14
24
  }
15
-
25
+ /**
26
+ * Returns true when `name` contains a path separator, a bare dot, or a
27
+ * dot-dot sequence — any of which would make the name unsafe for use as a
28
+ * filesystem path segment.
29
+ */
30
+ function hasInvalidPathSegment(name) {
31
+ const value = String(name ?? '');
32
+ return /[/\\]/.test(value) || value === '.' || value === '..' || value.includes('..');
33
+ }
16
34
  function validateActiveWorkstreamName(name) {
17
35
  const value = normalizeWorkstreamNameInput(name);
18
36
  if (!value) {
@@ -50,20 +68,11 @@ function validateWorkstreamName(name) {
50
68
  * Lowercases, collapses non-alphanumeric runs to hyphens, strips leading/trailing hyphens.
51
69
  */
52
70
  function toWorkstreamSlug(name) {
53
- return String(name || '')
71
+ return String(name ?? '')
54
72
  .toLowerCase()
55
73
  .replace(/[^a-z0-9]+/g, '-')
56
74
  .replace(/^-+|-+$/g, '');
57
75
  }
58
- /**
59
- * Returns true when `name` contains a path separator, a bare dot, or a
60
- * dot-dot sequence — any of which would make the name unsafe for use as a
61
- * filesystem path segment.
62
- */
63
- function hasInvalidPathSegment(name) {
64
- const value = String(name || '');
65
- return /[/\\]/.test(value) || value === '.' || value === '..' || value.includes('..');
66
- }
67
76
  /**
68
77
  * Returns true when `name` is a valid active workstream name:
69
78
  * - Must start with alphanumeric
@@ -73,22 +82,10 @@ function hasInvalidPathSegment(name) {
73
82
  function isValidActiveWorkstreamName(name) {
74
83
  return validateActiveWorkstreamName(name).ok;
75
84
  }
76
-
77
- function assertValidActiveWorkstreamName(name, errorMessage = INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE) {
85
+ function assertValidActiveWorkstreamName(name, errorMessage = exports.INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE) {
78
86
  const validation = validateActiveWorkstreamName(name);
79
87
  if (!validation.ok) {
80
88
  throw new Error(errorMessage);
81
89
  }
82
90
  return validation.value;
83
91
  }
84
-
85
- module.exports = {
86
- INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE,
87
- normalizeWorkstreamNameInput,
88
- validateActiveWorkstreamName,
89
- validateWorkstreamName,
90
- toWorkstreamSlug,
91
- hasInvalidPathSegment,
92
- isValidActiveWorkstreamName,
93
- assertValidActiveWorkstreamName,
94
- };
@@ -0,0 +1,380 @@
1
+ "use strict";
2
+ /**
3
+ * Workstream — CRUD operations for workstream namespacing
4
+ *
5
+ * Workstreams enable parallel milestones by scoping ROADMAP.md, STATE.md,
6
+ * REQUIREMENTS.md, and phases/ into .planning/workstreams/{name}/ directories.
7
+ *
8
+ * When no workstreams/ directory exists, GSD operates in "flat mode" with
9
+ * everything at .planning/ — backward compatible with pre-workstream installs.
10
+ *
11
+ * ADR-457 build-at-publish: the hand-written bin/lib/workstream.cjs collapsed
12
+ * to a TypeScript source of truth. Behaviour is preserved byte-for-behaviour
13
+ * from the prior hand-written .cjs; only strict types are added.
14
+ */
15
+ var __importDefault = (this && this.__importDefault) || function (mod) {
16
+ return (mod && mod.__esModule) ? mod : { "default": mod };
17
+ };
18
+ const node_fs_1 = __importDefault(require("node:fs"));
19
+ const node_path_1 = __importDefault(require("node:path"));
20
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
21
+ const core = require("./core.cjs");
22
+ const { output, error, toPosixPath, getMilestoneInfo, generateSlugInternal } = core;
23
+ const shell_command_projection_cjs_1 = require("./shell-command-projection.cjs");
24
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
25
+ const planningWorkspace = require("./planning-workspace.cjs");
26
+ const { planningRoot, setActiveWorkstream, getActiveWorkstream } = planningWorkspace;
27
+ const workstream_name_policy_cjs_1 = require("./workstream-name-policy.cjs");
28
+ const runtime_slash_cjs_1 = require("./runtime-slash.cjs");
29
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
30
+ const workstreamInventory = require("./workstream-inventory.cjs");
31
+ const { getOtherActiveWorkstreamInventories, inspectWorkstream, listWorkstreamInventories, } = workstreamInventory;
32
+ // ─── Migration ───────────────────────────────────────────────────────────────
33
+ /**
34
+ * Migrate flat .planning/ layout to workstream mode.
35
+ * Moves per-workstream files (ROADMAP.md, STATE.md, REQUIREMENTS.md, phases/)
36
+ * into .planning/workstreams/{name}/. Shared files (PROJECT.md, config.json,
37
+ * milestones/, research/, codebase/, todos/) stay in place.
38
+ */
39
+ function migrateToWorkstreams(cwd, workstreamName) {
40
+ try {
41
+ (0, workstream_name_policy_cjs_1.assertValidActiveWorkstreamName)(workstreamName, 'Invalid workstream name for migration');
42
+ }
43
+ catch {
44
+ throw new Error('Invalid workstream name for migration');
45
+ }
46
+ const baseDir = planningRoot(cwd);
47
+ const wsDir = node_path_1.default.join(baseDir, 'workstreams', workstreamName);
48
+ if (node_fs_1.default.existsSync(node_path_1.default.join(baseDir, 'workstreams'))) {
49
+ throw new Error('Already in workstream mode — .planning/workstreams/ exists');
50
+ }
51
+ const toMove = [
52
+ { name: 'ROADMAP.md', type: 'file' },
53
+ { name: 'STATE.md', type: 'file' },
54
+ { name: 'REQUIREMENTS.md', type: 'file' },
55
+ { name: 'phases', type: 'dir' },
56
+ ];
57
+ (0, shell_command_projection_cjs_1.platformEnsureDir)(wsDir);
58
+ const filesMoved = [];
59
+ try {
60
+ for (const item of toMove) {
61
+ const src = node_path_1.default.join(baseDir, item.name);
62
+ if (node_fs_1.default.existsSync(src)) {
63
+ const dest = node_path_1.default.join(wsDir, item.name);
64
+ node_fs_1.default.renameSync(src, dest);
65
+ filesMoved.push(item.name);
66
+ }
67
+ }
68
+ }
69
+ catch (err) {
70
+ for (const name of filesMoved) {
71
+ try {
72
+ node_fs_1.default.renameSync(node_path_1.default.join(wsDir, name), node_path_1.default.join(baseDir, name));
73
+ }
74
+ catch { /* ignore */ }
75
+ }
76
+ try {
77
+ node_fs_1.default.rmSync(wsDir, { recursive: true });
78
+ }
79
+ catch { /* ignore */ }
80
+ try {
81
+ node_fs_1.default.rmdirSync(node_path_1.default.join(baseDir, 'workstreams'));
82
+ }
83
+ catch { /* ignore */ }
84
+ throw err;
85
+ }
86
+ return { migrated: true, workstream: workstreamName, files_moved: filesMoved };
87
+ }
88
+ // ─── CRUD Commands ────────────────────────────────────────────────────────────
89
+ function cmdWorkstreamCreate(cwd, name, options, raw) {
90
+ if (!name) {
91
+ error('workstream name required. Usage: workstream create <name>');
92
+ }
93
+ const slug = (0, workstream_name_policy_cjs_1.toWorkstreamSlug)(name);
94
+ if (!slug) {
95
+ error('Invalid workstream name — must contain at least one alphanumeric character');
96
+ }
97
+ const baseDir = planningRoot(cwd);
98
+ if (!node_fs_1.default.existsSync(baseDir)) {
99
+ error(`.planning/ directory not found — run ${(0, runtime_slash_cjs_1.formatGsdSlash)('new-project', (0, runtime_slash_cjs_1.resolveRuntime)(cwd))} first`);
100
+ }
101
+ const wsRoot = node_path_1.default.join(baseDir, 'workstreams');
102
+ const wsDir = node_path_1.default.join(wsRoot, slug);
103
+ if (node_fs_1.default.existsSync(wsDir) && node_fs_1.default.existsSync(node_path_1.default.join(wsDir, 'STATE.md'))) {
104
+ output({ created: false, error: 'already_exists', workstream: slug, path: toPosixPath(node_path_1.default.relative(cwd, wsDir)) }, raw, undefined);
105
+ return;
106
+ }
107
+ const isFlatMode = !node_fs_1.default.existsSync(wsRoot);
108
+ let migration = null;
109
+ if (isFlatMode && options.migrate !== false) {
110
+ const hasExistingWork = node_fs_1.default.existsSync(node_path_1.default.join(baseDir, 'ROADMAP.md')) ||
111
+ node_fs_1.default.existsSync(node_path_1.default.join(baseDir, 'STATE.md')) ||
112
+ node_fs_1.default.existsSync(node_path_1.default.join(baseDir, 'phases'));
113
+ if (hasExistingWork) {
114
+ const migrateName = options.migrateName || null;
115
+ let existingWsName;
116
+ if (migrateName) {
117
+ const slugged = (0, workstream_name_policy_cjs_1.toWorkstreamSlug)(migrateName);
118
+ if (!slugged) {
119
+ output({
120
+ created: false,
121
+ error: 'migration_failed',
122
+ message: 'Invalid migrate-name — must contain at least one alphanumeric character',
123
+ }, raw, undefined);
124
+ return;
125
+ }
126
+ existingWsName = slugged;
127
+ }
128
+ else {
129
+ try {
130
+ const milestone = getMilestoneInfo(cwd);
131
+ existingWsName = generateSlugInternal(milestone.name) || 'default';
132
+ }
133
+ catch {
134
+ existingWsName = 'default';
135
+ }
136
+ }
137
+ try {
138
+ migration = migrateToWorkstreams(cwd, existingWsName);
139
+ }
140
+ catch (e) {
141
+ output({ created: false, error: 'migration_failed', message: e.message }, raw, undefined);
142
+ return;
143
+ }
144
+ }
145
+ else {
146
+ (0, shell_command_projection_cjs_1.platformEnsureDir)(wsRoot);
147
+ }
148
+ }
149
+ (0, shell_command_projection_cjs_1.platformEnsureDir)(wsDir);
150
+ (0, shell_command_projection_cjs_1.platformEnsureDir)(node_path_1.default.join(wsDir, 'phases'));
151
+ const today = new Date().toISOString().split('T')[0];
152
+ const stateContent = [
153
+ '---',
154
+ `workstream: ${slug}`,
155
+ `created: ${today}`,
156
+ '---',
157
+ '',
158
+ '# Project State',
159
+ '',
160
+ '## Current Position',
161
+ '**Status:** Not started',
162
+ '**Current Phase:** None',
163
+ `**Last Activity:** ${today}`,
164
+ '**Last Activity Description:** Workstream created',
165
+ '',
166
+ '## Progress',
167
+ '**Phases Complete:** 0',
168
+ '**Current Plan:** N/A',
169
+ '',
170
+ '## Session Continuity',
171
+ '**Stopped At:** N/A',
172
+ '**Resume File:** None',
173
+ '',
174
+ ].join('\n');
175
+ const statePath = node_path_1.default.join(wsDir, 'STATE.md');
176
+ if (!node_fs_1.default.existsSync(statePath)) {
177
+ (0, shell_command_projection_cjs_1.platformWriteSync)(statePath, stateContent);
178
+ }
179
+ setActiveWorkstream(cwd, slug);
180
+ const relPath = toPosixPath(node_path_1.default.relative(cwd, wsDir));
181
+ output({
182
+ created: true,
183
+ workstream: slug,
184
+ path: relPath,
185
+ state_path: relPath + '/STATE.md',
186
+ phases_path: relPath + '/phases',
187
+ migration: migration || null,
188
+ active: true,
189
+ }, raw, undefined);
190
+ }
191
+ function cmdWorkstreamList(cwd, raw) {
192
+ const inventory = listWorkstreamInventories(cwd);
193
+ if (inventory.mode === 'flat') {
194
+ output({ mode: 'flat', workstreams: [], message: inventory.message }, raw, undefined);
195
+ return;
196
+ }
197
+ const workstreams = inventory.workstreams.map(ws => ({
198
+ name: ws.name,
199
+ path: ws.path,
200
+ has_roadmap: ws.files.roadmap,
201
+ has_state: ws.files.state,
202
+ status: ws.status,
203
+ current_phase: ws.current_phase,
204
+ phase_count: ws.phase_count,
205
+ completed_phases: ws.completed_phases,
206
+ }));
207
+ output({ mode: 'workstream', workstreams, count: workstreams.length }, raw, undefined);
208
+ }
209
+ function cmdWorkstreamStatus(cwd, name, raw) {
210
+ if (!name)
211
+ error('workstream name required. Usage: workstream status <name>');
212
+ try {
213
+ (0, workstream_name_policy_cjs_1.assertValidActiveWorkstreamName)(name, workstream_name_policy_cjs_1.INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE);
214
+ }
215
+ catch {
216
+ error(workstream_name_policy_cjs_1.INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE);
217
+ }
218
+ const wsDir = node_path_1.default.join(planningRoot(cwd), 'workstreams', name);
219
+ if (!node_fs_1.default.existsSync(wsDir)) {
220
+ output({ found: false, workstream: name }, raw, undefined);
221
+ return;
222
+ }
223
+ const inv = inspectWorkstream(cwd, name);
224
+ if (!inv) {
225
+ output({ found: false, workstream: name }, raw, undefined);
226
+ return;
227
+ }
228
+ output({
229
+ found: true,
230
+ workstream: name,
231
+ path: inv.path,
232
+ files: inv.files,
233
+ phases: inv.phases,
234
+ phase_count: inv.phase_count,
235
+ completed_phases: inv.completed_phases,
236
+ status: inv.status,
237
+ current_phase: inv.current_phase,
238
+ last_activity: inv.last_activity,
239
+ }, raw, undefined);
240
+ }
241
+ function cmdWorkstreamComplete(cwd, name, options, raw) {
242
+ if (!name)
243
+ error('workstream name required. Usage: workstream complete <name>');
244
+ try {
245
+ (0, workstream_name_policy_cjs_1.assertValidActiveWorkstreamName)(name, workstream_name_policy_cjs_1.INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE);
246
+ }
247
+ catch {
248
+ error(workstream_name_policy_cjs_1.INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE);
249
+ }
250
+ const root = planningRoot(cwd);
251
+ const wsRoot = node_path_1.default.join(root, 'workstreams');
252
+ const wsDir = node_path_1.default.join(wsRoot, name);
253
+ if (!node_fs_1.default.existsSync(wsDir)) {
254
+ output({ completed: false, error: 'not_found', workstream: name }, raw, undefined);
255
+ return;
256
+ }
257
+ const active = getActiveWorkstream(cwd);
258
+ if (active === name)
259
+ setActiveWorkstream(cwd, null);
260
+ const archiveDir = node_path_1.default.join(root, 'milestones');
261
+ const today = new Date().toISOString().split('T')[0];
262
+ let archivePath = node_path_1.default.join(archiveDir, `ws-${name}-${today}`);
263
+ let suffix = 1;
264
+ while (node_fs_1.default.existsSync(archivePath)) {
265
+ archivePath = node_path_1.default.join(archiveDir, `ws-${name}-${today}-${suffix++}`);
266
+ }
267
+ (0, shell_command_projection_cjs_1.platformEnsureDir)(archivePath);
268
+ const filesMoved = [];
269
+ try {
270
+ const entries = node_fs_1.default.readdirSync(wsDir, { withFileTypes: true });
271
+ for (const entry of entries) {
272
+ node_fs_1.default.renameSync(node_path_1.default.join(wsDir, entry.name), node_path_1.default.join(archivePath, entry.name));
273
+ filesMoved.push(entry.name);
274
+ }
275
+ }
276
+ catch (err) {
277
+ for (const fname of filesMoved) {
278
+ try {
279
+ node_fs_1.default.renameSync(node_path_1.default.join(archivePath, fname), node_path_1.default.join(wsDir, fname));
280
+ }
281
+ catch { /* ignore */ }
282
+ }
283
+ try {
284
+ node_fs_1.default.rmSync(archivePath, { recursive: true });
285
+ }
286
+ catch { /* ignore */ }
287
+ if (active === name)
288
+ setActiveWorkstream(cwd, name);
289
+ output({ completed: false, error: 'archive_failed', message: err.message, workstream: name }, raw, undefined);
290
+ return;
291
+ }
292
+ try {
293
+ node_fs_1.default.rmdirSync(wsDir);
294
+ }
295
+ catch { /* ignore */ }
296
+ let remainingWs = 0;
297
+ try {
298
+ remainingWs = node_fs_1.default.readdirSync(wsRoot, { withFileTypes: true }).filter(e => e.isDirectory()).length;
299
+ if (remainingWs === 0)
300
+ node_fs_1.default.rmdirSync(wsRoot);
301
+ }
302
+ catch { /* ignore */ }
303
+ output({
304
+ completed: true,
305
+ workstream: name,
306
+ archived_to: toPosixPath(node_path_1.default.relative(cwd, archivePath)),
307
+ remaining_workstreams: remainingWs,
308
+ reverted_to_flat: remainingWs === 0,
309
+ }, raw, undefined);
310
+ }
311
+ // ─── Active Workstream Commands ───────────────────────────────────────────────
312
+ function cmdWorkstreamSet(cwd, name, raw) {
313
+ if (!name || name === '--clear') {
314
+ if (name !== '--clear') {
315
+ error('Workstream name required. Usage: workstream set <name> (or workstream set --clear to unset)');
316
+ }
317
+ const previous = getActiveWorkstream(cwd);
318
+ setActiveWorkstream(cwd, null);
319
+ output({ active: null, cleared: true, previous: previous || null }, raw, undefined);
320
+ return;
321
+ }
322
+ if (!(0, workstream_name_policy_cjs_1.isValidActiveWorkstreamName)(name)) {
323
+ output({ active: null, error: 'invalid_name', message: 'Workstream name must be alphanumeric, hyphens, underscores, or dots' }, raw, undefined);
324
+ return;
325
+ }
326
+ const wsDir = node_path_1.default.join(planningRoot(cwd), 'workstreams', name);
327
+ if (!node_fs_1.default.existsSync(wsDir)) {
328
+ output({ active: null, error: 'not_found', workstream: name }, raw, undefined);
329
+ return;
330
+ }
331
+ setActiveWorkstream(cwd, name);
332
+ output({ active: name, set: true }, raw, name);
333
+ }
334
+ function cmdWorkstreamGet(cwd, raw) {
335
+ const active = getActiveWorkstream(cwd);
336
+ const wsRoot = node_path_1.default.join(planningRoot(cwd), 'workstreams');
337
+ output({ active, mode: node_fs_1.default.existsSync(wsRoot) ? 'workstream' : 'flat' }, raw, active || 'none');
338
+ }
339
+ function cmdWorkstreamProgress(cwd, raw) {
340
+ const inventory = listWorkstreamInventories(cwd);
341
+ if (inventory.mode === 'flat') {
342
+ output({ mode: 'flat', workstreams: [], message: inventory.message }, raw, undefined);
343
+ return;
344
+ }
345
+ const workstreams = inventory.workstreams.map(ws => ({
346
+ name: ws.name,
347
+ active: ws.active,
348
+ status: ws.status,
349
+ current_phase: ws.current_phase ?? null,
350
+ phases: `${ws.completed_phases}/${ws.roadmap_phase_count}`,
351
+ plans: `${ws.completed_plans}/${ws.total_plans}`,
352
+ progress_percent: ws.progress_percent,
353
+ }));
354
+ output({ mode: 'workstream', active: inventory.active, workstreams, count: workstreams.length }, raw, undefined);
355
+ }
356
+ // ─── Collision Detection ──────────────────────────────────────────────────────
357
+ /**
358
+ * Return other workstreams that are NOT complete.
359
+ * Used to detect whether the milestone has active parallel work
360
+ * when a workstream finishes its last phase.
361
+ */
362
+ function getOtherActiveWorkstreams(cwd, excludeWs) {
363
+ return getOtherActiveWorkstreamInventories(cwd, excludeWs).map(ws => ({
364
+ name: ws.name,
365
+ status: ws.status,
366
+ current_phase: ws.current_phase ?? null,
367
+ phases: `${ws.completed_phases}/${ws.phase_count}`,
368
+ }));
369
+ }
370
+ module.exports = {
371
+ migrateToWorkstreams,
372
+ cmdWorkstreamCreate,
373
+ cmdWorkstreamList,
374
+ cmdWorkstreamStatus,
375
+ cmdWorkstreamComplete,
376
+ cmdWorkstreamSet,
377
+ cmdWorkstreamGet,
378
+ cmdWorkstreamProgress,
379
+ getOtherActiveWorkstreams,
380
+ };