gsd-pi 2.58.0-dev.778d6ac → 2.58.0-dev.d63175c

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 (628) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +35 -49
  3. package/dist/headless-ui.d.ts +0 -17
  4. package/dist/headless-ui.js +3 -97
  5. package/dist/headless.js +6 -67
  6. package/dist/help-text.js +0 -1
  7. package/dist/onboarding.js +0 -44
  8. package/dist/resource-loader.js +1 -16
  9. package/dist/resources/agents/researcher.md +1 -1
  10. package/dist/resources/extensions/ask-user-questions.js +3 -16
  11. package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
  12. package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
  13. package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
  14. package/dist/resources/extensions/claude-code-cli/partial-builder.js +6 -14
  15. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +36 -59
  16. package/dist/resources/extensions/context7/extension-manifest.json +1 -1
  17. package/dist/resources/extensions/get-secrets-from-user.js +5 -8
  18. package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
  19. package/dist/resources/extensions/google-search/index.js +1 -2
  20. package/dist/resources/extensions/gsd/auto/phases.js +21 -25
  21. package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
  22. package/dist/resources/extensions/gsd/auto-dashboard.js +20 -37
  23. package/dist/resources/extensions/gsd/auto-dispatch.js +2 -17
  24. package/dist/resources/extensions/gsd/auto-model-selection.js +3 -26
  25. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -16
  26. package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
  27. package/dist/resources/extensions/gsd/auto-recovery.js +5 -13
  28. package/dist/resources/extensions/gsd/auto-start.js +22 -35
  29. package/dist/resources/extensions/gsd/auto-worktree.js +12 -196
  30. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +0 -32
  31. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +8 -80
  32. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -32
  33. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +18 -33
  34. package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -44
  35. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +0 -67
  36. package/dist/resources/extensions/gsd/captures.js +4 -56
  37. package/dist/resources/extensions/gsd/db-writer.js +8 -116
  38. package/dist/resources/extensions/gsd/doctor-git-checks.js +0 -28
  39. package/dist/resources/extensions/gsd/doctor-providers.js +1 -2
  40. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +4 -5
  41. package/dist/resources/extensions/gsd/doctor.js +1 -3
  42. package/dist/resources/extensions/gsd/error-classifier.js +10 -13
  43. package/dist/resources/extensions/gsd/extension-manifest.json +1 -16
  44. package/dist/resources/extensions/gsd/forensics.js +20 -123
  45. package/dist/resources/extensions/gsd/git-service.js +1 -23
  46. package/dist/resources/extensions/gsd/gitignore.js +0 -33
  47. package/dist/resources/extensions/gsd/gsd-db.js +9 -36
  48. package/dist/resources/extensions/gsd/guided-flow.js +44 -106
  49. package/dist/resources/extensions/gsd/health-widget-core.js +0 -31
  50. package/dist/resources/extensions/gsd/health-widget.js +0 -17
  51. package/dist/resources/extensions/gsd/index.js +1 -1
  52. package/dist/resources/extensions/gsd/memory-extractor.js +0 -7
  53. package/dist/resources/extensions/gsd/migrate-external.js +1 -8
  54. package/dist/resources/extensions/gsd/model-cost-table.js +0 -18
  55. package/dist/resources/extensions/gsd/model-router.js +1 -35
  56. package/dist/resources/extensions/gsd/native-git-bridge.js +0 -17
  57. package/dist/resources/extensions/gsd/notifications.js +1 -16
  58. package/dist/resources/extensions/gsd/parallel-eligibility.js +2 -13
  59. package/dist/resources/extensions/gsd/parallel-merge.js +5 -78
  60. package/dist/resources/extensions/gsd/parsers-legacy.js +3 -20
  61. package/dist/resources/extensions/gsd/paths.js +0 -43
  62. package/dist/resources/extensions/gsd/preferences-models.js +1 -14
  63. package/dist/resources/extensions/gsd/preferences-types.js +1 -2
  64. package/dist/resources/extensions/gsd/preferences.js +16 -13
  65. package/dist/resources/extensions/gsd/prompt-loader.js +1 -4
  66. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -4
  68. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -3
  71. package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
  72. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  73. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  74. package/dist/resources/extensions/gsd/prompts/plan-slice.md +0 -2
  75. package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/triage-captures.md +0 -1
  77. package/dist/resources/extensions/gsd/repo-identity.js +11 -205
  78. package/dist/resources/extensions/gsd/rethink.js +0 -5
  79. package/dist/resources/extensions/gsd/roadmap-slices.js +4 -5
  80. package/dist/resources/extensions/gsd/state.js +27 -85
  81. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +1 -20
  82. package/dist/resources/extensions/gsd/tools/complete-task.js +71 -34
  83. package/dist/resources/extensions/gsd/tools/plan-milestone.js +2 -12
  84. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +1 -29
  85. package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -14
  86. package/dist/resources/extensions/gsd/triage-resolution.js +7 -22
  87. package/dist/resources/extensions/gsd/undo.js +2 -2
  88. package/dist/resources/extensions/gsd/unit-ownership.js +33 -164
  89. package/dist/resources/extensions/gsd/verdict-parser.js +8 -20
  90. package/dist/resources/extensions/gsd/workflow-manifest.js +5 -24
  91. package/dist/resources/extensions/gsd/workflow-projections.js +63 -95
  92. package/dist/resources/extensions/gsd/workflow-reconcile.js +5 -35
  93. package/dist/resources/extensions/gsd/workspace-index.js +0 -24
  94. package/dist/resources/extensions/gsd/worktree-manager.js +1 -105
  95. package/dist/resources/extensions/gsd/worktree-resolver.js +3 -20
  96. package/dist/resources/extensions/mcp-client/index.js +7 -11
  97. package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
  98. package/dist/resources/extensions/shared/interview-ui.js +1 -11
  99. package/dist/resources/skills/create-gsd-extension/SKILL.md +3 -5
  100. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +4 -5
  101. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  102. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  103. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +3 -5
  104. package/dist/web/standalone/.next/BUILD_ID +1 -1
  105. package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
  106. package/dist/web/standalone/.next/build-manifest.json +3 -3
  107. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  108. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  109. package/dist/web/standalone/.next/required-server-files.json +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  112. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.rsc +2 -2
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  128. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.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_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/index.html +1 -1
  183. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  184. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  185. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  186. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  187. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  188. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  189. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
  191. package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
  192. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  195. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  196. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  197. package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +9 -0
  198. package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-61d3afac6d0f0ce7.js} +1 -1
  199. package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +1 -0
  200. package/dist/web/standalone/server.js +1 -1
  201. package/dist/web-mode.js +1 -2
  202. package/package.json +2 -2
  203. package/packages/native/dist/ast/index.js +5 -9
  204. package/packages/native/dist/ast/types.js +1 -2
  205. package/packages/native/dist/clipboard/index.js +7 -12
  206. package/packages/native/dist/clipboard/types.js +1 -2
  207. package/packages/native/dist/diff/index.js +7 -12
  208. package/packages/native/dist/diff/types.js +1 -2
  209. package/packages/native/dist/fd/index.js +3 -6
  210. package/packages/native/dist/fd/types.js +1 -2
  211. package/packages/native/dist/glob/index.js +5 -9
  212. package/packages/native/dist/glob/types.js +1 -2
  213. package/packages/native/dist/grep/index.js +5 -9
  214. package/packages/native/dist/grep/types.js +1 -2
  215. package/packages/native/dist/gsd-parser/index.js +11 -18
  216. package/packages/native/dist/gsd-parser/types.js +1 -2
  217. package/packages/native/dist/highlight/index.js +7 -12
  218. package/packages/native/dist/highlight/types.js +1 -2
  219. package/packages/native/dist/html/index.js +3 -6
  220. package/packages/native/dist/html/types.js +1 -2
  221. package/packages/native/dist/image/index.js +5 -10
  222. package/packages/native/dist/image/types.js +4 -7
  223. package/packages/native/dist/index.js +17 -70
  224. package/packages/native/dist/json-parse/index.js +8 -13
  225. package/packages/native/dist/native.js +10 -47
  226. package/packages/native/dist/ps/index.js +9 -15
  227. package/packages/native/dist/ps/types.js +1 -2
  228. package/packages/native/dist/stream-process/index.js +7 -12
  229. package/packages/native/dist/text/index.js +14 -24
  230. package/packages/native/dist/text/types.js +2 -5
  231. package/packages/native/dist/truncate/index.js +7 -12
  232. package/packages/native/dist/ttsr/index.js +7 -12
  233. package/packages/native/dist/ttsr/types.js +1 -2
  234. package/packages/native/dist/xxhash/index.js +5 -9
  235. package/packages/native/package.json +19 -19
  236. package/packages/native/src/native.ts +8 -9
  237. package/packages/pi-agent-core/dist/agent-loop.js +2 -3
  238. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  239. package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
  240. package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
  241. package/packages/pi-agent-core/dist/proxy.js.map +1 -1
  242. package/packages/pi-agent-core/src/agent-loop.ts +2 -3
  243. package/packages/pi-agent-core/src/proxy.ts +1 -1
  244. package/packages/pi-ai/dist/env-api-keys.js +0 -1
  245. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  246. package/packages/pi-ai/dist/index.d.ts +0 -1
  247. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  248. package/packages/pi-ai/dist/index.js +0 -1
  249. package/packages/pi-ai/dist/index.js.map +1 -1
  250. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/providers/anthropic-shared.js +2 -19
  252. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  253. package/packages/pi-ai/dist/types.d.ts +3 -3
  254. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  255. package/packages/pi-ai/dist/types.js.map +1 -1
  256. package/packages/pi-ai/dist/utils/json-parse.d.ts +0 -3
  257. package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
  258. package/packages/pi-ai/dist/utils/json-parse.js +1 -24
  259. package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
  260. package/packages/pi-ai/src/env-api-keys.ts +0 -1
  261. package/packages/pi-ai/src/index.ts +0 -1
  262. package/packages/pi-ai/src/providers/anthropic-shared.ts +2 -17
  263. package/packages/pi-ai/src/types.ts +2 -3
  264. package/packages/pi-ai/src/utils/json-parse.ts +1 -28
  265. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +0 -4
  266. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  267. package/packages/pi-coding-agent/dist/core/agent-session.js +0 -31
  268. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  269. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +1 -17
  270. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  271. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +2 -62
  272. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  273. package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
  274. package/packages/pi-coding-agent/dist/core/exec.js +1 -3
  275. package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +0 -4
  277. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  278. package/packages/pi-coding-agent/dist/core/extensions/index.js +0 -2
  279. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  280. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +0 -5
  281. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  282. package/packages/pi-coding-agent/dist/core/extensions/loader.js +0 -5
  283. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  284. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
  285. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  286. package/packages/pi-coding-agent/dist/core/index.js +1 -1
  287. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  288. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/lsp/index.js +0 -3
  290. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +0 -3
  293. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  294. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/messages.js +2 -31
  296. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/model-resolver.js +0 -1
  299. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +0 -10
  301. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/resource-loader.js +1 -12
  303. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +0 -6
  305. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/core/retry-handler.js +1 -48
  307. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  309. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +3 -10
  310. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  311. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/tools/read.js +4 -13
  313. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  314. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  315. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  316. package/packages/pi-coding-agent/dist/index.js +1 -1
  317. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  318. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +0 -4
  320. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  321. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +0 -1
  322. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
  323. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +0 -5
  324. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
  325. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -38
  326. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +1 -94
  327. package/packages/pi-coding-agent/src/core/exec.ts +1 -3
  328. package/packages/pi-coding-agent/src/core/extensions/index.ts +0 -4
  329. package/packages/pi-coding-agent/src/core/extensions/loader.ts +0 -5
  330. package/packages/pi-coding-agent/src/core/index.ts +0 -6
  331. package/packages/pi-coding-agent/src/core/lsp/index.ts +0 -3
  332. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +0 -3
  333. package/packages/pi-coding-agent/src/core/messages.ts +2 -29
  334. package/packages/pi-coding-agent/src/core/model-resolver.ts +0 -1
  335. package/packages/pi-coding-agent/src/core/resource-loader.ts +1 -20
  336. package/packages/pi-coding-agent/src/core/retry-handler.ts +1 -52
  337. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +3 -11
  338. package/packages/pi-coding-agent/src/core/tools/read.ts +4 -14
  339. package/packages/pi-coding-agent/src/index.ts +0 -6
  340. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +0 -7
  341. package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +0 -6
  342. package/packages/pi-tui/dist/terminal.d.ts +0 -2
  343. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  344. package/packages/pi-tui/dist/terminal.js +0 -9
  345. package/packages/pi-tui/dist/terminal.js.map +1 -1
  346. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  347. package/packages/pi-tui/dist/tui.js +0 -9
  348. package/packages/pi-tui/dist/tui.js.map +1 -1
  349. package/packages/pi-tui/src/terminal.ts +0 -14
  350. package/packages/pi-tui/src/tui.ts +0 -8
  351. package/scripts/ensure-workspace-builds.cjs +14 -45
  352. package/src/resources/agents/researcher.md +1 -1
  353. package/src/resources/extensions/ask-user-questions.ts +3 -21
  354. package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
  355. package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
  356. package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
  357. package/src/resources/extensions/claude-code-cli/partial-builder.ts +6 -13
  358. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +35 -63
  359. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +0 -28
  360. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +1 -108
  361. package/src/resources/extensions/context7/extension-manifest.json +1 -1
  362. package/src/resources/extensions/get-secrets-from-user.ts +5 -8
  363. package/src/resources/extensions/google-search/extension-manifest.json +1 -1
  364. package/src/resources/extensions/google-search/index.ts +1 -2
  365. package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -1
  366. package/src/resources/extensions/gsd/auto/phases.ts +34 -43
  367. package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
  368. package/src/resources/extensions/gsd/auto-dashboard.ts +19 -37
  369. package/src/resources/extensions/gsd/auto-dispatch.ts +2 -18
  370. package/src/resources/extensions/gsd/auto-model-selection.ts +5 -26
  371. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -18
  372. package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
  373. package/src/resources/extensions/gsd/auto-recovery.ts +5 -12
  374. package/src/resources/extensions/gsd/auto-start.ts +26 -35
  375. package/src/resources/extensions/gsd/auto-worktree.ts +9 -190
  376. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +0 -31
  377. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +8 -85
  378. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -38
  379. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +19 -31
  380. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -50
  381. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +0 -75
  382. package/src/resources/extensions/gsd/captures.ts +3 -63
  383. package/src/resources/extensions/gsd/db-writer.ts +7 -140
  384. package/src/resources/extensions/gsd/doctor-git-checks.ts +0 -26
  385. package/src/resources/extensions/gsd/doctor-providers.ts +1 -2
  386. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +4 -5
  387. package/src/resources/extensions/gsd/doctor.ts +1 -3
  388. package/src/resources/extensions/gsd/error-classifier.ts +11 -14
  389. package/src/resources/extensions/gsd/extension-manifest.json +1 -16
  390. package/src/resources/extensions/gsd/forensics.ts +20 -144
  391. package/src/resources/extensions/gsd/git-service.ts +3 -26
  392. package/src/resources/extensions/gsd/gitignore.ts +0 -33
  393. package/src/resources/extensions/gsd/gsd-db.ts +7 -43
  394. package/src/resources/extensions/gsd/guided-flow.ts +45 -114
  395. package/src/resources/extensions/gsd/health-widget-core.ts +0 -34
  396. package/src/resources/extensions/gsd/health-widget.ts +0 -17
  397. package/src/resources/extensions/gsd/index.ts +0 -1
  398. package/src/resources/extensions/gsd/memory-extractor.ts +0 -8
  399. package/src/resources/extensions/gsd/migrate-external.ts +1 -9
  400. package/src/resources/extensions/gsd/model-cost-table.ts +0 -19
  401. package/src/resources/extensions/gsd/model-router.ts +1 -35
  402. package/src/resources/extensions/gsd/native-git-bridge.ts +0 -17
  403. package/src/resources/extensions/gsd/notifications.ts +0 -16
  404. package/src/resources/extensions/gsd/parallel-eligibility.ts +2 -15
  405. package/src/resources/extensions/gsd/parallel-merge.ts +4 -87
  406. package/src/resources/extensions/gsd/parsers-legacy.ts +3 -22
  407. package/src/resources/extensions/gsd/paths.ts +0 -42
  408. package/src/resources/extensions/gsd/preferences-models.ts +1 -14
  409. package/src/resources/extensions/gsd/preferences-types.ts +1 -2
  410. package/src/resources/extensions/gsd/preferences.ts +15 -13
  411. package/src/resources/extensions/gsd/prompt-loader.ts +1 -4
  412. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  413. package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -4
  414. package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  415. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  416. package/src/resources/extensions/gsd/prompts/execute-task.md +1 -3
  417. package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
  418. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  419. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  420. package/src/resources/extensions/gsd/prompts/plan-slice.md +0 -2
  421. package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
  422. package/src/resources/extensions/gsd/prompts/triage-captures.md +0 -1
  423. package/src/resources/extensions/gsd/repo-identity.ts +11 -186
  424. package/src/resources/extensions/gsd/rethink.ts +0 -6
  425. package/src/resources/extensions/gsd/roadmap-slices.ts +4 -5
  426. package/src/resources/extensions/gsd/state.ts +32 -84
  427. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +0 -29
  428. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +1 -71
  429. package/src/resources/extensions/gsd/tests/captures.test.ts +0 -103
  430. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +0 -27
  431. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +0 -21
  432. package/src/resources/extensions/gsd/tests/db-writer.test.ts +12 -7
  433. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +5 -78
  434. package/src/resources/extensions/gsd/tests/derive-state.test.ts +0 -29
  435. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +0 -40
  436. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +1 -20
  437. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +0 -117
  438. package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +79 -0
  439. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -31
  440. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +12 -125
  441. package/src/resources/extensions/gsd/tests/health-widget.test.ts +0 -67
  442. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +1 -111
  443. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +0 -101
  444. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +0 -59
  445. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +0 -110
  446. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
  447. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +2 -85
  448. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +0 -34
  449. package/src/resources/extensions/gsd/tests/model-router.test.ts +3 -68
  450. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +0 -28
  451. package/src/resources/extensions/gsd/tests/notifications.test.ts +0 -45
  452. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +1 -33
  453. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +0 -29
  454. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +0 -38
  455. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +0 -117
  456. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +0 -97
  457. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +0 -134
  458. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +1 -2
  459. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +0 -8
  460. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +17 -100
  461. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +1 -4
  462. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +0 -48
  463. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +0 -92
  464. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +2 -4
  465. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +1 -48
  466. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +5 -29
  467. package/src/resources/extensions/gsd/tools/complete-task.ts +74 -36
  468. package/src/resources/extensions/gsd/tools/plan-milestone.ts +1 -13
  469. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +0 -36
  470. package/src/resources/extensions/gsd/tools/validate-milestone.ts +2 -20
  471. package/src/resources/extensions/gsd/triage-resolution.ts +6 -23
  472. package/src/resources/extensions/gsd/types.ts +2 -4
  473. package/src/resources/extensions/gsd/undo.ts +2 -2
  474. package/src/resources/extensions/gsd/unit-ownership.ts +35 -206
  475. package/src/resources/extensions/gsd/verdict-parser.ts +6 -21
  476. package/src/resources/extensions/gsd/workflow-logger.ts +1 -3
  477. package/src/resources/extensions/gsd/workflow-manifest.ts +5 -22
  478. package/src/resources/extensions/gsd/workflow-projections.ts +64 -97
  479. package/src/resources/extensions/gsd/workflow-reconcile.ts +10 -39
  480. package/src/resources/extensions/gsd/workspace-index.ts +0 -30
  481. package/src/resources/extensions/gsd/worktree-manager.ts +1 -120
  482. package/src/resources/extensions/gsd/worktree-resolver.ts +3 -22
  483. package/src/resources/extensions/mcp-client/index.ts +7 -13
  484. package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
  485. package/src/resources/extensions/shared/interview-ui.ts +1 -12
  486. package/src/resources/skills/create-gsd-extension/SKILL.md +3 -5
  487. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +4 -5
  488. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  489. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  490. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +3 -5
  491. package/dist/resources/extensions/gsd/milestone-validation-gates.js +0 -45
  492. package/dist/resources/extensions/ollama/index.js +0 -112
  493. package/dist/resources/extensions/ollama/model-capabilities.js +0 -115
  494. package/dist/resources/extensions/ollama/ollama-client.js +0 -168
  495. package/dist/resources/extensions/ollama/ollama-commands.js +0 -194
  496. package/dist/resources/extensions/ollama/ollama-discovery.js +0 -69
  497. package/dist/resources/extensions/ollama/ollama-tool.js +0 -184
  498. package/dist/resources/extensions/ollama/types.js +0 -2
  499. package/dist/startup-model-validation.d.ts +0 -39
  500. package/dist/startup-model-validation.js +0 -50
  501. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
  502. package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +0 -1
  503. package/packages/native/src/__tests__/module-compat.test.mjs +0 -91
  504. package/packages/pi-agent-core/src/agent-loop.test.ts +0 -45
  505. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +0 -2
  506. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +0 -1
  507. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +0 -25
  508. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +0 -1
  509. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +0 -37
  510. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +0 -1
  511. package/packages/pi-ai/dist/utils/repair-tool-json.js +0 -75
  512. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +0 -1
  513. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +0 -2
  514. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +0 -1
  515. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +0 -73
  516. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +0 -1
  517. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +0 -29
  518. package/packages/pi-ai/src/utils/repair-tool-json.ts +0 -88
  519. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +0 -102
  520. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +0 -6
  521. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +0 -1
  522. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +0 -176
  523. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +0 -1
  524. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +0 -28
  525. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +0 -1
  526. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +0 -37
  527. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +0 -1
  528. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +0 -2
  529. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +0 -1
  530. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +0 -63
  531. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +0 -1
  532. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +0 -19
  533. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +0 -1
  534. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +0 -115
  535. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +0 -1
  536. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +0 -2
  537. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +0 -1
  538. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +0 -109
  539. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +0 -1
  540. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +0 -44
  541. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +0 -1
  542. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +0 -97
  543. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +0 -1
  544. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +0 -2
  545. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +0 -1
  546. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +0 -181
  547. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +0 -1
  548. package/packages/pi-coding-agent/dist/core/messages.test.d.ts +0 -9
  549. package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +0 -1
  550. package/packages/pi-coding-agent/dist/core/messages.test.js +0 -86
  551. package/packages/pi-coding-agent/dist/core/messages.test.js.map +0 -1
  552. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +0 -9
  553. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +0 -1
  554. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +0 -193
  555. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +0 -1
  556. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +0 -16
  557. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +0 -1
  558. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +0 -80
  559. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +0 -1
  560. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +0 -236
  561. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +0 -77
  562. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +0 -62
  563. package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +0 -134
  564. package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +0 -137
  565. package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +0 -228
  566. package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +0 -118
  567. package/packages/pi-coding-agent/src/core/messages.test.ts +0 -114
  568. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +0 -255
  569. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +0 -92
  570. package/src/resources/extensions/gsd/milestone-validation-gates.ts +0 -56
  571. package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +0 -71
  572. package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +0 -47
  573. package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +0 -192
  574. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +0 -131
  575. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +0 -47
  576. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +0 -127
  577. package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +0 -20
  578. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -74
  579. package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +0 -140
  580. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -129
  581. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  582. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +0 -164
  583. package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +0 -135
  584. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +0 -97
  585. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +0 -107
  586. package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +0 -243
  587. package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +0 -150
  588. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +0 -959
  589. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +0 -105
  590. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +0 -116
  591. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +0 -159
  592. package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +0 -150
  593. package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +0 -70
  594. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +0 -297
  595. package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +0 -178
  596. package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +0 -69
  597. package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +0 -157
  598. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +0 -90
  599. package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +0 -162
  600. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +0 -233
  601. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +0 -305
  602. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +0 -405
  603. package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +0 -257
  604. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +0 -1628
  605. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +0 -106
  606. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +0 -174
  607. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +0 -221
  608. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +0 -289
  609. package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +0 -154
  610. package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +0 -156
  611. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +0 -82
  612. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +0 -140
  613. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +0 -101
  614. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +0 -95
  615. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +0 -55
  616. package/src/resources/extensions/ollama/index.ts +0 -130
  617. package/src/resources/extensions/ollama/model-capabilities.ts +0 -145
  618. package/src/resources/extensions/ollama/ollama-client.ts +0 -196
  619. package/src/resources/extensions/ollama/ollama-commands.ts +0 -248
  620. package/src/resources/extensions/ollama/ollama-discovery.ts +0 -106
  621. package/src/resources/extensions/ollama/ollama-tool.ts +0 -218
  622. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +0 -162
  623. package/src/resources/extensions/ollama/tests/ollama-client.test.ts +0 -38
  624. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +0 -28
  625. package/src/resources/extensions/ollama/types.ts +0 -130
  626. package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +0 -156
  627. /package/dist/web/standalone/.next/static/{R0D4xaIPl5kg93edN7Oo0 → 5DLsjFHdSB6_a1EDQVjr7}/_buildManifest.js +0 -0
  628. /package/dist/web/standalone/.next/static/{R0D4xaIPl5kg93edN7Oo0 → 5DLsjFHdSB6_a1EDQVjr7}/_ssgManifest.js +0 -0
@@ -1,75 +0,0 @@
1
- /**
2
- * Repair malformed JSON in LLM tool-call arguments.
3
- *
4
- * LLMs sometimes copy YAML template formatting into JSON tool arguments,
5
- * producing patterns like:
6
- *
7
- * "keyDecisions": - Used Web Notification API...,
8
- * "keyFiles": - src-tauri/src/lib.rs — Extended...
9
- *
10
- * instead of valid JSON arrays:
11
- *
12
- * "keyDecisions": ["Used Web Notification API..."],
13
- * "keyFiles": ["src-tauri/src/lib.rs — Extended..."]
14
- *
15
- * This module detects and repairs such patterns before JSON.parse is called.
16
- *
17
- * @see https://github.com/gsd-build/gsd-2/issues/2660
18
- */
19
- /**
20
- * Detect whether a JSON string contains YAML-style bullet-list values
21
- * (i.e. `"key": - item` instead of `"key": ["item"]`).
22
- */
23
- export function hasYamlBulletLists(json) {
24
- // Match: "key": followed by whitespace then a dash-space pattern (YAML bullet)
25
- // The negative lookahead excludes negative numbers (e.g. "key": -1)
26
- return /"\s*:\s*-\s+(?!\d)/.test(json);
27
- }
28
- /**
29
- * Attempt to repair YAML-style bullet lists embedded in a JSON string.
30
- *
31
- * Converts patterns like:
32
- * "keyDecisions": - Used Web Notification API..., "keyFiles": - file1
33
- *
34
- * Into:
35
- * "keyDecisions": ["Used Web Notification API..."], "keyFiles": ["file1"]
36
- *
37
- * Returns the original string unchanged if no YAML patterns are detected
38
- * or if the repair itself would produce invalid JSON.
39
- */
40
- export function repairToolJson(json) {
41
- if (!hasYamlBulletLists(json)) {
42
- return json;
43
- }
44
- // Strategy: find each `"key": - item1\n - item2\n - item3` region and
45
- // wrap items in a JSON array.
46
- //
47
- // We work on the raw string because the JSON is not parseable yet.
48
- // The pattern we target:
49
- // "someKey":\s*- item text (possibly multiline)
50
- // optionally followed by more `- item` lines
51
- // terminated by the next `"key":` or `}` or end of string.
52
- let repaired = json;
53
- // Match a key followed by YAML-style bullet list.
54
- // Capture: (1) the key portion including colon, (2) the bullet-list body,
55
- // (3) the separator (comma or empty) before the next key/bracket.
56
- // The bullet list body ends at the next `"key":` or `}` or `]` or end of string.
57
- const keyBulletPattern = /("(?:[^"\\]|\\.)*"\s*:\s*)(- .+?)(,?\s*)(?="(?:[^"\\]|\\.)*"\s*:|[}\]]|$)/gs;
58
- repaired = repaired.replace(keyBulletPattern, (_match, keyPart, bulletBody, separator) => {
59
- // Split the bullet body into individual items on `- ` boundaries.
60
- // Items may contain embedded newlines for multi-line values.
61
- const items = bulletBody
62
- .split(/\n?\s*- /)
63
- .filter((s) => s.trim().length > 0)
64
- .map((s) => s.replace(/,\s*$/, "").trim());
65
- // JSON-encode each item as a string, then wrap in an array.
66
- const jsonArray = "[" + items.map((item) => JSON.stringify(item)).join(", ") + "]";
67
- // Re-emit the separator (comma) so the next key is properly delimited
68
- const sep = separator.trim() ? separator : (/^\s*"/.test(separator + "x") ? ", " : "");
69
- return keyPart + jsonArray + sep;
70
- });
71
- // Strip trailing commas before } or ] (common in repaired JSON)
72
- repaired = repaired.replace(/,(\s*[}\]])/g, "$1");
73
- return repaired;
74
- }
75
- //# sourceMappingURL=repair-tool-json.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"repair-tool-json.js","sourceRoot":"","sources":["../../src/utils/repair-tool-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC9C,+EAA+E;IAC/E,oEAAoE;IACpE,OAAO,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IAC1C,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACb,CAAC;IAED,wEAAwE;IACxE,8BAA8B;IAC9B,EAAE;IACF,mEAAmE;IACnE,yBAAyB;IACzB,kDAAkD;IAClD,+CAA+C;IAC/C,6DAA6D;IAE7D,IAAI,QAAQ,GAAG,IAAI,CAAC;IAEpB,kDAAkD;IAClD,0EAA0E;IAC1E,kEAAkE;IAClE,iFAAiF;IACjF,MAAM,gBAAgB,GACrB,6EAA6E,CAAC;IAE/E,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAC1B,gBAAgB,EAChB,CAAC,MAAM,EAAE,OAAe,EAAE,UAAkB,EAAE,SAAiB,EAAE,EAAE;QAClE,kEAAkE;QAClE,6DAA6D;QAC7D,MAAM,KAAK,GAAG,UAAU;aACtB,KAAK,CAAC,UAAU,CAAC;aACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;aAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAE5C,4DAA4D;QAC5D,MAAM,SAAS,GAAG,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;QAEnF,sEAAsE;QACtE,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACvF,OAAO,OAAO,GAAG,SAAS,GAAG,GAAG,CAAC;IAClC,CAAC,CACD,CAAC;IAEF,gEAAgE;IAChE,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAElD,OAAO,QAAQ,CAAC;AACjB,CAAC","sourcesContent":["/**\n * Repair malformed JSON in LLM tool-call arguments.\n *\n * LLMs sometimes copy YAML template formatting into JSON tool arguments,\n * producing patterns like:\n *\n * \"keyDecisions\": - Used Web Notification API...,\n * \"keyFiles\": - src-tauri/src/lib.rs — Extended...\n *\n * instead of valid JSON arrays:\n *\n * \"keyDecisions\": [\"Used Web Notification API...\"],\n * \"keyFiles\": [\"src-tauri/src/lib.rs — Extended...\"]\n *\n * This module detects and repairs such patterns before JSON.parse is called.\n *\n * @see https://github.com/gsd-build/gsd-2/issues/2660\n */\n\n/**\n * Detect whether a JSON string contains YAML-style bullet-list values\n * (i.e. `\"key\": - item` instead of `\"key\": [\"item\"]`).\n */\nexport function hasYamlBulletLists(json: string): boolean {\n\t// Match: \"key\": followed by whitespace then a dash-space pattern (YAML bullet)\n\t// The negative lookahead excludes negative numbers (e.g. \"key\": -1)\n\treturn /\"\\s*:\\s*-\\s+(?!\\d)/.test(json);\n}\n\n/**\n * Attempt to repair YAML-style bullet lists embedded in a JSON string.\n *\n * Converts patterns like:\n * \"keyDecisions\": - Used Web Notification API..., \"keyFiles\": - file1\n *\n * Into:\n * \"keyDecisions\": [\"Used Web Notification API...\"], \"keyFiles\": [\"file1\"]\n *\n * Returns the original string unchanged if no YAML patterns are detected\n * or if the repair itself would produce invalid JSON.\n */\nexport function repairToolJson(json: string): string {\n\tif (!hasYamlBulletLists(json)) {\n\t\treturn json;\n\t}\n\n\t// Strategy: find each `\"key\": - item1\\n - item2\\n - item3` region and\n\t// wrap items in a JSON array.\n\t//\n\t// We work on the raw string because the JSON is not parseable yet.\n\t// The pattern we target:\n\t// \"someKey\":\\s*- item text (possibly multiline)\n\t// optionally followed by more `- item` lines\n\t// terminated by the next `\"key\":` or `}` or end of string.\n\n\tlet repaired = json;\n\n\t// Match a key followed by YAML-style bullet list.\n\t// Capture: (1) the key portion including colon, (2) the bullet-list body,\n\t// (3) the separator (comma or empty) before the next key/bracket.\n\t// The bullet list body ends at the next `\"key\":` or `}` or `]` or end of string.\n\tconst keyBulletPattern =\n\t\t/(\"(?:[^\"\\\\]|\\\\.)*\"\\s*:\\s*)(- .+?)(,?\\s*)(?=\"(?:[^\"\\\\]|\\\\.)*\"\\s*:|[}\\]]|$)/gs;\n\n\trepaired = repaired.replace(\n\t\tkeyBulletPattern,\n\t\t(_match, keyPart: string, bulletBody: string, separator: string) => {\n\t\t\t// Split the bullet body into individual items on `- ` boundaries.\n\t\t\t// Items may contain embedded newlines for multi-line values.\n\t\t\tconst items = bulletBody\n\t\t\t\t.split(/\\n?\\s*- /)\n\t\t\t\t.filter((s) => s.trim().length > 0)\n\t\t\t\t.map((s) => s.replace(/,\\s*$/, \"\").trim());\n\n\t\t\t// JSON-encode each item as a string, then wrap in an array.\n\t\t\tconst jsonArray = \"[\" + items.map((item) => JSON.stringify(item)).join(\", \") + \"]\";\n\n\t\t\t// Re-emit the separator (comma) so the next key is properly delimited\n\t\t\tconst sep = separator.trim() ? separator : (/^\\s*\"/.test(separator + \"x\") ? \", \" : \"\");\n\t\t\treturn keyPart + jsonArray + sep;\n\t\t},\n\t);\n\n\t// Strip trailing commas before } or ] (common in repaired JSON)\n\trepaired = repaired.replace(/,(\\s*[}\\]])/g, \"$1\");\n\n\treturn repaired;\n}\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=repair-tool-json.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"repair-tool-json.test.d.ts","sourceRoot":"","sources":["../../../src/utils/tests/repair-tool-json.test.ts"],"names":[],"mappings":""}
@@ -1,73 +0,0 @@
1
- import { describe, test } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { repairToolJson, hasYamlBulletLists } from "../repair-tool-json.js";
4
- describe("repairToolJson — YAML bullet list repair (#2660)", () => {
5
- // ── Detection ──────────────────────────────────────────────────────────
6
- test("hasYamlBulletLists detects YAML-style bullets", () => {
7
- assert.equal(hasYamlBulletLists('"keyDecisions": - Used Web Notification API'), true);
8
- });
9
- test("hasYamlBulletLists ignores negative numbers", () => {
10
- assert.equal(hasYamlBulletLists('"offset": -1'), false, "negative number should not be detected as YAML bullet");
11
- });
12
- test("hasYamlBulletLists returns false for valid JSON", () => {
13
- assert.equal(hasYamlBulletLists('{"keyDecisions": ["item1", "item2"]}'), false);
14
- });
15
- // ── Single bullet item ────────────────────────────────────────────────
16
- test("repairs single YAML bullet to JSON array", () => {
17
- const malformed = '{"keyDecisions": - Used Web Notification API}';
18
- const repaired = repairToolJson(malformed);
19
- const parsed = JSON.parse(repaired);
20
- assert.deepEqual(parsed.keyDecisions, ["Used Web Notification API"]);
21
- });
22
- // ── Multiple bullet items (newline-separated) ─────────────────────────
23
- test("repairs multiple YAML bullets separated by newlines", () => {
24
- const malformed = '{"keyDecisions": - Used Web Notification API\n - Chose Tauri over Electron\n - Adopted SQLite for storage, "title": "M005"}';
25
- const repaired = repairToolJson(malformed);
26
- const parsed = JSON.parse(repaired);
27
- assert.deepEqual(parsed.keyDecisions, [
28
- "Used Web Notification API",
29
- "Chose Tauri over Electron",
30
- "Adopted SQLite for storage",
31
- ]);
32
- assert.equal(parsed.title, "M005");
33
- });
34
- // ── Multiple fields with YAML bullets ─────────────────────────────────
35
- test("repairs multiple fields each with YAML bullet lists", () => {
36
- const malformed = '{"keyDecisions": - decision one\n - decision two, "keyFiles": - src/lib.rs — Extended menu\n - src/main.ts — Entry point, "title": "done"}';
37
- const repaired = repairToolJson(malformed);
38
- const parsed = JSON.parse(repaired);
39
- assert.deepEqual(parsed.keyDecisions, ["decision one", "decision two"]);
40
- assert.deepEqual(parsed.keyFiles, [
41
- "src/lib.rs \u2014 Extended menu",
42
- "src/main.ts \u2014 Entry point",
43
- ]);
44
- assert.equal(parsed.title, "done");
45
- });
46
- // ── Exact reproduction from issue #2660 ───────────────────────────────
47
- test("repairs the exact malformed JSON from issue #2660", () => {
48
- const malformed = `{"milestoneId": "M005", "title": "Native Desktop Polish", "oneLiner": "summary", "narrative": "details", "successCriteriaResults": "all pass", "definitionOfDoneResults": "all done", "requirementOutcomes": "met", "keyDecisions": - Used Web Notification API (new window.Notification()) instead of Tauri sendNotification wrapper, "keyFiles": - src-tauri/src/lib.rs \u2014 Extended menu builder with notification toggle, "lessonsLearned": - Always test notification permissions before sending, "followUps": "none", "deviations": "none", "verificationPassed": true}`;
49
- const repaired = repairToolJson(malformed);
50
- const parsed = JSON.parse(repaired);
51
- assert.equal(parsed.milestoneId, "M005");
52
- assert.equal(parsed.title, "Native Desktop Polish");
53
- assert.ok(Array.isArray(parsed.keyDecisions), "keyDecisions should be an array");
54
- assert.ok(parsed.keyDecisions[0].includes("Web Notification API"));
55
- assert.ok(Array.isArray(parsed.keyFiles), "keyFiles should be an array");
56
- assert.ok(parsed.keyFiles[0].includes("src-tauri/src/lib.rs"));
57
- assert.ok(Array.isArray(parsed.lessonsLearned), "lessonsLearned should be an array");
58
- assert.equal(parsed.verificationPassed, true);
59
- });
60
- // ── Passthrough for valid JSON ────────────────────────────────────────
61
- test("returns valid JSON unchanged", () => {
62
- const valid = '{"keyDecisions": ["item1", "item2"], "count": -5}';
63
- const result = repairToolJson(valid);
64
- assert.equal(result, valid, "valid JSON should be returned unchanged");
65
- });
66
- // ── Negative numbers are preserved ────────────────────────────────────
67
- test("does not mangle negative numbers", () => {
68
- const valid = '{"offset": -1, "limit": -100}';
69
- const result = repairToolJson(valid);
70
- assert.equal(result, valid);
71
- });
72
- });
73
- //# sourceMappingURL=repair-tool-json.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"repair-tool-json.test.js","sourceRoot":"","sources":["../../../src/utils/tests/repair-tool-json.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, test } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { repairToolJson, hasYamlBulletLists } from \"../repair-tool-json.js\";\n\ndescribe(\"repairToolJson — YAML bullet list repair (#2660)\", () => {\n\t// ── Detection ──────────────────────────────────────────────────────────\n\n\ttest(\"hasYamlBulletLists detects YAML-style bullets\", () => {\n\t\tassert.equal(\n\t\t\thasYamlBulletLists('\"keyDecisions\": - Used Web Notification API'),\n\t\t\ttrue,\n\t\t);\n\t});\n\n\ttest(\"hasYamlBulletLists ignores negative numbers\", () => {\n\t\tassert.equal(\n\t\t\thasYamlBulletLists('\"offset\": -1'),\n\t\t\tfalse,\n\t\t\t\"negative number should not be detected as YAML bullet\",\n\t\t);\n\t});\n\n\ttest(\"hasYamlBulletLists returns false for valid JSON\", () => {\n\t\tassert.equal(\n\t\t\thasYamlBulletLists('{\"keyDecisions\": [\"item1\", \"item2\"]}'),\n\t\t\tfalse,\n\t\t);\n\t});\n\n\t// ── Single bullet item ────────────────────────────────────────────────\n\n\ttest(\"repairs single YAML bullet to JSON array\", () => {\n\t\tconst malformed = '{\"keyDecisions\": - Used Web Notification API}';\n\t\tconst repaired = repairToolJson(malformed);\n\t\tconst parsed = JSON.parse(repaired);\n\t\tassert.deepEqual(parsed.keyDecisions, [\"Used Web Notification API\"]);\n\t});\n\n\t// ── Multiple bullet items (newline-separated) ─────────────────────────\n\n\ttest(\"repairs multiple YAML bullets separated by newlines\", () => {\n\t\tconst malformed =\n\t\t\t'{\"keyDecisions\": - Used Web Notification API\\n - Chose Tauri over Electron\\n - Adopted SQLite for storage, \"title\": \"M005\"}';\n\t\tconst repaired = repairToolJson(malformed);\n\t\tconst parsed = JSON.parse(repaired);\n\t\tassert.deepEqual(parsed.keyDecisions, [\n\t\t\t\"Used Web Notification API\",\n\t\t\t\"Chose Tauri over Electron\",\n\t\t\t\"Adopted SQLite for storage\",\n\t\t]);\n\t\tassert.equal(parsed.title, \"M005\");\n\t});\n\n\t// ── Multiple fields with YAML bullets ─────────────────────────────────\n\n\ttest(\"repairs multiple fields each with YAML bullet lists\", () => {\n\t\tconst malformed =\n\t\t\t'{\"keyDecisions\": - decision one\\n - decision two, \"keyFiles\": - src/lib.rs — Extended menu\\n - src/main.ts — Entry point, \"title\": \"done\"}';\n\t\tconst repaired = repairToolJson(malformed);\n\t\tconst parsed = JSON.parse(repaired);\n\t\tassert.deepEqual(parsed.keyDecisions, [\"decision one\", \"decision two\"]);\n\t\tassert.deepEqual(parsed.keyFiles, [\n\t\t\t\"src/lib.rs \\u2014 Extended menu\",\n\t\t\t\"src/main.ts \\u2014 Entry point\",\n\t\t]);\n\t\tassert.equal(parsed.title, \"done\");\n\t});\n\n\t// ── Exact reproduction from issue #2660 ───────────────────────────────\n\n\ttest(\"repairs the exact malformed JSON from issue #2660\", () => {\n\t\tconst malformed = `{\"milestoneId\": \"M005\", \"title\": \"Native Desktop Polish\", \"oneLiner\": \"summary\", \"narrative\": \"details\", \"successCriteriaResults\": \"all pass\", \"definitionOfDoneResults\": \"all done\", \"requirementOutcomes\": \"met\", \"keyDecisions\": - Used Web Notification API (new window.Notification()) instead of Tauri sendNotification wrapper, \"keyFiles\": - src-tauri/src/lib.rs \\u2014 Extended menu builder with notification toggle, \"lessonsLearned\": - Always test notification permissions before sending, \"followUps\": \"none\", \"deviations\": \"none\", \"verificationPassed\": true}`;\n\n\t\tconst repaired = repairToolJson(malformed);\n\t\tconst parsed = JSON.parse(repaired);\n\n\t\tassert.equal(parsed.milestoneId, \"M005\");\n\t\tassert.equal(parsed.title, \"Native Desktop Polish\");\n\t\tassert.ok(Array.isArray(parsed.keyDecisions), \"keyDecisions should be an array\");\n\t\tassert.ok(parsed.keyDecisions[0].includes(\"Web Notification API\"));\n\t\tassert.ok(Array.isArray(parsed.keyFiles), \"keyFiles should be an array\");\n\t\tassert.ok(parsed.keyFiles[0].includes(\"src-tauri/src/lib.rs\"));\n\t\tassert.ok(Array.isArray(parsed.lessonsLearned), \"lessonsLearned should be an array\");\n\t\tassert.equal(parsed.verificationPassed, true);\n\t});\n\n\t// ── Passthrough for valid JSON ────────────────────────────────────────\n\n\ttest(\"returns valid JSON unchanged\", () => {\n\t\tconst valid = '{\"keyDecisions\": [\"item1\", \"item2\"], \"count\": -5}';\n\t\tconst result = repairToolJson(valid);\n\t\tassert.equal(result, valid, \"valid JSON should be returned unchanged\");\n\t});\n\n\t// ── Negative numbers are preserved ────────────────────────────────────\n\n\ttest(\"does not mangle negative numbers\", () => {\n\t\tconst valid = '{\"offset\": -1, \"limit\": -100}';\n\t\tconst result = repairToolJson(valid);\n\t\tassert.equal(result, valid);\n\t});\n});\n"]}
@@ -1,29 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { mapStopReason } from "./anthropic-shared.js";
4
-
5
- describe("mapStopReason", () => {
6
- it("maps end_turn to stop", () => {
7
- assert.equal(mapStopReason("end_turn"), "stop");
8
- });
9
-
10
- it("maps max_tokens to length", () => {
11
- assert.equal(mapStopReason("max_tokens"), "length");
12
- });
13
-
14
- it("maps tool_use to toolUse", () => {
15
- assert.equal(mapStopReason("tool_use"), "toolUse");
16
- });
17
-
18
- it("maps pause_turn to pauseTurn (not stop)", () => {
19
- // pause_turn means the server paused a long-running turn (e.g. native
20
- // web search hit its iteration limit). Mapping it to "stop" causes the
21
- // agent loop to exit, leaving an incomplete server_tool_use block in
22
- // history which triggers a 400 on the next request.
23
- assert.equal(mapStopReason("pause_turn"), "pauseTurn");
24
- });
25
-
26
- it("throws on unknown stop reason", () => {
27
- assert.throws(() => mapStopReason("bogus"), /Unhandled stop reason/);
28
- });
29
- });
@@ -1,88 +0,0 @@
1
- /**
2
- * Repair malformed JSON in LLM tool-call arguments.
3
- *
4
- * LLMs sometimes copy YAML template formatting into JSON tool arguments,
5
- * producing patterns like:
6
- *
7
- * "keyDecisions": - Used Web Notification API...,
8
- * "keyFiles": - src-tauri/src/lib.rs — Extended...
9
- *
10
- * instead of valid JSON arrays:
11
- *
12
- * "keyDecisions": ["Used Web Notification API..."],
13
- * "keyFiles": ["src-tauri/src/lib.rs — Extended..."]
14
- *
15
- * This module detects and repairs such patterns before JSON.parse is called.
16
- *
17
- * @see https://github.com/gsd-build/gsd-2/issues/2660
18
- */
19
-
20
- /**
21
- * Detect whether a JSON string contains YAML-style bullet-list values
22
- * (i.e. `"key": - item` instead of `"key": ["item"]`).
23
- */
24
- export function hasYamlBulletLists(json: string): boolean {
25
- // Match: "key": followed by whitespace then a dash-space pattern (YAML bullet)
26
- // The negative lookahead excludes negative numbers (e.g. "key": -1)
27
- return /"\s*:\s*-\s+(?!\d)/.test(json);
28
- }
29
-
30
- /**
31
- * Attempt to repair YAML-style bullet lists embedded in a JSON string.
32
- *
33
- * Converts patterns like:
34
- * "keyDecisions": - Used Web Notification API..., "keyFiles": - file1
35
- *
36
- * Into:
37
- * "keyDecisions": ["Used Web Notification API..."], "keyFiles": ["file1"]
38
- *
39
- * Returns the original string unchanged if no YAML patterns are detected
40
- * or if the repair itself would produce invalid JSON.
41
- */
42
- export function repairToolJson(json: string): string {
43
- if (!hasYamlBulletLists(json)) {
44
- return json;
45
- }
46
-
47
- // Strategy: find each `"key": - item1\n - item2\n - item3` region and
48
- // wrap items in a JSON array.
49
- //
50
- // We work on the raw string because the JSON is not parseable yet.
51
- // The pattern we target:
52
- // "someKey":\s*- item text (possibly multiline)
53
- // optionally followed by more `- item` lines
54
- // terminated by the next `"key":` or `}` or end of string.
55
-
56
- let repaired = json;
57
-
58
- // Match a key followed by YAML-style bullet list.
59
- // Capture: (1) the key portion including colon, (2) the bullet-list body,
60
- // (3) the separator (comma or empty) before the next key/bracket.
61
- // The bullet list body ends at the next `"key":` or `}` or `]` or end of string.
62
- const keyBulletPattern =
63
- /("(?:[^"\\]|\\.)*"\s*:\s*)(- .+?)(,?\s*)(?="(?:[^"\\]|\\.)*"\s*:|[}\]]|$)/gs;
64
-
65
- repaired = repaired.replace(
66
- keyBulletPattern,
67
- (_match, keyPart: string, bulletBody: string, separator: string) => {
68
- // Split the bullet body into individual items on `- ` boundaries.
69
- // Items may contain embedded newlines for multi-line values.
70
- const items = bulletBody
71
- .split(/\n?\s*- /)
72
- .filter((s) => s.trim().length > 0)
73
- .map((s) => s.replace(/,\s*$/, "").trim());
74
-
75
- // JSON-encode each item as a string, then wrap in an array.
76
- const jsonArray = "[" + items.map((item) => JSON.stringify(item)).join(", ") + "]";
77
-
78
- // Re-emit the separator (comma) so the next key is properly delimited
79
- const sep = separator.trim() ? separator : (/^\s*"/.test(separator + "x") ? ", " : "");
80
- return keyPart + jsonArray + sep;
81
- },
82
- );
83
-
84
- // Strip trailing commas before } or ] (common in repaired JSON)
85
- repaired = repaired.replace(/,(\s*[}\]])/g, "$1");
86
-
87
- return repaired;
88
- }
@@ -1,102 +0,0 @@
1
- import { describe, test } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { repairToolJson, hasYamlBulletLists } from "../repair-tool-json.js";
4
-
5
- describe("repairToolJson — YAML bullet list repair (#2660)", () => {
6
- // ── Detection ──────────────────────────────────────────────────────────
7
-
8
- test("hasYamlBulletLists detects YAML-style bullets", () => {
9
- assert.equal(
10
- hasYamlBulletLists('"keyDecisions": - Used Web Notification API'),
11
- true,
12
- );
13
- });
14
-
15
- test("hasYamlBulletLists ignores negative numbers", () => {
16
- assert.equal(
17
- hasYamlBulletLists('"offset": -1'),
18
- false,
19
- "negative number should not be detected as YAML bullet",
20
- );
21
- });
22
-
23
- test("hasYamlBulletLists returns false for valid JSON", () => {
24
- assert.equal(
25
- hasYamlBulletLists('{"keyDecisions": ["item1", "item2"]}'),
26
- false,
27
- );
28
- });
29
-
30
- // ── Single bullet item ────────────────────────────────────────────────
31
-
32
- test("repairs single YAML bullet to JSON array", () => {
33
- const malformed = '{"keyDecisions": - Used Web Notification API}';
34
- const repaired = repairToolJson(malformed);
35
- const parsed = JSON.parse(repaired);
36
- assert.deepEqual(parsed.keyDecisions, ["Used Web Notification API"]);
37
- });
38
-
39
- // ── Multiple bullet items (newline-separated) ─────────────────────────
40
-
41
- test("repairs multiple YAML bullets separated by newlines", () => {
42
- const malformed =
43
- '{"keyDecisions": - Used Web Notification API\n - Chose Tauri over Electron\n - Adopted SQLite for storage, "title": "M005"}';
44
- const repaired = repairToolJson(malformed);
45
- const parsed = JSON.parse(repaired);
46
- assert.deepEqual(parsed.keyDecisions, [
47
- "Used Web Notification API",
48
- "Chose Tauri over Electron",
49
- "Adopted SQLite for storage",
50
- ]);
51
- assert.equal(parsed.title, "M005");
52
- });
53
-
54
- // ── Multiple fields with YAML bullets ─────────────────────────────────
55
-
56
- test("repairs multiple fields each with YAML bullet lists", () => {
57
- const malformed =
58
- '{"keyDecisions": - decision one\n - decision two, "keyFiles": - src/lib.rs — Extended menu\n - src/main.ts — Entry point, "title": "done"}';
59
- const repaired = repairToolJson(malformed);
60
- const parsed = JSON.parse(repaired);
61
- assert.deepEqual(parsed.keyDecisions, ["decision one", "decision two"]);
62
- assert.deepEqual(parsed.keyFiles, [
63
- "src/lib.rs \u2014 Extended menu",
64
- "src/main.ts \u2014 Entry point",
65
- ]);
66
- assert.equal(parsed.title, "done");
67
- });
68
-
69
- // ── Exact reproduction from issue #2660 ───────────────────────────────
70
-
71
- test("repairs the exact malformed JSON from issue #2660", () => {
72
- const malformed = `{"milestoneId": "M005", "title": "Native Desktop Polish", "oneLiner": "summary", "narrative": "details", "successCriteriaResults": "all pass", "definitionOfDoneResults": "all done", "requirementOutcomes": "met", "keyDecisions": - Used Web Notification API (new window.Notification()) instead of Tauri sendNotification wrapper, "keyFiles": - src-tauri/src/lib.rs \u2014 Extended menu builder with notification toggle, "lessonsLearned": - Always test notification permissions before sending, "followUps": "none", "deviations": "none", "verificationPassed": true}`;
73
-
74
- const repaired = repairToolJson(malformed);
75
- const parsed = JSON.parse(repaired);
76
-
77
- assert.equal(parsed.milestoneId, "M005");
78
- assert.equal(parsed.title, "Native Desktop Polish");
79
- assert.ok(Array.isArray(parsed.keyDecisions), "keyDecisions should be an array");
80
- assert.ok(parsed.keyDecisions[0].includes("Web Notification API"));
81
- assert.ok(Array.isArray(parsed.keyFiles), "keyFiles should be an array");
82
- assert.ok(parsed.keyFiles[0].includes("src-tauri/src/lib.rs"));
83
- assert.ok(Array.isArray(parsed.lessonsLearned), "lessonsLearned should be an array");
84
- assert.equal(parsed.verificationPassed, true);
85
- });
86
-
87
- // ── Passthrough for valid JSON ────────────────────────────────────────
88
-
89
- test("returns valid JSON unchanged", () => {
90
- const valid = '{"keyDecisions": ["item1", "item2"], "count": -5}';
91
- const result = repairToolJson(valid);
92
- assert.equal(result, valid, "valid JSON should be returned unchanged");
93
- });
94
-
95
- // ── Negative numbers are preserved ────────────────────────────────────
96
-
97
- test("does not mangle negative numbers", () => {
98
- const valid = '{"offset": -1, "limit": -100}';
99
- const result = repairToolJson(valid);
100
- assert.equal(result, valid);
101
- });
102
- });
@@ -1,6 +0,0 @@
1
- /**
2
- * Tests for chunked compaction fallback when messages exceed model context window.
3
- * Regression test for #2932.
4
- */
5
- export {};
6
- //# sourceMappingURL=compaction.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compaction.test.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -1,176 +0,0 @@
1
- /**
2
- * Tests for chunked compaction fallback when messages exceed model context window.
3
- * Regression test for #2932.
4
- */
5
- import assert from "node:assert/strict";
6
- import { describe, it, mock } from "node:test";
7
- import { generateSummary, estimateTokens, chunkMessages } from "./compaction.js";
8
- // ---------------------------------------------------------------------------
9
- // Helpers
10
- // ---------------------------------------------------------------------------
11
- /** Create a user message with approximately `tokenCount` tokens (chars = tokens * 4). */
12
- function makeUserMessage(tokenCount) {
13
- const text = "x".repeat(tokenCount * 4);
14
- return { role: "user", content: text };
15
- }
16
- /** Create a mock model with a given context window. */
17
- function makeModel(contextWindow) {
18
- return {
19
- id: "test-model",
20
- name: "Test Model",
21
- api: "anthropic-messages",
22
- provider: "anthropic",
23
- baseUrl: "https://api.test",
24
- reasoning: false,
25
- input: ["text"],
26
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
27
- contextWindow,
28
- maxTokens: 4096,
29
- };
30
- }
31
- function makeFakeResponse(text) {
32
- return {
33
- content: [{ type: "text", text }],
34
- stopReason: "end_turn",
35
- };
36
- }
37
- // ---------------------------------------------------------------------------
38
- // chunkMessages tests
39
- // ---------------------------------------------------------------------------
40
- describe("chunkMessages", () => {
41
- it("returns a single chunk when messages fit in budget", () => {
42
- const messages = [
43
- makeUserMessage(1_000),
44
- makeUserMessage(1_000),
45
- ];
46
- const chunks = chunkMessages(messages, 100_000);
47
- assert.equal(chunks.length, 1);
48
- assert.equal(chunks[0].length, 2);
49
- });
50
- it("splits messages into multiple chunks when they exceed budget", () => {
51
- const messages = [
52
- makeUserMessage(50_000),
53
- makeUserMessage(50_000),
54
- makeUserMessage(50_000),
55
- ];
56
- // Budget of 80k tokens means each 50k message gets its own chunk
57
- // (or two fit together if budget allows)
58
- const chunks = chunkMessages(messages, 80_000);
59
- assert.ok(chunks.length > 1, `Expected multiple chunks, got ${chunks.length}`);
60
- // All messages should be present across chunks
61
- const totalMessages = chunks.reduce((sum, c) => sum + c.length, 0);
62
- assert.equal(totalMessages, 3);
63
- });
64
- it("puts a single oversized message in its own chunk", () => {
65
- const messages = [
66
- makeUserMessage(200_000), // Way over any reasonable budget
67
- ];
68
- const chunks = chunkMessages(messages, 80_000);
69
- assert.equal(chunks.length, 1);
70
- assert.equal(chunks[0].length, 1);
71
- });
72
- it("preserves message order across chunks", () => {
73
- // Create messages with identifiable sizes
74
- const messages = [
75
- makeUserMessage(30_000), // ~30k tokens
76
- makeUserMessage(30_000),
77
- makeUserMessage(30_000),
78
- makeUserMessage(30_000),
79
- ];
80
- const chunks = chunkMessages(messages, 50_000);
81
- // Reconstruct original order
82
- const flat = chunks.flat();
83
- assert.equal(flat.length, 4);
84
- for (let i = 0; i < flat.length; i++) {
85
- assert.strictEqual(flat[i], messages[i], `Message ${i} should be in order`);
86
- }
87
- });
88
- });
89
- // ---------------------------------------------------------------------------
90
- // generateSummary chunked fallback tests
91
- // ---------------------------------------------------------------------------
92
- describe("generateSummary — chunked fallback (#2932)", () => {
93
- it("calls _completeFn multiple times when messages exceed model context window", async () => {
94
- // Arrange: 3 messages of ~80k tokens each = ~240k total, model has 200k window
95
- const messages = [
96
- makeUserMessage(80_000),
97
- makeUserMessage(80_000),
98
- makeUserMessage(80_000),
99
- ];
100
- const model = makeModel(200_000);
101
- const reserveTokens = 16_384;
102
- // Verify our test setup: messages really do exceed the model window
103
- let totalTokens = 0;
104
- for (const m of messages)
105
- totalTokens += estimateTokens(m);
106
- assert.ok(totalTokens > model.contextWindow, `Test setup: ${totalTokens} tokens should exceed ${model.contextWindow} context window`);
107
- // Track calls
108
- const calls = [];
109
- const mockComplete = mock.fn(async (_model, context, _options) => {
110
- const userMsg = context.messages?.[0];
111
- const text = typeof userMsg?.content === "string"
112
- ? userMsg.content
113
- : userMsg?.content?.[0]?.text ?? "";
114
- if (text.includes("<previous-summary>")) {
115
- calls.push("update");
116
- }
117
- else {
118
- calls.push("initial");
119
- }
120
- return makeFakeResponse("Summary of chunk");
121
- });
122
- const summary = await generateSummary(messages, model, reserveTokens, undefined, // apiKey
123
- undefined, // signal
124
- undefined, // customInstructions
125
- undefined, // previousSummary
126
- mockComplete);
127
- // Assert: should have called completeSimple more than once (chunked)
128
- assert.ok(mockComplete.mock.callCount() > 1, `Expected multiple calls for chunked summarization, got ${mockComplete.mock.callCount()}`);
129
- // First call should be an initial summary, subsequent should be updates
130
- assert.equal(calls[0], "initial", "First chunk should use initial summarization prompt");
131
- for (let i = 1; i < calls.length; i++) {
132
- assert.equal(calls[i], "update", `Chunk ${i + 1} should use update summarization prompt`);
133
- }
134
- // Should return a non-empty summary
135
- assert.ok(summary.length > 0, "Summary should not be empty");
136
- });
137
- it("uses single-pass when messages fit within model context window", async () => {
138
- const messages = [
139
- makeUserMessage(10_000),
140
- makeUserMessage(10_000),
141
- ];
142
- const model = makeModel(200_000);
143
- const reserveTokens = 16_384;
144
- // Verify test setup
145
- let totalTokens = 0;
146
- for (const m of messages)
147
- totalTokens += estimateTokens(m);
148
- assert.ok(totalTokens < model.contextWindow, `Test setup: ${totalTokens} tokens should fit in ${model.contextWindow} context window`);
149
- const mockComplete = mock.fn(async () => makeFakeResponse("Single pass summary"));
150
- await generateSummary(messages, model, reserveTokens, undefined, undefined, undefined, undefined, mockComplete);
151
- assert.equal(mockComplete.mock.callCount(), 1, "Should use single-pass summarization when messages fit in context window");
152
- });
153
- it("passes previousSummary through chunked summarization", async () => {
154
- const messages = [
155
- makeUserMessage(80_000),
156
- makeUserMessage(80_000),
157
- makeUserMessage(80_000),
158
- ];
159
- const model = makeModel(200_000);
160
- const reserveTokens = 16_384;
161
- const previousSummary = "Previous session summary content";
162
- const prompts = [];
163
- const mockComplete = mock.fn(async (_model, context) => {
164
- const userMsg = context.messages?.[0];
165
- const text = typeof userMsg?.content === "string"
166
- ? userMsg.content
167
- : userMsg?.content?.[0]?.text ?? "";
168
- prompts.push(text);
169
- return makeFakeResponse("Chunk summary");
170
- });
171
- await generateSummary(messages, model, reserveTokens, undefined, undefined, undefined, previousSummary, mockComplete);
172
- // First chunk should include the previousSummary
173
- assert.ok(prompts[0].includes(previousSummary), "First chunk should incorporate the previousSummary");
174
- });
175
- });
176
- //# sourceMappingURL=compaction.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"compaction.test.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tests for chunked compaction fallback when messages exceed model context window.\n * Regression test for #2932.\n */\n\nimport assert from \"node:assert/strict\";\nimport { describe, it, mock } from \"node:test\";\n\nimport type { AgentMessage } from \"@gsd/pi-agent-core\";\nimport type { Model, AssistantMessage } from \"@gsd/pi-ai\";\n\nimport { generateSummary, estimateTokens, chunkMessages } from \"./compaction.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Create a user message with approximately `tokenCount` tokens (chars = tokens * 4). */\nfunction makeUserMessage(tokenCount: number): AgentMessage {\n\tconst text = \"x\".repeat(tokenCount * 4);\n\treturn { role: \"user\", content: text } as unknown as AgentMessage;\n}\n\n/** Create a mock model with a given context window. */\nfunction makeModel(contextWindow: number): Model<any> {\n\treturn {\n\t\tid: \"test-model\",\n\t\tname: \"Test Model\",\n\t\tapi: \"anthropic-messages\",\n\t\tprovider: \"anthropic\",\n\t\tbaseUrl: \"https://api.test\",\n\t\treasoning: false,\n\t\tinput: [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow,\n\t\tmaxTokens: 4096,\n\t} as Model<any>;\n}\n\nfunction makeFakeResponse(text: string): AssistantMessage {\n\treturn {\n\t\tcontent: [{ type: \"text\", text }],\n\t\tstopReason: \"end_turn\",\n\t} as unknown as AssistantMessage;\n}\n\n// ---------------------------------------------------------------------------\n// chunkMessages tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"chunkMessages\", () => {\n\tit(\"returns a single chunk when messages fit in budget\", () => {\n\t\tconst messages: AgentMessage[] = [\n\t\t\tmakeUserMessage(1_000),\n\t\t\tmakeUserMessage(1_000),\n\t\t];\n\t\tconst chunks = chunkMessages(messages, 100_000);\n\t\tassert.equal(chunks.length, 1);\n\t\tassert.equal(chunks[0].length, 2);\n\t});\n\n\tit(\"splits messages into multiple chunks when they exceed budget\", () => {\n\t\tconst messages: AgentMessage[] = [\n\t\t\tmakeUserMessage(50_000),\n\t\t\tmakeUserMessage(50_000),\n\t\t\tmakeUserMessage(50_000),\n\t\t];\n\t\t// Budget of 80k tokens means each 50k message gets its own chunk\n\t\t// (or two fit together if budget allows)\n\t\tconst chunks = chunkMessages(messages, 80_000);\n\t\tassert.ok(chunks.length > 1, `Expected multiple chunks, got ${chunks.length}`);\n\t\t// All messages should be present across chunks\n\t\tconst totalMessages = chunks.reduce((sum, c) => sum + c.length, 0);\n\t\tassert.equal(totalMessages, 3);\n\t});\n\n\tit(\"puts a single oversized message in its own chunk\", () => {\n\t\tconst messages: AgentMessage[] = [\n\t\t\tmakeUserMessage(200_000), // Way over any reasonable budget\n\t\t];\n\t\tconst chunks = chunkMessages(messages, 80_000);\n\t\tassert.equal(chunks.length, 1);\n\t\tassert.equal(chunks[0].length, 1);\n\t});\n\n\tit(\"preserves message order across chunks\", () => {\n\t\t// Create messages with identifiable sizes\n\t\tconst messages: AgentMessage[] = [\n\t\t\tmakeUserMessage(30_000), // ~30k tokens\n\t\t\tmakeUserMessage(30_000),\n\t\t\tmakeUserMessage(30_000),\n\t\t\tmakeUserMessage(30_000),\n\t\t];\n\t\tconst chunks = chunkMessages(messages, 50_000);\n\t\t// Reconstruct original order\n\t\tconst flat = chunks.flat();\n\t\tassert.equal(flat.length, 4);\n\t\tfor (let i = 0; i < flat.length; i++) {\n\t\t\tassert.strictEqual(flat[i], messages[i], `Message ${i} should be in order`);\n\t\t}\n\t});\n});\n\n// ---------------------------------------------------------------------------\n// generateSummary chunked fallback tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"generateSummary — chunked fallback (#2932)\", () => {\n\tit(\"calls _completeFn multiple times when messages exceed model context window\", async () => {\n\t\t// Arrange: 3 messages of ~80k tokens each = ~240k total, model has 200k window\n\t\tconst messages: AgentMessage[] = [\n\t\t\tmakeUserMessage(80_000),\n\t\t\tmakeUserMessage(80_000),\n\t\t\tmakeUserMessage(80_000),\n\t\t];\n\t\tconst model = makeModel(200_000);\n\t\tconst reserveTokens = 16_384;\n\n\t\t// Verify our test setup: messages really do exceed the model window\n\t\tlet totalTokens = 0;\n\t\tfor (const m of messages) totalTokens += estimateTokens(m);\n\t\tassert.ok(\n\t\t\ttotalTokens > model.contextWindow,\n\t\t\t`Test setup: ${totalTokens} tokens should exceed ${model.contextWindow} context window`,\n\t\t);\n\n\t\t// Track calls\n\t\tconst calls: string[] = [];\n\t\tconst mockComplete = mock.fn(async (_model: any, context: any, _options: any) => {\n\t\t\tconst userMsg = context.messages?.[0];\n\t\t\tconst text =\n\t\t\t\ttypeof userMsg?.content === \"string\"\n\t\t\t\t\t? userMsg.content\n\t\t\t\t\t: userMsg?.content?.[0]?.text ?? \"\";\n\n\t\t\tif (text.includes(\"<previous-summary>\")) {\n\t\t\t\tcalls.push(\"update\");\n\t\t\t} else {\n\t\t\t\tcalls.push(\"initial\");\n\t\t\t}\n\t\t\treturn makeFakeResponse(\"Summary of chunk\");\n\t\t});\n\n\t\tconst summary = await generateSummary(\n\t\t\tmessages,\n\t\t\tmodel,\n\t\t\treserveTokens,\n\t\t\tundefined, // apiKey\n\t\t\tundefined, // signal\n\t\t\tundefined, // customInstructions\n\t\t\tundefined, // previousSummary\n\t\t\tmockComplete, // _completeFn override for testing\n\t\t);\n\n\t\t// Assert: should have called completeSimple more than once (chunked)\n\t\tassert.ok(\n\t\t\tmockComplete.mock.callCount() > 1,\n\t\t\t`Expected multiple calls for chunked summarization, got ${mockComplete.mock.callCount()}`,\n\t\t);\n\n\t\t// First call should be an initial summary, subsequent should be updates\n\t\tassert.equal(calls[0], \"initial\", \"First chunk should use initial summarization prompt\");\n\t\tfor (let i = 1; i < calls.length; i++) {\n\t\t\tassert.equal(calls[i], \"update\", `Chunk ${i + 1} should use update summarization prompt`);\n\t\t}\n\n\t\t// Should return a non-empty summary\n\t\tassert.ok(summary.length > 0, \"Summary should not be empty\");\n\t});\n\n\tit(\"uses single-pass when messages fit within model context window\", async () => {\n\t\tconst messages: AgentMessage[] = [\n\t\t\tmakeUserMessage(10_000),\n\t\t\tmakeUserMessage(10_000),\n\t\t];\n\t\tconst model = makeModel(200_000);\n\t\tconst reserveTokens = 16_384;\n\n\t\t// Verify test setup\n\t\tlet totalTokens = 0;\n\t\tfor (const m of messages) totalTokens += estimateTokens(m);\n\t\tassert.ok(\n\t\t\ttotalTokens < model.contextWindow,\n\t\t\t`Test setup: ${totalTokens} tokens should fit in ${model.contextWindow} context window`,\n\t\t);\n\n\t\tconst mockComplete = mock.fn(async () => makeFakeResponse(\"Single pass summary\"));\n\n\t\tawait generateSummary(messages, model, reserveTokens, undefined, undefined, undefined, undefined, mockComplete);\n\n\t\tassert.equal(\n\t\t\tmockComplete.mock.callCount(),\n\t\t\t1,\n\t\t\t\"Should use single-pass summarization when messages fit in context window\",\n\t\t);\n\t});\n\n\tit(\"passes previousSummary through chunked summarization\", async () => {\n\t\tconst messages: AgentMessage[] = [\n\t\t\tmakeUserMessage(80_000),\n\t\t\tmakeUserMessage(80_000),\n\t\t\tmakeUserMessage(80_000),\n\t\t];\n\t\tconst model = makeModel(200_000);\n\t\tconst reserveTokens = 16_384;\n\t\tconst previousSummary = \"Previous session summary content\";\n\n\t\tconst prompts: string[] = [];\n\t\tconst mockComplete = mock.fn(async (_model: any, context: any) => {\n\t\t\tconst userMsg = context.messages?.[0];\n\t\t\tconst text =\n\t\t\t\ttypeof userMsg?.content === \"string\"\n\t\t\t\t\t? userMsg.content\n\t\t\t\t\t: userMsg?.content?.[0]?.text ?? \"\";\n\t\t\tprompts.push(text);\n\t\t\treturn makeFakeResponse(\"Chunk summary\");\n\t\t});\n\n\t\tawait generateSummary(\n\t\t\tmessages,\n\t\t\tmodel,\n\t\t\treserveTokens,\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tpreviousSummary,\n\t\t\tmockComplete,\n\t\t);\n\n\t\t// First chunk should include the previousSummary\n\t\tassert.ok(\n\t\t\tprompts[0].includes(previousSummary),\n\t\t\t\"First chunk should incorporate the previousSummary\",\n\t\t);\n\t});\n});\n"]}