@opengsd/gsd-core 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (532) hide show
  1. package/README.ja-JP.md +46 -791
  2. package/README.ko-KR.md +44 -780
  3. package/README.md +42 -218
  4. package/README.pt-BR.md +47 -414
  5. package/README.zh-CN.md +46 -763
  6. package/agents/gsd-ai-researcher.md +2 -2
  7. package/agents/gsd-debug-session-manager.md +1 -1
  8. package/agents/gsd-debugger.md +8 -8
  9. package/agents/gsd-doc-writer.md +7 -6
  10. package/agents/gsd-domain-researcher.md +15 -2
  11. package/agents/gsd-eval-auditor.md +1 -1
  12. package/agents/gsd-eval-planner.md +2 -2
  13. package/agents/gsd-executor.md +21 -8
  14. package/agents/gsd-framework-selector.md +1 -1
  15. package/agents/gsd-intel-updater.md +4 -4
  16. package/agents/gsd-phase-researcher.md +19 -6
  17. package/agents/gsd-plan-checker.md +3 -3
  18. package/agents/gsd-planner.md +36 -23
  19. package/agents/gsd-project-researcher.md +13 -0
  20. package/agents/gsd-research-synthesizer.md +6 -2
  21. package/agents/gsd-roadmapper.md +6 -6
  22. package/agents/gsd-ui-researcher.md +16 -3
  23. package/agents/gsd-user-profiler.md +2 -2
  24. package/agents/gsd-verifier.md +8 -8
  25. package/assets/gsd-logo-2000-transparent.png +0 -0
  26. package/assets/gsd-logo-2000-transparent.svg +17 -0
  27. package/assets/gsd-logo-2000.png +0 -0
  28. package/assets/gsd-logo-2000.svg +21 -0
  29. package/assets/terminal.svg +68 -0
  30. package/bin/install.js +255 -103
  31. package/commands/gsd/add-tests.md +1 -1
  32. package/commands/gsd/ai-integration-phase.md +3 -3
  33. package/commands/gsd/audit-fix.md +1 -1
  34. package/commands/gsd/audit-milestone.md +1 -1
  35. package/commands/gsd/audit-uat.md +1 -1
  36. package/commands/gsd/autonomous.md +2 -2
  37. package/commands/gsd/capture.md +6 -6
  38. package/commands/gsd/cleanup.md +1 -1
  39. package/commands/gsd/code-review.md +1 -1
  40. package/commands/gsd/complete-milestone.md +2 -2
  41. package/commands/gsd/config.md +3 -3
  42. package/commands/gsd/debug.md +1 -1
  43. package/commands/gsd/discuss-phase.md +5 -4
  44. package/commands/gsd/docs-update.md +1 -1
  45. package/commands/gsd/eval-review.md +2 -2
  46. package/commands/gsd/execute-phase.md +2 -2
  47. package/commands/gsd/explore.md +1 -1
  48. package/commands/gsd/extract-learnings.md +2 -2
  49. package/commands/gsd/fast.md +1 -1
  50. package/commands/gsd/forensics.md +1 -1
  51. package/commands/gsd/graphify.md +9 -9
  52. package/commands/gsd/health.md +1 -1
  53. package/commands/gsd/help.md +2 -2
  54. package/commands/gsd/import.md +5 -5
  55. package/commands/gsd/inbox.md +1 -1
  56. package/commands/gsd/ingest-docs.md +4 -4
  57. package/commands/gsd/manager.md +3 -3
  58. package/commands/gsd/map-codebase.md +1 -1
  59. package/commands/gsd/milestone-summary.md +1 -1
  60. package/commands/gsd/mvp-phase.md +4 -4
  61. package/commands/gsd/new-milestone.md +5 -5
  62. package/commands/gsd/new-project.md +5 -5
  63. package/commands/gsd/pause-work.md +2 -2
  64. package/commands/gsd/phase.md +4 -4
  65. package/commands/gsd/plan-phase.md +2 -2
  66. package/commands/gsd/plan-review-convergence.md +4 -4
  67. package/commands/gsd/pr-branch.md +1 -1
  68. package/commands/gsd/profile-user.md +2 -2
  69. package/commands/gsd/progress.md +4 -4
  70. package/commands/gsd/quick.md +1 -1
  71. package/commands/gsd/resume-work.md +1 -1
  72. package/commands/gsd/review.md +3 -2
  73. package/commands/gsd/secure-phase.md +1 -1
  74. package/commands/gsd/settings.md +1 -1
  75. package/commands/gsd/ship.md +2 -2
  76. package/commands/gsd/sketch.md +7 -7
  77. package/commands/gsd/spec-phase.md +2 -2
  78. package/commands/gsd/spike.md +3 -3
  79. package/commands/gsd/stats.md +1 -1
  80. package/commands/gsd/surface.md +4 -4
  81. package/commands/gsd/thread.md +1 -1
  82. package/commands/gsd/ui-phase.md +2 -2
  83. package/commands/gsd/ui-review.md +2 -2
  84. package/commands/gsd/ultraplan-phase.md +2 -2
  85. package/commands/gsd/undo.md +3 -3
  86. package/commands/gsd/update.md +3 -3
  87. package/commands/gsd/validate-phase.md +1 -1
  88. package/commands/gsd/verify-work.md +2 -2
  89. package/commands/gsd/workspace.md +4 -4
  90. package/{get-shit-done → gsd-core}/bin/check-latest-version.cjs +1 -1
  91. package/{get-shit-done → gsd-core}/bin/gsd-tools.cjs +50 -4
  92. package/gsd-core/bin/lib/active-workstream-store.cjs +291 -0
  93. package/gsd-core/bin/lib/adr-parser.cjs +399 -0
  94. package/gsd-core/bin/lib/agent-command-router.cjs +68 -0
  95. package/gsd-core/bin/lib/artifacts.cjs +51 -0
  96. package/gsd-core/bin/lib/audit.cjs +743 -0
  97. package/gsd-core/bin/lib/check-command-router.cjs +342 -0
  98. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +81 -0
  99. package/gsd-core/bin/lib/clock.cjs +95 -0
  100. package/gsd-core/bin/lib/clusters.cjs +128 -0
  101. package/gsd-core/bin/lib/code-review-flags.cjs +59 -0
  102. package/gsd-core/bin/lib/command-aliases.cjs +809 -0
  103. package/gsd-core/bin/lib/command-arg-projection.cjs +55 -0
  104. package/gsd-core/bin/lib/command-routing-hub.cjs +300 -0
  105. package/gsd-core/bin/lib/commands.cjs +1202 -0
  106. package/gsd-core/bin/lib/config-schema.cjs +29 -0
  107. package/gsd-core/bin/lib/config-types.cjs +19 -0
  108. package/gsd-core/bin/lib/config.cjs +714 -0
  109. package/{get-shit-done → gsd-core}/bin/lib/configuration.cjs +76 -85
  110. package/gsd-core/bin/lib/context-utilization.cjs +48 -0
  111. package/gsd-core/bin/lib/core.cjs +2007 -0
  112. package/{get-shit-done → gsd-core}/bin/lib/decisions.cjs +9 -7
  113. package/gsd-core/bin/lib/docs.cjs +252 -0
  114. package/gsd-core/bin/lib/drift.cjs +364 -0
  115. package/gsd-core/bin/lib/fallow-runner.cjs +115 -0
  116. package/gsd-core/bin/lib/frontmatter.cjs +442 -0
  117. package/gsd-core/bin/lib/gap-checker.cjs +257 -0
  118. package/gsd-core/bin/lib/graphify.cjs +496 -0
  119. package/gsd-core/bin/lib/gsd2-import.cjs +456 -0
  120. package/gsd-core/bin/lib/init-command-router.cjs +62 -0
  121. package/gsd-core/bin/lib/init.cjs +1799 -0
  122. package/gsd-core/bin/lib/install-profiles.cjs +526 -0
  123. package/gsd-core/bin/lib/installer-migration-authoring.cjs +122 -0
  124. package/gsd-core/bin/lib/installer-migration-report.cjs +347 -0
  125. package/gsd-core/bin/lib/installer-migrations/000-first-time-baseline.cjs +218 -0
  126. package/gsd-core/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +48 -0
  127. package/gsd-core/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +94 -0
  128. package/gsd-core/bin/lib/installer-migrations/003-rename-get-shit-done-to-gsd-core.cjs +108 -0
  129. package/gsd-core/bin/lib/installer-migrations.cjs +784 -0
  130. package/gsd-core/bin/lib/intel.cjs +607 -0
  131. package/gsd-core/bin/lib/learnings.cjs +270 -0
  132. package/gsd-core/bin/lib/legacy-cleanup.cjs +253 -0
  133. package/gsd-core/bin/lib/milestone.cjs +373 -0
  134. package/gsd-core/bin/lib/model-catalog.cjs +154 -0
  135. package/gsd-core/bin/lib/model-profiles.cjs +24 -0
  136. package/gsd-core/bin/lib/observability/event.cjs +51 -0
  137. package/gsd-core/bin/lib/observability/logger.cjs +146 -0
  138. package/{get-shit-done → gsd-core}/bin/lib/observability/redaction.cjs +19 -21
  139. package/{get-shit-done → gsd-core}/bin/lib/package-identity.cjs +5 -1
  140. package/gsd-core/bin/lib/phase-command-router.cjs +189 -0
  141. package/gsd-core/bin/lib/phase-lifecycle.cjs +74 -0
  142. package/gsd-core/bin/lib/phase.cjs +1307 -0
  143. package/gsd-core/bin/lib/phases-command-router.cjs +43 -0
  144. package/{get-shit-done → gsd-core}/bin/lib/plan-scan.cjs +18 -24
  145. package/gsd-core/bin/lib/planning-workspace.cjs +245 -0
  146. package/gsd-core/bin/lib/profile-output.cjs +1120 -0
  147. package/gsd-core/bin/lib/profile-pipeline.cjs +517 -0
  148. package/gsd-core/bin/lib/project-root.cjs +119 -0
  149. package/gsd-core/bin/lib/prompt-budget.cjs +305 -0
  150. package/gsd-core/bin/lib/review-reviewer-selection.cjs +121 -0
  151. package/gsd-core/bin/lib/roadmap-command-router.cjs +166 -0
  152. package/gsd-core/bin/lib/roadmap-upgrade.cjs +491 -0
  153. package/gsd-core/bin/lib/roadmap.cjs +600 -0
  154. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +254 -0
  155. package/gsd-core/bin/lib/runtime-homes.cjs +169 -0
  156. package/gsd-core/bin/lib/runtime-name-policy.cjs +96 -0
  157. package/gsd-core/bin/lib/runtime-slash.cjs +119 -0
  158. package/{get-shit-done → gsd-core}/bin/lib/schema-detect.cjs +20 -26
  159. package/gsd-core/bin/lib/secrets.cjs +34 -0
  160. package/gsd-core/bin/lib/security.cjs +407 -0
  161. package/gsd-core/bin/lib/semver-compare.cjs +42 -0
  162. package/gsd-core/bin/lib/shell-command-projection.cjs +524 -0
  163. package/gsd-core/bin/lib/state-command-router.cjs +160 -0
  164. package/{get-shit-done → gsd-core}/bin/lib/state-document.cjs +78 -82
  165. package/gsd-core/bin/lib/state.cjs +2010 -0
  166. package/gsd-core/bin/lib/surface.cjs +406 -0
  167. package/gsd-core/bin/lib/task-command-router.cjs +85 -0
  168. package/gsd-core/bin/lib/template.cjs +237 -0
  169. package/gsd-core/bin/lib/uat.cjs +297 -0
  170. package/gsd-core/bin/lib/ui-safety-gate.cjs +98 -0
  171. package/gsd-core/bin/lib/update-context.cjs +218 -0
  172. package/gsd-core/bin/lib/validate-command-router.cjs +91 -0
  173. package/gsd-core/bin/lib/validate.cjs +112 -0
  174. package/gsd-core/bin/lib/verify-command-router.cjs +44 -0
  175. package/gsd-core/bin/lib/verify.cjs +1451 -0
  176. package/{get-shit-done → gsd-core}/bin/lib/workstream-inventory-builder.cjs +19 -12
  177. package/gsd-core/bin/lib/workstream-inventory.cjs +147 -0
  178. package/{get-shit-done → gsd-core}/bin/lib/workstream-name-policy.cjs +28 -31
  179. package/gsd-core/bin/lib/workstream.cjs +380 -0
  180. package/gsd-core/bin/lib/worktree-safety.cjs +912 -0
  181. package/{get-shit-done → gsd-core}/bin/shared/config-defaults.manifest.json +1 -0
  182. package/{get-shit-done → gsd-core}/bin/shared/config-schema.manifest.json +17 -1
  183. package/{get-shit-done → gsd-core}/bin/shared/model-catalog.json +27 -0
  184. package/{get-shit-done → gsd-core}/references/artifact-types.md +1 -1
  185. package/{get-shit-done → gsd-core}/references/checkpoints.md +1 -1
  186. package/{get-shit-done → gsd-core}/references/few-shot-examples/plan-checker.md +2 -2
  187. package/{get-shit-done → gsd-core}/references/few-shot-examples/verifier.md +12 -12
  188. package/{get-shit-done → gsd-core}/references/model-profile-resolution.md +1 -1
  189. package/{get-shit-done → gsd-core}/references/mvp-concepts.md +1 -1
  190. package/{get-shit-done → gsd-core}/references/planner-graphify-auto-update.md +2 -2
  191. package/{get-shit-done → gsd-core}/references/planner-human-verify-mode.md +1 -1
  192. package/{get-shit-done → gsd-core}/references/planner-mvp-mode.md +1 -1
  193. package/{get-shit-done → gsd-core}/references/ui-brand.md +4 -2
  194. package/{get-shit-done → gsd-core}/references/verification-patterns.md +1 -1
  195. package/gsd-core/references/worktree-branch-check.md +38 -0
  196. package/{get-shit-done → gsd-core}/references/worktree-path-safety.md +4 -26
  197. package/{get-shit-done → gsd-core}/templates/README.md +2 -2
  198. package/{get-shit-done → gsd-core}/templates/codebase/structure.md +10 -10
  199. package/{get-shit-done → gsd-core}/templates/copilot-instructions.md +1 -1
  200. package/{get-shit-done → gsd-core}/templates/phase-prompt.md +10 -10
  201. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -0
  202. package/{get-shit-done → gsd-core}/workflows/add-backlog.md +1 -1
  203. package/{get-shit-done → gsd-core}/workflows/add-phase.md +1 -1
  204. package/{get-shit-done → gsd-core}/workflows/add-tests.md +1 -1
  205. package/{get-shit-done → gsd-core}/workflows/add-todo.md +1 -1
  206. package/{get-shit-done → gsd-core}/workflows/ai-integration-phase.md +4 -4
  207. package/{get-shit-done → gsd-core}/workflows/audit-fix.md +2 -2
  208. package/{get-shit-done → gsd-core}/workflows/audit-milestone.md +3 -1
  209. package/{get-shit-done → gsd-core}/workflows/audit-uat.md +1 -1
  210. package/{get-shit-done → gsd-core}/workflows/autonomous.md +10 -8
  211. package/{get-shit-done → gsd-core}/workflows/check-todos.md +1 -1
  212. package/{get-shit-done → gsd-core}/workflows/cleanup.md +44 -4
  213. package/{get-shit-done → gsd-core}/workflows/code-review-fix.md +4 -4
  214. package/{get-shit-done → gsd-core}/workflows/code-review.md +6 -4
  215. package/{get-shit-done → gsd-core}/workflows/complete-milestone.md +2 -2
  216. package/{get-shit-done → gsd-core}/workflows/debug.md +7 -2
  217. package/{get-shit-done → gsd-core}/workflows/diagnose-issues.md +6 -2
  218. package/{get-shit-done → gsd-core}/workflows/discovery-phase.md +5 -5
  219. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/advisor.md +5 -5
  220. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/auto.md +1 -1
  221. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/chain.md +1 -1
  222. package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/power.md +1 -1
  223. package/{get-shit-done → gsd-core}/workflows/discuss-phase-assumptions.md +4 -4
  224. package/{get-shit-done → gsd-core}/workflows/discuss-phase.md +6 -6
  225. package/{get-shit-done → gsd-core}/workflows/do.md +1 -1
  226. package/{get-shit-done → gsd-core}/workflows/docs-update.md +19 -5
  227. package/{get-shit-done → gsd-core}/workflows/edit-phase.md +1 -1
  228. package/{get-shit-done → gsd-core}/workflows/eval-review.md +3 -3
  229. package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/codebase-drift-gate.md +16 -3
  230. package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/post-merge-gate.md +1 -1
  231. package/{get-shit-done → gsd-core}/workflows/execute-phase.md +89 -57
  232. package/{get-shit-done → gsd-core}/workflows/execute-plan.md +8 -8
  233. package/{get-shit-done → gsd-core}/workflows/explore.md +5 -3
  234. package/{get-shit-done → gsd-core}/workflows/extract-learnings.md +1 -1
  235. package/{get-shit-done → gsd-core}/workflows/forensics.md +1 -1
  236. package/{get-shit-done → gsd-core}/workflows/graduation.md +1 -1
  237. package/{get-shit-done → gsd-core}/workflows/health.md +1 -1
  238. package/{get-shit-done → gsd-core}/workflows/help/modes/default.md +3 -3
  239. package/{get-shit-done → gsd-core}/workflows/help/modes/full.md +6 -6
  240. package/{get-shit-done → gsd-core}/workflows/import.md +3 -1
  241. package/{get-shit-done → gsd-core}/workflows/ingest-docs.md +5 -5
  242. package/{get-shit-done → gsd-core}/workflows/insert-phase.md +1 -1
  243. package/{get-shit-done → gsd-core}/workflows/list-workspaces.md +1 -1
  244. package/{get-shit-done → gsd-core}/workflows/manager.md +3 -3
  245. package/{get-shit-done → gsd-core}/workflows/map-codebase.md +3 -1
  246. package/{get-shit-done → gsd-core}/workflows/milestone-summary.md +1 -1
  247. package/{get-shit-done → gsd-core}/workflows/mvp-phase.md +7 -7
  248. package/{get-shit-done → gsd-core}/workflows/new-milestone.md +5 -5
  249. package/{get-shit-done → gsd-core}/workflows/new-project.md +8 -8
  250. package/{get-shit-done → gsd-core}/workflows/new-workspace.md +1 -1
  251. package/{get-shit-done → gsd-core}/workflows/next.md +1 -1
  252. package/{get-shit-done → gsd-core}/workflows/pause-work.md +1 -1
  253. package/{get-shit-done → gsd-core}/workflows/plan-milestone-gaps.md +1 -1
  254. package/{get-shit-done → gsd-core}/workflows/plan-phase.md +29 -28
  255. package/{get-shit-done → gsd-core}/workflows/plan-review-convergence.md +10 -10
  256. package/{get-shit-done → gsd-core}/workflows/plant-seed.md +1 -1
  257. package/{get-shit-done → gsd-core}/workflows/profile-user.md +11 -11
  258. package/{get-shit-done → gsd-core}/workflows/progress.md +1 -1
  259. package/{get-shit-done → gsd-core}/workflows/quick.md +7 -29
  260. package/{get-shit-done → gsd-core}/workflows/reapply-patches.md +2 -2
  261. package/{get-shit-done → gsd-core}/workflows/remove-phase.md +1 -1
  262. package/{get-shit-done → gsd-core}/workflows/remove-workspace.md +1 -1
  263. package/{get-shit-done → gsd-core}/workflows/resume-project.md +2 -2
  264. package/{get-shit-done → gsd-core}/workflows/review.md +110 -2
  265. package/{get-shit-done → gsd-core}/workflows/scan.md +3 -1
  266. package/{get-shit-done → gsd-core}/workflows/secure-phase.md +5 -3
  267. package/{get-shit-done → gsd-core}/workflows/settings-advanced.md +196 -6
  268. package/{get-shit-done → gsd-core}/workflows/settings-integrations.md +2 -2
  269. package/{get-shit-done → gsd-core}/workflows/settings.md +16 -2
  270. package/{get-shit-done → gsd-core}/workflows/ship.md +56 -4
  271. package/{get-shit-done → gsd-core}/workflows/sketch-wrap-up.md +1 -1
  272. package/{get-shit-done → gsd-core}/workflows/sketch.md +5 -5
  273. package/{get-shit-done → gsd-core}/workflows/spec-phase.md +2 -2
  274. package/{get-shit-done → gsd-core}/workflows/spike-wrap-up.md +1 -1
  275. package/{get-shit-done → gsd-core}/workflows/spike.md +1 -1
  276. package/{get-shit-done → gsd-core}/workflows/stats.md +1 -1
  277. package/{get-shit-done → gsd-core}/workflows/sync-skills.md +3 -3
  278. package/{get-shit-done → gsd-core}/workflows/thread.md +1 -1
  279. package/{get-shit-done → gsd-core}/workflows/transition.md +2 -2
  280. package/{get-shit-done → gsd-core}/workflows/ui-phase.md +5 -5
  281. package/{get-shit-done → gsd-core}/workflows/ui-review.md +3 -3
  282. package/{get-shit-done → gsd-core}/workflows/ultraplan-phase.md +1 -1
  283. package/{get-shit-done → gsd-core}/workflows/undo.md +2 -2
  284. package/{get-shit-done → gsd-core}/workflows/update.md +41 -16
  285. package/{get-shit-done → gsd-core}/workflows/validate-phase.md +5 -3
  286. package/{get-shit-done → gsd-core}/workflows/verify-phase.md +4 -4
  287. package/{get-shit-done → gsd-core}/workflows/verify-work.md +7 -7
  288. package/hooks/dist/gsd-check-update-worker.js +16 -3
  289. package/hooks/dist/gsd-check-update.js +7 -5
  290. package/hooks/dist/gsd-context-monitor.js +2 -2
  291. package/hooks/dist/gsd-statusline.js +39 -21
  292. package/hooks/dist/gsd-update-banner.js +6 -2
  293. package/hooks/dist/gsd-worktree-path-guard.js +169 -0
  294. package/hooks/dist/managed-hooks-registry.cjs +35 -0
  295. package/hooks/gsd-check-update-worker.js +16 -3
  296. package/hooks/gsd-check-update.js +7 -5
  297. package/hooks/gsd-context-monitor.js +2 -2
  298. package/hooks/gsd-statusline.js +39 -21
  299. package/hooks/gsd-update-banner.js +6 -2
  300. package/hooks/gsd-worktree-path-guard.js +169 -0
  301. package/hooks/managed-hooks-registry.cjs +1 -0
  302. package/package.json +17 -11
  303. package/scripts/affected-tests-lib.cjs +1 -1
  304. package/scripts/base64-scan.sh +12 -0
  305. package/scripts/build-hooks.js +5 -1
  306. package/scripts/changeset/cli.cjs +2 -2
  307. package/scripts/changeset/github-release-notes.cjs +1 -1
  308. package/scripts/changeset/lint.cjs +1 -1
  309. package/scripts/check-alias-drift.cjs +8 -8
  310. package/scripts/check-env.cjs +5 -1
  311. package/scripts/ci-test-scope.cjs +34 -9
  312. package/scripts/command-contract-helpers.cjs +1 -1
  313. package/scripts/fix-slash-commands.cjs +5 -5
  314. package/scripts/gen-inventory-manifest.cjs +3 -3
  315. package/scripts/generate-package-identity.cjs +28 -7
  316. package/scripts/lib/allowlist-ratchet.cjs +136 -0
  317. package/scripts/lint-command-contract.cjs +1 -1
  318. package/scripts/lint-legacy-dir-name.cjs +156 -0
  319. package/scripts/lint-package-identity-drift.cjs +8 -8
  320. package/scripts/lint-pr-check-project-dir.cjs +0 -1
  321. package/scripts/lint-shell-command-projection-drift.cjs +1 -1
  322. package/scripts/lint-skill-deps.cjs +1 -1
  323. package/scripts/lint-test-file-count.allowlist.json +129 -32
  324. package/scripts/lint-test-file-count.cjs +85 -30
  325. package/scripts/mutation-matrix.cjs +219 -0
  326. package/scripts/prompt-injection-scan.sh +5 -1
  327. package/scripts/release-notes/format-github-release-notes.cjs +256 -0
  328. package/scripts/release-tarball-smoke.cjs +9 -9
  329. package/scripts/run-tests.cjs +34 -2
  330. package/scripts/strip-prose-atrefs.cjs +2 -2
  331. package/scripts/sync-runtime-launcher.cjs +2 -2
  332. package/scripts/verify-npm-publish.cjs +252 -0
  333. package/get-shit-done/bin/lib/active-workstream-store.cjs +0 -302
  334. package/get-shit-done/bin/lib/adr-parser.cjs +0 -394
  335. package/get-shit-done/bin/lib/agent-command-router.cjs +0 -65
  336. package/get-shit-done/bin/lib/artifacts.cjs +0 -53
  337. package/get-shit-done/bin/lib/audit.cjs +0 -755
  338. package/get-shit-done/bin/lib/check-command-router.cjs +0 -333
  339. package/get-shit-done/bin/lib/cjs-command-router-adapter.cjs +0 -118
  340. package/get-shit-done/bin/lib/clock.cjs +0 -96
  341. package/get-shit-done/bin/lib/clusters.cjs +0 -135
  342. package/get-shit-done/bin/lib/code-review-flags.cjs +0 -74
  343. package/get-shit-done/bin/lib/command-aliases.cjs +0 -815
  344. package/get-shit-done/bin/lib/command-arg-projection.cjs +0 -62
  345. package/get-shit-done/bin/lib/command-routing-hub.cjs +0 -388
  346. package/get-shit-done/bin/lib/commands.cjs +0 -1188
  347. package/get-shit-done/bin/lib/config-schema.cjs +0 -31
  348. package/get-shit-done/bin/lib/config.cjs +0 -728
  349. package/get-shit-done/bin/lib/context-utilization.cjs +0 -47
  350. package/get-shit-done/bin/lib/core.cjs +0 -2121
  351. package/get-shit-done/bin/lib/docs.cjs +0 -270
  352. package/get-shit-done/bin/lib/drift.cjs +0 -388
  353. package/get-shit-done/bin/lib/fallow-runner.cjs +0 -109
  354. package/get-shit-done/bin/lib/frontmatter.cjs +0 -389
  355. package/get-shit-done/bin/lib/gap-checker.cjs +0 -205
  356. package/get-shit-done/bin/lib/graphify.cjs +0 -592
  357. package/get-shit-done/bin/lib/gsd2-import.cjs +0 -514
  358. package/get-shit-done/bin/lib/init-command-router.cjs +0 -58
  359. package/get-shit-done/bin/lib/init.cjs +0 -2112
  360. package/get-shit-done/bin/lib/install-profiles.cjs +0 -603
  361. package/get-shit-done/bin/lib/installer-migration-authoring.cjs +0 -117
  362. package/get-shit-done/bin/lib/installer-migration-report.cjs +0 -354
  363. package/get-shit-done/bin/lib/installer-migrations/000-first-time-baseline.cjs +0 -220
  364. package/get-shit-done/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +0 -41
  365. package/get-shit-done/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +0 -80
  366. package/get-shit-done/bin/lib/installer-migrations.cjs +0 -778
  367. package/get-shit-done/bin/lib/intel.cjs +0 -708
  368. package/get-shit-done/bin/lib/learnings.cjs +0 -421
  369. package/get-shit-done/bin/lib/milestone.cjs +0 -314
  370. package/get-shit-done/bin/lib/model-catalog.cjs +0 -212
  371. package/get-shit-done/bin/lib/model-profiles.cjs +0 -31
  372. package/get-shit-done/bin/lib/observability/event.cjs +0 -82
  373. package/get-shit-done/bin/lib/observability/logger.cjs +0 -174
  374. package/get-shit-done/bin/lib/phase-command-router.cjs +0 -191
  375. package/get-shit-done/bin/lib/phase-lifecycle.cjs +0 -80
  376. package/get-shit-done/bin/lib/phase.cjs +0 -1607
  377. package/get-shit-done/bin/lib/phases-command-router.cjs +0 -39
  378. package/get-shit-done/bin/lib/planning-workspace.cjs +0 -238
  379. package/get-shit-done/bin/lib/profile-output.cjs +0 -1141
  380. package/get-shit-done/bin/lib/profile-pipeline.cjs +0 -539
  381. package/get-shit-done/bin/lib/project-root.cjs +0 -112
  382. package/get-shit-done/bin/lib/prompt-budget.cjs +0 -399
  383. package/get-shit-done/bin/lib/review-reviewer-selection.cjs +0 -125
  384. package/get-shit-done/bin/lib/roadmap-command-router.cjs +0 -28
  385. package/get-shit-done/bin/lib/roadmap.cjs +0 -650
  386. package/get-shit-done/bin/lib/runtime-artifact-layout.cjs +0 -301
  387. package/get-shit-done/bin/lib/runtime-homes.cjs +0 -222
  388. package/get-shit-done/bin/lib/runtime-name-policy.cjs +0 -83
  389. package/get-shit-done/bin/lib/runtime-slash.cjs +0 -112
  390. package/get-shit-done/bin/lib/secrets.cjs +0 -32
  391. package/get-shit-done/bin/lib/security.cjs +0 -600
  392. package/get-shit-done/bin/lib/semver-compare.cjs +0 -35
  393. package/get-shit-done/bin/lib/shell-command-projection.cjs +0 -500
  394. package/get-shit-done/bin/lib/state-command-router.cjs +0 -252
  395. package/get-shit-done/bin/lib/state.cjs +0 -2038
  396. package/get-shit-done/bin/lib/surface.cjs +0 -470
  397. package/get-shit-done/bin/lib/task-command-router.cjs +0 -81
  398. package/get-shit-done/bin/lib/template.cjs +0 -228
  399. package/get-shit-done/bin/lib/uat.cjs +0 -289
  400. package/get-shit-done/bin/lib/update-context.cjs +0 -209
  401. package/get-shit-done/bin/lib/validate-command-router.cjs +0 -83
  402. package/get-shit-done/bin/lib/validate.cjs +0 -92
  403. package/get-shit-done/bin/lib/verify-command-router.cjs +0 -40
  404. package/get-shit-done/bin/lib/verify.cjs +0 -1511
  405. package/get-shit-done/bin/lib/workstream-inventory.cjs +0 -146
  406. package/get-shit-done/bin/lib/workstream.cjs +0 -389
  407. package/get-shit-done/bin/lib/worktree-safety.cjs +0 -985
  408. package/get-shit-done/workflows/_runtime-launcher.snippet.sh +0 -1
  409. package/scripts/lint-no-source-grep-extras.cjs +0 -81
  410. package/scripts/lint-no-source-grep.cjs +0 -174
  411. package/scripts/lint-shared-module-handsync.cjs +0 -388
  412. package/scripts/shared-module-handsync-allowlist.json +0 -183
  413. /package/{get-shit-done → gsd-core}/bin/shared/runtime-aliases.manifest.json +0 -0
  414. /package/{get-shit-done → gsd-core}/bin/verify-reapply-patches.cjs +0 -0
  415. /package/{get-shit-done → gsd-core}/contexts/dev.md +0 -0
  416. /package/{get-shit-done → gsd-core}/contexts/research.md +0 -0
  417. /package/{get-shit-done → gsd-core}/contexts/review.md +0 -0
  418. /package/{get-shit-done → gsd-core}/references/agent-contracts.md +0 -0
  419. /package/{get-shit-done → gsd-core}/references/ai-evals.md +0 -0
  420. /package/{get-shit-done → gsd-core}/references/ai-frameworks.md +0 -0
  421. /package/{get-shit-done → gsd-core}/references/autonomous-smart-discuss.md +0 -0
  422. /package/{get-shit-done → gsd-core}/references/common-bug-patterns.md +0 -0
  423. /package/{get-shit-done → gsd-core}/references/context-budget.md +0 -0
  424. /package/{get-shit-done → gsd-core}/references/continuation-format.md +0 -0
  425. /package/{get-shit-done → gsd-core}/references/debugger-philosophy.md +0 -0
  426. /package/{get-shit-done → gsd-core}/references/decimal-phase-calculation.md +0 -0
  427. /package/{get-shit-done → gsd-core}/references/doc-conflict-engine.md +0 -0
  428. /package/{get-shit-done → gsd-core}/references/domain-probes.md +0 -0
  429. /package/{get-shit-done → gsd-core}/references/execute-mvp-tdd.md +0 -0
  430. /package/{get-shit-done → gsd-core}/references/executor-examples.md +0 -0
  431. /package/{get-shit-done → gsd-core}/references/gate-prompts.md +0 -0
  432. /package/{get-shit-done → gsd-core}/references/gates.md +0 -0
  433. /package/{get-shit-done → gsd-core}/references/git-integration.md +0 -0
  434. /package/{get-shit-done → gsd-core}/references/git-planning-commit.md +0 -0
  435. /package/{get-shit-done → gsd-core}/references/ios-scaffold.md +0 -0
  436. /package/{get-shit-done → gsd-core}/references/mandatory-initial-read.md +0 -0
  437. /package/{get-shit-done → gsd-core}/references/model-profiles.md +0 -0
  438. /package/{get-shit-done → gsd-core}/references/phase-argument-parsing.md +0 -0
  439. /package/{get-shit-done → gsd-core}/references/planner-antipatterns.md +0 -0
  440. /package/{get-shit-done → gsd-core}/references/planner-chunked.md +0 -0
  441. /package/{get-shit-done → gsd-core}/references/planner-gap-closure.md +0 -0
  442. /package/{get-shit-done → gsd-core}/references/planner-interface-context.md +0 -0
  443. /package/{get-shit-done → gsd-core}/references/planner-reviews.md +0 -0
  444. /package/{get-shit-done → gsd-core}/references/planner-revision.md +0 -0
  445. /package/{get-shit-done → gsd-core}/references/planner-source-audit.md +0 -0
  446. /package/{get-shit-done → gsd-core}/references/planning-config.md +0 -0
  447. /package/{get-shit-done → gsd-core}/references/project-skills-discovery.md +0 -0
  448. /package/{get-shit-done → gsd-core}/references/questioning.md +0 -0
  449. /package/{get-shit-done → gsd-core}/references/revision-loop.md +0 -0
  450. /package/{get-shit-done → gsd-core}/references/scout-codebase.md +0 -0
  451. /package/{get-shit-done → gsd-core}/references/skeleton-template.md +0 -0
  452. /package/{get-shit-done → gsd-core}/references/sketch-interactivity.md +0 -0
  453. /package/{get-shit-done → gsd-core}/references/sketch-theme-system.md +0 -0
  454. /package/{get-shit-done → gsd-core}/references/sketch-tooling.md +0 -0
  455. /package/{get-shit-done → gsd-core}/references/sketch-variant-patterns.md +0 -0
  456. /package/{get-shit-done → gsd-core}/references/spidr-splitting.md +0 -0
  457. /package/{get-shit-done → gsd-core}/references/tdd.md +0 -0
  458. /package/{get-shit-done → gsd-core}/references/thinking-models-debug.md +0 -0
  459. /package/{get-shit-done → gsd-core}/references/thinking-models-execution.md +0 -0
  460. /package/{get-shit-done → gsd-core}/references/thinking-models-planning.md +0 -0
  461. /package/{get-shit-done → gsd-core}/references/thinking-models-research.md +0 -0
  462. /package/{get-shit-done → gsd-core}/references/thinking-models-verification.md +0 -0
  463. /package/{get-shit-done → gsd-core}/references/thinking-partner.md +0 -0
  464. /package/{get-shit-done → gsd-core}/references/universal-anti-patterns.md +0 -0
  465. /package/{get-shit-done → gsd-core}/references/user-profiling.md +0 -0
  466. /package/{get-shit-done → gsd-core}/references/user-story-template.md +0 -0
  467. /package/{get-shit-done → gsd-core}/references/verification-overrides.md +0 -0
  468. /package/{get-shit-done → gsd-core}/references/verify-mvp-mode.md +0 -0
  469. /package/{get-shit-done → gsd-core}/references/workstream-flag.md +0 -0
  470. /package/{get-shit-done → gsd-core}/templates/AI-SPEC.md +0 -0
  471. /package/{get-shit-done → gsd-core}/templates/DEBUG.md +0 -0
  472. /package/{get-shit-done → gsd-core}/templates/SECURITY.md +0 -0
  473. /package/{get-shit-done → gsd-core}/templates/UAT.md +0 -0
  474. /package/{get-shit-done → gsd-core}/templates/UI-SPEC.md +0 -0
  475. /package/{get-shit-done → gsd-core}/templates/VALIDATION.md +0 -0
  476. /package/{get-shit-done → gsd-core}/templates/claude-md.md +0 -0
  477. /package/{get-shit-done → gsd-core}/templates/codebase/architecture.md +0 -0
  478. /package/{get-shit-done → gsd-core}/templates/codebase/concerns.md +0 -0
  479. /package/{get-shit-done → gsd-core}/templates/codebase/conventions.md +0 -0
  480. /package/{get-shit-done → gsd-core}/templates/codebase/integrations.md +0 -0
  481. /package/{get-shit-done → gsd-core}/templates/codebase/stack.md +0 -0
  482. /package/{get-shit-done → gsd-core}/templates/codebase/testing.md +0 -0
  483. /package/{get-shit-done → gsd-core}/templates/config.json +0 -0
  484. /package/{get-shit-done → gsd-core}/templates/context.md +0 -0
  485. /package/{get-shit-done → gsd-core}/templates/continue-here.md +0 -0
  486. /package/{get-shit-done → gsd-core}/templates/debug-subagent-prompt.md +0 -0
  487. /package/{get-shit-done → gsd-core}/templates/dev-preferences.md +0 -0
  488. /package/{get-shit-done → gsd-core}/templates/discovery.md +0 -0
  489. /package/{get-shit-done → gsd-core}/templates/discussion-log.md +0 -0
  490. /package/{get-shit-done → gsd-core}/templates/milestone-archive.md +0 -0
  491. /package/{get-shit-done → gsd-core}/templates/milestone.md +0 -0
  492. /package/{get-shit-done → gsd-core}/templates/planner-subagent-prompt.md +0 -0
  493. /package/{get-shit-done → gsd-core}/templates/project.md +0 -0
  494. /package/{get-shit-done → gsd-core}/templates/requirements.md +0 -0
  495. /package/{get-shit-done → gsd-core}/templates/research-project/ARCHITECTURE.md +0 -0
  496. /package/{get-shit-done → gsd-core}/templates/research-project/FEATURES.md +0 -0
  497. /package/{get-shit-done → gsd-core}/templates/research-project/PITFALLS.md +0 -0
  498. /package/{get-shit-done → gsd-core}/templates/research-project/STACK.md +0 -0
  499. /package/{get-shit-done → gsd-core}/templates/research-project/SUMMARY.md +0 -0
  500. /package/{get-shit-done → gsd-core}/templates/research.md +0 -0
  501. /package/{get-shit-done → gsd-core}/templates/retrospective.md +0 -0
  502. /package/{get-shit-done → gsd-core}/templates/roadmap.md +0 -0
  503. /package/{get-shit-done → gsd-core}/templates/spec.md +0 -0
  504. /package/{get-shit-done → gsd-core}/templates/state.md +0 -0
  505. /package/{get-shit-done → gsd-core}/templates/summary-complex.md +0 -0
  506. /package/{get-shit-done → gsd-core}/templates/summary-minimal.md +0 -0
  507. /package/{get-shit-done → gsd-core}/templates/summary-standard.md +0 -0
  508. /package/{get-shit-done → gsd-core}/templates/summary.md +0 -0
  509. /package/{get-shit-done → gsd-core}/templates/user-profile.md +0 -0
  510. /package/{get-shit-done → gsd-core}/templates/user-setup.md +0 -0
  511. /package/{get-shit-done → gsd-core}/templates/verification-report.md +0 -0
  512. /package/{get-shit-done → gsd-core}/workflows/analyze-dependencies.md +0 -0
  513. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/all.md +0 -0
  514. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/analyze.md +0 -0
  515. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/batch.md +0 -0
  516. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/default.md +0 -0
  517. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/modes/text.md +0 -0
  518. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/checkpoint.json +0 -0
  519. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/context.md +0 -0
  520. /package/{get-shit-done → gsd-core}/workflows/discuss-phase/templates/discussion-log.md +0 -0
  521. /package/{get-shit-done → gsd-core}/workflows/discuss-phase-power.md +0 -0
  522. /package/{get-shit-done → gsd-core}/workflows/execute-phase/steps/per-plan-worktree-gate.md +0 -0
  523. /package/{get-shit-done → gsd-core}/workflows/fast.md +0 -0
  524. /package/{get-shit-done → gsd-core}/workflows/help/modes/brief.md +0 -0
  525. /package/{get-shit-done → gsd-core}/workflows/help/modes/topic.md +0 -0
  526. /package/{get-shit-done → gsd-core}/workflows/help.md +0 -0
  527. /package/{get-shit-done → gsd-core}/workflows/inbox.md +0 -0
  528. /package/{get-shit-done → gsd-core}/workflows/list-phase-assumptions.md +0 -0
  529. /package/{get-shit-done → gsd-core}/workflows/node-repair.md +0 -0
  530. /package/{get-shit-done → gsd-core}/workflows/note.md +0 -0
  531. /package/{get-shit-done → gsd-core}/workflows/pr-branch.md +0 -0
  532. /package/{get-shit-done → gsd-core}/workflows/session-report.md +0 -0
@@ -1,755 +0,0 @@
1
- /**
2
- * Open Artifact Audit — Cross-type unresolved state scanner
3
- *
4
- * Scans all .planning/ artifact categories for items with open/unresolved state.
5
- * Returns structured JSON for workflow consumption.
6
- * Called by: gsd-tools.cjs audit-open
7
- * Used by: /gsd:complete-milestone pre-close gate
8
- */
9
-
10
- 'use strict';
11
-
12
- const fs = require('fs');
13
- const path = require('path');
14
- const { toPosixPath } = require('./core.cjs');
15
- const { platformReadSync } = require('./shell-command-projection.cjs');
16
- const { planningDir } = require('./planning-workspace.cjs');
17
- const { extractFrontmatter } = require('./frontmatter.cjs');
18
- const { requireSafePath, sanitizeForDisplay } = require('./security.cjs');
19
-
20
- /**
21
- * Scan .planning/debug/ for open sessions.
22
- * Open = status NOT in ['resolved', 'complete'].
23
- * Ignores the resolved/ subdirectory.
24
- */
25
- function scanDebugSessions(planDir) {
26
- const debugDir = path.join(planDir, 'debug');
27
- if (!fs.existsSync(debugDir)) return [];
28
-
29
- const results = [];
30
- let files;
31
- try {
32
- files = fs.readdirSync(debugDir, { withFileTypes: true });
33
- } catch {
34
- return [{ scan_error: true }];
35
- }
36
-
37
- for (const entry of files) {
38
- if (!entry.isFile()) continue;
39
- if (!entry.name.endsWith('.md')) continue;
40
-
41
- const filePath = path.join(debugDir, entry.name);
42
-
43
- let safeFilePath;
44
- try {
45
- safeFilePath = requireSafePath(filePath, planDir, 'debug session file', { allowAbsolute: true });
46
- } catch {
47
- continue;
48
- }
49
-
50
- const content = platformReadSync(safeFilePath);
51
- if (content === null) continue;
52
-
53
- const fm = extractFrontmatter(content);
54
- const status = (fm.status || 'unknown').toLowerCase();
55
- if (status === 'resolved' || status === 'complete') continue;
56
-
57
- // Extract hypothesis from "Current Focus" block if parseable
58
- let hypothesis = '';
59
- const focusMatch = content.match(/##\s*Current Focus[^\n]*\n([\s\S]*?)(?=\n##\s|$)/i);
60
- if (focusMatch) {
61
- const focusText = focusMatch[1].trim().split('\n')[0].trim();
62
- hypothesis = sanitizeForDisplay(focusText.slice(0, 100));
63
- }
64
-
65
- const slug = path.basename(entry.name, '.md');
66
- results.push({
67
- slug: sanitizeForDisplay(slug),
68
- status: sanitizeForDisplay(status),
69
- updated: sanitizeForDisplay(String(fm.updated || fm.date || '')),
70
- hypothesis,
71
- });
72
- }
73
-
74
- return results;
75
- }
76
-
77
- /**
78
- * Scan .planning/quick/ for incomplete tasks.
79
- * Incomplete if SUMMARY.md missing or status !== 'complete'.
80
- */
81
- function scanQuickTasks(planDir) {
82
- const quickDir = path.join(planDir, 'quick');
83
- if (!fs.existsSync(quickDir)) return [];
84
-
85
- let entries;
86
- try {
87
- entries = fs.readdirSync(quickDir, { withFileTypes: true });
88
- } catch {
89
- return [{ scan_error: true }];
90
- }
91
-
92
- const results = [];
93
- for (const entry of entries) {
94
- if (!entry.isDirectory()) continue;
95
-
96
- const dirName = entry.name;
97
- const taskDir = path.join(quickDir, dirName);
98
-
99
- let safeTaskDir;
100
- try {
101
- safeTaskDir = requireSafePath(taskDir, planDir, 'quick task dir', { allowAbsolute: true });
102
- } catch {
103
- continue;
104
- }
105
-
106
- // workflows/quick.md mandates `${quick_id}-SUMMARY.md`; older flows used
107
- // bare `SUMMARY.md`. Accept either to avoid false-positive "missing".
108
- let summaryPath = null;
109
- try {
110
- const summaryFiles = fs.readdirSync(safeTaskDir, { withFileTypes: true })
111
- .filter(e => e.isFile() && (e.name === 'SUMMARY.md' || e.name.endsWith('-SUMMARY.md')));
112
- if (summaryFiles.length > 0) {
113
- // Prefer the per-task `${quick_id}-SUMMARY.md` form when present.
114
- const preferred = summaryFiles.find(e => e.name === `${dirName}-SUMMARY.md`)
115
- || summaryFiles.find(e => e.name.endsWith('-SUMMARY.md'))
116
- || summaryFiles[0];
117
- summaryPath = path.join(safeTaskDir, preferred.name);
118
- }
119
- } catch {
120
- // fall through with summaryPath = null → status: missing
121
- }
122
-
123
- let status = 'missing';
124
- const description = '';
125
-
126
- if (summaryPath && fs.existsSync(summaryPath)) {
127
- let safeSum;
128
- try {
129
- safeSum = requireSafePath(summaryPath, planDir, 'quick task summary', { allowAbsolute: true });
130
- } catch {
131
- continue;
132
- }
133
- const content = platformReadSync(safeSum);
134
- if (content === null) {
135
- status = 'unreadable';
136
- } else {
137
- const fm = extractFrontmatter(content);
138
- status = (fm.status || 'unknown').toLowerCase();
139
- }
140
- }
141
-
142
- if (status === 'complete') continue;
143
-
144
- // Parse date and slug from directory name: YYYYMMDD-slug or YYYY-MM-DD-slug
145
- let date = '';
146
- let slug = sanitizeForDisplay(dirName);
147
- const dateMatch = dirName.match(/^(\d{4}-?\d{2}-?\d{2})-(.+)$/);
148
- if (dateMatch) {
149
- date = dateMatch[1];
150
- slug = sanitizeForDisplay(dateMatch[2]);
151
- }
152
-
153
- results.push({
154
- slug,
155
- date,
156
- status: sanitizeForDisplay(status),
157
- description,
158
- });
159
- }
160
-
161
- return results;
162
- }
163
-
164
- /**
165
- * Scan .planning/threads/ for open threads.
166
- * Open if status in ['open', 'in_progress', 'in progress'] (case-insensitive).
167
- */
168
- function scanThreads(planDir) {
169
- const threadsDir = path.join(planDir, 'threads');
170
- if (!fs.existsSync(threadsDir)) return [];
171
-
172
- let files;
173
- try {
174
- files = fs.readdirSync(threadsDir, { withFileTypes: true });
175
- } catch {
176
- return [{ scan_error: true }];
177
- }
178
-
179
- const openStatuses = new Set(['open', 'in_progress', 'in progress']);
180
- const results = [];
181
-
182
- for (const entry of files) {
183
- if (!entry.isFile()) continue;
184
- if (!entry.name.endsWith('.md')) continue;
185
-
186
- const filePath = path.join(threadsDir, entry.name);
187
-
188
- let safeFilePath;
189
- try {
190
- safeFilePath = requireSafePath(filePath, planDir, 'thread file', { allowAbsolute: true });
191
- } catch {
192
- continue;
193
- }
194
-
195
- const content = platformReadSync(safeFilePath);
196
- if (content === null) continue;
197
-
198
- const fm = extractFrontmatter(content);
199
- let status = (fm.status || '').toLowerCase().trim();
200
-
201
- // Fall back to scanning body for ## Status: OPEN / IN PROGRESS
202
- if (!status) {
203
- const bodyStatusMatch = content.match(/##\s*Status:\s*(OPEN|IN PROGRESS|IN_PROGRESS)/i);
204
- if (bodyStatusMatch) {
205
- status = bodyStatusMatch[1].toLowerCase().replace(/ /g, '_');
206
- }
207
- }
208
-
209
- if (!openStatuses.has(status)) continue;
210
-
211
- // Extract title from # Thread: heading or frontmatter title
212
- let title = sanitizeForDisplay(String(fm.title || ''));
213
- if (!title) {
214
- const headingMatch = content.match(/^#\s*Thread:\s*(.+)$/m);
215
- if (headingMatch) {
216
- title = sanitizeForDisplay(headingMatch[1].trim().slice(0, 100));
217
- }
218
- }
219
-
220
- const slug = path.basename(entry.name, '.md');
221
- results.push({
222
- slug: sanitizeForDisplay(slug),
223
- status: sanitizeForDisplay(status),
224
- updated: sanitizeForDisplay(String(fm.updated || fm.date || '')),
225
- title,
226
- });
227
- }
228
-
229
- return results;
230
- }
231
-
232
- /**
233
- * Scan .planning/todos/pending/ for pending todos.
234
- * Returns array of { filename, priority, area, summary }.
235
- * Display limited to first 5 + count of remainder.
236
- */
237
- function scanTodos(planDir) {
238
- const pendingDir = path.join(planDir, 'todos', 'pending');
239
- if (!fs.existsSync(pendingDir)) return [];
240
-
241
- let files;
242
- try {
243
- files = fs.readdirSync(pendingDir, { withFileTypes: true });
244
- } catch {
245
- return [{ scan_error: true }];
246
- }
247
-
248
- const mdFiles = files.filter(e => e.isFile() && e.name.endsWith('.md'));
249
- const results = [];
250
-
251
- const displayFiles = mdFiles.slice(0, 5);
252
- for (const entry of displayFiles) {
253
- const filePath = path.join(pendingDir, entry.name);
254
-
255
- let safeFilePath;
256
- try {
257
- safeFilePath = requireSafePath(filePath, planDir, 'todo file', { allowAbsolute: true });
258
- } catch {
259
- continue;
260
- }
261
-
262
- const content = platformReadSync(safeFilePath);
263
- if (content === null) continue;
264
-
265
- const fm = extractFrontmatter(content);
266
-
267
- // Extract first line of body after frontmatter
268
- const bodyMatch = content.replace(/^---[\s\S]*?---\n?/, '');
269
- const firstLine = bodyMatch.trim().split('\n')[0] || '';
270
- const summary = sanitizeForDisplay(firstLine.slice(0, 100));
271
-
272
- results.push({
273
- filename: sanitizeForDisplay(entry.name),
274
- priority: sanitizeForDisplay(String(fm.priority || '')),
275
- area: sanitizeForDisplay(String(fm.area || '')),
276
- summary,
277
- });
278
- }
279
-
280
- if (mdFiles.length > 5) {
281
- results.push({ _remainder_count: mdFiles.length - 5 });
282
- }
283
-
284
- return results;
285
- }
286
-
287
- /**
288
- * Scan .planning/seeds/SEED-*.md for unimplemented seeds.
289
- * Unimplemented if status in ['dormant', 'active', 'triggered'].
290
- */
291
- function scanSeeds(planDir) {
292
- const seedsDir = path.join(planDir, 'seeds');
293
- if (!fs.existsSync(seedsDir)) return [];
294
-
295
- let files;
296
- try {
297
- files = fs.readdirSync(seedsDir, { withFileTypes: true });
298
- } catch {
299
- return [{ scan_error: true }];
300
- }
301
-
302
- const unimplementedStatuses = new Set(['dormant', 'active', 'triggered']);
303
- const results = [];
304
-
305
- for (const entry of files) {
306
- if (!entry.isFile()) continue;
307
- if (!entry.name.startsWith('SEED-') || !entry.name.endsWith('.md')) continue;
308
-
309
- const filePath = path.join(seedsDir, entry.name);
310
-
311
- let safeFilePath;
312
- try {
313
- safeFilePath = requireSafePath(filePath, planDir, 'seed file', { allowAbsolute: true });
314
- } catch {
315
- continue;
316
- }
317
-
318
- const content = platformReadSync(safeFilePath);
319
- if (content === null) continue;
320
-
321
- const fm = extractFrontmatter(content);
322
- const status = (fm.status || 'dormant').toLowerCase();
323
-
324
- if (!unimplementedStatuses.has(status)) continue;
325
-
326
- // Extract seed_id from filename or frontmatter
327
- const seedIdMatch = entry.name.match(/^(SEED-[\w-]+)\.md$/);
328
- const seed_id = seedIdMatch ? seedIdMatch[1] : path.basename(entry.name, '.md');
329
- const slug = sanitizeForDisplay(seed_id.replace(/^SEED-/, ''));
330
-
331
- let title = sanitizeForDisplay(String(fm.title || ''));
332
- if (!title) {
333
- const headingMatch = content.match(/^#\s*(.+)$/m);
334
- if (headingMatch) title = sanitizeForDisplay(headingMatch[1].trim().slice(0, 100));
335
- }
336
-
337
- results.push({
338
- seed_id: sanitizeForDisplay(seed_id),
339
- slug,
340
- status: sanitizeForDisplay(status),
341
- title,
342
- });
343
- }
344
-
345
- return results;
346
- }
347
-
348
- // Terminal UAT states: `complete` (legacy) and `resolved` (post-gap-closure
349
- // per workflows/execute-phase.md). Hoisted outside scanUatGaps so the Set is
350
- // not recreated on each loop iteration.
351
- const TERMINAL_UAT_STATUSES = new Set(['complete', 'resolved']);
352
-
353
- /**
354
- * Scan .planning/phases for UAT gaps (UAT files with status != 'complete').
355
- */
356
- function scanUatGaps(planDir) {
357
- const phasesDir = path.join(planDir, 'phases');
358
- if (!fs.existsSync(phasesDir)) return [];
359
-
360
- let dirs;
361
- try {
362
- dirs = fs.readdirSync(phasesDir, { withFileTypes: true })
363
- .filter(e => e.isDirectory())
364
- .map(e => e.name)
365
- .sort();
366
- } catch {
367
- return [{ scan_error: true }];
368
- }
369
-
370
- const results = [];
371
-
372
- for (const dir of dirs) {
373
- const phaseDir = path.join(phasesDir, dir);
374
- const phaseMatch = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)/i);
375
- const phaseNum = phaseMatch ? phaseMatch[1] : dir;
376
-
377
- let files;
378
- try {
379
- files = fs.readdirSync(phaseDir);
380
- } catch {
381
- continue;
382
- }
383
-
384
- for (const file of files.filter(f => f.includes('-UAT') && f.endsWith('.md'))) {
385
- const filePath = path.join(phaseDir, file);
386
-
387
- let safeFilePath;
388
- try {
389
- safeFilePath = requireSafePath(filePath, planDir, 'UAT file', { allowAbsolute: true });
390
- } catch {
391
- continue;
392
- }
393
-
394
- const content = platformReadSync(safeFilePath);
395
- if (content === null) continue;
396
-
397
- const fm = extractFrontmatter(content);
398
- const status = (fm.status || 'unknown').toLowerCase();
399
- const result = (fm.result || '').toString().toLowerCase();
400
-
401
- // Also accept `result: all_pass` as a fallback when status is absent
402
- // — covers UATs that omit `status:`.
403
- if (TERMINAL_UAT_STATUSES.has(status)) continue;
404
- if (status === 'unknown' && result === 'all_pass') continue;
405
-
406
- // Count open scenarios
407
- const pendingMatches = (content.match(/result:\s*(?:pending|\[pending\])/gi) || []).length;
408
-
409
- results.push({
410
- phase: sanitizeForDisplay(phaseNum),
411
- file: sanitizeForDisplay(file),
412
- status: sanitizeForDisplay(status),
413
- open_scenario_count: pendingMatches,
414
- });
415
- }
416
- }
417
-
418
- return results;
419
- }
420
-
421
- /**
422
- * Scan .planning/phases for VERIFICATION gaps.
423
- */
424
- function scanVerificationGaps(planDir) {
425
- const phasesDir = path.join(planDir, 'phases');
426
- if (!fs.existsSync(phasesDir)) return [];
427
-
428
- let dirs;
429
- try {
430
- dirs = fs.readdirSync(phasesDir, { withFileTypes: true })
431
- .filter(e => e.isDirectory())
432
- .map(e => e.name)
433
- .sort();
434
- } catch {
435
- return [{ scan_error: true }];
436
- }
437
-
438
- const results = [];
439
-
440
- for (const dir of dirs) {
441
- const phaseDir = path.join(phasesDir, dir);
442
- const phaseMatch = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)/i);
443
- const phaseNum = phaseMatch ? phaseMatch[1] : dir;
444
-
445
- let files;
446
- try {
447
- files = fs.readdirSync(phaseDir);
448
- } catch {
449
- continue;
450
- }
451
-
452
- for (const file of files.filter(f => f.includes('-VERIFICATION') && f.endsWith('.md'))) {
453
- const filePath = path.join(phaseDir, file);
454
-
455
- let safeFilePath;
456
- try {
457
- safeFilePath = requireSafePath(filePath, planDir, 'VERIFICATION file', { allowAbsolute: true });
458
- } catch {
459
- continue;
460
- }
461
-
462
- const content = platformReadSync(safeFilePath);
463
- if (content === null) continue;
464
-
465
- const fm = extractFrontmatter(content);
466
- const status = (fm.status || 'unknown').toLowerCase();
467
-
468
- if (status !== 'gaps_found' && status !== 'human_needed') continue;
469
-
470
- results.push({
471
- phase: sanitizeForDisplay(phaseNum),
472
- file: sanitizeForDisplay(file),
473
- status: sanitizeForDisplay(status),
474
- });
475
- }
476
- }
477
-
478
- return results;
479
- }
480
-
481
- /**
482
- * Scan .planning/phases for CONTEXT files with open_questions.
483
- */
484
- function scanContextQuestions(planDir) {
485
- const phasesDir = path.join(planDir, 'phases');
486
- if (!fs.existsSync(phasesDir)) return [];
487
-
488
- let dirs;
489
- try {
490
- dirs = fs.readdirSync(phasesDir, { withFileTypes: true })
491
- .filter(e => e.isDirectory())
492
- .map(e => e.name)
493
- .sort();
494
- } catch {
495
- return [{ scan_error: true }];
496
- }
497
-
498
- const results = [];
499
-
500
- for (const dir of dirs) {
501
- const phaseDir = path.join(phasesDir, dir);
502
- const phaseMatch = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)/i);
503
- const phaseNum = phaseMatch ? phaseMatch[1] : dir;
504
-
505
- let files;
506
- try {
507
- files = fs.readdirSync(phaseDir);
508
- } catch {
509
- continue;
510
- }
511
-
512
- for (const file of files.filter(f => f.includes('-CONTEXT') && f.endsWith('.md'))) {
513
- const filePath = path.join(phaseDir, file);
514
-
515
- let safeFilePath;
516
- try {
517
- safeFilePath = requireSafePath(filePath, planDir, 'CONTEXT file', { allowAbsolute: true });
518
- } catch {
519
- continue;
520
- }
521
-
522
- const content = platformReadSync(safeFilePath);
523
- if (content === null) continue;
524
-
525
- const fm = extractFrontmatter(content);
526
-
527
- // Check frontmatter open_questions field
528
- let questions = [];
529
- if (fm.open_questions) {
530
- if (Array.isArray(fm.open_questions) && fm.open_questions.length > 0) {
531
- questions = fm.open_questions.map(q => sanitizeForDisplay(String(q).slice(0, 200)));
532
- }
533
- }
534
-
535
- // Also check for ## Open Questions section in body
536
- if (questions.length === 0) {
537
- const oqMatch = content.match(/##\s*Open Questions[^\n]*\n([\s\S]*?)(?=\n##\s|$)/i);
538
- if (oqMatch) {
539
- const oqBody = oqMatch[1].trim();
540
- if (oqBody && oqBody.length > 0 && !/^\s*none\s*$/i.test(oqBody)) {
541
- const items = oqBody.split('\n')
542
- .map(l => l.trim())
543
- .filter(l => l && l !== '-' && l !== '*')
544
- .filter(l => /^[-*\d]/.test(l) || l.includes('?'));
545
- questions = items.slice(0, 3).map(q => sanitizeForDisplay(q.slice(0, 200)));
546
- }
547
- }
548
- }
549
-
550
- if (questions.length === 0) continue;
551
-
552
- results.push({
553
- phase: sanitizeForDisplay(phaseNum),
554
- file: sanitizeForDisplay(file),
555
- question_count: questions.length,
556
- questions: questions.slice(0, 3),
557
- });
558
- }
559
- }
560
-
561
- return results;
562
- }
563
-
564
- /**
565
- * Main audit function. Scans all .planning/ artifact categories.
566
- *
567
- * @param {string} cwd - Project root directory
568
- * @returns {object} Structured audit result
569
- */
570
- function auditOpenArtifacts(cwd) {
571
- const planDir = planningDir(cwd);
572
-
573
- const debugSessions = (() => {
574
- try { return scanDebugSessions(planDir); } catch { return [{ scan_error: true }]; }
575
- })();
576
-
577
- const quickTasks = (() => {
578
- try { return scanQuickTasks(planDir); } catch { return [{ scan_error: true }]; }
579
- })();
580
-
581
- const threads = (() => {
582
- try { return scanThreads(planDir); } catch { return [{ scan_error: true }]; }
583
- })();
584
-
585
- const todos = (() => {
586
- try { return scanTodos(planDir); } catch { return [{ scan_error: true }]; }
587
- })();
588
-
589
- const seeds = (() => {
590
- try { return scanSeeds(planDir); } catch { return [{ scan_error: true }]; }
591
- })();
592
-
593
- const uatGaps = (() => {
594
- try { return scanUatGaps(planDir); } catch { return [{ scan_error: true }]; }
595
- })();
596
-
597
- const verificationGaps = (() => {
598
- try { return scanVerificationGaps(planDir); } catch { return [{ scan_error: true }]; }
599
- })();
600
-
601
- const contextQuestions = (() => {
602
- try { return scanContextQuestions(planDir); } catch { return [{ scan_error: true }]; }
603
- })();
604
-
605
- // Count real items (not scan_error sentinels)
606
- const countReal = arr => arr.filter(i => !i.scan_error && !i._remainder_count).length;
607
-
608
- const counts = {
609
- debug_sessions: countReal(debugSessions),
610
- quick_tasks: countReal(quickTasks),
611
- threads: countReal(threads),
612
- todos: countReal(todos),
613
- seeds: countReal(seeds),
614
- uat_gaps: countReal(uatGaps),
615
- verification_gaps: countReal(verificationGaps),
616
- context_questions: countReal(contextQuestions),
617
- };
618
- counts.total = Object.values(counts).reduce((s, n) => s + n, 0);
619
-
620
- return {
621
- scanned_at: new Date().toISOString(),
622
- has_open_items: counts.total > 0,
623
- counts,
624
- items: {
625
- debug_sessions: debugSessions,
626
- quick_tasks: quickTasks,
627
- threads,
628
- todos,
629
- seeds,
630
- uat_gaps: uatGaps,
631
- verification_gaps: verificationGaps,
632
- context_questions: contextQuestions,
633
- },
634
- };
635
- }
636
-
637
- /**
638
- * Format the audit result as a human-readable report.
639
- *
640
- * @param {object} auditResult - Result from auditOpenArtifacts()
641
- * @returns {string} Formatted report
642
- */
643
- function formatAuditReport(auditResult) {
644
- const { counts, items, has_open_items } = auditResult;
645
- const lines = [];
646
- const hr = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━';
647
-
648
- lines.push(hr);
649
- lines.push(' Milestone Close: Open Artifact Audit');
650
- lines.push(hr);
651
-
652
- if (!has_open_items) {
653
- lines.push('');
654
- lines.push(' All artifact types clear. Safe to proceed.');
655
- lines.push('');
656
- lines.push(hr);
657
- return lines.join('\n');
658
- }
659
-
660
- // Debug sessions (blocking quality — red)
661
- if (counts.debug_sessions > 0) {
662
- lines.push('');
663
- lines.push(`🔴 Debug Sessions (${counts.debug_sessions} open)`);
664
- for (const item of items.debug_sessions.filter(i => !i.scan_error)) {
665
- const hyp = item.hypothesis ? ` — ${item.hypothesis}` : '';
666
- lines.push(` • ${item.slug} [${item.status}]${hyp}`);
667
- }
668
- }
669
-
670
- // UAT gaps (blocking quality — red)
671
- if (counts.uat_gaps > 0) {
672
- lines.push('');
673
- lines.push(`🔴 UAT Gaps (${counts.uat_gaps} phases with incomplete UAT)`);
674
- for (const item of items.uat_gaps.filter(i => !i.scan_error)) {
675
- lines.push(` • Phase ${item.phase}: ${item.file} [${item.status}] — ${item.open_scenario_count} pending scenarios`);
676
- }
677
- }
678
-
679
- // Verification gaps (blocking quality — red)
680
- if (counts.verification_gaps > 0) {
681
- lines.push('');
682
- lines.push(`🔴 Verification Gaps (${counts.verification_gaps} unresolved)`);
683
- for (const item of items.verification_gaps.filter(i => !i.scan_error)) {
684
- lines.push(` • Phase ${item.phase}: ${item.file} [${item.status}]`);
685
- }
686
- }
687
-
688
- // Quick tasks (incomplete work — yellow)
689
- if (counts.quick_tasks > 0) {
690
- lines.push('');
691
- lines.push(`🟡 Quick Tasks (${counts.quick_tasks} incomplete)`);
692
- for (const item of items.quick_tasks.filter(i => !i.scan_error)) {
693
- const d = item.date ? ` (${item.date})` : '';
694
- lines.push(` • ${item.slug}${d} [${item.status}]`);
695
- }
696
- }
697
-
698
- // Todos (incomplete work — yellow)
699
- if (counts.todos > 0) {
700
- const realTodos = items.todos.filter(i => !i.scan_error && !i._remainder_count);
701
- const remainder = items.todos.find(i => i._remainder_count);
702
- lines.push('');
703
- lines.push(`🟡 Pending Todos (${counts.todos} pending)`);
704
- for (const item of realTodos) {
705
- const area = item.area ? ` [${item.area}]` : '';
706
- const pri = item.priority ? ` (${item.priority})` : '';
707
- lines.push(` • ${item.filename}${area}${pri}`);
708
- if (item.summary) lines.push(` ${item.summary}`);
709
- }
710
- if (remainder) {
711
- lines.push(` ... and ${remainder._remainder_count} more`);
712
- }
713
- }
714
-
715
- // Threads (deferred decisions — blue)
716
- if (counts.threads > 0) {
717
- lines.push('');
718
- lines.push(`🔵 Open Threads (${counts.threads} active)`);
719
- for (const item of items.threads.filter(i => !i.scan_error)) {
720
- const title = item.title ? ` — ${item.title}` : '';
721
- lines.push(` • ${item.slug} [${item.status}]${title}`);
722
- }
723
- }
724
-
725
- // Seeds (deferred decisions — blue)
726
- if (counts.seeds > 0) {
727
- lines.push('');
728
- lines.push(`🔵 Unimplemented Seeds (${counts.seeds} pending)`);
729
- for (const item of items.seeds.filter(i => !i.scan_error)) {
730
- const title = item.title ? ` — ${item.title}` : '';
731
- lines.push(` • ${item.seed_id} [${item.status}]${title}`);
732
- }
733
- }
734
-
735
- // Context questions (deferred decisions — blue)
736
- if (counts.context_questions > 0) {
737
- lines.push('');
738
- lines.push(`🔵 CONTEXT Open Questions (${counts.context_questions} phases with open questions)`);
739
- for (const item of items.context_questions.filter(i => !i.scan_error)) {
740
- lines.push(` • Phase ${item.phase}: ${item.file} (${item.question_count} question${item.question_count !== 1 ? 's' : ''})`);
741
- for (const q of item.questions) {
742
- lines.push(` - ${q}`);
743
- }
744
- }
745
- }
746
-
747
- lines.push('');
748
- lines.push(hr);
749
- lines.push(` ${counts.total} item${counts.total !== 1 ? 's' : ''} require decisions before close.`);
750
- lines.push(hr);
751
-
752
- return lines.join('\n');
753
- }
754
-
755
- module.exports = { auditOpenArtifacts, formatAuditReport };