@opengsd/gsd-core 1.12.0 → 1.14.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 (455) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.opencode/plugins/gsd-core.js +12 -0
  4. package/agents/gsd-advisor-researcher.compact.md +85 -0
  5. package/agents/gsd-ai-researcher.compact.md +96 -0
  6. package/agents/gsd-assumptions-analyzer.compact.md +81 -0
  7. package/agents/gsd-code-fixer.compact.md +458 -0
  8. package/agents/gsd-code-fixer.md +5 -5
  9. package/agents/gsd-code-reviewer.compact.md +269 -0
  10. package/agents/gsd-code-reviewer.md +15 -3
  11. package/agents/gsd-codebase-mapper.compact.md +760 -0
  12. package/agents/gsd-debug-session-manager.compact.md +345 -0
  13. package/agents/gsd-doc-classifier.compact.md +192 -0
  14. package/agents/gsd-doc-synthesizer.compact.md +200 -0
  15. package/agents/gsd-doc-verifier.compact.md +143 -0
  16. package/agents/gsd-doc-writer.compact.md +440 -0
  17. package/agents/gsd-dom-verifier.compact.md +138 -0
  18. package/agents/gsd-domain-researcher.compact.md +141 -0
  19. package/agents/gsd-eval-auditor.compact.md +160 -0
  20. package/agents/gsd-eval-planner.compact.md +137 -0
  21. package/agents/gsd-executor.md +63 -35
  22. package/agents/gsd-framework-selector.compact.md +82 -0
  23. package/agents/gsd-integration-checker.compact.md +245 -0
  24. package/agents/gsd-intel-updater.compact.md +226 -0
  25. package/agents/gsd-mempalace-curator.compact.md +45 -0
  26. package/agents/gsd-nyquist-auditor.compact.md +179 -0
  27. package/agents/gsd-pattern-mapper.compact.md +275 -0
  28. package/agents/gsd-plan-checker.md +76 -57
  29. package/agents/gsd-planner.md +14 -0
  30. package/agents/gsd-project-researcher.compact.md +587 -0
  31. package/agents/gsd-research-synthesizer.compact.md +212 -0
  32. package/agents/gsd-roadmapper.compact.md +454 -0
  33. package/agents/gsd-roadmapper.md +13 -0
  34. package/agents/gsd-security-auditor.compact.md +162 -0
  35. package/agents/gsd-ui-auditor.compact.md +404 -0
  36. package/agents/gsd-ui-checker.compact.md +277 -0
  37. package/agents/gsd-ui-checker.md +19 -3
  38. package/agents/gsd-ui-researcher.compact.md +282 -0
  39. package/agents/gsd-ui-researcher.md +29 -0
  40. package/agents/gsd-user-profiler.compact.md +108 -0
  41. package/agents/gsd-verifier.md +23 -1
  42. package/bin/install.js +444 -134
  43. package/commands/gsd/cleanup.md +1 -0
  44. package/commands/gsd/code-review.md +2 -1
  45. package/commands/gsd/complete-milestone.md +1 -0
  46. package/commands/gsd/config.md +1 -0
  47. package/commands/gsd/debug.md +1 -0
  48. package/commands/gsd/execute-phase.md +1 -1
  49. package/commands/gsd/graphify.md +1 -0
  50. package/commands/gsd/health.md +1 -0
  51. package/commands/gsd/mempalace-capture.md +1 -0
  52. package/commands/gsd/mempalace-recall.md +1 -0
  53. package/commands/gsd/new-milestone.md +1 -0
  54. package/commands/gsd/new-project.md +1 -0
  55. package/commands/gsd/next.md +1 -0
  56. package/commands/gsd/ns-workflow.md +2 -1
  57. package/commands/gsd/pause-work.md +1 -0
  58. package/commands/gsd/phase.md +2 -1
  59. package/commands/gsd/pr-branch.md +1 -0
  60. package/commands/gsd/quick-batch.md +105 -0
  61. package/commands/gsd/resume-work.md +1 -0
  62. package/commands/gsd/review-backlog.md +1 -0
  63. package/commands/gsd/settings.md +2 -1
  64. package/commands/gsd/stats.md +1 -0
  65. package/commands/gsd/surface.md +18 -8
  66. package/commands/gsd/thread.md +1 -0
  67. package/commands/gsd/workspace.md +1 -0
  68. package/commands/gsd/workstreams.md +1 -0
  69. package/gsd-core/bin/check-latest-version.cjs +8 -3
  70. package/gsd-core/bin/gsd-tools.cjs +532 -174
  71. package/gsd-core/bin/lib/adr-parser.cjs +1 -1
  72. package/gsd-core/bin/lib/artifacts.cjs +2 -1
  73. package/gsd-core/bin/lib/audit.cjs +39 -22
  74. package/gsd-core/bin/lib/broken-windows.cjs +168 -49
  75. package/gsd-core/bin/lib/capability-activation.cjs +27 -0
  76. package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
  77. package/gsd-core/bin/lib/capability-loader.cjs +135 -1
  78. package/gsd-core/bin/lib/capability-registry.cjs +528 -116
  79. package/gsd-core/bin/lib/capability-source.cjs +19 -2
  80. package/gsd-core/bin/lib/capability-state.cjs +7 -1
  81. package/gsd-core/bin/lib/capability-validator.cjs +134 -5
  82. package/gsd-core/bin/lib/capability-writer.cjs +14 -4
  83. package/gsd-core/bin/lib/check-command-router.cjs +198 -38
  84. package/gsd-core/bin/lib/claude-orchestration.cjs +10 -25
  85. package/gsd-core/bin/lib/clusters.cjs +1 -0
  86. package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
  87. package/gsd-core/bin/lib/command-aliases.cjs +16 -0
  88. package/gsd-core/bin/lib/commands.cjs +981 -79
  89. package/gsd-core/bin/lib/config-loader.cjs +4 -0
  90. package/gsd-core/bin/lib/config.cjs +153 -38
  91. package/gsd-core/bin/lib/core-utils.cjs +34 -7
  92. package/gsd-core/bin/lib/coverage.cjs +1 -1
  93. package/gsd-core/bin/lib/decisions.cjs +343 -28
  94. package/gsd-core/bin/lib/edge-probe.cjs +14 -1
  95. package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
  96. package/gsd-core/bin/lib/file-overlap-partitioner.cjs +74 -0
  97. package/gsd-core/bin/lib/frontmatter.cjs +137 -23
  98. package/gsd-core/bin/lib/gap-checker.cjs +22 -13
  99. package/gsd-core/bin/lib/git-base-branch.cjs +10 -2
  100. package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
  101. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +8 -2
  102. package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +54 -11
  103. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +87 -23
  104. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
  105. package/gsd-core/bin/lib/host-integration.cjs +57 -5
  106. package/gsd-core/bin/lib/init-command-router.cjs +14 -0
  107. package/gsd-core/bin/lib/init.cjs +539 -60
  108. package/gsd-core/bin/lib/install-engine.cjs +199 -14
  109. package/gsd-core/bin/lib/install-model-override-resolver.cjs +45 -0
  110. package/gsd-core/bin/lib/install-profiles.cjs +36 -14
  111. package/gsd-core/bin/lib/installer-migration-report.cjs +1 -0
  112. package/gsd-core/bin/lib/installer-migrations.cjs +33 -4
  113. package/gsd-core/bin/lib/io.cjs +35 -0
  114. package/gsd-core/bin/lib/loop-resolver.cjs +64 -39
  115. package/gsd-core/bin/lib/markdown-table.cjs +123 -0
  116. package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
  117. package/gsd-core/bin/lib/milestone.cjs +41 -10
  118. package/gsd-core/bin/lib/model-resolver.cjs +101 -10
  119. package/gsd-core/bin/lib/phase-command-router.cjs +20 -7
  120. package/gsd-core/bin/lib/phase-id.cjs +412 -31
  121. package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
  122. package/gsd-core/bin/lib/phase.cjs +941 -98
  123. package/gsd-core/bin/lib/plan-document.cjs +10 -0
  124. package/gsd-core/bin/lib/planning-inspect.cjs +34 -18
  125. package/gsd-core/bin/lib/planning-snapshot.cjs +206 -30
  126. package/gsd-core/bin/lib/planning-workspace.cjs +153 -29
  127. package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
  128. package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
  129. package/gsd-core/bin/lib/quick-batch-command-router.cjs +285 -0
  130. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +250 -0
  131. package/gsd-core/bin/lib/quick-batch.cjs +840 -0
  132. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
  133. package/gsd-core/bin/lib/research-store.cjs +11 -12
  134. package/gsd-core/bin/lib/review-lane-descriptor.cjs +53 -5
  135. package/gsd-core/bin/lib/review-lane-invocation.cjs +96 -1
  136. package/gsd-core/bin/lib/review-lane-runner.cjs +136 -10
  137. package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
  138. package/gsd-core/bin/lib/roadmap-parser.cjs +555 -41
  139. package/gsd-core/bin/lib/roadmap.cjs +292 -69
  140. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +260 -43
  141. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +28 -20
  142. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +294 -108
  143. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +408 -47
  144. package/gsd-core/bin/lib/security.cjs +126 -7
  145. package/gsd-core/bin/lib/shell-command-projection.cjs +4 -0
  146. package/gsd-core/bin/lib/smart-entry.cjs +7 -9
  147. package/gsd-core/bin/lib/state-document.cjs +159 -32
  148. package/gsd-core/bin/lib/state-md-schema.cjs +44 -27
  149. package/gsd-core/bin/lib/state-transition.cjs +465 -62
  150. package/gsd-core/bin/lib/state.cjs +906 -151
  151. package/gsd-core/bin/lib/surface.cjs +83 -10
  152. package/gsd-core/bin/lib/task-command-router.cjs +12 -6
  153. package/gsd-core/bin/lib/tdd-red-evidence.cjs +133 -0
  154. package/gsd-core/bin/lib/uat.cjs +1420 -516
  155. package/gsd-core/bin/lib/update-context.cjs +36 -26
  156. package/gsd-core/bin/lib/validate.cjs +230 -12
  157. package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
  158. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  159. package/gsd-core/bin/lib/verification.cjs +316 -23
  160. package/gsd-core/bin/lib/verify-command-grounding.cjs +1 -1
  161. package/gsd-core/bin/lib/verify-command-router.cjs +1 -0
  162. package/gsd-core/bin/lib/verify.cjs +531 -36
  163. package/gsd-core/bin/lib/workstream-inventory.cjs +21 -2
  164. package/gsd-core/bin/lib/worktree-safety.cjs +21 -7
  165. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  166. package/gsd-core/bin/shared/config-schema.manifest.json +13 -0
  167. package/gsd-core/bin/verify-reapply-patches.cjs +507 -81
  168. package/gsd-core/references/agent-contracts.md +3 -3
  169. package/gsd-core/references/compact-content-gate.md +66 -0
  170. package/gsd-core/references/edge-probe.md +17 -13
  171. package/gsd-core/references/execute-mvp-tdd.md +18 -16
  172. package/gsd-core/references/execute-phase-response-language.md +6 -0
  173. package/gsd-core/references/executor-examples.md +42 -0
  174. package/gsd-core/references/few-shot-examples/plan-checker.md +15 -15
  175. package/gsd-core/references/loop-hook-dispatch.md +18 -0
  176. package/gsd-core/references/model-profiles.md +12 -3
  177. package/gsd-core/references/mvp-concepts.md +2 -2
  178. package/gsd-core/references/plan-checker-examples.md +41 -0
  179. package/gsd-core/references/planner-antipatterns.md +25 -0
  180. package/gsd-core/references/planner-chunked.md +5 -1
  181. package/gsd-core/references/planner-coupling.md +42 -0
  182. package/gsd-core/references/planner-quick-batch.md +71 -0
  183. package/gsd-core/references/planner-reviews.md +47 -0
  184. package/gsd-core/references/planner-revision.md +75 -2
  185. package/gsd-core/references/planning-config.md +5 -1
  186. package/gsd-core/references/response-language-directive.md +9 -0
  187. package/gsd-core/references/revision-loop.md +118 -11
  188. package/gsd-core/references/tdd.md +17 -9
  189. package/gsd-core/references/thinking-models-planning.md +18 -2
  190. package/gsd-core/references/verification-patterns.md +17 -4
  191. package/gsd-core/references/verifier-evidence-gate.md +160 -0
  192. package/gsd-core/references/worktree-path-safety.md +112 -2
  193. package/gsd-core/templates/README.md +7 -1
  194. package/gsd-core/templates/phase-prompt.md +4 -0
  195. package/gsd-core/templates/state.md +6 -3
  196. package/gsd-core/templates/summary.compact.md +212 -0
  197. package/gsd-core/templates/user-setup.compact.md +199 -0
  198. package/gsd-core/templates/user-setup.md +0 -9
  199. package/gsd-core/templates/verification-report.md +5 -0
  200. package/gsd-core/workflows/add-backlog.md +2 -0
  201. package/gsd-core/workflows/add-phase.md +2 -0
  202. package/gsd-core/workflows/add-tests.md +1 -1
  203. package/gsd-core/workflows/add-todo.md +4 -3
  204. package/gsd-core/workflows/ai-integration-phase.md +1 -1
  205. package/gsd-core/workflows/analyze-dependencies.md +2 -0
  206. package/gsd-core/workflows/audit-fix.md +2 -0
  207. package/gsd-core/workflows/audit-milestone.md +2 -0
  208. package/gsd-core/workflows/audit-uat.md +2 -0
  209. package/gsd-core/workflows/autonomous.md +15 -10
  210. package/gsd-core/workflows/check-todos.md +5 -3
  211. package/gsd-core/workflows/cleanup.md +4 -2
  212. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +22 -13
  213. package/gsd-core/workflows/code-review-fix.md +5 -3
  214. package/gsd-core/workflows/code-review.md +211 -43
  215. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
  216. package/gsd-core/workflows/complete-milestone.md +40 -254
  217. package/gsd-core/workflows/debug.md +1 -1
  218. package/gsd-core/workflows/diagnose-issues.md +5 -1
  219. package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -0
  220. package/gsd-core/workflows/discuss-phase/modes/all.md +2 -0
  221. package/gsd-core/workflows/discuss-phase/modes/analyze.md +2 -0
  222. package/gsd-core/workflows/discuss-phase/modes/auto.md +2 -0
  223. package/gsd-core/workflows/discuss-phase/modes/batch.md +2 -0
  224. package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -0
  225. package/gsd-core/workflows/discuss-phase/modes/default.md +2 -0
  226. package/gsd-core/workflows/discuss-phase/modes/power.md +2 -0
  227. package/gsd-core/workflows/discuss-phase/modes/text.md +2 -0
  228. package/gsd-core/workflows/discuss-phase/templates/context.md +2 -0
  229. package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +2 -0
  230. package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
  231. package/gsd-core/workflows/discuss-phase-power.md +2 -0
  232. package/gsd-core/workflows/discuss-phase.md +1 -1
  233. package/gsd-core/workflows/do.md +43 -13
  234. package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
  235. package/gsd-core/workflows/docs-update.md +15 -156
  236. package/gsd-core/workflows/edit-phase.md +2 -0
  237. package/gsd-core/workflows/eval-review.md +1 -1
  238. package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
  239. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +20 -3
  240. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
  241. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +24 -3
  242. package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
  243. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +8 -2
  244. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -0
  245. package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
  246. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +25 -0
  247. package/gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md +2 -0
  248. package/gsd-core/workflows/execute-phase.md +78 -159
  249. package/gsd-core/workflows/execute-plan.md +28 -15
  250. package/gsd-core/workflows/explore.md +2 -0
  251. package/gsd-core/workflows/extract-learnings.md +2 -0
  252. package/gsd-core/workflows/fast.md +6 -0
  253. package/gsd-core/workflows/forensics.md +2 -0
  254. package/gsd-core/workflows/graduation.md +1 -1
  255. package/gsd-core/workflows/health.md +1 -1
  256. package/gsd-core/workflows/help/modes/brief.md +2 -0
  257. package/gsd-core/workflows/help/modes/default.md +2 -0
  258. package/gsd-core/workflows/help/modes/full.compact.md +398 -0
  259. package/gsd-core/workflows/help/modes/full.md +12 -0
  260. package/gsd-core/workflows/help/modes/topic.md +2 -0
  261. package/gsd-core/workflows/help.md +3 -1
  262. package/gsd-core/workflows/import.md +3 -3
  263. package/gsd-core/workflows/inbox.md +1 -1
  264. package/gsd-core/workflows/ingest-docs.md +1 -1
  265. package/gsd-core/workflows/insert-phase.md +2 -0
  266. package/gsd-core/workflows/list-phase-assumptions.md +2 -0
  267. package/gsd-core/workflows/list-seeds.md +2 -0
  268. package/gsd-core/workflows/list-workspaces.md +2 -0
  269. package/gsd-core/workflows/manager.md +3 -3
  270. package/gsd-core/workflows/map-codebase.md +52 -3
  271. package/gsd-core/workflows/milestone-summary.md +2 -0
  272. package/gsd-core/workflows/mvp-phase.md +1 -1
  273. package/gsd-core/workflows/new-milestone.md +55 -13
  274. package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
  275. package/gsd-core/workflows/new-project.md +37 -205
  276. package/gsd-core/workflows/new-workspace.md +1 -1
  277. package/gsd-core/workflows/next.md +2 -0
  278. package/gsd-core/workflows/node-repair.md +2 -0
  279. package/gsd-core/workflows/note.md +2 -0
  280. package/gsd-core/workflows/onboard.md +1 -1
  281. package/gsd-core/workflows/pause-work.md +19 -4
  282. package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
  283. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +100 -18
  284. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -0
  285. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +9 -0
  286. package/gsd-core/workflows/plan-phase.md +144 -185
  287. package/gsd-core/workflows/plan-review-convergence.md +102 -10
  288. package/gsd-core/workflows/plant-seed.md +1 -1
  289. package/gsd-core/workflows/pr-branch.md +30 -10
  290. package/gsd-core/workflows/profile-user.md +1 -1
  291. package/gsd-core/workflows/progress/steps/forensic-audit.md +1 -1
  292. package/gsd-core/workflows/progress.md +25 -3
  293. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +37 -2
  294. package/gsd-core/workflows/quick/steps/research-phase.md +3 -3
  295. package/gsd-core/workflows/quick-batch/steps/batch-init.md +55 -0
  296. package/gsd-core/workflows/quick-batch/steps/completion.md +65 -0
  297. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +100 -0
  298. package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +147 -0
  299. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +158 -0
  300. package/gsd-core/workflows/quick-batch/steps/research-phase.md +95 -0
  301. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +49 -0
  302. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +73 -0
  303. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +169 -0
  304. package/gsd-core/workflows/quick-batch.md +203 -0
  305. package/gsd-core/workflows/quick.md +21 -4
  306. package/gsd-core/workflows/reapply-patches.md +79 -3
  307. package/gsd-core/workflows/remove-phase.md +2 -0
  308. package/gsd-core/workflows/remove-workspace.md +1 -1
  309. package/gsd-core/workflows/resume-project.md +6 -2
  310. package/gsd-core/workflows/review.md +215 -10
  311. package/gsd-core/workflows/scan.md +2 -0
  312. package/gsd-core/workflows/section-manifest.json +12 -0
  313. package/gsd-core/workflows/secure-phase.md +1 -1
  314. package/gsd-core/workflows/session-report.md +2 -0
  315. package/gsd-core/workflows/settings-advanced.md +2 -0
  316. package/gsd-core/workflows/settings-integrations.md +9 -8
  317. package/gsd-core/workflows/settings.md +19 -6
  318. package/gsd-core/workflows/ship.md +10 -10
  319. package/gsd-core/workflows/sketch-wrap-up.md +2 -0
  320. package/gsd-core/workflows/sketch.md +1 -1
  321. package/gsd-core/workflows/smart-entry.md +1 -1
  322. package/gsd-core/workflows/spec-phase.md +24 -19
  323. package/gsd-core/workflows/spike-wrap-up.md +2 -0
  324. package/gsd-core/workflows/spike.md +1 -1
  325. package/gsd-core/workflows/stats.md +2 -0
  326. package/gsd-core/workflows/sync-skills.md +12 -4
  327. package/gsd-core/workflows/thread.md +2 -0
  328. package/gsd-core/workflows/transition.md +2 -0
  329. package/gsd-core/workflows/ui-phase.md +26 -5
  330. package/gsd-core/workflows/ui-review.md +1 -1
  331. package/gsd-core/workflows/ultraplan-phase.md +2 -0
  332. package/gsd-core/workflows/undo.md +1 -1
  333. package/gsd-core/workflows/update.md +48 -43
  334. package/gsd-core/workflows/validate-phase.md +1 -1
  335. package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
  336. package/gsd-core/workflows/verify-work.md +68 -182
  337. package/hooks/dist/gsd-agent-isolation-guard.js +42 -16
  338. package/hooks/dist/gsd-check-update-worker.js +19 -2
  339. package/hooks/dist/gsd-context-monitor.js +371 -27
  340. package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
  341. package/hooks/dist/gsd-node-runner.sh +1 -0
  342. package/hooks/dist/gsd-prompt-guard.js +30 -5
  343. package/hooks/dist/gsd-read-guard.js +2 -0
  344. package/hooks/dist/gsd-read-injection-scanner.js +5 -5
  345. package/hooks/dist/gsd-secret-read-guard.js +1105 -0
  346. package/hooks/dist/gsd-statusline.js +18 -10
  347. package/hooks/dist/gsd-validate-commit.sh +474 -7
  348. package/hooks/dist/gsd-workflow-guard.js +2 -1
  349. package/hooks/dist/gsd-worktree-path-guard.js +25 -14
  350. package/hooks/dist/gsd-write-guard.js +46 -1
  351. package/hooks/dist/lib/dispatch-identity.js +187 -0
  352. package/hooks/dist/lib/filename-classification.js +64 -0
  353. package/hooks/dist/lib/git-cmd.js +210 -1
  354. package/hooks/dist/lib/injection-patterns.js +36 -6
  355. package/hooks/dist/lib/isolation-deny-reason.js +53 -1
  356. package/hooks/dist/lib/isolation-sentinel.js +58 -19
  357. package/hooks/dist/managed-hooks-registry.cjs +1 -0
  358. package/hooks/gsd-agent-isolation-guard.js +42 -16
  359. package/hooks/gsd-check-update-worker.js +19 -2
  360. package/hooks/gsd-context-monitor.js +371 -27
  361. package/hooks/gsd-cursor-subagent-start.js +34 -14
  362. package/hooks/gsd-node-runner.sh +1 -0
  363. package/hooks/gsd-prompt-guard.js +30 -5
  364. package/hooks/gsd-read-guard.js +2 -0
  365. package/hooks/gsd-read-injection-scanner.js +5 -5
  366. package/hooks/gsd-secret-read-guard.js +1105 -0
  367. package/hooks/gsd-statusline.js +18 -10
  368. package/hooks/gsd-validate-commit.sh +474 -7
  369. package/hooks/gsd-workflow-guard.js +2 -1
  370. package/hooks/gsd-worktree-path-guard.js +25 -14
  371. package/hooks/gsd-write-guard.js +46 -1
  372. package/hooks/hooks.json +6 -0
  373. package/hooks/lib/dispatch-identity.js +187 -0
  374. package/hooks/lib/filename-classification.js +64 -0
  375. package/hooks/lib/git-cmd.js +210 -1
  376. package/hooks/lib/injection-patterns.js +36 -6
  377. package/hooks/lib/isolation-deny-reason.js +53 -1
  378. package/hooks/lib/isolation-sentinel.js +58 -19
  379. package/hooks/managed-hooks-registry.cjs +1 -0
  380. package/package.json +13 -9
  381. package/scripts/benchmark-compact-content-variants.cjs +298 -0
  382. package/scripts/benchmark-compact-content.cjs +368 -0
  383. package/scripts/build-hooks.js +11 -4
  384. package/scripts/check-contract-drift.cjs +4 -1
  385. package/scripts/check-env.cjs +36 -8
  386. package/scripts/check-glossary-refs.cjs +25 -21
  387. package/scripts/ci-next-health.cjs +271 -0
  388. package/scripts/ci-prepare-test-scope.cjs +7 -7
  389. package/scripts/ci-test-scope.cjs +133 -20
  390. package/scripts/ci-timeout-report.cjs +1 -1
  391. package/scripts/diff-touches-shipped-paths.cjs +1 -1
  392. package/scripts/docs-guard-registry.cjs +17 -2
  393. package/scripts/gen-adr-index.cjs +8 -2
  394. package/scripts/gen-inventory-manifest.cjs +12 -0
  395. package/scripts/gen-loop-host-contract.cjs +67 -15
  396. package/scripts/gen-platform-conformance-tier.cjs +557 -0
  397. package/scripts/lib/drift-scan.cjs +1 -1
  398. package/scripts/lib/macos-conformance-tier.generated.cjs +210 -0
  399. package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
  400. package/scripts/lib/platform-conformance-tier.generated.cjs +276 -0
  401. package/scripts/lib/shellcheck-fetch.cjs +247 -0
  402. package/scripts/lib/suite-detection.cjs +32 -0
  403. package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -6
  404. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
  405. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  406. package/scripts/lint-allowed-tools-parity.cjs +221 -0
  407. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +24 -2
  408. package/scripts/lint-phase-enumeration-drift.cjs +24 -6
  409. package/scripts/lint-phase-id-drift.cjs +465 -15
  410. package/scripts/lint-portable-grep.cjs +176 -0
  411. package/scripts/lint-response-language-coverage.cjs +530 -0
  412. package/scripts/lint-source-test-name-collision.cjs +1 -1
  413. package/scripts/lint-test-file-count.allowlist.json +4 -1
  414. package/scripts/lint-vendored-deps.cjs +128 -17
  415. package/scripts/lint-workflow-shellcheck-baseline.json +1112 -0
  416. package/scripts/lint-workflow-shellcheck.cjs +614 -0
  417. package/scripts/npm-audit-baseline.cjs +376 -0
  418. package/scripts/prompt-injection-scan.sh +22 -0
  419. package/scripts/require-issue-link-policy.cjs +16 -1
  420. package/scripts/workflow-size.cjs +139 -0
  421. package/skills/gsd-cleanup/SKILL.md +1 -0
  422. package/skills/gsd-code-review/SKILL.md +2 -1
  423. package/skills/gsd-complete-milestone/SKILL.md +1 -0
  424. package/skills/gsd-config/SKILL.md +1 -0
  425. package/skills/gsd-debug/SKILL.md +1 -0
  426. package/skills/gsd-execute-phase/SKILL.md +1 -1
  427. package/skills/gsd-graphify/SKILL.md +1 -0
  428. package/skills/gsd-health/SKILL.md +1 -0
  429. package/skills/gsd-mempalace-capture/SKILL.md +1 -0
  430. package/skills/gsd-mempalace-recall/SKILL.md +1 -0
  431. package/skills/gsd-new-milestone/SKILL.md +1 -0
  432. package/skills/gsd-new-project/SKILL.md +1 -0
  433. package/skills/gsd-next/SKILL.md +1 -0
  434. package/skills/gsd-ns-workflow/SKILL.md +1 -0
  435. package/skills/gsd-pause-work/SKILL.md +1 -0
  436. package/skills/gsd-phase/SKILL.md +2 -1
  437. package/skills/gsd-pr-branch/SKILL.md +1 -0
  438. package/skills/gsd-quick-batch/SKILL.md +105 -0
  439. package/skills/gsd-resume-work/SKILL.md +1 -0
  440. package/skills/gsd-review-backlog/SKILL.md +1 -0
  441. package/skills/gsd-settings/SKILL.md +2 -1
  442. package/skills/gsd-stats/SKILL.md +1 -0
  443. package/skills/gsd-surface/SKILL.md +18 -8
  444. package/skills/gsd-thread/SKILL.md +1 -0
  445. package/skills/gsd-workspace/SKILL.md +1 -0
  446. package/skills/gsd-workstreams/SKILL.md +1 -0
  447. package/vscode/package.json +1 -1
  448. package/gsd-core/templates/claude-md.md +0 -145
  449. package/gsd-core/templates/codebase/concerns.md +0 -310
  450. package/gsd-core/templates/codebase/conventions.md +0 -307
  451. package/gsd-core/templates/codebase/integrations.md +0 -280
  452. package/gsd-core/templates/codebase/structure.md +0 -285
  453. package/gsd-core/templates/codebase/testing.md +0 -480
  454. package/gsd-core/templates/debug-subagent-prompt.md +0 -91
  455. package/gsd-core/templates/discovery.md +0 -146
@@ -119,7 +119,7 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
119
119
 
120
120
  Parse JSON for: `phase_dir`, `phase_number`, `padded_phase`, `phase_name`, `has_plans`, `plan_count`, `commit_docs`, `text_mode`, `response_language`.
121
121
 
122
- **If `response_language` is set:** All user-facing output should be in `{response_language}`.
122
+ **If `response_language` is set:** All user-facing output — narration between tool calls, status updates, progress notes, findings, questions, and report prose — should be in `{response_language}`.
123
123
 
124
124
  Set `TEXT_MODE=true` if `--text` is present in $ARGUMENTS OR `text_mode` from init JSON is `true`. When `TEXT_MODE` is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number.
125
125
 
@@ -341,13 +341,20 @@ Run this pass whenever the source-grounding pass ran — it is the second axis o
341
341
 
342
342
  **Coverage, never silence.** If STATE.md or CONTEXT.md is absent, that axis is skipped and the skip is recorded in the same "Verification coverage" block. A clean pass must never mean "nothing was compared."
343
343
 
344
- After agent returns, verify REVIEWS.md exists:
344
+ After agent returns, verify REVIEWS.md exists. Assign the path directly and quote it — an unquoted
345
+ `${phase_dir}` inside `$(ls …)` word-splits and glob-expands, and a discarded stderr hides it (#3899):
345
346
  ```bash
346
- REVIEWS_FILE=$(ls ${phase_dir}/${padded_phase}-REVIEWS.md 2>/dev/null)
347
+ if [ -z "${phase_dir}" ]; then
348
+ echo "ERROR: phase_dir is empty — cannot resolve the expected REVIEWS.md path." >&2
349
+ exit 1
350
+ fi
351
+ REVIEWS_FILE="${phase_dir}/${padded_phase}-REVIEWS.md"
352
+ if [ ! -f "${REVIEWS_FILE}" ] || [ ! -r "${REVIEWS_FILE}" ]; then
353
+ echo "ERROR: expected reviews file is not a readable file: '${REVIEWS_FILE}'. Confirm the phase directory resolved correctly before concluding the review agent produced nothing." >&2
354
+ exit 1
355
+ fi
347
356
  ```
348
357
 
349
- If REVIEWS_FILE is empty: Error — review agent did not produce REVIEWS.md. Exit.
350
-
351
358
  ### 5b. Extract unresolved counts from CYCLE_SUMMARY Contract
352
359
 
353
360
  **Do NOT grep REVIEWS.md for HIGH or actionable counts.** REVIEWS.md accumulates history across cycles — resolved findings from prior cycles remain in the file as audit trail, inflating a raw grep count and causing false stall detection.
@@ -390,7 +397,68 @@ if [ "${ACTIONABLE_COUNT}" -gt 0 ] && [ -z "${ACTIONABLE_LINES}" ]; then
390
397
  fi
391
398
  ```
392
399
 
393
- **If HIGH_COUNT == 0 and ACTIONABLE_COUNT == 0 (converged):**
400
+ **Open plan-revision conflicts are part of the converged condition (#3771).** An entry under
401
+ `## Plan-Revision Conflicts` in REVIEWS.md is a checker `fix_hint` that contradicted a locked
402
+ decision, capability guidance, or an existing plan constraint, recorded by `/gsd:plan-phase`
403
+ together with the alternatives the planner considered. It is NOT counted by `CYCLE_SUMMARY`, so
404
+ it must be read from the file directly — evaluate this BEFORE the converged branch below, or a
405
+ run would write `planned-phase` and print the success banner over a conflict nobody resolved:
406
+
407
+ ```bash
408
+ if [ ! -f "${REVIEWS_FILE}" ]; then
409
+ # Fail CLOSED. A missing/non-file REVIEWS.md is "I cannot tell", never "no conflicts".
410
+ echo "BLOCKED: cannot read REVIEWS.md ('${REVIEWS_FILE}') to check for open plan-revision conflicts. Refusing to declare convergence on an unverifiable gate." >&2
411
+ exit 1
412
+ fi
413
+ if OPEN_CONFLICTS=$(awk '
414
+ BEGIN { saw_title = 0; in_owned = 0; saw_heading = 0; done = 0; count = 0 }
415
+ { sub(/\r$/, "") }
416
+ !saw_title && /^# Cross-AI Plan Review — Phase / { saw_title = 1; next }
417
+ saw_title && !in_owned && !done {
418
+ if ($0 == "") next
419
+ if ($0 == "<!-- gsd:plan-revision-conflicts:begin -->") { in_owned = 1; next }
420
+ exit 2
421
+ }
422
+ in_owned && $0 == "<!-- gsd:plan-revision-conflicts:begin -->" { exit 2 }
423
+ in_owned && !saw_heading && $0 == "" { next }
424
+ in_owned && !saw_heading && $0 == "## Plan-Revision Conflicts" { saw_heading = 1; next }
425
+ in_owned && !saw_heading { exit 2 }
426
+ in_owned && $0 == "<!-- gsd:plan-revision-conflicts:end -->" {
427
+ done = 1
428
+ in_owned = 0
429
+ print count
430
+ exit
431
+ }
432
+ in_owned && /^- \[ \] REVISION_CONFLICT .*required_property:/ { count++ }
433
+ END { if (!done) exit 2 }
434
+ ' "${REVIEWS_FILE}"); then
435
+ :
436
+ else
437
+ awk_status=$?
438
+ echo "BLOCKED: could not parse the writer-owned plan-revision conflict block in '${REVIEWS_FILE}' (awk exit ${awk_status}). Refusing to declare convergence on an unverifiable gate." >&2
439
+ exit 1
440
+ fi
441
+ ```
442
+
443
+ `/gsd:review` emits exactly one writer-owned slot immediately after the artifact title,
444
+ between `<!-- gsd:plan-revision-conflicts:begin -->` and
445
+ `<!-- gsd:plan-revision-conflicts:end -->`. Inside that slot, `/gsd:plan-phase` records each
446
+ conflict as a `- [ ] REVISION_CONFLICT` checklist line and flips it to
447
+ `- [x] REVISION_CONFLICT` when resolved. The reader counts only the first fixed slot at that
448
+ position and stops at its explicit end delimiter. Reviewer output is rendered after the slot, so
449
+ raw reviewer text containing either the heading or an exact conflict-shaped checklist line cannot
450
+ forge blocking state. There is deliberately no fallback to the prior global line-shape scan: that
451
+ shape never merged to `next`, and accepting both grammars would recreate the reviewer collision.
452
+
453
+ **Only `/gsd:plan-phase` mutates the contents of this slot.** The review agent preserves the
454
+ existing `## Plan-Revision Conflicts` block byte-for-byte between its delimiters; every other
455
+ agent with write access to REVIEWS.md must leave it alone. Appending, editing, reordering or
456
+ deleting a line there forges the state of a blocking gate. Readers read. If `OPEN_CONFLICTS` > 0, convergence has NOT been
457
+ achieved regardless of the counts: skip the converged branch and continue to 5c so the next cycle
458
+ arbitrates. Escalation at `MAX_CYCLES` is unchanged and still terminates the loop, so an
459
+ unresolvable conflict escalates rather than deadlocking.
460
+
461
+ **If HIGH_COUNT == 0 and ACTIONABLE_COUNT == 0 and OPEN_CONFLICTS == 0 (converged):**
394
462
 
395
463
  ```bash
396
464
  gsd_run state planned-phase --phase "${PHASE}" --name "${phase_name}" --plans "${PLAN_COUNT}"
@@ -410,11 +478,11 @@ Display:
410
478
 
411
479
  Exit — convergence achieved.
412
480
 
413
- **If HIGH_COUNT > 0 or ACTIONABLE_COUNT > 0:** Continue to 5c.
481
+ **If HIGH_COUNT > 0 or ACTIONABLE_COUNT > 0 or OPEN_CONFLICTS > 0:** Continue to 5c.
414
482
 
415
483
  ### 5c. Stall Detection + Escalation Check
416
484
 
417
- Display: `◆ Cycle {cycle}/{MAX_CYCLES} — {HIGH_COUNT} HIGH, {ACTIONABLE_COUNT} actionable non-HIGH review concerns found`
485
+ Display: `◆ Cycle {cycle}/{MAX_CYCLES} — {HIGH_COUNT} HIGH, {ACTIONABLE_COUNT} actionable non-HIGH review concerns, {OPEN_CONFLICTS} open plan-revision conflicts found`
418
486
 
419
487
  **Stall detection:** If `UNRESOLVED_COUNT >= prev_unresolved_count`:
420
488
  ```text
@@ -424,6 +492,29 @@ Display: `◆ Cycle {cycle}/{MAX_CYCLES} — {HIGH_COUNT} HIGH, {ACTIONABLE_COUN
424
492
 
425
493
  **Max cycles check:** If `cycle >= MAX_CYCLES`:
426
494
 
495
+ **If `OPEN_CONFLICTS` > 0 (#3771): "Proceed anyway" is never offered.** An open plan-revision
496
+ conflict is a blocker — this loop's whole purpose is to surface it rather than let a success
497
+ banner paper over it, so escalation cannot end in the same silent acceptance a HIGH/actionable
498
+ concern can. Only "Manual review" is available:
499
+
500
+ If `TEXT_MODE` is true, present as plain text:
501
+ ```text
502
+ Plan convergence did not complete after {MAX_CYCLES} cycles.
503
+ {OPEN_CONFLICTS} open plan-revision conflict(s) remain — these are blockers and cannot be accepted:
504
+
505
+ {HIGH_LINES}
506
+
507
+ {ACTIONABLE_LINES}
508
+
509
+ Review the concerns in: {REVIEWS_FILE}
510
+
511
+ To replan manually: /gsd:plan-phase {PHASE} --reviews
512
+ To restart loop: /gsd:plan-review-convergence {PHASE} {REVIEWER_FLAGS}
513
+ ```
514
+ Exit workflow.
515
+
516
+ **Otherwise (`OPEN_CONFLICTS` == 0):**
517
+
427
518
  If `TEXT_MODE` is true, present as plain-text numbered list:
428
519
  ```text
429
520
  Plan convergence did not complete after {MAX_CYCLES} cycles.
@@ -478,7 +569,7 @@ Display: `◆ Replanning inline with review feedback... (plan-phase runs here in
478
569
  Skill(skill="gsd-plan-phase", args="{PHASE} --reviews --skip-research {GSD_WS}")
479
570
  ```
480
571
 
481
- Run plan-phase **inline** (do NOT wrap it in Agent()). Same rationale as step 4: the convergence orchestrator runs at depth 0 with Agent available, so inline plan-phase can spawn gsd-planner and gsd-plan-checker at depth 1. Wrapping in Agent() pushes plan-phase to depth 1 where the Agent tool is absent — the replan loop can never produce a revised plan when HIGHs are found. This is the root cause of bug #936. Actionable MEDIUM/LOW findings must be incorporated into executable PLAN.md content or explicitly deferred/rejected in the relevant PLAN.md before convergence can complete. Wait until plan-phase completes (outputs '## PLANNING COMPLETE') and updated PLAN.md files are committed before continuing.
572
+ Run plan-phase **inline** (do NOT wrap it in Agent()). Same rationale as step 4: the convergence orchestrator runs at depth 0 with Agent available, so inline plan-phase can spawn gsd-planner and gsd-plan-checker at depth 1. Wrapping in Agent() pushes plan-phase to depth 1 where the Agent tool is absent — the replan loop can never produce a revised plan when HIGHs are found. This is the root cause of bug #936. Actionable MEDIUM/LOW findings must be incorporated into executable PLAN.md content or explicitly deferred/rejected in the relevant PLAN.md before convergence can complete. The same holds for any open `## Plan-Revision Conflicts` entry (#3771): the replan must resolve it by adopting one of its recorded alternatives, overriding the named constraint, or amending the constraint — and mark the entry resolved. Re-running the planner against an unchanged conflict cannot resolve it and only burns a cycle. Wait until plan-phase completes (outputs '## PLANNING COMPLETE') and updated PLAN.md files are committed before continuing.
482
573
 
483
574
  After plan-phase completes → go back to **step 5a** (review again).
484
575
 
@@ -497,7 +588,8 @@ After plan-phase completes → go back to **step 5a** (review again).
497
588
  - [ ] Abort with clear error if current_actionable is absent or malformed
498
589
  - [ ] Warn if ACTIONABLE_COUNT > 0 but ## Current Actionable Non-HIGH Concerns section is absent from return message
499
590
  - [ ] The review Agent fully completes gsd-review before returning (plan-phase runs inline — no Agent wrap)
500
- - [ ] Loop exits on: no HIGH concerns and no actionable non-HIGH concerns (converged) OR max cycles (escalation)
591
+ - [ ] Loop exits on: no HIGH concerns, no actionable non-HIGH concerns, and OPEN_CONFLICTS == 0 (converged) OR max cycles (escalation)
592
+ - [ ] OPEN_CONFLICTS read from REVIEWS.md and evaluated BEFORE the converged branch writes state or prints the banner
501
593
  - [ ] Stall detection reported when total unresolved review concern count is not decreasing
502
594
  - [ ] STATE.md updated on convergence completion
503
595
  </success_criteria>
@@ -140,7 +140,7 @@ RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --raw --default "
140
140
  gsd_run query commit "docs: plant seed — {$IDEA}" --files .planning/seeds/SEED-{PADDED}-{slug}.md
141
141
  ```
142
142
 
143
- **If `response_language` is set:** All user-facing questions, prompts, and explanations in this workflow MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
143
+ **If `response_language` is set:** All user-facing output of this workflow — narration between tool calls, status updates, progress notes, findings, questions, prompts, and explanations — MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
144
144
  </step>
145
145
 
146
146
  <step name="confirm">
@@ -1,3 +1,5 @@
1
+ @~/.claude/gsd-core/references/response-language-directive.md
2
+
1
3
  <purpose>
2
4
  Create a clean branch for pull requests by filtering .planning/ paths out of the
3
5
  cherry-picked history. Two modes, selected by the `planning.pr_strict` config key:
@@ -261,7 +263,10 @@ if [ "$PR_STRICT" = "true" ]; then
261
263
  FILTER_PATHS=".planning/"
262
264
  FORBIDDEN_RE="^\.planning/"
263
265
  else
264
- FILTER_PATHS=$(for d in $TRANSIENT_DIRS; do printf '.planning/%s/ ' "$d"; done)
266
+ # Rewrapped through unquoted command substitution (gsd-core#4109): a bare
267
+ # `$VAR` word-splits under bash but not zsh, collapsing every element onto
268
+ # one iteration there.
269
+ FILTER_PATHS=$(for d in $(printf '%s' "$TRANSIENT_DIRS"); do printf '.planning/%s/ ' "$d"; done)
265
270
  FORBIDDEN_RE="^\.planning/($(echo "$TRANSIENT_DIRS" | tr ' ' '|'))/"
266
271
  fi
267
272
  ```
@@ -273,16 +278,27 @@ For each commit, check what it touches:
273
278
  FILES=$(git diff-tree --no-commit-id --name-only -r $HASH)
274
279
  NON_PLANNING=$(echo "$FILES" | grep -c -v "^\.planning/" || true)
275
280
  STRUCTURAL=$(echo "$FILES" | grep -Ec "$STRUCTURAL_RE" || true)
281
+ PLANNING_COUNT=$(echo "$FILES" | grep -c "^\.planning/" || true)
276
282
  ```
277
283
 
278
- Classify:
279
- - **Code commits**: touch at least one non-`.planning/` file → INCLUDE (both modes)
280
- - **Mixed commits**: touch code + any planning files → INCLUDE (both modes; the planning
281
- paths are filtered out by `create_pr_branch`, not the commit)
282
- - **Structural planning commits**: touch only structural `.planning/` files → INCLUDE in
284
+ Classify, using `NON_PLANNING`, `STRUCTURAL`, and `PLANNING_COUNT` computed above — every arm's
285
+ condition is explicit and computable so no reading of it is ambiguous:
286
+ - **Code commits**: `NON_PLANNING > 0` and `PLANNING_COUNT == 0` → INCLUDE (both modes)
287
+ - **Mixed code+planning commits**: `NON_PLANNING > 0` and `PLANNING_COUNT > 0` → INCLUDE (both
288
+ modes; the planning paths are filtered out by `create_pr_branch`, not the commit)
289
+ - **Structural-only planning commits**: `NON_PLANNING == 0` and `STRUCTURAL == PLANNING_COUNT`
290
+ and `PLANNING_COUNT > 0` (every `.planning/` file touched is structural) → INCLUDE in
283
291
  **default** mode; **EXCLUDE** in strict mode, which has no structural carve-out
284
- - **Transient planning commits**: touch only `.planning/` paths that are not structural →
285
- EXCLUDE (both modes)
292
+ - **Mixed planning commits (#4447)**: `NON_PLANNING == 0` and `STRUCTURAL > 0` and
293
+ `STRUCTURAL < PLANNING_COUNT` (some but not all `.planning/` files touched are structural —
294
+ the rest are transient and/or the "other" bucket, e.g. `config.json`/`intel/`) → INCLUDE in
295
+ **default** mode (the transient-dir subset of the non-structural paths is filtered out by
296
+ `create_pr_branch`'s universal per-commit filter exactly as for a mixed code+planning commit;
297
+ any "other" non-structural, non-transient path — `config.json`, `intel/`, etc. — is simply
298
+ preserved, same as default mode already does for such paths on any commit); **EXCLUDE** in
299
+ strict mode
300
+ - **Transient-only planning commits**: `NON_PLANNING == 0` and `STRUCTURAL == 0` and
301
+ `PLANNING_COUNT > 0` → EXCLUDE (both modes)
286
302
 
287
303
  In strict mode this collapses to a single rule: `NON_PLANNING > 0` → INCLUDE, else EXCLUDE.
288
304
 
@@ -292,6 +308,7 @@ Commits to include: {N} (code changes{, + structural planning — default mode o
292
308
  Commits to exclude: {N} (planning-only)
293
309
  Mixed commits: {N} (code + planning — included, planning paths filtered)
294
310
  Structural planning commits: {N} ({included|excluded — strict mode})
311
+ Mixed planning commits: {N} ({included — structural + transient/other, planning paths filtered|excluded — strict mode})
295
312
  ```
296
313
  </step>
297
314
 
@@ -322,12 +339,15 @@ touching the same planning path makes `git cherry-pick` abort with *"untracked w
322
339
  files would be overwritten by merge"*, and every remaining commit is silently dropped.
323
340
 
324
341
  ```bash
325
- for HASH in $INCLUDED_COMMITS; do
342
+ # Rewrapped through unquoted command substitution (gsd-core#4109): a bare
343
+ # `$VAR` word-splits under bash but not zsh, collapsing every element onto
344
+ # one iteration there.
345
+ for HASH in $(printf '%s' "$INCLUDED_COMMITS"); do
326
346
  # A modify/delete conflict on a filtered path is EXPECTED and is resolved below — the
327
347
  # filtered path is absent from HEAD by construction. Do not treat it as a failure here.
328
348
  git cherry-pick --no-commit "$HASH" || true
329
349
 
330
- for P in $FILTER_PATHS; do
350
+ for P in $(printf '%s' "$FILTER_PATHS"); do
331
351
  git rm -r -f -q --ignore-unmatch -- "$P" 2>/dev/null || true
332
352
  git checkout HEAD -- "$P" 2>/dev/null || true
333
353
  done
@@ -19,7 +19,7 @@ _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-pars
19
19
  RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --raw --default "" 2>/dev/null || echo "")
20
20
  ```
21
21
 
22
- **If `response_language` is set:** All user-facing questions, prompts, and explanations in this workflow MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
22
+ **If `response_language` is set:** All user-facing output of this workflow — narration between tool calls, status updates, progress notes, findings, questions, prompts, and explanations — MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
23
23
 
24
24
  ## 1. Initialize
25
25
 
@@ -89,7 +89,7 @@ Glob every phase directory's SCOPE BOUNDARY log (executor writes out-of-scope di
89
89
  ls .planning/phases/*/deferred-items.md 2>/dev/null || true
90
90
  ```
91
91
 
92
- For each `deferred-items.md` found, read its entries (bullet list, one entry per top-level `- ` line, continuation lines indented beneath it). An entry is RESOLVED only if it carries an explicit `status: resolved` field (case-insensitive) on one of its lines; every other entry — including one with no `status:` field at all — is UNRESOLVED and must be surfaced (fail-safe: never silently drop a possibly-open item).
92
+ For each `deferred-items.md` found, read its entries (bullet list, one entry per top-level list item — `-`, `*`, `+` or an ordered marker of one to nine digits terminated by a DOT, where an ordered list counts when it starts at `0.` or `1.` or continues a list already open at its level; `1)` is not a marker and neither is a ten-digit ordinal (`999999999.` counts, `1234567890.` does not) — with continuation lines indented beneath it; fenced code blocks at ANY indent, including deeper than CommonMark's three-space cap, and `* * *`-style separators are not entries; an unclosed fence ends with its own entry and never hides the entries after it; a closed pair of delimiters is a fence whatever sits between them). An entry is RESOLVED only if it carries an explicit `status: resolved` field on one of its lines — the bare key lower-case only, or the bolded `**Status:**` form in any case; the VALUE is case-insensitive in both; every other entry — including one with no `status:` field at all — is UNRESOLVED and must be surfaced (fail-safe: never silently drop a possibly-open item).
93
93
 
94
94
  Emit:
95
95
  - ✓ `No unresolved deferred items` — if no `deferred-items.md` files exist, or every entry in every file is `status: resolved`
@@ -1,3 +1,5 @@
1
+ @~/.claude/gsd-core/references/response-language-directive.md
2
+
1
3
  <purpose>
2
4
  Check project progress, summarize recent work and what's ahead, then intelligently route to the next action — either executing an existing plan or creating the next one. Provides situational awareness before continuing work.
3
5
  </purpose>
@@ -18,13 +20,33 @@ INIT=$(gsd_run query init.progress $FORENSIC_PARAM)
18
20
  if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
19
21
  ```
20
22
 
21
- Extract from init JSON: `project_exists`, `roadmap_exists`, `state_exists`, `phases`, `current_phase`, `next_phase`, `milestone_version`, `completed_count`, `phase_count`, `paused_at`, `state_path`, `roadmap_path`, `project_path`, `config_path`, `phase_mvp_mode`.
23
+ Extract from init JSON: `project_exists`, `roadmap_exists`, `state_exists`, `requirements_exists`, `planning_exists`, `milestones_exists`, `init_incomplete`, `phases`, `current_phase`, `next_phase`, `milestone_version`, `completed_count`, `phase_count`, `paused_at`, `state_path`, `roadmap_path`, `project_path`, `config_path`, `phase_mvp_mode`.
22
24
 
23
25
  ```bash
24
26
  DISCUSS_MODE=$(gsd_run query config-get workflow.discuss_mode --raw 2>/dev/null || echo "discuss")
25
27
  ```
26
28
 
27
- If `project_exists` is false (no `.planning/` directory):
29
+ **If `init_incomplete` is true (#4040 — interrupted bootstrap):**
30
+
31
+ `.planning/` exists but the core initialization artifacts are missing (one or more of `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md` were never created — a bootstrap that stopped partway, e.g. after PROJECT.md). This is NOT a new project, NOT a missing STATE.md, and NOT a between-milestones state — do not fall through to any of those routes. Route to initialization recovery:
32
+
33
+ ```
34
+ ---
35
+
36
+ ## ⚠ Initialization Incomplete
37
+
38
+ A partial `.planning/` was found: project initialization started but stopped before creating all core artifacts (missing: REQUIREMENTS.md, ROADMAP.md, STATE.md — whichever `requirements_exists` / `roadmap_exists` / `state_exists` report as false).
39
+
40
+ `/clear` then:
41
+
42
+ `/gsd:new-project` — resumes initialization from the first missing artifact; existing PROJECT.md (and any already-created artifacts) are kept, not regenerated.
43
+
44
+ ---
45
+ ```
46
+
47
+ Exit. (The payload's `init_incomplete` is computed with the between-milestones archive case excluded — `MILESTONES.md` present means missing ROADMAP/REQUIREMENTS is archival, and that state still routes to Route F below.)
48
+
49
+ If `init_incomplete` is false and `planning_exists` is false and `project_exists` is false (no `.planning/` directory at all):
28
50
 
29
51
  ```
30
52
  No planning structure found.
@@ -36,7 +58,7 @@ Exit.
36
58
 
37
59
  If missing STATE.md: suggest `/gsd:new-project`.
38
60
 
39
- **If ROADMAP.md missing but PROJECT.md exists:**
61
+ **If ROADMAP.md missing but PROJECT.md exists (and `init_incomplete` is false):**
40
62
 
41
63
  This means a milestone was completed and archived. Go to **Route F** (between milestones).
42
64
 
@@ -56,7 +56,7 @@ Agent(
56
56
  **Handle checker return:**
57
57
 
58
58
  - **`## VERIFICATION PASSED`:** Display confirmation, proceed to step 6.
59
- - **`## ISSUES FOUND`:** Display issues, check iteration count, enter revision loop.
59
+ - **`## ISSUES FOUND`:** Count BLOCKER + WARNING entries in the YAML issues block; an entry whose severity is missing or unrecognized counts as a BLOCKER (fail closed). If zero — every entry is explicitly INFO — display `ℹ advisory — {dimension}: {description}` per entry and proceed to step 6; INFO is advisory and never enters the loop (#3724). Otherwise display issues, check iteration count, enter revision loop.
60
60
 
61
61
  **Revision loop (max 2 iterations):**
62
62
 
@@ -68,6 +68,8 @@ Display: `Sending back to planner for revision... (iteration ${N}/2)`
68
68
 
69
69
  Revision prompt:
70
70
 
71
+ Reuse the `PLAN_PRE_HOOKS_JSON` snapshot captured by Quick Step 5; do not render hooks again.
72
+
71
73
  ```markdown
72
74
  <revision_context>
73
75
  **Mode:** quick-full (revision)
@@ -78,12 +80,23 @@ Revision prompt:
78
80
 
79
81
  ${AGENT_SKILLS_PLANNER}
80
82
 
83
+ {For each active entry in `PLAN_PRE_HOOKS_JSON` where `kind == "contribution"` and `into == "planner"` (in array order): inject the entry's `fragment.inline` verbatim here, plus its resolved `configValues` when the entry carries them. If no active planner contributions exist, omit this block entirely.}
84
+
81
85
  **Checker issues:** ${structured_issues_from_checker}
82
86
 
83
87
  </revision_context>
84
88
 
85
89
  <instructions>
86
90
  Make targeted updates to address checker issues.
91
+
92
+ `required_property` + evidence + severity BIND. `fix_hint` is ONE non-binding example route: a
93
+ smaller or different mechanism reaching the same property addresses the issue in full — say which
94
+ you used. Re-check ${DISCUSS_MODE ? 'locked decisions in ' + quick_id + '-CONTEXT.md, ' : ''}capability guidance (CLAUDE.md, project skills) and the
95
+ constraints these plans already encode BEFORE editing; if a hint would contradict one, or the
96
+ property is unreachable without breaking one, return `## REVISION_CONFLICT` with the conflict and
97
+ the alternatives rather than applying or working around it. Full contract:
98
+ `gsd-core/references/planner-revision.md`, which you load in revision mode.
99
+
87
100
  Do NOT replan from scratch unless issues are fundamental.
88
101
  Return what changed.
89
102
  </instructions>
@@ -100,7 +113,29 @@ Agent(
100
113
 
101
114
  > **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
102
115
 
103
- After planner returns → spawn checker again, increment iteration_count.
116
+ **If the planner returns `## REVISION_CONFLICT`:** a conflict is not resolvable by re-running the
117
+ same loop, so it must not consume retry budget. Do NOT increment `iteration_count` and do NOT
118
+ re-spawn the checker yet. Present the conflict table and its alternatives to the user and ask
119
+ which to take: adopt a named alternative / override the named constraint and apply the hint /
120
+ amend the constraint itself. Every option resolves the conflict. Accepting the plan with the
121
+ blocker still open is NOT offered here — the blocking `required_property` still fails, and that
122
+ choice belongs to the max-iteration escalation below, which is unchanged.
123
+
124
+ A quick task has no REVIEWS.md and no phase, so `workflow.plan_review_convergence` has nothing to
125
+ arbitrate over here; the user is the only route. `plan-phase` is where the convergence hand-off
126
+ lives.
127
+
128
+ Re-spawn the planner with the chosen resolution, then **re-evaluate its return from the top of
129
+ this handler** — do not fall through to the checker spawn below. A second conflict is still a
130
+ conflict, not a revised plan.
131
+
132
+ **Bounded:** A conflict naming the SAME `required_property` twice in a row (no successful revision in between) is a stall, and so is the
133
+ THIRD conflict return of this loop whatever property it names — alternating property names
134
+ would otherwise never trip the repeat rule and the path would be unbounded. Stop re-spawning and
135
+ route it to the same iteration-count check below, so declining to spend an iteration cannot make
136
+ this path unbounded.
137
+
138
+ **Otherwise (the planner returns a revised plan, not `## REVISION_CONFLICT`):** spawn checker again, increment `iteration_count`.
104
139
 
105
140
  **If iteration_count >= 2:**
106
141
 
@@ -13,7 +13,7 @@ Spawn a single focused researcher (not 4 parallel researchers like full phases
13
13
 
14
14
  <!-- #2517 model-omit-on-inherit -->
15
15
 
16
- > **Model omission (#2517).** Omit the `model` parameter entirely when the value it would carry (`planner_model`, `checker_model`, `executor_model`, `reviewer_model`, `verifier_model`) is `"inherit"` or empty. An empty value 404s on runtimes without native tier aliases — the default on non-Claude runtimes. Omitting it inherits the orchestrator's model. See @gsd-core/references/model-profile-resolution.md.
16
+ > **Model omission (#2517).** Omit the `model` parameter entirely when the value it would carry (`planner_model`, `checker_model`, `executor_model`, `reviewer_model`, `verifier_model`, `researcher_model`) is `"inherit"` or empty. An empty value 404s on runtimes without native tier aliases — the default on non-Claude runtimes. Omitting it inherits the orchestrator's model. See @gsd-core/references/model-profile-resolution.md.
17
17
 
18
18
  <!-- #2508 runtime-aware-dispatch -->
19
19
 
@@ -35,7 +35,7 @@ Agent(
35
35
  ${DISCUSS_MODE ? '- ' + QUICK_DIR + '/' + quick_id + '-CONTEXT.md (User decisions — research should align with these. #3894: when workflow.research_before_questions is enabled research runs BEFORE discussion, so this file will not exist yet — read it only if present)' : ''}
36
36
  </required_reading>
37
37
 
38
- ${AGENT_SKILLS_PLANNER}
38
+ ${AGENT_SKILLS_RESEARCHER}
39
39
 
40
40
  </research_context>
41
41
 
@@ -56,7 +56,7 @@ Return: ## RESEARCH COMPLETE with file path
56
56
  </output>
57
57
  ",
58
58
  subagent_type="gsd-phase-researcher",
59
- model="{planner_model}",
59
+ model="{researcher_model}",
60
60
  description="Research: ${DESCRIPTION}"
61
61
  )
62
62
  ```
@@ -0,0 +1,55 @@
1
+ **Step 2b: Create a new batch (only when `$RESUME_BATCH_ID` is empty)**
2
+
3
+ Skip this step entirely if `$RESUME_BATCH_ID` is set (resume-mode.md owns
4
+ that path instead).
5
+
6
+ **Get the task list.** If `--file <path>` was present in `$ARGUMENTS`, use its
7
+ value as `$TASK_FILE`. Otherwise the remaining, non-flag text of `$ARGUMENTS`
8
+ IS the inline task list (a bulleted/numbered list, ≥2 items — the same
9
+ grammar `parseTaskList` enforces).
10
+
11
+ If `$TASK_FILE` is set:
12
+ ```bash
13
+ _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif _gsd_at "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd_run is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; case "$(gsd_run runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') GSD_IDENTITY_STATUS=ok;; esac; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
14
+ QB_CREATE_JSON=$(gsd_run quick-batch create --file "$TASK_FILE" --base-revision "$(git rev-parse HEAD)" --raw)
15
+ ```
16
+
17
+ Otherwise, the inline list must land on disk first — `quick-batch create`
18
+ only accepts `--file` (path-confined, same as `/gsd:quick-batch`'s own
19
+ security posture): write it to a scratch file under `.planning/` before
20
+ calling the verb.
21
+ ```bash
22
+ TASK_FILE="${quick_dir%/quick}/.quick-batch-task-list.tmp"
23
+ mkdir -p "$(dirname "$TASK_FILE")"
24
+ printf '%s\n' "$INLINE_TASK_LIST" > "$TASK_FILE"
25
+ QB_CREATE_JSON=$(gsd_run quick-batch create --file "$TASK_FILE" --base-revision "$(git rev-parse HEAD)" --raw)
26
+ rm -f "$TASK_FILE"
27
+ ```
28
+
29
+ ```bash
30
+ QB_CREATE_RC=$?
31
+ if [[ "$QB_CREATE_JSON" == @file:* ]]; then QB_CREATE_JSON=$(cat "${QB_CREATE_JSON#@file:}"); fi
32
+ ```
33
+
34
+ **If `$QB_CREATE_RC` is non-zero:** the task list failed to parse (fewer than
35
+ 2 items — row 2/12) or the dependency DAG was invalid. Print the CLI's error
36
+ message verbatim and STOP. Do not dispatch anything.
37
+
38
+ **Otherwise:** parse `$QB_CREATE_JSON` for `batchId` and `manifest` (every
39
+ item starts `pending`, wave `0` — no dependency/file-overlap signal exists
40
+ yet before planning; this is expected, not a bug, per the design's negative-
41
+ space note).
42
+
43
+ ```bash
44
+ BATCH_ID="$batchId"
45
+ BATCH_MANIFEST_JSON=$(printf '%s' "$QB_CREATE_JSON" | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{try{const j=JSON.parse(s);process.stdout.write(JSON.stringify(j.manifest))}catch{process.stdout.write("")}})')
46
+ ITEM_COUNT=$(printf '%s' "$BATCH_MANIFEST_JSON" | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{try{const j=JSON.parse(s);process.stdout.write(String(j.items.length))}catch{process.stdout.write("0")}})')
47
+ ```
48
+
49
+ Report to user:
50
+ ```
51
+ Creating quick batch ${BATCH_ID}: ${ITEM_COUNT} item(s).
52
+ Manifest: .planning/quick-batches/${BATCH_ID}/BATCH.json
53
+ ```
54
+
55
+ Continue to Step 3 in `quick-batch.md`.
@@ -0,0 +1,65 @@
1
+ **Step 9: Completion**
2
+
3
+ For every item that merged successfully in Step 7 AND (NOT `$VALIDATE_MODE`,
4
+ OR Step 8 routed it to `complete`): call `completeQuickItem` via its CLI verb
5
+ — this is the ONLY writer of a "Quick Tasks Completed" STATE.md row and the
6
+ item's `complete` status; both happen inside ONE lock transaction, exactly
7
+ once per item (idempotent — re-running this step for an already-complete
8
+ item is a no-op, same guarantee `/gsd:quick` relies on):
9
+
10
+ ```bash
11
+ _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif _gsd_at "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd_run is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; case "$(gsd_run runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') GSD_IDENTITY_STATUS=ok;; esac; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
12
+ gsd_run quick-batch complete \
13
+ --batch "$BATCH_ID" \
14
+ --quick-id "$quick_id" \
15
+ --description "$description" \
16
+ --date "$date" \
17
+ --commit "$commit_hash" \
18
+ --directory "$ITEM_DIR" \
19
+ --raw
20
+ ```
21
+
22
+ Items NOT reaching this call — `human_needed`, `failed` (planner/checker/
23
+ merge/verification failure), or still `blocked`/`pending` (a dependency
24
+ failed, row 32) — are left exactly as their respective routing step set
25
+ them. No STATE row, no `complete` status, worktree preserved where
26
+ applicable.
27
+
28
+ **Final commit.** Stage every artifact produced this run (PLAN.md, SUMMARY.md,
29
+ `--research` RESEARCH.md, `--validate` VERIFICATION.md, per item, plus
30
+ `.planning/STATE.md`) and commit:
31
+ `$BATCH_ARTIFACT_FILES` is a bash ARRAY (not a plain string — a plain
32
+ space-joined string re-splits unpredictably under `set -f`/globbing and
33
+ diverges between bash and zsh, the #4109 word-splitting bug class):
34
+ ```bash
35
+ COMMIT_DOCS=$(gsd_run query config-get commit_docs --raw 2>/dev/null || echo "true")
36
+ if [ "$COMMIT_DOCS" != "false" ]; then
37
+ git add "${BATCH_ARTIFACT_FILES[@]}" 2>/dev/null
38
+ gsd_run query commit "docs(quick-batch-${BATCH_ID}): ${ITEM_COUNT} item(s)" --files "${BATCH_ARTIFACT_FILES[@]}"
39
+ fi
40
+ ```
41
+
42
+ **Final report.** Re-load the batch (`gsd_run quick-batch resume --batch
43
+ "$BATCH_ID" --raw` — read-only in effect when nothing changed) and summarize
44
+ by status:
45
+
46
+ ```
47
+ ---
48
+ GSD > QUICK BATCH COMPLETE
49
+
50
+ Batch ${BATCH_ID}: ${ITEM_COUNT} item(s)
51
+ Complete: ${complete_count}
52
+ Failed: ${failed_count}${failed_count > 0 ? ' (' + failed_reasons + ')' : ''}
53
+ Needs review: ${human_needed_count}
54
+ Blocked: ${blocked_count}
55
+
56
+ ${failed_count + human_needed_count > 0 ? 'Resume after resolving: /gsd:quick-batch --resume ' + BATCH_ID : ''}
57
+ ---
58
+ ```
59
+
60
+ If EVERY item is `complete`, this is a clean finish — no further action
61
+ needed. If any item is `failed`/`human_needed`/`blocked`, the batch stays
62
+ resumable: fix the underlying issue (or accept the failure), then re-run
63
+ `/gsd:quick-batch --resume ${BATCH_ID}` — `resumeBatch`'s own propagation
64
+ (unmodified from Phase 3) re-evaluates eligibility from the current state, no
65
+ special quick-batch-side recovery logic needed.