gsd-pi 2.78.1-dev.84a383f51 → 2.78.1

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 (474) hide show
  1. package/README.md +7 -7
  2. package/dist/cli.js +55 -95
  3. package/dist/headless-query.d.ts +0 -22
  4. package/dist/headless-query.js +4 -24
  5. package/dist/headless.d.ts +0 -10
  6. package/dist/headless.js +1 -16
  7. package/dist/loader.js +10 -7
  8. package/dist/onboarding.d.ts +0 -10
  9. package/dist/onboarding.js +2 -2
  10. package/dist/provider-migrations.d.ts +2 -2
  11. package/dist/provider-migrations.js +2 -5
  12. package/dist/resource-loader.d.ts +2 -5
  13. package/dist/resource-loader.js +5 -28
  14. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +601 -0
  15. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +651 -0
  16. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +91 -0
  17. package/dist/resources/extensions/gsd/auto/loop.js +0 -23
  18. package/dist/resources/extensions/gsd/auto/phases.js +2 -2
  19. package/dist/resources/extensions/gsd/auto/run-unit.js +1 -3
  20. package/dist/resources/extensions/gsd/auto/session.js +0 -3
  21. package/dist/resources/extensions/gsd/auto-recovery.js +4 -43
  22. package/dist/resources/extensions/gsd/auto-start.js +1 -1
  23. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
  24. package/dist/resources/extensions/gsd/auto-worktree.js +0 -30
  25. package/dist/resources/extensions/gsd/auto.js +5 -14
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -14
  27. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +5 -7
  28. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  29. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +4 -5
  30. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +31 -94
  31. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +6 -11
  32. package/dist/resources/extensions/gsd/bootstrap/system-context.js +8 -34
  33. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +2 -38
  34. package/dist/resources/extensions/gsd/commands/catalog.js +5 -69
  35. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -22
  36. package/dist/resources/extensions/gsd/commands-mcp-status.js +1 -3
  37. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -10
  38. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -4
  40. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +1 -39
  41. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  42. package/dist/resources/extensions/gsd/forensics.js +2 -2
  43. package/dist/resources/extensions/gsd/git-service.js +5 -12
  44. package/dist/resources/extensions/gsd/gsd-db.js +2 -11
  45. package/dist/resources/extensions/gsd/guided-flow.js +23 -23
  46. package/dist/resources/extensions/gsd/memory-store.js +31 -66
  47. package/dist/resources/extensions/gsd/model-router.js +9 -114
  48. package/dist/resources/extensions/gsd/native-git-bridge.js +1 -7
  49. package/dist/resources/extensions/gsd/preferences-models.js +15 -91
  50. package/dist/resources/extensions/gsd/preferences-types.js +0 -2
  51. package/dist/resources/extensions/gsd/preferences-validation.js +0 -32
  52. package/dist/resources/extensions/gsd/preferences.js +3 -5
  53. package/dist/resources/extensions/gsd/prompt-loader.js +12 -23
  54. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -9
  55. package/dist/resources/extensions/gsd/state.js +0 -42
  56. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +0 -1
  57. package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +53 -0
  58. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +112 -0
  59. package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +23 -0
  60. package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +5 -0
  61. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -18
  62. package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
  63. package/dist/resources/extensions/gsd/watch/header-renderer.js +1 -3
  64. package/dist/resources/extensions/gsd/worktree-command.js +46 -26
  65. package/dist/resources/extensions/mcp-client/index.js +3 -6
  66. package/dist/resources/extensions/slash-commands/create-extension.js +22 -36
  67. package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -9
  68. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  69. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  70. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  71. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  72. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  73. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  74. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  75. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +12 -32
  76. package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  77. package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +608 -0
  78. package/dist/rtk-shared.d.ts +0 -3
  79. package/dist/rtk-shared.js +0 -17
  80. package/dist/rtk.d.ts +5 -2
  81. package/dist/rtk.js +20 -3
  82. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  83. package/dist/web/standalone/.next/BUILD_ID +1 -1
  84. package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
  85. package/dist/web/standalone/.next/build-manifest.json +4 -4
  86. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  87. package/dist/web/standalone/.next/react-loadable-manifest.json +4 -44
  88. package/dist/web/standalone/.next/required-server-files.json +3 -3
  89. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  100. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  116. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  128. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  148. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  158. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -4
  164. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  178. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  180. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  184. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/index.html +1 -1
  194. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  195. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  196. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  197. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  198. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  199. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  200. package/dist/web/standalone/.next/server/app/page.js +2 -2
  201. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
  203. package/dist/web/standalone/.next/server/chunks/63.js +3 -3
  204. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  205. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  206. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  207. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  208. package/dist/web/standalone/.next/server/middleware.js +2 -2
  209. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  211. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  212. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  213. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  214. package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
  215. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  216. package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +20 -0
  217. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  218. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
  219. package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +1 -0
  220. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  221. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +1 -0
  223. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  224. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  225. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  226. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  227. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  228. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  229. package/dist/web/standalone/package.json +1 -2
  230. package/dist/web/standalone/server.js +1 -1
  231. package/package.json +1 -1
  232. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  233. package/packages/mcp-server/dist/workflow-tools.js +46 -74
  234. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  235. package/packages/mcp-server/src/workflow-tools.test.ts +0 -26
  236. package/packages/mcp-server/src/workflow-tools.ts +58 -93
  237. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  238. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  239. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  240. package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -48
  241. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  242. package/packages/pi-ai/dist/types.d.ts +0 -13
  243. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  244. package/packages/pi-ai/dist/types.js.map +1 -1
  245. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
  246. package/packages/pi-ai/dist/utils/repair-tool-json.js +3 -24
  247. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
  248. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +0 -26
  249. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
  250. package/packages/pi-ai/src/providers/anthropic-shared.ts +20 -52
  251. package/packages/pi-ai/src/types.ts +0 -13
  252. package/packages/pi-ai/src/utils/repair-tool-json.ts +3 -24
  253. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +0 -32
  254. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  255. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  256. package/packages/pi-coding-agent/dist/core/agent-session.js +0 -6
  257. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  259. package/packages/pi-coding-agent/dist/core/messages.js +0 -4
  260. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  261. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +2 -19
  262. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  263. package/packages/pi-coding-agent/dist/core/model-registry.d.ts +0 -10
  264. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  265. package/packages/pi-coding-agent/dist/core/model-registry.js +0 -18
  266. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  267. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +0 -13
  268. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -20
  270. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  271. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -14
  274. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  275. package/packages/pi-coding-agent/src/core/agent-session.ts +0 -7
  276. package/packages/pi-coding-agent/src/core/messages.ts +0 -4
  277. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -32
  278. package/packages/pi-coding-agent/src/core/model-registry.ts +0 -21
  279. package/packages/pi-coding-agent/src/core/system-prompt.ts +15 -33
  280. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -17
  281. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
  282. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  283. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +3 -17
  284. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  285. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +3 -20
  286. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  287. package/src/resources/extensions/gsd/auto/loop.ts +2 -24
  288. package/src/resources/extensions/gsd/auto/phases.ts +3 -3
  289. package/src/resources/extensions/gsd/auto/run-unit.ts +1 -3
  290. package/src/resources/extensions/gsd/auto/session.ts +0 -3
  291. package/src/resources/extensions/gsd/auto/types.ts +0 -1
  292. package/src/resources/extensions/gsd/auto-recovery.ts +8 -46
  293. package/src/resources/extensions/gsd/auto-start.ts +1 -1
  294. package/src/resources/extensions/gsd/auto-tool-tracking.ts +4 -2
  295. package/src/resources/extensions/gsd/auto-worktree.ts +0 -38
  296. package/src/resources/extensions/gsd/auto.ts +4 -14
  297. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +13 -15
  298. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +7 -8
  299. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  300. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +9 -10
  301. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -102
  302. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +6 -12
  303. package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -39
  304. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +11 -39
  305. package/src/resources/extensions/gsd/commands/catalog.ts +5 -75
  306. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -22
  307. package/src/resources/extensions/gsd/commands-mcp-status.ts +1 -3
  308. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -15
  309. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
  310. package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -4
  311. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +1 -39
  312. package/src/resources/extensions/gsd/doctor-types.ts +1 -3
  313. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  314. package/src/resources/extensions/gsd/forensics.ts +2 -2
  315. package/src/resources/extensions/gsd/git-service.ts +5 -13
  316. package/src/resources/extensions/gsd/gsd-db.ts +2 -12
  317. package/src/resources/extensions/gsd/guided-flow.ts +25 -25
  318. package/src/resources/extensions/gsd/memory-store.ts +28 -81
  319. package/src/resources/extensions/gsd/model-router.ts +9 -172
  320. package/src/resources/extensions/gsd/native-git-bridge.ts +1 -7
  321. package/src/resources/extensions/gsd/preferences-models.ts +15 -101
  322. package/src/resources/extensions/gsd/preferences-types.ts +0 -6
  323. package/src/resources/extensions/gsd/preferences-validation.ts +0 -35
  324. package/src/resources/extensions/gsd/preferences.ts +2 -16
  325. package/src/resources/extensions/gsd/prompt-loader.ts +12 -26
  326. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -9
  327. package/src/resources/extensions/gsd/state.ts +0 -42
  328. package/src/resources/extensions/gsd/templates/PREFERENCES.md +0 -1
  329. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +1 -178
  330. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +0 -58
  331. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +5 -9
  332. package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +4 -21
  333. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
  334. package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +211 -138
  335. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +59 -142
  336. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +4 -7
  337. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +32 -89
  338. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +22 -0
  339. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +23 -41
  340. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +43 -3
  341. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +3 -5
  342. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +87 -22
  343. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +118 -7
  344. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +47 -0
  345. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +60 -18
  346. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +76 -14
  347. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +75 -0
  348. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +83 -22
  349. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +63 -1
  350. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +1 -26
  351. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +0 -30
  352. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +4 -14
  353. package/src/resources/extensions/gsd/tests/health-widget.test.ts +12 -22
  354. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +1 -64
  355. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +0 -22
  356. package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +23 -0
  357. package/src/resources/extensions/gsd/tests/memory-store.test.ts +0 -128
  358. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +1 -33
  359. package/src/resources/extensions/gsd/tests/model-router.test.ts +8 -169
  360. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +0 -8
  361. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +43 -32
  362. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +10 -4
  363. package/src/resources/extensions/gsd/tests/preferences.test.ts +0 -127
  364. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +0 -16
  365. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +0 -7
  366. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
  367. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +19 -168
  368. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +1 -7
  369. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -23
  370. package/src/resources/extensions/gsd/tests/token-profile.test.ts +4 -51
  371. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +16 -7
  372. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +7 -5
  373. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +1 -15
  374. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
  375. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +0 -15
  376. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -17
  377. package/src/resources/extensions/gsd/unit-context-manifest.ts +8 -8
  378. package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
  379. package/src/resources/extensions/gsd/watch/header-renderer.ts +1 -3
  380. package/src/resources/extensions/gsd/workflow-logger.ts +0 -1
  381. package/src/resources/extensions/gsd/worktree-command.ts +44 -31
  382. package/src/resources/extensions/mcp-client/index.ts +3 -6
  383. package/src/resources/extensions/slash-commands/create-extension.ts +24 -38
  384. package/src/resources/skills/create-gsd-extension/SKILL.md +5 -9
  385. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
  386. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
  387. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
  388. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
  389. package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
  390. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
  391. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
  392. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
  393. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
  394. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +12 -32
  395. package/dist/cli-policy.d.ts +0 -13
  396. package/dist/cli-policy.js +0 -17
  397. package/dist/resources/.managed-resources-content-hash +0 -1
  398. package/dist/resources/extensions/gsd/auto-runtime-state.js +0 -31
  399. package/dist/resources/extensions/gsd/milestone-id-reservation.js +0 -36
  400. package/dist/resources/extensions/gsd/worktree-session-state.js +0 -33
  401. package/dist/runtime-checks.d.ts +0 -27
  402. package/dist/runtime-checks.js +0 -38
  403. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  404. package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +0 -1
  405. package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +0 -1
  406. package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +0 -1
  407. package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +0 -1
  408. package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +0 -1
  409. package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +0 -10
  410. package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +0 -2
  411. package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +0 -20
  412. package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
  413. package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +0 -1
  414. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  415. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  416. package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +0 -1
  417. package/dist/worktree-status-banner.d.ts +0 -1
  418. package/dist/worktree-status-banner.js +0 -132
  419. package/packages/mcp-server/dist/alias-telemetry.d.ts +0 -8
  420. package/packages/mcp-server/dist/alias-telemetry.d.ts.map +0 -1
  421. package/packages/mcp-server/dist/alias-telemetry.js +0 -30
  422. package/packages/mcp-server/dist/alias-telemetry.js.map +0 -1
  423. package/packages/mcp-server/src/alias-telemetry.test.ts +0 -78
  424. package/packages/mcp-server/src/alias-telemetry.ts +0 -30
  425. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +0 -2
  426. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +0 -1
  427. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +0 -231
  428. package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +0 -1
  429. package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +0 -289
  430. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +0 -37
  431. package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +0 -1
  432. package/packages/pi-coding-agent/dist/core/token-telemetry.js +0 -49
  433. package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +0 -1
  434. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +0 -2
  435. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +0 -1
  436. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +0 -133
  437. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +0 -1
  438. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +0 -2
  439. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +0 -1
  440. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +0 -78
  441. package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +0 -1
  442. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +0 -2
  443. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +0 -1
  444. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +0 -181
  445. package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +0 -1
  446. package/packages/pi-coding-agent/src/core/token-telemetry.ts +0 -77
  447. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +0 -212
  448. package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +0 -102
  449. package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +0 -200
  450. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +0 -2
  451. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +0 -1
  452. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +0 -161
  453. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +0 -1
  454. package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +0 -219
  455. package/src/resources/extensions/gsd/auto-runtime-state.ts +0 -51
  456. package/src/resources/extensions/gsd/milestone-id-reservation.ts +0 -47
  457. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +0 -116
  458. package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +0 -100
  459. package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +0 -93
  460. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +0 -47
  461. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +0 -63
  462. package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +0 -81
  463. package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +0 -57
  464. package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +0 -145
  465. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +0 -124
  466. package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +0 -152
  467. package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +0 -50
  468. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +0 -93
  469. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +0 -101
  470. package/src/resources/extensions/gsd/worktree-session-state.ts +0 -35
  471. package/src/resources/extensions/mcp-client/tests/global-config.test.ts +0 -91
  472. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +0 -58
  473. /package/dist/web/standalone/.next/static/{UF5VF4F1tB0miEtJS7LyX → 7afp7gq8-DVbxum83zRQ-}/_buildManifest.js +0 -0
  474. /package/dist/web/standalone/.next/static/{UF5VF4F1tB0miEtJS7LyX → 7afp7gq8-DVbxum83zRQ-}/_ssgManifest.js +0 -0
@@ -1,147 +1,220 @@
1
1
  /**
2
- * budget-prediction.test.ts — unit tests for budget prediction math
3
- * (`getAverageCostPerUnitType`, `predictRemainingCost`) exported from
4
- * `metrics.ts`.
2
+ * Budget Prediction — unit tests for M004/S04.
5
3
  *
6
- * The previous version (PR #582, `972dd05f4`) re-implemented both
7
- * functions inline, citing a `paths.js @gsd/pi-coding-agent` import
8
- * chain as the reason. That chain concern is no longer valid — the
9
- * real exports import cleanly from `metrics.ts`. All 10 math tests
10
- * were then exercising the test's own copy of the functions, not the
11
- * product code. #4840 documented the false-coverage case.
12
- *
13
- * This rewrite imports the real functions, deletes the inline copies,
14
- * drops the 3 source-grep tests (`metricsSrc.includes(...)`) and the
15
- * 2 dashboard `includes` tests (dashboard integration should be a
16
- * behaviour test against the dashboard builder, not a grep), and
17
- * deletes the synthesized `downgrade:` test that exercised a local
18
- * closure instead of product code. See #4784 / #4840.
4
+ * Tests prediction math, auto-downgrade logic, and dashboard integration.
5
+ * Uses extracted pure functions (avoiding module import chain) and
6
+ * source-level structural checks for dashboard/auto.ts integration.
19
7
  */
20
8
 
21
- import { describe, test } from "node:test";
9
+ import test from "node:test";
22
10
  import assert from "node:assert/strict";
11
+ import { readFileSync } from "node:fs";
12
+ import { join, dirname } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+ const metricsSrc = readFileSync(join(__dirname, "..", "metrics.ts"), "utf-8");
17
+ const dashboardSrc = readFileSync(join(__dirname, "..", "auto-dashboard.ts"), "utf-8");
18
+
19
+ // ─── Extract pure functions from metrics.ts source ────────────────────────
20
+ // Can't import directly due to paths.js → @gsd/pi-coding-agent import chain.
21
+ // Extract and evaluate the pure math functions.
22
+
23
+ interface MockUnitMetrics {
24
+ type: string;
25
+ cost: number;
26
+ }
27
+
28
+ // Re-implement the functions under test (verified against source below)
29
+ function getAverageCostPerUnitType(units: MockUnitMetrics[]): Map<string, number> {
30
+ const sums = new Map<string, { total: number; count: number }>();
31
+ for (const u of units) {
32
+ const entry = sums.get(u.type) ?? { total: 0, count: 0 };
33
+ entry.total += u.cost;
34
+ entry.count += 1;
35
+ sums.set(u.type, entry);
36
+ }
37
+ const avgs = new Map<string, number>();
38
+ for (const [type, { total, count }] of sums) {
39
+ avgs.set(type, total / count);
40
+ }
41
+ return avgs;
42
+ }
23
43
 
24
- import {
25
- getAverageCostPerUnitType,
26
- predictRemainingCost,
27
- } from "../metrics.ts";
28
- import type { UnitMetrics } from "../metrics.ts";
29
-
30
- // ─── Fixture helper ───────────────────────────────────────────────────────
31
- // UnitMetrics has several required fields; this builder lets each test
32
- // specify only the fields that matter for the cost math.
33
-
34
- function makeUnit(partial: Partial<UnitMetrics> & { type: string; cost: number }): UnitMetrics {
35
- return {
36
- id: "M001/S01/T01",
37
- model: "test-model",
38
- startedAt: 0,
39
- finishedAt: 0,
40
- tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
41
- toolCalls: 0,
42
- assistantMessages: 0,
43
- userMessages: 0,
44
- ...partial,
45
- };
44
+ function predictRemainingCost(
45
+ avgCosts: Map<string, number>,
46
+ remainingUnits: string[],
47
+ fallbackAvg?: number,
48
+ ): number {
49
+ const allAvgs = [...avgCosts.values()];
50
+ const overallAvg = fallbackAvg ?? (allAvgs.length > 0 ? allAvgs.reduce((a, b) => a + b, 0) / allAvgs.length : 0);
51
+ let total = 0;
52
+ for (const unitType of remainingUnits) {
53
+ total += avgCosts.get(unitType) ?? overallAvg;
54
+ }
55
+ return total;
46
56
  }
47
57
 
48
- describe("getAverageCostPerUnitType (metrics.ts)", () => {
49
- test("returns correct averages per unit type", () => {
50
- const units = [
51
- makeUnit({ type: "execute-task", cost: 0.1 }),
52
- makeUnit({ type: "execute-task", cost: 0.2 }),
53
- makeUnit({ type: "plan-slice", cost: 0.05 }),
54
- makeUnit({ type: "plan-slice", cost: 0.15 }),
55
- makeUnit({ type: "complete-slice", cost: 0.08 }),
56
- ];
57
- const avgs = getAverageCostPerUnitType(units);
58
- assert.ok(Math.abs(avgs.get("execute-task")! - 0.15) < 0.001, "execute-task avg");
59
- assert.ok(Math.abs(avgs.get("plan-slice")! - 0.10) < 0.001, "plan-slice avg");
60
- assert.ok(Math.abs(avgs.get("complete-slice")! - 0.08) < 0.001, "complete-slice avg");
61
- });
62
-
63
- test("returns empty map for empty input", () => {
64
- assert.equal(getAverageCostPerUnitType([]).size, 0);
65
- });
66
-
67
- test("single unit per type returns exact cost", () => {
68
- const avgs = getAverageCostPerUnitType([makeUnit({ type: "execute-task", cost: 0.42 })]);
69
- assert.ok(Math.abs(avgs.get("execute-task")! - 0.42) < 0.001);
70
- });
71
- });
72
-
73
- describe("predictRemainingCost (metrics.ts)", () => {
74
- test("calculates remaining cost from known averages", () => {
75
- const avgs = new Map([
76
- ["execute-task", 0.15],
77
- ["plan-slice", 0.10],
78
- ["complete-slice", 0.08],
79
- ]);
80
- const remaining = ["execute-task", "execute-task", "complete-slice"];
81
- const cost = predictRemainingCost(avgs, remaining);
82
- // 2 × 0.15 + 0.08 = 0.38
83
- assert.ok(Math.abs(cost - 0.38) < 0.001);
84
- });
85
-
86
- test("uses overall average for unknown unit types", () => {
87
- const avgs = new Map([
88
- ["execute-task", 0.10],
89
- ["plan-slice", 0.20],
90
- ]);
91
- const remaining = ["execute-task", "unknown-type"];
92
- // unknown: (0.10 + 0.20) / 2 = 0.15 total 0.10 + 0.15 = 0.25
93
- assert.ok(Math.abs(predictRemainingCost(avgs, remaining) - 0.25) < 0.001);
94
- });
95
-
96
- test("returns 0 for empty remaining list", () => {
97
- const avgs = new Map([["execute-task", 0.15]]);
98
- assert.equal(predictRemainingCost(avgs, []), 0);
99
- });
100
-
101
- test("uses fallback when no averages are known", () => {
102
- const cost = predictRemainingCost(new Map(), ["execute-task", "plan-slice"], 0.10);
103
- assert.ok(Math.abs(cost - 0.20) < 0.001);
104
- });
105
-
106
- test("returns 0 when no averages and no fallback", () => {
107
- assert.equal(predictRemainingCost(new Map(), ["execute-task"]), 0);
108
- });
109
- });
110
-
111
- describe("end-to-end budget prediction (composes the real functions)", () => {
112
- test("budget ceiling exceeded is detectable from real averages + projection", () => {
113
- const units = [
114
- makeUnit({ type: "execute-task", cost: 0.5 }),
115
- makeUnit({ type: "execute-task", cost: 0.6 }),
116
- makeUnit({ type: "plan-slice", cost: 0.3 }),
117
- makeUnit({ type: "complete-slice", cost: 0.2 }),
118
- ];
119
- const totalSpent = units.reduce((sum, u) => sum + u.cost, 0); // 1.60
120
- const avgs = getAverageCostPerUnitType(units);
121
- const predicted = predictRemainingCost(avgs, [
122
- "execute-task",
123
- "execute-task",
124
- "execute-task",
125
- ]);
126
- // avg execute-task = 0.55, predicted remaining = 3 × 0.55 = 1.65
127
- // total = 1.60 + 1.65 = 3.25 > 2.50 ceiling
128
- assert.ok(
129
- totalSpent + predicted > 2.5,
130
- "spent + predicted should exceed test ceiling",
131
- );
132
- });
133
-
134
- test("budget ceiling not exceeded when averages stay low", () => {
135
- const units = [
136
- makeUnit({ type: "execute-task", cost: 0.1 }),
137
- makeUnit({ type: "plan-slice", cost: 0.05 }),
138
- ];
139
- const totalSpent = units.reduce((sum, u) => sum + u.cost, 0); // 0.15
140
- const avgs = getAverageCostPerUnitType(units);
141
- const predicted = predictRemainingCost(avgs, ["execute-task", "complete-slice"]);
142
- assert.ok(
143
- totalSpent + predicted <= 5.0,
144
- "spent + predicted should stay under test ceiling",
145
- );
146
- });
58
+ // ═══════════════════════════════════════════════════════════════════════════
59
+ // Source Verification confirm our re-implementation matches
60
+ // ═══════════════════════════════════════════════════════════════════════════
61
+
62
+ test("source: metrics.ts exports getAverageCostPerUnitType", () => {
63
+ assert.ok(metricsSrc.includes("export function getAverageCostPerUnitType"), "should be exported");
64
+ });
65
+
66
+ test("source: metrics.ts exports predictRemainingCost", () => {
67
+ assert.ok(metricsSrc.includes("export function predictRemainingCost"), "should be exported");
68
+ });
69
+
70
+ test("source: getAverageCostPerUnitType uses Map<string, number>", () => {
71
+ assert.ok(
72
+ metricsSrc.includes("Map<string, number>") && metricsSrc.includes("getAverageCostPerUnitType"),
73
+ "should return Map<string, number>",
74
+ );
75
+ });
76
+
77
+ // ═══════════════════════════════════════════════════════════════════════════
78
+ // Average Cost Per Unit Type
79
+ // ═══════════════════════════════════════════════════════════════════════════
80
+
81
+ test("avgCost: returns correct averages per unit type", () => {
82
+ const units: MockUnitMetrics[] = [
83
+ { type: "execute-task", cost: 0.10 },
84
+ { type: "execute-task", cost: 0.20 },
85
+ { type: "plan-slice", cost: 0.05 },
86
+ { type: "plan-slice", cost: 0.15 },
87
+ { type: "complete-slice", cost: 0.08 },
88
+ ];
89
+ const avgs = getAverageCostPerUnitType(units);
90
+ assert.ok(Math.abs(avgs.get("execute-task")! - 0.15) < 0.001, "execute-task avg should be 0.15");
91
+ assert.ok(Math.abs(avgs.get("plan-slice")! - 0.10) < 0.001, "plan-slice avg should be 0.10");
92
+ assert.ok(Math.abs(avgs.get("complete-slice")! - 0.08) < 0.001, "complete-slice avg should be 0.08");
93
+ });
94
+
95
+ test("avgCost: returns empty map for empty input", () => {
96
+ const avgs = getAverageCostPerUnitType([]);
97
+ assert.equal(avgs.size, 0);
98
+ });
99
+
100
+ test("avgCost: single unit per type returns exact cost", () => {
101
+ const avgs = getAverageCostPerUnitType([{ type: "execute-task", cost: 0.42 }]);
102
+ assert.ok(Math.abs(avgs.get("execute-task")! - 0.42) < 0.001);
103
+ });
104
+
105
+ // ═══════════════════════════════════════════════════════════════════════════
106
+ // Predict Remaining Cost
107
+ // ═══════════════════════════════════════════════════════════════════════════
108
+
109
+ test("predict: calculates remaining cost from averages", () => {
110
+ const avgs = new Map([
111
+ ["execute-task", 0.15],
112
+ ["plan-slice", 0.10],
113
+ ["complete-slice", 0.08],
114
+ ]);
115
+ const remaining = ["execute-task", "execute-task", "complete-slice"];
116
+ const cost = predictRemainingCost(avgs, remaining);
117
+ assert.ok(Math.abs(cost - 0.38) < 0.001);
118
+ });
119
+
120
+ test("predict: uses overall average for unknown unit types", () => {
121
+ const avgs = new Map([
122
+ ["execute-task", 0.10],
123
+ ["plan-slice", 0.20],
124
+ ]);
125
+ const remaining = ["execute-task", "unknown-type"];
126
+ const cost = predictRemainingCost(avgs, remaining);
127
+ // unknown: (0.10 + 0.20) / 2 = 0.15 → total 0.10 + 0.15 = 0.25
128
+ assert.ok(Math.abs(cost - 0.25) < 0.001);
129
+ });
130
+
131
+ test("predict: returns 0 for empty remaining", () => {
132
+ const avgs = new Map([["execute-task", 0.15]]);
133
+ assert.equal(predictRemainingCost(avgs, []), 0);
134
+ });
135
+
136
+ test("predict: handles no averages with fallback", () => {
137
+ const avgs = new Map<string, number>();
138
+ const cost = predictRemainingCost(avgs, ["execute-task", "plan-slice"], 0.10);
139
+ assert.ok(Math.abs(cost - 0.20) < 0.001);
140
+ });
141
+
142
+ test("predict: handles no averages and no fallback", () => {
143
+ const avgs = new Map<string, number>();
144
+ const cost = predictRemainingCost(avgs, ["execute-task"]);
145
+ assert.equal(cost, 0);
146
+ });
147
+
148
+ // ═══════════════════════════════════════════════════════════════════════════
149
+ // Dashboard Integration
150
+ // ═══════════════════════════════════════════════════════════════════════════
151
+
152
+ test("dashboard: AutoDashboardData includes projectedRemainingCost field", () => {
153
+ assert.ok(
154
+ dashboardSrc.includes("projectedRemainingCost"),
155
+ "AutoDashboardData should have projectedRemainingCost field",
156
+ );
157
+ });
158
+
159
+ test("dashboard: AutoDashboardData includes profileDowngraded field", () => {
160
+ assert.ok(
161
+ dashboardSrc.includes("profileDowngraded"),
162
+ "AutoDashboardData should have profileDowngraded field",
163
+ );
164
+ });
165
+
166
+ // ═══════════════════════════════════════════════════════════════════════════
167
+ // Budget Prediction — End-to-End Math
168
+ // ═══════════════════════════════════════════════════════════════════════════
169
+
170
+ test("e2e: budget ceiling exceeded triggers downgrade prediction", () => {
171
+ const units: MockUnitMetrics[] = [
172
+ { type: "execute-task", cost: 0.50 },
173
+ { type: "execute-task", cost: 0.60 },
174
+ { type: "plan-slice", cost: 0.30 },
175
+ { type: "complete-slice", cost: 0.20 },
176
+ ];
177
+ const totalSpent = units.reduce((sum, u) => sum + u.cost, 0); // 1.60
178
+ const avgs = getAverageCostPerUnitType(units);
179
+ const remaining = ["execute-task", "execute-task", "execute-task"];
180
+ const predictedRemaining = predictRemainingCost(avgs, remaining);
181
+ const predictedTotal = totalSpent + predictedRemaining;
182
+ const budgetCeiling = 2.50;
183
+ assert.ok(predictedTotal > budgetCeiling, "should predict budget exhaustion");
184
+ });
185
+
186
+ test("e2e: budget ceiling not exceeded does not trigger", () => {
187
+ const units: MockUnitMetrics[] = [
188
+ { type: "execute-task", cost: 0.10 },
189
+ { type: "plan-slice", cost: 0.05 },
190
+ ];
191
+ const totalSpent = units.reduce((sum, u) => sum + u.cost, 0); // 0.15
192
+ const avgs = getAverageCostPerUnitType(units);
193
+ const remaining = ["execute-task", "complete-slice"];
194
+ const predictedRemaining = predictRemainingCost(avgs, remaining);
195
+ const predictedTotal = totalSpent + predictedRemaining;
196
+ const budgetCeiling = 5.00;
197
+ assert.ok(predictedTotal <= budgetCeiling, "should not predict budget exhaustion");
198
+ });
199
+
200
+ // ═══════════════════════════════════════════════════════════════════════════
201
+ // Downgrade Logic
202
+ // ═══════════════════════════════════════════════════════════════════════════
203
+
204
+ test("downgrade: one-way per D048 — downgrade should not be reversible", () => {
205
+ // Simulate: first prediction triggers downgrade, second doesn't reverse it
206
+ let downgraded = false;
207
+
208
+ function checkDowngrade(predictedTotal: number, ceiling: number) {
209
+ if (!downgraded && predictedTotal > ceiling) {
210
+ downgraded = true;
211
+ }
212
+ // Never reverse — per D048
213
+ }
214
+
215
+ checkDowngrade(3.00, 2.50); // triggers
216
+ assert.ok(downgraded, "should downgrade when prediction exceeds ceiling");
217
+
218
+ checkDowngrade(1.50, 2.50); // doesn't reverse
219
+ assert.ok(downgraded, "should stay downgraded (one-way per D048)");
147
220
  });
@@ -1,156 +1,73 @@
1
1
  /**
2
- * Behavioural regression test for #3580 — complete-slice verification gate.
2
+ * Regression test for #3580 — complete-slice verification gate
3
3
  *
4
- * The gate must reject completion when the verification or UAT content
5
- * indicates a blocked or failed slice. Drives the real handler with
6
- * blocked-signal fixtures and asserts on the returned error. Replaces an
7
- * earlier test file that only string-matched the BLOCKED_SIGNALS regex
8
- * literal in the source (Refs #4826/#4831).
4
+ * Without the gate, a prompt regression could silently advance a blocked
5
+ * or failed slice to "complete" status. The fix adds a BLOCKED_SIGNALS
6
+ * regex that rejects completion when verification/UAT content clearly
7
+ * indicates blocked or failed state.
9
8
  */
10
9
 
11
- import { describe, test, beforeEach, afterEach } from 'node:test';
12
- import assert from 'node:assert/strict';
13
- import * as fs from 'node:fs';
14
- import * as path from 'node:path';
15
- import * as os from 'node:os';
10
+ import { describe, it } from 'node:test'
11
+ import assert from 'node:assert/strict'
12
+ import { readFileSync } from 'node:fs'
13
+ import { resolve } from 'node:path'
14
+ import { extractSourceRegion } from "./test-helpers.ts";
16
15
 
17
- import {
18
- openDatabase,
19
- closeDatabase,
20
- insertMilestone,
21
- insertSlice,
22
- insertTask,
23
- } from '../gsd-db.ts';
24
- import { handleCompleteSlice } from '../tools/complete-slice.ts';
25
- import type { CompleteSliceParams } from '../types.ts';
26
-
27
- function tempDbPath(): string {
28
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-blocked-gate-'));
29
- return path.join(dir, 'test.db');
30
- }
31
-
32
- function cleanupDb(dbPath: string): void {
33
- closeDatabase();
34
- try { fs.rmSync(path.dirname(dbPath), { recursive: true, force: true }); } catch { /* */ }
35
- }
36
-
37
- function makeProject(): string {
38
- const basePath = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-gate-proj-'));
39
- fs.mkdirSync(path.join(basePath, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'tasks'), { recursive: true });
40
- fs.writeFileSync(
41
- path.join(basePath, '.gsd', 'milestones', 'M001', 'M001-ROADMAP.md'),
42
- `# M001\n\n## Slices\n- [ ] **S01: Test** \`risk:low\` \`depends:[]\`\n - After this: works\n`,
43
- );
44
- return basePath;
45
- }
46
-
47
- function makeParams(overrides: Partial<CompleteSliceParams>): CompleteSliceParams {
48
- return {
49
- sliceId: 'S01',
50
- milestoneId: 'M001',
51
- sliceTitle: 'Test Slice',
52
- oneLiner: 'one liner',
53
- narrative: 'narrative',
54
- verification: 'all green',
55
- deviations: 'None.',
56
- knownLimitations: 'None.',
57
- followUps: 'None.',
58
- keyFiles: [],
59
- keyDecisions: [],
60
- patternsEstablished: [],
61
- observabilitySurfaces: [],
62
- provides: [],
63
- requirementsSurfaced: [],
64
- drillDownPaths: [],
65
- affects: [],
66
- requirementsAdvanced: [],
67
- requirementsValidated: [],
68
- requirementsInvalidated: [],
69
- filesModified: [],
70
- requires: [],
71
- uatContent: 'UAT body.',
72
- ...overrides,
73
- };
74
- }
16
+ const src = readFileSync(
17
+ resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'tools', 'complete-slice.ts'),
18
+ 'utf-8',
19
+ )
75
20
 
76
21
  describe('complete-slice verification gate (#3580)', () => {
77
- let dbPath: string;
78
- let basePath: string;
79
-
80
- beforeEach(() => {
81
- dbPath = tempDbPath();
82
- openDatabase(dbPath);
83
- basePath = makeProject();
84
- insertMilestone({ id: 'M001' });
85
- insertSlice({ id: 'S01', milestoneId: 'M001' });
86
- insertTask({ id: 'T01', sliceId: 'S01', milestoneId: 'M001', status: 'complete', title: 'T1' });
87
- });
22
+ it('BLOCKED_SIGNALS regex is defined', () => {
23
+ assert.ok(
24
+ src.includes('BLOCKED_SIGNALS'),
25
+ 'BLOCKED_SIGNALS constant must be defined in complete-slice.ts',
26
+ )
27
+ })
88
28
 
89
- afterEach(() => {
90
- cleanupDb(dbPath);
91
- try { fs.rmSync(basePath, { recursive: true, force: true }); } catch { /* */ }
92
- });
29
+ it('BLOCKED_SIGNALS is a regex that tests verification content', () => {
30
+ // Extract the BLOCKED_SIGNALS definition line
31
+ const idx = src.indexOf('BLOCKED_SIGNALS')
32
+ assert.ok(idx !== -1)
33
+ const lineEnd = src.indexOf(';', idx)
34
+ const definition = src.slice(idx, lineEnd)
93
35
 
94
- test('rejects when verification text contains "verification failed"', async () => {
95
- const result = await handleCompleteSlice(
96
- makeParams({ verification: 'verification failed: the regression came back' }),
97
- basePath,
98
- );
99
- assert.ok('error' in result, 'expected handler to return an error');
100
- assert.match((result as { error: string }).error, /blocked|failed|do not complete/i);
101
- });
36
+ // Must be a regex (starts with /)
37
+ assert.ok(
38
+ definition.includes('= /'),
39
+ 'BLOCKED_SIGNALS must be assigned a regex literal',
40
+ )
102
41
 
103
- test('rejects when uatContent contains "verification_result: failed"', async () => {
104
- const result = await handleCompleteSlice(
105
- makeParams({ uatContent: '## Result\nverification_result: failed\n' }),
106
- basePath,
107
- );
108
- assert.ok('error' in result, 'expected handler to return an error');
109
- assert.match((result as { error: string }).error, /blocked|failed|do not complete/i);
110
- });
42
+ // Must match key blocked/failed signals
43
+ assert.ok(definition.includes('blocked'), 'regex must match "blocked" signals')
44
+ assert.ok(definition.includes('failed'), 'regex must match "failed" signals')
45
+ })
111
46
 
112
- test('rejects when verification declares "status: blocked"', async () => {
113
- const result = await handleCompleteSlice(
114
- makeParams({ verification: 'status: blocked — db unavailable' }),
115
- basePath,
116
- );
117
- assert.ok('error' in result, 'expected handler to return an error');
118
- assert.match((result as { error: string }).error, /blocked|failed|do not complete/i);
119
- });
47
+ it('gate checks params.verification and params.uatContent', () => {
48
+ // Find usage of BLOCKED_SIGNALS.test
49
+ const testCalls = src.match(/BLOCKED_SIGNALS\.test\([^)]+\)/g)
50
+ assert.ok(testCalls, 'BLOCKED_SIGNALS.test() must be called')
51
+ assert.ok(testCalls.length >= 2, 'must check at least verification and uatContent')
120
52
 
121
- test('rejects when uatContent says "slice is blocked"', async () => {
122
- const result = await handleCompleteSlice(
123
- makeParams({ uatContent: 'slice is blocked on upstream' }),
124
- basePath,
125
- );
126
- assert.ok('error' in result, 'expected handler to return an error');
127
- assert.match((result as { error: string }).error, /blocked|failed|do not complete/i);
128
- });
53
+ const joined = testCalls.join(' ')
54
+ assert.ok(joined.includes('verification'), 'must test params.verification')
55
+ assert.ok(joined.includes('uatContent'), 'must test params.uatContent')
56
+ })
129
57
 
130
- test('rejects when verification says "cannot complete"', async () => {
131
- const result = await handleCompleteSlice(
132
- makeParams({ verification: 'cannot complete: requirements unmet' }),
133
- basePath,
134
- );
135
- assert.ok('error' in result, 'expected handler to return an error');
136
- assert.match((result as { error: string }).error, /blocked|failed|do not complete/i);
137
- });
58
+ it('gate returns an error message when blocked signals detected', () => {
59
+ // Find the return statement after BLOCKED_SIGNALS check
60
+ const gateIdx = src.indexOf('BLOCKED_SIGNALS.test(')
61
+ assert.ok(gateIdx !== -1)
138
62
 
139
- test('passes the gate when verification + uatContent are clean', async () => {
140
- // Sanity: the gate is not over-eager. Clean inputs reach the rest of
141
- // the handler. (This call may still fail downstream because we provide
142
- // a thin fixture; the only guarantee here is that the error — if any —
143
- // is NOT the blocked-signals error.)
144
- const result = await handleCompleteSlice(
145
- makeParams({ verification: 'all 8 sections pass', uatContent: 'green across the board' }),
146
- basePath,
147
- );
148
- if ('error' in result) {
149
- assert.doesNotMatch(
150
- result.error,
151
- /blocked\/failed state — do not complete/,
152
- `clean inputs should not be rejected by the BLOCKED_SIGNALS gate, got: ${result.error}`,
153
- );
154
- }
155
- });
156
- });
63
+ const afterGate = extractSourceRegion(src, 'BLOCKED_SIGNALS.test(')
64
+ assert.ok(
65
+ afterGate.includes('return { error:'),
66
+ 'blocked signal detection must return an error',
67
+ )
68
+ assert.ok(
69
+ afterGate.includes('do not complete'),
70
+ 'error message must explain why completion is rejected',
71
+ )
72
+ })
73
+ })
@@ -13,7 +13,6 @@ import {
13
13
  getSlice,
14
14
  updateSliceStatus,
15
15
  getSliceTasks,
16
- SCHEMA_VERSION,
17
16
  } from '../gsd-db.ts';
18
17
  import { handleCompleteSlice } from '../tools/complete-slice.ts';
19
18
  import type { CompleteSliceParams } from '../types.ts';
@@ -116,21 +115,19 @@ Run the test suite and verify all assertions pass.
116
115
  }
117
116
 
118
117
  // ═══════════════════════════════════════════════════════════════════════════
119
- // complete-slice: fresh DB migrates to current schema version
118
+ // complete-slice: Schema v6 migration
120
119
  // ═══════════════════════════════════════════════════════════════════════════
121
120
 
122
- console.log('\n=== complete-slice: fresh DB migrates to current schema version ===');
121
+ console.log('\n=== complete-slice: schema v6 migration ===');
123
122
  {
124
123
  const dbPath = tempDbPath();
125
124
  openDatabase(dbPath);
126
125
 
127
126
  const adapter = _getAdapter()!;
128
127
 
129
- // Pin schema version against the source-of-truth constant so this test
130
- // survives migration bumps but still catches a "fresh DB was not migrated"
131
- // regression.
128
+ // Verify schema version is current (v22 quality_gates DDL fix)
132
129
  const versionRow = adapter.prepare('SELECT MAX(version) as v FROM schema_version').get();
133
- assertEq(versionRow?.['v'], SCHEMA_VERSION, 'fresh DB should be migrated to current SCHEMA_VERSION');
130
+ assertEq(versionRow?.['v'], 22, 'schema version should be 22');
134
131
 
135
132
  // Verify slices table has full_summary_md and full_uat_md columns
136
133
  const cols = adapter.prepare("PRAGMA table_info(slices)").all();