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
@@ -3,7 +3,7 @@
3
3
 
4
4
  import { describe, test } from "node:test";
5
5
  import assert from "node:assert/strict";
6
- import { mkdtempSync, mkdirSync, readFileSync, realpathSync, rmSync } from "node:fs";
6
+ import { mkdtempSync, mkdirSync, realpathSync, rmSync } from "node:fs";
7
7
  import { join } from "node:path";
8
8
  import { tmpdir } from "node:os";
9
9
 
@@ -12,18 +12,6 @@ import { dispatchHookUnit } from "../auto.ts";
12
12
  import { registerHooks } from "../bootstrap/register-hooks.ts";
13
13
  import { clearDiscussionFlowState, getPendingGate } from "../bootstrap/write-gate.ts";
14
14
 
15
- const autoTimersPath = join(import.meta.dirname, "..", "auto-timers.ts");
16
- const autoTimersSrc = readFileSync(autoTimersPath, "utf-8");
17
-
18
- const autoPath = join(import.meta.dirname, "..", "auto.ts");
19
- const autoSrc = readFileSync(autoPath, "utf-8");
20
-
21
- const runUnitPath = join(import.meta.dirname, "..", "auto", "run-unit.ts");
22
- const runUnitSrc = readFileSync(runUnitPath, "utf-8");
23
-
24
- const registerHooksPath = join(import.meta.dirname, "..", "bootstrap", "register-hooks.ts");
25
- const registerHooksSrc = readFileSync(registerHooksPath, "utf-8");
26
-
27
15
  function makeHookHarness() {
28
16
  const handlers = new Map<string, Array<(event: any, ctx: any) => Promise<any>>>();
29
17
  const pi = {
@@ -55,61 +43,6 @@ function makeHookHarness() {
55
43
  return { emit };
56
44
  }
57
45
 
58
- describe("#3512: gsd-auto-wrapup must not interrupt in-flight tool calls", () => {
59
- test("soft timeout wrapup gates triggerTurn on getInFlightToolCount() === 0", () => {
60
- // The soft timeout sendMessage must NOT use a hardcoded `triggerTurn: true`.
61
- // It must check getInFlightToolCount() before deciding whether to trigger.
62
- // Use the section marker comment to isolate the soft timeout block.
63
- const startMarker = "── 1. Soft timeout warning";
64
- const endMarker = "── 2. Idle watchdog";
65
- const softTimeoutSection = autoTimersSrc.slice(
66
- autoTimersSrc.indexOf(startMarker),
67
- autoTimersSrc.indexOf(endMarker),
68
- );
69
- assert.ok(
70
- softTimeoutSection.length > 0,
71
- "Could not locate soft timeout section",
72
- );
73
-
74
- // Must reference getInFlightToolCount to gate the trigger
75
- assert.ok(
76
- softTimeoutSection.includes("getInFlightToolCount"),
77
- "Soft timeout wrapup must gate triggerTurn behind getInFlightToolCount() check",
78
- );
79
-
80
- // Must NOT have a hardcoded triggerTurn: true
81
- assert.ok(
82
- !softTimeoutSection.includes("triggerTurn: true"),
83
- "Soft timeout wrapup must not use hardcoded triggerTurn: true",
84
- );
85
- });
86
-
87
- test("context-pressure wrapup gates triggerTurn on getInFlightToolCount() === 0", () => {
88
- // The context budget sendMessage must NOT use a hardcoded `triggerTurn: true`.
89
- // Use the section marker to isolate the context-pressure block.
90
- const startMarker = "── 4. Context-pressure continue-here monitor";
91
- const contextSection = autoTimersSrc.slice(
92
- autoTimersSrc.indexOf(startMarker),
93
- );
94
- assert.ok(
95
- contextSection.length > 0,
96
- "Could not locate context budget section",
97
- );
98
-
99
- // Must reference getInFlightToolCount to gate the trigger
100
- assert.ok(
101
- contextSection.includes("getInFlightToolCount"),
102
- "Context budget wrapup must gate triggerTurn behind getInFlightToolCount() check",
103
- );
104
-
105
- // Must NOT have a hardcoded triggerTurn: true
106
- assert.ok(
107
- !contextSection.includes("triggerTurn: true"),
108
- "Context budget wrapup must not use hardcoded triggerTurn: true",
109
- );
110
- });
111
- });
112
-
113
46
  describe("hook dispatch session workspace root", () => {
114
47
  test("dispatchHookUnit passes basePath explicitly to newSession", async (t) => {
115
48
  const originalCwd = process.cwd();
@@ -165,156 +98,7 @@ describe("hook dispatch session workspace root", () => {
165
98
  });
166
99
  });
167
100
 
168
- describe("#4276: pending/skipped tools stay visible to auto-mode hooks", () => {
169
- test("tool_call handler marks GSD tools in-flight before execution_start", () => {
170
- const startMarker = 'pi.on("tool_call", async (event, ctx) => {';
171
- const endMarker = 'pi.on("tool_result", async (event, ctx) => {';
172
- const toolCallSection = registerHooksSrc.slice(
173
- registerHooksSrc.indexOf(startMarker),
174
- registerHooksSrc.indexOf(endMarker),
175
- );
176
-
177
- assert.ok(toolCallSection.length > 0, "Could not locate tool_call handler section");
178
- assert.ok(
179
- toolCallSection.includes("markToolStart(event.toolCallId, event.toolName)"),
180
- "tool_call handler must mark tools pending before tool_execution_start fires",
181
- );
182
- });
183
-
184
- test("tool_result handler clears pending tools and records queued-skip errors", () => {
185
- const startMarker = 'pi.on("tool_result", async (event, ctx) => {';
186
- const endMarker = 'pi.on("tool_execution_start", async (event) => {';
187
- const toolResultSection = registerHooksSrc.slice(
188
- registerHooksSrc.indexOf(startMarker),
189
- registerHooksSrc.indexOf(endMarker),
190
- );
191
-
192
- assert.ok(toolResultSection.length > 0, "Could not locate tool_result handler section");
193
- assert.ok(
194
- toolResultSection.includes("markToolEnd(event.toolCallId)"),
195
- "tool_result handler must clear pending tool tracking even when execution hooks never fire",
196
- );
197
- assert.ok(
198
- toolResultSection.includes("recordToolInvocationError(event.toolName, errorText)"),
199
- "tool_result handler must surface queued-skip errors for GSD tools",
200
- );
201
- });
202
- });
203
-
204
- describe("#3512: pauseAuto and stopAuto must flush queued follow-up messages", () => {
205
- test("stopAuto calls clearQueue()", () => {
206
- // stopAuto must flush queued messages to prevent late async_job_result
207
- // notifications from triggering extra LLM turns after stop.
208
- const stopAutoSection = autoSrc.slice(
209
- autoSrc.indexOf("export async function stopAuto("),
210
- autoSrc.indexOf("export async function pauseAuto("),
211
- );
212
- assert.ok(stopAutoSection, "Could not locate stopAuto function");
213
- assert.ok(
214
- stopAutoSection.includes("clearQueue"),
215
- "stopAuto must call clearQueue() to flush queued follow-up messages",
216
- );
217
- });
218
-
219
- test("pauseAuto calls clearQueue()", () => {
220
- // pauseAuto must also flush queued messages — same issue as stopAuto.
221
- const pauseAutoSection = autoSrc.slice(
222
- autoSrc.indexOf("export async function pauseAuto("),
223
- );
224
- assert.ok(pauseAutoSection, "Could not locate pauseAuto function");
225
- assert.ok(
226
- pauseAutoSection.includes("clearQueue"),
227
- "pauseAuto must call clearQueue() to flush queued follow-up messages",
228
- );
229
- });
230
-
231
- test("pauseAuto rebuilds STATE.md before releasing the session lock", () => {
232
- // pauseAuto must persist the DB-backed state projection so resume/debugging
233
- // does not see a stale STATE.md after a mid-unit interruption.
234
- const start = autoSrc.indexOf("export async function pauseAuto(");
235
- const end = autoSrc.indexOf("/**\n * Build a WorktreeResolverDeps", start);
236
- const pauseAutoSection = autoSrc.slice(start, end);
237
- assert.ok(pauseAutoSection.length > 0, "Could not locate pauseAuto function");
238
-
239
- const rebuildIndex = pauseAutoSection.indexOf("await rebuildState(s.basePath)");
240
- const releaseIndex = pauseAutoSection.indexOf("releaseSessionLock(lockBase())");
241
- assert.ok(
242
- rebuildIndex >= 0,
243
- "pauseAuto must rebuild STATE.md from DB-backed state before pause completes",
244
- );
245
- assert.ok(
246
- releaseIndex >= 0,
247
- "pauseAuto must still release the session lock",
248
- );
249
- assert.ok(
250
- rebuildIndex < releaseIndex,
251
- "pauseAuto must rebuild state before releasing the session lock",
252
- );
253
- });
254
-
255
- test("run-unit.ts still has its existing clearQueue() call (baseline)", () => {
256
- // Verify the original clearQueue pattern in run-unit.ts hasn't been removed.
257
- assert.ok(
258
- runUnitSrc.includes("clearQueue"),
259
- "run-unit.ts must retain its clearQueue() call after unit completion",
260
- );
261
- });
262
- });
263
-
264
- describe("#4365: tool_execution_start hook must pass toolName to markToolStart", () => {
265
- test("tool_execution_start handler passes event.toolName to markToolStart", () => {
266
- // The tool_execution_start handler must forward toolName so that
267
- // hasInteractiveToolInFlight() can correctly identify ask_user_questions
268
- // and prevent the idle watchdog from firing during interactive tool calls.
269
- const startMarker = 'pi.on("tool_execution_start", async (event) => {';
270
- const endMarker = 'pi.on("tool_execution_end", async (event) => {';
271
- const toolExecutionStartSection = registerHooksSrc.slice(
272
- registerHooksSrc.indexOf(startMarker),
273
- registerHooksSrc.indexOf(endMarker),
274
- );
275
-
276
- assert.ok(
277
- toolExecutionStartSection.length > 0,
278
- "Could not locate tool_execution_start handler section",
279
- );
280
- assert.ok(
281
- toolExecutionStartSection.includes("markToolStart(event.toolCallId, event.toolName)"),
282
- "tool_execution_start handler must pass event.toolName to markToolStart so hasInteractiveToolInFlight() works correctly",
283
- );
284
- });
285
- });
286
-
287
101
  describe("deep setup approval questions pause immediately", () => {
288
- test("register-hooks defers the pending gate during message_update without aborting the stream", () => {
289
- const startMarker = 'pi.on("message_update"';
290
- const endMarker = 'pi.on("session_shutdown"';
291
- const messageUpdateSection = registerHooksSrc.slice(
292
- registerHooksSrc.indexOf(startMarker),
293
- registerHooksSrc.indexOf(endMarker),
294
- );
295
-
296
- assert.ok(
297
- messageUpdateSection.length > 0,
298
- "Could not locate message_update approval pause handler",
299
- );
300
- assert.ok(
301
- messageUpdateSection.includes("shouldPauseForUserApprovalQuestion"),
302
- "message_update must detect approval/question boundaries",
303
- );
304
- assert.ok(
305
- messageUpdateSection.includes("approvalGateIdForUnit") && messageUpdateSection.includes("deferApprovalGate"),
306
- "plain-text approval questions must defer the durable write gate until same-turn draft persistence can finish",
307
- );
308
- assert.ok(
309
- messageUpdateSection.includes("getDiscussionMilestoneIdFor") && messageUpdateSection.includes('"discuss-milestone"'),
310
- "foreground milestone discussion questions must also set the durable write gate",
311
- );
312
- assert.ok(
313
- !messageUpdateSection.includes("ctx.abort()"),
314
- "message_update must NOT abort the stream — aborting eats the model's question text on external CLI providers; the pending gate set above blocks subsequent tool calls instead",
315
- );
316
- });
317
-
318
102
  test("plain-text approval boundary defers durable gate until same-turn CONTEXT-DRAFT can save", async () => {
319
103
  const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-deferred-approval-")));
320
104
  const previousCwd = process.cwd();
@@ -1,40 +1,23 @@
1
- import { describe, test } from "node:test";
1
+ import { describe, test, afterEach } from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { readFileSync } from "node:fs";
3
+ import { mkdtempSync, mkdirSync, realpathSync, rmSync } from "node:fs";
4
4
  import { join } from "node:path";
5
- import { extractSourceRegion } from "./test-helpers.ts";
5
+ import { tmpdir } from "node:os";
6
6
 
7
- const systemContextSrc = readFileSync(
8
- join(import.meta.dirname, "..", "bootstrap", "system-context.ts"),
9
- "utf-8",
10
- );
11
- const registerHooksSrc = readFileSync(
12
- join(import.meta.dirname, "..", "bootstrap", "register-hooks.ts"),
13
- "utf-8",
14
- );
7
+ import { ensureDbOpen } from "../bootstrap/dynamic-tools.ts";
8
+ import { closeDatabase, isDbAvailable } from "../gsd-db.ts";
9
+
10
+ afterEach(() => {
11
+ if (isDbAvailable()) closeDatabase();
12
+ });
15
13
 
16
14
  describe("bootstrap deriveState DB guards (#3844)", () => {
17
- test("system-context opens DB before deriveState in resume flows", () => {
18
- const helperIdx = systemContextSrc.indexOf("const ensureStateDbOpen = async () => {");
19
- const firstDeriveIdx = systemContextSrc.indexOf("const state = await deriveState(basePath);");
20
- assert.ok(helperIdx > -1, "system-context should define a DB-open helper for deriveState callers");
21
- assert.ok(firstDeriveIdx > -1, "system-context should still derive state for resume flows");
22
- assert.ok(helperIdx < firstDeriveIdx, "system-context should prepare DB opening before deriveState resume calls");
23
- assert.match(
24
- systemContextSrc,
25
- /await ensureStateDbOpen\(\);\s*\n\s*const state = await deriveState\(basePath\);/g,
26
- "system-context resume flows should open DB before deriveState",
27
- );
28
- });
15
+ test("ensureDbOpen creates and opens the project DB when .gsd exists", async (t) => {
16
+ const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-ensure-db-")));
17
+ t.after(() => rmSync(base, { recursive: true, force: true }));
18
+ mkdirSync(join(base, ".gsd"), { recursive: true });
29
19
 
30
- test("register-hooks opens DB before deriveState in session_before_compact", () => {
31
- const compactIdx = registerHooksSrc.indexOf('pi.on("session_before_compact"');
32
- assert.ok(compactIdx > -1, "register-hooks should define session_before_compact");
33
- const compactSection = extractSourceRegion(registerHooksSrc, 'pi.on("session_before_compact"');
34
- const ensureIdx = compactSection.indexOf("ensureDbOpen(basePath)");
35
- const deriveIdx = compactSection.indexOf("deriveGsdState(basePath)");
36
- assert.ok(ensureIdx > -1, "session_before_compact should call ensureDbOpen(basePath)");
37
- assert.ok(deriveIdx > -1, "session_before_compact should derive state");
38
- assert.ok(ensureIdx < deriveIdx, "session_before_compact should open DB before deriveState");
20
+ assert.equal(await ensureDbOpen(base), true);
21
+ assert.equal(isDbAvailable(), true);
39
22
  });
40
23
  });
@@ -90,44 +90,3 @@ test("getBrowser() guard triggers closeBrowser when browser is active", async ()
90
90
  assert.equal(closeCalled, true, "browser.close() should have been called");
91
91
  assert.equal(getBrowser(), null, "browser should be null after guarded teardown");
92
92
  });
93
-
94
- // ─── Source code verification ───────────────────────────────────────────────
95
-
96
- test("stopAuto finally block includes browser teardown", async () => {
97
- // Verify the source code contains the browser teardown call
98
- const { readFileSync } = await import("node:fs");
99
- const { resolve } = await import("node:path");
100
- const autoSource = readFileSync(resolve(import.meta.dirname, "..", "auto.ts"), "utf-8");
101
-
102
- assert.ok(
103
- autoSource.includes("closeBrowser"),
104
- "auto.ts should reference closeBrowser for teardown in stopAuto",
105
- );
106
- assert.ok(
107
- autoSource.includes("getBrowser"),
108
- "auto.ts should check getBrowser() before calling closeBrowser",
109
- );
110
- assert.ok(
111
- autoSource.includes("browser-tools/lifecycle"),
112
- "auto.ts should import from browser-tools/lifecycle",
113
- );
114
- });
115
-
116
- test("postUnitPreVerification includes browser teardown between units", async () => {
117
- const { readFileSync } = await import("node:fs");
118
- const { resolve } = await import("node:path");
119
- const postUnitSource = readFileSync(resolve(import.meta.dirname, "..", "auto-post-unit.ts"), "utf-8");
120
-
121
- assert.ok(
122
- postUnitSource.includes("closeBrowser"),
123
- "auto-post-unit.ts should reference closeBrowser for inter-unit teardown",
124
- );
125
- assert.ok(
126
- postUnitSource.includes("getBrowser"),
127
- "auto-post-unit.ts should check getBrowser() before calling closeBrowser",
128
- );
129
- assert.ok(
130
- postUnitSource.includes("browser-teardown"),
131
- "auto-post-unit.ts should have browser-teardown debug phase",
132
- );
133
- });
@@ -1,41 +1,48 @@
1
1
  /**
2
2
  * clear-stale-autostart.test.ts — #3667
3
3
  *
4
- * Verify that guided-flow.ts adds a createdAt timestamp to pending auto-start
5
- * entries and implements a staleness check (30s age guard) so that /clear
6
- * interrupted discussions don't permanently block future /gsd invocations.
4
+ * Pending auto-start entries carry a createdAt timestamp so later /gsd
5
+ * invocations can distinguish an in-flight discussion from a stale one.
7
6
  */
8
7
 
9
- import { describe, test } from "node:test";
8
+ import { describe, test, afterEach } from "node:test";
10
9
  import assert from "node:assert/strict";
11
- import { readFileSync } from "node:fs";
12
- import { join, dirname } from "node:path";
13
- import { fileURLToPath } from "node:url";
14
-
15
- const __dirname = dirname(fileURLToPath(import.meta.url));
16
- const sourceFile = join(__dirname, "..", "guided-flow.ts");
10
+ import { mkdtempSync, mkdirSync, realpathSync, rmSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { tmpdir } from "node:os";
13
+
14
+ import {
15
+ _getPendingAutoStart,
16
+ clearPendingAutoStart,
17
+ setPendingAutoStart,
18
+ } from "../guided-flow.ts";
19
+
20
+ afterEach(() => {
21
+ clearPendingAutoStart();
22
+ });
17
23
 
18
24
  describe("clear stale pending auto-start (#3667)", () => {
19
- const source = readFileSync(sourceFile, "utf-8");
20
-
21
- test("PendingAutoStartEntry interface includes createdAt field", () => {
22
- assert.match(source, /createdAt:\s*number/);
25
+ test("setPendingAutoStart defaults createdAt to Date.now()", (t) => {
26
+ const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-pending-autostart-")));
27
+ t.after(() => rmSync(base, { recursive: true, force: true }));
28
+ mkdirSync(join(base, ".gsd"), { recursive: true });
29
+ const before = Date.now();
30
+
31
+ setPendingAutoStart(base, { basePath: base, milestoneId: "M001" });
32
+
33
+ const entry = _getPendingAutoStart(base);
34
+ assert.ok(entry);
35
+ assert.equal(typeof entry!.createdAt, "number");
36
+ assert.ok(entry!.createdAt >= before);
23
37
  });
24
38
 
25
- test("setPendingAutoStart defaults createdAt to Date.now()", () => {
26
- assert.match(source, /createdAt:\s*Date\.now\(\)/);
27
- });
39
+ test("setPendingAutoStart preserves explicit createdAt for stale-entry checks", (t) => {
40
+ const base = realpathSync(mkdtempSync(join(tmpdir(), "gsd-pending-autostart-old-")));
41
+ t.after(() => rmSync(base, { recursive: true, force: true }));
42
+ mkdirSync(join(base, ".gsd"), { recursive: true });
28
43
 
29
- test("staleness check uses 30_000ms threshold", () => {
30
- assert.match(source, /30[_]?000/);
31
- });
32
-
33
- test("stale entry detection checks manifest and context files", () => {
34
- assert.match(source, /DISCUSSION-MANIFEST\.json/);
35
- assert.match(source, /CONTEXT\.md/);
36
- });
44
+ setPendingAutoStart(base, { basePath: base, milestoneId: "M001", createdAt: 123 });
37
45
 
38
- test("stale entries are deleted from the map", () => {
39
- assert.match(source, /pendingAutoStartMap\.delete\(basePath\)/);
46
+ assert.equal(_getPendingAutoStart(base)?.createdAt, 123);
40
47
  });
41
48
  });
@@ -1,3 +1,5 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Unit tests for cmux integration, layout, and CLI isolation.
1
3
  import test, { describe, beforeEach, afterEach } from "node:test";
2
4
  import assert from "node:assert/strict";
3
5
  import * as fs from "node:fs";
@@ -7,6 +9,7 @@ import { fileURLToPath } from "node:url";
7
9
  import {
8
10
  buildCmuxProgress,
9
11
  buildCmuxStatusLabel,
12
+ CmuxClient,
10
13
  detectCmuxEnvironment,
11
14
  markCmuxPromptShown,
12
15
  resetCmuxPromptState,
@@ -256,60 +259,55 @@ describe("createGridLayout", () => {
256
259
  });
257
260
 
258
261
  describe("CmuxClient stdio isolation", () => {
259
- test("runSync and runAsync explicitly set stdio to prevent terminal interference", () => {
260
- // Read the cmux index source and verify that execFileSync/spawn calls
261
- // inside runSync/runAsync include stdio options that isolate stdin and stderr.
262
- // This prevents the cmux CLI child process from inheriting the parent's
263
- // stdin/stderr, which can steal keyboard input or corrupt TUI rendering (#1922).
264
- const cmuxIndexPath = path.resolve(
265
- path.dirname(fileURLToPath(import.meta.url)),
266
- "../../cmux/index.ts",
267
- );
268
- const source = fs.readFileSync(cmuxIndexPath, "utf-8");
269
-
270
- // Extract runSync method body
271
- const runSyncMatch = source.match(/private runSync\(args: string\[\]\)[^{]*\{([\s\S]*?)\n \}/);
272
- assert.ok(runSyncMatch, "runSync method must exist");
273
- const runSyncBody = runSyncMatch[1];
274
- assert.ok(
275
- runSyncBody.includes('stdio:'),
276
- "runSync must explicitly set stdio to prevent terminal interference (see #1922)",
277
- );
278
- assert.ok(
279
- runSyncBody.includes('"ignore"'),
280
- "runSync stdio must ignore stdin to prevent stealing keyboard input from TUI",
281
- );
282
-
283
- // Extract runAsync method body
284
- const runAsyncMatch = source.match(/private async runAsync\(args: string\[\]\)[^{]*\{([\s\S]*?)\n \}/);
285
- assert.ok(runAsyncMatch, "runAsync method must exist");
286
- const runAsyncBody = runAsyncMatch[1];
287
- assert.ok(
288
- runAsyncBody.includes('stdio:'),
289
- "runAsync must explicitly set stdio to prevent terminal interference (see #1922)",
290
- );
291
- assert.ok(
292
- runAsyncBody.includes('"ignore"'),
293
- "runAsync stdio must ignore stdin to prevent stealing keyboard input from TUI",
294
- );
295
- });
296
-
297
- test("isCmuxCliAvailable uses stdio ignore to prevent terminal interference", () => {
298
- const cmuxIndexPath = path.resolve(
299
- path.dirname(fileURLToPath(import.meta.url)),
300
- "../../cmux/index.ts",
301
- );
302
- const source = fs.readFileSync(cmuxIndexPath, "utf-8");
303
-
304
- // Find isCmuxCliAvailable or the cli-check function body
305
- const fnMatch = source.match(/function isCmuxCliAvailable[\s\S]*?\{([\s\S]*?)\n\}/);
306
- if (!fnMatch) return; // function may be inlined or renamed — skip rather than fail
307
-
308
- const fnBody = fnMatch[1];
309
- assert.ok(
310
- fnBody.includes('"ignore"') || !fnBody.includes('execFileSync'),
311
- "isCmuxCliAvailable must not inherit parent stdio (see #1922)",
262
+ test("runSync and runAsync execute the cmux CLI without inheriting test stdin", async () => {
263
+ const binDir = fs.mkdtempSync(path.join(tmpdir(), "cmux-bin-"));
264
+ const logPath = path.join(binDir, "calls.jsonl");
265
+ const cmuxPath = path.join(binDir, "cmux");
266
+ const originalPath = process.env.PATH;
267
+ fs.writeFileSync(
268
+ cmuxPath,
269
+ [
270
+ "#!/usr/bin/env node",
271
+ "const fs = require('node:fs');",
272
+ `fs.appendFileSync(${JSON.stringify(logPath)}, JSON.stringify(process.argv.slice(2)) + '\\n');`,
273
+ "if (process.argv.includes('--json')) process.stdout.write(JSON.stringify({surfaces:[{id:'surface-1'}]}));",
274
+ "else process.stdout.write('ok');",
275
+ ].join("\n"),
276
+ "utf-8",
312
277
  );
278
+ fs.chmodSync(cmuxPath, 0o755);
279
+ process.env.PATH = `${binDir}:${originalPath ?? ""}`;
280
+ try {
281
+ const client = new CmuxClient({
282
+ enabled: true,
283
+ available: true,
284
+ cliAvailable: true,
285
+ notifications: true,
286
+ sidebar: true,
287
+ splits: true,
288
+ browser: false,
289
+ workspaceId: "workspace-1",
290
+ surfaceId: "surface-0",
291
+ socketPath: "/tmp/cmux.sock",
292
+ });
293
+
294
+ client.setStatus("M001", "executing");
295
+ await client.listSurfaceIds();
296
+
297
+ const calls = fs.readFileSync(logPath, "utf-8").trim().split("\n").map((line) => JSON.parse(line));
298
+ const commandPrefixes = calls.map((call) => call.slice(0, 2));
299
+ assert.ok(
300
+ commandPrefixes.some((prefix) => JSON.stringify(prefix) === JSON.stringify(["set-status", "gsd"])),
301
+ "set-status command should be invoked",
302
+ );
303
+ assert.ok(
304
+ commandPrefixes.some((prefix) => JSON.stringify(prefix) === JSON.stringify(["list-surfaces", "--json"])),
305
+ "list-surfaces command should be invoked",
306
+ );
307
+ } finally {
308
+ process.env.PATH = originalPath;
309
+ fs.rmSync(binDir, { recursive: true, force: true });
310
+ }
313
311
  });
314
312
  });
315
313
 
@@ -1,65 +1,43 @@
1
1
  /**
2
2
  * cold-resume-db-reopen.test.ts — Regression test for #2940.
3
- *
4
- * Validates that the paused-session resume path in auto.ts opens the project
5
- * database before calling rebuildState() / deriveState(), matching the fresh
6
- * bootstrap path in auto-start.ts.
7
- *
8
- * Without this, cold resume falls back to markdown parsing which misreads
9
- * done cells and redispatches wrong slices.
10
3
  */
11
4
 
12
- import { readFileSync } from "node:fs";
13
- import { join } from "node:path";
14
-
15
- import { createTestContext } from "./test-helpers.ts";
16
-
17
- const { assertTrue, report } = createTestContext();
18
-
19
- const autoSrc = readFileSync(join(import.meta.dirname, "..", "auto.ts"), "utf-8");
20
-
21
- console.log("\n=== resume path refreshes resources and opens DB before rebuildState/deriveState ===");
22
-
23
- // The resume block is the `if (s.paused) { ... }` section that calls rebuildState/deriveState.
24
- // Locate the resume section by finding `s.paused = false;` followed by `rebuildState`.
25
- const resumeSectionStart = autoSrc.indexOf("if (s.paused) {", autoSrc.indexOf("// If resuming from paused state"));
26
- assertTrue(resumeSectionStart > 0, "auto.ts has the paused-session resume block");
27
-
28
- const resumeSectionEndCandidates = [
29
- autoSrc.indexOf("await runAutoLoopWithUok(", resumeSectionStart),
30
- autoSrc.indexOf("await autoLoop(", resumeSectionStart),
31
- ].filter((idx) => idx > resumeSectionStart);
32
- const resumeSectionEnd = resumeSectionEndCandidates.length > 0 ? Math.min(...resumeSectionEndCandidates) : -1;
33
- assertTrue(resumeSectionEnd > resumeSectionStart, "resume block reaches the dispatch loop");
34
-
35
- const resumeSection = autoSrc.slice(resumeSectionStart, resumeSectionEnd);
36
-
37
- // The resume path must refresh managed resources and open the DB before
38
- // rebuildState/deriveState so resumed auto-mode uses current extension code.
39
- const rebuildIdx = resumeSection.indexOf("rebuildState(");
40
- assertTrue(rebuildIdx > 0, "resume block calls rebuildState");
41
-
42
- const deriveIdx = resumeSection.indexOf("deriveState(");
43
- assertTrue(deriveIdx > 0, "resume block calls deriveState");
44
-
45
- const preDeriveSection = resumeSection.slice(0, rebuildIdx);
46
-
47
- assertTrue(
48
- preDeriveSection.includes("initResources("),
49
- "resume path must refresh managed resources before rebuildState/deriveState (#3761)",
50
- );
51
-
52
- // There must be a DB open call before the first rebuildState call
53
- const dbOpenPatterns = [
54
- "openProjectDbIfPresent(",
55
- "openDatabase(",
56
- "ensureDbOpen(",
57
- ];
58
-
59
- const hasDbOpen = dbOpenPatterns.some(pat => preDeriveSection.includes(pat));
60
- assertTrue(
61
- hasDbOpen,
62
- "resume path must open DB before rebuildState/deriveState (#2940)",
63
- );
64
-
65
- report();
5
+ import test from "node:test";
6
+ import assert from "node:assert/strict";
7
+ import { refreshResumeResourcesAndDb } from "../auto.ts";
8
+
9
+ test("resume refreshes managed resources and opens DB before state rebuild", async () => {
10
+ const calls: string[] = [];
11
+
12
+ await refreshResumeResourcesAndDb("/tmp/project", {
13
+ env: {
14
+ GSD_CODING_AGENT_DIR: "/tmp/agent",
15
+ GSD_PKG_ROOT: "/tmp/pkg",
16
+ } as NodeJS.ProcessEnv,
17
+ importModule: async (specifier: string) => {
18
+ calls.push(`import:${specifier}`);
19
+ if (specifier.endsWith("/dist/resource-loader.js")) {
20
+ return {
21
+ initResources: (agentDir: string) => calls.push(`initResources:${agentDir}`),
22
+ };
23
+ }
24
+ if (specifier === "./prompt-loader.js") {
25
+ return {
26
+ primeCache: () => calls.push("primeCache"),
27
+ };
28
+ }
29
+ throw new Error(`unexpected import: ${specifier}`);
30
+ },
31
+ openProjectDb: async (basePath: string) => {
32
+ calls.push(`openDb:${basePath}`);
33
+ },
34
+ });
35
+
36
+ assert.deepEqual(calls, [
37
+ "import:file:///tmp/pkg/dist/resource-loader.js",
38
+ "initResources:/tmp/agent",
39
+ "import:./prompt-loader.js",
40
+ "primeCache",
41
+ "openDb:/tmp/project",
42
+ ]);
43
+ });