gsd-pi 2.77.0-dev.c9c8932c6 → 2.77.0-dev.cfd69e714

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 (708) hide show
  1. package/README.md +1 -1
  2. package/dist/claude-cli-check.js +5 -1
  3. package/dist/cli-web-branch.d.ts +1 -0
  4. package/dist/cli-web-branch.js +3 -0
  5. package/dist/cli.js +24 -2
  6. package/dist/headless.js +49 -4
  7. package/dist/provider-migrations.d.ts +18 -0
  8. package/dist/provider-migrations.js +14 -0
  9. package/dist/resource-loader.d.ts +40 -0
  10. package/dist/resource-loader.js +32 -13
  11. package/dist/resources/extensions/browser-tools/capture.js +9 -0
  12. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  13. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  14. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  15. package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
  16. package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
  17. package/dist/resources/extensions/claude-code-cli/readiness.js +5 -1
  18. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +495 -27
  19. package/dist/resources/extensions/github-sync/templates.js +103 -0
  20. package/dist/resources/extensions/google-search/index.js +3 -2
  21. package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
  22. package/dist/resources/extensions/gsd/auto/loop.js +124 -2
  23. package/dist/resources/extensions/gsd/auto/phases.js +57 -39
  24. package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
  25. package/dist/resources/extensions/gsd/auto/run-unit.js +10 -2
  26. package/dist/resources/extensions/gsd/auto/session.js +6 -2
  27. package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
  28. package/dist/resources/extensions/gsd/auto-dispatch.js +166 -29
  29. package/dist/resources/extensions/gsd/auto-loop.js +1 -1
  30. package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
  31. package/dist/resources/extensions/gsd/auto-post-unit.js +181 -64
  32. package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
  33. package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
  34. package/dist/resources/extensions/gsd/auto-start.js +107 -29
  35. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
  36. package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
  37. package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
  38. package/dist/resources/extensions/gsd/auto-worktree.js +180 -34
  39. package/dist/resources/extensions/gsd/auto.js +80 -21
  40. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
  41. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
  42. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +5 -6
  43. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
  44. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
  45. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
  46. package/dist/resources/extensions/gsd/component-loader.js +447 -0
  47. package/dist/resources/extensions/gsd/component-types.js +69 -0
  48. package/dist/resources/extensions/gsd/context-store.js +23 -7
  49. package/dist/resources/extensions/gsd/detection.js +49 -1
  50. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
  51. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  52. package/dist/resources/extensions/gsd/file-lock.js +49 -9
  53. package/dist/resources/extensions/gsd/forensics.js +106 -0
  54. package/dist/resources/extensions/gsd/gate-registry.js +2 -2
  55. package/dist/resources/extensions/gsd/git-constants.js +28 -1
  56. package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
  57. package/dist/resources/extensions/gsd/git-service.js +127 -2
  58. package/dist/resources/extensions/gsd/gitignore.js +1 -0
  59. package/dist/resources/extensions/gsd/gsd-db.js +6 -3
  60. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
  61. package/dist/resources/extensions/gsd/guided-flow.js +39 -13
  62. package/dist/resources/extensions/gsd/journal.js +17 -2
  63. package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
  64. package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
  65. package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
  66. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  67. package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
  68. package/dist/resources/extensions/gsd/model-router.js +6 -0
  69. package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
  70. package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
  71. package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
  72. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  73. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  74. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  75. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  76. package/dist/resources/extensions/gsd/reports.js +5 -4
  77. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
  78. package/dist/resources/extensions/gsd/service-tier.js +5 -2
  79. package/dist/resources/extensions/gsd/session-lock.js +19 -10
  80. package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
  81. package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
  82. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
  83. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  84. package/dist/resources/extensions/gsd/state.js +69 -58
  85. package/dist/resources/extensions/gsd/sync-lock.js +98 -42
  86. package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
  87. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
  88. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
  89. package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
  90. package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
  91. package/dist/resources/extensions/gsd/uok/audit.js +18 -2
  92. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  93. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  94. package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
  95. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  96. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  97. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  98. package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
  99. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  100. package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
  101. package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
  102. package/dist/resources/extensions/gsd/worktree-manager.js +86 -8
  103. package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
  104. package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
  105. package/dist/resources/extensions/mcp-client/auth.js +10 -1
  106. package/dist/resources/extensions/mcp-client/index.js +121 -10
  107. package/dist/resources/extensions/ollama/index.js +5 -1
  108. package/dist/resources/extensions/remote-questions/manager.js +11 -5
  109. package/dist/resources/skills/create-skill/SKILL.md +2 -2
  110. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  111. package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  112. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  113. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  114. package/dist/web/standalone/.next/BUILD_ID +1 -1
  115. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  116. package/dist/web/standalone/.next/build-manifest.json +3 -3
  117. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  118. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +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.js.nft.json +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.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  195. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  197. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  199. package/dist/web/standalone/.next/server/app/index.html +1 -1
  200. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  201. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  202. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  203. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  204. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  205. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  206. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  207. package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
  208. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  209. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  211. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  213. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  214. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  215. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  216. package/dist/web/standalone/.next/static/chunks/{webpack-1832629448831fdc.js → webpack-2e68521d7c82f7c2.js} +1 -1
  217. package/package.json +4 -5
  218. package/packages/daemon/src/logger.ts +4 -3
  219. package/packages/mcp-server/README.md +3 -3
  220. package/packages/mcp-server/dist/env-writer.d.ts +1 -0
  221. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
  222. package/packages/mcp-server/dist/env-writer.js +74 -6
  223. package/packages/mcp-server/dist/env-writer.js.map +1 -1
  224. package/packages/mcp-server/dist/server.d.ts +24 -0
  225. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  226. package/packages/mcp-server/dist/server.js +111 -87
  227. package/packages/mcp-server/dist/server.js.map +1 -1
  228. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  229. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  230. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  231. package/packages/mcp-server/src/env-writer.test.ts +79 -1
  232. package/packages/mcp-server/src/env-writer.ts +76 -6
  233. package/packages/mcp-server/src/mcp-server.test.ts +25 -3
  234. package/packages/mcp-server/src/readers/graph.test.ts +87 -15
  235. package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
  236. package/packages/mcp-server/src/server.ts +158 -105
  237. package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
  238. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  239. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  240. package/packages/native/package.json +1 -1
  241. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  242. package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
  243. package/packages/native/src/__tests__/ps.test.mjs +14 -8
  244. package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
  245. package/packages/native/src/__tests__/truncate.test.mjs +17 -2
  246. package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
  247. package/packages/pi-agent-core/src/agent.test.ts +96 -102
  248. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  249. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  250. package/packages/pi-ai/dist/models/capability-patches.js +9 -2
  251. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  252. package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
  253. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  254. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  255. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  256. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  257. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  258. package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
  259. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
  260. package/packages/pi-ai/dist/models/generated/openai.js +17 -0
  261. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
  262. package/packages/pi-ai/dist/models.generated.test.js +43 -70
  263. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  264. package/packages/pi-ai/dist/models.test.js +36 -11
  265. package/packages/pi-ai/dist/models.test.js.map +1 -1
  266. package/packages/pi-ai/scripts/generate-models.ts +44 -0
  267. package/packages/pi-ai/src/models/capability-patches.ts +10 -2
  268. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  269. package/packages/pi-ai/src/models/generated/openai.ts +17 -0
  270. package/packages/pi-ai/src/models.generated.test.ts +46 -73
  271. package/packages/pi-ai/src/models.test.ts +48 -11
  272. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  273. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
  274. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
  276. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
  277. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
  278. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
  280. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +21 -16
  282. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
  284. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
  285. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
  286. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
  287. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  288. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
  290. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
  292. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
  294. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
  296. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  298. package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
  299. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  300. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
  301. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
  303. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
  304. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
  305. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
  306. package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
  307. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  308. package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
  309. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  310. package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
  311. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  312. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
  313. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  314. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
  315. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  316. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  317. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  318. package/packages/pi-coding-agent/dist/index.js +1 -0
  319. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
  321. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
  322. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
  323. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  324. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
  325. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  326. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  327. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
  328. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  329. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
  330. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
  332. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  333. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  334. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
  335. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  336. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  337. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
  338. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  339. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
  340. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  341. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
  342. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  343. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  344. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  345. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  346. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
  347. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
  349. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
  350. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
  351. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
  352. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
  353. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
  354. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
  355. package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
  356. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +24 -17
  357. package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
  358. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
  359. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
  360. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
  361. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
  362. package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
  363. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  364. package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
  365. package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
  366. package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
  367. package/packages/pi-coding-agent/src/index.ts +1 -0
  368. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
  369. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
  370. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
  371. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
  372. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
  373. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
  374. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
  375. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
  376. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
  377. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
  378. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  379. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  380. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
  381. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  382. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
  383. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  384. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +51 -6
  385. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  386. package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
  387. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  388. package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
  389. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  390. package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
  391. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
  392. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
  393. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
  394. package/packages/pi-tui/dist/components/editor.d.ts +14 -0
  395. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  396. package/packages/pi-tui/dist/components/editor.js +19 -0
  397. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  398. package/packages/pi-tui/dist/components/image.test.js +6 -5
  399. package/packages/pi-tui/dist/components/image.test.js.map +1 -1
  400. package/packages/pi-tui/dist/editor-component.d.ts +2 -0
  401. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
  402. package/packages/pi-tui/dist/editor-component.js.map +1 -1
  403. package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
  404. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  405. package/packages/pi-tui/dist/stdin-buffer.js +20 -0
  406. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  407. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
  408. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
  409. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +62 -6
  410. package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
  411. package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
  412. package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
  413. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
  414. package/packages/pi-tui/src/components/editor.ts +22 -0
  415. package/packages/pi-tui/src/components/image.test.ts +10 -5
  416. package/packages/pi-tui/src/editor-component.ts +3 -0
  417. package/packages/pi-tui/src/stdin-buffer.ts +26 -0
  418. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  419. package/packages/rpc-client/dist/rpc-client.test.js +101 -51
  420. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
  421. package/packages/rpc-client/src/rpc-client.test.ts +109 -52
  422. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  423. package/scripts/install.js +15 -1
  424. package/src/resources/extensions/browser-tools/capture.ts +12 -0
  425. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  426. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  427. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  428. package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
  429. package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
  430. package/src/resources/extensions/claude-code-cli/readiness.ts +5 -1
  431. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +532 -29
  432. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +941 -91
  433. package/src/resources/extensions/github-sync/templates.ts +151 -0
  434. package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
  435. package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
  436. package/src/resources/extensions/google-search/index.ts +3 -2
  437. package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
  438. package/src/resources/extensions/gsd/auto/loop.ts +142 -2
  439. package/src/resources/extensions/gsd/auto/phases.ts +62 -38
  440. package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
  441. package/src/resources/extensions/gsd/auto/run-unit.ts +16 -2
  442. package/src/resources/extensions/gsd/auto/session.ts +7 -2
  443. package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
  444. package/src/resources/extensions/gsd/auto-dispatch.ts +176 -29
  445. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  446. package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
  447. package/src/resources/extensions/gsd/auto-post-unit.ts +193 -73
  448. package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
  449. package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
  450. package/src/resources/extensions/gsd/auto-start.ts +127 -9
  451. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
  452. package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
  453. package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
  454. package/src/resources/extensions/gsd/auto-worktree.ts +190 -31
  455. package/src/resources/extensions/gsd/auto.ts +95 -23
  456. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
  457. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
  458. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -6
  459. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
  460. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
  461. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
  462. package/src/resources/extensions/gsd/component-loader.ts +598 -0
  463. package/src/resources/extensions/gsd/component-types.ts +362 -0
  464. package/src/resources/extensions/gsd/context-store.ts +25 -8
  465. package/src/resources/extensions/gsd/detection.ts +58 -1
  466. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
  467. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  468. package/src/resources/extensions/gsd/file-lock.ts +84 -11
  469. package/src/resources/extensions/gsd/forensics.ts +118 -1
  470. package/src/resources/extensions/gsd/gate-registry.ts +2 -2
  471. package/src/resources/extensions/gsd/git-constants.ts +30 -1
  472. package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
  473. package/src/resources/extensions/gsd/git-service.ts +150 -2
  474. package/src/resources/extensions/gsd/gitignore.ts +1 -0
  475. package/src/resources/extensions/gsd/gsd-db.ts +6 -3
  476. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
  477. package/src/resources/extensions/gsd/guided-flow.ts +57 -14
  478. package/src/resources/extensions/gsd/journal.ts +38 -3
  479. package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
  480. package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
  481. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
  482. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  483. package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
  484. package/src/resources/extensions/gsd/model-router.ts +6 -0
  485. package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
  486. package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
  487. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
  488. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  489. package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  490. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  491. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  492. package/src/resources/extensions/gsd/reports.ts +5 -4
  493. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
  494. package/src/resources/extensions/gsd/service-tier.ts +5 -2
  495. package/src/resources/extensions/gsd/session-lock.ts +20 -10
  496. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  497. package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
  498. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
  499. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  500. package/src/resources/extensions/gsd/state.ts +76 -66
  501. package/src/resources/extensions/gsd/sync-lock.ts +97 -39
  502. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
  503. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
  504. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
  505. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
  506. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +135 -285
  507. package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
  508. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  509. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
  510. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
  511. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
  512. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
  513. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
  514. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
  515. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
  516. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
  517. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
  518. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
  519. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
  520. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
  521. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
  522. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
  523. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
  524. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
  525. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
  526. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
  527. package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
  528. package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
  529. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  530. package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
  531. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
  532. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
  533. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
  534. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  535. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
  536. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
  537. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
  538. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
  539. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
  540. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
  541. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
  542. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  543. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  544. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
  545. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
  546. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
  547. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  548. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
  549. package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
  550. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
  551. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  552. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
  553. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
  554. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  555. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
  556. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
  557. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
  558. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
  559. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
  560. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  561. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
  562. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
  563. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
  564. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
  565. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
  566. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
  567. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
  568. package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
  569. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +47 -0
  570. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
  571. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
  572. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
  573. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  574. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  575. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  576. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
  577. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
  578. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
  579. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
  580. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
  581. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
  582. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
  583. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
  584. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
  585. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +54 -41
  586. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +213 -0
  587. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
  588. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
  589. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
  590. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
  591. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
  592. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
  593. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
  594. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
  595. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
  596. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
  597. package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
  598. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
  599. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  600. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
  601. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
  602. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
  603. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  604. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
  605. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  606. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
  607. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
  608. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
  609. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
  610. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  611. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
  612. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  613. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
  614. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
  615. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
  616. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
  617. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
  618. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
  619. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
  620. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
  621. package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
  622. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  623. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
  624. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
  625. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
  626. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
  627. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
  628. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
  629. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  630. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  631. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
  632. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
  633. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  634. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  635. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
  636. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  637. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
  638. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
  639. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
  640. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
  641. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
  642. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
  643. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
  644. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
  645. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
  646. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
  647. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
  648. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
  649. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
  650. package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
  651. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
  652. package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
  653. package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
  654. package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
  655. package/src/resources/extensions/gsd/types.ts +3 -3
  656. package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
  657. package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
  658. package/src/resources/extensions/gsd/uok/audit.ts +20 -2
  659. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  660. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  661. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  662. package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
  663. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  664. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  665. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  666. package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
  667. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  668. package/src/resources/extensions/gsd/workflow-logger.ts +22 -3
  669. package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
  670. package/src/resources/extensions/gsd/worktree-manager.ts +109 -7
  671. package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
  672. package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
  673. package/src/resources/extensions/mcp-client/auth.ts +12 -1
  674. package/src/resources/extensions/mcp-client/index.ts +132 -11
  675. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
  676. package/src/resources/extensions/ollama/index.ts +5 -1
  677. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
  678. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
  679. package/src/resources/extensions/remote-questions/manager.ts +36 -4
  680. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
  681. package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
  682. package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
  683. package/src/resources/skills/create-skill/SKILL.md +2 -2
  684. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  685. package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  686. package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  687. package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
  688. package/dist/web/standalone/.next/static/chunks/2826.d445fb428ef41fa1.js +0 -9
  689. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
  690. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
  691. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
  692. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
  693. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
  694. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
  695. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
  696. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
  697. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
  698. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
  699. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  700. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
  701. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
  702. package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
  703. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
  704. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
  705. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
  706. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
  707. /package/dist/web/standalone/.next/static/{H51SzzS_EEgdBsDVhrLBv → SvCJDZPQW104bR1KnBQg1}/_buildManifest.js +0 -0
  708. /package/dist/web/standalone/.next/static/{H51SzzS_EEgdBsDVhrLBv → SvCJDZPQW104bR1KnBQg1}/_ssgManifest.js +0 -0
@@ -0,0 +1,154 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtempSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { describe, it, mock, type Mock } from "node:test";
6
+
7
+ import type { Agent } from "@gsd/pi-agent-core";
8
+ import type { Api, AssistantMessage, Model } from "@gsd/pi-ai";
9
+
10
+ import { CompactionOrchestrator, type CompactionOrchestratorDeps } from "./compaction-orchestrator.js";
11
+ import { SessionManager } from "./session-manager.js";
12
+
13
+ function createMockModel(): Model<Api> {
14
+ return {
15
+ id: "claude-opus-4-6",
16
+ name: "Claude Opus 4.6",
17
+ api: "anthropic-messages" as Api,
18
+ provider: "anthropic",
19
+ baseUrl: "https://api.anthropic.com",
20
+ reasoning: false,
21
+ input: ["text"],
22
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
23
+ contextWindow: 200_000,
24
+ maxTokens: 16_384,
25
+ } as Model<Api>;
26
+ }
27
+
28
+ function createAssistantMessage(
29
+ stopReason: AssistantMessage["stopReason"],
30
+ contentText: string,
31
+ ): AssistantMessage {
32
+ return {
33
+ role: "assistant",
34
+ content: [{ type: "text", text: contentText }],
35
+ api: "anthropic-messages",
36
+ provider: "anthropic",
37
+ model: "claude-opus-4-6",
38
+ usage: {
39
+ input: 100,
40
+ output: 100,
41
+ cacheRead: 0,
42
+ cacheWrite: 0,
43
+ totalTokens: 200,
44
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
45
+ },
46
+ stopReason,
47
+ timestamp: Date.now(),
48
+ errorMessage: stopReason === "error" ? contentText : undefined,
49
+ } as AssistantMessage;
50
+ }
51
+
52
+ function wait(ms: number): Promise<void> {
53
+ return new Promise((resolve) => setTimeout(resolve, ms));
54
+ }
55
+
56
+ function createHarness(overrides?: {
57
+ cancelResult?: boolean;
58
+ willRetry?: boolean;
59
+ hasQueuedMessages?: boolean;
60
+ }) {
61
+ const dir = mkdtempSync(join(tmpdir(), "compaction-orchestrator-test-"));
62
+ const sessionManager = SessionManager.create(dir, dir);
63
+ sessionManager.appendMessage({ role: "user", content: "First user message" } as any);
64
+ sessionManager.appendMessage(createAssistantMessage("stop", "First assistant message"));
65
+ sessionManager.appendMessage({ role: "user", content: "Second user message" } as any);
66
+
67
+ const emittedEvents: Array<Record<string, unknown>> = [];
68
+ const continueFn = mock.fn(async () => {});
69
+ const replaceMessages = mock.fn((nextMessages: unknown[]) => {
70
+ (agent.state.messages as unknown[]) = nextMessages;
71
+ });
72
+ const agent = {
73
+ state: {
74
+ messages: [
75
+ { role: "user", content: "queued follow-up" },
76
+ createAssistantMessage("error", "context overflow"),
77
+ ],
78
+ },
79
+ continue: continueFn,
80
+ replaceMessages,
81
+ hasQueuedMessages: () => overrides?.hasQueuedMessages ?? false,
82
+ } as unknown as Agent;
83
+
84
+ const extensionRunner = {
85
+ hasHandlers: mock.fn(() => true),
86
+ emit: mock.fn(async () => ({ cancel: overrides?.cancelResult ?? true })),
87
+ };
88
+
89
+ const deps: CompactionOrchestratorDeps = {
90
+ agent,
91
+ sessionManager,
92
+ settingsManager: {
93
+ getCompactionSettings: () => ({
94
+ enabled: true,
95
+ reserveTokens: 16_384,
96
+ keepRecentTokens: 1,
97
+ }),
98
+ } as any,
99
+ modelRegistry: {
100
+ isProviderRequestReady: () => true,
101
+ getApiKey: async () => undefined,
102
+ } as any,
103
+ getModel: () => createMockModel(),
104
+ getSessionId: () => "test-session",
105
+ getExtensionRunner: () => extensionRunner as any,
106
+ emit: (event) => emittedEvents.push(event as unknown as Record<string, unknown>),
107
+ disconnectFromAgent: () => {},
108
+ reconnectToAgent: () => {},
109
+ abort: async () => {},
110
+ };
111
+
112
+ return {
113
+ dir,
114
+ agent,
115
+ continueFn,
116
+ replaceMessages,
117
+ emittedEvents,
118
+ extensionRunner,
119
+ orchestrator: new CompactionOrchestrator(deps),
120
+ cleanup: () => rmSync(dir, { recursive: true, force: true }),
121
+ };
122
+ }
123
+
124
+ describe("CompactionOrchestrator", () => {
125
+ it("overflow cancel keeps retry intent and resumes the agent (#3971)", async (t) => {
126
+ const harness = createHarness({ willRetry: true });
127
+ t.after(harness.cleanup);
128
+
129
+ await (harness.orchestrator as any)._runAutoCompaction("overflow", true);
130
+ await wait(150);
131
+
132
+ const endEvent = harness.emittedEvents.find((event) => event.type === "auto_compaction_end");
133
+ assert.ok(endEvent, "should emit auto_compaction_end");
134
+ assert.equal(endEvent?.aborted, true, "cancelled compaction should be marked aborted");
135
+ assert.equal(endEvent?.willRetry, true, "overflow cancel should preserve retry intent");
136
+ assert.equal(harness.continueFn.mock.callCount(), 1, "overflow cancel should resume the agent");
137
+ assert.equal(harness.replaceMessages.mock.callCount(), 1, "retry follow-up should trim the error message when present");
138
+ });
139
+
140
+ it("threshold cancel stays non-retrying when no queued messages exist", async (t) => {
141
+ const harness = createHarness({ willRetry: false, hasQueuedMessages: false });
142
+ t.after(harness.cleanup);
143
+
144
+ await (harness.orchestrator as any)._runAutoCompaction("threshold", false);
145
+ await wait(150);
146
+
147
+ const endEvent = harness.emittedEvents.find((event) => event.type === "auto_compaction_end");
148
+ assert.ok(endEvent, "should emit auto_compaction_end");
149
+ assert.equal(endEvent?.aborted, true, "cancelled compaction should be marked aborted");
150
+ assert.equal(endEvent?.willRetry, false, "threshold cancel should stay non-retrying");
151
+ assert.equal(harness.continueFn.mock.callCount(), 0, "threshold cancel should not resume the agent without queued work");
152
+ assert.equal(harness.replaceMessages.mock.callCount(), 0, "non-retry cancel should not trim messages");
153
+ });
154
+ });
@@ -333,8 +333,9 @@ export class CompactionOrchestrator {
333
333
  type: "auto_compaction_end",
334
334
  result: undefined,
335
335
  aborted: true,
336
- willRetry: false,
336
+ willRetry,
337
337
  });
338
+ this._scheduleAutoCompactionFollowup(willRetry);
338
339
  return;
339
340
  }
340
341
 
@@ -392,22 +393,7 @@ export class CompactionOrchestrator {
392
393
 
393
394
  const result: CompactionResult = { summary, firstKeptEntryId, tokensBefore, details };
394
395
  this._deps.emit({ type: "auto_compaction_end", result, aborted: false, willRetry });
395
-
396
- if (willRetry) {
397
- const messages = this._deps.agent.state.messages;
398
- const lastMsg = messages[messages.length - 1];
399
- if (lastMsg?.role === "assistant" && (lastMsg as AssistantMessage).stopReason === "error") {
400
- this._deps.agent.replaceMessages(messages.slice(0, -1));
401
- }
402
-
403
- setTimeout(() => {
404
- this._deps.agent.continue().catch(() => {});
405
- }, 100);
406
- } else if (this._deps.agent.hasQueuedMessages()) {
407
- setTimeout(() => {
408
- this._deps.agent.continue().catch(() => {});
409
- }, 100);
410
- }
396
+ this._scheduleAutoCompactionFollowup(willRetry);
411
397
  } catch (error) {
412
398
  // Distinguish the "no usable summary" failure (issue #4665) so the UI
413
399
  // can surface a clearer message than a generic compaction failure.
@@ -430,4 +416,25 @@ export class CompactionOrchestrator {
430
416
  this._autoCompactionAbortController = undefined;
431
417
  }
432
418
  }
419
+
420
+ private _scheduleAutoCompactionFollowup(willRetry: boolean): void {
421
+ if (willRetry) {
422
+ const messages = this._deps.agent.state.messages;
423
+ const lastMsg = messages[messages.length - 1];
424
+ if (lastMsg?.role === "assistant" && (lastMsg as AssistantMessage).stopReason === "error") {
425
+ this._deps.agent.replaceMessages(messages.slice(0, -1));
426
+ }
427
+
428
+ setTimeout(() => {
429
+ this._deps.agent.continue().catch(() => {});
430
+ }, 100);
431
+ return;
432
+ }
433
+
434
+ if (this._deps.agent.hasQueuedMessages()) {
435
+ setTimeout(() => {
436
+ this._deps.agent.continue().catch(() => {});
437
+ }, 100);
438
+ }
439
+ }
433
440
  }
@@ -653,15 +653,72 @@ export function containsTypeScriptSyntax(source: string): boolean {
653
653
  * are compiled once and reused across all extensions.
654
654
  */
655
655
  let _extensionLoaderJiti: ReturnType<typeof createJiti> | null = null;
656
+ // Tracks every extension-module path that jiti has compiled through the shared
657
+ // singleton so resetExtensionLoaderCache() can also evict Node's global
658
+ // require.cache entries for those modules. jiti stores compiled modules under
659
+ // `nativeRequire.cache[filename]` when `moduleCache: true`, so a new singleton
660
+ // still returns the stale cached module on re-import without this eviction.
661
+ const _loadedExtensionPaths = new Set<string>();
662
+ const _extensionRequire = createRequire(import.meta.url);
656
663
 
657
664
  /**
658
665
  * Reset the shared jiti singleton so the next call to getExtensionLoaderJiti()
659
666
  * creates a fresh instance. This prevents memory leaks in long-running daemon
660
667
  * processes (every loaded module stays cached forever) and ensures stale modules
661
668
  * are not returned when extension source changes on disk.
669
+ *
670
+ * #3616: resetting the singleton alone is insufficient — jiti stores compiled
671
+ * modules in Node's global require.cache when `moduleCache: true`, which is
672
+ * shared across singletons. We also evict cached entries for every extension
673
+ * path we've previously loaded so the next import recompiles from disk.
662
674
  */
663
675
  export function resetExtensionLoaderCache(): void {
664
676
  _extensionLoaderJiti = null;
677
+ // Build a set of exact cache keys we expect (raw path, resolved path,
678
+ // realpath) AND a set of (basename, containing-directory) pairs so we
679
+ // can also catch entries that jiti/Node wrote under a canonicalized
680
+ // form (Windows drive-letter case, separator swap, UNC prefix, symlink
681
+ // resolution). require.cache is shared across all createRequire
682
+ // instances for CJS, so iterating any instance's cache covers jiti's
683
+ // internal `nativeRequire.cache` writes.
684
+ const exact = new Set<string>();
685
+ const signatures = new Set<string>();
686
+ const makeSignature = (p: string): string => {
687
+ const normalized = p.replace(/\\/g, "/").toLowerCase();
688
+ const slash = normalized.lastIndexOf("/");
689
+ const base = slash >= 0 ? normalized.slice(slash + 1) : normalized;
690
+ // Use the trailing two path segments as the signature — unique
691
+ // enough to avoid collisions in typical filesystems while tolerating
692
+ // drive-letter / separator variations that differ in the prefix.
693
+ const parent = slash >= 0 ? normalized.slice(0, slash) : "";
694
+ const parentSlash = parent.lastIndexOf("/");
695
+ const parentSeg = parentSlash >= 0 ? parent.slice(parentSlash + 1) : parent;
696
+ return `${parentSeg}/${base}`;
697
+ };
698
+ for (const raw of _loadedExtensionPaths) {
699
+ exact.add(raw);
700
+ try {
701
+ exact.add(_extensionRequire.resolve(raw));
702
+ } catch {
703
+ // unresolvable — fall through; signature scan may still hit it
704
+ }
705
+ try {
706
+ exact.add(fs.realpathSync(raw));
707
+ } catch {
708
+ // file may have been deleted already; ignore
709
+ }
710
+ signatures.add(makeSignature(raw));
711
+ }
712
+ for (const key of Object.keys(_extensionRequire.cache)) {
713
+ if (exact.has(key) || signatures.has(makeSignature(key))) {
714
+ try {
715
+ delete _extensionRequire.cache[key];
716
+ } catch {
717
+ // require.cache is best-effort; ignore failures (e.g. frozen cache).
718
+ }
719
+ }
720
+ }
721
+ _loadedExtensionPaths.clear();
665
722
  }
666
723
 
667
724
  function getExtensionLoaderJiti() {
@@ -696,6 +753,7 @@ async function loadExtensionModule(extensionPath: string) {
696
753
  const jiti = getExtensionLoaderJiti();
697
754
 
698
755
  const module = await jiti.import(extensionPath, { default: true });
756
+ _loadedExtensionPaths.add(extensionPath);
699
757
  const factory = module as ExtensionFactory;
700
758
  return typeof factory !== "function" ? undefined : factory;
701
759
  }
@@ -315,8 +315,19 @@ test("LSP integration: typescript-language-server", async (t) => {
315
315
  textDocument: { uri: mathUri, languageId: "typescript", version: 1, text: mathContent },
316
316
  });
317
317
 
318
- // Give the server time to index
319
- await new Promise((r) => setTimeout(r, 3000));
318
+ // Poll for a published diagnostics notification on main.ts, which
319
+ // is the observable signal that TypeScript has finished indexing
320
+ // the opened file. Previous magic-sleep (3000ms) was too short on
321
+ // slow CI machines and wasteful on fast ones (#4798).
322
+ const INDEX_DEADLINE_MS = 15_000;
323
+ const indexDeadline = Date.now() + INDEX_DEADLINE_MS;
324
+ while (Date.now() < indexDeadline) {
325
+ const diags = lsp
326
+ .getNotifications("textDocument/publishDiagnostics")
327
+ .filter((n) => (n.params as { uri: string }).uri === mainUri);
328
+ if (diags.length > 0) break;
329
+ await new Promise((r) => setTimeout(r, 50));
330
+ }
320
331
 
321
332
  // ---- Hover ----
322
333
  await t.test("hover on 'add' call", async () => {
@@ -381,8 +392,28 @@ test("LSP integration: typescript-language-server", async (t) => {
381
392
 
382
393
  // ---- Diagnostics (published via notification) ----
383
394
  await t.test("diagnostics for type error", async () => {
384
- // Wait a bit more for diagnostics to arrive
385
- await new Promise((r) => setTimeout(r, 2000));
395
+ // Poll for the specific type-error diagnostic on main.ts
396
+ // instead of sleeping a fixed 2s. tsserver pushes diagnostics
397
+ // incrementally — we need to wait until at least one diag
398
+ // contains a type-error signal, not just any diag.
399
+ const DIAG_DEADLINE_MS = 10_000;
400
+ const diagDeadline = Date.now() + DIAG_DEADLINE_MS;
401
+ while (Date.now() < diagDeadline) {
402
+ const candidates = lsp
403
+ .getNotifications("textDocument/publishDiagnostics")
404
+ .filter((n) => (n.params as { uri: string }).uri === mainUri)
405
+ .flatMap(
406
+ (n) => (n.params as { diagnostics: Array<{ message: string }> }).diagnostics,
407
+ );
408
+ if (
409
+ candidates.some(
410
+ (d) => d.message.includes("not assignable") || d.message.includes("Type"),
411
+ )
412
+ ) {
413
+ break;
414
+ }
415
+ await new Promise((r) => setTimeout(r, 50));
416
+ }
386
417
 
387
418
  const diagNotifications = lsp.getNotifications("textDocument/publishDiagnostics");
388
419
  const mainDiags = diagNotifications.filter(
@@ -39,6 +39,10 @@ function findModel(registry: ModelRegistry, provider: string, id: string): Model
39
39
  return registry.getAvailable().find((m) => m.provider === provider && m.id === id);
40
40
  }
41
41
 
42
+ function availableModelIds(registry: ModelRegistry): Set<string> {
43
+ return new Set(registry.getAvailable().map((model) => `${model.provider}/${model.id}`));
44
+ }
45
+
42
46
  function makeModel(provider: string, id: string, api: string): Model<Api> {
43
47
  return {
44
48
  id,
@@ -93,6 +97,22 @@ function createStreamSpy(): {
93
97
  // ─── Registration ─────────────────────────────────────────────────────────────
94
98
 
95
99
  describe("ModelRegistry authMode — registration", () => {
100
+ it("includes GPT-5.5 in the authenticated all-models menu backing list", () => {
101
+ const registry = createInMemoryRegistry({
102
+ openai: { type: "api_key", key: "sk-test" },
103
+ "openai-codex": {
104
+ type: "oauth",
105
+ access: "codex-access",
106
+ refresh: "codex-refresh",
107
+ expires: Date.now() + 60_000,
108
+ },
109
+ });
110
+
111
+ const ids = availableModelIds(registry);
112
+ assert.ok(ids.has("openai/gpt-5.5"), "all-models menu backing list should include openai/gpt-5.5");
113
+ assert.ok(ids.has("openai-codex/gpt-5.5"), "all-models menu backing list should include openai-codex/gpt-5.5");
114
+ });
115
+
96
116
  it("registers externalCli provider with streamSimple and without apiKey/oauth", () => {
97
117
  const registry = createRegistry();
98
118
  const spy = createStreamSpy();
@@ -1,42 +1,107 @@
1
- // GSD-2 — Regression test for #3616: reload() must reset jiti extension loader cache
2
- // Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
1
+ // Regression test for #3616: DefaultResourceLoader.reload() must invalidate
2
+ // the jiti module cache before loading extensions, so that edits to
3
+ // extension source on disk are picked up on the next reload (not served
4
+ // stale from memory).
5
+ //
6
+ // Verified end-to-end behaviourally: we write a .ts extension that
7
+ // registers a tool whose NAME is a module-scope constant, load it,
8
+ // rewrite the source with a new constant value, reload(), and assert
9
+ // the observable tool name reflects the NEW source. Without jiti cache
10
+ // invalidation, the second reload would re-register the stale name.
3
11
 
4
- import test, { describe } from "node:test";
5
12
  import assert from "node:assert/strict";
6
- import { readFileSync } from "node:fs";
13
+ import { mkdtempSync, rmSync, utimesSync, writeFileSync } from "node:fs";
14
+ import { tmpdir } from "node:os";
7
15
  import { join } from "node:path";
16
+ import { afterEach, beforeEach, describe, it } from "node:test";
8
17
 
9
- const source = readFileSync(
10
- join(process.cwd(), "packages/pi-coding-agent/src/core/resource-loader.ts"),
11
- "utf-8",
12
- );
18
+ import { DefaultResourceLoader } from "./resource-loader.js";
19
+ import { SettingsManager } from "./settings-manager.js";
20
+ import { resetExtensionLoaderCache } from "./extensions/loader.js";
13
21
 
14
- describe("#3616 — reload() must invalidate jiti module cache", () => {
15
- test("resource-loader imports resetExtensionLoaderCache from loader.js", () => {
16
- assert.ok(
17
- source.includes("resetExtensionLoaderCache"),
18
- "resource-loader.ts should import resetExtensionLoaderCache",
19
- );
20
- assert.ok(
21
- source.includes('from "./extensions/loader.js"'),
22
- "resetExtensionLoaderCache should be imported from extensions/loader.js",
23
- );
22
+ let testDir: string;
23
+
24
+ function writeExtensionWithToolName(extPath: string, toolName: string): void {
25
+ // Extension factory signature expected by the loader. Uses `any` so the
26
+ // test stays decoupled from the ExtensionAPI type shape.
27
+ writeFileSync(
28
+ extPath,
29
+ [
30
+ `const TOOL_NAME = "${toolName}";`,
31
+ `export default function activate(api: any) {`,
32
+ ` api.registerTool({`,
33
+ ` name: TOOL_NAME,`,
34
+ ` label: TOOL_NAME,`,
35
+ ` description: "test tool — source-generated name",`,
36
+ ` parameters: { type: "object", properties: {}, additionalProperties: false },`,
37
+ ` execute: async () => ({ content: [], details: undefined }),`,
38
+ ` });`,
39
+ `}`,
40
+ "",
41
+ ].join("\n"),
42
+ );
43
+ }
44
+
45
+ describe("#3616 — DefaultResourceLoader.reload() invalidates extension module cache", () => {
46
+ beforeEach(() => {
47
+ testDir = mkdtempSync(join(tmpdir(), "resource-loader-cache-reset-"));
48
+ // Ensure a clean jiti singleton — prior tests in this process may
49
+ // have populated it with unrelated entries.
50
+ resetExtensionLoaderCache();
51
+ });
52
+
53
+ afterEach(() => {
54
+ resetExtensionLoaderCache();
55
+ rmSync(testDir, { recursive: true, force: true });
24
56
  });
25
57
 
26
- test("reload() calls resetExtensionLoaderCache before loadExtensions", () => {
27
- const reloadStart = source.indexOf("async reload(): Promise<void>");
28
- assert.ok(reloadStart >= 0, "should find reload() method");
29
- const reloadBody = source.slice(reloadStart, reloadStart + 4000);
58
+ it("reload() picks up source edits after the extension has been loaded once", async () => {
59
+ const agentDir = join(testDir, "agent-home");
60
+ const extPath = join(testDir, "reload-probe.ts");
30
61
 
31
- const resetIdx = reloadBody.indexOf("resetExtensionLoaderCache()");
32
- assert.ok(resetIdx >= 0, "reload() should call resetExtensionLoaderCache()");
62
+ // v1 — initial content
63
+ writeExtensionWithToolName(extPath, "probe_v1");
33
64
 
34
- const loadIdx = reloadBody.indexOf("loadExtensions(");
35
- assert.ok(loadIdx >= 0, "reload() should call loadExtensions");
65
+ const loader = new DefaultResourceLoader({
66
+ cwd: testDir,
67
+ agentDir,
68
+ settingsManager: SettingsManager.inMemory(),
69
+ noExtensions: true,
70
+ noPromptTemplates: true,
71
+ noThemes: true,
72
+ additionalExtensionPaths: [extPath],
73
+ });
36
74
 
75
+ await loader.reload();
76
+
77
+ const toolsV1 = [...loader.getExtensions().extensions.flatMap((e) => [...e.tools.keys()])];
78
+ assert.ok(
79
+ toolsV1.includes("probe_v1"),
80
+ `first reload should register probe_v1; got=${JSON.stringify(toolsV1)}`,
81
+ );
82
+
83
+ // v2 — overwrite the source on disk with a different tool name.
84
+ writeExtensionWithToolName(extPath, "probe_v2");
85
+ // Bump mtime explicitly so file-stat–based cache strategies (jiti's
86
+ // moduleCache consults Node's require.cache, which some runtimes
87
+ // tiebreak on mtime) always see "newer than last seen". On Windows
88
+ // NTFS + node the default fs mtime resolution can silently collapse
89
+ // two writes in the same tick to an identical mtime — that fooled
90
+ // the Windows CI run on #3616.
91
+ const futureTime = new Date(Date.now() + 5000);
92
+ utimesSync(extPath, futureTime, futureTime);
93
+
94
+ await loader.reload();
95
+
96
+ const toolsV2 = [...loader.getExtensions().extensions.flatMap((e) => [...e.tools.keys()])];
97
+ assert.ok(
98
+ toolsV2.includes("probe_v2"),
99
+ `second reload must observe the edited source (probe_v2) — if reload() ` +
100
+ `fails to reset the jiti cache, the stale module returns probe_v1. got=${JSON.stringify(toolsV2)}`,
101
+ );
37
102
  assert.ok(
38
- resetIdx < loadIdx,
39
- "resetExtensionLoaderCache() must be called BEFORE loadExtensions to ensure fresh modules",
103
+ !toolsV2.includes("probe_v1"),
104
+ `second reload must NOT still expose the stale probe_v1 name; got=${JSON.stringify(toolsV2)}`,
40
105
  );
41
106
  });
42
107
  });
@@ -281,7 +281,11 @@ describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
281
281
  assert.equal(result, true, "retry should be initiated");
282
282
 
283
283
  handler.abortRetry();
284
- await new Promise((resolve) => setTimeout(resolve, 10));
284
+ // Yield the microtask queue so any synchronous continuation
285
+ // scheduled by abortRetry() settles before we assert. This is
286
+ // deterministic — no magic-sleep dependency (#4798 / #4784).
287
+ await Promise.resolve();
288
+ await Promise.resolve();
285
289
 
286
290
  assert.equal(continueFn.mock.calls.length, 0, "cancelled retry must not continue after explicit abort");
287
291
  const endEvents = emittedEvents.filter((e) => e.type === "auto_retry_end");
@@ -18,6 +18,7 @@ import type { ModelRegistry } from "./model-registry.js";
18
18
  import type { SettingsManager } from "./settings-manager.js";
19
19
  import { sleep } from "../utils/sleep.js";
20
20
  import type { AgentSessionEvent } from "./agent-session.js";
21
+ import { RETRYABLE_ERROR_RE } from "./retryable-error-regex.js";
21
22
 
22
23
  /** Dependencies injected from AgentSession into RetryHandler */
23
24
  export interface RetryHandlerDeps {
@@ -111,14 +112,7 @@ export class RetryHandler {
111
112
  const contextWindow = this._deps.getModel()?.contextWindow ?? 0;
112
113
  if (isContextOverflow(message, contextWindow)) return false;
113
114
 
114
- const err = message.errorMessage;
115
- // "temporarily backed off" is intentionally excluded: it is an internally-
116
- // generated error from getApiKey() when credentials are in a backoff window.
117
- // Re-entering the retry handler for that message creates a cascade of empty
118
- // error entries in the session file, breaking resume (#3429).
119
- return /overloaded|rate.?limit|too many requests|402|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay|network.?(?:is\s+)?unavailable|credentials.*expired|requires more credits|can only afford|insufficient credits|not enough credits|extra usage is required|(?:out of|no) extra usage|third.party.*draw from extra|third.party.*not.*available/i.test(
120
- err,
121
- );
115
+ return RETRYABLE_ERROR_RE.test(message.errorMessage);
122
116
  }
123
117
 
124
118
  /**
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Regex matching retryable provider errors — overloaded, rate limits, transient
3
+ * server/connection failures, credential-backoff, quota/credit issues.
4
+ *
5
+ * Kept in its own zero-import module so tests can consume the live pattern
6
+ * without pulling in the full RetryHandler dependency graph (Agent /
7
+ * FallbackResolver / ModelRegistry / @gsd/pi-ai …). The test in
8
+ * `src/resources/extensions/gsd/tests/provider-errors.test.ts` previously
9
+ * redefined this regex inline, which meant runtime and test could drift
10
+ * silently on every edit (see #4837).
11
+ *
12
+ * "temporarily backed off" is intentionally excluded: it is an internally-
13
+ * generated error from getApiKey() when credentials are in a backoff window.
14
+ * Re-entering the retry handler for that message creates a cascade of empty
15
+ * error entries in the session file, breaking resume (#3429).
16
+ */
17
+ export const RETRYABLE_ERROR_RE =
18
+ /overloaded|rate.?limit|too many requests|402|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay|network.?(?:is\s+)?unavailable|credentials.*expired|requires more credits|can only afford|insufficient credits|not enough credits|extra usage is required|(?:out of|no) extra usage|third.party.*draw from extra|third.party.*not.*available/i;
@@ -3,7 +3,8 @@
3
3
 
4
4
  import { describe, it } from "node:test";
5
5
  import assert from "node:assert/strict";
6
- import { CredentialCooldownError } from "./sdk.js";
6
+ import { canRestoreSessionModel, CredentialCooldownError } from "./sdk.js";
7
+ import type { Model } from "@gsd/pi-ai";
7
8
 
8
9
  // ─── CredentialCooldownError ──────────────────────────────────────────────────
9
10
 
@@ -87,3 +88,26 @@ describe("CredentialCooldownError", () => {
87
88
  assert.equal(plain.retryAfterMs, 15_000);
88
89
  });
89
90
  });
91
+
92
+ describe("canRestoreSessionModel", () => {
93
+ const model = {
94
+ provider: "claude-code",
95
+ id: "claude-sonnet",
96
+ } as Model<any>;
97
+
98
+ it("allows keyless external providers when the provider is request-ready", () => {
99
+ const registry = {
100
+ isProviderRequestReady: (provider: string) => provider === "claude-code",
101
+ };
102
+
103
+ assert.equal(canRestoreSessionModel(registry, model), true);
104
+ });
105
+
106
+ it("blocks restore when the provider is not request-ready", () => {
107
+ const registry = {
108
+ isProviderRequestReady: () => false,
109
+ };
110
+
111
+ assert.equal(canRestoreSessionModel(registry, model), false);
112
+ });
113
+ });
@@ -31,6 +31,13 @@ export class CredentialCooldownError extends Error {
31
31
  this.retryAfterMs = retryAfterMs;
32
32
  }
33
33
  }
34
+
35
+ export function canRestoreSessionModel(
36
+ modelRegistry: Pick<ModelRegistry, "isProviderRequestReady">,
37
+ model: Model<any>,
38
+ ): boolean {
39
+ return modelRegistry.isProviderRequestReady(model.provider);
40
+ }
34
41
  import { Agent, type AgentMessage, type ThinkingLevel } from "@gsd/pi-agent-core";
35
42
  import type { Message, Model } from "@gsd/pi-ai";
36
43
  import { getAgentDir, getDocsPath } from "../config.js";
@@ -262,9 +269,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
262
269
  // If session has data, try to restore model from it
263
270
  if (!model && hasExistingSession && existingSession.model) {
264
271
  const restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);
265
- if (restoredModel && (await modelRegistry.getApiKey(restoredModel))) {
266
- model = restoredModel;
267
- }
272
+ if (restoredModel && canRestoreSessionModel(modelRegistry, restoredModel)) {
273
+ model = restoredModel;
274
+ }
268
275
  if (!model) {
269
276
  modelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;
270
277
  }