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
@@ -6,41 +6,45 @@
6
6
  * adds a filter for classification === "note" and calls markCaptureExecuted
7
7
  * for each matching capture.
8
8
  *
9
- * Structural verification test — reads source to confirm the note filter
10
- * and markCaptureExecuted call exist.
9
+ * Behavior test — resolved note captures should be marked executed without
10
+ * dispatching inject/replan work.
11
11
  */
12
12
 
13
13
  import { describe, test } from 'node:test';
14
14
  import assert from 'node:assert/strict';
15
- import { readFileSync } from 'node:fs';
16
- import { fileURLToPath } from 'node:url';
17
- import { dirname, join } from 'node:path';
18
-
19
- const __filename = fileURLToPath(import.meta.url);
20
- const __dirname = dirname(__filename);
21
-
22
- const source = readFileSync(join(__dirname, '..', 'triage-resolution.ts'), 'utf-8');
15
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
16
+ import { join } from 'node:path';
17
+ import { tmpdir } from 'node:os';
18
+ import { loadAllCaptures } from '../captures.ts';
19
+ import { executeTriageResolutions } from '../triage-resolution.ts';
23
20
 
24
21
  describe('note captures executed in triage resolution (#3578)', () => {
25
- test('markCaptureExecuted is imported', () => {
26
- assert.match(source, /markCaptureExecuted/,
27
- 'markCaptureExecuted should be imported');
28
- });
22
+ test('resolved note captures are stamped executed', () => {
23
+ const base = mkdtempSync(join(tmpdir(), 'gsd-note-capture-'));
24
+ try {
25
+ mkdirSync(join(base, '.gsd'), { recursive: true });
26
+ writeFileSync(join(base, '.gsd', 'CAPTURES.md'), [
27
+ '# Captures',
28
+ '',
29
+ '### cap-note',
30
+ '**Text:** Remember this',
31
+ '**Captured:** 2026-01-01T00:00:00.000Z',
32
+ '**Status:** resolved',
33
+ '**Classification:** note',
34
+ '**Resolution:** informational only',
35
+ '**Resolved:** 2026-01-01T00:01:00.000Z',
36
+ '',
37
+ ].join('\n'));
29
38
 
30
- test('note classification filter exists', () => {
31
- assert.match(source, /classification\s*===\s*"note"/,
32
- 'filter should check classification === "note"');
33
- });
34
-
35
- test('note filter checks resolved status and not-executed', () => {
36
- assert.match(source, /status\s*===\s*"resolved"\s*&&\s*!c\.executed\s*&&\s*c\.classification\s*===\s*"note"/,
37
- 'filter should check resolved + not-executed + note classification');
38
- });
39
+ const result = executeTriageResolutions(base, 'M001', 'S01');
40
+ const [capture] = loadAllCaptures(base);
39
41
 
40
- test('markCaptureExecuted is called for note captures', () => {
41
- // The source should call markCaptureExecuted for note captures
42
- const noteSection = source.slice(source.indexOf('classification === "note"'));
43
- assert.match(noteSection, /markCaptureExecuted\(basePath,\s*cap\.id\)/,
44
- 'markCaptureExecuted should be called for note captures');
42
+ assert.equal(result.injected, 0);
43
+ assert.equal(result.replanned, 0);
44
+ assert.ok(result.actions.some((action) => action.includes('Note acknowledged: cap-note')));
45
+ assert.equal(capture?.executed, true);
46
+ } finally {
47
+ rmSync(base, { recursive: true, force: true });
48
+ }
45
49
  });
46
50
  });
@@ -8,48 +8,35 @@
8
8
  * The fix makes isGhostMilestone treat a "queued" DB row with no disk
9
9
  * artifacts (CONTEXT, ROADMAP, SUMMARY) as a ghost.
10
10
  *
11
- * This structural test verifies the dbRow.status === 'queued' guard exists.
11
+ * This behavior test exercises isGhostMilestone against real DB rows and
12
+ * milestone artifacts.
12
13
  */
13
14
 
14
15
  import { describe, test } from 'node:test';
15
16
  import assert from 'node:assert/strict';
16
- import { readFileSync } from 'node:fs';
17
- import { fileURLToPath } from 'node:url';
18
- import { dirname, join } from 'node:path';
19
-
20
- const __filename = fileURLToPath(import.meta.url);
21
- const __dirname = dirname(__filename);
22
-
23
- const source = readFileSync(join(__dirname, '..', 'state.ts'), 'utf-8');
17
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
18
+ import { join } from 'node:path';
19
+ import { tmpdir } from 'node:os';
20
+ import { closeDatabase, insertMilestone, openDatabase } from '../gsd-db.ts';
21
+ import { clearPathCache } from '../paths.ts';
22
+ import { isGhostMilestone } from '../state.ts';
24
23
 
25
24
  describe('isGhostMilestone phantom queued detection (#3671)', () => {
26
- test('isGhostMilestone function exists', () => {
27
- assert.match(source, /export function isGhostMilestone\(/,
28
- 'isGhostMilestone should be exported');
29
- });
30
-
31
- test('checks dbRow.status === queued', () => {
32
- assert.match(source, /dbRow\.status\s*===\s*['"]queued['"]/,
33
- 'isGhostMilestone should check dbRow.status === "queued"');
34
- });
35
-
36
- test('checks for CONTEXT disk artifact', () => {
37
- assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']CONTEXT["']\)/,
38
- 'should check for CONTEXT file');
39
- });
40
-
41
- test('checks for ROADMAP disk artifact', () => {
42
- assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']ROADMAP["']\)/,
43
- 'should check for ROADMAP file');
44
- });
45
-
46
- test('checks for SUMMARY disk artifact', () => {
47
- assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']SUMMARY["']\)/,
48
- 'should check for SUMMARY file');
49
- });
50
-
51
- test('returns !hasContent for queued rows (ghost if no artifacts)', () => {
52
- assert.match(source, /return !hasContent/,
53
- 'should return !hasContent for queued phantom milestones');
25
+ test('queued DB row with no artifacts is a ghost, but content makes it real', () => {
26
+ const base = mkdtempSync(join(tmpdir(), 'gsd-phantom-ghost-'));
27
+ try {
28
+ openDatabase(':memory:');
29
+ insertMilestone({ id: 'M001', title: 'Reserved only', status: 'queued' });
30
+ mkdirSync(join(base, '.gsd', 'milestones', 'M001'), { recursive: true });
31
+
32
+ assert.equal(isGhostMilestone(base, 'M001'), true);
33
+
34
+ writeFileSync(join(base, '.gsd', 'milestones', 'M001', 'M001-CONTEXT.md'), '# Context\n');
35
+ clearPathCache();
36
+ assert.equal(isGhostMilestone(base, 'M001'), false);
37
+ } finally {
38
+ closeDatabase();
39
+ rmSync(base, { recursive: true, force: true });
40
+ }
54
41
  });
55
42
  });
@@ -8,32 +8,17 @@
8
8
 
9
9
  import { describe, test } from 'node:test';
10
10
  import assert from 'node:assert/strict';
11
- import { readFileSync } from 'node:fs';
12
- import { fileURLToPath } from 'node:url';
13
- import { dirname, join } from 'node:path';
14
-
15
- const __filename = fileURLToPath(import.meta.url);
16
- const __dirname = dirname(__filename);
17
-
18
- const dbSrc = readFileSync(
19
- join(__dirname, '..', 'gsd-db.ts'),
20
- 'utf-8',
21
- );
11
+ import { closeDatabase, getMilestone, insertMilestone, openDatabase } from '../gsd-db.ts';
22
12
 
23
13
  describe('insertMilestone defaults status to queued (#3695)', () => {
24
- test('insertMilestone function exists', () => {
25
- assert.match(dbSrc, /export function insertMilestone\(/,
26
- 'insertMilestone should be exported from gsd-db.ts');
27
- });
28
-
29
- test('default status is "queued" not "active"', () => {
30
- // The status parameter should default to "queued" via nullish coalescing
31
- assert.match(dbSrc, /m\.status\s*\?\?\s*"queued"/,
32
- 'insertMilestone should default status to "queued"');
33
- });
14
+ test('omitted status persists as queued, not active', () => {
15
+ try {
16
+ openDatabase(':memory:');
17
+ insertMilestone({ id: 'M001', title: 'Reserved milestone' });
34
18
 
35
- test('comment explains the rationale', () => {
36
- assert.match(dbSrc, /never auto-create milestones as "active"/i,
37
- 'should have a comment explaining why default is queued');
19
+ assert.equal(getMilestone('M001')?.status, 'queued');
20
+ } finally {
21
+ closeDatabase();
22
+ }
38
23
  });
39
24
  });
@@ -0,0 +1,113 @@
1
+ /**
2
+ * phases-merge-error-stops-auto.test.ts — Regression test for #2766.
3
+ *
4
+ * When mergeAndExit throws a non-MergeConflictError, the auto loop must
5
+ * stop instead of continuing with unmerged work. This test verifies that
6
+ * all catch blocks in auto/phases.ts that handle mergeAndExit errors
7
+ * call stopAuto and return { action: "break" } for non-conflict errors.
8
+ */
9
+
10
+ import { createTestContext } from "./test-helpers.ts";
11
+ import { runPreDispatch } from "../auto/phases.ts";
12
+
13
+ const { assertTrue, report } = createTestContext();
14
+
15
+ console.log("\n=== #2766: Non-MergeConflictError stops auto mode ===");
16
+
17
+ const notifications: Array<{ message: string; level?: string }> = [];
18
+ const calls: string[] = [];
19
+ const basePath = "/tmp/gsd-test";
20
+ const ic = {
21
+ ctx: {
22
+ ui: {
23
+ notify(message: string, level?: string) {
24
+ notifications.push({ message, level });
25
+ },
26
+ },
27
+ },
28
+ pi: {},
29
+ s: {
30
+ basePath,
31
+ originalBasePath: basePath,
32
+ canonicalProjectRoot: basePath,
33
+ resourceVersionOnStart: "test",
34
+ currentMilestoneId: "M001",
35
+ currentUnit: null,
36
+ milestoneMergedInPhases: false,
37
+ },
38
+ prefs: undefined,
39
+ iteration: 1,
40
+ flowId: "test-flow",
41
+ nextSeq: () => 1,
42
+ deps: {
43
+ checkResourcesStale() {
44
+ return null;
45
+ },
46
+ invalidateAllCaches() {
47
+ calls.push("invalidate");
48
+ },
49
+ async preDispatchHealthGate() {
50
+ calls.push("health");
51
+ return { proceed: true, fixesApplied: [] };
52
+ },
53
+ async deriveState(projectRoot: string) {
54
+ calls.push(`derive:${projectRoot}`);
55
+ return {
56
+ phase: "complete",
57
+ activeMilestone: { id: "M001", title: "Milestone one" },
58
+ activeSlice: null,
59
+ activeTask: null,
60
+ registry: [{ id: "M001", status: "complete" }],
61
+ nextAction: "complete",
62
+ };
63
+ },
64
+ syncCmuxSidebar() {
65
+ calls.push("sync-sidebar");
66
+ },
67
+ setActiveMilestoneId(_basePath: string, mid: string) {
68
+ calls.push(`set-active:${mid}`);
69
+ },
70
+ reconcileMergeState() {
71
+ calls.push("reconcile");
72
+ return "clean";
73
+ },
74
+ preflightCleanRoot() {
75
+ calls.push("preflight");
76
+ return { ok: true, stashPushed: true, stashMarker: "marker" };
77
+ },
78
+ postflightPopStash() {
79
+ calls.push("postflight");
80
+ return { ok: true, needsManualRecovery: false };
81
+ },
82
+ resolver: {
83
+ mergeAndExit() {
84
+ calls.push("merge");
85
+ throw new Error("remote rejected push");
86
+ },
87
+ },
88
+ async stopAuto(_ctx: unknown, _pi: unknown, reason?: string) {
89
+ calls.push(`stop:${reason}`);
90
+ },
91
+ },
92
+ } as any;
93
+
94
+ const result = await runPreDispatch(ic, {
95
+ recentUnits: [],
96
+ stuckRecoveryAttempts: 0,
97
+ consecutiveFinalizeTimeouts: 0,
98
+ });
99
+
100
+ assertTrue(result.action === "break", "non-conflict merge error returns break");
101
+ if (result.action === "break") {
102
+ assertTrue(result.reason === "merge-failed", "non-conflict merge error uses merge-failed reason");
103
+ }
104
+ assertTrue(
105
+ calls.join(" > ") === "invalidate > health > derive:/tmp/gsd-test > sync-sidebar > set-active:M001 > reconcile > preflight > merge > postflight > stop:Merge error on milestone M001: Error: remote rejected push",
106
+ `pre-dispatch stops immediately after non-conflict merge failure (${calls.join(" > ")})`,
107
+ );
108
+ assertTrue(
109
+ notifications.some((n) => n.level === "error" && n.message.includes("Merge failed: remote rejected push")),
110
+ "user is notified with an error that merge failed",
111
+ );
112
+
113
+ report();
@@ -5,31 +5,45 @@
5
5
 
6
6
  import test from "node:test";
7
7
  import assert from "node:assert/strict";
8
- import { readFileSync } from "node:fs";
8
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
9
9
  import { join } from "node:path";
10
+ import { tmpdir } from "node:os";
11
+ import { AutoSession } from "../auto/session.ts";
12
+ import { postUnitPreVerification } from "../auto-post-unit.ts";
10
13
 
11
- const source = readFileSync(join(import.meta.dirname, "..", "auto-post-unit.ts"), "utf-8");
14
+ test("postUnitPreVerification rebuilds STATE.md after a completed unit", async () => {
15
+ const base = mkdtempSync(join(tmpdir(), "gsd-post-unit-state-"));
16
+ try {
17
+ const sliceDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
18
+ mkdirSync(sliceDir, { recursive: true });
19
+ writeFileSync(
20
+ join(base, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
21
+ "# Roadmap\n\n## Slices\n\n- [ ] **S01: Discussed slice** `risk:low` `depends:[]`\n",
22
+ );
23
+ writeFileSync(join(sliceDir, "S01-CONTEXT.md"), "# Slice Context\n\nReady.\n");
12
24
 
13
- test("auto-post-unit imports rebuildState", () => {
14
- assert.ok(
15
- source.includes('import { rebuildState } from "./doctor.js";'),
16
- "auto-post-unit.ts should import rebuildState from doctor.ts",
17
- );
18
- });
19
-
20
- test("postUnitPreVerification rebuilds STATE.md before worktree sync", () => {
21
- const fnStart = source.indexOf("export async function postUnitPreVerification");
22
- assert.ok(fnStart > 0, "postUnitPreVerification should exist");
25
+ const s = new AutoSession();
26
+ s.basePath = base;
27
+ s.originalBasePath = base;
28
+ s.currentMilestoneId = "M001";
29
+ s.currentUnit = { type: "discuss-slice", id: "M001/S01", startedAt: Date.now() };
23
30
 
24
- const fnEnd = source.indexOf("export async function postUnitPostVerification", fnStart);
25
- const section = source.slice(fnStart, fnEnd > fnStart ? fnEnd : undefined);
26
- const rebuildIdx = section.indexOf('await runSafely("postUnit", "state-rebuild"');
27
- const syncIdx = section.indexOf('await runSafely("postUnit", "worktree-sync"');
31
+ const result = await postUnitPreVerification({
32
+ s,
33
+ ctx: { ui: { notify() {} } } as any,
34
+ pi: {} as any,
35
+ buildSnapshotOpts: () => ({}),
36
+ lockBase: () => base,
37
+ stopAuto: async () => {},
38
+ pauseAuto: async () => {},
39
+ updateProgressWidget: () => {},
40
+ }, { skipSettleDelay: true, skipWorktreeSync: true });
28
41
 
29
- assert.ok(rebuildIdx > 0, "postUnitPreVerification should rebuild STATE.md after unit completion");
30
- assert.ok(syncIdx > 0, "postUnitPreVerification should sync worktree state back to the project root");
31
- assert.ok(
32
- rebuildIdx < syncIdx,
33
- "STATE.md rebuild should happen before worktree sync so synced state is fresh",
34
- );
42
+ assert.equal(result, "continue");
43
+ const statePath = join(base, ".gsd", "STATE.md");
44
+ assert.equal(existsSync(statePath), true);
45
+ assert.ok(readFileSync(statePath, "utf-8").includes("M001"));
46
+ } finally {
47
+ rmSync(base, { recursive: true, force: true });
48
+ }
35
49
  });
@@ -12,14 +12,9 @@
12
12
  import { describe, it } from 'node:test'
13
13
  import assert from 'node:assert/strict'
14
14
  import { normalizeFilePath, checkFilePathConsistency } from '../pre-execution-checks.ts'
15
- import { mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
15
+ import { mkdirSync, rmSync, writeFileSync } from 'node:fs'
16
16
  import { resolve } from 'node:path'
17
17
 
18
- const src = readFileSync(
19
- resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'pre-execution-checks.ts'),
20
- 'utf-8',
21
- )
22
-
23
18
  describe('normalizeFilePath backtick stripping (#3649)', () => {
24
19
  it('strips backticks from file paths', () => {
25
20
  assert.equal(normalizeFilePath('`src/foo.ts`'), 'src/foo.ts')
@@ -58,31 +53,42 @@ describe('normalizeFilePath backtick stripping (#3649)', () => {
58
53
  })
59
54
 
60
55
  describe('checkFilePathConsistency checks task.inputs not task.files (#3626)', () => {
61
- it('source uses only task.inputs in filesToCheck', () => {
62
- // Verify the fix structurally: the spread should be [...task.inputs] only
63
- const fnStart = src.indexOf('export function checkFilePathConsistency(')
64
- assert.ok(fnStart !== -1, 'checkFilePathConsistency function must exist')
65
-
66
- // Find the filesToCheck assignment
67
- const filesToCheckLine = src.indexOf('filesToCheck', fnStart)
68
- assert.ok(filesToCheckLine !== -1, 'filesToCheck assignment must exist')
69
-
70
- // Extract the line
71
- const lineEnd = src.indexOf('\n', filesToCheckLine)
72
- const line = src.slice(filesToCheckLine, lineEnd)
73
-
74
- // Must include task.inputs
75
- assert.ok(
76
- line.includes('task.inputs'),
77
- 'filesToCheck must reference task.inputs',
78
- )
56
+ it('ignores missing task.files entries that are only likely outputs', () => {
57
+ const task = {
58
+ milestone_id: 'M001',
59
+ slice_id: 'S01',
60
+ id: 'T01',
61
+ title: 'Create missing file',
62
+ status: 'pending',
63
+ one_liner: '',
64
+ narrative: '',
65
+ verification_result: '',
66
+ duration: '',
67
+ completed_at: null,
68
+ blocker_discovered: false,
69
+ deviations: '',
70
+ known_issues: '',
71
+ key_files: [],
72
+ key_decisions: [],
73
+ full_summary_md: '',
74
+ description: '',
75
+ estimate: '',
76
+ files: ['src/new-file.ts'],
77
+ verify: '',
78
+ inputs: [],
79
+ expected_output: ['src/new-file.ts'],
80
+ observability_impact: '',
81
+ full_plan_md: '',
82
+ sequence: 0,
83
+ }
79
84
 
80
- // Must NOT include task.files
81
- assert.ok(
82
- !line.includes('task.files'),
83
- 'filesToCheck must NOT reference task.files files likely touched include ' +
84
- 'files the task will create, so they do not need to pre-exist',
85
- )
85
+ const tmp = resolve(process.cwd(), '.tmp-pre-exec-files-ignore')
86
+ try {
87
+ mkdirSync(tmp, { recursive: true })
88
+ assert.deepEqual(checkFilePathConsistency([task as any], tmp), [])
89
+ } finally {
90
+ rmSync(tmp, { recursive: true, force: true })
91
+ }
86
92
  })
87
93
  })
88
94
 
@@ -1,3 +1,5 @@
1
+ // Project/App: GSD-2
2
+ // File Purpose: Integration tests for pre-execution check pause wiring.
1
3
  /**
2
4
  * pre-execution-pause-wiring.test.ts — Integration tests for pre-execution check → pauseAuto wiring.
3
5
  *
@@ -27,6 +29,11 @@ let tempDir: string;
27
29
  let dbPath: string;
28
30
  let originalCwd: string;
29
31
 
32
+ function resetAllCaches(): void {
33
+ invalidateAllCaches();
34
+ _clearGsdRootCache();
35
+ }
36
+
30
37
  /**
31
38
  * Create a minimal mock ExtensionContext.
32
39
  */
@@ -112,8 +119,8 @@ function setupTestEnvironment(): void {
112
119
  // Change cwd so loadEffectiveGSDPreferences finds our PREFERENCES.md
113
120
  process.chdir(tempDir);
114
121
 
115
- // Clear gsdRoot cache so it finds the new .gsd directory
116
- _clearGsdRootCache();
122
+ // Clear caches so it finds the new .gsd directory and preferences.
123
+ resetAllCaches();
117
124
 
118
125
  // Initialize DB
119
126
  dbPath = join(gsdDir, "gsd.db");
@@ -136,6 +143,7 @@ function cleanupTestEnvironment(): void {
136
143
  } catch {
137
144
  // Ignore close errors
138
145
  }
146
+ resetAllCaches();
139
147
  try {
140
148
  rmSync(tempDir, { recursive: true, force: true });
141
149
  } catch {
@@ -158,8 +166,7 @@ ${yamlLines.join("\n")}
158
166
  `;
159
167
  writeFileSync(join(tempDir, ".gsd", "PREFERENCES.md"), prefsContent);
160
168
  // Invalidate caches so the new preferences file is found
161
- invalidateAllCaches();
162
- _clearGsdRootCache();
169
+ resetAllCaches();
163
170
  }
164
171
 
165
172
  /**
@@ -486,6 +493,69 @@ describe("Pre-execution checks → pauseAuto wiring", () => {
486
493
  );
487
494
  });
488
495
 
496
+ test("files present in s.basePath (worktree) but absent from canonicalProjectRoot do not block", async () => {
497
+ writePreferences({
498
+ enhanced_verification: true,
499
+ enhanced_verification_pre: true,
500
+ enhanced_verification_strict: false,
501
+ });
502
+
503
+ // Regression: pre-exec checks used canonicalProjectRoot (project root), so
504
+ // files that a prior slice created in the worktree were falsely flagged as
505
+ // missing because they hadn't merged to main yet. Fix: use s.basePath.
506
+
507
+ // Create a separate "worktree" directory with the referenced files present.
508
+ const worktreeDir = join(tempDir, "worktree");
509
+ mkdirSync(join(worktreeDir, "lib"), { recursive: true });
510
+ mkdirSync(join(worktreeDir, ".gsd", "milestones", "M001", "slices", "S01", "tasks"), { recursive: true });
511
+ writeFileSync(join(worktreeDir, "lib", "types.ts"), "export type Habit = { id: string; name: string; };");
512
+ writeFileSync(join(worktreeDir, "lib", "useLocalStorage.ts"), "export function useLocalStorage() {}");
513
+
514
+ // The DB lives under tempDir (the "project root"). Insert slice + tasks.
515
+ insertMilestone({ id: "M001" });
516
+ insertSlice({ id: "S01", milestoneId: "M001", title: "Test Slice", risk: "low" });
517
+ insertTask({
518
+ id: "T01",
519
+ sliceId: "S01",
520
+ milestoneId: "M001",
521
+ title: "Task that reads prior-slice files",
522
+ status: "pending",
523
+ planning: {
524
+ description: "Reads lib/types.ts and lib/useLocalStorage.ts from prior slice",
525
+ estimate: "1h",
526
+ files: [],
527
+ verify: "npm test",
528
+ inputs: ["lib/types.ts", "lib/useLocalStorage.ts"],
529
+ expectedOutput: ["lib/utils.ts"],
530
+ observabilityImpact: "",
531
+ },
532
+ sequence: 0,
533
+ });
534
+
535
+ const ctx = makeMockCtx();
536
+ const pi = makeMockPi();
537
+ const pauseAutoMock = mock.fn(async () => {});
538
+
539
+ // s.basePath = worktreeDir (files exist here)
540
+ // Override canonicalProjectRoot → tempDir (files do NOT exist there)
541
+ const s = makeMockSession(worktreeDir, { type: "plan-slice", id: "M001/S01" });
542
+ Object.defineProperty(s, "canonicalProjectRoot", { get: () => tempDir });
543
+
544
+ const pctx = makePostUnitContext(s, ctx, pi, pauseAutoMock);
545
+ const result = await postUnitPostVerification(pctx);
546
+
547
+ assert.equal(
548
+ pauseAutoMock.mock.callCount(),
549
+ 0,
550
+ "pauseAuto should NOT be called when referenced files exist in s.basePath (worktree)",
551
+ );
552
+ assert.equal(
553
+ result,
554
+ "continue",
555
+ "postUnitPostVerification should return 'continue' when worktree files satisfy pre-exec inputs",
556
+ );
557
+ });
558
+
489
559
  test("uok gate runner persists pre-execution gate outcomes when enabled", async () => {
490
560
  writePreferences({
491
561
  enhanced_verification: true,
@@ -12,32 +12,30 @@ import assert from "node:assert/strict";
12
12
  import { readFileSync, mkdtempSync, mkdirSync, writeFileSync, existsSync, readdirSync, rmSync } from "node:fs";
13
13
  import { join } from "node:path";
14
14
  import { tmpdir } from "node:os";
15
+ import { syncWorktreeStateBack } from "../auto-worktree.ts";
15
16
 
16
- test("#2684: preferences files are NOT in ROOT_STATE_FILES (forward-only sync)", () => {
17
- const srcPath = join(import.meta.dirname, "..", "auto-worktree.ts");
18
- const src = readFileSync(srcPath, "utf-8");
17
+ test("#2684: syncWorktreeStateBack does not overwrite project PREFERENCES.md", () => {
18
+ const mainBase = mkdtempSync(join(tmpdir(), "gsd-wt-prefs-main-"));
19
+ const wtBase = mkdtempSync(join(tmpdir(), "gsd-wt-prefs-worktree-"));
20
+ const mainGsd = join(mainBase, ".gsd");
21
+ const wtGsd = join(wtBase, ".gsd");
22
+ mkdirSync(mainGsd, { recursive: true });
23
+ mkdirSync(wtGsd, { recursive: true });
19
24
 
20
- const constIdx = src.indexOf("ROOT_STATE_FILES");
21
- assert.ok(constIdx !== -1, "ROOT_STATE_FILES constant exists");
25
+ try {
26
+ const authoritative = "---\nversion: 1\n---\n\nmode: team\n";
27
+ writeFileSync(join(mainGsd, "PREFERENCES.md"), authoritative);
28
+ writeFileSync(join(wtGsd, "PREFERENCES.md"), "---\nversion: 1\n---\n\nmode: solo\n");
22
29
 
23
- const arrayStart = src.indexOf("[", constIdx);
24
- const arrayEnd = src.indexOf("] as const", arrayStart);
25
- const block = src.slice(arrayStart, arrayEnd);
30
+ const result = syncWorktreeStateBack(mainBase, wtBase, "M001");
26
31
 
27
- // Project preferences must NOT be in ROOT_STATE_FILES — they are handled separately
28
- // in syncGsdStateToWorktree() (forward-only, additive). Including it in
29
- // ROOT_STATE_FILES would cause syncWorktreeStateBack() to overwrite the
30
- // authoritative project root copy (#2684).
31
- const entries = block.split("\n")
32
- .map(l => l.trim())
33
- .filter(l => l.startsWith('"') && l.includes(".md"));
34
- const hasPrefs = entries.some(
35
- l => l.includes("PREFERENCES.md") || l.includes("preferences.md"),
36
- );
37
- assert.ok(
38
- !hasPrefs,
39
- "preferences files must NOT be in ROOT_STATE_FILES (back-sync would overwrite root)",
40
- );
32
+ assert.equal(readFileSync(join(mainGsd, "PREFERENCES.md"), "utf-8"), authoritative);
33
+ assert.ok(!result.synced.includes("PREFERENCES.md"));
34
+ assert.ok(!result.synced.includes("preferences.md"));
35
+ } finally {
36
+ rmSync(mainBase, { recursive: true, force: true });
37
+ rmSync(wtBase, { recursive: true, force: true });
38
+ }
41
39
  });
42
40
 
43
41
  // Phase C: copyPlanningArtifacts was deleted. Worktrees no longer