gsd-pi 2.65.0 → 2.66.0-dev.6c91c1f

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 (458) hide show
  1. package/dist/mcp-server.js +6 -2
  2. package/dist/resources/extensions/browser-tools/capture.js +20 -1
  3. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  4. package/dist/resources/extensions/gsd/auto/finalize-timeout.js +2 -0
  5. package/dist/resources/extensions/gsd/auto/loop.js +2 -2
  6. package/dist/resources/extensions/gsd/auto/phases.js +48 -5
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +13 -2
  8. package/dist/resources/extensions/gsd/auto/session.js +4 -0
  9. package/dist/resources/extensions/gsd/auto/types.js +2 -0
  10. package/dist/resources/extensions/gsd/auto-dashboard.js +2 -1
  11. package/dist/resources/extensions/gsd/auto-dispatch.js +99 -9
  12. package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
  13. package/dist/resources/extensions/gsd/auto-post-unit.js +17 -6
  14. package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
  15. package/dist/resources/extensions/gsd/auto-recovery.js +40 -22
  16. package/dist/resources/extensions/gsd/auto-start.js +175 -12
  17. package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
  18. package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
  19. package/dist/resources/extensions/gsd/auto.js +21 -15
  20. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
  21. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -0
  22. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +6 -4
  23. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -1
  24. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -3
  25. package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -1
  26. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +31 -1
  27. package/dist/resources/extensions/gsd/commands/context.js +8 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +23 -2
  29. package/dist/resources/extensions/gsd/commands-extensions.js +1 -1
  30. package/dist/resources/extensions/gsd/config-overlay.js +312 -0
  31. package/dist/resources/extensions/gsd/db-writer.js +13 -3
  32. package/dist/resources/extensions/gsd/detection.js +1 -1
  33. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
  34. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  35. package/dist/resources/extensions/gsd/doctor.js +2 -1
  36. package/dist/resources/extensions/gsd/files.js +17 -0
  37. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  38. package/dist/resources/extensions/gsd/gsd-db.js +47 -4
  39. package/dist/resources/extensions/gsd/guided-flow.js +220 -29
  40. package/dist/resources/extensions/gsd/index.js +1 -1
  41. package/dist/resources/extensions/gsd/json-persistence.js +5 -2
  42. package/dist/resources/extensions/gsd/md-importer.js +14 -7
  43. package/dist/resources/extensions/gsd/notification-overlay.js +1 -1
  44. package/dist/resources/extensions/gsd/notification-widget.js +2 -1
  45. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +1 -1
  46. package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
  47. package/dist/resources/extensions/gsd/pre-execution-checks.js +26 -5
  48. package/dist/resources/extensions/gsd/preferences-types.js +3 -0
  49. package/dist/resources/extensions/gsd/preferences-validation.js +45 -1
  50. package/dist/resources/extensions/gsd/preferences.js +9 -2
  51. package/dist/resources/extensions/gsd/preparation.js +1092 -0
  52. package/dist/resources/extensions/gsd/prompt-validation.js +67 -0
  53. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  54. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  55. package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  56. package/dist/resources/extensions/gsd/prompts/discuss.md +2 -0
  57. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +6 -1
  58. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  59. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  60. package/dist/resources/extensions/gsd/prompts/queue.md +2 -0
  61. package/dist/resources/extensions/gsd/prompts/rethink.md +2 -1
  62. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  63. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  64. package/dist/resources/extensions/gsd/quick.js +19 -15
  65. package/dist/resources/extensions/gsd/reactive-graph.js +12 -0
  66. package/dist/resources/extensions/gsd/roadmap-slices.js +24 -5
  67. package/dist/resources/extensions/gsd/safety/content-validator.js +3 -3
  68. package/dist/resources/extensions/gsd/session-lock.js +23 -1
  69. package/dist/resources/extensions/gsd/state.js +115 -28
  70. package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  71. package/dist/resources/extensions/gsd/tools/complete-milestone.js +15 -3
  72. package/dist/resources/extensions/gsd/tools/complete-slice.js +27 -6
  73. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -7
  74. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -5
  75. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +5 -2
  76. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +119 -0
  77. package/dist/resources/extensions/gsd/tools/reopen-slice.js +30 -0
  78. package/dist/resources/extensions/gsd/tools/reopen-task.js +18 -0
  79. package/dist/resources/extensions/gsd/triage-resolution.js +33 -16
  80. package/dist/resources/extensions/gsd/undo.js +3 -2
  81. package/dist/resources/extensions/gsd/workflow-events.js +1 -0
  82. package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
  83. package/dist/resources/extensions/gsd/workflow-projections.js +7 -9
  84. package/dist/resources/extensions/gsd/workflow-reconcile.js +100 -9
  85. package/dist/resources/extensions/gsd/workflow-templates.js +11 -2
  86. package/dist/resources/extensions/gsd/worktree-manager.js +5 -2
  87. package/dist/resources/extensions/gsd/worktree.js +9 -0
  88. package/dist/resources/extensions/shared/interview-ui.js +1 -1
  89. package/dist/resources/extensions/subagent/agents.js +19 -5
  90. package/dist/web/standalone/.next/BUILD_ID +1 -1
  91. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  92. package/dist/web/standalone/.next/build-manifest.json +4 -4
  93. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  94. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  95. package/dist/web/standalone/.next/required-server-files.json +3 -3
  96. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  97. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  99. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  107. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  109. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  110. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  111. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  123. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  135. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  155. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  165. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  171. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  185. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  187. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  189. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  191. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/index.html +1 -1
  201. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  202. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  203. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  204. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  205. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  206. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  207. package/dist/web/standalone/.next/server/app/page.js +2 -2
  208. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  210. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  211. package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
  212. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  214. package/dist/web/standalone/.next/server/middleware.js +2 -2
  215. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  216. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  217. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  218. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  219. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  220. package/dist/web/standalone/.next/static/chunks/6502.8874bcae249c02e1.js +9 -0
  221. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  222. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  223. package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +1 -0
  224. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  226. package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
  227. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  228. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  229. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  230. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  231. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  232. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  233. package/dist/web/standalone/server.js +1 -1
  234. package/package.json +1 -1
  235. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  236. package/packages/pi-coding-agent/dist/core/retry-handler.js +30 -19
  237. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  238. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +51 -0
  239. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  240. package/packages/pi-coding-agent/dist/core/sdk.js +9 -9
  241. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  242. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -1
  243. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  244. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +10 -1
  245. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  246. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
  247. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  248. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +20 -5
  249. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +15 -1
  251. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  252. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +18 -0
  253. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  254. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  255. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -0
  256. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  257. package/packages/pi-coding-agent/package.json +1 -1
  258. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +80 -0
  259. package/packages/pi-coding-agent/src/core/retry-handler.ts +37 -25
  260. package/packages/pi-coding-agent/src/core/sdk.ts +9 -9
  261. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +10 -0
  262. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +20 -4
  263. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +27 -0
  264. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +16 -1
  265. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +5 -0
  266. package/packages/pi-tui/dist/components/image.d.ts +2 -0
  267. package/packages/pi-tui/dist/components/image.d.ts.map +1 -1
  268. package/packages/pi-tui/dist/components/image.js +4 -0
  269. package/packages/pi-tui/dist/components/image.js.map +1 -1
  270. package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
  271. package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
  272. package/packages/pi-tui/dist/components/image.test.js +32 -0
  273. package/packages/pi-tui/dist/components/image.test.js.map +1 -0
  274. package/packages/pi-tui/src/components/image.test.ts +36 -0
  275. package/packages/pi-tui/src/components/image.ts +5 -0
  276. package/pkg/package.json +1 -1
  277. package/src/resources/extensions/browser-tools/capture.ts +19 -1
  278. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  279. package/src/resources/extensions/gsd/auto/finalize-timeout.ts +3 -0
  280. package/src/resources/extensions/gsd/auto/loop.ts +2 -2
  281. package/src/resources/extensions/gsd/auto/phases.ts +68 -3
  282. package/src/resources/extensions/gsd/auto/run-unit.ts +12 -2
  283. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  284. package/src/resources/extensions/gsd/auto/types.ts +5 -0
  285. package/src/resources/extensions/gsd/auto-dashboard.ts +2 -1
  286. package/src/resources/extensions/gsd/auto-dispatch.ts +110 -9
  287. package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
  288. package/src/resources/extensions/gsd/auto-post-unit.ts +16 -6
  289. package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
  290. package/src/resources/extensions/gsd/auto-recovery.ts +29 -23
  291. package/src/resources/extensions/gsd/auto-start.ts +188 -10
  292. package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
  293. package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
  294. package/src/resources/extensions/gsd/auto.ts +19 -8
  295. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
  296. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -0
  297. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -4
  298. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -1
  299. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +11 -3
  300. package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -1
  301. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +36 -1
  302. package/src/resources/extensions/gsd/commands/context.ts +7 -1
  303. package/src/resources/extensions/gsd/commands/handlers/core.ts +26 -2
  304. package/src/resources/extensions/gsd/commands-extensions.ts +1 -1
  305. package/src/resources/extensions/gsd/config-overlay.ts +331 -0
  306. package/src/resources/extensions/gsd/db-writer.ts +11 -3
  307. package/src/resources/extensions/gsd/detection.ts +1 -1
  308. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
  309. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  310. package/src/resources/extensions/gsd/doctor.ts +2 -1
  311. package/src/resources/extensions/gsd/files.ts +19 -0
  312. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  313. package/src/resources/extensions/gsd/gsd-db.ts +46 -4
  314. package/src/resources/extensions/gsd/guided-flow.ts +254 -30
  315. package/src/resources/extensions/gsd/index.ts +1 -0
  316. package/src/resources/extensions/gsd/json-persistence.ts +6 -3
  317. package/src/resources/extensions/gsd/md-importer.ts +13 -6
  318. package/src/resources/extensions/gsd/notification-overlay.ts +1 -1
  319. package/src/resources/extensions/gsd/notification-widget.ts +2 -1
  320. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +1 -1
  321. package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
  322. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -7
  323. package/src/resources/extensions/gsd/preferences-types.ts +25 -0
  324. package/src/resources/extensions/gsd/preferences-validation.ts +45 -1
  325. package/src/resources/extensions/gsd/preferences.ts +9 -2
  326. package/src/resources/extensions/gsd/preparation.ts +1419 -0
  327. package/src/resources/extensions/gsd/prompt-validation.ts +88 -0
  328. package/src/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  329. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  330. package/src/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  331. package/src/resources/extensions/gsd/prompts/discuss.md +2 -0
  332. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +6 -1
  333. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  334. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  335. package/src/resources/extensions/gsd/prompts/queue.md +2 -0
  336. package/src/resources/extensions/gsd/prompts/rethink.md +2 -1
  337. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  338. package/src/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  339. package/src/resources/extensions/gsd/quick.ts +20 -15
  340. package/src/resources/extensions/gsd/reactive-graph.ts +18 -0
  341. package/src/resources/extensions/gsd/roadmap-slices.ts +21 -5
  342. package/src/resources/extensions/gsd/safety/content-validator.ts +3 -3
  343. package/src/resources/extensions/gsd/session-lock.ts +17 -1
  344. package/src/resources/extensions/gsd/state.ts +115 -26
  345. package/src/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  346. package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +223 -0
  347. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +33 -2
  348. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +56 -0
  349. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +41 -0
  350. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +72 -0
  351. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +54 -0
  352. package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
  353. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
  354. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +36 -0
  355. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +46 -0
  356. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +33 -0
  357. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +37 -0
  358. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
  359. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +125 -0
  360. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -0
  361. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +69 -0
  362. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +42 -0
  363. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +38 -0
  364. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +103 -0
  365. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +42 -0
  366. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +11 -9
  367. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  368. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +28 -30
  369. package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
  370. package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +525 -0
  371. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +62 -0
  372. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +11 -10
  373. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +48 -0
  374. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +46 -0
  375. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +189 -0
  376. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +77 -0
  377. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +55 -0
  378. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +39 -0
  379. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +68 -0
  380. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +284 -20
  381. package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +2 -2
  382. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +2 -2
  383. package/src/resources/extensions/gsd/tests/preparation.test.ts +1211 -0
  384. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +53 -0
  385. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +83 -0
  386. package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +669 -0
  387. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -4
  388. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +85 -0
  389. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -1
  390. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +47 -0
  391. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +107 -0
  392. package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +45 -0
  393. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +63 -0
  394. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +4 -5
  395. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +51 -0
  396. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +56 -0
  397. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +31 -0
  398. package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +39 -0
  399. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +51 -0
  400. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -1
  401. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +36 -0
  402. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
  403. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +13 -0
  404. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +21 -0
  405. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +21 -0
  406. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +6 -7
  407. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +47 -0
  408. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +1 -0
  409. package/src/resources/extensions/gsd/tests/subagent-agent-discovery.test.ts +47 -0
  410. package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
  411. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +65 -0
  412. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +29 -1
  413. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +2 -1
  414. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +3 -4
  415. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +15 -0
  416. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +89 -0
  417. package/src/resources/extensions/gsd/tests/wave1-critical-regressions.test.ts +49 -0
  418. package/src/resources/extensions/gsd/tests/wave2-events-regressions.test.ts +48 -0
  419. package/src/resources/extensions/gsd/tests/wave3-session-regressions.test.ts +47 -0
  420. package/src/resources/extensions/gsd/tests/wave4-write-safety-regressions.test.ts +70 -0
  421. package/src/resources/extensions/gsd/tests/wave5-consistency-regressions.test.ts +165 -0
  422. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +48 -0
  423. package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +6 -3
  424. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +38 -0
  425. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +16 -0
  426. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -0
  427. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +16 -17
  428. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +13 -9
  429. package/src/resources/extensions/gsd/tests/worktree.test.ts +26 -9
  430. package/src/resources/extensions/gsd/tests/write-gate.test.ts +127 -2
  431. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -0
  432. package/src/resources/extensions/gsd/tools/complete-milestone.ts +13 -3
  433. package/src/resources/extensions/gsd/tools/complete-slice.ts +26 -6
  434. package/src/resources/extensions/gsd/tools/complete-task.ts +29 -7
  435. package/src/resources/extensions/gsd/tools/plan-milestone.ts +11 -9
  436. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +5 -2
  437. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
  438. package/src/resources/extensions/gsd/tools/reopen-slice.ts +27 -0
  439. package/src/resources/extensions/gsd/tools/reopen-task.ts +17 -0
  440. package/src/resources/extensions/gsd/triage-resolution.ts +37 -17
  441. package/src/resources/extensions/gsd/types.ts +4 -0
  442. package/src/resources/extensions/gsd/undo.ts +3 -2
  443. package/src/resources/extensions/gsd/workflow-events.ts +5 -3
  444. package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
  445. package/src/resources/extensions/gsd/workflow-projections.ts +7 -8
  446. package/src/resources/extensions/gsd/workflow-reconcile.ts +109 -8
  447. package/src/resources/extensions/gsd/workflow-templates.ts +11 -2
  448. package/src/resources/extensions/gsd/worktree-manager.ts +4 -2
  449. package/src/resources/extensions/gsd/worktree.ts +10 -0
  450. package/src/resources/extensions/shared/interview-ui.ts +1 -1
  451. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +8 -10
  452. package/src/resources/extensions/subagent/agents.ts +30 -6
  453. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
  454. package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +0 -1
  455. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  456. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  457. /package/dist/web/standalone/.next/static/{MRM3OSYIAa4HMDqVGQ9nt → _X1i-S7l1jZfb7lmIZozb}/_buildManifest.js +0 -0
  458. /package/dist/web/standalone/.next/static/{MRM3OSYIAa4HMDqVGQ9nt → _X1i-S7l1jZfb7lmIZozb}/_ssgManifest.js +0 -0
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Regression test for discuss phase incremental persistence (#2152).
3
+ * Verifies both milestone and slice discuss prompts instruct agents to
4
+ * save CONTEXT-DRAFT incrementally during question rounds.
5
+ */
6
+
7
+ import { describe, test } from "node:test";
8
+ import assert from "node:assert/strict";
9
+ import { readFileSync } from "node:fs";
10
+ import { join, dirname } from "node:path";
11
+ import { fileURLToPath } from "node:url";
12
+
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ const promptsDir = join(__dirname, "..", "prompts");
15
+
16
+ describe("discuss incremental persistence (#2152)", () => {
17
+ test("milestone discuss prompt includes CONTEXT-DRAFT save instruction", () => {
18
+ const content = readFileSync(join(promptsDir, "guided-discuss-milestone.md"), "utf-8");
19
+ assert.match(content, /CONTEXT-DRAFT/, "should mention CONTEXT-DRAFT");
20
+ assert.match(content, /Incremental persistence/, "should have incremental persistence section");
21
+ assert.match(content, /gsd_summary_save/, "should use gsd_summary_save tool");
22
+ });
23
+
24
+ test("slice discuss prompt includes CONTEXT-DRAFT save instruction", () => {
25
+ const content = readFileSync(join(promptsDir, "guided-discuss-slice.md"), "utf-8");
26
+ assert.match(content, /CONTEXT-DRAFT/, "should mention CONTEXT-DRAFT");
27
+ assert.match(content, /Incremental persistence/, "should have incremental persistence section");
28
+ });
29
+
30
+ test("drafts are saved silently without user notification", () => {
31
+ const milestone = readFileSync(join(promptsDir, "guided-discuss-milestone.md"), "utf-8");
32
+ const slice = readFileSync(join(promptsDir, "guided-discuss-slice.md"), "utf-8");
33
+ assert.match(milestone, /Do NOT mention this save to the user/);
34
+ assert.match(slice, /Do NOT mention this to the user/);
35
+ });
36
+ });
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Regression test for discuss-slice structured questions availability
3
+ *
4
+ * The guided-discuss-slice.md template must use the structuredQuestionsAvailable
5
+ * template variable to conditionally switch between ask_user_questions tool
6
+ * calls and plain-text questions, so the prompt works correctly when the
7
+ * structured questions tool is not available.
8
+ */
9
+
10
+ import { describe, it } from 'node:test'
11
+ import assert from 'node:assert/strict'
12
+ import { readFileSync } from 'node:fs'
13
+ import { resolve } from 'node:path'
14
+
15
+ const template = readFileSync(
16
+ resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'prompts', 'guided-discuss-slice.md'),
17
+ 'utf-8',
18
+ )
19
+
20
+ describe('discuss-slice structuredQuestionsAvailable template variable', () => {
21
+ it('template references structuredQuestionsAvailable variable', () => {
22
+ assert.ok(
23
+ template.includes('{{structuredQuestionsAvailable}}'),
24
+ 'guided-discuss-slice.md must use {{structuredQuestionsAvailable}} template variable',
25
+ )
26
+ })
27
+
28
+ it('template handles both true and false cases', () => {
29
+ const trueCase = template.includes('`{{structuredQuestionsAvailable}}` is `true`')
30
+ const falseCase = template.includes('`{{structuredQuestionsAvailable}}` is `false`')
31
+
32
+ assert.ok(trueCase, 'template must have a branch for structuredQuestionsAvailable=true')
33
+ assert.ok(falseCase, 'template must have a branch for structuredQuestionsAvailable=false')
34
+ })
35
+
36
+ it('false case instructs plain text questions', () => {
37
+ const falseIdx = template.indexOf('`{{structuredQuestionsAvailable}}` is `false`')
38
+ assert.ok(falseIdx !== -1)
39
+
40
+ const afterFalse = template.slice(falseIdx, falseIdx + 300)
41
+ assert.ok(
42
+ afterFalse.includes('plain text'),
43
+ 'when structuredQuestionsAvailable is false, questions should be in plain text',
44
+ )
45
+ })
46
+ })
@@ -0,0 +1,33 @@
1
+ /**
2
+ * dispatch-guard-closed-status.test.ts — #3653
3
+ *
4
+ * Verify that the dispatch guard uses isClosedStatus() instead of a raw
5
+ * `status === "complete"` check when determining whether a slice is done.
6
+ * Reconciled slices may carry statuses like "skipped" or "cancelled" which
7
+ * are also closed — the raw check caused false dispatch blocks.
8
+ */
9
+
10
+ import { describe, test } from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { readFileSync } from "node:fs";
13
+ import { join, dirname } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ const __dirname = dirname(fileURLToPath(import.meta.url));
17
+ const sourceFile = join(__dirname, "..", "dispatch-guard.ts");
18
+
19
+ describe("dispatch-guard isClosedStatus migration (#3653)", () => {
20
+ const source = readFileSync(sourceFile, "utf-8");
21
+
22
+ test("imports isClosedStatus from status-guards", () => {
23
+ assert.match(source, /import\s*\{[^}]*isClosedStatus[^}]*\}\s*from\s*["']\.\/status-guards/);
24
+ });
25
+
26
+ test("uses isClosedStatus() for slice done check instead of raw comparison", () => {
27
+ assert.match(source, /done:\s*isClosedStatus\(r\.status\)/);
28
+ });
29
+
30
+ test("does not use raw status === 'complete' for DB slice rows", () => {
31
+ assert.doesNotMatch(source, /done:\s*r\.status\s*===\s*["']complete["']/);
32
+ });
33
+ });
@@ -0,0 +1,37 @@
1
+ /**
2
+ * dispatcher-stuck-planning.test.ts — #3656
3
+ *
4
+ * Verify that state.ts contains the disk-to-DB task reconciliation logic
5
+ * that prevents the dispatcher from getting stuck in an infinite planning
6
+ * loop when the planner writes a PLAN.md but never calls the persistence
7
+ * tool, leaving the DB with zero task rows.
8
+ */
9
+
10
+ import { describe, test } from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { readFileSync } from "node:fs";
13
+ import { join, dirname } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ const __dirname = dirname(fileURLToPath(import.meta.url));
17
+ const sourceFile = join(__dirname, "..", "state.ts");
18
+
19
+ describe("dispatcher stuck-planning reconciliation (#3656)", () => {
20
+ const source = readFileSync(sourceFile, "utf-8");
21
+
22
+ test("imports insertTask from gsd-db", () => {
23
+ assert.match(source, /import\s*\{[^}]*insertTask[^}]*\}\s*from/);
24
+ });
25
+
26
+ test("contains plan-file task reconciliation block", () => {
27
+ assert.match(source, /tasks\.length\s*===\s*0\s*&&\s*planFile/);
28
+ });
29
+
30
+ test("calls insertTask for each disk plan task", () => {
31
+ assert.match(source, /insertTask\(\{/);
32
+ });
33
+
34
+ test("references issue #3600 in reconciliation comment", () => {
35
+ assert.match(source, /#3600/);
36
+ });
37
+ });
@@ -0,0 +1,37 @@
1
+ /**
2
+ * error-success-mask.test.ts — #3664
3
+ *
4
+ * Verify that the agent-end-recovery error handler detects when errorMessage
5
+ * is uninformative (e.g. "success", "ok", "unknown") and falls back to
6
+ * extracting the real error from the assistant message text content.
7
+ */
8
+
9
+ import { describe, test } from "node:test";
10
+ 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, "..", "bootstrap", "agent-end-recovery.ts");
17
+
18
+ describe("error-success mask detection (#3664)", () => {
19
+ const source = readFileSync(sourceFile, "utf-8");
20
+
21
+ test("detects useless errorMessage values with regex", () => {
22
+ assert.match(source, /success\|ok\|true\|error\|unknown/i);
23
+ });
24
+
25
+ test("extracts display message from content text block", () => {
26
+ assert.match(source, /textBlock/);
27
+ assert.match(source, /\.text\.slice\(0,\s*300\)/);
28
+ });
29
+
30
+ test("classifies using rawErrorMsg, not displayMsg", () => {
31
+ assert.match(source, /classifyError\(rawErrorMsg/);
32
+ });
33
+
34
+ test("references issue #3588 in comments", () => {
35
+ assert.match(source, /#3588/);
36
+ });
37
+ });
@@ -19,8 +19,10 @@
19
19
  import { createTestContext } from "./test-helpers.ts";
20
20
  import {
21
21
  withTimeout,
22
+ FINALIZE_PRE_TIMEOUT_MS,
22
23
  FINALIZE_POST_TIMEOUT_MS,
23
24
  } from "../auto/finalize-timeout.ts";
25
+ import { MAX_FINALIZE_TIMEOUTS } from "../auto/types.ts";
24
26
 
25
27
  const { assertTrue, assertEq, report } = createTestContext();
26
28
 
@@ -78,6 +80,25 @@ const { assertTrue, assertEq, report } = createTestContext();
78
80
  assertTrue(caught, "rejection should propagate");
79
81
  }
80
82
 
83
+ // ═══ Test: FINALIZE_PRE_TIMEOUT_MS is defined and reasonable ═════════════════
84
+
85
+ {
86
+ console.log("\n=== #3757: pre-verification timeout constant is defined and reasonable ===");
87
+
88
+ assertTrue(
89
+ typeof FINALIZE_PRE_TIMEOUT_MS === "number",
90
+ "FINALIZE_PRE_TIMEOUT_MS should be a number",
91
+ );
92
+ assertTrue(
93
+ FINALIZE_PRE_TIMEOUT_MS >= 30_000,
94
+ `pre timeout should be >= 30s (got ${FINALIZE_PRE_TIMEOUT_MS}ms)`,
95
+ );
96
+ assertTrue(
97
+ FINALIZE_PRE_TIMEOUT_MS <= 120_000,
98
+ `pre timeout should be <= 120s (got ${FINALIZE_PRE_TIMEOUT_MS}ms)`,
99
+ );
100
+ }
101
+
81
102
  // ═══ Test: FINALIZE_POST_TIMEOUT_MS is defined and reasonable ═════════════════
82
103
 
83
104
  {
@@ -113,4 +134,108 @@ const { assertTrue, assertEq, report } = createTestContext();
113
134
  assertEq(result.timedOut, false, "should not time out");
114
135
  }
115
136
 
137
+ // ═══ Test: runFinalize wraps BOTH pre and post verification with withTimeout ═
138
+
139
+ {
140
+ console.log("\n=== #3757: runFinalize wraps preVerification with timeout guard ===");
141
+
142
+ const { readFileSync } = await import("node:fs");
143
+ const phasesSource = readFileSync(
144
+ new URL("../auto/phases.ts", import.meta.url),
145
+ "utf-8",
146
+ );
147
+
148
+ // Find the runFinalize function body
149
+ const fnIdx = phasesSource.indexOf("export async function runFinalize(");
150
+ assertTrue(fnIdx > 0, "runFinalize function should exist in phases.ts");
151
+
152
+ const fnBody = phasesSource.slice(fnIdx, fnIdx + 8000);
153
+
154
+ // postUnitPreVerification must be wrapped in withTimeout
155
+ const preTimeoutIdx = fnBody.indexOf("withTimeout(");
156
+ assertTrue(preTimeoutIdx > 0, "withTimeout should appear in runFinalize");
157
+
158
+ const preVerIdx = fnBody.indexOf("postUnitPreVerification");
159
+ assertTrue(preVerIdx > 0, "postUnitPreVerification should appear in runFinalize");
160
+
161
+ // The first withTimeout should wrap postUnitPreVerification (not postUnitPostVerification)
162
+ const firstWithTimeout = fnBody.slice(preTimeoutIdx, preTimeoutIdx + 200);
163
+ assertTrue(
164
+ firstWithTimeout.includes("postUnitPreVerification"),
165
+ "first withTimeout in runFinalize should wrap postUnitPreVerification",
166
+ );
167
+
168
+ // postUnitPostVerification must also be wrapped
169
+ const postVerIdx = fnBody.indexOf("postUnitPostVerification");
170
+ assertTrue(postVerIdx > 0, "postUnitPostVerification should appear in runFinalize");
171
+
172
+ // Count withTimeout occurrences — should be at least 2 (pre + post)
173
+ const timeoutCount = (fnBody.match(/withTimeout\(/g) || []).length;
174
+ assertTrue(
175
+ timeoutCount >= 2,
176
+ `runFinalize should have at least 2 withTimeout guards (found ${timeoutCount})`,
177
+ );
178
+ }
179
+
180
+ // ═══ Test: MAX_FINALIZE_TIMEOUTS is defined and reasonable ═══════════════════
181
+
182
+ {
183
+ console.log("\n=== #3757: MAX_FINALIZE_TIMEOUTS is defined and reasonable ===");
184
+
185
+ assertTrue(
186
+ typeof MAX_FINALIZE_TIMEOUTS === "number",
187
+ "MAX_FINALIZE_TIMEOUTS should be a number",
188
+ );
189
+ assertTrue(
190
+ MAX_FINALIZE_TIMEOUTS >= 2,
191
+ `threshold should be >= 2 (got ${MAX_FINALIZE_TIMEOUTS})`,
192
+ );
193
+ assertTrue(
194
+ MAX_FINALIZE_TIMEOUTS <= 10,
195
+ `threshold should be <= 10 (got ${MAX_FINALIZE_TIMEOUTS})`,
196
+ );
197
+ }
198
+
199
+ // ═══ Test: timeout handlers escalate after consecutive timeouts ══════════════
200
+
201
+ {
202
+ console.log("\n=== #3757: timeout handlers escalate and detach currentUnit ===");
203
+
204
+ const { readFileSync } = await import("node:fs");
205
+ const phasesSource = readFileSync(
206
+ new URL("../auto/phases.ts", import.meta.url),
207
+ "utf-8",
208
+ );
209
+
210
+ const fnIdx = phasesSource.indexOf("export async function runFinalize(");
211
+ const fnBody = phasesSource.slice(fnIdx, fnIdx + 8000);
212
+
213
+ // Both timeout handlers should increment consecutiveFinalizeTimeouts
214
+ const incrementCount = (fnBody.match(/consecutiveFinalizeTimeouts\+\+/g) || []).length;
215
+ assertTrue(
216
+ incrementCount >= 2,
217
+ `should increment consecutiveFinalizeTimeouts in both pre and post handlers (found ${incrementCount})`,
218
+ );
219
+
220
+ // Both timeout handlers should check MAX_FINALIZE_TIMEOUTS for escalation
221
+ const escalationCount = (fnBody.match(/MAX_FINALIZE_TIMEOUTS/g) || []).length;
222
+ assertTrue(
223
+ escalationCount >= 2,
224
+ `should check MAX_FINALIZE_TIMEOUTS in both handlers (found ${escalationCount})`,
225
+ );
226
+
227
+ // Both timeout handlers should null out s.currentUnit to prevent late mutations
228
+ const detachCount = (fnBody.match(/s\.currentUnit\s*=\s*null/g) || []).length;
229
+ assertTrue(
230
+ detachCount >= 2,
231
+ `should detach s.currentUnit in both timeout handlers (found ${detachCount})`,
232
+ );
233
+
234
+ // Successful finalize should reset the counter
235
+ assertTrue(
236
+ fnBody.includes("consecutiveFinalizeTimeouts = 0"),
237
+ "should reset consecutiveFinalizeTimeouts on successful finalize",
238
+ );
239
+ }
240
+
116
241
  report();
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Regression test for #3669 — findMissingSummaries skips closed slices
3
+ *
4
+ * When a slice has status "skipped", "complete", or "done", it should be
5
+ * excluded from the missing-summary check because closed slices intentionally
6
+ * lack SUMMARY files (or their DB status is authoritative).
7
+ *
8
+ * This is a structural verification test — it reads the source to confirm the
9
+ * CLOSED_STATUSES guard exists at the filter site.
10
+ */
11
+
12
+ import { describe, test } from 'node:test';
13
+ import assert from 'node:assert/strict';
14
+ import { readFileSync } from 'node:fs';
15
+ import { fileURLToPath } from 'node:url';
16
+ import { dirname, join } from 'node:path';
17
+
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = dirname(__filename);
20
+
21
+ const source = readFileSync(join(__dirname, '..', 'auto-dispatch.ts'), 'utf-8');
22
+
23
+ describe('findMissingSummaries closed-status exclusion (#3669)', () => {
24
+ test('CLOSED_STATUSES set includes skipped, complete, and done', () => {
25
+ // The source must define a CLOSED_STATUSES set with all three statuses
26
+ assert.match(source, /CLOSED_STATUSES.*=.*new Set\(/,
27
+ 'CLOSED_STATUSES set should be defined');
28
+ assert.match(source, /"skipped"/, 'CLOSED_STATUSES should include "skipped"');
29
+ assert.match(source, /"complete"/, 'CLOSED_STATUSES should include "complete"');
30
+ assert.match(source, /"done"/, 'CLOSED_STATUSES should include "done"');
31
+ });
32
+
33
+ test('filter uses CLOSED_STATUSES.has() to exclude closed slices', () => {
34
+ assert.match(source, /CLOSED_STATUSES\.has\(s\.status\)/,
35
+ 'filter should call CLOSED_STATUSES.has(s.status)');
36
+ });
37
+
38
+ test('findMissingSummaries function exists', () => {
39
+ assert.match(source, /function findMissingSummaries\(/,
40
+ 'findMissingSummaries function should be defined');
41
+ });
42
+
43
+ test('filter is negated (excludes closed, keeps open)', () => {
44
+ // The filter should use !CLOSED_STATUSES.has() to exclude closed slices
45
+ assert.match(source, /!CLOSED_STATUSES\.has\(s\.status\)/,
46
+ 'filter should negate CLOSED_STATUSES.has() to exclude closed slices');
47
+ });
48
+ });
@@ -0,0 +1,69 @@
1
+ // GSD Extension — formatShortcut tests
2
+ // Verifies OS-specific keyboard shortcut rendering.
3
+
4
+ import test from 'node:test';
5
+ import assert from 'node:assert/strict';
6
+ import { formatShortcut } from '../files.ts';
7
+
8
+ // ─── formatShortcut renders per-platform shortcuts ──────────────────────
9
+
10
+ test('formatShortcut: converts Ctrl+Alt combo on macOS', () => {
11
+ // formatShortcut uses process.platform at module load time.
12
+ // We can only test the current platform's behavior.
13
+ const result = formatShortcut('Ctrl+Alt+G');
14
+ if (process.platform === 'darwin') {
15
+ assert.strictEqual(result, '⌃⌥G', 'macOS should use ⌃⌥ symbols');
16
+ } else {
17
+ assert.strictEqual(result, 'Ctrl+Alt+G', 'non-macOS should pass through unchanged');
18
+ }
19
+ });
20
+
21
+ test('formatShortcut: converts Ctrl+Alt+N', () => {
22
+ const result = formatShortcut('Ctrl+Alt+N');
23
+ if (process.platform === 'darwin') {
24
+ assert.strictEqual(result, '⌃⌥N');
25
+ } else {
26
+ assert.strictEqual(result, 'Ctrl+Alt+N');
27
+ }
28
+ });
29
+
30
+ test('formatShortcut: converts Ctrl+Alt+B', () => {
31
+ const result = formatShortcut('Ctrl+Alt+B');
32
+ if (process.platform === 'darwin') {
33
+ assert.strictEqual(result, '⌃⌥B');
34
+ } else {
35
+ assert.strictEqual(result, 'Ctrl+Alt+B');
36
+ }
37
+ });
38
+
39
+ test('formatShortcut: converts standalone Ctrl modifier', () => {
40
+ const result = formatShortcut('Ctrl+C');
41
+ if (process.platform === 'darwin') {
42
+ assert.strictEqual(result, '⌃C');
43
+ } else {
44
+ assert.strictEqual(result, 'Ctrl+C');
45
+ }
46
+ });
47
+
48
+ test('formatShortcut: converts Shift modifier', () => {
49
+ const result = formatShortcut('Shift+Tab');
50
+ if (process.platform === 'darwin') {
51
+ assert.strictEqual(result, '⇧Tab');
52
+ } else {
53
+ assert.strictEqual(result, 'Shift+Tab');
54
+ }
55
+ });
56
+
57
+ test('formatShortcut: converts Cmd modifier', () => {
58
+ const result = formatShortcut('Cmd+S');
59
+ if (process.platform === 'darwin') {
60
+ assert.strictEqual(result, '⌘S');
61
+ } else {
62
+ assert.strictEqual(result, 'Cmd+S');
63
+ }
64
+ });
65
+
66
+ test('formatShortcut: passes through plain key names', () => {
67
+ assert.strictEqual(formatShortcut('Escape'), 'Escape');
68
+ assert.strictEqual(formatShortcut('Enter'), 'Enter');
69
+ });
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Regression test for #3693 — suppress repeated frontmatter parse warnings
3
+ *
4
+ * parseFrontmatterBlock was logging a YAML parse warning on every call.
5
+ * The fix adds a _warnedFrontmatterParse flag so the warning only fires once.
6
+ */
7
+
8
+ import { describe, test } from 'node:test';
9
+ import assert from 'node:assert/strict';
10
+ import { readFileSync } from 'node:fs';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { dirname, join } from 'node:path';
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = dirname(__filename);
16
+
17
+ const prefsSrc = readFileSync(
18
+ join(__dirname, '..', 'preferences.ts'),
19
+ 'utf-8',
20
+ );
21
+
22
+ describe('frontmatter parse noise suppression (#3693)', () => {
23
+ test('_warnedFrontmatterParse flag is defined', () => {
24
+ assert.match(prefsSrc, /_warnedFrontmatterParse/,
25
+ '_warnedFrontmatterParse flag should exist in preferences.ts');
26
+ });
27
+
28
+ test('parseFrontmatterBlock function exists', () => {
29
+ assert.match(prefsSrc, /function parseFrontmatterBlock\(/,
30
+ 'parseFrontmatterBlock function should be defined');
31
+ });
32
+
33
+ test('flag is checked before warning', () => {
34
+ assert.match(prefsSrc, /if\s*\(\s*!_warnedFrontmatterParse\s*\)/,
35
+ 'should check !_warnedFrontmatterParse before logging');
36
+ });
37
+
38
+ test('flag is set to true after first warning', () => {
39
+ assert.match(prefsSrc, /_warnedFrontmatterParse\s*=\s*true/,
40
+ 'should set _warnedFrontmatterParse = true after warning');
41
+ });
42
+ });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Regression test — .bg-shell/ added to BASELINE_PATTERNS in gitignore.ts
3
+ *
4
+ * The bg-shell background process directory was not included in the
5
+ * baseline gitignore patterns, causing it to appear as untracked in
6
+ * git status and potentially be committed.
7
+ *
8
+ * Structural verification test — reads source to confirm .bg-shell/
9
+ * is in BASELINE_PATTERNS.
10
+ */
11
+
12
+ import { describe, test } from 'node:test';
13
+ import assert from 'node:assert/strict';
14
+ import { readFileSync } from 'node:fs';
15
+ import { fileURLToPath } from 'node:url';
16
+ import { dirname, join } from 'node:path';
17
+
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = dirname(__filename);
20
+
21
+ const source = readFileSync(join(__dirname, '..', 'gitignore.ts'), 'utf-8');
22
+
23
+ describe('.bg-shell/ in BASELINE_PATTERNS', () => {
24
+ test('BASELINE_PATTERNS array is defined', () => {
25
+ assert.match(source, /const BASELINE_PATTERNS\s*=/,
26
+ 'BASELINE_PATTERNS should be defined');
27
+ });
28
+
29
+ test('.bg-shell/ is included in BASELINE_PATTERNS', () => {
30
+ // Extract the BASELINE_PATTERNS array content
31
+ const patternsStart = source.indexOf('BASELINE_PATTERNS');
32
+ const arrayStart = source.indexOf('[', patternsStart);
33
+ const arrayEnd = source.indexOf('] as const', arrayStart);
34
+ const patternsContent = source.slice(arrayStart, arrayEnd);
35
+ assert.match(patternsContent, /\.bg-shell\//,
36
+ '.bg-shell/ should be in BASELINE_PATTERNS');
37
+ });
38
+ });
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Regression test for #3475: guided-flow must rebuild STATE.md from derived
3
+ * state before dispatching workflows.
4
+ *
5
+ * Verifies that buildStateMarkdown() produces content matching the derived
6
+ * state (not a stale on-disk cache), and that the rebuild helper is wired
7
+ * correctly from doctor.ts.
8
+ */
9
+
10
+ import { describe, test, afterEach } from "node:test";
11
+ import assert from "node:assert/strict";
12
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync } from "node:fs";
13
+ import { join } from "node:path";
14
+ import { tmpdir } from "node:os";
15
+
16
+ import { deriveState, invalidateStateCache } from "../state.ts";
17
+ import { buildStateMarkdown, rebuildState } from "../doctor.ts";
18
+ import { resolveGsdRootFile } from "../paths.ts";
19
+ import {
20
+ openDatabase,
21
+ closeDatabase,
22
+ insertMilestone,
23
+ insertSlice,
24
+ insertTask,
25
+ } from "../gsd-db.ts";
26
+
27
+ function createFixtureBase(): string {
28
+ const base = mkdtempSync(join(tmpdir(), "gsd-guided-state-"));
29
+ mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
30
+ return base;
31
+ }
32
+
33
+ function writeFile(base: string, relativePath: string, content: string): void {
34
+ const full = join(base, ".gsd", relativePath);
35
+ mkdirSync(join(full, ".."), { recursive: true });
36
+ writeFileSync(full, content);
37
+ }
38
+
39
+ describe("guided-flow STATE.md rebuild (#3475)", () => {
40
+ let base: string;
41
+
42
+ afterEach(() => {
43
+ closeDatabase();
44
+ if (base) rmSync(base, { recursive: true, force: true });
45
+ });
46
+
47
+ test("rebuildState writes STATE.md matching derived state, not stale cache", async () => {
48
+ base = createFixtureBase();
49
+ openDatabase(":memory:");
50
+
51
+ // Set up real active milestone M010
52
+ insertMilestone({ id: "M010", title: "Real Active", status: "active" });
53
+ insertSlice({ id: "S03", milestoneId: "M010", title: "Slice Three", status: "active", risk: "low", depends: [] });
54
+ insertTask({ id: "T05", sliceId: "S03", milestoneId: "M010", title: "Task Five", status: "pending" });
55
+ writeFile(base, "milestones/M010/M010-CONTEXT.md", "# M010: Real Active\n\nReal work here.");
56
+ writeFile(base, "milestones/M010/M010-ROADMAP.md", "# M010\n\n## Slices\n\n- [ ] **S03: Slice Three**");
57
+
58
+ // Write a STALE STATE.md pointing to wrong milestone
59
+ writeFile(base, "STATE.md", [
60
+ "# GSD State",
61
+ "",
62
+ "**Active Milestone:** M008: Old Queued",
63
+ "**Active Slice:** None",
64
+ "**Phase:** pre-planning",
65
+ "",
66
+ "## Next Action",
67
+ "Milestone M008 has a roadmap but no slices defined.",
68
+ ].join("\n"));
69
+
70
+ // Derive state — should return M010
71
+ invalidateStateCache();
72
+ const state = await deriveState(base);
73
+ assert.equal(state.activeMilestone?.id, "M010", "Derived state should be M010");
74
+
75
+ // Rebuild STATE.md
76
+ await rebuildState(base);
77
+
78
+ // Read the rebuilt STATE.md
79
+ const statePath = resolveGsdRootFile(base, "STATE");
80
+ const rebuilt = readFileSync(statePath, "utf-8");
81
+
82
+ // Should contain M010, NOT M008
83
+ assert.ok(rebuilt.includes("M010"), "Rebuilt STATE.md should reference M010");
84
+ assert.ok(!rebuilt.includes("M008"), "Rebuilt STATE.md should NOT reference stale M008");
85
+ });
86
+
87
+ test("buildStateMarkdown produces correct active milestone from GSDState", async () => {
88
+ base = createFixtureBase();
89
+ openDatabase(":memory:");
90
+
91
+ insertMilestone({ id: "M070", title: "Current Work", status: "active" });
92
+ insertSlice({ id: "S01", milestoneId: "M070", title: "First Slice", status: "active", risk: "low", depends: [] });
93
+ writeFile(base, "milestones/M070/M070-CONTEXT.md", "# M070: Current Work");
94
+ writeFile(base, "milestones/M070/M070-ROADMAP.md", "# M070\n\n## Slices\n\n- [ ] **S01: First Slice**");
95
+
96
+ invalidateStateCache();
97
+ const state = await deriveState(base);
98
+ const md = buildStateMarkdown(state);
99
+
100
+ assert.ok(md.includes("M070"), "State markdown should include active milestone M070");
101
+ assert.ok(md.includes("Current Work") || md.includes("M070"), "State markdown should include milestone title or ID");
102
+ });
103
+ });