@therocketcode/gsd-core 1.4.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 (568) hide show
  1. package/.claude-plugin/plugin.json +23 -0
  2. package/GEMINI.md +53 -0
  3. package/LICENSE +21 -0
  4. package/README.ja-JP.md +125 -0
  5. package/README.ko-KR.md +125 -0
  6. package/README.md +144 -0
  7. package/README.pt-BR.md +125 -0
  8. package/README.zh-CN.md +125 -0
  9. package/agents/gsd-advisor-researcher.md +108 -0
  10. package/agents/gsd-ai-researcher.md +114 -0
  11. package/agents/gsd-assumptions-analyzer.md +105 -0
  12. package/agents/gsd-code-fixer.md +668 -0
  13. package/agents/gsd-code-reviewer.md +387 -0
  14. package/agents/gsd-codebase-mapper.md +853 -0
  15. package/agents/gsd-debug-session-manager.md +314 -0
  16. package/agents/gsd-debugger.md +1452 -0
  17. package/agents/gsd-doc-classifier.md +168 -0
  18. package/agents/gsd-doc-synthesizer.md +204 -0
  19. package/agents/gsd-doc-verifier.md +217 -0
  20. package/agents/gsd-doc-writer.md +616 -0
  21. package/agents/gsd-domain-researcher.md +147 -0
  22. package/agents/gsd-eval-auditor.md +191 -0
  23. package/agents/gsd-eval-planner.md +154 -0
  24. package/agents/gsd-executor.md +785 -0
  25. package/agents/gsd-framework-selector.md +160 -0
  26. package/agents/gsd-integration-checker.md +470 -0
  27. package/agents/gsd-intel-updater.md +342 -0
  28. package/agents/gsd-nyquist-auditor.md +203 -0
  29. package/agents/gsd-pattern-mapper.md +335 -0
  30. package/agents/gsd-phase-researcher.md +867 -0
  31. package/agents/gsd-plan-checker.md +978 -0
  32. package/agents/gsd-planner.md +1204 -0
  33. package/agents/gsd-project-researcher.md +611 -0
  34. package/agents/gsd-research-synthesizer.md +259 -0
  35. package/agents/gsd-roadmapper.md +688 -0
  36. package/agents/gsd-security-auditor.md +155 -0
  37. package/agents/gsd-ui-auditor.md +495 -0
  38. package/agents/gsd-ui-checker.md +309 -0
  39. package/agents/gsd-ui-researcher.md +374 -0
  40. package/agents/gsd-user-profiler.md +171 -0
  41. package/agents/gsd-verifier.md +923 -0
  42. package/assets/gsd-logo-2000-transparent.png +0 -0
  43. package/assets/gsd-logo-2000-transparent.svg +17 -0
  44. package/assets/gsd-logo-2000.png +0 -0
  45. package/assets/gsd-logo-2000.svg +21 -0
  46. package/assets/terminal.svg +68 -0
  47. package/bin/install.js +12726 -0
  48. package/bin/lib/ui-safety-gate.cjs +107 -0
  49. package/commands/gsd/add-tests.md +42 -0
  50. package/commands/gsd/ai-integration-phase.md +37 -0
  51. package/commands/gsd/audit-fix.md +34 -0
  52. package/commands/gsd/audit-milestone.md +37 -0
  53. package/commands/gsd/audit-uat.md +24 -0
  54. package/commands/gsd/autonomous.md +48 -0
  55. package/commands/gsd/capture.md +62 -0
  56. package/commands/gsd/cleanup.md +24 -0
  57. package/commands/gsd/code-review.md +59 -0
  58. package/commands/gsd/complete-milestone.md +143 -0
  59. package/commands/gsd/config.md +56 -0
  60. package/commands/gsd/debug.md +52 -0
  61. package/commands/gsd/discover-product.md +65 -0
  62. package/commands/gsd/discuss-phase.md +77 -0
  63. package/commands/gsd/docs-update.md +49 -0
  64. package/commands/gsd/eval-review.md +33 -0
  65. package/commands/gsd/execute-phase.md +66 -0
  66. package/commands/gsd/explore.md +27 -0
  67. package/commands/gsd/extract-learnings.md +23 -0
  68. package/commands/gsd/fast.md +31 -0
  69. package/commands/gsd/forensics.md +57 -0
  70. package/commands/gsd/graphify.md +204 -0
  71. package/commands/gsd/health.md +31 -0
  72. package/commands/gsd/help.md +28 -0
  73. package/commands/gsd/import.md +45 -0
  74. package/commands/gsd/inbox.md +39 -0
  75. package/commands/gsd/ingest-docs.md +42 -0
  76. package/commands/gsd/manager.md +45 -0
  77. package/commands/gsd/map-codebase.md +83 -0
  78. package/commands/gsd/milestone-summary.md +51 -0
  79. package/commands/gsd/model-domain.md +65 -0
  80. package/commands/gsd/mvp-phase.md +45 -0
  81. package/commands/gsd/new-milestone.md +45 -0
  82. package/commands/gsd/new-project.md +47 -0
  83. package/commands/gsd/ns-context.md +23 -0
  84. package/commands/gsd/ns-ideate.md +24 -0
  85. package/commands/gsd/ns-manage.md +29 -0
  86. package/commands/gsd/ns-project.md +22 -0
  87. package/commands/gsd/ns-review.md +26 -0
  88. package/commands/gsd/ns-workflow.md +28 -0
  89. package/commands/gsd/pause-work.md +43 -0
  90. package/commands/gsd/phase.md +56 -0
  91. package/commands/gsd/plan-phase.md +64 -0
  92. package/commands/gsd/plan-review-convergence.md +59 -0
  93. package/commands/gsd/pr-branch.md +26 -0
  94. package/commands/gsd/profile-user.md +46 -0
  95. package/commands/gsd/progress.md +48 -0
  96. package/commands/gsd/quick.md +174 -0
  97. package/commands/gsd/recommend-architecture.md +64 -0
  98. package/commands/gsd/resume-work.md +30 -0
  99. package/commands/gsd/review-backlog.md +63 -0
  100. package/commands/gsd/review.md +42 -0
  101. package/commands/gsd/secure-phase.md +36 -0
  102. package/commands/gsd/settings.md +29 -0
  103. package/commands/gsd/ship.md +24 -0
  104. package/commands/gsd/sketch.md +60 -0
  105. package/commands/gsd/spec-phase.md +63 -0
  106. package/commands/gsd/spike.md +57 -0
  107. package/commands/gsd/stats.md +20 -0
  108. package/commands/gsd/surface.md +155 -0
  109. package/commands/gsd/testing-strategy.md +65 -0
  110. package/commands/gsd/thread.md +24 -0
  111. package/commands/gsd/ui-phase.md +35 -0
  112. package/commands/gsd/ui-review.md +33 -0
  113. package/commands/gsd/ultraplan-phase.md +34 -0
  114. package/commands/gsd/undo.md +35 -0
  115. package/commands/gsd/update.md +49 -0
  116. package/commands/gsd/validate-phase.md +36 -0
  117. package/commands/gsd/verify-work.md +39 -0
  118. package/commands/gsd/workspace.md +52 -0
  119. package/commands/gsd/workstreams.md +70 -0
  120. package/gemini-extension.json +6 -0
  121. package/gsd-core/bin/check-latest-version.cjs +161 -0
  122. package/gsd-core/bin/gsd-tools.cjs +1928 -0
  123. package/gsd-core/bin/lib/active-workstream-store.cjs +291 -0
  124. package/gsd-core/bin/lib/adr-parser.cjs +399 -0
  125. package/gsd-core/bin/lib/agent-command-router.cjs +68 -0
  126. package/gsd-core/bin/lib/artifacts.cjs +51 -0
  127. package/gsd-core/bin/lib/audit.cjs +743 -0
  128. package/gsd-core/bin/lib/check-command-router.cjs +343 -0
  129. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +81 -0
  130. package/gsd-core/bin/lib/cli-exit.cjs +42 -0
  131. package/gsd-core/bin/lib/clock.cjs +95 -0
  132. package/gsd-core/bin/lib/clusters.cjs +132 -0
  133. package/gsd-core/bin/lib/code-review-flags.cjs +59 -0
  134. package/gsd-core/bin/lib/command-aliases.cjs +809 -0
  135. package/gsd-core/bin/lib/command-arg-projection.cjs +55 -0
  136. package/gsd-core/bin/lib/command-routing-hub.cjs +300 -0
  137. package/gsd-core/bin/lib/commands.cjs +1203 -0
  138. package/gsd-core/bin/lib/config-schema.cjs +29 -0
  139. package/gsd-core/bin/lib/config-types.cjs +19 -0
  140. package/gsd-core/bin/lib/config.cjs +738 -0
  141. package/gsd-core/bin/lib/configuration.cjs +239 -0
  142. package/gsd-core/bin/lib/context-utilization.cjs +48 -0
  143. package/gsd-core/bin/lib/core.cjs +2051 -0
  144. package/gsd-core/bin/lib/decisions.cjs +118 -0
  145. package/gsd-core/bin/lib/docs.cjs +252 -0
  146. package/gsd-core/bin/lib/drift.cjs +364 -0
  147. package/gsd-core/bin/lib/fallow-runner.cjs +115 -0
  148. package/gsd-core/bin/lib/frontmatter.cjs +442 -0
  149. package/gsd-core/bin/lib/gap-checker.cjs +257 -0
  150. package/gsd-core/bin/lib/graphify.cjs +496 -0
  151. package/gsd-core/bin/lib/gsd2-import.cjs +456 -0
  152. package/gsd-core/bin/lib/init-command-router.cjs +62 -0
  153. package/gsd-core/bin/lib/init.cjs +1815 -0
  154. package/gsd-core/bin/lib/install-profiles.cjs +584 -0
  155. package/gsd-core/bin/lib/installer-migration-authoring.cjs +122 -0
  156. package/gsd-core/bin/lib/installer-migration-report.cjs +350 -0
  157. package/gsd-core/bin/lib/installer-migrations/000-first-time-baseline.cjs +218 -0
  158. package/gsd-core/bin/lib/installer-migrations/001-legacy-orphan-files.cjs +48 -0
  159. package/gsd-core/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs +94 -0
  160. package/gsd-core/bin/lib/installer-migrations/003-rename-get-shit-done-to-gsd-core.cjs +108 -0
  161. package/gsd-core/bin/lib/installer-migrations.cjs +823 -0
  162. package/gsd-core/bin/lib/intel.cjs +590 -0
  163. package/gsd-core/bin/lib/learnings.cjs +270 -0
  164. package/gsd-core/bin/lib/legacy-cleanup.cjs +253 -0
  165. package/gsd-core/bin/lib/milestone.cjs +373 -0
  166. package/gsd-core/bin/lib/model-catalog.cjs +154 -0
  167. package/gsd-core/bin/lib/model-profiles.cjs +24 -0
  168. package/gsd-core/bin/lib/observability/event.cjs +51 -0
  169. package/gsd-core/bin/lib/observability/logger.cjs +146 -0
  170. package/gsd-core/bin/lib/observability/redaction.cjs +48 -0
  171. package/gsd-core/bin/lib/package-identity.cjs +35 -0
  172. package/gsd-core/bin/lib/package-legitimacy.cjs +368 -0
  173. package/gsd-core/bin/lib/phase-command-router.cjs +189 -0
  174. package/gsd-core/bin/lib/phase-lifecycle.cjs +74 -0
  175. package/gsd-core/bin/lib/phase.cjs +1307 -0
  176. package/gsd-core/bin/lib/phases-command-router.cjs +43 -0
  177. package/gsd-core/bin/lib/plan-scan.cjs +91 -0
  178. package/gsd-core/bin/lib/planning-workspace.cjs +245 -0
  179. package/gsd-core/bin/lib/profile-output.cjs +1120 -0
  180. package/gsd-core/bin/lib/profile-pipeline.cjs +517 -0
  181. package/gsd-core/bin/lib/project-root.cjs +119 -0
  182. package/gsd-core/bin/lib/prompt-budget.cjs +305 -0
  183. package/gsd-core/bin/lib/research-provider.cjs +137 -0
  184. package/gsd-core/bin/lib/research-store.cjs +167 -0
  185. package/gsd-core/bin/lib/review-reviewer-selection.cjs +121 -0
  186. package/gsd-core/bin/lib/roadmap-command-router.cjs +166 -0
  187. package/gsd-core/bin/lib/roadmap-upgrade.cjs +476 -0
  188. package/gsd-core/bin/lib/roadmap.cjs +600 -0
  189. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +312 -0
  190. package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +56 -0
  191. package/gsd-core/bin/lib/runtime-homes.cjs +190 -0
  192. package/gsd-core/bin/lib/runtime-name-policy.cjs +96 -0
  193. package/gsd-core/bin/lib/runtime-slash.cjs +119 -0
  194. package/gsd-core/bin/lib/schema-detect.cjs +159 -0
  195. package/gsd-core/bin/lib/secrets.cjs +34 -0
  196. package/gsd-core/bin/lib/security.cjs +480 -0
  197. package/gsd-core/bin/lib/semver-compare.cjs +42 -0
  198. package/gsd-core/bin/lib/shell-command-projection.cjs +533 -0
  199. package/gsd-core/bin/lib/state-command-router.cjs +160 -0
  200. package/gsd-core/bin/lib/state-document.cjs +259 -0
  201. package/gsd-core/bin/lib/state.cjs +2010 -0
  202. package/gsd-core/bin/lib/surface.cjs +449 -0
  203. package/gsd-core/bin/lib/task-command-router.cjs +85 -0
  204. package/gsd-core/bin/lib/template.cjs +237 -0
  205. package/gsd-core/bin/lib/uat.cjs +297 -0
  206. package/gsd-core/bin/lib/ui-safety-gate.cjs +98 -0
  207. package/gsd-core/bin/lib/update-context.cjs +218 -0
  208. package/gsd-core/bin/lib/validate-command-router.cjs +91 -0
  209. package/gsd-core/bin/lib/validate.cjs +112 -0
  210. package/gsd-core/bin/lib/verification-command-router.cjs +31 -0
  211. package/gsd-core/bin/lib/verification.cjs +193 -0
  212. package/gsd-core/bin/lib/verify-command-router.cjs +44 -0
  213. package/gsd-core/bin/lib/verify.cjs +1451 -0
  214. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +81 -0
  215. package/gsd-core/bin/lib/workstream-inventory.cjs +147 -0
  216. package/gsd-core/bin/lib/workstream-name-policy.cjs +91 -0
  217. package/gsd-core/bin/lib/workstream.cjs +380 -0
  218. package/gsd-core/bin/lib/worktree-base-ref.cjs +325 -0
  219. package/gsd-core/bin/lib/worktree-safety.cjs +943 -0
  220. package/gsd-core/bin/shared/config-defaults.manifest.json +98 -0
  221. package/gsd-core/bin/shared/config-schema.manifest.json +192 -0
  222. package/gsd-core/bin/shared/model-catalog.json +149 -0
  223. package/gsd-core/bin/shared/runtime-aliases.manifest.json +75 -0
  224. package/gsd-core/bin/verify-reapply-patches.cjs +349 -0
  225. package/gsd-core/contexts/dev.md +21 -0
  226. package/gsd-core/contexts/research.md +22 -0
  227. package/gsd-core/contexts/review.md +23 -0
  228. package/gsd-core/references/agent-contracts.md +79 -0
  229. package/gsd-core/references/ai-evals.md +156 -0
  230. package/gsd-core/references/ai-frameworks.md +186 -0
  231. package/gsd-core/references/architecture-decision.md +74 -0
  232. package/gsd-core/references/artifact-types.md +131 -0
  233. package/gsd-core/references/auth-in-tests.md +91 -0
  234. package/gsd-core/references/autonomous-smart-discuss.md +277 -0
  235. package/gsd-core/references/checkpoints.md +814 -0
  236. package/gsd-core/references/common-bug-patterns.md +114 -0
  237. package/gsd-core/references/context-budget.md +85 -0
  238. package/gsd-core/references/continuation-format.md +253 -0
  239. package/gsd-core/references/db-test-isolation.md +54 -0
  240. package/gsd-core/references/debugger-philosophy.md +76 -0
  241. package/gsd-core/references/decimal-phase-calculation.md +64 -0
  242. package/gsd-core/references/doc-conflict-engine.md +91 -0
  243. package/gsd-core/references/domain-modeling.md +80 -0
  244. package/gsd-core/references/domain-probes.md +125 -0
  245. package/gsd-core/references/e2e-tiering.md +35 -0
  246. package/gsd-core/references/execute-mvp-tdd.md +81 -0
  247. package/gsd-core/references/executor-examples.md +110 -0
  248. package/gsd-core/references/few-shot-examples/plan-checker.md +73 -0
  249. package/gsd-core/references/few-shot-examples/verifier.md +109 -0
  250. package/gsd-core/references/flaky-test-checklist.md +22 -0
  251. package/gsd-core/references/gate-prompts.md +100 -0
  252. package/gsd-core/references/gates.md +70 -0
  253. package/gsd-core/references/git-integration.md +298 -0
  254. package/gsd-core/references/git-planning-commit.md +40 -0
  255. package/gsd-core/references/ios-scaffold.md +123 -0
  256. package/gsd-core/references/mandatory-initial-read.md +2 -0
  257. package/gsd-core/references/model-profile-resolution.md +38 -0
  258. package/gsd-core/references/model-profiles.md +245 -0
  259. package/gsd-core/references/mvp-concepts.md +49 -0
  260. package/gsd-core/references/phase-argument-parsing.md +61 -0
  261. package/gsd-core/references/planner-antipatterns.md +89 -0
  262. package/gsd-core/references/planner-chunked.md +49 -0
  263. package/gsd-core/references/planner-gap-closure.md +62 -0
  264. package/gsd-core/references/planner-graphify-auto-update.md +67 -0
  265. package/gsd-core/references/planner-human-verify-mode.md +57 -0
  266. package/gsd-core/references/planner-interface-context.md +62 -0
  267. package/gsd-core/references/planner-load-graph-context.md +36 -0
  268. package/gsd-core/references/planner-mvp-mode.md +53 -0
  269. package/gsd-core/references/planner-reviews.md +39 -0
  270. package/gsd-core/references/planner-revision.md +87 -0
  271. package/gsd-core/references/planner-source-audit.md +73 -0
  272. package/gsd-core/references/planning-config.md +473 -0
  273. package/gsd-core/references/product-discovery.md +49 -0
  274. package/gsd-core/references/project-skills-discovery.md +19 -0
  275. package/gsd-core/references/questioning.md +162 -0
  276. package/gsd-core/references/realistic-test-data.md +44 -0
  277. package/gsd-core/references/research-documentation-lookup.md +29 -0
  278. package/gsd-core/references/research-philosophy.md +29 -0
  279. package/gsd-core/references/research-verification-protocol.md +27 -0
  280. package/gsd-core/references/revision-loop.md +97 -0
  281. package/gsd-core/references/scout-codebase.md +51 -0
  282. package/gsd-core/references/skeleton-template.md +48 -0
  283. package/gsd-core/references/sketch-interactivity.md +41 -0
  284. package/gsd-core/references/sketch-theme-system.md +94 -0
  285. package/gsd-core/references/sketch-tooling.md +45 -0
  286. package/gsd-core/references/sketch-variant-patterns.md +81 -0
  287. package/gsd-core/references/spidr-splitting.md +69 -0
  288. package/gsd-core/references/tdd.md +330 -0
  289. package/gsd-core/references/test-containers.md +55 -0
  290. package/gsd-core/references/test-strategy.md +75 -0
  291. package/gsd-core/references/thinking-models-debug.md +44 -0
  292. package/gsd-core/references/thinking-models-execution.md +50 -0
  293. package/gsd-core/references/thinking-models-planning.md +62 -0
  294. package/gsd-core/references/thinking-models-research.md +50 -0
  295. package/gsd-core/references/thinking-models-verification.md +55 -0
  296. package/gsd-core/references/thinking-partner.md +96 -0
  297. package/gsd-core/references/ui-brand.md +162 -0
  298. package/gsd-core/references/universal-anti-patterns.md +63 -0
  299. package/gsd-core/references/user-profiling.md +681 -0
  300. package/gsd-core/references/user-story-template.md +58 -0
  301. package/gsd-core/references/verification-overrides.md +227 -0
  302. package/gsd-core/references/verification-patterns.md +612 -0
  303. package/gsd-core/references/verify-mvp-mode.md +85 -0
  304. package/gsd-core/references/workstream-flag.md +111 -0
  305. package/gsd-core/references/worktree-branch-check.md +38 -0
  306. package/gsd-core/references/worktree-path-safety.md +67 -0
  307. package/gsd-core/templates/AI-SPEC.md +246 -0
  308. package/gsd-core/templates/DEBUG.md +169 -0
  309. package/gsd-core/templates/README.md +77 -0
  310. package/gsd-core/templates/SECURITY.md +61 -0
  311. package/gsd-core/templates/UAT.md +265 -0
  312. package/gsd-core/templates/UI-SPEC.md +100 -0
  313. package/gsd-core/templates/VALIDATION.md +76 -0
  314. package/gsd-core/templates/adr.md +58 -0
  315. package/gsd-core/templates/claude-md.md +145 -0
  316. package/gsd-core/templates/codebase/architecture.md +255 -0
  317. package/gsd-core/templates/codebase/concerns.md +310 -0
  318. package/gsd-core/templates/codebase/conventions.md +307 -0
  319. package/gsd-core/templates/codebase/integrations.md +280 -0
  320. package/gsd-core/templates/codebase/stack.md +186 -0
  321. package/gsd-core/templates/codebase/structure.md +285 -0
  322. package/gsd-core/templates/codebase/testing.md +480 -0
  323. package/gsd-core/templates/config.json +62 -0
  324. package/gsd-core/templates/context.md +352 -0
  325. package/gsd-core/templates/continue-here.md +78 -0
  326. package/gsd-core/templates/copilot-instructions.md +7 -0
  327. package/gsd-core/templates/debug-subagent-prompt.md +91 -0
  328. package/gsd-core/templates/dev-preferences.md +21 -0
  329. package/gsd-core/templates/discovery.md +146 -0
  330. package/gsd-core/templates/discussion-log.md +63 -0
  331. package/gsd-core/templates/domain-model.md +54 -0
  332. package/gsd-core/templates/milestone-archive.md +123 -0
  333. package/gsd-core/templates/milestone.md +115 -0
  334. package/gsd-core/templates/phase-prompt.md +610 -0
  335. package/gsd-core/templates/planner-subagent-prompt.md +117 -0
  336. package/gsd-core/templates/product-brief.md +55 -0
  337. package/gsd-core/templates/project.md +186 -0
  338. package/gsd-core/templates/requirements.md +231 -0
  339. package/gsd-core/templates/research-project/ARCHITECTURE.md +204 -0
  340. package/gsd-core/templates/research-project/FEATURES.md +147 -0
  341. package/gsd-core/templates/research-project/PITFALLS.md +200 -0
  342. package/gsd-core/templates/research-project/STACK.md +120 -0
  343. package/gsd-core/templates/research-project/SUMMARY.md +170 -0
  344. package/gsd-core/templates/research.md +592 -0
  345. package/gsd-core/templates/retrospective.md +54 -0
  346. package/gsd-core/templates/roadmap.md +202 -0
  347. package/gsd-core/templates/spec.md +307 -0
  348. package/gsd-core/templates/state.md +195 -0
  349. package/gsd-core/templates/summary-complex.md +59 -0
  350. package/gsd-core/templates/summary-minimal.md +41 -0
  351. package/gsd-core/templates/summary-standard.md +48 -0
  352. package/gsd-core/templates/summary.md +248 -0
  353. package/gsd-core/templates/test-strategy.md +50 -0
  354. package/gsd-core/templates/user-profile.md +146 -0
  355. package/gsd-core/templates/user-setup.md +311 -0
  356. package/gsd-core/templates/verification-report.md +322 -0
  357. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -0
  358. package/gsd-core/workflows/add-backlog.md +91 -0
  359. package/gsd-core/workflows/add-phase.md +113 -0
  360. package/gsd-core/workflows/add-tests.md +355 -0
  361. package/gsd-core/workflows/add-todo.md +161 -0
  362. package/gsd-core/workflows/ai-integration-phase.md +295 -0
  363. package/gsd-core/workflows/analyze-dependencies.md +96 -0
  364. package/gsd-core/workflows/audit-fix.md +178 -0
  365. package/gsd-core/workflows/audit-milestone.md +360 -0
  366. package/gsd-core/workflows/audit-uat.md +110 -0
  367. package/gsd-core/workflows/autonomous.md +797 -0
  368. package/gsd-core/workflows/check-todos.md +180 -0
  369. package/gsd-core/workflows/cleanup.md +195 -0
  370. package/gsd-core/workflows/code-review-fix.md +502 -0
  371. package/gsd-core/workflows/code-review.md +658 -0
  372. package/gsd-core/workflows/complete-milestone.md +855 -0
  373. package/gsd-core/workflows/debug.md +237 -0
  374. package/gsd-core/workflows/diagnose-issues.md +245 -0
  375. package/gsd-core/workflows/discover-product.md +112 -0
  376. package/gsd-core/workflows/discovery-phase.md +291 -0
  377. package/gsd-core/workflows/discuss-phase/modes/advisor.md +176 -0
  378. package/gsd-core/workflows/discuss-phase/modes/all.md +28 -0
  379. package/gsd-core/workflows/discuss-phase/modes/analyze.md +44 -0
  380. package/gsd-core/workflows/discuss-phase/modes/auto.md +57 -0
  381. package/gsd-core/workflows/discuss-phase/modes/batch.md +52 -0
  382. package/gsd-core/workflows/discuss-phase/modes/chain.md +98 -0
  383. package/gsd-core/workflows/discuss-phase/modes/default.md +141 -0
  384. package/gsd-core/workflows/discuss-phase/modes/power.md +44 -0
  385. package/gsd-core/workflows/discuss-phase/modes/text.md +55 -0
  386. package/gsd-core/workflows/discuss-phase/templates/checkpoint.json +18 -0
  387. package/gsd-core/workflows/discuss-phase/templates/context.md +136 -0
  388. package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +50 -0
  389. package/gsd-core/workflows/discuss-phase-assumptions.md +675 -0
  390. package/gsd-core/workflows/discuss-phase-power.md +291 -0
  391. package/gsd-core/workflows/discuss-phase.md +499 -0
  392. package/gsd-core/workflows/do.md +111 -0
  393. package/gsd-core/workflows/docs-update.md +1176 -0
  394. package/gsd-core/workflows/edit-phase.md +295 -0
  395. package/gsd-core/workflows/eval-review.md +156 -0
  396. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +95 -0
  397. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +94 -0
  398. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +117 -0
  399. package/gsd-core/workflows/execute-phase.md +1752 -0
  400. package/gsd-core/workflows/execute-plan.md +526 -0
  401. package/gsd-core/workflows/explore.md +146 -0
  402. package/gsd-core/workflows/extract-learnings.md +243 -0
  403. package/gsd-core/workflows/fast.md +124 -0
  404. package/gsd-core/workflows/forensics.md +279 -0
  405. package/gsd-core/workflows/graduation.md +196 -0
  406. package/gsd-core/workflows/health.md +224 -0
  407. package/gsd-core/workflows/help/modes/brief.md +22 -0
  408. package/gsd-core/workflows/help/modes/default.md +50 -0
  409. package/gsd-core/workflows/help/modes/full.md +789 -0
  410. package/gsd-core/workflows/help/modes/topic.md +74 -0
  411. package/gsd-core/workflows/help.md +24 -0
  412. package/gsd-core/workflows/import.md +256 -0
  413. package/gsd-core/workflows/inbox.md +387 -0
  414. package/gsd-core/workflows/ingest-docs.md +340 -0
  415. package/gsd-core/workflows/insert-phase.md +152 -0
  416. package/gsd-core/workflows/list-phase-assumptions.md +178 -0
  417. package/gsd-core/workflows/list-workspaces.md +57 -0
  418. package/gsd-core/workflows/manager.md +393 -0
  419. package/gsd-core/workflows/map-codebase.md +446 -0
  420. package/gsd-core/workflows/milestone-summary.md +224 -0
  421. package/gsd-core/workflows/model-domain.md +162 -0
  422. package/gsd-core/workflows/mvp-phase.md +222 -0
  423. package/gsd-core/workflows/new-milestone.md +635 -0
  424. package/gsd-core/workflows/new-project.md +1555 -0
  425. package/gsd-core/workflows/new-workspace.md +240 -0
  426. package/gsd-core/workflows/next.md +299 -0
  427. package/gsd-core/workflows/node-repair.md +92 -0
  428. package/gsd-core/workflows/note.md +158 -0
  429. package/gsd-core/workflows/pause-work.md +244 -0
  430. package/gsd-core/workflows/plan-milestone-gaps.md +281 -0
  431. package/gsd-core/workflows/plan-phase.md +1814 -0
  432. package/gsd-core/workflows/plan-review-convergence.md +346 -0
  433. package/gsd-core/workflows/plant-seed.md +230 -0
  434. package/gsd-core/workflows/pr-branch.md +157 -0
  435. package/gsd-core/workflows/profile-user.md +453 -0
  436. package/gsd-core/workflows/progress.md +699 -0
  437. package/gsd-core/workflows/quick.md +1017 -0
  438. package/gsd-core/workflows/reapply-patches.md +426 -0
  439. package/gsd-core/workflows/recommend-architecture.md +135 -0
  440. package/gsd-core/workflows/remove-phase.md +156 -0
  441. package/gsd-core/workflows/remove-workspace.md +108 -0
  442. package/gsd-core/workflows/resume-project.md +332 -0
  443. package/gsd-core/workflows/review.md +748 -0
  444. package/gsd-core/workflows/scan.md +107 -0
  445. package/gsd-core/workflows/secure-phase.md +182 -0
  446. package/gsd-core/workflows/session-report.md +146 -0
  447. package/gsd-core/workflows/settings-advanced.md +810 -0
  448. package/gsd-core/workflows/settings-integrations.md +312 -0
  449. package/gsd-core/workflows/settings.md +566 -0
  450. package/gsd-core/workflows/ship.md +405 -0
  451. package/gsd-core/workflows/sketch-wrap-up.md +286 -0
  452. package/gsd-core/workflows/sketch.md +361 -0
  453. package/gsd-core/workflows/spec-phase.md +263 -0
  454. package/gsd-core/workflows/spike-wrap-up.md +307 -0
  455. package/gsd-core/workflows/spike.md +453 -0
  456. package/gsd-core/workflows/stats.md +80 -0
  457. package/gsd-core/workflows/sync-skills.md +182 -0
  458. package/gsd-core/workflows/testing-strategy.md +122 -0
  459. package/gsd-core/workflows/thread.md +222 -0
  460. package/gsd-core/workflows/transition.md +694 -0
  461. package/gsd-core/workflows/ui-phase.md +328 -0
  462. package/gsd-core/workflows/ui-review.md +193 -0
  463. package/gsd-core/workflows/ultraplan-phase.md +199 -0
  464. package/gsd-core/workflows/undo.md +314 -0
  465. package/gsd-core/workflows/update.md +496 -0
  466. package/gsd-core/workflows/validate-phase.md +181 -0
  467. package/gsd-core/workflows/verify-phase.md +544 -0
  468. package/gsd-core/workflows/verify-work.md +781 -0
  469. package/hooks/dist/gsd-check-update-worker.js +108 -0
  470. package/hooks/dist/gsd-check-update.js +66 -0
  471. package/hooks/dist/gsd-config-reload.js +133 -0
  472. package/hooks/dist/gsd-context-monitor.js +195 -0
  473. package/hooks/dist/gsd-cursor-post-tool.js +75 -0
  474. package/hooks/dist/gsd-cursor-session-start.js +52 -0
  475. package/hooks/dist/gsd-graphify-update.sh +158 -0
  476. package/hooks/dist/gsd-phase-boundary.sh +47 -0
  477. package/hooks/dist/gsd-prompt-guard.js +97 -0
  478. package/hooks/dist/gsd-read-guard.js +101 -0
  479. package/hooks/dist/gsd-read-injection-scanner.js +203 -0
  480. package/hooks/dist/gsd-session-state.sh +59 -0
  481. package/hooks/dist/gsd-statusline.js +566 -0
  482. package/hooks/dist/gsd-update-banner.js +138 -0
  483. package/hooks/dist/gsd-validate-commit.sh +57 -0
  484. package/hooks/dist/gsd-workflow-guard.js +167 -0
  485. package/hooks/dist/gsd-worktree-path-guard.js +169 -0
  486. package/hooks/dist/lib/git-cmd.js +150 -0
  487. package/hooks/dist/lib/gsd-graphify-rebuild.sh +65 -0
  488. package/hooks/dist/managed-hooks-registry.cjs +38 -0
  489. package/hooks/gsd-check-update-worker.js +108 -0
  490. package/hooks/gsd-check-update.js +66 -0
  491. package/hooks/gsd-config-reload.js +133 -0
  492. package/hooks/gsd-context-monitor.js +195 -0
  493. package/hooks/gsd-cursor-post-tool.js +75 -0
  494. package/hooks/gsd-cursor-session-start.js +52 -0
  495. package/hooks/gsd-graphify-update.sh +158 -0
  496. package/hooks/gsd-phase-boundary.sh +47 -0
  497. package/hooks/gsd-prompt-guard.js +97 -0
  498. package/hooks/gsd-read-guard.js +101 -0
  499. package/hooks/gsd-read-injection-scanner.js +203 -0
  500. package/hooks/gsd-session-state.sh +59 -0
  501. package/hooks/gsd-statusline.js +566 -0
  502. package/hooks/gsd-update-banner.js +138 -0
  503. package/hooks/gsd-validate-commit.sh +57 -0
  504. package/hooks/gsd-workflow-guard.js +167 -0
  505. package/hooks/gsd-worktree-path-guard.js +169 -0
  506. package/hooks/hooks.json +69 -0
  507. package/hooks/lib/git-cmd.js +150 -0
  508. package/hooks/lib/gsd-graphify-rebuild.sh +65 -0
  509. package/hooks/managed-hooks-registry.cjs +38 -0
  510. package/package.json +115 -0
  511. package/scripts/affected-tests-lib.cjs +542 -0
  512. package/scripts/audit-workflow-script-paths.cjs +73 -0
  513. package/scripts/base64-scan.sh +351 -0
  514. package/scripts/build-hooks.js +247 -0
  515. package/scripts/changeset/README.md +129 -0
  516. package/scripts/changeset/cli.cjs +590 -0
  517. package/scripts/changeset/github-release-notes.cjs +199 -0
  518. package/scripts/changeset/lint.cjs +111 -0
  519. package/scripts/changeset/new.cjs +137 -0
  520. package/scripts/changeset/parse.cjs +114 -0
  521. package/scripts/changeset/render.cjs +34 -0
  522. package/scripts/changeset/serialize.cjs +130 -0
  523. package/scripts/check-alias-drift.cjs +114 -0
  524. package/scripts/check-env.cjs +312 -0
  525. package/scripts/check-npm-integrity.cjs +215 -0
  526. package/scripts/ci-guard-runner.cjs +22 -0
  527. package/scripts/ci-prepare-test-scope.cjs +51 -0
  528. package/scripts/ci-rebase-check.cjs +86 -0
  529. package/scripts/ci-test-scope.cjs +431 -0
  530. package/scripts/command-contract-helpers.cjs +64 -0
  531. package/scripts/diff-touches-shipped-paths.cjs +155 -0
  532. package/scripts/fix-slash-commands.cjs +147 -0
  533. package/scripts/gen-inventory-manifest.cjs +115 -0
  534. package/scripts/gen-research-agents.cjs +276 -0
  535. package/scripts/generate-package-identity.cjs +125 -0
  536. package/scripts/issue-dedupe.cjs +278 -0
  537. package/scripts/lib/allowlist-ratchet.cjs +136 -0
  538. package/scripts/lib/cli-exit.cjs +56 -0
  539. package/scripts/lint-command-contract.cjs +114 -0
  540. package/scripts/lint-descriptions.cjs +87 -0
  541. package/scripts/lint-docs-required.cjs +222 -0
  542. package/scripts/lint-legacy-dir-name.cjs +160 -0
  543. package/scripts/lint-package-identity-drift.cjs +141 -0
  544. package/scripts/lint-pr-check-project-dir.cjs +99 -0
  545. package/scripts/lint-shell-command-projection-drift.cjs +62 -0
  546. package/scripts/lint-skill-deps.cjs +185 -0
  547. package/scripts/lint-test-file-count.allowlist.json +135 -0
  548. package/scripts/lint-test-file-count.cjs +246 -0
  549. package/scripts/mutation-matrix.cjs +222 -0
  550. package/scripts/pr-template-policy.cjs +268 -0
  551. package/scripts/prompt-injection-scan.sh +207 -0
  552. package/scripts/release-notes/discord-release-summary.cjs +373 -0
  553. package/scripts/release-notes/format-github-release-notes.cjs +261 -0
  554. package/scripts/release-tarball-smoke.cjs +629 -0
  555. package/scripts/research-profiles.cjs +149 -0
  556. package/scripts/run-affected-tests.cjs +7 -0
  557. package/scripts/run-cross-platform-tests.cjs +67 -0
  558. package/scripts/run-tests.cjs +315 -0
  559. package/scripts/secret-scan-lint.sh +231 -0
  560. package/scripts/secret-scan.sh +358 -0
  561. package/scripts/setup-branch-protection.sh +236 -0
  562. package/scripts/strip-prose-atrefs.cjs +106 -0
  563. package/scripts/sync-manifest-versions.cjs +119 -0
  564. package/scripts/sync-rulesets.sh +34 -0
  565. package/scripts/sync-runtime-launcher.cjs +399 -0
  566. package/scripts/test-failure-reasons.cjs +34 -0
  567. package/scripts/verify-npm-publish.cjs +240 -0
  568. package/scripts/workflow-policy.cjs +450 -0
@@ -0,0 +1,629 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * scripts/release-tarball-smoke.cjs
4
+ *
5
+ * Release tarball smoke test for issue #3686.
6
+ *
7
+ * Guards against the class of bugs that can't be caught by working-tree tests:
8
+ * - #3684: maskIfSecret import/export mismatch shipped in v1.42.3 (runtime
9
+ * crash on installed package, invisible to unit tests)
10
+ *
11
+ * Strategy: pack the working tree, install into a temp prefix, invoke the
12
+ * installed binary, assert the version matches package.json. Exercises the
13
+ * INSTALLED package, not the working tree.
14
+ *
15
+ * Exports:
16
+ * SMOKE — frozen enum of result codes
17
+ * runSmoke({ tarballPath, installPrefix, expectedVersion, fixtureDir,
18
+ * lifecycleCommands, dryRun })
19
+ * → { code: SMOKE.*, details: { version, tarball, ... } }
20
+ *
21
+ * CLI entry: node scripts/release-tarball-smoke.cjs --json
22
+ * Packs working tree, installs to a temp prefix, checks version.
23
+ * Exits 0 on SMOKE.OK, 1 otherwise.
24
+ * Always prints JSON to stdout when --json flag is present.
25
+ *
26
+ * Lifecycle command checks (Cycle 2):
27
+ * For each command name (other than 'init') in lifecycleCommands:
28
+ * - Assert commands/gsd/<cmd>.md exists in the installed package
29
+ * - Parse the .md for a workflow @-import or inline reference
30
+ * - Assert the referenced workflow .md exists in the installed package
31
+ * If 'init' is in lifecycleCommands, runs `gsd-core --local --claude`
32
+ * in fixtureDir to verify the installer is callable (INIT_FAILED on crash).
33
+ * Non-interactive: --local --claude flags skip all prompts.
34
+ *
35
+ * Workflow-body checks (Cycle 3 — informational):
36
+ * - Scans all installed gsd-core/workflows/*.md for /gsd:<known-cmd>
37
+ * colon-namespace leaks (WORKFLOW_BODY_COLON_LEAK).
38
+ * This check populates result.details with counters but does NOT return a
39
+ * failure code by default; it is informational until enforcement is enabled.
40
+ */
41
+
42
+ 'use strict';
43
+
44
+ const { execFileSync, spawnSync } = require('child_process');
45
+ const fs = require('fs');
46
+ const os = require('os');
47
+ const path = require('path');
48
+ const { PACKAGE_NAME } = require('../gsd-core/bin/lib/package-identity.cjs');
49
+ const { ExitError, runMain } = require('./lib/cli-exit.cjs');
50
+ // 120 s proved too tight on Windows GitHub-hosted runners: cold-cache
51
+ // `npm install -g` with a 1499-file tarball took ~120 s exactly, causing
52
+ // spawnSync to fire SIGTERM and return { status: null, stdout: '', stderr: '' }
53
+ // (Node docs: status is null when subprocess terminated due to a signal).
54
+ // The INSTALL_FAILED branch checks `status !== 0`, which null satisfies, so the
55
+ // test saw empty stdout/stderr and a spurious INSTALL_FAILED. Windows runners
56
+ // are slower than Linux/macOS for filesystem-heavy operations (
57
+ // https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories
58
+ // ). Raise to 600 s (the same ceiling the before() helper uses for pack+install).
59
+ const CHILD_TIMEOUT_MS = process.platform === 'win32' ? 600_000 : 120_000;
60
+
61
+ // ---------------------------------------------------------------------------
62
+ // Frozen result-code enum
63
+ // ---------------------------------------------------------------------------
64
+
65
+ const SMOKE = Object.freeze({
66
+ OK: 'ok',
67
+ VERSION_MISMATCH: 'version_mismatch',
68
+ PACK_FAILED: 'pack_failed',
69
+ INSTALL_FAILED: 'install_failed',
70
+ BIN_NOT_CALLABLE: 'bin_not_callable',
71
+ // Cycle 2 codes
72
+ COMMAND_FILE_MISSING: 'command_file_missing',
73
+ WORKFLOW_FILE_MISSING: 'workflow_file_missing',
74
+ INIT_FAILED: 'init_failed',
75
+ // Cycle 3 code
76
+ WORKFLOW_BODY_COLON_LEAK: 'workflow_body_colon_leak',
77
+ });
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // Exported helper: binInvocation
81
+ // ---------------------------------------------------------------------------
82
+
83
+ /**
84
+ * Build the { command, args, shell } descriptor needed to spawn an installed
85
+ * npm bin correctly on both Windows and POSIX.
86
+ *
87
+ * On Windows, npm installs a `.cmd` (or `.bat`) shim in .bin/. Node ≥18.20.2
88
+ * / ≥20.12.2 throws EINVAL when you try to spawnSync a .cmd/.bat without
89
+ * shell:true (CVE-2024-27980 mitigation). With shell:true, Node does NOT
90
+ * auto-quote argv, so a bin path that contains spaces must be wrapped in
91
+ * double-quotes to arrive at the shell as one token.
92
+ *
93
+ * On POSIX the bin is a regular shebang JS file; we invoke it directly via
94
+ * process.execPath (the same Node binary) without a shell.
95
+ *
96
+ * @param {string} binPath - Absolute path to the resolved bin file.
97
+ * @param {string[]} [args] - Additional arguments (e.g. ['--help']).
98
+ * @returns {{ command: string, args: string[], shell: boolean }}
99
+ */
100
+ function binInvocation(binPath, args = []) {
101
+ const lower = binPath.toLowerCase();
102
+ // Note: .ps1 shims are intentionally NOT handled here. The bin-resolution
103
+ // helpers (findGsdToolsBin / findInstallerBin) only ever surface a .cmd path
104
+ // on Windows — npm does not write .ps1 shims into .bin/ by default — so a
105
+ // .ps1 path never reaches this function in practice.
106
+ if (lower.endsWith('.cmd') || lower.endsWith('.bat')) {
107
+ // Quote the path if it contains a space so the Windows shell treats it as
108
+ // a single token. Simple double-quote wrap is sufficient because npm-
109
+ // generated shim paths don't contain embedded double-quotes.
110
+ const command = binPath.includes(' ') ? `"${binPath}"` : binPath;
111
+ return { command, args: [...args], shell: true };
112
+ }
113
+ // POSIX: invoke via node, no shell needed.
114
+ return { command: process.execPath, args: [binPath, ...args], shell: false };
115
+ }
116
+
117
+ // ---------------------------------------------------------------------------
118
+ // Internal helpers
119
+ // ---------------------------------------------------------------------------
120
+
121
+ /**
122
+ * Locate the lib/node_modules/@therocketcode/gsd-core package root inside
123
+ * an npm --prefix install directory.
124
+ */
125
+ function pkgRoot(installPrefix) {
126
+ // POSIX: <prefix>/lib/node_modules/<scope>/<pkg>
127
+ // Windows: <prefix>/node_modules/<scope>/<pkg>
128
+ // PACKAGE_NAME is scoped (@scope/pkg), so split('/') yields the two path segments.
129
+ const pkgSegments = PACKAGE_NAME.split('/');
130
+ const posix = path.join(installPrefix, 'lib', 'node_modules', ...pkgSegments);
131
+ const win = path.join(installPrefix, 'node_modules', ...pkgSegments);
132
+ return fs.existsSync(posix) ? posix : win;
133
+ }
134
+
135
+ /**
136
+ * Return the ordered list of candidate paths to check when locating an npm
137
+ * global bin named `name` under `installPrefix`.
138
+ *
139
+ * On Windows, `npm install -g --prefix X` writes shims (*.cmd, *.ps1, bare)
140
+ * to the PREFIX ROOT (X\), NOT to X\node_modules\.bin\. We therefore probe
141
+ * the prefix root first, then fall back to node_modules\.bin in case a
142
+ * non-standard layout puts them there.
143
+ *
144
+ * On POSIX the shim lands in <prefix>/bin/ as a symlink; only one candidate.
145
+ */
146
+ function binCandidates(installPrefix, name) {
147
+ if (process.platform === 'win32') {
148
+ return [
149
+ // npm global --prefix on Windows writes shims to the prefix ROOT
150
+ path.join(installPrefix, `${name}.cmd`),
151
+ path.join(installPrefix, name),
152
+ // fallback: some layouts use node_modules/.bin
153
+ path.join(installPrefix, 'node_modules', '.bin', `${name}.cmd`),
154
+ path.join(installPrefix, 'node_modules', '.bin', name),
155
+ ];
156
+ }
157
+ return [path.join(installPrefix, 'bin', name)];
158
+ }
159
+
160
+ /**
161
+ * Locate the installed gsd-tools binary (symlink in <prefix>/bin/).
162
+ */
163
+ function findGsdToolsBin(installPrefix) {
164
+ for (const c of binCandidates(installPrefix, 'gsd-tools')) {
165
+ if (fs.existsSync(c)) return c;
166
+ }
167
+ return null;
168
+ }
169
+
170
+ /**
171
+ * Locate the gsd-core installer binary (the symlink in <prefix>/bin/).
172
+ */
173
+ function findInstallerBin(installPrefix) {
174
+ for (const c of binCandidates(installPrefix, 'gsd-core')) {
175
+ if (fs.existsSync(c)) return c;
176
+ }
177
+ return null;
178
+ }
179
+
180
+ /**
181
+ * Parse a command .md file and return the first workflow path it references.
182
+ *
183
+ * Structured parser — only inspects individual lines; never regexes on the
184
+ * whole-file string. Two recognised forms (in priority order):
185
+ *
186
+ * 1. @-import line: `@~/.claude/gsd-core/workflows/<name>.md`
187
+ * 2. Inline mention: any line containing `~/.claude/gsd-core/workflows/<name>.md`
188
+ * (takes the LAST occurrence so conditional-dispatch files resolve to the
189
+ * default / unconditional branch, e.g. discuss-phase.md)
190
+ *
191
+ * Returns the bare workflow filename (e.g. `"discuss-phase.md"`) or null.
192
+ */
193
+ function parseWorkflowRef(mdContent) {
194
+ const WORKFLOW_PREFIX = 'gsd-core/workflows/';
195
+ let atImportResult = null;
196
+ let lastInlineResult = null;
197
+
198
+ const lines = mdContent.split(/\r?\n/);
199
+ for (const line of lines) {
200
+ const trimmed = line.trim();
201
+
202
+ // Form 1: @-import
203
+ if (trimmed.startsWith('@') && trimmed.includes(WORKFLOW_PREFIX)) {
204
+ const idx = trimmed.indexOf(WORKFLOW_PREFIX);
205
+ const rest = trimmed.slice(idx + WORKFLOW_PREFIX.length);
206
+ // rest is like "discuss-phase.md" or "discuss-phase.md end-to-end."
207
+ const name = rest.split(/[\s`"]/)[0];
208
+ if (name.endsWith('.md')) {
209
+ atImportResult = name;
210
+ break; // @-imports are authoritative; stop on first
211
+ }
212
+ }
213
+
214
+ // Form 2: inline mention (collect last)
215
+ if (trimmed.includes(WORKFLOW_PREFIX)) {
216
+ const idx = trimmed.indexOf(WORKFLOW_PREFIX);
217
+ const rest = trimmed.slice(idx + WORKFLOW_PREFIX.length);
218
+ const name = rest.split(/[\s`"]/)[0];
219
+ if (name.endsWith('.md')) {
220
+ lastInlineResult = name;
221
+ }
222
+ }
223
+ }
224
+
225
+ return atImportResult !== null ? atImportResult : lastInlineResult;
226
+ }
227
+
228
+ /**
229
+ * Read the list of known GSD command names from the installed package.
230
+ * Returns an array of strings like `['init', 'discuss-phase', ...]`.
231
+ */
232
+ function readInstalledCmdNames(pkg) {
233
+ const commandsDir = path.join(pkg, 'commands', 'gsd');
234
+ if (!fs.existsSync(commandsDir)) return [];
235
+ return fs.readdirSync(commandsDir)
236
+ .filter((f) => f.endsWith('.md'))
237
+ .map((f) => f.slice(0, -3)); // strip .md
238
+ }
239
+
240
+ /**
241
+ * Scan a single workflow .md file for /gsd:<cmd> colon-namespace leaks.
242
+ *
243
+ * Uses the word-boundary-safe regex shape from scripts/fix-slash-commands.cjs:
244
+ * /gsd-(<cmd1>|<cmd2>|...)(?=[^a-zA-Z0-9_-]|$)/g — forward
245
+ * We check the colon form: /gsd:<cmd> leaking in installed workflow bodies.
246
+ *
247
+ * Returns the first leaking { line, lineNumber } or null.
248
+ */
249
+ function scanWorkflowColonLeak(filePath, cmdNames) {
250
+ if (!cmdNames || cmdNames.length === 0) return null;
251
+ const sorted = [...cmdNames].sort((a, b) => b.length - a.length);
252
+ const pattern = new RegExp(`/gsd:(${sorted.join('|')})(?=[^a-zA-Z0-9_-]|$)`, 'g');
253
+
254
+ const content = fs.readFileSync(filePath, 'utf-8');
255
+ const lines = content.split(/\r?\n/);
256
+ for (let i = 0; i < lines.length; i++) {
257
+ pattern.lastIndex = 0;
258
+ if (pattern.test(lines[i])) {
259
+ return { line: i + 1, content: lines[i].trim() };
260
+ }
261
+ }
262
+ return null;
263
+ }
264
+
265
+ // ---------------------------------------------------------------------------
266
+ // Pure function: runSmoke
267
+ // ---------------------------------------------------------------------------
268
+
269
+ /**
270
+ * @param {object} opts
271
+ * @param {string} opts.tarballPath - Absolute path to a pre-packed .tgz
272
+ * @param {string} opts.installPrefix - Temp directory to use as npm --prefix
273
+ * @param {string} opts.expectedVersion - semver string to assert (e.g. "1.50.0")
274
+ * @param {string} [opts.fixtureDir] - Temp dir to run `init` into (must NOT be HOME)
275
+ * @param {string[]} [opts.lifecycleCommands] - Commands to file-check (default: see below)
276
+ * @param {boolean} [opts.dryRun=false] - If true, skip actual npm install; validate input only
277
+ * @param {object} [opts.npmEnv] - Optional env dict for the internal npm install
278
+ * spawnSync call. Pass an isolated HOME env (e.g. from isolatedNpmEnv() in tests/helpers.cjs)
279
+ * to prevent npm from reading/writing the caller's $HOME — required on Docker hosts where HOME
280
+ * may be unwritable. Defaults to process.env. (#131)
281
+ * @returns {{ code: string, details: object }}
282
+ */
283
+ function runSmoke({
284
+ tarballPath,
285
+ installPrefix,
286
+ expectedVersion,
287
+ fixtureDir,
288
+ lifecycleCommands = ['init', 'discuss-phase', 'plan-phase', 'execute-phase'],
289
+ dryRun = false,
290
+ npmEnv = undefined,
291
+ }) {
292
+ const details = {
293
+ tarball: tarballPath,
294
+ prefix: installPrefix,
295
+ expectedVersion,
296
+ };
297
+
298
+ if (dryRun) {
299
+ return { code: SMOKE.OK, details: { ...details, version: expectedVersion, dryRun: true } };
300
+ }
301
+
302
+ // --- Install the tarball into the temp prefix ----------------------------
303
+ const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
304
+ // Use the caller-supplied npmEnv if provided (allows HOME isolation on Docker
305
+ // hosts where HOME may be unwritable — same pattern as runNpm() in helpers.cjs).
306
+ // Falls back to process.env to preserve existing CLI / programmatic behaviour. (#131)
307
+ const effectiveNpmEnv = npmEnv !== undefined ? npmEnv : process.env;
308
+ const installResult = spawnSync(
309
+ npmCmd,
310
+ ['install', '-g', '--prefix', installPrefix, tarballPath],
311
+ { encoding: 'utf-8', shell: process.platform === 'win32', timeout: CHILD_TIMEOUT_MS, env: effectiveNpmEnv },
312
+ );
313
+
314
+ if (installResult.status !== 0) {
315
+ return {
316
+ code: SMOKE.INSTALL_FAILED,
317
+ details: {
318
+ ...details,
319
+ stderr: installResult.stderr,
320
+ stdout: installResult.stdout,
321
+ // Expose signal + error so a timeout (status=null, signal='SIGTERM',
322
+ // stdout='', stderr='') is immediately diagnosable in CI logs.
323
+ signal: installResult.signal ?? null,
324
+ installError: installResult.error ? String(installResult.error) : null,
325
+ },
326
+ };
327
+ }
328
+
329
+ // --- Locate the installed gsd-tools binary --------------------------------
330
+ const actualBin = findGsdToolsBin(installPrefix);
331
+
332
+ if (!actualBin) {
333
+ const searched = binCandidates(installPrefix, 'gsd-tools');
334
+ return {
335
+ code: SMOKE.BIN_NOT_CALLABLE,
336
+ details: { ...details, searched },
337
+ };
338
+ }
339
+
340
+ // --- Invoke `gsd-tools --help` to assert the shipped binary is callable ---
341
+ // Use effectiveNpmEnv so the installed binary sees an isolated HOME on Docker
342
+ // hosts where HOME may be unwritable (same isolation as the npm install). (#131)
343
+ const versionInvocation = binInvocation(actualBin, ['--help']);
344
+ const versionResult = spawnSync(
345
+ versionInvocation.command,
346
+ versionInvocation.args,
347
+ { encoding: 'utf-8', timeout: CHILD_TIMEOUT_MS, env: effectiveNpmEnv, shell: versionInvocation.shell },
348
+ );
349
+
350
+ if (versionResult.status !== 0) {
351
+ return {
352
+ code: SMOKE.BIN_NOT_CALLABLE,
353
+ details: {
354
+ ...details,
355
+ bin: actualBin,
356
+ stderr: versionResult.stderr,
357
+ stdout: versionResult.stdout,
358
+ },
359
+ };
360
+ }
361
+
362
+ // Source of truth for shipped version is the installed package.json.
363
+ const installedPkgPath = path.join(pkgRoot(installPrefix), 'package.json');
364
+ const installedPkg = JSON.parse(fs.readFileSync(installedPkgPath, 'utf-8'));
365
+ const installedVersion = String(installedPkg.version || '').trim();
366
+
367
+ details.version = installedVersion;
368
+ details.bin = actualBin;
369
+ details.installedPackageJson = installedPkgPath;
370
+
371
+ if (installedVersion !== expectedVersion) {
372
+ return {
373
+ code: SMOKE.VERSION_MISMATCH,
374
+ details: { ...details, installedVersion, expectedVersion },
375
+ };
376
+ }
377
+
378
+ // ─────────────────────────────────────────────────────────────────────────
379
+ // Cycle 2: lifecycle command file-resolution checks
380
+ // ─────────────────────────────────────────────────────────────────────────
381
+
382
+ const pkg = pkgRoot(installPrefix);
383
+ const shouldRunInit = lifecycleCommands.includes('init');
384
+ const commandsToCheck = lifecycleCommands.filter((c) => c !== 'init');
385
+
386
+ // --- Run init if requested -----------------------------------------------
387
+ if (shouldRunInit && fixtureDir) {
388
+ const installerBin = findInstallerBin(installPrefix);
389
+ if (!installerBin) {
390
+ return {
391
+ code: SMOKE.INIT_FAILED,
392
+ details: {
393
+ ...details,
394
+ reason: 'gsd-core binary not found in installPrefix',
395
+ installPrefix,
396
+ },
397
+ };
398
+ }
399
+
400
+ // Non-interactive: --local --claude installs to .claude/ in cwd (fixtureDir).
401
+ // GSD_TEST_MODE must be cleared — install.js skips its main() block when
402
+ // GSD_TEST_MODE is set, which would cause the installer to exit 0 silently
403
+ // without actually creating any files.
404
+ const initEnv = { ...process.env };
405
+ delete initEnv.GSD_TEST_MODE;
406
+
407
+ const initInvocation = binInvocation(installerBin, ['--local', '--claude']);
408
+ const initResult = spawnSync(
409
+ initInvocation.command,
410
+ initInvocation.args,
411
+ {
412
+ encoding: 'utf-8',
413
+ cwd: fixtureDir,
414
+ // Ensure no TTY so the installer's non-interactive fallback fires
415
+ stdio: ['pipe', 'pipe', 'pipe'],
416
+ env: initEnv,
417
+ timeout: CHILD_TIMEOUT_MS,
418
+ shell: initInvocation.shell,
419
+ },
420
+ );
421
+
422
+ if (initResult.status !== 0) {
423
+ return {
424
+ code: SMOKE.INIT_FAILED,
425
+ details: {
426
+ ...details,
427
+ fixtureDir,
428
+ stderr: initResult.stderr,
429
+ stdout: initResult.stdout,
430
+ },
431
+ };
432
+ }
433
+
434
+ // Verify expected dirs were created
435
+ const expectedDirs = [
436
+ path.join(fixtureDir, '.claude', 'commands'),
437
+ path.join(fixtureDir, '.claude', 'gsd-core'),
438
+ ];
439
+ for (const dir of expectedDirs) {
440
+ if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
441
+ return {
442
+ code: SMOKE.INIT_FAILED,
443
+ details: {
444
+ ...details,
445
+ fixtureDir,
446
+ reason: `expected dir not created: ${dir}`,
447
+ },
448
+ };
449
+ }
450
+ }
451
+ }
452
+
453
+ // --- Check command files and workflow references -------------------------
454
+ const lifecycleResolved = [];
455
+
456
+ for (const cmd of commandsToCheck) {
457
+ const cmdFilePath = path.join(pkg, 'commands', 'gsd', `${cmd}.md`);
458
+
459
+ if (!fs.existsSync(cmdFilePath) || !fs.statSync(cmdFilePath).isFile()) {
460
+ return {
461
+ code: SMOKE.COMMAND_FILE_MISSING,
462
+ details: {
463
+ ...details,
464
+ command: cmd,
465
+ path: cmdFilePath,
466
+ },
467
+ };
468
+ }
469
+
470
+ // Parse workflow reference
471
+ const mdContent = fs.readFileSync(cmdFilePath, 'utf-8');
472
+ const workflowName = parseWorkflowRef(mdContent);
473
+
474
+ let workflowPath = null;
475
+ if (workflowName) {
476
+ // Workflow files live at gsd-core/workflows/<name> in the package.
477
+ // Some live in subdirectories; try flat first then scan once.
478
+ const flat = path.join(pkg, 'gsd-core', 'workflows', workflowName);
479
+ workflowPath = fs.existsSync(flat) ? flat : null;
480
+
481
+ if (!workflowPath) {
482
+ return {
483
+ code: SMOKE.WORKFLOW_FILE_MISSING,
484
+ details: {
485
+ ...details,
486
+ command: cmd,
487
+ path: flat,
488
+ },
489
+ };
490
+ }
491
+ }
492
+
493
+ lifecycleResolved.push({
494
+ command: cmd,
495
+ commandPath: cmdFilePath,
496
+ workflowPath,
497
+ });
498
+ }
499
+
500
+ details.lifecycleResolved = lifecycleResolved;
501
+
502
+ // ─────────────────────────────────────────────────────────────────────────
503
+ // Cycle 3: workflow-body validation (informational)
504
+ // ─────────────────────────────────────────────────────────────────────────
505
+
506
+ // --- Workflow-body checks (informational — #3668 not yet fixed) ----------
507
+ const workflowsDir = path.join(pkg, 'gsd-core', 'workflows');
508
+ const installedCmdNames = readInstalledCmdNames(pkg);
509
+
510
+ let workflowsScanned = 0;
511
+ let colonLeakCount = 0;
512
+ // Store first finding for potential future enforcement mode.
513
+ let firstColonLeak = null;
514
+
515
+ if (fs.existsSync(workflowsDir)) {
516
+ // Collect all .md files (flat only — subdirs contain sub-workflows that
517
+ // follow the same contract, but the top-level .md files are the primary surface)
518
+ const entries = fs.readdirSync(workflowsDir, { withFileTypes: true });
519
+ for (const entry of entries) {
520
+ if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
521
+ const filePath = path.join(workflowsDir, entry.name);
522
+ workflowsScanned++;
523
+
524
+ const leak = scanWorkflowColonLeak(filePath, installedCmdNames);
525
+ if (leak) {
526
+ colonLeakCount++;
527
+ if (!firstColonLeak) {
528
+ firstColonLeak = { file: filePath, line: leak.line };
529
+ }
530
+ }
531
+
532
+ }
533
+ }
534
+
535
+ details.workflowsScanned = workflowsScanned;
536
+ details.colonLeakCount = colonLeakCount;
537
+ if (firstColonLeak) details.firstColonLeak = firstColonLeak;
538
+
539
+ // NOTE: colonLeakCount is informational here. Once the backlog is fixed,
540
+ // a future enforcement mode can fail on non-zero counts.
541
+
542
+ return { code: SMOKE.OK, details };
543
+ }
544
+
545
+ // ---------------------------------------------------------------------------
546
+ // CLI entry
547
+ // ---------------------------------------------------------------------------
548
+
549
+ function cliMain() {
550
+ const args = process.argv.slice(2);
551
+ const isJson = args.includes('--json');
552
+
553
+ const pkgPath = path.join(__dirname, '..', 'package.json');
554
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
555
+ const expectedVersion = process.env.SMOKE_FORCE_EXPECTED_VERSION || pkg.version;
556
+
557
+ // Pack the working tree into a temp directory
558
+ const packDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-smoke-pack-'));
559
+ const installPrefix = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-smoke-prefix-'));
560
+ const fixtureDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-smoke-fixture-'));
561
+
562
+ let tarballPath;
563
+ try {
564
+ const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
565
+ const packOutput = execFileSync(
566
+ npmCmd,
567
+ ['pack', '--pack-destination', packDir],
568
+ {
569
+ cwd: path.join(__dirname, '..'),
570
+ encoding: 'utf-8',
571
+ shell: process.platform === 'win32',
572
+ timeout: CHILD_TIMEOUT_MS,
573
+ },
574
+ ).trim();
575
+ // npm pack outputs the filename on stdout (last line when verbose)
576
+ const lines = packOutput.split(/\r?\n/).filter(Boolean);
577
+ const tgzName = lines[lines.length - 1];
578
+ tarballPath = path.join(packDir, tgzName);
579
+ if (!fs.existsSync(tarballPath)) {
580
+ // npm 7+ may print just the filename without .tgz extension on some platforms
581
+ const found = fs.readdirSync(packDir).find((f) => f.endsWith('.tgz'));
582
+ if (found) {
583
+ tarballPath = path.join(packDir, found);
584
+ } else {
585
+ const result = {
586
+ code: SMOKE.PACK_FAILED,
587
+ details: { packDir, packOutput, reason: 'no .tgz in pack destination' },
588
+ };
589
+ if (isJson) process.stdout.write(JSON.stringify(result) + '\n');
590
+ cleanup(packDir, installPrefix, fixtureDir);
591
+ throw new ExitError(1);
592
+ }
593
+ }
594
+ } catch (err) {
595
+ if (err instanceof ExitError) throw err;
596
+ const result = {
597
+ code: SMOKE.PACK_FAILED,
598
+ details: { error: err.message, stderr: err.stderr },
599
+ };
600
+ if (isJson) process.stdout.write(JSON.stringify(result) + '\n');
601
+ cleanup(packDir, installPrefix, fixtureDir);
602
+ throw new ExitError(1);
603
+ }
604
+
605
+ const result = runSmoke({ tarballPath, installPrefix, expectedVersion, fixtureDir });
606
+ if (isJson) process.stdout.write(JSON.stringify(result) + '\n');
607
+ cleanup(packDir, installPrefix, fixtureDir);
608
+ return result.code === SMOKE.OK ? 0 : 1;
609
+ }
610
+
611
+ function cleanup(...dirs) {
612
+ for (const dir of dirs) {
613
+ try {
614
+ fs.rmSync(dir, { recursive: true, force: true });
615
+ } catch {
616
+ // best-effort
617
+ }
618
+ }
619
+ }
620
+
621
+ // ---------------------------------------------------------------------------
622
+ // Exports
623
+ // ---------------------------------------------------------------------------
624
+
625
+ module.exports = { SMOKE, runSmoke, binInvocation };
626
+
627
+ if (require.main === module) {
628
+ runMain(cliMain);
629
+ }