gsd-pi 2.57.0-dev.f22a903 → 2.58.0-dev.778d6ac

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 (643) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +49 -35
  3. package/dist/headless-ui.d.ts +17 -0
  4. package/dist/headless-ui.js +97 -3
  5. package/dist/headless.js +67 -6
  6. package/dist/help-text.js +1 -0
  7. package/dist/onboarding.js +44 -0
  8. package/dist/resource-loader.js +16 -1
  9. package/dist/resources/agents/researcher.md +1 -1
  10. package/dist/resources/extensions/ask-user-questions.js +16 -3
  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 +14 -6
  15. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -36
  16. package/dist/resources/extensions/context7/extension-manifest.json +1 -1
  17. package/dist/resources/extensions/get-secrets-from-user.js +8 -5
  18. package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
  19. package/dist/resources/extensions/google-search/index.js +2 -1
  20. package/dist/resources/extensions/gsd/auto/phases.js +25 -21
  21. package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
  22. package/dist/resources/extensions/gsd/auto-dashboard.js +37 -20
  23. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -2
  24. package/dist/resources/extensions/gsd/auto-model-selection.js +26 -3
  25. package/dist/resources/extensions/gsd/auto-post-unit.js +16 -4
  26. package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
  27. package/dist/resources/extensions/gsd/auto-recovery.js +13 -5
  28. package/dist/resources/extensions/gsd/auto-start.js +35 -22
  29. package/dist/resources/extensions/gsd/auto-worktree.js +196 -12
  30. package/dist/resources/extensions/gsd/auto.js +4 -0
  31. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -0
  32. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -8
  33. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -1
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
  35. package/dist/resources/extensions/gsd/bootstrap/system-context.js +44 -11
  36. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -0
  37. package/dist/resources/extensions/gsd/captures.js +56 -4
  38. package/dist/resources/extensions/gsd/db-writer.js +116 -8
  39. package/dist/resources/extensions/gsd/doctor-git-checks.js +28 -0
  40. package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
  41. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +5 -4
  42. package/dist/resources/extensions/gsd/doctor.js +3 -1
  43. package/dist/resources/extensions/gsd/error-classifier.js +13 -10
  44. package/dist/resources/extensions/gsd/extension-manifest.json +16 -1
  45. package/dist/resources/extensions/gsd/forensics.js +123 -20
  46. package/dist/resources/extensions/gsd/git-service.js +23 -1
  47. package/dist/resources/extensions/gsd/gitignore.js +33 -0
  48. package/dist/resources/extensions/gsd/gsd-db.js +36 -9
  49. package/dist/resources/extensions/gsd/guided-flow.js +106 -44
  50. package/dist/resources/extensions/gsd/health-widget-core.js +31 -0
  51. package/dist/resources/extensions/gsd/health-widget.js +17 -0
  52. package/dist/resources/extensions/gsd/index.js +1 -1
  53. package/dist/resources/extensions/gsd/memory-extractor.js +7 -0
  54. package/dist/resources/extensions/gsd/migrate-external.js +8 -1
  55. package/dist/resources/extensions/gsd/milestone-validation-gates.js +45 -0
  56. package/dist/resources/extensions/gsd/model-cost-table.js +18 -0
  57. package/dist/resources/extensions/gsd/model-router.js +35 -1
  58. package/dist/resources/extensions/gsd/native-git-bridge.js +17 -0
  59. package/dist/resources/extensions/gsd/notifications.js +16 -1
  60. package/dist/resources/extensions/gsd/parallel-eligibility.js +13 -2
  61. package/dist/resources/extensions/gsd/parallel-merge.js +78 -5
  62. package/dist/resources/extensions/gsd/parsers-legacy.js +20 -3
  63. package/dist/resources/extensions/gsd/paths.js +43 -0
  64. package/dist/resources/extensions/gsd/preferences-models.js +14 -1
  65. package/dist/resources/extensions/gsd/preferences-types.js +2 -1
  66. package/dist/resources/extensions/gsd/preferences.js +13 -16
  67. package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
  68. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -2
  70. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  71. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  72. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
  73. package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
  74. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  75. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -0
  77. package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -0
  79. package/dist/resources/extensions/gsd/repo-identity.js +205 -11
  80. package/dist/resources/extensions/gsd/rethink.js +5 -0
  81. package/dist/resources/extensions/gsd/roadmap-slices.js +5 -4
  82. package/dist/resources/extensions/gsd/state.js +85 -27
  83. package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
  84. package/dist/resources/extensions/gsd/tools/complete-task.js +34 -71
  85. package/dist/resources/extensions/gsd/tools/plan-milestone.js +12 -2
  86. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +29 -1
  87. package/dist/resources/extensions/gsd/tools/validate-milestone.js +14 -3
  88. package/dist/resources/extensions/gsd/triage-resolution.js +22 -7
  89. package/dist/resources/extensions/gsd/undo.js +2 -2
  90. package/dist/resources/extensions/gsd/unit-ownership.js +164 -33
  91. package/dist/resources/extensions/gsd/verdict-parser.js +20 -8
  92. package/dist/resources/extensions/gsd/workflow-manifest.js +24 -5
  93. package/dist/resources/extensions/gsd/workflow-projections.js +95 -63
  94. package/dist/resources/extensions/gsd/workflow-reconcile.js +35 -5
  95. package/dist/resources/extensions/gsd/workspace-index.js +24 -0
  96. package/dist/resources/extensions/gsd/worktree-manager.js +105 -1
  97. package/dist/resources/extensions/gsd/worktree-resolver.js +20 -3
  98. package/dist/resources/extensions/mcp-client/index.js +11 -7
  99. package/dist/resources/extensions/ollama/index.js +112 -0
  100. package/dist/resources/extensions/ollama/model-capabilities.js +115 -0
  101. package/dist/resources/extensions/ollama/ollama-client.js +168 -0
  102. package/dist/resources/extensions/ollama/ollama-commands.js +194 -0
  103. package/dist/resources/extensions/ollama/ollama-discovery.js +69 -0
  104. package/dist/resources/extensions/ollama/ollama-tool.js +184 -0
  105. package/dist/resources/extensions/ollama/types.js +2 -0
  106. package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
  107. package/dist/resources/extensions/shared/interview-ui.js +11 -1
  108. package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -3
  109. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
  110. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  111. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  112. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
  113. package/dist/startup-model-validation.d.ts +39 -0
  114. package/dist/startup-model-validation.js +50 -0
  115. package/dist/web/standalone/.next/BUILD_ID +1 -1
  116. package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
  117. package/dist/web/standalone/.next/build-manifest.json +3 -3
  118. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  119. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  122. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.rsc +2 -2
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  135. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  138. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/index.html +1 -1
  193. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  194. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  195. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  196. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  197. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  198. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  199. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
  201. package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
  202. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  205. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  206. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  207. package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
  208. package/dist/web/standalone/.next/static/chunks/{webpack-61d3afac6d0f0ce7.js → webpack-a1c1e452c6b32d04.js} +1 -1
  209. package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
  210. package/dist/web-mode.js +2 -1
  211. package/package.json +2 -2
  212. package/packages/daemon/src/cli.ts +49 -0
  213. package/packages/daemon/src/daemon.test.ts +104 -1
  214. package/packages/daemon/src/daemon.ts +24 -1
  215. package/packages/daemon/src/discord-bot.ts +73 -3
  216. package/packages/daemon/src/event-bridge.ts +15 -9
  217. package/packages/daemon/src/event-formatter.ts +30 -2
  218. package/packages/daemon/src/index.ts +9 -0
  219. package/packages/daemon/src/launchd.test.ts +356 -0
  220. package/packages/daemon/src/launchd.ts +242 -0
  221. package/packages/daemon/src/message-batcher.test.ts +2 -2
  222. package/packages/daemon/src/message-batcher.ts +9 -3
  223. package/packages/daemon/src/orchestrator.test.ts +1 -0
  224. package/packages/daemon/src/orchestrator.ts +106 -2
  225. package/packages/native/dist/ast/index.js +9 -5
  226. package/packages/native/dist/ast/types.js +2 -1
  227. package/packages/native/dist/clipboard/index.js +12 -7
  228. package/packages/native/dist/clipboard/types.js +2 -1
  229. package/packages/native/dist/diff/index.js +12 -7
  230. package/packages/native/dist/diff/types.js +2 -1
  231. package/packages/native/dist/fd/index.js +6 -3
  232. package/packages/native/dist/fd/types.js +2 -1
  233. package/packages/native/dist/glob/index.js +9 -5
  234. package/packages/native/dist/glob/types.js +2 -1
  235. package/packages/native/dist/grep/index.js +9 -5
  236. package/packages/native/dist/grep/types.js +2 -1
  237. package/packages/native/dist/gsd-parser/index.js +18 -11
  238. package/packages/native/dist/gsd-parser/types.js +2 -1
  239. package/packages/native/dist/highlight/index.js +12 -7
  240. package/packages/native/dist/highlight/types.js +2 -1
  241. package/packages/native/dist/html/index.js +6 -3
  242. package/packages/native/dist/html/types.js +2 -1
  243. package/packages/native/dist/image/index.js +10 -5
  244. package/packages/native/dist/image/types.js +7 -4
  245. package/packages/native/dist/index.js +70 -17
  246. package/packages/native/dist/json-parse/index.js +13 -8
  247. package/packages/native/dist/native.js +47 -10
  248. package/packages/native/dist/ps/index.js +15 -9
  249. package/packages/native/dist/ps/types.js +2 -1
  250. package/packages/native/dist/stream-process/index.js +12 -7
  251. package/packages/native/dist/text/index.js +24 -14
  252. package/packages/native/dist/text/types.js +5 -2
  253. package/packages/native/dist/truncate/index.js +12 -7
  254. package/packages/native/dist/ttsr/index.js +12 -7
  255. package/packages/native/dist/ttsr/types.js +2 -1
  256. package/packages/native/dist/xxhash/index.js +9 -5
  257. package/packages/native/package.json +19 -19
  258. package/packages/native/src/__tests__/module-compat.test.mjs +91 -0
  259. package/packages/native/src/native.ts +9 -8
  260. package/packages/pi-agent-core/dist/agent-loop.js +3 -2
  261. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  262. package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
  263. package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
  264. package/packages/pi-agent-core/dist/proxy.js.map +1 -1
  265. package/packages/pi-agent-core/src/agent-loop.test.ts +45 -0
  266. package/packages/pi-agent-core/src/agent-loop.ts +3 -2
  267. package/packages/pi-agent-core/src/proxy.ts +1 -1
  268. package/packages/pi-ai/dist/env-api-keys.js +1 -0
  269. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  270. package/packages/pi-ai/dist/index.d.ts +1 -0
  271. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  272. package/packages/pi-ai/dist/index.js +1 -0
  273. package/packages/pi-ai/dist/index.js.map +1 -1
  274. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  275. package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -2
  276. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  277. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +2 -0
  278. package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +1 -0
  279. package/packages/pi-ai/dist/providers/anthropic-shared.test.js +25 -0
  280. package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -0
  281. package/packages/pi-ai/dist/types.d.ts +3 -3
  282. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  283. package/packages/pi-ai/dist/types.js.map +1 -1
  284. package/packages/pi-ai/dist/utils/json-parse.d.ts +3 -0
  285. package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
  286. package/packages/pi-ai/dist/utils/json-parse.js +24 -1
  287. package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
  288. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +37 -0
  289. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -0
  290. package/packages/pi-ai/dist/utils/repair-tool-json.js +75 -0
  291. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -0
  292. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +2 -0
  293. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +1 -0
  294. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +73 -0
  295. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -0
  296. package/packages/pi-ai/src/env-api-keys.ts +1 -0
  297. package/packages/pi-ai/src/index.ts +1 -0
  298. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +29 -0
  299. package/packages/pi-ai/src/providers/anthropic-shared.ts +17 -2
  300. package/packages/pi-ai/src/types.ts +3 -2
  301. package/packages/pi-ai/src/utils/json-parse.ts +28 -1
  302. package/packages/pi-ai/src/utils/repair-tool-json.ts +88 -0
  303. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +102 -0
  304. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
  305. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/core/agent-session.js +31 -0
  307. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +17 -1
  309. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +62 -2
  311. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +6 -0
  313. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +1 -0
  314. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +176 -0
  315. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -0
  316. package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/core/exec.js +3 -1
  318. package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +28 -0
  320. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +1 -0
  321. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +37 -0
  322. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +1 -0
  323. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +2 -0
  324. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +1 -0
  325. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +63 -0
  326. package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +1 -0
  327. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +19 -0
  328. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +1 -0
  329. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +115 -0
  330. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +1 -0
  331. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +2 -0
  332. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +1 -0
  333. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +109 -0
  334. package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +1 -0
  335. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +4 -0
  336. package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
  337. package/packages/pi-coding-agent/dist/core/extensions/index.js +2 -0
  338. package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
  339. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  340. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  341. package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
  342. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +44 -0
  344. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +1 -0
  345. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +97 -0
  346. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +1 -0
  347. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +2 -0
  348. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +1 -0
  349. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +181 -0
  350. package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +1 -0
  351. package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
  352. package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/core/index.js +1 -1
  354. package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
  356. package/packages/pi-coding-agent/dist/core/lsp/index.js +3 -0
  357. package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
  358. package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
  359. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -0
  360. package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
  361. package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/core/messages.js +31 -2
  363. package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
  364. package/packages/pi-coding-agent/dist/core/messages.test.d.ts +9 -0
  365. package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +1 -0
  366. package/packages/pi-coding-agent/dist/core/messages.test.js +86 -0
  367. package/packages/pi-coding-agent/dist/core/messages.test.js.map +1 -0
  368. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  369. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  370. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  371. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +10 -0
  372. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  373. package/packages/pi-coding-agent/dist/core/resource-loader.js +12 -1
  374. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  375. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +6 -0
  376. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  377. package/packages/pi-coding-agent/dist/core/retry-handler.js +48 -1
  378. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  379. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +9 -0
  380. package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +1 -0
  381. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +193 -0
  382. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -0
  383. package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
  384. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +10 -3
  385. package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
  386. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  387. package/packages/pi-coding-agent/dist/core/tools/read.js +13 -4
  388. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  389. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +16 -0
  390. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +1 -0
  391. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +80 -0
  392. package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -0
  393. package/packages/pi-coding-agent/dist/index.d.ts +2 -2
  394. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  395. package/packages/pi-coding-agent/dist/index.js +1 -1
  396. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  397. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  398. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +4 -0
  399. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  400. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +1 -0
  401. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
  402. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +5 -0
  403. package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
  404. package/packages/pi-coding-agent/package.json +1 -1
  405. package/packages/pi-coding-agent/src/core/agent-session.ts +38 -1
  406. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +236 -0
  407. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +94 -1
  408. package/packages/pi-coding-agent/src/core/exec.ts +3 -1
  409. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
  410. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
  411. package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
  412. package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
  413. package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
  414. package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
  415. package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
  416. package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
  417. package/packages/pi-coding-agent/src/core/index.ts +6 -0
  418. package/packages/pi-coding-agent/src/core/lsp/index.ts +3 -0
  419. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -0
  420. package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
  421. package/packages/pi-coding-agent/src/core/messages.ts +29 -2
  422. package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
  423. package/packages/pi-coding-agent/src/core/resource-loader.ts +20 -1
  424. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +255 -0
  425. package/packages/pi-coding-agent/src/core/retry-handler.ts +52 -1
  426. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +11 -3
  427. package/packages/pi-coding-agent/src/core/tools/read.ts +14 -4
  428. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +92 -0
  429. package/packages/pi-coding-agent/src/index.ts +6 -0
  430. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -0
  431. package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +6 -0
  432. package/packages/pi-tui/dist/terminal.d.ts +2 -0
  433. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  434. package/packages/pi-tui/dist/terminal.js +9 -0
  435. package/packages/pi-tui/dist/terminal.js.map +1 -1
  436. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  437. package/packages/pi-tui/dist/tui.js +9 -0
  438. package/packages/pi-tui/dist/tui.js.map +1 -1
  439. package/packages/pi-tui/src/terminal.ts +14 -0
  440. package/packages/pi-tui/src/tui.ts +8 -0
  441. package/pkg/package.json +1 -1
  442. package/scripts/ensure-workspace-builds.cjs +45 -14
  443. package/src/resources/agents/researcher.md +1 -1
  444. package/src/resources/extensions/ask-user-questions.ts +21 -3
  445. package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
  446. package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
  447. package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
  448. package/src/resources/extensions/claude-code-cli/partial-builder.ts +13 -6
  449. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +63 -35
  450. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +28 -0
  451. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -1
  452. package/src/resources/extensions/context7/extension-manifest.json +1 -1
  453. package/src/resources/extensions/get-secrets-from-user.ts +8 -5
  454. package/src/resources/extensions/google-search/extension-manifest.json +1 -1
  455. package/src/resources/extensions/google-search/index.ts +2 -1
  456. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  457. package/src/resources/extensions/gsd/auto/phases.ts +43 -34
  458. package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
  459. package/src/resources/extensions/gsd/auto-dashboard.ts +37 -19
  460. package/src/resources/extensions/gsd/auto-dispatch.ts +18 -2
  461. package/src/resources/extensions/gsd/auto-model-selection.ts +26 -5
  462. package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
  463. package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
  464. package/src/resources/extensions/gsd/auto-recovery.ts +12 -5
  465. package/src/resources/extensions/gsd/auto-start.ts +35 -26
  466. package/src/resources/extensions/gsd/auto-worktree.ts +190 -9
  467. package/src/resources/extensions/gsd/auto.ts +5 -0
  468. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +31 -0
  469. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +85 -8
  470. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +38 -1
  471. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -19
  472. package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -11
  473. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +75 -0
  474. package/src/resources/extensions/gsd/captures.ts +63 -3
  475. package/src/resources/extensions/gsd/db-writer.ts +140 -7
  476. package/src/resources/extensions/gsd/doctor-git-checks.ts +26 -0
  477. package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
  478. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +5 -4
  479. package/src/resources/extensions/gsd/doctor.ts +3 -1
  480. package/src/resources/extensions/gsd/error-classifier.ts +14 -11
  481. package/src/resources/extensions/gsd/extension-manifest.json +16 -1
  482. package/src/resources/extensions/gsd/forensics.ts +144 -20
  483. package/src/resources/extensions/gsd/git-service.ts +26 -3
  484. package/src/resources/extensions/gsd/gitignore.ts +33 -0
  485. package/src/resources/extensions/gsd/gsd-db.ts +43 -7
  486. package/src/resources/extensions/gsd/guided-flow.ts +114 -45
  487. package/src/resources/extensions/gsd/health-widget-core.ts +34 -0
  488. package/src/resources/extensions/gsd/health-widget.ts +17 -0
  489. package/src/resources/extensions/gsd/index.ts +1 -0
  490. package/src/resources/extensions/gsd/memory-extractor.ts +8 -0
  491. package/src/resources/extensions/gsd/migrate-external.ts +9 -1
  492. package/src/resources/extensions/gsd/milestone-validation-gates.ts +56 -0
  493. package/src/resources/extensions/gsd/model-cost-table.ts +19 -0
  494. package/src/resources/extensions/gsd/model-router.ts +35 -1
  495. package/src/resources/extensions/gsd/native-git-bridge.ts +17 -0
  496. package/src/resources/extensions/gsd/notifications.ts +16 -0
  497. package/src/resources/extensions/gsd/parallel-eligibility.ts +15 -2
  498. package/src/resources/extensions/gsd/parallel-merge.ts +87 -4
  499. package/src/resources/extensions/gsd/parsers-legacy.ts +22 -3
  500. package/src/resources/extensions/gsd/paths.ts +42 -0
  501. package/src/resources/extensions/gsd/preferences-models.ts +14 -1
  502. package/src/resources/extensions/gsd/preferences-types.ts +2 -1
  503. package/src/resources/extensions/gsd/preferences.ts +13 -15
  504. package/src/resources/extensions/gsd/prompt-loader.ts +4 -1
  505. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  506. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -2
  507. package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
  508. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  509. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
  510. package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
  511. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  512. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
  513. package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -0
  514. package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
  515. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -0
  516. package/src/resources/extensions/gsd/repo-identity.ts +186 -11
  517. package/src/resources/extensions/gsd/rethink.ts +6 -0
  518. package/src/resources/extensions/gsd/roadmap-slices.ts +5 -4
  519. package/src/resources/extensions/gsd/state.ts +84 -32
  520. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +47 -0
  521. package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
  522. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +71 -1
  523. package/src/resources/extensions/gsd/tests/captures.test.ts +103 -0
  524. package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
  525. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +27 -0
  526. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +21 -0
  527. package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
  528. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +131 -0
  529. package/src/resources/extensions/gsd/tests/db-writer.test.ts +7 -12
  530. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +78 -5
  531. package/src/resources/extensions/gsd/tests/derive-state.test.ts +29 -0
  532. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
  533. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +127 -0
  534. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +40 -0
  535. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
  536. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +117 -0
  537. package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
  538. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +74 -0
  539. package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
  540. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +129 -0
  541. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +96 -0
  542. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +31 -0
  543. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +125 -12
  544. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +164 -0
  545. package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
  546. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +97 -0
  547. package/src/resources/extensions/gsd/tests/health-widget.test.ts +67 -0
  548. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +107 -0
  549. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +111 -1
  550. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +101 -0
  551. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +59 -0
  552. package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
  553. package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
  554. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +110 -0
  555. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
  556. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +959 -0
  557. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +85 -2
  558. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +105 -0
  559. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
  560. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +34 -0
  561. package/src/resources/extensions/gsd/tests/model-router.test.ts +68 -3
  562. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +28 -0
  563. package/src/resources/extensions/gsd/tests/notifications.test.ts +45 -0
  564. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +159 -0
  565. package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +150 -0
  566. package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +70 -0
  567. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +33 -1
  568. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
  569. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +29 -0
  570. package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
  571. package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
  572. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +38 -0
  573. package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +157 -0
  574. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +90 -0
  575. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +117 -0
  576. package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
  577. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +97 -0
  578. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +134 -0
  579. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +233 -0
  580. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +305 -0
  581. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +405 -0
  582. package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
  583. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1628 -0
  584. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +106 -0
  585. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +174 -0
  586. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +221 -0
  587. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
  588. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +8 -0
  589. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
  590. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +100 -17
  591. package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
  592. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +4 -1
  593. package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
  594. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +82 -0
  595. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +48 -0
  596. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +92 -0
  597. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -2
  598. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +140 -0
  599. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +101 -0
  600. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +48 -1
  601. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +29 -5
  602. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +95 -0
  603. package/src/resources/extensions/gsd/tools/complete-task.ts +36 -74
  604. package/src/resources/extensions/gsd/tools/plan-milestone.ts +13 -1
  605. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +36 -0
  606. package/src/resources/extensions/gsd/tools/validate-milestone.ts +20 -2
  607. package/src/resources/extensions/gsd/triage-resolution.ts +23 -6
  608. package/src/resources/extensions/gsd/types.ts +4 -2
  609. package/src/resources/extensions/gsd/undo.ts +2 -2
  610. package/src/resources/extensions/gsd/unit-ownership.ts +206 -35
  611. package/src/resources/extensions/gsd/verdict-parser.ts +21 -6
  612. package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
  613. package/src/resources/extensions/gsd/workflow-manifest.ts +22 -5
  614. package/src/resources/extensions/gsd/workflow-projections.ts +97 -64
  615. package/src/resources/extensions/gsd/workflow-reconcile.ts +39 -10
  616. package/src/resources/extensions/gsd/workspace-index.ts +30 -0
  617. package/src/resources/extensions/gsd/worktree-manager.ts +120 -1
  618. package/src/resources/extensions/gsd/worktree-resolver.ts +22 -3
  619. package/src/resources/extensions/mcp-client/index.ts +13 -7
  620. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +55 -0
  621. package/src/resources/extensions/ollama/index.ts +130 -0
  622. package/src/resources/extensions/ollama/model-capabilities.ts +145 -0
  623. package/src/resources/extensions/ollama/ollama-client.ts +196 -0
  624. package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
  625. package/src/resources/extensions/ollama/ollama-discovery.ts +106 -0
  626. package/src/resources/extensions/ollama/ollama-tool.ts +218 -0
  627. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +162 -0
  628. package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
  629. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +28 -0
  630. package/src/resources/extensions/ollama/types.ts +130 -0
  631. package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
  632. package/src/resources/extensions/shared/interview-ui.ts +12 -1
  633. package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +156 -0
  634. package/src/resources/skills/create-gsd-extension/SKILL.md +5 -3
  635. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
  636. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
  637. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
  638. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
  639. package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +0 -9
  640. package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +0 -1
  641. package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
  642. /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_buildManifest.js +0 -0
  643. /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_ssgManifest.js +0 -0
@@ -0,0 +1,228 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import {
4
+ isImageDimensionError,
5
+ MANY_IMAGE_MAX_DIMENSION,
6
+ downsizeConversationImages,
7
+ } from "./image-overflow-recovery.js";
8
+ import type { Message } from "@gsd/pi-ai";
9
+
10
+ // ─── isImageDimensionError ────────────────────────────────────────────────────
11
+
12
+ describe("isImageDimensionError", () => {
13
+ it("returns true for Anthropic many-image dimension error", () => {
14
+ const errorMessage =
15
+ 'Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"messages.125.content.38.image.source.base64.data: At least one of the image dimensions exceed max allowed size for many-image requests: 2000 pixels"}}';
16
+ assert.equal(isImageDimensionError(errorMessage), true);
17
+ });
18
+
19
+ it("returns true for bare dimension exceed message", () => {
20
+ const errorMessage =
21
+ "image dimensions exceed max allowed size for many-image requests: 2000 pixels";
22
+ assert.equal(isImageDimensionError(errorMessage), true);
23
+ });
24
+
25
+ it("returns false for unrelated 400 error", () => {
26
+ const errorMessage =
27
+ 'Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"max_tokens: 4096 > 2048"}}';
28
+ assert.equal(isImageDimensionError(errorMessage), false);
29
+ });
30
+
31
+ it("returns false for rate limit error", () => {
32
+ assert.equal(isImageDimensionError("429 rate limit exceeded"), false);
33
+ });
34
+
35
+ it("returns false for empty string", () => {
36
+ assert.equal(isImageDimensionError(""), false);
37
+ });
38
+
39
+ it("returns false for undefined", () => {
40
+ assert.equal(isImageDimensionError(undefined), false);
41
+ });
42
+ });
43
+
44
+ // ─── MANY_IMAGE_MAX_DIMENSION ─────────────────────────────────────────────────
45
+
46
+ describe("MANY_IMAGE_MAX_DIMENSION", () => {
47
+ it("is less than 2000 (the API-enforced limit)", () => {
48
+ assert.ok(MANY_IMAGE_MAX_DIMENSION < 2000);
49
+ });
50
+
51
+ it("is a positive integer", () => {
52
+ assert.ok(MANY_IMAGE_MAX_DIMENSION > 0);
53
+ assert.equal(MANY_IMAGE_MAX_DIMENSION, Math.floor(MANY_IMAGE_MAX_DIMENSION));
54
+ });
55
+ });
56
+
57
+ // ─── helpers ──────────────────────────────────────────────────────────────────
58
+
59
+ function makeUserMsg(content: Message["content"] & any): Message {
60
+ return { role: "user", content, timestamp: Date.now() } as Message;
61
+ }
62
+
63
+ function makeAssistantMsg(text: string): Message {
64
+ return {
65
+ role: "assistant",
66
+ content: [{ type: "text", text }],
67
+ api: "anthropic-messages",
68
+ provider: "anthropic",
69
+ model: "claude-opus-4-6",
70
+ usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
71
+ stopReason: "stop",
72
+ timestamp: Date.now(),
73
+ } as Message;
74
+ }
75
+
76
+ function makeToolResultMsg(images: number): Message {
77
+ const content: any[] = [];
78
+ for (let i = 0; i < images; i++) {
79
+ content.push({ type: "image", data: `img${i}`, mimeType: "image/png" });
80
+ }
81
+ return {
82
+ role: "toolResult",
83
+ toolCallId: `tc${Math.random()}`,
84
+ toolName: "screenshot",
85
+ content,
86
+ isError: false,
87
+ timestamp: Date.now(),
88
+ } as Message;
89
+ }
90
+
91
+ // ─── downsizeConversationImages ───────────────────────────────────────────────
92
+
93
+ describe("downsizeConversationImages", () => {
94
+ it("counts images in user and toolResult messages", () => {
95
+ const messages: Message[] = [
96
+ makeUserMsg([
97
+ { type: "image", data: "img1", mimeType: "image/png" },
98
+ { type: "image", data: "img2", mimeType: "image/png" },
99
+ ]),
100
+ makeAssistantMsg("I see them"),
101
+ makeToolResultMsg(1),
102
+ ];
103
+
104
+ const result = downsizeConversationImages(messages);
105
+ assert.equal(result.imageCount, 3);
106
+ });
107
+
108
+ it("returns processed=false when no images present", () => {
109
+ const messages: Message[] = [
110
+ makeUserMsg("just text"),
111
+ makeAssistantMsg("reply"),
112
+ ];
113
+
114
+ const result = downsizeConversationImages(messages);
115
+ assert.equal(result.imageCount, 0);
116
+ assert.equal(result.processed, false);
117
+ });
118
+
119
+ it("returns processed=false when image count <= RECENT_IMAGES_TO_KEEP", () => {
120
+ const messages: Message[] = [
121
+ makeUserMsg([
122
+ { type: "image", data: "img1", mimeType: "image/png" },
123
+ ]),
124
+ makeAssistantMsg("got it"),
125
+ ];
126
+
127
+ const result = downsizeConversationImages(messages);
128
+ assert.equal(result.imageCount, 1);
129
+ assert.equal(result.processed, false);
130
+ });
131
+
132
+ it("strips older images when many images present, preserves recent ones", () => {
133
+ const messages: Message[] = [];
134
+ for (let i = 0; i < 25; i++) {
135
+ messages.push(
136
+ makeUserMsg([
137
+ { type: "text", text: `message ${i}` },
138
+ { type: "image", data: `img${i}`, mimeType: "image/png" },
139
+ ]),
140
+ );
141
+ messages.push(makeAssistantMsg(`reply ${i}`));
142
+ }
143
+
144
+ const result = downsizeConversationImages(messages);
145
+ assert.ok(result.processed);
146
+ assert.equal(result.imageCount, 25);
147
+ assert.equal(result.strippedCount, 20); // 25 - 5 recent
148
+
149
+ // Count remaining images
150
+ let remainingImages = 0;
151
+ for (const msg of messages) {
152
+ if (msg.role === "assistant") continue;
153
+ if (typeof msg.content === "string") continue;
154
+ const arr = msg.content as any[];
155
+ for (const block of arr) {
156
+ if (block.type === "image") remainingImages++;
157
+ }
158
+ }
159
+ assert.equal(remainingImages, 5, "Should keep exactly 5 most recent images");
160
+
161
+ // The 5 most recent user messages (indices 40,42,44,46,48) should have images
162
+ for (let i = 20; i < 25; i++) {
163
+ const userMsg = messages[i * 2]; // user messages at even indices
164
+ const arr = userMsg.content as any[];
165
+ const hasImage = arr.some((c: any) => c.type === "image");
166
+ assert.ok(hasImage, `Recent message ${i} should retain its image`);
167
+ }
168
+ });
169
+
170
+ it("adds text placeholder when stripping an image", () => {
171
+ const messages: Message[] = [];
172
+ for (let i = 0; i < 10; i++) {
173
+ messages.push(
174
+ makeUserMsg([
175
+ { type: "image", data: `img${i}`, mimeType: "image/jpeg" },
176
+ ]),
177
+ );
178
+ messages.push(makeAssistantMsg(`reply ${i}`));
179
+ }
180
+
181
+ downsizeConversationImages(messages);
182
+
183
+ // First message's image should have been replaced with text
184
+ const firstMsg = messages[0];
185
+ const arr = firstMsg.content as any[];
186
+ const placeholder = arr.find(
187
+ (c: any) => c.type === "text" && c.text.includes("[image removed"),
188
+ );
189
+ assert.ok(placeholder, "Stripped image should be replaced with text placeholder");
190
+ assert.ok(
191
+ placeholder.text.includes("image/jpeg"),
192
+ "Placeholder should mention original mime type",
193
+ );
194
+ });
195
+
196
+ it("handles toolResult messages with images", () => {
197
+ const messages: Message[] = [];
198
+ for (let i = 0; i < 10; i++) {
199
+ messages.push(makeToolResultMsg(1));
200
+ messages.push(makeAssistantMsg(`reply ${i}`));
201
+ }
202
+
203
+ const result = downsizeConversationImages(messages);
204
+ assert.equal(result.imageCount, 10);
205
+ assert.equal(result.strippedCount, 5);
206
+ assert.ok(result.processed);
207
+ });
208
+
209
+ it("handles mixed user and toolResult images", () => {
210
+ const messages: Message[] = [];
211
+ for (let i = 0; i < 8; i++) {
212
+ messages.push(
213
+ makeUserMsg([
214
+ { type: "text", text: `check ${i}` },
215
+ { type: "image", data: `uimg${i}`, mimeType: "image/png" },
216
+ ]),
217
+ );
218
+ messages.push(makeAssistantMsg(`processing ${i}`));
219
+ messages.push(makeToolResultMsg(1));
220
+ messages.push(makeAssistantMsg(`done ${i}`));
221
+ }
222
+
223
+ const result = downsizeConversationImages(messages);
224
+ // 8 user images + 8 tool result images = 16 total
225
+ assert.equal(result.imageCount, 16);
226
+ assert.equal(result.strippedCount, 11); // 16 - 5 recent
227
+ });
228
+ });
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Image overflow recovery for many-image sessions.
3
+ *
4
+ * When a conversation accumulates many images (screenshots, file reads, etc.),
5
+ * the Anthropic API enforces a stricter per-image dimension limit (2000px) for
6
+ * "many-image requests." This module detects the resulting 400 error and
7
+ * recovers by stripping older images from the conversation history, preserving
8
+ * the most recent ones to maintain session continuity.
9
+ *
10
+ * @see https://github.com/gsd-build/gsd-2/issues/2874
11
+ */
12
+
13
+ import type { Message, ImageContent, TextContent } from "@gsd/pi-ai";
14
+
15
+ /**
16
+ * Maximum image dimension (px) that the Anthropic API allows in many-image
17
+ * requests. Images at or above this size in a large conversation will be
18
+ * rejected with a 400 error. We use 1568 as the safe ceiling (Anthropic's
19
+ * recommended max for multi-image requests).
20
+ */
21
+ export const MANY_IMAGE_MAX_DIMENSION = 1568;
22
+
23
+ /**
24
+ * Number of recent images to preserve when stripping old images.
25
+ * Keeps the most recent screenshots/images so the model retains visual context
26
+ * for the current task.
27
+ */
28
+ const RECENT_IMAGES_TO_KEEP = 5;
29
+
30
+ /**
31
+ * Regex matching the Anthropic API error for oversized images in many-image requests.
32
+ */
33
+ const IMAGE_DIMENSION_ERROR_RE =
34
+ /image.dimensions?.exceed.*max.*allowed.*size.*many.image/i;
35
+
36
+ /**
37
+ * Detect whether an error message is the Anthropic "image dimensions exceed max
38
+ * allowed size for many-image requests" 400 error.
39
+ */
40
+ export function isImageDimensionError(errorMessage: string | undefined | null): boolean {
41
+ if (!errorMessage) return false;
42
+ return IMAGE_DIMENSION_ERROR_RE.test(errorMessage);
43
+ }
44
+
45
+ export interface DownsizeResult {
46
+ /** Total number of images found in the conversation */
47
+ imageCount: number;
48
+ /** Whether any images were stripped */
49
+ processed: boolean;
50
+ /** Number of images that were stripped */
51
+ strippedCount: number;
52
+ }
53
+
54
+ /**
55
+ * Strip older images from conversation messages to recover from many-image
56
+ * dimension errors. Preserves the N most recent images and replaces older ones
57
+ * with a text placeholder.
58
+ *
59
+ * Mutates messages in place (same pattern as replaceMessages/compaction).
60
+ *
61
+ * Accepts Message[] (the LLM message union) so it works with both
62
+ * agent.state.messages and session entries.
63
+ */
64
+ export function downsizeConversationImages(messages: Message[]): DownsizeResult {
65
+ // First pass: collect all image locations (message index + content index)
66
+ const imageLocations: Array<{ msgIdx: number; contentIdx: number }> = [];
67
+
68
+ for (let msgIdx = 0; msgIdx < messages.length; msgIdx++) {
69
+ const msg = messages[msgIdx];
70
+ if (msg.role === "assistant") continue;
71
+
72
+ // UserMessage can have string content; ToolResultMessage always has array
73
+ if (msg.role === "user" && typeof msg.content === "string") continue;
74
+
75
+ const contentArr = msg.content as (TextContent | ImageContent)[];
76
+ if (!Array.isArray(contentArr)) continue;
77
+
78
+ for (let contentIdx = 0; contentIdx < contentArr.length; contentIdx++) {
79
+ if (contentArr[contentIdx].type === "image") {
80
+ imageLocations.push({ msgIdx, contentIdx });
81
+ }
82
+ }
83
+ }
84
+
85
+ const imageCount = imageLocations.length;
86
+ if (imageCount === 0) {
87
+ return { imageCount: 0, processed: false, strippedCount: 0 };
88
+ }
89
+
90
+ // Determine which images to strip (all except the N most recent)
91
+ const stripCount = Math.max(0, imageCount - RECENT_IMAGES_TO_KEEP);
92
+ if (stripCount === 0) {
93
+ return { imageCount, processed: false, strippedCount: 0 };
94
+ }
95
+
96
+ const toStrip = imageLocations.slice(0, stripCount);
97
+
98
+ // Second pass: replace stripped images with text placeholder.
99
+ // Process in reverse order to maintain content indices.
100
+ for (let i = toStrip.length - 1; i >= 0; i--) {
101
+ const { msgIdx, contentIdx } = toStrip[i];
102
+ const msg = messages[msgIdx];
103
+ if (msg.role === "assistant") continue;
104
+ if (msg.role === "user" && typeof msg.content === "string") continue;
105
+
106
+ const contentArr = msg.content as (TextContent | ImageContent)[];
107
+ const imageBlock = contentArr[contentIdx] as ImageContent;
108
+ const mimeType = imageBlock.mimeType || "image/unknown";
109
+
110
+ // Replace the image block with a text placeholder
111
+ (contentArr as any[])[contentIdx] = {
112
+ type: "text",
113
+ text: `[image removed to reduce context size — was ${mimeType}]`,
114
+ } as TextContent;
115
+ }
116
+
117
+ return { imageCount, processed: true, strippedCount: stripCount };
118
+ }
@@ -29,6 +29,7 @@ export {
29
29
  type ExecResult,
30
30
  type Extension,
31
31
  type ExtensionAPI,
32
+ type ExtensionManifest,
32
33
  type ExtensionCommandContext,
33
34
  type ExtensionContext,
34
35
  type ExtensionError,
@@ -53,6 +54,11 @@ export {
53
54
  type SessionSwitchEvent,
54
55
  type SessionTreeEvent,
55
56
  type ToolCallEvent,
57
+ readManifest,
58
+ readManifestFromEntryPath,
59
+ type SortResult,
60
+ type SortWarning,
61
+ sortExtensionPaths,
56
62
  type ToolDefinition,
57
63
  type ToolRenderResultOptions,
58
64
  type ToolResultEvent,
@@ -340,6 +340,9 @@ async function runWorkspaceDiagnostics(
340
340
  const proc = spawn(cmd, cmdArgs, {
341
341
  cwd,
342
342
  stdio: ["ignore", "pipe", "pipe"],
343
+ // On Windows, project-type commands (tsc, cargo, etc.) may be .cmd
344
+ // wrappers that need shell resolution to avoid ENOENT/EINVAL (#2854).
345
+ shell: process.platform === "win32",
343
346
  });
344
347
  const abortHandler = () => {
345
348
  proc.kill();
@@ -90,6 +90,9 @@ async function checkServerRunning(binaryPath: string): Promise<boolean> {
90
90
  try {
91
91
  const proc = spawn(binaryPath, ["status"], {
92
92
  stdio: ["ignore", "pipe", "pipe"],
93
+ // On Windows, the binary may be a .cmd wrapper requiring shell
94
+ // resolution to avoid ENOENT/EINVAL (#2854).
95
+ shell: process.platform === "win32",
93
96
  });
94
97
 
95
98
  const exited = await Promise.race([
@@ -0,0 +1,114 @@
1
+ /**
2
+ * messages.test.ts — Tests for convertToLlm custom message handling.
3
+ *
4
+ * Reproduction test for #3026: background job completion notifications
5
+ * delivered as custom messages must be clearly distinguishable from
6
+ * user-typed input when converted to LLM messages.
7
+ */
8
+
9
+ import test from "node:test";
10
+ import assert from "node:assert/strict";
11
+ import { convertToLlm, type CustomMessage } from "./messages.js";
12
+
13
+ /** Extract the first content block from a message, asserting array content. */
14
+ function firstTextBlock(msg: ReturnType<typeof convertToLlm>[number]) {
15
+ const { content } = msg;
16
+ assert.ok(Array.isArray(content), "Expected content to be an array");
17
+ const block = content[0];
18
+ assert.ok(typeof block === "object" && block !== null, "Expected first block to be an object");
19
+ return block;
20
+ }
21
+
22
+ test("convertToLlm wraps custom messages with system notification prefix", () => {
23
+ const customMsg: CustomMessage = {
24
+ role: "custom",
25
+ customType: "async_job_result",
26
+ content: "**Background job done: bg_abc123** (sleep 2, 2.1s)\n\ndone",
27
+ display: true,
28
+ timestamp: Date.now(),
29
+ };
30
+
31
+ const result = convertToLlm([customMsg]);
32
+ assert.equal(result.length, 1);
33
+ assert.equal(result[0].role, "user");
34
+
35
+ // The content must include a system notification wrapper so the LLM
36
+ // does not confuse it with user input (#3026).
37
+ const text = firstTextBlock(result[0]);
38
+ assert.equal(text.type, "text");
39
+ assert.ok(
40
+ "text" in text && text.text.includes("[system notification"),
41
+ "Custom message should be wrapped with system notification marker",
42
+ );
43
+ });
44
+
45
+ test("convertToLlm wraps custom messages with array content", () => {
46
+ const customMsg: CustomMessage = {
47
+ role: "custom",
48
+ customType: "bg-shell-status",
49
+ content: [{ type: "text", text: "Background processes:\n ✓ bg1 dev-server :3000" }],
50
+ display: false,
51
+ timestamp: Date.now(),
52
+ };
53
+
54
+ const result = convertToLlm([customMsg]);
55
+ assert.equal(result.length, 1);
56
+ assert.equal(result[0].role, "user");
57
+
58
+ const text = firstTextBlock(result[0]);
59
+ assert.equal(text.type, "text");
60
+ assert.ok(
61
+ "text" in text && text.text.includes("[system notification"),
62
+ "Custom message with array content should be wrapped with system notification marker",
63
+ );
64
+ });
65
+
66
+ test("convertToLlm includes customType in notification wrapper", () => {
67
+ const customMsg: CustomMessage = {
68
+ role: "custom",
69
+ customType: "async_job_result",
70
+ content: "job output here",
71
+ display: true,
72
+ timestamp: Date.now(),
73
+ };
74
+
75
+ const result = convertToLlm([customMsg]);
76
+ const text = firstTextBlock(result[0]);
77
+ assert.ok(
78
+ "text" in text && text.text.includes("async_job_result"),
79
+ "Notification wrapper should include the customType for context",
80
+ );
81
+ });
82
+
83
+ test("convertToLlm notification wrapper instructs LLM not to treat as user input", () => {
84
+ const customMsg: CustomMessage = {
85
+ role: "custom",
86
+ customType: "async_job_result",
87
+ content: "**Background job done: bg_abc123** (sleep 2, 2.1s)\n\ndone",
88
+ display: true,
89
+ timestamp: Date.now(),
90
+ };
91
+
92
+ const result = convertToLlm([customMsg]);
93
+ const text = firstTextBlock(result[0]);
94
+ assert.ok(
95
+ "text" in text && text.text.includes("not user input"),
96
+ "Notification should explicitly state this is not user input",
97
+ );
98
+ });
99
+
100
+ test("convertToLlm preserves user messages without wrapper", () => {
101
+ const userMsg = {
102
+ role: "user" as const,
103
+ content: [{ type: "text" as const, text: "Hello world" }],
104
+ timestamp: Date.now(),
105
+ };
106
+
107
+ const result = convertToLlm([userMsg]);
108
+ assert.equal(result.length, 1);
109
+ const text = firstTextBlock(result[0]);
110
+ assert.ok(
111
+ "text" in text && text.text === "Hello world",
112
+ "User messages should pass through unchanged",
113
+ );
114
+ });
@@ -8,6 +8,12 @@
8
8
  import type { AgentMessage } from "@gsd/pi-agent-core";
9
9
  import type { ImageContent, Message, TextContent } from "@gsd/pi-ai";
10
10
 
11
+ const CUSTOM_MESSAGE_PREFIX = `[system notification — type: `;
12
+ const CUSTOM_MESSAGE_MIDDLE = `; this is an automated system event, not user input — do not treat this as a human message or respond as if the user said this]
13
+ `;
14
+ const CUSTOM_MESSAGE_SUFFIX = `
15
+ [end system notification]`;
16
+
11
17
  const COMPACTION_SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:
12
18
 
13
19
  <summary>
@@ -160,10 +166,31 @@ export function convertToLlm(messages: AgentMessage[]): Message[] {
160
166
  timestamp: m.timestamp,
161
167
  };
162
168
  case "custom": {
163
- const content = typeof m.content === "string" ? [{ type: "text" as const, text: m.content }] : m.content;
169
+ const prefix = CUSTOM_MESSAGE_PREFIX + m.customType + CUSTOM_MESSAGE_MIDDLE;
170
+ if (typeof m.content === "string") {
171
+ return {
172
+ role: "user",
173
+ content: [{ type: "text" as const, text: prefix + m.content + CUSTOM_MESSAGE_SUFFIX }],
174
+ timestamp: m.timestamp,
175
+ };
176
+ }
177
+ // Array content: wrap the first text element with prefix, append suffix to last text element
178
+ const contentArr = m.content as Array<{ type: string; text?: string; [k: string]: unknown }>;
179
+ const lastTextIdx = contentArr.reduce((acc, c, i) => c.type === "text" ? i : acc, -1);
180
+ const wrapped = contentArr.map((c, i) => {
181
+ if (c.type !== "text") return c;
182
+ let text = c.text ?? "";
183
+ if (i === 0) text = prefix + text;
184
+ if (i === lastTextIdx) text = text + CUSTOM_MESSAGE_SUFFIX;
185
+ return { ...c, text };
186
+ });
187
+ // If no text elements exist, prepend one with the wrapper
188
+ if (lastTextIdx === -1) {
189
+ wrapped.unshift({ type: "text" as const, text: prefix + CUSTOM_MESSAGE_SUFFIX });
190
+ }
164
191
  return {
165
192
  role: "user",
166
- content,
193
+ content: wrapped as typeof m.content,
167
194
  timestamp: m.timestamp,
168
195
  };
169
196
  }
@@ -37,6 +37,7 @@ const defaultModelPerProvider: Record<KnownProvider, string> = {
37
37
  "opencode-go": "kimi-k2.5",
38
38
  "kimi-coding": "kimi-k2-thinking",
39
39
  "alibaba-coding-plan": "qwen3.5-plus",
40
+ ollama: "llama3.1:8b",
40
41
  "ollama-cloud": "qwen3:32b",
41
42
  };
42
43
 
@@ -129,6 +129,12 @@ export interface DefaultResourceLoaderOptions {
129
129
  appendSystemPrompt?: string;
130
130
  /** Names of bundled extensions (used to identify built-in extensions in conflict detection). */
131
131
  bundledExtensionNames?: Set<string>;
132
+ /**
133
+ * Transform extension paths before loading. Receives the merged list of all
134
+ * discovered extension paths and returns a (possibly reordered/filtered) list.
135
+ * Use this to apply dependency sorting or registry-based filtering.
136
+ */
137
+ extensionPathsTransform?: (paths: string[]) => { paths: string[]; diagnostics?: string[] };
132
138
  extensionsOverride?: (base: LoadExtensionsResult) => LoadExtensionsResult;
133
139
  skillsOverride?: (base: { skills: Skill[]; diagnostics: ResourceDiagnostic[] }) => {
134
140
  skills: Skill[];
@@ -167,6 +173,7 @@ export class DefaultResourceLoader implements ResourceLoader {
167
173
  private systemPromptSource?: string;
168
174
  private appendSystemPromptSource?: string;
169
175
  private bundledExtensionNames: Set<string>;
176
+ private extensionPathsTransform?: (paths: string[]) => { paths: string[]; diagnostics?: string[] };
170
177
  private extensionsOverride?: (base: LoadExtensionsResult) => LoadExtensionsResult;
171
178
  private skillsOverride?: (base: { skills: Skill[]; diagnostics: ResourceDiagnostic[] }) => {
172
179
  skills: Skill[];
@@ -223,6 +230,7 @@ export class DefaultResourceLoader implements ResourceLoader {
223
230
  this.systemPromptSource = options.systemPrompt;
224
231
  this.appendSystemPromptSource = options.appendSystemPrompt;
225
232
  this.bundledExtensionNames = options.bundledExtensionNames ?? new Set();
233
+ this.extensionPathsTransform = options.extensionPathsTransform;
226
234
  this.extensionsOverride = options.extensionsOverride;
227
235
  this.skillsOverride = options.skillsOverride;
228
236
  this.promptsOverride = options.promptsOverride;
@@ -378,10 +386,21 @@ export class DefaultResourceLoader implements ResourceLoader {
378
386
  const cliEnabledPrompts = getEnabledPaths(cliExtensionPaths.prompts);
379
387
  const cliEnabledThemes = getEnabledPaths(cliExtensionPaths.themes);
380
388
 
381
- const extensionPaths = this.noExtensions
389
+ let extensionPaths = this.noExtensions
382
390
  ? cliEnabledExtensions
383
391
  : this.mergePaths(cliEnabledExtensions, enabledExtensions);
384
392
 
393
+ // Apply path transform (dependency sorting, registry filtering) if provided
394
+ if (this.extensionPathsTransform) {
395
+ const transformed = this.extensionPathsTransform(extensionPaths);
396
+ extensionPaths = transformed.paths;
397
+ if (transformed.diagnostics?.length) {
398
+ for (const msg of transformed.diagnostics) {
399
+ process.stderr.write(`[extensions] ${msg}\n`);
400
+ }
401
+ }
402
+ }
403
+
385
404
  const extensionsResult = await loadExtensions(extensionPaths, this.cwd, this.eventBus);
386
405
  const inlineExtensions = await this.loadExtensionFactories(extensionsResult.runtime);
387
406
  extensionsResult.extensions.push(...inlineExtensions.extensions);