gsd-pi 2.80.0-dev.3065f7bfa → 2.80.0-dev.488219eb6

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 (376) hide show
  1. package/dist/claude-cli-check.d.ts +30 -0
  2. package/dist/claude-cli-check.js +18 -7
  3. package/dist/cli.js +0 -19
  4. package/dist/headless-query.d.ts +10 -0
  5. package/dist/headless-query.js +6 -4
  6. package/dist/loader-entrypoint.d.ts +8 -0
  7. package/dist/loader-entrypoint.js +27 -0
  8. package/dist/loader.js +2 -11
  9. package/dist/mcp-server.d.ts +1 -0
  10. package/dist/mcp-server.js +6 -3
  11. package/dist/resources/.managed-resources-content-hash +1 -1
  12. package/dist/resources/extensions/claude-code-cli/readiness.js +18 -7
  13. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
  14. package/dist/resources/extensions/github-sync/sync.js +4 -1
  15. package/dist/resources/extensions/gsd/auto/loop.js +71 -8
  16. package/dist/resources/extensions/gsd/auto/phases.js +32 -8
  17. package/dist/resources/extensions/gsd/auto/resolve.js +12 -0
  18. package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
  19. package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
  20. package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
  21. package/dist/resources/extensions/gsd/auto-post-unit.js +81 -76
  22. package/dist/resources/extensions/gsd/auto-start.js +41 -6
  23. package/dist/resources/extensions/gsd/auto-worktree.js +98 -80
  24. package/dist/resources/extensions/gsd/auto.js +84 -29
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +62 -13
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +20 -26
  27. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +29 -12
  28. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +6 -9
  29. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +4 -7
  30. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +6 -10
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +5 -9
  32. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +1 -1
  33. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +60 -26
  34. package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +4 -0
  35. package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
  36. package/dist/resources/extensions/gsd/commands-config.js +1 -1
  37. package/dist/resources/extensions/gsd/commands-eval-review.js +2 -2
  38. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  39. package/dist/resources/extensions/gsd/db/unit-dispatches.js +53 -0
  40. package/dist/resources/extensions/gsd/git-service.js +37 -1
  41. package/dist/resources/extensions/gsd/guided-flow.js +14 -4
  42. package/dist/resources/extensions/gsd/init-wizard.js +4 -1
  43. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -4
  44. package/dist/resources/extensions/gsd/slice-cadence.js +45 -2
  45. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +15 -9
  46. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -7
  47. package/dist/resources/extensions/gsd/tools/complete-task.js +1 -1
  48. package/dist/resources/extensions/gsd/worktree-resolver.js +22 -1
  49. package/dist/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
  50. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  51. package/dist/web/standalone/.next/BUILD_ID +1 -1
  52. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  53. package/dist/web/standalone/.next/build-manifest.json +3 -3
  54. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  55. package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
  56. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  57. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  58. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  59. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  60. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  61. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  66. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  67. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/index.html +1 -1
  75. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  76. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  77. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  78. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  83. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  85. package/dist/web/standalone/.next/server/middleware.js +3 -3
  86. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  87. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  88. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  89. package/dist/web/standalone/.next/static/chunks/8359.e059d86b255fce1c.js +10 -0
  90. package/dist/web/standalone/.next/static/chunks/app/{page-fab3ebb85b006001.js → page-752f1e2ebdaa3e45.js} +1 -1
  91. package/dist/web/standalone/.next/static/chunks/{webpack-0481f1221120a7c6.js → webpack-de742b64187e13fe.js} +1 -1
  92. package/dist/welcome-screen.d.ts +2 -0
  93. package/dist/welcome-screen.js +9 -7
  94. package/package.json +1 -1
  95. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +35 -13
  96. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  97. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +21 -11
  98. package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -1
  99. package/packages/pi-ai/dist/providers/anthropic.d.ts +7 -0
  100. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  101. package/packages/pi-ai/dist/providers/anthropic.js +9 -7
  102. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  103. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +23 -14
  104. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -1
  105. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +48 -21
  106. package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
  107. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +22 -21
  108. package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -1
  109. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +22 -21
  110. package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -1
  111. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +39 -25
  112. package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -22
  113. package/packages/pi-ai/src/providers/anthropic.ts +22 -9
  114. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +34 -21
  115. package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +56 -22
  116. package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +24 -28
  117. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +24 -28
  118. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  119. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +3 -1
  120. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  121. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -2
  122. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  123. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  124. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js +22 -56
  125. package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js.map +1 -1
  126. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +1 -0
  127. package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
  128. package/packages/pi-coding-agent/dist/core/tools/bash.js +3 -1
  129. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  130. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts +2 -0
  131. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  132. package/packages/pi-coding-agent/dist/core/tools/edit.js +12 -1
  133. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  134. package/packages/pi-coding-agent/dist/core/tools/find.d.ts +2 -0
  135. package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  136. package/packages/pi-coding-agent/dist/core/tools/find.js +14 -6
  137. package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  138. package/packages/pi-coding-agent/dist/core/tools/grep.d.ts +2 -0
  139. package/packages/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
  140. package/packages/pi-coding-agent/dist/core/tools/grep.js +12 -3
  141. package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
  142. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts +2 -0
  143. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  144. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +3 -1
  145. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  146. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -1
  147. package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  148. package/packages/pi-coding-agent/dist/core/tools/index.js +1 -0
  149. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  150. package/packages/pi-coding-agent/dist/core/tools/ls.d.ts +2 -0
  151. package/packages/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
  152. package/packages/pi-coding-agent/dist/core/tools/ls.js +10 -3
  153. package/packages/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
  154. package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -0
  155. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  156. package/packages/pi-coding-agent/dist/core/tools/read.js +3 -1
  157. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  158. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +7 -62
  159. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -1
  160. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts +2 -0
  161. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts.map +1 -0
  162. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js +115 -0
  163. package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js.map +1 -0
  164. package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts +19 -0
  165. package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts.map +1 -0
  166. package/packages/pi-coding-agent/dist/core/tools/tool-target.js +20 -0
  167. package/packages/pi-coding-agent/dist/core/tools/tool-target.js.map +1 -0
  168. package/packages/pi-coding-agent/dist/core/tools/write.d.ts +4 -0
  169. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  170. package/packages/pi-coding-agent/dist/core/tools/write.js +9 -1
  171. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  172. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +89 -2
  173. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  174. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +25 -1
  175. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  176. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +5 -0
  177. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  178. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +153 -8
  179. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  180. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  181. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +18 -1
  182. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +23 -5
  184. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
  186. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +19 -0
  188. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +23 -5
  190. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -1
  191. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +3 -1
  192. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
  193. package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +22 -66
  194. package/packages/pi-coding-agent/src/core/tools/bash.ts +4 -1
  195. package/packages/pi-coding-agent/src/core/tools/edit.ts +13 -1
  196. package/packages/pi-coding-agent/src/core/tools/find.ts +15 -6
  197. package/packages/pi-coding-agent/src/core/tools/grep.ts +13 -3
  198. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +4 -1
  199. package/packages/pi-coding-agent/src/core/tools/index.ts +8 -0
  200. package/packages/pi-coding-agent/src/core/tools/ls.ts +11 -3
  201. package/packages/pi-coding-agent/src/core/tools/read.ts +4 -1
  202. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +11 -72
  203. package/packages/pi-coding-agent/src/core/tools/tool-target-metadata.test.ts +127 -0
  204. package/packages/pi-coding-agent/src/core/tools/tool-target.ts +48 -0
  205. package/packages/pi-coding-agent/src/core/tools/write.ts +14 -2
  206. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +119 -2
  207. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +31 -1
  208. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +177 -8
  209. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +24 -5
  210. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +17 -1
  211. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +21 -0
  212. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +25 -8
  213. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  214. package/src/resources/extensions/claude-code-cli/readiness.ts +25 -7
  215. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +30 -0
  216. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
  217. package/src/resources/extensions/github-sync/sync.ts +8 -1
  218. package/src/resources/extensions/github-sync/tests/sync-source.test.ts +6 -18
  219. package/src/resources/extensions/gsd/auto/loop.ts +84 -8
  220. package/src/resources/extensions/gsd/auto/phases.ts +43 -8
  221. package/src/resources/extensions/gsd/auto/resolve.ts +19 -0
  222. package/src/resources/extensions/gsd/auto/run-unit.ts +3 -0
  223. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
  224. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
  225. package/src/resources/extensions/gsd/auto-post-unit.ts +93 -78
  226. package/src/resources/extensions/gsd/auto-start.ts +56 -6
  227. package/src/resources/extensions/gsd/auto-worktree.ts +118 -72
  228. package/src/resources/extensions/gsd/auto.ts +121 -29
  229. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +76 -12
  230. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +20 -26
  231. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +27 -12
  232. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +7 -9
  233. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +4 -7
  234. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +6 -10
  235. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -9
  236. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +1 -1
  237. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +64 -26
  238. package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +4 -0
  239. package/src/resources/extensions/gsd/commands/handlers/ops.ts +4 -2
  240. package/src/resources/extensions/gsd/commands-config.ts +1 -1
  241. package/src/resources/extensions/gsd/commands-eval-review.ts +2 -2
  242. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  243. package/src/resources/extensions/gsd/db/unit-dispatches.ts +66 -0
  244. package/src/resources/extensions/gsd/git-service.ts +41 -2
  245. package/src/resources/extensions/gsd/guided-flow.ts +19 -4
  246. package/src/resources/extensions/gsd/init-wizard.ts +5 -1
  247. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -4
  248. package/src/resources/extensions/gsd/slice-cadence.ts +49 -2
  249. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +23 -9
  250. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +59 -89
  251. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +47 -172
  252. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +0 -35
  253. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +35 -9
  254. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +15 -0
  255. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +80 -59
  256. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +3 -47
  257. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +76 -18
  258. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +106 -0
  259. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +54 -95
  260. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +67 -26
  261. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +32 -30
  262. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +32 -128
  263. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +20 -54
  264. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +20 -30
  265. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +17 -29
  266. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +138 -0
  267. package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +21 -39
  268. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +15 -24
  269. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +44 -29
  270. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +39 -51
  271. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +1 -217
  272. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +15 -32
  273. package/src/resources/extensions/gsd/tests/browser-teardown.test.ts +0 -41
  274. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +34 -27
  275. package/src/resources/extensions/gsd/tests/cmux.test.ts +51 -53
  276. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +39 -61
  277. package/src/resources/extensions/gsd/tests/commands-config.test.ts +26 -19
  278. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
  279. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +29 -33
  280. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +45 -108
  281. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +35 -31
  282. package/src/resources/extensions/gsd/tests/cwd-fallback-hardening.test.ts +138 -0
  283. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +4 -68
  284. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +4 -9
  285. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +14 -65
  286. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +44 -37
  287. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +58 -40
  288. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +25 -15
  289. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +35 -17
  290. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +16 -21
  291. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +15 -82
  292. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +2 -20
  293. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +18 -26
  294. package/src/resources/extensions/gsd/tests/init-skip-git.test.ts +9 -12
  295. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +40 -0
  296. package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +4 -2
  297. package/src/resources/extensions/gsd/tests/integration/git-locale.test.ts +31 -20
  298. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +12 -0
  299. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +0 -47
  300. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +60 -202
  301. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +13 -59
  302. package/src/resources/extensions/gsd/tests/lazy-pi-tui-import.test.ts +44 -6
  303. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +21 -35
  304. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +79 -98
  305. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +70 -278
  306. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +37 -30
  307. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +32 -28
  308. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +24 -37
  309. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +9 -24
  310. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +113 -0
  311. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +36 -22
  312. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +36 -30
  313. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +74 -4
  314. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +20 -22
  315. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +130 -32
  316. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +18 -36
  317. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +35 -73
  318. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +76 -138
  319. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +70 -125
  320. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +59 -161
  321. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +33 -29
  322. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +22 -196
  323. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +23 -93
  324. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +50 -79
  325. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +27 -13
  326. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +151 -251
  327. package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +41 -29
  328. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +58 -90
  329. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +32 -164
  330. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +57 -41
  331. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +14 -9
  332. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
  333. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +61 -1
  334. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +44 -42
  335. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +56 -24
  336. package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +51 -11
  337. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +23 -0
  338. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +66 -50
  339. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +68 -107
  340. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +115 -42
  341. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +21 -97
  342. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +25 -116
  343. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +21 -57
  344. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +29 -76
  345. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +33 -24
  346. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +39 -30
  347. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +33 -47
  348. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +48 -46
  349. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +14 -102
  350. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +78 -232
  351. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +32 -35
  352. package/src/resources/extensions/gsd/tests/token-profile.test.ts +84 -309
  353. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +134 -341
  354. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +8 -25
  355. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +50 -1
  356. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +6 -101
  357. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +43 -36
  358. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -444
  359. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
  360. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +44 -189
  361. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -57
  362. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
  363. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +21 -44
  364. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +27 -26
  365. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +14 -13
  366. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -18
  367. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +36 -0
  368. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -13
  369. package/src/resources/extensions/gsd/tools/complete-milestone.ts +14 -15
  370. package/src/resources/extensions/gsd/tools/complete-task.ts +1 -1
  371. package/src/resources/extensions/gsd/worktree-resolver.ts +34 -1
  372. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +86 -40
  373. package/src/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
  374. package/dist/web/standalone/.next/static/chunks/8336.631939fb583761fa.js +0 -10
  375. /package/dist/web/standalone/.next/static/{O2WvnXROue6l7nAp_4dhC → G68KoLv5claox_Dyd4pZn}/_buildManifest.js +0 -0
  376. /package/dist/web/standalone/.next/static/{O2WvnXROue6l7nAp_4dhC → G68KoLv5claox_Dyd4pZn}/_ssgManifest.js +0 -0
@@ -1,3 +1,5 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Registers Context Mode execution tools.
1
3
  // GSD2 — Exec (context-mode) tool registration.
2
4
  //
3
5
  // Exposes the Context Mode runtime tools in-process. Default-on; opt out with
@@ -6,12 +8,8 @@
6
8
  import { Type } from "@sinclair/typebox";
7
9
  import type { ExtensionAPI } from "@gsd/pi-coding-agent";
8
10
 
9
- function toolWorkspaceRoot(ctx: unknown): string {
10
- if (ctx && typeof ctx === "object" && typeof (ctx as { cwd?: unknown }).cwd === "string") {
11
- return (ctx as { cwd: string }).cwd;
12
- }
13
- return process.cwd();
14
- }
11
+ import { resolveCtxCwd } from "./dynamic-tools.js";
12
+
15
13
 
16
14
  async function loadContextModePreferences(baseDir: string) {
17
15
  const [{ loadEffectiveGSDPreferences }, { logWarning }] = await Promise.all([
@@ -61,7 +59,7 @@ export function registerExecTools(pi: ExtensionAPI): void {
61
59
  }),
62
60
  async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
63
61
  const { executeGsdExec } = await import("../tools/exec-tool.js");
64
- const baseDir = toolWorkspaceRoot(_ctx);
62
+ const baseDir = resolveCtxCwd(_ctx);
65
63
  return executeGsdExec(params as Parameters<typeof executeGsdExec>[0], {
66
64
  baseDir,
67
65
  preferences: await loadContextModePreferences(baseDir),
@@ -92,7 +90,7 @@ export function registerExecTools(pi: ExtensionAPI): void {
92
90
  }),
93
91
  async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
94
92
  const { executeExecSearch } = await import("../tools/exec-search-tool.js");
95
- const baseDir = toolWorkspaceRoot(_ctx);
93
+ const baseDir = resolveCtxCwd(_ctx);
96
94
  return executeExecSearch(params as Parameters<typeof executeExecSearch>[0], {
97
95
  baseDir,
98
96
  preferences: await loadContextModePreferences(baseDir),
@@ -115,7 +113,7 @@ export function registerExecTools(pi: ExtensionAPI): void {
115
113
  parameters: Type.Object({}),
116
114
  async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
117
115
  const { executeResume } = await import("../tools/resume-tool.js");
118
- const baseDir = toolWorkspaceRoot(_ctx);
116
+ const baseDir = resolveCtxCwd(_ctx);
119
117
  return executeResume(params as Parameters<typeof executeResume>[0], {
120
118
  baseDir,
121
119
  preferences: await loadContextModePreferences(baseDir),
@@ -1,15 +1,12 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Registers journal query tools.
1
3
  import { Type } from "@sinclair/typebox";
2
4
  import type { ExtensionAPI } from "@gsd/pi-coding-agent";
3
5
 
4
6
  import { queryJournal } from "../journal.js";
5
7
  import { logWarning } from "../workflow-logger.js";
8
+ import { resolveCtxCwd } from "./dynamic-tools.js";
6
9
 
7
- function toolWorkspaceRoot(ctx: unknown): string {
8
- if (ctx && typeof ctx === "object" && typeof (ctx as { cwd?: unknown }).cwd === "string") {
9
- return (ctx as { cwd: string }).cwd;
10
- }
11
- return process.cwd();
12
- }
13
10
 
14
11
  export function registerJournalTools(pi: ExtensionAPI): void {
15
12
  pi.registerTool({
@@ -43,7 +40,7 @@ export function registerJournalTools(pi: ExtensionAPI): void {
43
40
  if (params.after !== undefined) filters.after = params.after;
44
41
  if (params.before !== undefined) filters.before = params.before;
45
42
 
46
- const entries = queryJournal(toolWorkspaceRoot(_ctx), filters);
43
+ const entries = queryJournal(resolveCtxCwd(_ctx), filters);
47
44
  const limited = entries.slice(0, params.limit ?? 100);
48
45
 
49
46
  if (limited.length === 0) {
@@ -1,3 +1,5 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Registers memory-layer tools.
1
3
  // GSD2 — Memory tool registration
2
4
  //
3
5
  // Exposes the memory-layer tools (capture_thought, memory_query, gsd_graph)
@@ -7,19 +9,13 @@
7
9
  import { Type } from "@sinclair/typebox";
8
10
  import type { ExtensionAPI } from "@gsd/pi-coding-agent";
9
11
 
10
- import { ensureDbOpen } from "./dynamic-tools.js";
12
+ import { ensureDbOpen, resolveCtxCwd } from "./dynamic-tools.js";
11
13
  import {
12
14
  executeGsdGraph,
13
15
  executeMemoryCapture,
14
16
  executeMemoryQuery,
15
17
  } from "../tools/memory-tools.js";
16
18
 
17
- function toolWorkspaceRoot(ctx: unknown): string {
18
- if (ctx && typeof ctx === "object" && typeof (ctx as { cwd?: unknown }).cwd === "string") {
19
- return (ctx as { cwd: string }).cwd;
20
- }
21
- return process.cwd();
22
- }
23
19
 
24
20
  export function registerMemoryTools(pi: ExtensionAPI): void {
25
21
  // ─── capture_thought ────────────────────────────────────────────────────
@@ -64,7 +60,7 @@ export function registerMemoryTools(pi: ExtensionAPI): void {
64
60
  ),
65
61
  }),
66
62
  async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
67
- const ok = await ensureDbOpen(toolWorkspaceRoot(_ctx));
63
+ const ok = await ensureDbOpen(resolveCtxCwd(_ctx));
68
64
  if (!ok) {
69
65
  return {
70
66
  content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot capture memory." }],
@@ -115,7 +111,7 @@ export function registerMemoryTools(pi: ExtensionAPI): void {
115
111
  ),
116
112
  }),
117
113
  async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
118
- const ok = await ensureDbOpen(toolWorkspaceRoot(_ctx));
114
+ const ok = await ensureDbOpen(resolveCtxCwd(_ctx));
119
115
  if (!ok) {
120
116
  return {
121
117
  content: [{ type: "text" as const, text: "Error: GSD database is not available. Cannot query memory." }],
@@ -156,7 +152,7 @@ export function registerMemoryTools(pi: ExtensionAPI): void {
156
152
  ], { description: "Only include edges with this relation type" })),
157
153
  }),
158
154
  async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
159
- const ok = await ensureDbOpen(toolWorkspaceRoot(_ctx));
155
+ const ok = await ensureDbOpen(resolveCtxCwd(_ctx));
160
156
  if (!ok) {
161
157
  return {
162
158
  content: [{ type: "text" as const, text: "Error: GSD database is not available." }],
@@ -1,15 +1,11 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Registers read-only DB query tools.
1
3
  // GSD2 — Read-only query tools exposing DB state to the LLM via the WAL connection
2
4
 
3
5
  import { Type } from "@sinclair/typebox";
4
6
  import type { ExtensionAPI } from "@gsd/pi-coding-agent";
5
- import { ensureDbOpen } from "./dynamic-tools.js";
7
+ import { ensureDbOpen, resolveCtxCwd } from "./dynamic-tools.js";
6
8
 
7
- function toolWorkspaceRoot(ctx: unknown): string {
8
- if (ctx && typeof ctx === "object" && typeof (ctx as { cwd?: unknown }).cwd === "string") {
9
- return (ctx as { cwd: string }).cwd;
10
- }
11
- return process.cwd();
12
- }
13
9
 
14
10
  export function registerQueryTools(pi: ExtensionAPI): void {
15
11
  pi.registerTool({
@@ -27,7 +23,7 @@ export function registerQueryTools(pi: ExtensionAPI): void {
27
23
  milestoneId: Type.String({ description: "Milestone ID to query (e.g. M001)" }),
28
24
  }),
29
25
  async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
30
- const dbAvailable = await ensureDbOpen(toolWorkspaceRoot(_ctx));
26
+ const dbAvailable = await ensureDbOpen(resolveCtxCwd(_ctx));
31
27
  if (!dbAvailable) {
32
28
  return {
33
29
  content: [{ type: "text", text: "Error: GSD database is not available. Cannot read milestone status." }],
@@ -54,7 +50,7 @@ export function registerQueryTools(pi: ExtensionAPI): void {
54
50
  ],
55
51
  parameters: Type.Object({}),
56
52
  async execute(_toolCallId, _params, _signal, _onUpdate, _ctx) {
57
- const dbAvailable = await ensureDbOpen(toolWorkspaceRoot(_ctx));
53
+ const dbAvailable = await ensureDbOpen(resolveCtxCwd(_ctx));
58
54
  if (!dbAvailable) {
59
55
  return {
60
56
  content: [{ type: "text", text: "Error: GSD database is not available. Cannot checkpoint." }],
@@ -43,7 +43,7 @@ export function handleRecoverableExtensionProcessError(err: Error): boolean {
43
43
  return false;
44
44
  }
45
45
 
46
- function installEpipeGuard(): void {
46
+ export function installEpipeGuard(): void {
47
47
  if (!process.listeners("uncaughtException").some((listener) => listener.name === "_gsdEpipeGuard")) {
48
48
  const _gsdEpipeGuard = (err: Error): void => {
49
49
  if (handleRecoverableExtensionProcessError(err)) return;
@@ -1,7 +1,9 @@
1
1
  // Project/App: GSD-2
2
2
  // File Purpose: Registers GSD extension runtime hooks and token-saving tool policies.
3
3
 
4
- import { join } from "node:path";
4
+ import { existsSync } from "node:fs";
5
+ import { dirname, join } from "node:path";
6
+ import { pathToFileURL } from "node:url";
5
7
 
6
8
  import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
7
9
  import { isToolCallEventType } from "@gsd/pi-coding-agent";
@@ -30,9 +32,6 @@ import { extractSubagentAgentClasses } from "./subagent-input.js";
30
32
  import { approvalGateIdForUnit, isExplicitApprovalResponse, shouldPauseForUserApprovalQuestion } from "../user-input-boundary.js";
31
33
  import { resolveSkillManifest } from "../skill-manifest.js";
32
34
 
33
- // Skip the welcome screen on the very first session_start — cli.ts already
34
- // printed it before the TUI launched. Only re-print on /clear (subsequent sessions).
35
- let isFirstSession = true;
36
35
  let approvalQuestionAbortInFlight = false;
37
36
 
38
37
  interface DeferredApprovalGate {
@@ -40,6 +39,66 @@ interface DeferredApprovalGate {
40
39
  basePath: string;
41
40
  }
42
41
 
42
+ type WelcomeScreenModule = {
43
+ buildWelcomeScreenLines(opts: { version: string; remoteChannel?: string; width?: number }): string[];
44
+ };
45
+
46
+ async function loadWelcomeScreenModule(): Promise<WelcomeScreenModule | undefined> {
47
+ const candidates: string[] = [];
48
+ const gsdBinPath = process.env.GSD_BIN_PATH;
49
+ if (gsdBinPath) {
50
+ candidates.push(join(dirname(gsdBinPath), "welcome-screen.js"));
51
+ }
52
+
53
+ const packageRoot = process.env.GSD_PKG_ROOT;
54
+ if (packageRoot) {
55
+ candidates.push(join(packageRoot, "dist", "welcome-screen.js"));
56
+ candidates.push(join(packageRoot, "src", "welcome-screen.ts"));
57
+ }
58
+
59
+ for (const candidate of candidates) {
60
+ try {
61
+ if (!existsSync(candidate)) continue;
62
+ const mod = await import(pathToFileURL(candidate).href) as Partial<WelcomeScreenModule>;
63
+ if (typeof mod.buildWelcomeScreenLines === "function") {
64
+ return mod as WelcomeScreenModule;
65
+ }
66
+ } catch {
67
+ // Try the next package layout.
68
+ }
69
+ }
70
+ return undefined;
71
+ }
72
+
73
+ async function installWelcomeHeader(ctx: ExtensionContext): Promise<void> {
74
+ if (!ctx.hasUI || typeof ctx.ui?.setHeader !== "function") return;
75
+
76
+ try {
77
+ const welcome = await loadWelcomeScreenModule();
78
+ if (!welcome) return;
79
+
80
+ let remoteChannel: string | undefined;
81
+ try {
82
+ const { resolveRemoteConfig } = await import("../../remote-questions/config.js");
83
+ const rc = resolveRemoteConfig();
84
+ if (rc) remoteChannel = rc.channel;
85
+ } catch { /* non-fatal */ }
86
+
87
+ ctx.ui.setHeader(() => ({
88
+ render(width: number): string[] {
89
+ return welcome.buildWelcomeScreenLines({
90
+ version: process.env.GSD_VERSION || "0.0.0",
91
+ remoteChannel,
92
+ width,
93
+ });
94
+ },
95
+ invalidate(): void {},
96
+ }));
97
+ } catch {
98
+ /* non-fatal */
99
+ }
100
+ }
101
+
43
102
  let deferredApprovalGate: DeferredApprovalGate | null = null;
44
103
 
45
104
  export const MINIMAL_GSD_TOOL_NAMES = [
@@ -382,28 +441,7 @@ export function registerHooks(
382
441
  const prefs = loadEffectiveGSDPreferences(basePath);
383
442
  process.env.GSD_SHOW_TOKEN_COST = prefs?.preferences.show_token_cost ? "1" : "";
384
443
  } catch { /* non-fatal */ }
385
- if (isFirstSession) {
386
- isFirstSession = false;
387
- } else {
388
- try {
389
- const gsdBinPath = process.env.GSD_BIN_PATH;
390
- if (gsdBinPath) {
391
- const { dirname } = await import("node:path");
392
- const { printWelcomeScreen } = await import(
393
- join(dirname(gsdBinPath), "welcome-screen.js")
394
- ) as { printWelcomeScreen: (opts: { version: string; modelName?: string; provider?: string; remoteChannel?: string }) => void };
395
-
396
- let remoteChannel: string | undefined;
397
- try {
398
- const { resolveRemoteConfig } = await import("../../remote-questions/config.js");
399
- const rc = resolveRemoteConfig();
400
- if (rc) remoteChannel = rc.channel;
401
- } catch { /* non-fatal */ }
402
-
403
- printWelcomeScreen({ version: process.env.GSD_VERSION || "0.0.0", remoteChannel });
404
- }
405
- } catch { /* non-fatal */ }
406
- }
444
+ await installWelcomeHeader(ctx);
407
445
  await loadToolApiKeysForSession();
408
446
  if (isAutoActive()) {
409
447
  ctx.ui.setWidget("gsd-health", undefined);
@@ -39,6 +39,8 @@ function toStrArray(v: unknown): string[] {
39
39
  * CompleteMilestoneParams, tolerating type mismatches from LLM JSON quirks.
40
40
  */
41
41
  export function sanitizeCompleteMilestoneParams(raw: Record<string, unknown>): CompleteMilestoneParams {
42
+ const actorName = toStr(raw.actorName);
43
+ const triggerReason = toStr(raw.triggerReason);
42
44
  return {
43
45
  milestoneId: toStr(raw.milestoneId),
44
46
  title: toStr(raw.title),
@@ -53,5 +55,7 @@ export function sanitizeCompleteMilestoneParams(raw: Record<string, unknown>): C
53
55
  followUps: toStr(raw.followUps),
54
56
  deviations: toStr(raw.deviations),
55
57
  verificationPassed: raw.verificationPassed === true || raw.verificationPassed === "true",
58
+ ...(actorName ? { actorName } : {}),
59
+ ...(triggerReason ? { triggerReason } : {}),
56
60
  };
57
61
  }
@@ -1,3 +1,5 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Handles operational /gsd subcommands.
1
3
  import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
2
4
 
3
5
  import { enableDebug } from "../../debug-logger.js";
@@ -15,7 +17,7 @@ import { handleRemote } from "../../../remote-questions/mod.js";
15
17
  import { handleShip } from "../../commands-ship.js";
16
18
  import { handleSessionReport } from "../../commands-session-report.js";
17
19
  import { handlePrBranch } from "../../commands-pr-branch.js";
18
- import { projectRoot } from "../context.js";
20
+ import { currentDirectoryRoot, projectRoot } from "../context.js";
19
21
 
20
22
  export async function handleOpsCommand(trimmed: string, ctx: ExtensionCommandContext, pi: ExtensionAPI): Promise<boolean> {
21
23
  if (trimmed === "init") {
@@ -117,7 +119,7 @@ export async function handleOpsCommand(trimmed: string, ctx: ExtensionCommandCon
117
119
  return true;
118
120
  }
119
121
  if (trimmed === "triage") {
120
- await handleTriage(ctx, pi, process.cwd());
122
+ await handleTriage(ctx, pi, currentDirectoryRoot());
121
123
  return true;
122
124
  }
123
125
  if (trimmed === "config") {
@@ -23,7 +23,7 @@ export const TOOL_KEYS = [
23
23
  { id: "groq", env: "GROQ_API_KEY", label: "Groq Voice", hint: "console.groq.com" },
24
24
  ] as const;
25
25
 
26
- function getStoredToolKey(auth: AuthStorage, providerId: string): string | undefined {
26
+ export function getStoredToolKey(auth: AuthStorage, providerId: string): string | undefined {
27
27
  const creds = auth.getCredentialsForProvider(providerId);
28
28
  const cred = creds.find((c) => c.type === "api_key" && c.key);
29
29
  return cred?.type === "api_key" ? cred.key : undefined;
@@ -26,7 +26,7 @@
26
26
 
27
27
  import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
28
28
 
29
- import { existsSync } from "node:fs";
29
+ import { existsSync, realpathSync } from "node:fs";
30
30
  import { open, readFile } from "node:fs/promises";
31
31
  import { join, relative } from "node:path";
32
32
 
@@ -304,7 +304,7 @@ export async function buildEvalReviewContext(
304
304
  }
305
305
 
306
306
  const truncated = summaryRead.truncated || specTruncated;
307
- const outputPath = evalReviewWritePath(state.sliceDir, state.sliceId);
307
+ const outputPath = evalReviewWritePath(realpathSync(state.sliceDir), state.sliceId);
308
308
  const basePath = projectRoot();
309
309
  const relativeOutputPath = relative(basePath, outputPath);
310
310
 
@@ -29,7 +29,7 @@ import { computeProgressScore, formatProgressLine } from "./progress-score.js";
29
29
  import { runEnvironmentChecks, type EnvironmentCheckResult } from "./doctor-environment.js";
30
30
  import { formattedShortcutPair } from "./shortcut-defs.js";
31
31
 
32
- function unitLabel(type: string): string {
32
+ export function unitLabel(type: string): string {
33
33
  switch (type) {
34
34
  case "discuss-milestone":
35
35
  case "discuss-slice": return "Discuss";
@@ -98,6 +98,70 @@ function isAlreadyActiveConstraintError(err: unknown): boolean {
98
98
  return /\bUNIQUE\b|\bconstraint failed\b/i.test(msg);
99
99
  }
100
100
 
101
+ function settleStaleActiveDispatchForUnit(input: RecordClaimInput, now: string): void {
102
+ const db = _getAdapter()!;
103
+ const active = db.prepare(
104
+ `SELECT id, status, worker_id, milestone_lease_token
105
+ FROM unit_dispatches
106
+ WHERE unit_id = :unit_id
107
+ AND status IN ('claimed','running')
108
+ ORDER BY id DESC
109
+ LIMIT 1`,
110
+ ).get({ ":unit_id": input.unitId }) as
111
+ | { id: number; status: DispatchStatus; worker_id: string; milestone_lease_token: number }
112
+ | undefined;
113
+
114
+ if (!active) return;
115
+ if (
116
+ active.worker_id === input.workerId &&
117
+ active.milestone_lease_token === input.milestoneLeaseToken
118
+ ) {
119
+ return;
120
+ }
121
+
122
+ const reason = "stale-dispatch-lease-takeover";
123
+ const result = db.prepare(
124
+ `UPDATE unit_dispatches
125
+ SET status = 'canceled',
126
+ ended_at = :ended_at,
127
+ exit_reason = :reason
128
+ WHERE id = :id
129
+ AND status IN ('claimed','running')
130
+ AND (worker_id != :worker_id OR milestone_lease_token != :token)`,
131
+ ).run({
132
+ ":id": active.id,
133
+ ":ended_at": now,
134
+ ":reason": reason,
135
+ ":worker_id": input.workerId,
136
+ ":token": input.milestoneLeaseToken,
137
+ });
138
+
139
+ const changes =
140
+ typeof (result as { changes?: unknown }).changes === "number"
141
+ ? (result as { changes: number }).changes
142
+ : 0;
143
+ if (changes < 1) return;
144
+
145
+ insertAuditEvent({
146
+ eventId: randomUUID(),
147
+ traceId: input.traceId,
148
+ turnId: input.turnId ?? undefined,
149
+ category: "orchestration",
150
+ type: "dispatch-stale-canceled",
151
+ ts: now,
152
+ payload: {
153
+ dispatchId: active.id,
154
+ unitId: input.unitId,
155
+ priorStatus: active.status,
156
+ priorWorkerId: active.worker_id,
157
+ priorMilestoneLeaseToken: active.milestone_lease_token,
158
+ takeoverWorkerId: input.workerId,
159
+ takeoverMilestoneLeaseToken: input.milestoneLeaseToken,
160
+ reason,
161
+ },
162
+ });
163
+ }
164
+
101
165
  /**
102
166
  * Insert a new dispatch row in `claimed` state. Atomic guard against
103
167
  * double-claim (B2): the partial unique index
@@ -135,6 +199,8 @@ export function recordDispatchClaim(input: RecordClaimInput): RecordClaimResult
135
199
  };
136
200
  }
137
201
 
202
+ settleStaleActiveDispatchForUnit(input, now);
203
+
138
204
  try {
139
205
  const result = db.prepare(
140
206
  `INSERT INTO unit_dispatches (
@@ -1,3 +1,5 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Git operations, commit-message formatting, and turn git actions.
1
3
  /**
2
4
  * GSD Git Service
3
5
  *
@@ -129,6 +131,11 @@ export interface TurnGitActionResult {
129
131
  export interface TaskCommitContext {
130
132
  taskId: string;
131
133
  taskTitle: string;
134
+ milestoneId?: string;
135
+ milestoneTitle?: string;
136
+ sliceId?: string;
137
+ sliceTitle?: string;
138
+ taskDisplayId?: string;
132
139
  /** The one-liner from the task summary (e.g. "Added retry-aware worker status logging") */
133
140
  oneLiner?: string;
134
141
  /** Files modified by this task (from task summary frontmatter) */
@@ -170,6 +177,11 @@ export function buildTaskCommitMessage(ctx: TaskCommitContext): string {
170
177
  bodyParts.push(fileLines);
171
178
  }
172
179
 
180
+ const contextLines = buildTaskCommitContextLines(ctx);
181
+ if (contextLines.length > 0) {
182
+ bodyParts.push(`GSD context:\n${contextLines.join("\n")}`);
183
+ }
184
+
173
185
  // Trailers: GSD-Task first, then Resolves
174
186
  bodyParts.push(`GSD-Task: ${ctx.taskId}`);
175
187
 
@@ -180,6 +192,28 @@ export function buildTaskCommitMessage(ctx: TaskCommitContext): string {
180
192
  return `${subject}\n\n${bodyParts.join("\n\n")}`;
181
193
  }
182
194
 
195
+ function buildTaskCommitContextLines(ctx: TaskCommitContext): string[] {
196
+ const lines: string[] = [];
197
+ const milestone = formatNamedContext(ctx.milestoneId, ctx.milestoneTitle);
198
+ const slice = formatNamedContext(ctx.sliceId, ctx.sliceTitle);
199
+ const taskId = ctx.taskDisplayId ?? ctx.taskId.split("/").pop();
200
+ const task = formatNamedContext(taskId, ctx.taskTitle);
201
+
202
+ if (milestone) lines.push(`- Milestone: ${milestone}`);
203
+ if (slice) lines.push(`- Slice: ${slice}`);
204
+ if (task) lines.push(`- Task: ${task}`);
205
+ return lines;
206
+ }
207
+
208
+ function formatNamedContext(id: string | undefined, title: string | undefined): string | null {
209
+ const cleanId = id?.trim();
210
+ const cleanTitle = title?.trim();
211
+ if (!cleanId && !cleanTitle) return null;
212
+ if (!cleanId) return cleanTitle ?? null;
213
+ if (!cleanTitle || cleanTitle === cleanId) return cleanId;
214
+ return `${cleanId} - ${cleanTitle}`;
215
+ }
216
+
183
217
  function sanitizeCommitSubjectDescription(value: string): string {
184
218
  const cleaned = value
185
219
  .replace(/[\x00-\x1F\x7F]+/g, " ")
@@ -1073,7 +1107,7 @@ export function createDraftPR(
1073
1107
  milestoneId: string,
1074
1108
  title: string,
1075
1109
  body: string,
1076
- opts?: { head?: string; base?: string },
1110
+ opts?: { head?: string; base?: string; env?: NodeJS.ProcessEnv },
1077
1111
  ): string | null {
1078
1112
  try {
1079
1113
  const args = [
@@ -1083,7 +1117,12 @@ export function createDraftPR(
1083
1117
  ];
1084
1118
  if (opts?.head) args.push("--head", opts.head);
1085
1119
  if (opts?.base) args.push("--base", opts.base);
1086
- const result = execFileSync("gh", args, { cwd: basePath, encoding: "utf8", timeout: 30000, env: GIT_NO_PROMPT_ENV });
1120
+ const result = execFileSync("gh", args, {
1121
+ cwd: basePath,
1122
+ encoding: "utf8",
1123
+ timeout: 30000,
1124
+ env: opts?.env ?? GIT_NO_PROMPT_ENV,
1125
+ });
1087
1126
  return result.trim();
1088
1127
  } catch {
1089
1128
  return null;
@@ -72,6 +72,10 @@ import { verifyExpectedArtifact } from "./auto-recovery.js";
72
72
  import { createWorkspace, scopeMilestone, type MilestoneScope } from "./workspace.js";
73
73
  import { getPendingGate, extractDepthVerificationMilestoneId } from "./bootstrap/write-gate.js";
74
74
 
75
+ export function shouldSkipGitBootstrapAfterInit(result: { gitEnabled?: boolean }): boolean {
76
+ return result.gitEnabled === false;
77
+ }
78
+
75
79
  // ─── Re-exports (preserve public API for existing importers) ────────────────
76
80
  export {
77
81
  MILESTONE_ID_RE, generateMilestoneSuffix, nextMilestoneId,
@@ -205,6 +209,16 @@ function runPlanV2Gate(
205
209
  return "pass";
206
210
  }
207
211
 
212
+ export const _needsPlanV2GateForTest = needsPlanV2Gate;
213
+ export const _runPlanV2GateForTest = runPlanV2Gate;
214
+
215
+ export function _roadmapHasParseableSlicesForTest(
216
+ roadmapContent: string | null | undefined,
217
+ ): boolean {
218
+ if (!roadmapContent) return false;
219
+ return parseRoadmapSlices(roadmapContent).length > 0;
220
+ }
221
+
208
222
  // ─── Commit Instruction Helpers ──────────────────────────────────────────────
209
223
 
210
224
  /** Build commit instruction for planning prompts. .gsd/ is managed externally and always gitignored. */
@@ -266,7 +280,7 @@ const USER_DRIVEN_DEEP_SETUP_UNITS = new Set([
266
280
  "discuss-requirements",
267
281
  "research-decision",
268
282
  ]);
269
- const FOREGROUND_DEEP_SETUP_RULE_NAMES = new Set([
283
+ export const FOREGROUND_DEEP_SETUP_RULE_NAMES = new Set([
270
284
  "deep: pre-planning (no workflow prefs) → workflow-preferences",
271
285
  "deep: pre-planning (no PROJECT) → discuss-project",
272
286
  "deep: pre-planning (no REQUIREMENTS) → discuss-requirements",
@@ -1122,6 +1136,8 @@ async function dispatchWorkflow(
1122
1136
  }
1123
1137
  }
1124
1138
 
1139
+ export const _dispatchWorkflowForTest = dispatchWorkflow;
1140
+
1125
1141
  function getStructuredQuestionsAvailability(
1126
1142
  pi: ExtensionAPI,
1127
1143
  ctx: ExtensionContext | undefined,
@@ -2022,7 +2038,7 @@ export async function showSmartEntry(
2022
2038
  // No .gsd/ or zombie .gsd/ — run the project init wizard
2023
2039
  const result = await showProjectInit(ctx, pi, basePath, detection);
2024
2040
  if (!result.completed) return; // User cancelled
2025
- skipGitBootstrap = result.gitEnabled === false;
2041
+ skipGitBootstrap = shouldSkipGitBootstrapAfterInit(result);
2026
2042
 
2027
2043
  // Init wizard bootstrapped .gsd/ — fall through to the normal flow below
2028
2044
  // which will detect "no milestones" and start the discuss prompt
@@ -2381,8 +2397,7 @@ export async function showSmartEntry(
2381
2397
  if (hasRoadmap) {
2382
2398
  const roadmapContent = await loadFile(roadmapFile!);
2383
2399
  if (roadmapContent) {
2384
- const parsed = parseRoadmapSlices(roadmapContent);
2385
- roadmapHasSlices = parsed.length > 0;
2400
+ roadmapHasSlices = _roadmapHasParseableSlicesForTest(roadmapContent);
2386
2401
  }
2387
2402
  }
2388
2403
 
@@ -30,6 +30,10 @@ interface InitWizardResult {
30
30
  gitEnabled?: boolean;
31
31
  }
32
32
 
33
+ export function shouldWriteGitFiles(gitEnabled: boolean): boolean {
34
+ return gitEnabled;
35
+ }
36
+
33
37
  interface ProjectPreferences {
34
38
  mode: "solo" | "team";
35
39
  gitIsolation: "worktree" | "branch" | "none";
@@ -299,7 +303,7 @@ export async function showProjectInit(
299
303
 
300
304
  // Ensure .gitignore only when git is active. A user who selected "Skip"
301
305
  // should not have git initialized or git-related files mutated later.
302
- if (gitEnabled) {
306
+ if (shouldWriteGitFiles(gitEnabled)) {
303
307
  ensureGitignore(basePath);
304
308
  untrackRuntimeFiles(basePath);
305
309
  }
@@ -16,7 +16,7 @@ Preloaded context includes roadmap, requirements, decisions, project context, an
16
16
 
17
17
  Start with what the excerpts give you. Read full files when the section heads signal richer context you need.
18
18
 
19
- **On-demand Read ordering:** Complete all slice SUMMARY Reads you need for cross-slice synthesis, the Decision Re-evaluation table, and LEARNINGS **before** calling `gsd_complete_milestone` (step 12). Once that tool runs, the milestone is marked complete in the DB, so it must be the final persistent milestone-closeout write.
19
+ **On-demand Read ordering:** Complete all slice SUMMARY Reads you need for cross-slice synthesis, the Decision Re-evaluation table, and LEARNINGS **before** calling `gsd_complete_milestone` (step 13). Once that tool runs, the milestone is marked complete in the DB, so it must be the final persistent milestone-closeout write.
20
20
 
21
21
  ### Closeout Review Mode
22
22
 
@@ -45,7 +45,7 @@ Subagents report only; they do not write user source. Fold any findings into Dec
45
45
 
46
46
  ### Verification Gate — STOP if verification failed
47
47
 
48
- **If ANY verification failure was recorded in steps 3, 4, or 5, you MUST follow the failure path below. Do NOT proceed with steps 913.**
48
+ **If ANY verification failure was recorded in steps 4, 5, or 6, you MUST follow the failure path below. Do NOT proceed with steps 1014.**
49
49
 
50
50
  **Failure path** (verification failed):
51
51
  - Do NOT call `gsd_complete_milestone`.
@@ -69,13 +69,15 @@ Subagents report only; they do not write user source. Fold any findings into Dec
69
69
  - `title` (string) — Milestone title
70
70
  - `oneLiner` (string) — One-sentence summary of what the milestone achieved
71
71
  - `narrative` (string) — Detailed narrative of what happened during the milestone
72
+ - `verificationPassed` (boolean) — Must be `true`; confirms code-change verification, success criteria, and definition-of-done checks all passed
73
+
74
+ **Recommended parameters** (the schema accepts these as optional, but always fill them in — omitted values render as placeholders such as "Not provided.", "None.", or "(none)"):
72
75
  - `successCriteriaResults` (string) — Markdown detailing how each success criterion was met or not met
73
76
  - `definitionOfDoneResults` (string) — Markdown detailing how each definition-of-done item was met
74
77
  - `requirementOutcomes` (string) — Markdown detailing requirement status transitions with evidence
75
78
  - `keyDecisions` (array of strings) — Key architectural/pattern decisions made during the milestone
76
79
  - `keyFiles` (array of strings) — Key files created or modified during the milestone
77
80
  - `lessonsLearned` (array of strings) — Lessons learned during the milestone
78
- - `verificationPassed` (boolean) — Must be `true`; confirms code-change verification, success criteria, and definition-of-done checks all passed
79
81
 
80
82
  **Optional parameters:**
81
83
  - `followUps` (string) — Follow-up items for future milestones
@@ -84,6 +86,6 @@ Subagents report only; they do not write user source. Fold any findings into Dec
84
86
  14. Do not commit manually — the system auto-commits your changes after this unit completes.
85
87
  - Say: "Milestone {{milestoneId}} complete."
86
88
 
87
- **Important:** Do NOT skip code-change, success-criteria, or definition-of-done verification (steps 3-5). The summary must reflect verified outcomes. Verification failures block completion; there is no override. If a verification tool fails, errors, or returns unexpected output, treat it as failure.
89
+ **Important:** Do NOT skip code-change, success-criteria, or definition-of-done verification (steps 4-6). The summary must reflect verified outcomes. Verification failures block completion; there is no override. If a verification tool fails, errors, or returns unexpected output, treat it as failure.
88
90
 
89
91
  **File system safety:** When scanning milestone directories for evidence, use `ls` or `find` first. Never pass a directory path (e.g. `tasks/`, `slices/`) to `read`; it only accepts file paths.