gsd-pi 2.70.1 → 2.71.0-dev.4c35d99

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 (533) hide show
  1. package/README.md +57 -17
  2. package/dist/cli.js +29 -3
  3. package/dist/headless-events.d.ts +2 -0
  4. package/dist/headless-events.js +7 -0
  5. package/dist/headless.js +16 -3
  6. package/dist/mcp-server.js +40 -17
  7. package/dist/provider-migrations.d.ts +10 -0
  8. package/dist/provider-migrations.js +12 -0
  9. package/dist/resource-loader.js +139 -13
  10. package/dist/resources/GSD-WORKFLOW.md +1 -1
  11. package/dist/resources/agents/debugger.md +58 -0
  12. package/dist/resources/agents/doc-writer.md +43 -0
  13. package/dist/resources/agents/git-ops.md +56 -0
  14. package/dist/resources/agents/javascript-pro.md +46 -271
  15. package/dist/resources/agents/planner.md +55 -0
  16. package/dist/resources/agents/refactorer.md +47 -0
  17. package/dist/resources/agents/reviewer.md +48 -0
  18. package/dist/resources/agents/security.md +59 -0
  19. package/dist/resources/agents/tester.md +50 -0
  20. package/dist/resources/agents/typescript-pro.md +41 -235
  21. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +242 -40
  22. package/dist/resources/extensions/get-secrets-from-user.js +17 -1
  23. package/dist/resources/extensions/gsd/auto/infra-errors.js +34 -0
  24. package/dist/resources/extensions/gsd/auto/loop.js +32 -1
  25. package/dist/resources/extensions/gsd/auto/phases.js +5 -1
  26. package/dist/resources/extensions/gsd/auto/session.js +11 -0
  27. package/dist/resources/extensions/gsd/auto-dashboard.js +22 -16
  28. package/dist/resources/extensions/gsd/auto-model-selection.js +10 -2
  29. package/dist/resources/extensions/gsd/auto-prompts.js +88 -33
  30. package/dist/resources/extensions/gsd/auto-start.js +37 -18
  31. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  32. package/dist/resources/extensions/gsd/auto-worktree.js +1 -1
  33. package/dist/resources/extensions/gsd/auto.js +56 -0
  34. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
  35. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +6 -0
  36. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +63 -51
  37. package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -0
  38. package/dist/resources/extensions/gsd/commands/context.js +15 -6
  39. package/dist/resources/extensions/gsd/commands/dispatcher.js +12 -2
  40. package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -33
  41. package/dist/resources/extensions/gsd/commands/handlers/core.js +56 -11
  42. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +15 -6
  43. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +4 -10
  44. package/dist/resources/extensions/gsd/custom-workflow-engine.js +16 -12
  45. package/dist/resources/extensions/gsd/dashboard-overlay.js +8 -3
  46. package/dist/resources/extensions/gsd/dispatch-guard.js +18 -1
  47. package/dist/resources/extensions/gsd/doctor-providers.js +23 -0
  48. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  49. package/dist/resources/extensions/gsd/file-lock.js +60 -0
  50. package/dist/resources/extensions/gsd/forensics.js +19 -6
  51. package/dist/resources/extensions/gsd/gate-registry.js +208 -0
  52. package/dist/resources/extensions/gsd/gsd-db.js +41 -0
  53. package/dist/resources/extensions/gsd/guided-flow.js +17 -20
  54. package/dist/resources/extensions/gsd/init-wizard.js +3 -11
  55. package/dist/resources/extensions/gsd/metrics.js +1 -0
  56. package/dist/resources/extensions/gsd/milestone-actions.js +10 -4
  57. package/dist/resources/extensions/gsd/milestone-validation-gates.js +11 -12
  58. package/dist/resources/extensions/gsd/notification-overlay.js +42 -13
  59. package/dist/resources/extensions/gsd/notification-store.js +56 -5
  60. package/dist/resources/extensions/gsd/notification-widget.js +5 -13
  61. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +8 -3
  62. package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -2
  63. package/dist/resources/extensions/gsd/prompt-validation.js +126 -0
  64. package/dist/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  65. package/dist/resources/extensions/gsd/prompts/discuss.md +33 -13
  66. package/dist/resources/extensions/gsd/prompts/execute-task.md +22 -19
  67. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  68. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  69. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/queue.md +3 -2
  71. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  72. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  73. package/dist/resources/extensions/gsd/session-model-override.js +25 -0
  74. package/dist/resources/extensions/gsd/shortcut-defs.js +40 -0
  75. package/dist/resources/extensions/gsd/state.js +241 -332
  76. package/dist/resources/extensions/gsd/tools/complete-slice.js +52 -1
  77. package/dist/resources/extensions/gsd/tools/complete-task.js +51 -1
  78. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +38 -1
  79. package/dist/resources/extensions/gsd/workflow-events.js +25 -13
  80. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +56 -0
  81. package/dist/resources/extensions/gsd/workflow-mcp.js +1 -1
  82. package/dist/resources/extensions/ollama/index.js +13 -5
  83. package/dist/resources/extensions/shared/gsd-phase-state.js +35 -0
  84. package/dist/resources/extensions/subagent/agents.js +8 -0
  85. package/dist/resources/extensions/subagent/index.js +17 -0
  86. package/dist/resources/skills/create-skill/SKILL.md +2 -0
  87. package/dist/startup-model-validation.d.ts +0 -1
  88. package/dist/startup-model-validation.js +6 -2
  89. package/dist/web/standalone/.next/BUILD_ID +1 -1
  90. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  91. package/dist/web/standalone/.next/build-manifest.json +4 -4
  92. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  93. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  94. package/dist/web/standalone/.next/required-server-files.json +3 -3
  95. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  96. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  106. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  109. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  110. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  112. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  122. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  134. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  154. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  164. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  170. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  186. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
  190. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/index.html +1 -1
  200. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  201. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  202. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  203. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  204. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  205. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  206. package/dist/web/standalone/.next/server/app/page.js +2 -2
  207. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  209. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  210. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  211. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/middleware.js +2 -2
  214. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  216. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  217. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  218. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  219. package/dist/web/standalone/.next/static/chunks/2826.dd3dc8bbd3025fa5.js +9 -0
  220. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
  221. package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
  222. package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
  223. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
  224. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/{webpack-6e4d7e9a4f57bed4.js → webpack-b868033a5834586d.js} +1 -1
  226. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  227. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  228. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  229. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  230. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  231. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  232. package/dist/web/standalone/server.js +1 -1
  233. package/package.json +1 -1
  234. package/packages/mcp-server/dist/env-writer.d.ts +39 -0
  235. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -0
  236. package/packages/mcp-server/dist/env-writer.js +158 -0
  237. package/packages/mcp-server/dist/env-writer.js.map +1 -0
  238. package/packages/mcp-server/dist/server.d.ts +23 -3
  239. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  240. package/packages/mcp-server/dist/server.js +192 -44
  241. package/packages/mcp-server/dist/server.js.map +1 -1
  242. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  243. package/packages/mcp-server/dist/workflow-tools.js +22 -12
  244. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  245. package/packages/mcp-server/src/env-writer.test.ts +280 -0
  246. package/packages/mcp-server/src/env-writer.ts +183 -0
  247. package/packages/mcp-server/src/secure-env-collect.test.ts +265 -0
  248. package/packages/mcp-server/src/server.ts +247 -41
  249. package/packages/mcp-server/src/workflow-tools.test.ts +110 -0
  250. package/packages/mcp-server/src/workflow-tools.ts +32 -12
  251. package/packages/pi-ai/dist/providers/amazon-bedrock.js +11 -2
  252. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts +2 -0
  254. package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts.map +1 -0
  255. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +20 -0
  256. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -0
  257. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +4 -1
  258. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  259. package/packages/pi-ai/dist/providers/anthropic-shared.js +8 -3
  260. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  261. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +44 -1
  262. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
  263. package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -1
  264. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  265. package/packages/pi-ai/dist/providers/anthropic.js +7 -4
  266. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  267. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  268. package/packages/pi-ai/dist/providers/openai-completions.js +11 -0
  269. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  270. package/packages/pi-ai/src/providers/amazon-bedrock.ts +13 -1
  271. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +32 -0
  272. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +55 -1
  273. package/packages/pi-ai/src/providers/anthropic-shared.ts +14 -3
  274. package/packages/pi-ai/src/providers/anthropic.ts +8 -4
  275. package/packages/pi-ai/src/providers/openai-completions.ts +14 -0
  276. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts +2 -0
  277. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts.map +1 -0
  278. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js +61 -0
  279. package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js.map +1 -0
  280. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/agent-session.js +2 -1
  282. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
  284. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/auth-storage.js +27 -0
  286. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +85 -0
  288. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts +2 -0
  290. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts.map +1 -0
  291. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +388 -0
  292. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -0
  293. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
  294. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  296. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts +2 -0
  297. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts.map +1 -0
  298. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js +64 -0
  299. package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js.map +1 -0
  300. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  301. package/packages/pi-coding-agent/dist/core/model-resolver.js +22 -18
  302. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts +8 -0
  304. package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts.map +1 -0
  305. package/packages/pi-coding-agent/dist/core/model-resolver.test.js +75 -0
  306. package/packages/pi-coding-agent/dist/core/model-resolver.test.js.map +1 -0
  307. package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
  308. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  309. package/packages/pi-coding-agent/dist/core/sdk.js +38 -5
  310. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  311. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
  312. package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
  313. package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
  314. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
  315. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  316. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/index.js +1 -1
  318. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
  320. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
  321. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
  322. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
  323. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +19 -2
  324. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  325. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +50 -1
  326. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts +1 -0
  328. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  329. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js +1 -0
  330. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
  332. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  333. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
  334. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  335. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  336. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
  337. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  338. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
  339. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  340. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +43 -0
  341. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  343. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +175 -25
  344. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  345. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
  346. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
  347. package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  349. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  350. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  351. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
  352. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +62 -5
  354. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +4 -2
  356. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  357. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
  358. package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  359. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -0
  360. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  361. package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
  362. package/packages/pi-coding-agent/package.json +1 -1
  363. package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
  364. package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
  365. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
  366. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
  367. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +468 -0
  368. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
  369. package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
  370. package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
  371. package/packages/pi-coding-agent/src/core/model-resolver.ts +22 -18
  372. package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
  373. package/packages/pi-coding-agent/src/core/sdk.ts +45 -9
  374. package/packages/pi-coding-agent/src/index.ts +1 -0
  375. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
  376. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +58 -2
  377. package/packages/pi-coding-agent/src/modes/interactive/components/extension-input.ts +2 -0
  378. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
  379. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
  380. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +47 -0
  381. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +205 -31
  382. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
  383. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
  384. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +70 -5
  385. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
  386. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +1 -1
  387. package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +1 -0
  388. package/packages/pi-tui/dist/components/__tests__/input.test.js +9 -0
  389. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  390. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts +2 -0
  391. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts.map +1 -0
  392. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +66 -0
  393. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -0
  394. package/packages/pi-tui/dist/components/input.d.ts +2 -0
  395. package/packages/pi-tui/dist/components/input.d.ts.map +1 -1
  396. package/packages/pi-tui/dist/components/input.js +7 -4
  397. package/packages/pi-tui/dist/components/input.js.map +1 -1
  398. package/packages/pi-tui/dist/components/markdown.d.ts +3 -0
  399. package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -1
  400. package/packages/pi-tui/dist/components/markdown.js +17 -1
  401. package/packages/pi-tui/dist/components/markdown.js.map +1 -1
  402. package/packages/pi-tui/src/components/__tests__/input.test.ts +11 -0
  403. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +75 -0
  404. package/packages/pi-tui/src/components/input.ts +7 -4
  405. package/packages/pi-tui/src/components/markdown.ts +22 -1
  406. package/pkg/package.json +1 -1
  407. package/src/resources/GSD-WORKFLOW.md +1 -1
  408. package/src/resources/agents/debugger.md +58 -0
  409. package/src/resources/agents/doc-writer.md +43 -0
  410. package/src/resources/agents/git-ops.md +56 -0
  411. package/src/resources/agents/javascript-pro.md +46 -271
  412. package/src/resources/agents/planner.md +55 -0
  413. package/src/resources/agents/refactorer.md +47 -0
  414. package/src/resources/agents/reviewer.md +48 -0
  415. package/src/resources/agents/security.md +59 -0
  416. package/src/resources/agents/tester.md +50 -0
  417. package/src/resources/agents/typescript-pro.md +41 -235
  418. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +288 -39
  419. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +330 -2
  420. package/src/resources/extensions/get-secrets-from-user.ts +24 -1
  421. package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
  422. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  423. package/src/resources/extensions/gsd/auto/loop.ts +45 -1
  424. package/src/resources/extensions/gsd/auto/phases.ts +6 -0
  425. package/src/resources/extensions/gsd/auto/session.ts +11 -0
  426. package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
  427. package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
  428. package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
  429. package/src/resources/extensions/gsd/auto-start.ts +44 -20
  430. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  431. package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
  432. package/src/resources/extensions/gsd/auto.ts +72 -0
  433. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
  434. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +6 -0
  435. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +79 -60
  436. package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
  437. package/src/resources/extensions/gsd/commands/context.ts +16 -5
  438. package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
  439. package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
  440. package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
  441. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
  442. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
  443. package/src/resources/extensions/gsd/custom-workflow-engine.ts +19 -14
  444. package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
  445. package/src/resources/extensions/gsd/dispatch-guard.ts +18 -1
  446. package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
  447. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  448. package/src/resources/extensions/gsd/file-lock.ts +59 -0
  449. package/src/resources/extensions/gsd/forensics.ts +23 -7
  450. package/src/resources/extensions/gsd/gate-registry.ts +251 -0
  451. package/src/resources/extensions/gsd/gsd-db.ts +51 -0
  452. package/src/resources/extensions/gsd/guided-flow.ts +17 -19
  453. package/src/resources/extensions/gsd/init-wizard.ts +3 -13
  454. package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
  455. package/src/resources/extensions/gsd/metrics.ts +12 -1
  456. package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
  457. package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
  458. package/src/resources/extensions/gsd/notification-overlay.ts +47 -14
  459. package/src/resources/extensions/gsd/notification-store.ts +54 -5
  460. package/src/resources/extensions/gsd/notification-widget.ts +5 -14
  461. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
  462. package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
  463. package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
  464. package/src/resources/extensions/gsd/prompts/complete-slice.md +5 -3
  465. package/src/resources/extensions/gsd/prompts/discuss.md +33 -13
  466. package/src/resources/extensions/gsd/prompts/execute-task.md +22 -19
  467. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  468. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
  469. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  470. package/src/resources/extensions/gsd/prompts/queue.md +3 -2
  471. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  472. package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
  473. package/src/resources/extensions/gsd/session-model-override.ts +36 -0
  474. package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
  475. package/src/resources/extensions/gsd/state.ts +285 -344
  476. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +25 -9
  477. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
  478. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
  479. package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
  480. package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
  481. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +436 -0
  482. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +9 -0
  483. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  484. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
  485. package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
  486. package/src/resources/extensions/gsd/tests/file-lock.test.ts +103 -0
  487. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
  488. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +31 -0
  489. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
  490. package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
  491. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
  492. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
  493. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
  494. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
  495. package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
  496. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
  497. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
  498. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
  499. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
  500. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
  501. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
  502. package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
  503. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
  504. package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +63 -5
  505. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +45 -0
  506. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
  507. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
  508. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
  509. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
  510. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +76 -0
  511. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +155 -1
  512. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +22 -0
  513. package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
  514. package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
  515. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +64 -26
  516. package/src/resources/extensions/gsd/types.ts +26 -0
  517. package/src/resources/extensions/gsd/workflow-events.ts +34 -25
  518. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +76 -0
  519. package/src/resources/extensions/gsd/workflow-mcp.ts +1 -1
  520. package/src/resources/extensions/ollama/index.ts +13 -3
  521. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
  522. package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
  523. package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
  524. package/src/resources/extensions/subagent/agents.ts +10 -0
  525. package/src/resources/extensions/subagent/index.ts +18 -0
  526. package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
  527. package/src/resources/skills/create-skill/SKILL.md +2 -0
  528. package/dist/web/standalone/.next/static/chunks/2826.821e01b07d92e948.js +0 -9
  529. package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
  530. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
  531. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
  532. /package/dist/web/standalone/.next/static/{9pw9EXtXjdM7EFrCXUEPf → OI4n_CKC-lM8IQbvGJ_tK}/_buildManifest.js +0 -0
  533. /package/dist/web/standalone/.next/static/{9pw9EXtXjdM7EFrCXUEPf → OI4n_CKC-lM8IQbvGJ_tK}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Tests for model config isolation between concurrent instances (#650, #1065)
3
- * and GSD preferences override of settings.json defaults (#3517).
3
+ * and session-scoped model precedence behavior.
4
4
  */
5
5
 
6
6
  import { describe, it, beforeEach, afterEach } from "node:test";
@@ -157,75 +157,60 @@ describe("session model recovery on error (#1065)", () => {
157
157
  });
158
158
  });
159
159
 
160
- // ─── GSD Preferences override settings.json (#3517) ─────────────────────────
160
+ // ─── Manual session model override precedence ───────────────────────────────
161
161
 
162
- describe("GSD preferences override settings.json for session model (#3517)", () => {
163
- it("preferredModel takes priority over ctx.model when both are available", () => {
164
- // Simulates auto-start.ts logic: preferredModel ?? ctx.model snapshot
165
- const preferredModel = { provider: "openai-codex", id: "gpt-5.4" };
166
- const ctxModel = { provider: "claude-code", id: "claude-sonnet-4-6" };
162
+ describe("manual session model override precedence", () => {
163
+ it("manual session override takes priority over preferences and ctx.model", () => {
164
+ const manualSessionOverride = { provider: "openai-codex", id: "gpt-5.4" };
165
+ const preferredModel = { provider: "anthropic", id: "claude-sonnet-4-6" };
166
+ const ctxModel = { provider: "claude-code", id: "claude-opus-4-6" };
167
167
 
168
- const startModelSnapshot = preferredModel
168
+ const startModelSnapshot = manualSessionOverride
169
+ ?? preferredModel
169
170
  ?? { provider: ctxModel.provider, id: ctxModel.id };
170
171
 
171
- assert.equal(startModelSnapshot.provider, "openai-codex",
172
- "preferredModel provider should win over ctx.model");
173
- assert.equal(startModelSnapshot.id, "gpt-5.4",
174
- "preferredModel id should win over ctx.model");
172
+ assert.equal(startModelSnapshot.provider, "openai-codex");
173
+ assert.equal(startModelSnapshot.id, "gpt-5.4");
174
+ });
175
+
176
+ it("falls back to preferences when no manual override is active", () => {
177
+ const manualSessionOverride: { provider: string; id: string } | undefined = undefined;
178
+ const preferredModel = { provider: "anthropic", id: "claude-sonnet-4-6" };
179
+ const ctxModel = { provider: "claude-code", id: "claude-opus-4-6" };
180
+
181
+ const startModelSnapshot = manualSessionOverride
182
+ ?? preferredModel
183
+ ?? { provider: ctxModel.provider, id: ctxModel.id };
184
+
185
+ assert.equal(startModelSnapshot.provider, "anthropic");
186
+ assert.equal(startModelSnapshot.id, "claude-sonnet-4-6");
175
187
  });
176
188
 
177
- it("falls back to ctx.model when no GSD preferences are configured", () => {
189
+ it("falls back to ctx.model when no manual override or preferences are configured", () => {
190
+ const manualSessionOverride: { provider: string; id: string } | undefined = undefined;
178
191
  const preferredModel: { provider: string; id: string } | undefined = undefined;
179
- const ctxModel = { provider: "claude-code", id: "claude-sonnet-4-6" };
192
+ const ctxModel = { provider: "claude-code", id: "claude-opus-4-6" };
180
193
 
181
- const startModelSnapshot = preferredModel
194
+ const startModelSnapshot = manualSessionOverride
195
+ ?? preferredModel
182
196
  ?? { provider: ctxModel.provider, id: ctxModel.id };
183
197
 
184
- assert.equal(startModelSnapshot.provider, "claude-code",
185
- "should fall back to ctx.model provider when no preferences");
186
- assert.equal(startModelSnapshot.id, "claude-sonnet-4-6",
187
- "should fall back to ctx.model id when no preferences");
198
+ assert.equal(startModelSnapshot.provider, "claude-code");
199
+ assert.equal(startModelSnapshot.id, "claude-opus-4-6");
188
200
  });
189
201
 
190
- it("handles null ctx.model with no preferences gracefully", () => {
202
+ it("handles null ctx.model with no override or preferences gracefully", () => {
203
+ const manualSessionOverride: { provider: string; id: string } | undefined = undefined;
191
204
  const preferredModel: { provider: string; id: string } | undefined = undefined;
192
205
  // Use a function to prevent TS from narrowing to `never` in the ternary
193
206
  function getCtxModel(): { provider: string; id: string } | null { return null; }
194
207
  const ctxModel = getCtxModel();
195
208
 
196
- const startModelSnapshot = preferredModel
209
+ const startModelSnapshot = manualSessionOverride
210
+ ?? preferredModel
197
211
  ?? (ctxModel ? { provider: ctxModel.provider, id: ctxModel.id } : null);
198
212
 
199
213
  assert.equal(startModelSnapshot, null,
200
- "should be null when neither preferences nor ctx.model exist");
201
- });
202
-
203
- it("bare model ID uses session provider when available", () => {
204
- // Simulates: PREFERENCES.md has "gpt-5.4" (no provider), session is openai-codex
205
- const preferredModel = { provider: "openai-codex", id: "gpt-5.4" }; // from resolveDefaultSessionModel("openai-codex")
206
- const ctxModel = { provider: "openai-codex", id: "claude-sonnet-4-6" };
207
-
208
- const startModelSnapshot = preferredModel
209
- ?? { provider: ctxModel.provider, id: ctxModel.id };
210
-
211
- assert.equal(startModelSnapshot.provider, "openai-codex");
212
- assert.equal(startModelSnapshot.id, "gpt-5.4",
213
- "bare model ID from preferences should still override ctx.model");
214
- });
215
-
216
- it("stale settings.json does not leak when preferences are set", () => {
217
- // Scenario: settings.json has claude-code, PREFERENCES.md has openai-codex
218
- const settingsJsonDefault = { provider: "claude-code", id: "claude-sonnet-4-6" };
219
- const preferencesModel = { provider: "openai-codex", id: "gpt-5.4" };
220
-
221
- // auto-start.ts captures preferredModel first, which preempts settingsJsonDefault
222
- const startModelSnapshot = preferencesModel ?? settingsJsonDefault;
223
-
224
- assert.equal(startModelSnapshot.provider, "openai-codex",
225
- "PREFERENCES.md must override stale settings.json provider");
226
- assert.equal(startModelSnapshot.id, "gpt-5.4",
227
- "PREFERENCES.md must override stale settings.json model");
228
- assert.notEqual(startModelSnapshot.provider, settingsJsonDefault.provider,
229
- "settings.json provider must NOT leak through");
214
+ "should be null when no model source is available");
230
215
  });
231
216
  });
@@ -16,6 +16,7 @@ import {
16
16
  getLineCount,
17
17
  suppressPersistence,
18
18
  unsuppressPersistence,
19
+ onNotificationStoreChange,
19
20
  _resetNotificationStore,
20
21
  } from "../notification-store.js";
21
22
 
@@ -187,6 +188,23 @@ describe("notification-store", () => {
187
188
  assert.ok(!entries.some((e) => e.message === "suppressed"));
188
189
  });
189
190
 
191
+ test("appendNotification suppresses identical messages within the dedup window", (t) => {
192
+ initNotificationStore(tmp);
193
+ let now = 1_000;
194
+ t.mock.method(Date, "now", () => now);
195
+
196
+ appendNotification("same", "warning");
197
+ now += 1_000;
198
+ appendNotification("same", "warning");
199
+ now += 31_000;
200
+ appendNotification("same", "warning");
201
+
202
+ const entries = readNotifications();
203
+ assert.equal(entries.length, 2);
204
+ assert.equal(entries[0].message, "same");
205
+ assert.equal(entries[1].message, "same");
206
+ });
207
+
190
208
  test("suppressPersistence is ref-counted", () => {
191
209
  initNotificationStore(tmp);
192
210
  suppressPersistence();
@@ -279,4 +297,21 @@ describe("notification-store", () => {
279
297
 
280
298
  rmSync(lockPath, { force: true });
281
299
  });
300
+
301
+ test("listeners are notified on append, markAllRead, and clear", () => {
302
+ initNotificationStore(tmp);
303
+ let calls = 0;
304
+ const unsubscribe = onNotificationStoreChange(() => { calls++; });
305
+
306
+ appendNotification("msg1", "info");
307
+ assert.equal(calls, 1, "append should emit one change");
308
+
309
+ markAllRead();
310
+ assert.equal(calls, 2, "markAllRead should emit one change when state changes");
311
+
312
+ clearNotifications();
313
+ assert.equal(calls, 3, "clear should emit one change");
314
+
315
+ unsubscribe();
316
+ });
282
317
  });
@@ -0,0 +1,26 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, mkdirSync, rmSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+
7
+ import { initNotificationStore, appendNotification, _resetNotificationStore } from "../notification-store.js";
8
+ import { buildNotificationWidgetLines } from "../notification-widget.js";
9
+
10
+ test("buildNotificationWidgetLines shows unread count with shortcut pair", () => {
11
+ const tmp = mkdtempSync(join(tmpdir(), "gsd-notification-widget-"));
12
+ try {
13
+ mkdirSync(join(tmp, ".gsd"), { recursive: true });
14
+ _resetNotificationStore();
15
+ initNotificationStore(tmp);
16
+ appendNotification("Need attention", "warning");
17
+
18
+ const lines = buildNotificationWidgetLines();
19
+ assert.equal(lines.length, 1);
20
+ assert.match(lines[0]!, /Notifications:\s+1 unread/);
21
+ assert.match(lines[0]!, /\(.+\/.+\)/);
22
+ } finally {
23
+ _resetNotificationStore();
24
+ rmSync(tmp, { recursive: true, force: true });
25
+ }
26
+ });
@@ -0,0 +1,90 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { mkdirSync, rmSync } from "node:fs";
6
+
7
+ import { handleNotificationsCommand } from "../commands/handlers/notifications-handler.ts";
8
+ import {
9
+ _resetNotificationStore,
10
+ appendNotification,
11
+ initNotificationStore,
12
+ } from "../notification-store.ts";
13
+
14
+ function makeTempDir(prefix: string): string {
15
+ const dir = join(
16
+ tmpdir(),
17
+ `gsd-notifications-handler-test-${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
18
+ );
19
+ mkdirSync(dir, { recursive: true });
20
+ mkdirSync(join(dir, ".gsd"), { recursive: true });
21
+ return dir;
22
+ }
23
+
24
+ function cleanup(dir: string): void {
25
+ try {
26
+ rmSync(dir, { recursive: true, force: true });
27
+ } catch {
28
+ // best-effort
29
+ }
30
+ }
31
+
32
+ test("notifications command falls back to text output when overlay returns undefined", async (t) => {
33
+ const base = makeTempDir("overlay-fallback");
34
+ initNotificationStore(base);
35
+ appendNotification("Build complete", "success");
36
+
37
+ t.after(() => {
38
+ _resetNotificationStore();
39
+ cleanup(base);
40
+ });
41
+
42
+ const notices: Array<{ message: string; level?: string }> = [];
43
+ await handleNotificationsCommand(
44
+ "",
45
+ {
46
+ hasUI: true,
47
+ ui: {
48
+ custom: async () => undefined,
49
+ notify: (message: string, level?: string) => {
50
+ notices.push({ message, level });
51
+ },
52
+ },
53
+ } as any,
54
+ {} as any,
55
+ );
56
+
57
+ assert.equal(notices.length, 1, "text fallback should be emitted when overlay cannot render");
58
+ assert.match(notices[0].message, /Recent notifications:/);
59
+ });
60
+
61
+ test("notifications tail caps inline output and hints to open overlay", async (t) => {
62
+ const base = makeTempDir("tail-cap");
63
+ initNotificationStore(base);
64
+ for (let i = 0; i < 55; i++) {
65
+ appendNotification(`notification-${i + 1}`, "info");
66
+ }
67
+
68
+ t.after(() => {
69
+ _resetNotificationStore();
70
+ cleanup(base);
71
+ });
72
+
73
+ const notices: Array<{ message: string; level?: string }> = [];
74
+ await handleNotificationsCommand(
75
+ "tail 200",
76
+ {
77
+ hasUI: true,
78
+ ui: {
79
+ notify: (message: string, level?: string) => {
80
+ notices.push({ message, level });
81
+ },
82
+ },
83
+ } as any,
84
+ {} as any,
85
+ );
86
+
87
+ assert.equal(notices.length, 1);
88
+ assert.match(notices[0].message, /Last 40 notification\(s\):/);
89
+ assert.match(notices[0].message, /\.\.\. and \d+ more \(open \/gsd notifications to browse all\)/);
90
+ });
@@ -56,6 +56,7 @@ describe("parallel-monitor-overlay", () => {
56
56
  overlay2.handleInput("q");
57
57
  assert.ok(closed, "pressing q should trigger onClose");
58
58
  overlay2.dispose();
59
+
59
60
  });
60
61
 
61
62
  it("ParallelMonitorOverlay clamps scrollOffset during render", async () => {
@@ -69,6 +69,24 @@ test("unparkMilestone updates DB status to 'active' (#2694)", () => {
69
69
  }
70
70
  });
71
71
 
72
+ test("unparkMilestone repairs parked DB state when PARKED.md is missing (#3707)", () => {
73
+ const base = createBase();
74
+ try {
75
+ openDatabase(":memory:");
76
+ insertMilestone({ id: "M001", title: "Test", status: "parked" });
77
+
78
+ const unparked = unparkMilestone(base, "M001");
79
+
80
+ assert.ok(unparked, "unparkMilestone should recover DB-only parked state");
81
+ assert.equal(getMilestone("M001")!.status, "active", "DB status should be repaired to active");
82
+
83
+ closeDatabase();
84
+ } finally {
85
+ closeDatabase();
86
+ rmSync(base, { recursive: true, force: true });
87
+ }
88
+ });
89
+
72
90
  test("park/unpark are safe when DB is not available (#2694 guard)", () => {
73
91
  const base = createBase();
74
92
  try {
@@ -1107,6 +1107,38 @@ describe("checkTaskOrdering false positive regression (#3677)", () => {
1107
1107
  assert.equal(results[0].target, "`later.ts` — needed first");
1108
1108
  assert.ok(results[0].message.includes("sequence violation"));
1109
1109
  });
1110
+
1111
+ test("existing on-disk files do not trigger ordering violations just because a later task modifies them", () => {
1112
+ const tempDir = join(tmpdir(), `pre-exec-ordering-existing-file-${Date.now()}`);
1113
+ const existingFile = "frontend/src/__tests__/ProcurementPage29.test.tsx";
1114
+
1115
+ mkdirSync(join(tempDir, "frontend", "src", "__tests__"), { recursive: true });
1116
+ writeFileSync(join(tempDir, existingFile), "// existing file");
1117
+
1118
+ try {
1119
+ const tasks = [
1120
+ createTask({
1121
+ id: "T01",
1122
+ sequence: 0,
1123
+ files: [],
1124
+ inputs: ["`frontend/src/__tests__/ProcurementPage29.test.tsx` — contains matchMedia stub to remove"],
1125
+ expected_output: [],
1126
+ }),
1127
+ createTask({
1128
+ id: "T03",
1129
+ sequence: 2,
1130
+ files: [],
1131
+ inputs: [],
1132
+ expected_output: ["frontend/src/__tests__/ProcurementPage29.test.tsx"],
1133
+ }),
1134
+ ];
1135
+
1136
+ const results = checkTaskOrdering(tasks, tempDir);
1137
+ assert.equal(results.length, 0, "Pre-existing files should not be treated as created by later tasks");
1138
+ } finally {
1139
+ rmSync(tempDir, { recursive: true, force: true });
1140
+ }
1141
+ });
1110
1142
  });
1111
1143
 
1112
1144
  // ─── checkFilePathConsistency additional edge cases ──────────────────────────
@@ -1175,6 +1207,23 @@ describe("checkFilePathConsistency additional edge cases", () => {
1175
1207
  assert.equal(results![0].blocking, true);
1176
1208
  });
1177
1209
 
1210
+ test("multi-word prose inputs are ignored by path consistency checks", () => {
1211
+ const tasks = [
1212
+ createTask({
1213
+ id: "T01",
1214
+ files: [],
1215
+ inputs: [
1216
+ "Current WIZARD_PRODUCTS enum",
1217
+ "Existing test patterns in wizard.test.ts",
1218
+ ],
1219
+ expected_output: [],
1220
+ }),
1221
+ ];
1222
+
1223
+ const results = checkFilePathConsistency(tasks, "/tmp");
1224
+ assert.equal(results.length, 0, "Prose planning hints should not be treated as missing file paths");
1225
+ });
1226
+
1178
1227
  test("empty inputs array produces no results", () => {
1179
1228
  // A task with no inputs and only files should produce zero results from
1180
1229
  // consistency check — files are not checked (#3626).
@@ -42,9 +42,19 @@ test("system prompt references CODEBASE.md and /gsd codebase", () => {
42
42
  assert.match(prompt, /auto-refreshes it when tracked files change/i);
43
43
  });
44
44
 
45
+ test("system prompt hard rules forbid fabricating user responses", () => {
46
+ const prompt = readPrompt("system");
47
+ assert.match(prompt, /never fabricate, simulate, or role-play user responses/i);
48
+ assert.match(prompt, /never generate markers like `?\[User\]`?, `?\[Human\]`?, `?User:`?/i);
49
+ assert.match(prompt, /ask one question round \(1-3 questions\), then stop and wait for the user's actual response/i);
50
+ assert.match(prompt, /ask_user_questions.*only valid structured user input/i);
51
+ });
52
+
45
53
  test("discuss prompt allows implementation questions when they materially matter", () => {
46
54
  const prompt = readPrompt("discuss");
47
55
  assert.match(prompt, /Lead with experience, but ask implementation when it materially matters/i);
56
+ assert.match(prompt, /Never fabricate, simulate, or role-play user responses/i);
57
+ assert.match(prompt, /Ask one question round \(1-3 questions\) per turn, then stop and wait for the user's actual response/i);
48
58
  assert.match(prompt, /one gate, not two/i);
49
59
  assert.doesNotMatch(prompt, /Questions must be about the experience, not the implementation/i);
50
60
  });
@@ -56,6 +66,8 @@ test("guided discussion prompts avoid wrap-up prompts after every round", () =>
56
66
  assert.match(slicePrompt, /Do \*\*not\*\* ask a meta "ready to wrap up\?" question after every round/i);
57
67
  assert.doesNotMatch(milestonePrompt, /I think I have a solid picture of this milestone\. Ready to wrap up/i);
58
68
  assert.doesNotMatch(slicePrompt, /I think I have a solid picture of this slice\. Ready to wrap up/i);
69
+ assert.match(milestonePrompt, /Never fabricate or simulate user input/i);
70
+ assert.match(slicePrompt, /Never fabricate or simulate user input/i);
59
71
  });
60
72
 
61
73
  test("guided milestone discussion scopes depth verification to the milestone id", () => {
@@ -64,6 +76,13 @@ test("guided milestone discussion scopes depth verification to the milestone id"
64
76
  assert.doesNotMatch(prompt, /depth_verification_confirm" — this enables the write-gate downstream/i, "legacy global depth gate wording should be gone");
65
77
  });
66
78
 
79
+ test("queue prompt requires waiting for user response between rounds", () => {
80
+ const prompt = readPrompt("queue");
81
+ assert.match(prompt, /Never fabricate or simulate user input during this discussion/i);
82
+ assert.match(prompt, /Ask 1-3 questions per round, then wait for the user's response before asking the next round\./i);
83
+ assert.doesNotMatch(prompt, /treat that as permission to continue/i);
84
+ });
85
+
67
86
  test("guided-resume-task prompt preserves recovery state until work is superseded", () => {
68
87
  const prompt = readPrompt("guided-resume-task");
69
88
  assert.match(prompt, /Do \*\*not\*\* delete the continue file immediately/i);
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Prompt-system gate coverage tests.
3
+ *
4
+ * These tests pin the invariants the plan file documents:
5
+ * 1. Every pending slice-scoped gate is routed to exactly one owner turn.
6
+ * Q8 (owned by complete-slice) MUST NOT leak into gate-evaluate and
7
+ * get silently dropped the way it used to before the registry landed.
8
+ * 2. getPendingGatesForTurn filters by the registry's owner turn, not
9
+ * just the DB scope column.
10
+ * 3. Output validators recognize artifacts that contain the required
11
+ * gate section headings, and flag ones that don't.
12
+ * 4. Prompt output produced by the validators reflects MV01-MV04.
13
+ *
14
+ * They also assert the VALIDATION.md renderer still produces headings
15
+ * matching the registry's promptSection strings, so future renderer
16
+ * edits that drift from the registry fail the suite loudly.
17
+ */
18
+
19
+ import { describe, test, beforeEach, afterEach } from "node:test";
20
+ import assert from "node:assert/strict";
21
+ import { mkdtempSync, rmSync } from "node:fs";
22
+ import { join } from "node:path";
23
+ import { tmpdir } from "node:os";
24
+
25
+ import {
26
+ openDatabase,
27
+ closeDatabase,
28
+ insertMilestone,
29
+ insertSlice,
30
+ insertTask,
31
+ insertGateRow,
32
+ getPendingGates,
33
+ getPendingGatesForTurn,
34
+ } from "../gsd-db.ts";
35
+ import {
36
+ GATE_REGISTRY,
37
+ getGatesForTurn,
38
+ type OwnerTurn,
39
+ } from "../gate-registry.ts";
40
+ import {
41
+ validateSliceSummaryOutput,
42
+ validateTaskSummaryOutput,
43
+ validateMilestoneValidationOutput,
44
+ validateGateSections,
45
+ } from "../prompt-validation.ts";
46
+
47
+ function setupTestDb(): string {
48
+ const tmpDir = mkdtempSync(join(tmpdir(), "prompt-gate-coverage-"));
49
+ const dbPath = join(tmpDir, "gsd.db");
50
+ openDatabase(dbPath);
51
+ insertMilestone({ id: "M001", title: "Test", status: "active" });
52
+ insertSlice({
53
+ milestoneId: "M001",
54
+ id: "S01",
55
+ title: "Test Slice",
56
+ status: "pending",
57
+ risk: "medium",
58
+ depends: [],
59
+ });
60
+ insertTask({
61
+ id: "T01",
62
+ sliceId: "S01",
63
+ milestoneId: "M001",
64
+ title: "Test Task",
65
+ status: "pending",
66
+ });
67
+ return tmpDir;
68
+ }
69
+
70
+ describe("getPendingGatesForTurn routes by owner turn, not scope column", () => {
71
+ let tmpDir: string;
72
+ beforeEach(() => {
73
+ tmpDir = setupTestDb();
74
+ });
75
+ afterEach(() => {
76
+ closeDatabase();
77
+ rmSync(tmpDir, { recursive: true, force: true });
78
+ });
79
+
80
+ test("Q8 stored as scope:'slice' is owned by complete-slice, not gate-evaluate", () => {
81
+ // Seed the three slice-scoped gates plan-slice writes today.
82
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
83
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
84
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q8", scope: "slice" });
85
+
86
+ // getPendingGates(..., "slice") returns all three (unchanged).
87
+ const allSlicePending = getPendingGates("M001", "S01", "slice");
88
+ assert.equal(allSlicePending.length, 3);
89
+
90
+ // But the turn-aware helper routes them correctly.
91
+ const gateEval = getPendingGatesForTurn("M001", "S01", "gate-evaluate");
92
+ assert.deepEqual(gateEval.map((g) => g.gate_id).sort(), ["Q3", "Q4"]);
93
+
94
+ const completeSlice = getPendingGatesForTurn("M001", "S01", "complete-slice");
95
+ assert.deepEqual(completeSlice.map((g) => g.gate_id), ["Q8"]);
96
+ });
97
+
98
+ test("task-scoped gates are scoped to the requested task id", () => {
99
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q5", scope: "task", taskId: "T01" });
100
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q6", scope: "task", taskId: "T01" });
101
+ insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q5", scope: "task", taskId: "T02" });
102
+
103
+ const t1 = getPendingGatesForTurn("M001", "S01", "execute-task", "T01");
104
+ assert.equal(t1.length, 2);
105
+ assert.ok(t1.every((g) => g.gate_id === "Q5" || g.gate_id === "Q6"));
106
+
107
+ const t2 = getPendingGatesForTurn("M001", "S01", "execute-task", "T02");
108
+ assert.equal(t2.length, 1);
109
+ assert.equal(t2[0].gate_id, "Q5");
110
+ });
111
+ });
112
+
113
+ describe("per-turn output validators", () => {
114
+ test("validateSliceSummaryOutput flags missing Operational Readiness", () => {
115
+ const md = `# S01: Test Slice\n\n## What Happened\nstuff\n\n## Verification\nstuff\n`;
116
+ const result = validateSliceSummaryOutput(md);
117
+ assert.equal(result.valid, false);
118
+ assert.ok(result.missing.some((m) => m.includes("Q8")));
119
+ assert.ok(result.missing.some((m) => m.includes("Operational Readiness")));
120
+ });
121
+
122
+ test("validateSliceSummaryOutput passes when Operational Readiness heading is present", () => {
123
+ const md = `# S01\n\n## Operational Readiness\n- Health: /health\n- Failure: alert\n`;
124
+ const result = validateSliceSummaryOutput(md);
125
+ assert.equal(result.valid, true);
126
+ assert.equal(result.missing.length, 0);
127
+ });
128
+
129
+ test("validateMilestoneValidationOutput requires all four MV headings", () => {
130
+ // Missing Requirement Coverage.
131
+ const md = [
132
+ "# Milestone Validation: M001",
133
+ "## Success Criteria Checklist",
134
+ "ok",
135
+ "## Slice Delivery Audit",
136
+ "ok",
137
+ "## Cross-Slice Integration",
138
+ "ok",
139
+ ].join("\n\n");
140
+ const result = validateMilestoneValidationOutput(md);
141
+ assert.equal(result.valid, false);
142
+ assert.ok(result.missing.some((m) => m.includes("MV04")));
143
+ });
144
+
145
+ test("validateMilestoneValidationOutput passes for a complete VALIDATION.md", () => {
146
+ const md = [
147
+ "# Milestone Validation: M001",
148
+ "## Success Criteria Checklist",
149
+ "ok",
150
+ "## Slice Delivery Audit",
151
+ "ok",
152
+ "## Cross-Slice Integration",
153
+ "ok",
154
+ "## Requirement Coverage",
155
+ "ok",
156
+ ].join("\n\n");
157
+ const result = validateMilestoneValidationOutput(md);
158
+ assert.equal(result.valid, true, `unexpected missing: ${result.missing.join(", ")}`);
159
+ });
160
+
161
+ test("validateTaskSummaryOutput flags missing task-gate sections", () => {
162
+ const md = `# T01\n\n## What Happened\nstuff\n\n## Verification\nstuff\n`;
163
+ const result = validateTaskSummaryOutput(md);
164
+ assert.equal(result.valid, false);
165
+ const idsInMissing = result.missing.join(" ");
166
+ assert.ok(idsInMissing.includes("Q5"));
167
+ assert.ok(idsInMissing.includes("Q6"));
168
+ assert.ok(idsInMissing.includes("Q7"));
169
+ });
170
+
171
+ test("validateGateSections returns empty missing when gate bucket is empty", () => {
172
+ // Build a phoney owner turn that owns nothing (simulate by validating
173
+ // against a real turn against an artifact containing every section).
174
+ const fullMd = getGatesForTurn("validate-milestone")
175
+ .map((g) => `## ${g.promptSection}\n\nstuff`)
176
+ .join("\n\n");
177
+ const result = validateGateSections(fullMd, "validate-milestone");
178
+ assert.equal(result.valid, true);
179
+ });
180
+ });
181
+
182
+ describe("registry / renderer parity", () => {
183
+ test("MV promptSections match the validate-milestone renderer H2 headings", () => {
184
+ // Mirror the string literals from tools/validate-milestone.ts
185
+ // renderValidationMarkdown() so a rename there flips this test red.
186
+ const expectedHeadings = [
187
+ "Success Criteria Checklist",
188
+ "Slice Delivery Audit",
189
+ "Cross-Slice Integration",
190
+ "Requirement Coverage",
191
+ ];
192
+ const registryHeadings = getGatesForTurn("validate-milestone").map((g) => g.promptSection);
193
+ assert.deepEqual(registryHeadings.sort(), [...expectedHeadings].sort());
194
+ });
195
+
196
+ test("Q8 promptSection matches the complete-slice renderer H2 heading", () => {
197
+ // Mirror the slice-summary H2 introduced in tools/complete-slice.ts.
198
+ assert.equal(GATE_REGISTRY.Q8.promptSection, "Operational Readiness");
199
+ });
200
+
201
+ test("registry owner turns cover every turn gate-registry.ts declares", () => {
202
+ const ownerTurns = new Set<OwnerTurn>(Object.values(GATE_REGISTRY).map((g) => g.ownerTurn));
203
+ assert.ok(ownerTurns.has("gate-evaluate"));
204
+ assert.ok(ownerTurns.has("execute-task"));
205
+ assert.ok(ownerTurns.has("complete-slice"));
206
+ assert.ok(ownerTurns.has("validate-milestone"));
207
+ });
208
+ });
@@ -101,6 +101,13 @@ test("classifyError detects quota exceeded as permanent", () => {
101
101
  assert.ok(!isTransient(result));
102
102
  });
103
103
 
104
+ test("classifyError treats plain 'Connection error.' as transient connection failure (#3594)", () => {
105
+ const result = classifyError("Connection error.");
106
+ assert.ok(isTransient(result));
107
+ assert.equal(result.kind, "connection");
108
+ assert.ok("retryAfterMs" in result && result.retryAfterMs === 15_000);
109
+ });
110
+
104
111
  test("classifyError treats unknown error as not transient", () => {
105
112
  const result = classifyError("something went wrong");
106
113
  assert.ok(!isTransient(result));