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
@@ -9,12 +9,13 @@
9
9
 
10
10
  import { describe, test, beforeEach, afterEach } from "node:test";
11
11
  import assert from "node:assert/strict";
12
- import { existsSync, mkdtempSync, mkdirSync, readFileSync, writeFileSync, rmSync, readdirSync } from "node:fs";
12
+ import { existsSync, mkdtempSync, mkdirSync, writeFileSync, rmSync, readdirSync } from "node:fs";
13
13
  import { join } from "node:path";
14
14
  import { tmpdir } from "node:os";
15
15
  import { execSync } from "node:child_process";
16
16
 
17
17
  import { PROJECT_FILES, classifyProject } from "../detection.js";
18
+ import { _shouldProceedWithInvalidRepoClassificationForTest } from "../auto/phases.ts";
18
19
 
19
20
  // ─── Helpers ─────────────────────────────────────────────────────────────────
20
21
 
@@ -86,19 +87,19 @@ test("PROJECT_FILES is exported and contains expected multi-ecosystem entries",
86
87
  assert.ok(PROJECT_FILES.includes("Package.swift"), "includes Swift marker");
87
88
  });
88
89
 
89
- test("runUnitPhase fails closed when classification returns invalid-repo", () => {
90
- const source = readFileSync(join(process.cwd(), "src/resources/extensions/gsd/auto/phases.ts"), "utf-8");
91
- const invalidRepoBranch = source.slice(
92
- source.indexOf('projectClassification.kind === "invalid-repo"'),
93
- source.indexOf('projectClassification.kind === "greenfield"'),
90
+ test("invalid-repo classification only proceeds when the git marker was already confirmed", () => {
91
+ assert.equal(
92
+ _shouldProceedWithInvalidRepoClassificationForTest("missing .git", true),
93
+ true,
94
+ );
95
+ assert.equal(
96
+ _shouldProceedWithInvalidRepoClassificationForTest("missing .git", false),
97
+ false,
98
+ );
99
+ assert.equal(
100
+ _shouldProceedWithInvalidRepoClassificationForTest("permission denied", true),
101
+ false,
94
102
  );
95
-
96
- assert.match(invalidRepoBranch, /projectClassification\.reason === "missing \.git" && hasGit/);
97
- assert.match(invalidRepoBranch, /project classification could not confirm \.git/);
98
- assert.match(invalidRepoBranch, /ctx\.ui\.notify\(msg,\s*"error"\)/);
99
- assert.match(invalidRepoBranch, /await deps\.stopAuto\(ctx,\s*pi,\s*msg\)/);
100
- assert.match(invalidRepoBranch, /return \{ action: "break", reason: "worktree-invalid" \}/);
101
- assert.match(invalidRepoBranch, /classified as invalid-repo/);
102
103
  });
103
104
 
104
105
  describe("health check with git repo", () => {
@@ -1,25 +1,27 @@
1
- /**
2
- * Regression test for #3461: createAutoWorktree must use git.main_branch
3
- * preference when META.json integration branch is absent.
4
- */
1
+ // GSD-2 — Auto-worktree main branch preference regression tests.
2
+
5
3
  import { test } from "node:test";
6
4
  import assert from "node:assert/strict";
7
- import { readFileSync } from "node:fs";
8
- import { join } from "node:path";
9
5
 
10
- test("auto-worktree.ts includes main_branch preference in startPoint fallback (#3461)", () => {
11
- const src = readFileSync(
12
- join(import.meta.dirname, "..", "auto-worktree.ts"),
13
- "utf-8",
6
+ import { _resolveAutoWorktreeStartPointForTest } from "../auto-worktree.ts";
7
+
8
+ test("auto-worktree start point prefers milestone integration branch", () => {
9
+ const startPoint = _resolveAutoWorktreeStartPointForTest(
10
+ "release/integration",
11
+ "dev",
12
+ () => true,
14
13
  );
15
- // The fix adds gitPrefs?.main_branch to the startPoint fallback chain
16
- assert.ok(
17
- src.includes("gitPrefs?.main_branch") || src.includes("prefs.main_branch"),
18
- "createAutoWorktree must check git.main_branch preference before falling back to nativeDetectMainBranch",
14
+
15
+ assert.equal(startPoint, "release/integration");
16
+ });
17
+
18
+ test("auto-worktree start point uses git.main_branch only when it exists", () => {
19
+ assert.equal(
20
+ _resolveAutoWorktreeStartPointForTest(null, "dev", (branch) => branch === "dev"),
21
+ "dev",
19
22
  );
20
- assert.match(
21
- src,
22
- /nativeBranchExists\(basePath,\s*gitPrefs\.main_branch\)/,
23
- "createAutoWorktree must validate git.main_branch exists before using it",
23
+ assert.equal(
24
+ _resolveAutoWorktreeStartPointForTest(null, "stale", () => false),
25
+ undefined,
24
26
  );
25
27
  });
@@ -529,6 +529,42 @@ test("exitMilestone commits, tears down, and resets basePath", () => {
529
529
  assert.equal(findCalls(deps.calls, "invalidateAllCaches").length, 1);
530
530
  });
531
531
 
532
+ test("exitMilestone moves cwd to project root before teardown", (t) => {
533
+ const originalCwd = process.cwd();
534
+ const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-exit-cwd-")));
535
+ const wtPath = join(base, ".gsd", "worktrees", "M001");
536
+ mkdirSync(wtPath, { recursive: true });
537
+ t.after(() => {
538
+ process.chdir(originalCwd);
539
+ rmSync(base, { recursive: true, force: true });
540
+ });
541
+
542
+ process.chdir(wtPath);
543
+ const s = makeSession({
544
+ basePath: wtPath,
545
+ originalBasePath: base,
546
+ });
547
+ const deps = makeDeps({
548
+ isInAutoWorktree: () => true,
549
+ });
550
+ deps.teardownAutoWorktree = (
551
+ teardownBasePath: string,
552
+ milestoneId: string,
553
+ opts?: { preserveBranch?: boolean },
554
+ ) => {
555
+ deps.calls.push({ fn: "teardownAutoWorktree", args: [teardownBasePath, milestoneId, opts] });
556
+ assert.equal(process.cwd(), base);
557
+ rmSync(wtPath, { recursive: true, force: true });
558
+ };
559
+ const ctx = makeNotifyCtx();
560
+ const resolver = new WorktreeResolver(s, deps);
561
+
562
+ resolver.exitMilestone("M001", ctx);
563
+
564
+ assert.equal(process.cwd(), base);
565
+ assert.equal(s.basePath, base);
566
+ });
567
+
532
568
  test("exitMilestone is no-op when not in worktree", () => {
533
569
  const s = makeSession();
534
570
  const deps = makeDeps({
@@ -1,19 +1,25 @@
1
- /**
2
- * Regression test for #3441: guided flow must treat a roadmap with zero
3
- * parseable slices the same as no roadmap — offer "Create roadmap" not "Go auto".
4
- */
1
+ // GSD-2 — Guided roadmap slice detection regression tests.
2
+
5
3
  import { test } from "node:test";
6
4
  import assert from "node:assert/strict";
7
- import { readFileSync } from "node:fs";
8
- import { join } from "node:path";
9
5
 
10
- test("guided-flow checks roadmap slice count before offering auto (#3441)", () => {
11
- const src = readFileSync(
12
- join(import.meta.dirname, "..", "guided-flow.ts"),
13
- "utf-8",
6
+ import { _roadmapHasParseableSlicesForTest } from "../guided-flow.ts";
7
+
8
+ test("guided flow treats placeholder roadmaps with zero slices as not runnable", () => {
9
+ assert.equal(
10
+ _roadmapHasParseableSlicesForTest("# M001 Roadmap\n\nPlanning notes only.\n"),
11
+ false,
14
12
  );
15
- assert.ok(
16
- src.includes("roadmapHasSlices") || src.includes("parseRoadmapSlices"),
17
- "Guided flow must parse roadmap for slices before deciding which options to show",
13
+ });
14
+
15
+ test("guided flow accepts roadmaps with parseable slices", () => {
16
+ assert.equal(
17
+ _roadmapHasParseableSlicesForTest([
18
+ "# M001 Roadmap",
19
+ "",
20
+ "## Slices",
21
+ "- [ ] **S01: First slice** `risk:low` `depends:[]`",
22
+ ].join("\n")),
23
+ true,
18
24
  );
19
25
  });
@@ -32,21 +32,21 @@ export interface CompleteMilestoneParams {
32
32
  oneLiner: string;
33
33
  narrative: string;
34
34
  verificationPassed: boolean;
35
- /** @optional — defaults to "Not provided." when omitted by models with limited tool-calling */
35
+ /** @optional — empty/omitted renders as "Not provided." */
36
36
  successCriteriaResults?: string;
37
- /** @optional — defaults to "Not provided." when omitted */
37
+ /** @optional — empty/omitted renders as "Not provided." */
38
38
  definitionOfDoneResults?: string;
39
- /** @optional — defaults to "Not provided." when omitted */
39
+ /** @optional — empty/omitted renders as "Not provided." */
40
40
  requirementOutcomes?: string;
41
- /** @optional — defaults to [] when omitted */
41
+ /** @optional — empty/omitted renders as "(none)" */
42
42
  keyDecisions?: string[];
43
- /** @optional — defaults to [] when omitted */
43
+ /** @optional — empty/omitted renders as "(none)" */
44
44
  keyFiles?: string[];
45
- /** @optional — defaults to [] when omitted */
45
+ /** @optional — empty/omitted renders as "(none)" */
46
46
  lessonsLearned?: string[];
47
- /** @optional — defaults to "None." when omitted */
47
+ /** @optional — empty/omitted renders as "None." */
48
48
  followUps?: string;
49
- /** @optional — defaults to "None." when omitted */
49
+ /** @optional — empty/omitted renders as "None." */
50
50
  deviations?: string;
51
51
  /** Optional caller-provided identity for audit trail */
52
52
  actorName?: string;
@@ -61,8 +61,7 @@ export interface CompleteMilestoneResult {
61
61
  alreadyComplete?: boolean;
62
62
  }
63
63
 
64
- function renderMilestoneSummaryMarkdown(params: CompleteMilestoneParams): string {
65
- const now = new Date().toISOString();
64
+ function renderMilestoneSummaryMarkdown(params: CompleteMilestoneParams, completedAt: string): string {
66
65
  const displayTitle = stripIdPrefix(params.title, params.milestoneId);
67
66
 
68
67
  // Apply defaults for optional enrichment fields (#2771)
@@ -86,7 +85,7 @@ function renderMilestoneSummaryMarkdown(params: CompleteMilestoneParams): string
86
85
  id: ${params.milestoneId}
87
86
  title: "${displayTitle}"
88
87
  status: complete
89
- completed_at: ${now}
88
+ completed_at: ${completedAt}
90
89
  key_decisions:
91
90
  ${keyDecisionsYaml}
92
91
  key_files:
@@ -105,15 +104,15 @@ ${params.narrative}
105
104
 
106
105
  ## Success Criteria Results
107
106
 
108
- ${params.successCriteriaResults ?? "Not provided."}
107
+ ${params.successCriteriaResults || "Not provided."}
109
108
 
110
109
  ## Definition of Done Results
111
110
 
112
- ${params.definitionOfDoneResults ?? "Not provided."}
111
+ ${params.definitionOfDoneResults || "Not provided."}
113
112
 
114
113
  ## Requirement Outcomes
115
114
 
116
- ${params.requirementOutcomes ?? "Not provided."}
115
+ ${params.requirementOutcomes || "Not provided."}
117
116
 
118
117
  ## Deviations
119
118
 
@@ -193,7 +192,7 @@ export async function handleCompleteMilestone(
193
192
  }
194
193
 
195
194
  // ── Filesystem operations (outside transaction) ─────────────────────────
196
- const summaryMd = renderMilestoneSummaryMarkdown(params);
195
+ const summaryMd = renderMilestoneSummaryMarkdown(params, completedAt);
197
196
 
198
197
  let summaryPath: string;
199
198
  const milestoneDir = resolveMilestonePath(basePath, params.milestoneId);
@@ -85,7 +85,7 @@ function taskGateFieldForId(
85
85
  * Normalize a list parameter that may arrive as a string (newline-delimited
86
86
  * bullet list from the LLM) into a string array (#3361).
87
87
  */
88
- function normalizeListParam(value: unknown): string[] {
88
+ export function normalizeListParam(value: unknown): string[] {
89
89
  if (Array.isArray(value)) return value.map(String);
90
90
  if (typeof value === "string" && value.trim()) {
91
91
  return value.split(/\n/).map(s => s.replace(/^[\s\-*•]+/, "").trim()).filter(Boolean);
@@ -476,19 +476,47 @@ export class WorktreeResolver {
476
476
  phase: "auto-commit-failed",
477
477
  error: err instanceof Error ? err.message : String(err),
478
478
  });
479
+ ctx.notify(
480
+ `Auto-commit before exiting ${milestoneId} failed: ${err instanceof Error ? err.message : String(err)}. Branch ${this.deps.autoWorktreeBranch(milestoneId)} is preserved for recovery.`,
481
+ "warning",
482
+ );
479
483
  }
480
484
 
485
+ if (this.s.originalBasePath) {
486
+ try {
487
+ process.chdir(this.s.originalBasePath);
488
+ } catch (err) {
489
+ debugLog("WorktreeResolver", {
490
+ action: "exitMilestone",
491
+ milestoneId,
492
+ phase: "pre-teardown-chdir-failed",
493
+ originalBasePath: this.s.originalBasePath,
494
+ error: err instanceof Error ? err.message : String(err),
495
+ });
496
+ ctx.notify(
497
+ `Could not leave milestone worktree before cleanup: ${err instanceof Error ? err.message : String(err)}. Branch ${this.deps.autoWorktreeBranch(milestoneId)} is preserved for recovery.`,
498
+ "warning",
499
+ );
500
+ }
501
+ }
502
+
503
+ let teardownFailed = false;
481
504
  try {
482
505
  this.deps.teardownAutoWorktree(this.s.originalBasePath, milestoneId, {
483
506
  preserveBranch: opts?.preserveBranch ?? false,
484
507
  });
485
508
  } catch (err) {
509
+ teardownFailed = true;
486
510
  debugLog("WorktreeResolver", {
487
511
  action: "exitMilestone",
488
512
  milestoneId,
489
513
  phase: "teardown-failed",
490
514
  error: err instanceof Error ? err.message : String(err),
491
515
  });
516
+ ctx.notify(
517
+ `Worktree cleanup failed for ${milestoneId}: ${err instanceof Error ? err.message : String(err)}. Branch ${this.deps.autoWorktreeBranch(milestoneId)} is preserved for recovery.`,
518
+ "warning",
519
+ );
492
520
  }
493
521
 
494
522
  this.restoreToProjectRoot();
@@ -498,7 +526,12 @@ export class WorktreeResolver {
498
526
  result: "done",
499
527
  basePath: this.s.basePath,
500
528
  });
501
- ctx.notify(`Exited worktree for ${milestoneId}`, "info");
529
+ ctx.notify(
530
+ teardownFailed
531
+ ? `Worktree exit for ${milestoneId} needs manual cleanup.`
532
+ : `Exited worktree for ${milestoneId}`,
533
+ teardownFailed ? "warning" : "info",
534
+ );
502
535
  }
503
536
 
504
537
  // ── Merge and Exit ─────────────────────────────────────────────────────
@@ -3,56 +3,102 @@
3
3
 
4
4
  import { describe, it } from "node:test";
5
5
  import assert from "node:assert/strict";
6
- import { readFileSync, readdirSync, statSync } from "node:fs";
7
- import { join, dirname, relative } from "node:path";
6
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
7
+ import { tmpdir } from "node:os";
8
+ import { join, dirname } from "node:path";
8
9
  import { fileURLToPath } from "node:url";
10
+ import ts from "typescript";
9
11
 
10
12
  const __dirname = dirname(fileURLToPath(import.meta.url));
11
- const skillRoot = join(__dirname, "..");
12
-
13
- function walk(dir: string): string[] {
14
- const out: string[] = [];
15
- for (const entry of readdirSync(dir)) {
16
- const full = join(dir, entry);
17
- if (statSync(full).isDirectory()) {
18
- out.push(...walk(full));
19
- } else {
20
- out.push(full);
21
- }
13
+
14
+ const extensionApiStubs = `
15
+ declare module "@gsd/pi-coding-agent" {
16
+ export interface ExtensionContext {
17
+ hasUI: boolean;
18
+ sessionManager: { getBranch(): Array<{ type: string; message: { role?: string; toolName?: string; details?: unknown } }> };
19
+ ui: { notify(message: string, level: string): void; custom<T>(view: unknown): Promise<T> };
20
+ }
21
+ export interface ExtensionAPI {
22
+ on(event: string, handler: (event: unknown, ctx: ExtensionContext) => unknown): void;
23
+ registerTool(tool: Record<string, unknown>): void;
24
+ registerCommand(name: string, command: {
25
+ description: string;
26
+ handler: (args: string, ctx: ExtensionContext) => unknown;
27
+ }): void;
22
28
  }
23
- return out;
29
+ }
30
+
31
+ declare module "@sinclair/typebox" {
32
+ export const Type: {
33
+ Object(shape: Record<string, unknown>): unknown;
34
+ Optional(schema: unknown): unknown;
35
+ String(options?: Record<string, unknown>): unknown;
36
+ Number(options?: Record<string, unknown>): unknown;
37
+ };
38
+ }
39
+
40
+ declare module "@gsd/pi-ai" {
41
+ export function StringEnum<T extends readonly string[]>(values: T): unknown;
42
+ }
43
+
44
+ declare module "@gsd/pi-tui" {
45
+ export class Text {
46
+ constructor(text: string, x: number, y: number);
47
+ }
48
+ export function truncateToWidth(text: string, width: number): string;
49
+ export function matchesKey(data: string, key: string): boolean;
50
+ export const Key: { escape: string };
51
+ }
52
+ `;
53
+
54
+ function renderTemplate(template: string): string {
55
+ return template
56
+ .replaceAll("{{EXTENSION_NAME}}", "Sample Extension")
57
+ .replaceAll("{{DESCRIPTION}}", "Sample extension")
58
+ .replaceAll("{{CAPABILITIES_LIST}}", "- sample")
59
+ .replaceAll("{{tool_name}}", "sample_tool")
60
+ .replaceAll("{{Tool Label}}", "Sample Tool")
61
+ .replaceAll("{{Tool description for LLM}}", "Sample tool description")
62
+ .replaceAll("{{command_name}}", "sample")
63
+ .replaceAll("{{Command description}}", "Sample command")
64
+ .replaceAll("{{ItemType}}", "SampleItem")
65
+ .replaceAll("{{ToolDetails}}", "SampleToolDetails")
66
+ .replaceAll("{{Description for LLM}}", "Sample stateful tool description")
67
+ .replaceAll("{{items}}", "items")
68
+ .replaceAll("{{Items}}", "Items");
24
69
  }
25
70
 
26
71
  describe("extension templates use @gsd/* imports", () => {
27
72
  const templates = ["extension-skeleton.ts", "stateful-tool-skeleton.ts"];
28
73
 
29
74
  for (const template of templates) {
30
- it(`${template} uses @gsd/pi-coding-agent (not @mariozechner)`, () => {
31
- const content = readFileSync(join(__dirname, template), "utf-8");
32
- assert.ok(content.includes("@gsd/pi-coding-agent"), `Expected @gsd/pi-coding-agent import in ${template}`);
33
- assert.ok(!content.includes("@mariozechner/"), `Found stale @mariozechner/ import in ${template}`);
34
- });
35
- }
75
+ it(`${template} renders as a compilable extension module`, () => {
76
+ const dir = mkdtempSync(join(tmpdir(), "create-gsd-extension-template-"));
77
+ try {
78
+ const stubsPath = join(dir, "extension-api-stubs.d.ts");
79
+ const renderedPath = join(dir, template);
80
+ writeFileSync(stubsPath, extensionApiStubs, "utf-8");
81
+ const rendered = renderTemplate(readFileSync(join(__dirname, template), "utf-8"));
82
+ writeFileSync(renderedPath, rendered, "utf-8");
36
83
 
37
- it("extension-skeleton.ts uses @gsd/pi-ai for StringEnum", () => {
38
- const content = readFileSync(join(__dirname, "extension-skeleton.ts"), "utf-8");
39
- assert.ok(content.includes("@gsd/pi-ai"), "Expected @gsd/pi-ai import");
40
- });
41
-
42
- it("stateful-tool-skeleton.ts uses @gsd/pi-tui", () => {
43
- const content = readFileSync(join(__dirname, "stateful-tool-skeleton.ts"), "utf-8");
44
- assert.ok(content.includes("@gsd/pi-tui"), "Expected @gsd/pi-tui import");
45
- });
46
-
47
- it("no @mariozechner/ references anywhere in create-gsd-extension/", () => {
48
- const offenders: string[] = [];
49
- for (const file of walk(skillRoot)) {
50
- if (file.endsWith("templates.test.ts")) continue;
51
- const content = readFileSync(file, "utf-8");
52
- if (content.includes("@mariozechner/")) {
53
- offenders.push(relative(skillRoot, file));
84
+ const program = ts.createProgram([stubsPath, renderedPath], {
85
+ allowJs: false,
86
+ esModuleInterop: true,
87
+ module: ts.ModuleKind.NodeNext,
88
+ moduleResolution: ts.ModuleResolutionKind.NodeNext,
89
+ noEmit: true,
90
+ skipLibCheck: true,
91
+ strict: false,
92
+ target: ts.ScriptTarget.ES2022,
93
+ });
94
+ const diagnostics = ts.getPreEmitDiagnostics(program).filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error);
95
+ assert.deepEqual(
96
+ diagnostics.map((diagnostic) => ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")),
97
+ [],
98
+ );
99
+ } finally {
100
+ rmSync(dir, { recursive: true, force: true });
54
101
  }
55
- }
56
- assert.deepEqual(offenders, [], `Stale @mariozechner/ references found in: ${offenders.join(", ")}`);
57
- });
102
+ });
103
+ }
58
104
  });