gsd-pi 2.64.0-dev.f8aad9b → 2.65.0-dev.16e10d7

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 (473) hide show
  1. package/dist/headless.js +3 -1
  2. package/dist/mcp-server.js +6 -2
  3. package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +22 -7
  4. package/dist/resources/extensions/bg-shell/process-manager.js +6 -1
  5. package/dist/resources/extensions/browser-tools/capture.js +20 -1
  6. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +13 -2
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +94 -8
  9. package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
  10. package/dist/resources/extensions/gsd/auto-post-unit.js +115 -7
  11. package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
  12. package/dist/resources/extensions/gsd/auto-recovery.js +12 -8
  13. package/dist/resources/extensions/gsd/auto-start.js +35 -1
  14. package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
  15. package/dist/resources/extensions/gsd/auto-verification.js +138 -1
  16. package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
  17. package/dist/resources/extensions/gsd/auto.js +2 -2
  18. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
  19. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +34 -13
  20. package/dist/resources/extensions/gsd/bootstrap/notify-interceptor.js +28 -0
  21. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +6 -4
  22. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -1
  23. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +12 -1
  24. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +16 -0
  25. package/dist/resources/extensions/gsd/bootstrap/system-context.js +20 -0
  26. package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
  27. package/dist/resources/extensions/gsd/commands/context.js +8 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +21 -0
  29. package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +104 -0
  30. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  31. package/dist/resources/extensions/gsd/commands-extensions.js +1 -1
  32. package/dist/resources/extensions/gsd/config-overlay.js +312 -0
  33. package/dist/resources/extensions/gsd/detection.js +1 -1
  34. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
  35. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  36. package/dist/resources/extensions/gsd/doctor.js +2 -1
  37. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  38. package/dist/resources/extensions/gsd/gsd-db.js +11 -2
  39. package/dist/resources/extensions/gsd/guided-flow.js +220 -29
  40. package/dist/resources/extensions/gsd/md-importer.js +14 -7
  41. package/dist/resources/extensions/gsd/notification-overlay.js +256 -0
  42. package/dist/resources/extensions/gsd/notification-store.js +273 -0
  43. package/dist/resources/extensions/gsd/notification-widget.js +56 -0
  44. package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
  45. package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
  46. package/dist/resources/extensions/gsd/pre-execution-checks.js +471 -0
  47. package/dist/resources/extensions/gsd/preferences-types.js +7 -0
  48. package/dist/resources/extensions/gsd/preferences-validation.js +78 -1
  49. package/dist/resources/extensions/gsd/preferences.js +13 -2
  50. package/dist/resources/extensions/gsd/preparation.js +1092 -0
  51. package/dist/resources/extensions/gsd/prompt-validation.js +67 -0
  52. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  53. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  54. package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  55. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
  56. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  57. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  58. package/dist/resources/extensions/gsd/prompts/rethink.md +2 -1
  59. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  60. package/dist/resources/extensions/gsd/quick.js +19 -15
  61. package/dist/resources/extensions/gsd/reactive-graph.js +12 -0
  62. package/dist/resources/extensions/gsd/roadmap-slices.js +24 -5
  63. package/dist/resources/extensions/gsd/safety/content-validator.js +3 -3
  64. package/dist/resources/extensions/gsd/session-lock.js +23 -1
  65. package/dist/resources/extensions/gsd/state.js +100 -12
  66. package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  67. package/dist/resources/extensions/gsd/tools/complete-slice.js +12 -3
  68. package/dist/resources/extensions/gsd/tools/complete-task.js +16 -4
  69. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -5
  70. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +5 -2
  71. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +119 -0
  72. package/dist/resources/extensions/gsd/tools/reopen-slice.js +30 -0
  73. package/dist/resources/extensions/gsd/tools/reopen-task.js +18 -0
  74. package/dist/resources/extensions/gsd/triage-resolution.js +25 -9
  75. package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
  76. package/dist/resources/extensions/gsd/workflow-logger.js +8 -0
  77. package/dist/resources/extensions/gsd/workflow-projections.js +4 -7
  78. package/dist/resources/extensions/gsd/workflow-reconcile.js +2 -4
  79. package/dist/resources/extensions/gsd/workflow-templates.js +11 -2
  80. package/dist/resources/extensions/gsd/worktree-manager.js +5 -2
  81. package/dist/resources/extensions/gsd/worktree.js +9 -0
  82. package/dist/resources/extensions/shared/interview-ui.js +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
  85. package/dist/web/standalone/.next/build-manifest.json +3 -3
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  88. package/dist/web/standalone/.next/routes-manifest.json +6 -0
  89. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  90. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/api/notifications/route.js +3 -0
  106. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -0
  107. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -0
  108. package/dist/web/standalone/.next/server/app/index.html +1 -1
  109. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -17
  116. package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
  117. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  120. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  121. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  122. package/dist/web/standalone/.next/static/Z3TgDP0c7kG9j8CVQVGcl/_buildManifest.js +1 -0
  123. package/dist/web/standalone/.next/static/chunks/6502.8874bcae249c02e1.js +9 -0
  124. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-8805a20e15762c3c.js +1 -0
  125. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-8805a20e15762c3c.js +1 -0
  126. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-8805a20e15762c3c.js +1 -0
  127. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-8805a20e15762c3c.js +1 -0
  128. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-8805a20e15762c3c.js +1 -0
  129. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-8805a20e15762c3c.js +1 -0
  130. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-8805a20e15762c3c.js +1 -0
  131. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-8805a20e15762c3c.js +1 -0
  132. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-8805a20e15762c3c.js +1 -0
  133. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-8805a20e15762c3c.js +1 -0
  134. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-8805a20e15762c3c.js +1 -0
  135. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-8805a20e15762c3c.js +1 -0
  136. package/dist/web/standalone/.next/static/chunks/app/api/files/route-8805a20e15762c3c.js +1 -0
  137. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-8805a20e15762c3c.js +1 -0
  138. package/dist/web/standalone/.next/static/chunks/app/api/git/route-8805a20e15762c3c.js +1 -0
  139. package/dist/web/standalone/.next/static/chunks/app/api/history/route-8805a20e15762c3c.js +1 -0
  140. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-8805a20e15762c3c.js +1 -0
  141. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-8805a20e15762c3c.js +1 -0
  142. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-8805a20e15762c3c.js +1 -0
  143. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-8805a20e15762c3c.js +1 -0
  144. package/dist/web/standalone/.next/static/chunks/app/api/notifications/route-8805a20e15762c3c.js +1 -0
  145. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-8805a20e15762c3c.js +1 -0
  146. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-8805a20e15762c3c.js +1 -0
  147. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-8805a20e15762c3c.js +1 -0
  148. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-8805a20e15762c3c.js +1 -0
  149. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-8805a20e15762c3c.js +1 -0
  150. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-8805a20e15762c3c.js +1 -0
  151. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-8805a20e15762c3c.js +1 -0
  152. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-8805a20e15762c3c.js +1 -0
  153. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-8805a20e15762c3c.js +1 -0
  154. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-8805a20e15762c3c.js +1 -0
  155. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-8805a20e15762c3c.js +1 -0
  156. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-8805a20e15762c3c.js +1 -0
  157. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-8805a20e15762c3c.js +1 -0
  158. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-8805a20e15762c3c.js +1 -0
  159. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-8805a20e15762c3c.js +1 -0
  160. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-8805a20e15762c3c.js +1 -0
  161. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-8805a20e15762c3c.js +1 -0
  162. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-8805a20e15762c3c.js +1 -0
  163. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-8805a20e15762c3c.js +1 -0
  164. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-8805a20e15762c3c.js +1 -0
  165. package/dist/web/standalone/.next/static/chunks/app/api/update/route-8805a20e15762c3c.js +1 -0
  166. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-8805a20e15762c3c.js +1 -0
  167. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-8805a20e15762c3c.js +1 -0
  168. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-8805a20e15762c3c.js +1 -0
  169. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-8805a20e15762c3c.js +1 -0
  170. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8805a20e15762c3c.js +1 -0
  171. package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
  172. package/package.json +1 -1
  173. package/packages/pi-agent-core/dist/agent-loop.js +26 -9
  174. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  175. package/packages/pi-agent-core/src/agent-loop.test.ts +100 -4
  176. package/packages/pi-agent-core/src/agent-loop.ts +43 -12
  177. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts +2 -0
  178. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts.map +1 -0
  179. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +38 -0
  180. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -0
  181. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -0
  183. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts +2 -0
  185. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts.map +1 -0
  186. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +24 -0
  187. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -0
  188. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/resource-loader.js +4 -1
  190. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/core/retry-handler.js +30 -19
  193. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +51 -0
  195. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/sdk.js +9 -9
  197. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  198. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -1
  199. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  200. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +10 -1
  201. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  202. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  203. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  204. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +28 -5
  205. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  206. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +15 -1
  207. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +18 -0
  209. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +6 -0
  211. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +40 -0
  213. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  214. package/packages/pi-coding-agent/package.json +1 -1
  215. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +64 -0
  216. package/packages/pi-coding-agent/src/core/agent-session.ts +10 -0
  217. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +42 -0
  218. package/packages/pi-coding-agent/src/core/resource-loader.ts +5 -1
  219. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +80 -0
  220. package/packages/pi-coding-agent/src/core/retry-handler.ts +37 -25
  221. package/packages/pi-coding-agent/src/core/sdk.ts +9 -9
  222. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +10 -0
  223. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +29 -4
  224. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +27 -0
  225. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +16 -1
  226. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +38 -0
  227. package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts +2 -0
  228. package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts.map +1 -0
  229. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +66 -0
  230. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -0
  231. package/packages/pi-tui/dist/components/image.d.ts +2 -0
  232. package/packages/pi-tui/dist/components/image.d.ts.map +1 -1
  233. package/packages/pi-tui/dist/components/image.js +4 -0
  234. package/packages/pi-tui/dist/components/image.js.map +1 -1
  235. package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
  236. package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
  237. package/packages/pi-tui/dist/components/image.test.js +32 -0
  238. package/packages/pi-tui/dist/components/image.test.js.map +1 -0
  239. package/packages/pi-tui/dist/components/loader.d.ts +4 -2
  240. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  241. package/packages/pi-tui/dist/components/loader.js +27 -9
  242. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  243. package/packages/pi-tui/dist/components/text.d.ts.map +1 -1
  244. package/packages/pi-tui/dist/components/text.js +2 -0
  245. package/packages/pi-tui/dist/components/text.js.map +1 -1
  246. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
  247. package/packages/pi-tui/dist/overlay-layout.js +12 -1
  248. package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
  249. package/packages/pi-tui/dist/tui.d.ts +4 -0
  250. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  251. package/packages/pi-tui/dist/tui.js +35 -0
  252. package/packages/pi-tui/dist/tui.js.map +1 -1
  253. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +82 -0
  254. package/packages/pi-tui/src/components/image.test.ts +36 -0
  255. package/packages/pi-tui/src/components/image.ts +5 -0
  256. package/packages/pi-tui/src/components/loader.ts +27 -10
  257. package/packages/pi-tui/src/components/text.ts +1 -0
  258. package/packages/pi-tui/src/overlay-layout.ts +13 -1
  259. package/packages/pi-tui/src/tui.ts +34 -0
  260. package/pkg/package.json +1 -1
  261. package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +19 -7
  262. package/src/resources/extensions/bg-shell/process-manager.ts +8 -2
  263. package/src/resources/extensions/browser-tools/capture.ts +19 -1
  264. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
  265. package/src/resources/extensions/gsd/auto/run-unit.ts +12 -2
  266. package/src/resources/extensions/gsd/auto-dispatch.ts +105 -8
  267. package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
  268. package/src/resources/extensions/gsd/auto-post-unit.ts +138 -6
  269. package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
  270. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  271. package/src/resources/extensions/gsd/auto-start.ts +38 -0
  272. package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
  273. package/src/resources/extensions/gsd/auto-verification.ts +190 -2
  274. package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
  275. package/src/resources/extensions/gsd/auto.ts +2 -1
  276. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
  277. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +35 -13
  278. package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
  279. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -4
  280. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -1
  281. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +12 -1
  282. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +20 -0
  283. package/src/resources/extensions/gsd/bootstrap/system-context.ts +28 -0
  284. package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
  285. package/src/resources/extensions/gsd/commands/context.ts +7 -1
  286. package/src/resources/extensions/gsd/commands/handlers/core.ts +24 -0
  287. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +140 -0
  288. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  289. package/src/resources/extensions/gsd/commands-extensions.ts +1 -1
  290. package/src/resources/extensions/gsd/config-overlay.ts +331 -0
  291. package/src/resources/extensions/gsd/detection.ts +1 -1
  292. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
  293. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -0
  294. package/src/resources/extensions/gsd/doctor.ts +2 -1
  295. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  296. package/src/resources/extensions/gsd/gsd-db.ts +13 -2
  297. package/src/resources/extensions/gsd/guided-flow.ts +254 -30
  298. package/src/resources/extensions/gsd/md-importer.ts +13 -6
  299. package/src/resources/extensions/gsd/notification-overlay.ts +295 -0
  300. package/src/resources/extensions/gsd/notification-store.ts +293 -0
  301. package/src/resources/extensions/gsd/notification-widget.ts +68 -0
  302. package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
  303. package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
  304. package/src/resources/extensions/gsd/pre-execution-checks.ts +581 -0
  305. package/src/resources/extensions/gsd/preferences-types.ts +53 -0
  306. package/src/resources/extensions/gsd/preferences-validation.ts +78 -1
  307. package/src/resources/extensions/gsd/preferences.ts +13 -2
  308. package/src/resources/extensions/gsd/preparation.ts +1419 -0
  309. package/src/resources/extensions/gsd/prompt-validation.ts +88 -0
  310. package/src/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
  311. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  312. package/src/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
  313. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +4 -1
  314. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
  315. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
  316. package/src/resources/extensions/gsd/prompts/rethink.md +2 -1
  317. package/src/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
  318. package/src/resources/extensions/gsd/quick.ts +20 -15
  319. package/src/resources/extensions/gsd/reactive-graph.ts +18 -0
  320. package/src/resources/extensions/gsd/roadmap-slices.ts +21 -5
  321. package/src/resources/extensions/gsd/safety/content-validator.ts +3 -3
  322. package/src/resources/extensions/gsd/session-lock.ts +17 -1
  323. package/src/resources/extensions/gsd/state.ts +101 -11
  324. package/src/resources/extensions/gsd/templates/context-enhanced.md +138 -0
  325. package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +223 -0
  326. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +33 -2
  327. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +56 -0
  328. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +41 -0
  329. package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +36 -0
  330. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +72 -0
  331. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +54 -0
  332. package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
  333. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
  334. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +36 -0
  335. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +46 -0
  336. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +76 -0
  337. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +33 -0
  338. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +37 -0
  339. package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
  340. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
  341. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -0
  342. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +42 -0
  343. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +38 -0
  344. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +103 -0
  345. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +42 -0
  346. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +5 -3
  347. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  348. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +28 -30
  349. package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
  350. package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +525 -0
  351. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +62 -0
  352. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +48 -0
  353. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +46 -0
  354. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +73 -0
  355. package/src/resources/extensions/gsd/tests/notification-store.test.ts +282 -0
  356. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +77 -0
  357. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +55 -0
  358. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +39 -0
  359. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +312 -0
  360. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -0
  361. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +68 -0
  362. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +1197 -0
  363. package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
  364. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
  365. package/src/resources/extensions/gsd/tests/preparation.test.ts +1211 -0
  366. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +53 -0
  367. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +83 -0
  368. package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +669 -0
  369. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -4
  370. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +85 -0
  371. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -1
  372. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +47 -0
  373. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +107 -0
  374. package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +45 -0
  375. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +63 -0
  376. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +4 -5
  377. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +51 -0
  378. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +56 -0
  379. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +31 -0
  380. package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +39 -0
  381. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +51 -0
  382. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -1
  383. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +36 -0
  384. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
  385. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +13 -0
  386. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +21 -0
  387. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +21 -0
  388. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +6 -7
  389. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +47 -0
  390. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +1 -0
  391. package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
  392. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +65 -0
  393. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +29 -1
  394. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +2 -1
  395. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +163 -0
  396. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +3 -4
  397. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +15 -0
  398. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +89 -0
  399. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +48 -0
  400. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +38 -0
  401. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +16 -0
  402. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -0
  403. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +16 -17
  404. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +13 -9
  405. package/src/resources/extensions/gsd/tests/worktree.test.ts +26 -9
  406. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -0
  407. package/src/resources/extensions/gsd/tools/complete-slice.ts +13 -3
  408. package/src/resources/extensions/gsd/tools/complete-task.ts +16 -4
  409. package/src/resources/extensions/gsd/tools/plan-milestone.ts +11 -9
  410. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +5 -2
  411. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
  412. package/src/resources/extensions/gsd/tools/reopen-slice.ts +27 -0
  413. package/src/resources/extensions/gsd/tools/reopen-task.ts +17 -0
  414. package/src/resources/extensions/gsd/triage-resolution.ts +29 -10
  415. package/src/resources/extensions/gsd/types.ts +4 -0
  416. package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
  417. package/src/resources/extensions/gsd/workflow-logger.ts +13 -0
  418. package/src/resources/extensions/gsd/workflow-projections.ts +4 -6
  419. package/src/resources/extensions/gsd/workflow-reconcile.ts +2 -3
  420. package/src/resources/extensions/gsd/workflow-templates.ts +11 -2
  421. package/src/resources/extensions/gsd/worktree-manager.ts +4 -2
  422. package/src/resources/extensions/gsd/worktree.ts +10 -0
  423. package/src/resources/extensions/shared/interview-ui.ts +1 -1
  424. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +8 -10
  425. package/dist/web/standalone/.next/static/F1mOwzgCW9R8N3Pt1Et87/_buildManifest.js +0 -1
  426. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
  427. package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +0 -1
  428. package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +0 -1
  429. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +0 -1
  430. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  431. package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  432. package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +0 -1
  433. package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +0 -1
  434. package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +0 -1
  435. package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +0 -1
  436. package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +0 -1
  437. package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +0 -1
  438. package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +0 -1
  439. package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +0 -1
  440. package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +0 -1
  441. package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +0 -1
  442. package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +0 -1
  443. package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +0 -1
  444. package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +0 -1
  445. package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +0 -1
  446. package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +0 -1
  447. package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +0 -1
  448. package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +0 -1
  449. package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +0 -1
  450. package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +0 -1
  451. package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +0 -1
  452. package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +0 -1
  453. package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +0 -1
  454. package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +0 -1
  455. package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +0 -1
  456. package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +0 -1
  457. package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +0 -1
  458. package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +0 -1
  459. package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +0 -1
  460. package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +0 -1
  461. package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +0 -1
  462. package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +0 -1
  463. package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +0 -1
  464. package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +0 -1
  465. package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +0 -1
  466. package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +0 -1
  467. package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +0 -1
  468. package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +0 -1
  469. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +0 -1
  470. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +0 -1
  471. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +0 -1
  472. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +0 -1
  473. /package/dist/web/standalone/.next/static/{F1mOwzgCW9R8N3Pt1Et87 → Z3TgDP0c7kG9j8CVQVGcl}/_ssgManifest.js +0 -0
@@ -0,0 +1,76 @@
1
+ // GSD-2 — Regression test for #3616: discuss tool scoping must not leak into subsequent sessions
2
+ // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
3
+
4
+ /**
5
+ * Bug #3616: After a discuss session narrows the active tool set via
6
+ * setActiveTools(), the narrowed list persisted into the next auto-mode
7
+ * session because newSession() did not restore extension tools when cwd
8
+ * was unchanged. This caused gsd_plan_slice and other DB tools to be
9
+ * missing from plan-slice subagent sessions.
10
+ *
11
+ * This test verifies the structural properties that prevent the leak:
12
+ * 1. guided-flow.ts narrows tools ONLY for discuss-* unit types
13
+ * 2. The narrowed set explicitly excludes gsd_plan_slice (a HEAVY_TOOL)
14
+ * 3. agent-session.ts:newSession() has an else-branch that restores
15
+ * all extension tools even when cwd hasn't changed
16
+ */
17
+
18
+ import { describe, test } from "node:test";
19
+ import assert from "node:assert/strict";
20
+ import { readFileSync } from "node:fs";
21
+ import { join, dirname } from "node:path";
22
+ import { fileURLToPath } from "node:url";
23
+
24
+ import { DISCUSS_TOOLS_ALLOWLIST } from "../constants.ts";
25
+
26
+ const __dirname = dirname(fileURLToPath(import.meta.url));
27
+ const guidedFlowSource = readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
28
+
29
+ describe("#3616 — discuss tool scoping must not leak across sessions", () => {
30
+ test("gsd_plan_slice is NOT in DISCUSS_TOOLS_ALLOWLIST", () => {
31
+ assert.ok(
32
+ !DISCUSS_TOOLS_ALLOWLIST.includes("gsd_plan_slice"),
33
+ "gsd_plan_slice should be excluded from discuss scope (it's a heavy planning tool)",
34
+ );
35
+ });
36
+
37
+ test("tool scoping only activates for discuss-* unit types", () => {
38
+ // The guard must be: if (unitType?.startsWith("discuss-"))
39
+ assert.ok(
40
+ guidedFlowSource.includes('unitType?.startsWith("discuss-")'),
41
+ "tool scoping should only trigger for discuss-* unit types",
42
+ );
43
+ });
44
+
45
+ test("discuss tool scoping uses setActiveTools (not setTools) for reversibility", () => {
46
+ // setActiveTools changes the active subset but doesn't remove tools from
47
+ // the registry. newSession()'s _refreshToolRegistry can restore them.
48
+ assert.ok(
49
+ guidedFlowSource.includes("pi.setActiveTools(scopedTools)"),
50
+ "should use pi.setActiveTools to narrow tools (preserving registry)",
51
+ );
52
+ });
53
+
54
+ test("newSession() in agent-session.ts has defense against tool narrowing persistence", () => {
55
+ const agentSessionSource = readFileSync(
56
+ join(process.cwd(), "packages/pi-coding-agent/src/core/agent-session.ts"),
57
+ "utf-8",
58
+ );
59
+ const newSessionStart = agentSessionSource.indexOf("async newSession(options?:");
60
+ assert.ok(newSessionStart >= 0, "should find newSession");
61
+ const body = agentSessionSource.slice(newSessionStart, newSessionStart + 3000);
62
+
63
+ // Both branches (cwd-changed and cwd-unchanged) must include extension tools
64
+ assert.ok(
65
+ body.includes("includeAllExtensionTools: true"),
66
+ "newSession() must include all extension tools in both branches",
67
+ );
68
+
69
+ // Count occurrences — should be at least 2 (one per branch)
70
+ const matches = body.match(/includeAllExtensionTools:\s*true/g);
71
+ assert.ok(
72
+ matches && matches.length >= 2,
73
+ `expected >=2 includeAllExtensionTools:true in newSession(), got ${matches?.length ?? 0}`,
74
+ );
75
+ });
76
+ });
@@ -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,526 @@
1
+ /**
2
+ * enhanced-verification-integration.test.ts — Integration tests for enhanced verification.
3
+ *
4
+ * Exercises all 7 enhanced verification checks against GSD-2's actual source files.
5
+ * This proves:
6
+ * - R012: No false positives on production code
7
+ * - R013: Speed targets met (<2000ms pre-execution, <1000ms post-execution per task)
8
+ *
9
+ * The test constructs realistic TaskRow fixtures that reference real GSD source files,
10
+ * then runs both pre-execution and post-execution checks against them.
11
+ */
12
+
13
+ import { describe, test } from "node:test";
14
+ import assert from "node:assert/strict";
15
+ import { existsSync } from "node:fs";
16
+ import { join, dirname } from "node:path";
17
+ import { fileURLToPath } from "node:url";
18
+
19
+ import {
20
+ runPreExecutionChecks,
21
+ type PreExecutionResult,
22
+ } from "../pre-execution-checks.ts";
23
+ import {
24
+ runPostExecutionChecks,
25
+ type PostExecutionResult,
26
+ } from "../post-execution-checks.ts";
27
+ import type { TaskRow } from "../gsd-db.ts";
28
+
29
+ // ─── Constants ───────────────────────────────────────────────────────────────
30
+
31
+ const __filename = fileURLToPath(import.meta.url);
32
+ const __dirname = dirname(__filename);
33
+
34
+ // Path to the GSD extension source directory (relative to test file)
35
+ const GSD_SRC_DIR = join(__dirname, "..");
36
+
37
+ // Speed targets from R013
38
+ const PRE_EXECUTION_TIMEOUT_MS = 2000;
39
+ const POST_EXECUTION_TIMEOUT_MS = 1000;
40
+
41
+ // ─── Test Fixtures ───────────────────────────────────────────────────────────
42
+
43
+ /**
44
+ * Create a minimal TaskRow for testing.
45
+ */
46
+ function createTask(overrides: Partial<TaskRow> = {}): TaskRow {
47
+ return {
48
+ milestone_id: "M001",
49
+ slice_id: "S01",
50
+ id: overrides.id ?? "T01",
51
+ title: overrides.title ?? "Test Task",
52
+ status: overrides.status ?? "pending",
53
+ one_liner: "",
54
+ narrative: "",
55
+ verification_result: "",
56
+ duration: "",
57
+ completed_at: overrides.status === "complete" ? new Date().toISOString() : null,
58
+ blocker_discovered: false,
59
+ deviations: "",
60
+ known_issues: "",
61
+ key_files: overrides.key_files ?? [],
62
+ key_decisions: [],
63
+ full_summary_md: "",
64
+ description: overrides.description ?? "",
65
+ estimate: "",
66
+ files: overrides.files ?? [],
67
+ verify: "",
68
+ inputs: overrides.inputs ?? [],
69
+ expected_output: overrides.expected_output ?? [],
70
+ observability_impact: "",
71
+ full_plan_md: "",
72
+ sequence: overrides.sequence ?? 0,
73
+ ...overrides,
74
+ };
75
+ }
76
+
77
+ // ─── Real GSD Source Files for Testing ───────────────────────────────────────
78
+
79
+ // These are actual GSD extension source files that exist in the codebase
80
+ const REAL_GSD_FILES = [
81
+ "gsd-db.ts",
82
+ "auto-verification.ts",
83
+ "pre-execution-checks.ts",
84
+ "post-execution-checks.ts",
85
+ "state.ts",
86
+ "errors.ts",
87
+ "types.ts",
88
+ "cache.ts",
89
+ "atomic-write.ts",
90
+ ];
91
+
92
+ // Verify the test fixture files actually exist
93
+ function verifyTestFixturesExist(): void {
94
+ for (const file of REAL_GSD_FILES) {
95
+ const fullPath = join(GSD_SRC_DIR, file);
96
+ if (!existsSync(fullPath)) {
97
+ throw new Error(`Test fixture file does not exist: ${fullPath}`);
98
+ }
99
+ }
100
+ }
101
+
102
+ // ─── Integration Tests ───────────────────────────────────────────────────────
103
+
104
+ describe("Enhanced Verification Integration Tests", () => {
105
+ // Verify fixtures before running tests
106
+ test("test fixture files exist", () => {
107
+ verifyTestFixturesExist();
108
+ });
109
+
110
+ describe("Pre-Execution Checks on Real GSD Code", () => {
111
+ test("runs pre-execution checks on realistic tasks referencing real files", async () => {
112
+ // Simulate tasks that reference real GSD source files
113
+ const tasks: TaskRow[] = [
114
+ createTask({
115
+ id: "T01",
116
+ sequence: 0,
117
+ title: "Add validation to gsd-db",
118
+ description: `
119
+ ## Steps
120
+ 1. Update src/resources/extensions/gsd/gsd-db.ts to add validation
121
+ 2. Read from src/resources/extensions/gsd/types.ts for type definitions
122
+ 3. Update src/resources/extensions/gsd/errors.ts with new error types
123
+ 4. Run tests to verify changes
124
+ `.trim(),
125
+ files: REAL_GSD_FILES.slice(0, 4).map((f) => join(GSD_SRC_DIR, f)),
126
+ inputs: [
127
+ join(GSD_SRC_DIR, "types.ts"),
128
+ join(GSD_SRC_DIR, "errors.ts"),
129
+ ],
130
+ expected_output: [
131
+ join(GSD_SRC_DIR, "gsd-db.ts"),
132
+ ],
133
+ }),
134
+ ];
135
+
136
+ const start = performance.now();
137
+ const result = await runPreExecutionChecks(tasks, GSD_SRC_DIR);
138
+ const duration = performance.now() - start;
139
+
140
+ // R012: No blocking failures (false positives) on production code
141
+ const blockingFailures = result.checks.filter((c) => !c.passed && c.blocking);
142
+ assert.equal(
143
+ blockingFailures.length,
144
+ 0,
145
+ `Expected zero blocking failures, got: ${JSON.stringify(blockingFailures, null, 2)}`
146
+ );
147
+
148
+ // Overall status should not be fail
149
+ assert.notEqual(result.status, "fail", "Pre-execution checks should not fail on real GSD code");
150
+
151
+ // R013: Speed target met
152
+ assert.ok(
153
+ duration < PRE_EXECUTION_TIMEOUT_MS,
154
+ `Pre-execution checks took ${duration.toFixed(0)}ms, expected <${PRE_EXECUTION_TIMEOUT_MS}ms`
155
+ );
156
+ });
157
+
158
+ test("handles task with code block references to real packages", async () => {
159
+ // Task description with realistic code blocks using actual Node.js built-ins
160
+ const tasks: TaskRow[] = [
161
+ createTask({
162
+ id: "T01",
163
+ sequence: 0,
164
+ title: "Implement file watcher",
165
+ description: `
166
+ ## Implementation
167
+
168
+ \`\`\`typescript
169
+ import { readFileSync, writeFileSync } from "node:fs";
170
+ import { join, dirname } from "node:path";
171
+ import { existsSync } from "node:fs";
172
+
173
+ // Use existing GSD types
174
+ import type { TaskRow } from "./gsd-db.ts";
175
+ \`\`\`
176
+
177
+ Update the file watcher to use these imports.
178
+ `.trim(),
179
+ files: [join(GSD_SRC_DIR, "auto-verification.ts")],
180
+ }),
181
+ ];
182
+
183
+ const start = performance.now();
184
+ const result = await runPreExecutionChecks(tasks, GSD_SRC_DIR);
185
+ const duration = performance.now() - start;
186
+
187
+ // No blocking failures
188
+ const blockingFailures = result.checks.filter((c) => !c.passed && c.blocking);
189
+ assert.equal(
190
+ blockingFailures.length,
191
+ 0,
192
+ `Unexpected blocking failures: ${JSON.stringify(blockingFailures, null, 2)}`
193
+ );
194
+
195
+ // Speed target met
196
+ assert.ok(
197
+ duration < PRE_EXECUTION_TIMEOUT_MS,
198
+ `Pre-execution checks took ${duration.toFixed(0)}ms, expected <${PRE_EXECUTION_TIMEOUT_MS}ms`
199
+ );
200
+ });
201
+
202
+ test("handles multi-task sequence with file dependencies", async () => {
203
+ // Simulate a realistic task sequence where T02 depends on T01's output
204
+ const tasks: TaskRow[] = [
205
+ createTask({
206
+ id: "T01",
207
+ sequence: 0,
208
+ title: "Create types file",
209
+ status: "complete",
210
+ expected_output: [join(GSD_SRC_DIR, "types.ts")],
211
+ }),
212
+ createTask({
213
+ id: "T02",
214
+ sequence: 1,
215
+ title: "Use types in implementation",
216
+ description: `
217
+ Read the types from src/resources/extensions/gsd/types.ts and use them.
218
+ `.trim(),
219
+ inputs: [join(GSD_SRC_DIR, "types.ts")],
220
+ files: [join(GSD_SRC_DIR, "gsd-db.ts")],
221
+ }),
222
+ ];
223
+
224
+ const start = performance.now();
225
+ const result = await runPreExecutionChecks(tasks, GSD_SRC_DIR);
226
+ const duration = performance.now() - start;
227
+
228
+ // No blocking failures
229
+ const blockingFailures = result.checks.filter((c) => !c.passed && c.blocking);
230
+ assert.equal(
231
+ blockingFailures.length,
232
+ 0,
233
+ `Unexpected blocking failures: ${JSON.stringify(blockingFailures, null, 2)}`
234
+ );
235
+
236
+ // Speed target met
237
+ assert.ok(
238
+ duration < PRE_EXECUTION_TIMEOUT_MS,
239
+ `Pre-execution checks took ${duration.toFixed(0)}ms, expected <${PRE_EXECUTION_TIMEOUT_MS}ms`
240
+ );
241
+ });
242
+ });
243
+
244
+ describe("Post-Execution Checks on Real GSD Code", () => {
245
+ test("runs post-execution checks on real GSD source files", () => {
246
+ // Simulate a completed task that modified real files
247
+ const completedTask = createTask({
248
+ id: "T01",
249
+ title: "Update gsd-db validation",
250
+ status: "complete",
251
+ key_files: [
252
+ join(GSD_SRC_DIR, "gsd-db.ts"),
253
+ join(GSD_SRC_DIR, "types.ts"),
254
+ ],
255
+ });
256
+
257
+ const start = performance.now();
258
+ const result = runPostExecutionChecks(completedTask, [], GSD_SRC_DIR);
259
+ const duration = performance.now() - start;
260
+
261
+ // R012: No blocking failures (false positives) on production code
262
+ const blockingFailures = result.checks.filter((c) => !c.passed && c.blocking);
263
+ assert.equal(
264
+ blockingFailures.length,
265
+ 0,
266
+ `Expected zero blocking failures, got: ${JSON.stringify(blockingFailures, null, 2)}`
267
+ );
268
+
269
+ // Overall status should not be fail
270
+ assert.notEqual(result.status, "fail", "Post-execution checks should not fail on real GSD code");
271
+
272
+ // R013: Speed target met
273
+ assert.ok(
274
+ duration < POST_EXECUTION_TIMEOUT_MS,
275
+ `Post-execution checks took ${duration.toFixed(0)}ms, expected <${POST_EXECUTION_TIMEOUT_MS}ms`
276
+ );
277
+ });
278
+
279
+ test("analyzes imports in real TypeScript files", () => {
280
+ // Use auto-verification.ts which imports from multiple other GSD files
281
+ const completedTask = createTask({
282
+ id: "T02",
283
+ title: "Verify auto-verification imports",
284
+ status: "complete",
285
+ key_files: [join(GSD_SRC_DIR, "auto-verification.ts")],
286
+ });
287
+
288
+ const start = performance.now();
289
+ const result = runPostExecutionChecks(completedTask, [], GSD_SRC_DIR);
290
+ const duration = performance.now() - start;
291
+
292
+ // No blocking failures
293
+ const blockingFailures = result.checks.filter((c) => !c.passed && c.blocking);
294
+ assert.equal(
295
+ blockingFailures.length,
296
+ 0,
297
+ `Unexpected blocking failures: ${JSON.stringify(blockingFailures, null, 2)}`
298
+ );
299
+
300
+ // Speed target met
301
+ assert.ok(
302
+ duration < POST_EXECUTION_TIMEOUT_MS,
303
+ `Post-execution checks took ${duration.toFixed(0)}ms, expected <${POST_EXECUTION_TIMEOUT_MS}ms`
304
+ );
305
+ });
306
+
307
+ test("handles multi-file task with cross-file dependencies", () => {
308
+ // Task that touched multiple related files
309
+ const completedTask = createTask({
310
+ id: "T03",
311
+ title: "Refactor state management",
312
+ status: "complete",
313
+ key_files: [
314
+ join(GSD_SRC_DIR, "state.ts"),
315
+ join(GSD_SRC_DIR, "gsd-db.ts"),
316
+ join(GSD_SRC_DIR, "cache.ts"),
317
+ ],
318
+ });
319
+
320
+ const start = performance.now();
321
+ const result = runPostExecutionChecks(completedTask, [], GSD_SRC_DIR);
322
+ const duration = performance.now() - start;
323
+
324
+ // No blocking failures
325
+ const blockingFailures = result.checks.filter((c) => !c.passed && c.blocking);
326
+ assert.equal(
327
+ blockingFailures.length,
328
+ 0,
329
+ `Unexpected blocking failures: ${JSON.stringify(blockingFailures, null, 2)}`
330
+ );
331
+
332
+ // Speed target met
333
+ assert.ok(
334
+ duration < POST_EXECUTION_TIMEOUT_MS,
335
+ `Post-execution checks took ${duration.toFixed(0)}ms, expected <${POST_EXECUTION_TIMEOUT_MS}ms`
336
+ );
337
+ });
338
+
339
+ test("handles task sequence with signature analysis", () => {
340
+ // Simulate checking for signature consistency across tasks
341
+ const priorTasks: TaskRow[] = [
342
+ createTask({
343
+ id: "T01",
344
+ sequence: 0,
345
+ title: "Define TaskRow interface",
346
+ status: "complete",
347
+ key_files: [join(GSD_SRC_DIR, "gsd-db.ts")],
348
+ }),
349
+ ];
350
+
351
+ const completedTask = createTask({
352
+ id: "T02",
353
+ sequence: 1,
354
+ title: "Use TaskRow in state module",
355
+ status: "complete",
356
+ key_files: [join(GSD_SRC_DIR, "state.ts")],
357
+ });
358
+
359
+ const start = performance.now();
360
+ const result = runPostExecutionChecks(completedTask, priorTasks, GSD_SRC_DIR);
361
+ const duration = performance.now() - start;
362
+
363
+ // No blocking failures
364
+ const blockingFailures = result.checks.filter((c) => !c.passed && c.blocking);
365
+ assert.equal(
366
+ blockingFailures.length,
367
+ 0,
368
+ `Unexpected blocking failures: ${JSON.stringify(blockingFailures, null, 2)}`
369
+ );
370
+
371
+ // Speed target met
372
+ assert.ok(
373
+ duration < POST_EXECUTION_TIMEOUT_MS,
374
+ `Post-execution checks took ${duration.toFixed(0)}ms, expected <${POST_EXECUTION_TIMEOUT_MS}ms`
375
+ );
376
+ });
377
+ });
378
+
379
+ describe("Combined Pre and Post Execution Flow", () => {
380
+ test("full verification flow on realistic task lifecycle", async () => {
381
+ // Simulate a complete task lifecycle
382
+ const tasks: TaskRow[] = [
383
+ createTask({
384
+ id: "T01",
385
+ sequence: 0,
386
+ title: "Implement enhanced verification",
387
+ status: "pending",
388
+ description: `
389
+ ## Steps
390
+ 1. Update pre-execution-checks.ts with new validation
391
+ 2. Update post-execution-checks.ts with signature analysis
392
+ 3. Add integration tests
393
+
394
+ \`\`\`typescript
395
+ import { runPreExecutionChecks } from "./pre-execution-checks.ts";
396
+ import { runPostExecutionChecks } from "./post-execution-checks.ts";
397
+ \`\`\`
398
+ `.trim(),
399
+ files: [
400
+ join(GSD_SRC_DIR, "pre-execution-checks.ts"),
401
+ join(GSD_SRC_DIR, "post-execution-checks.ts"),
402
+ ],
403
+ inputs: [
404
+ join(GSD_SRC_DIR, "types.ts"),
405
+ join(GSD_SRC_DIR, "gsd-db.ts"),
406
+ ],
407
+ expected_output: [
408
+ join(GSD_SRC_DIR, "tests/enhanced-verification-integration.test.ts"),
409
+ ],
410
+ }),
411
+ ];
412
+
413
+ // Run pre-execution checks
414
+ const preStart = performance.now();
415
+ const preResult = await runPreExecutionChecks(tasks, GSD_SRC_DIR);
416
+ const preDuration = performance.now() - preStart;
417
+
418
+ // Verify pre-execution results
419
+ const preBlockingFailures = preResult.checks.filter((c) => !c.passed && c.blocking);
420
+ assert.equal(
421
+ preBlockingFailures.length,
422
+ 0,
423
+ `Pre-execution had blocking failures: ${JSON.stringify(preBlockingFailures, null, 2)}`
424
+ );
425
+ assert.ok(
426
+ preDuration < PRE_EXECUTION_TIMEOUT_MS,
427
+ `Pre-execution took ${preDuration.toFixed(0)}ms, expected <${PRE_EXECUTION_TIMEOUT_MS}ms`
428
+ );
429
+
430
+ // Task after execution (simulated completion)
431
+ const completedTask = createTask({
432
+ ...tasks[0],
433
+ status: "complete",
434
+ key_files: tasks[0].files,
435
+ });
436
+
437
+ // Run post-execution checks
438
+ const postStart = performance.now();
439
+ const postResult = runPostExecutionChecks(completedTask, [], GSD_SRC_DIR);
440
+ const postDuration = performance.now() - postStart;
441
+
442
+ // Verify post-execution results
443
+ const postBlockingFailures = postResult.checks.filter((c) => !c.passed && c.blocking);
444
+ assert.equal(
445
+ postBlockingFailures.length,
446
+ 0,
447
+ `Post-execution had blocking failures: ${JSON.stringify(postBlockingFailures, null, 2)}`
448
+ );
449
+ assert.ok(
450
+ postDuration < POST_EXECUTION_TIMEOUT_MS,
451
+ `Post-execution took ${postDuration.toFixed(0)}ms, expected <${POST_EXECUTION_TIMEOUT_MS}ms`
452
+ );
453
+ });
454
+
455
+ test("handles large number of files without timeout", () => {
456
+ // Use all available GSD source files to stress test
457
+ const allGsdFiles = REAL_GSD_FILES.map((f) => join(GSD_SRC_DIR, f));
458
+
459
+ const task = createTask({
460
+ id: "T01",
461
+ title: "Large refactor touching many files",
462
+ status: "complete",
463
+ key_files: allGsdFiles,
464
+ files: allGsdFiles,
465
+ });
466
+
467
+ const start = performance.now();
468
+ const result = runPostExecutionChecks(task, [], GSD_SRC_DIR);
469
+ const duration = performance.now() - start;
470
+
471
+ // No blocking failures
472
+ const blockingFailures = result.checks.filter((c) => !c.passed && c.blocking);
473
+ assert.equal(
474
+ blockingFailures.length,
475
+ 0,
476
+ `Unexpected blocking failures: ${JSON.stringify(blockingFailures, null, 2)}`
477
+ );
478
+
479
+ // Should still be fast even with many files
480
+ // Allow slightly more time for multi-file analysis but still within target
481
+ assert.ok(
482
+ duration < POST_EXECUTION_TIMEOUT_MS * 2, // Allow 2x for stress test
483
+ `Multi-file post-execution took ${duration.toFixed(0)}ms, expected <${POST_EXECUTION_TIMEOUT_MS * 2}ms`
484
+ );
485
+ });
486
+ });
487
+
488
+ describe("Warning Quality", () => {
489
+ test("warnings on real code are actionable, not spurious", () => {
490
+ // Run checks on well-formed production code
491
+ const task = createTask({
492
+ id: "T01",
493
+ title: "Review code quality",
494
+ status: "complete",
495
+ key_files: [
496
+ join(GSD_SRC_DIR, "pre-execution-checks.ts"),
497
+ join(GSD_SRC_DIR, "post-execution-checks.ts"),
498
+ ],
499
+ });
500
+
501
+ const result = runPostExecutionChecks(task, [], GSD_SRC_DIR);
502
+
503
+ // Extract warnings (either non-passed non-blocking, or passed with warning messages)
504
+ const warnings = result.checks.filter(
505
+ (c) => (!c.passed && !c.blocking) || (c.passed && c.message?.startsWith("Warning:"))
506
+ );
507
+
508
+ // Warnings are acceptable but should be few on well-maintained code
509
+ // If we get many warnings, it suggests the checks are too aggressive
510
+ assert.ok(
511
+ warnings.length <= 10,
512
+ `Too many warnings (${warnings.length}) suggests overly aggressive checks: ${JSON.stringify(warnings, null, 2)}`
513
+ );
514
+
515
+ // Each warning should have a clear message
516
+ for (const warning of warnings) {
517
+ assert.ok(warning.category, "Warning missing category");
518
+ assert.ok(warning.message, "Warning missing message");
519
+ assert.ok(
520
+ warning.message.length > 10,
521
+ `Warning message too short to be actionable: "${warning.message}"`
522
+ );
523
+ }
524
+ });
525
+ });
526
+ });