gsd-pi 2.76.0-dev.fe143342a → 2.77.0-dev.1d17f366c

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 (597) hide show
  1. package/README.md +17 -35
  2. package/dist/claude-cli-check.js +32 -3
  3. package/dist/cli-web-branch.d.ts +1 -0
  4. package/dist/cli-web-branch.js +3 -0
  5. package/dist/cli.js +38 -2
  6. package/dist/extension-discovery.d.ts +6 -0
  7. package/dist/extension-discovery.js +37 -0
  8. package/dist/extension-registry.d.ts +3 -0
  9. package/dist/extension-sort.d.ts +18 -0
  10. package/dist/extension-sort.js +114 -0
  11. package/dist/extension-validator.d.ts +47 -0
  12. package/dist/extension-validator.js +127 -0
  13. package/dist/loader.js +35 -7
  14. package/dist/onboarding.js +45 -0
  15. package/dist/provider-migrations.d.ts +18 -0
  16. package/dist/provider-migrations.js +14 -0
  17. package/dist/resources/extensions/claude-code-cli/readiness.js +4 -3
  18. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +78 -59
  19. package/dist/resources/extensions/cmux/index.js +20 -0
  20. package/dist/resources/extensions/github-sync/templates.js +103 -0
  21. package/dist/resources/extensions/google-search/extension-manifest.json +5 -4
  22. package/dist/resources/extensions/google-search/index.js +3 -375
  23. package/dist/resources/extensions/gsd/abandon-detect.js +44 -0
  24. package/dist/resources/extensions/gsd/auto/loop.js +90 -2
  25. package/dist/resources/extensions/gsd/auto/phases.js +95 -21
  26. package/dist/resources/extensions/gsd/auto/resolve.js +24 -0
  27. package/dist/resources/extensions/gsd/auto/run-unit.js +48 -4
  28. package/dist/resources/extensions/gsd/auto/session.js +18 -1
  29. package/dist/resources/extensions/gsd/auto/turn-epoch.js +95 -0
  30. package/dist/resources/extensions/gsd/auto-dispatch.js +115 -17
  31. package/dist/resources/extensions/gsd/auto-loop.js +1 -1
  32. package/dist/resources/extensions/gsd/auto-model-selection.js +1 -1
  33. package/dist/resources/extensions/gsd/auto-post-unit.js +90 -2
  34. package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
  35. package/dist/resources/extensions/gsd/auto-recovery.js +46 -1
  36. package/dist/resources/extensions/gsd/auto-start.js +45 -39
  37. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +11 -5
  38. package/dist/resources/extensions/gsd/auto-unit-closeout.js +11 -2
  39. package/dist/resources/extensions/gsd/auto-worktree.js +109 -61
  40. package/dist/resources/extensions/gsd/auto.js +97 -31
  41. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +27 -1
  42. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +4 -2
  43. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +11 -0
  44. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -6
  45. package/dist/resources/extensions/gsd/bootstrap/system-context.js +11 -6
  46. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
  47. package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
  48. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +31 -4
  49. package/dist/resources/extensions/gsd/commands-cmux.js +9 -6
  50. package/dist/resources/extensions/gsd/commands-extensions.js +634 -43
  51. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
  52. package/dist/resources/extensions/gsd/dispatch-guard.js +29 -3
  53. package/dist/resources/extensions/gsd/file-lock.js +49 -9
  54. package/dist/resources/extensions/gsd/git-service.js +1 -0
  55. package/dist/resources/extensions/gsd/gitignore.js +2 -0
  56. package/dist/resources/extensions/gsd/gsd-db.js +90 -30
  57. package/dist/resources/extensions/gsd/guided-flow-queue.js +4 -1
  58. package/dist/resources/extensions/gsd/guided-flow.js +212 -9
  59. package/dist/resources/extensions/gsd/health-widget.js +4 -1
  60. package/dist/resources/extensions/gsd/journal.js +17 -2
  61. package/dist/resources/extensions/gsd/key-manager.js +22 -0
  62. package/dist/resources/extensions/gsd/milestone-actions.js +15 -0
  63. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  64. package/dist/resources/extensions/gsd/model-router.js +36 -3
  65. package/dist/resources/extensions/gsd/notifications.js +30 -16
  66. package/dist/resources/extensions/gsd/pre-execution-checks.js +31 -6
  67. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
  68. package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
  69. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  70. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  71. package/dist/resources/extensions/gsd/prompts/system.md +1 -0
  72. package/dist/resources/extensions/gsd/reports.js +5 -4
  73. package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
  74. package/dist/resources/extensions/gsd/safety/file-change-validator.js +12 -4
  75. package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
  76. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  77. package/dist/resources/extensions/gsd/state.js +25 -25
  78. package/dist/resources/extensions/gsd/token-counter.js +22 -5
  79. package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
  80. package/dist/resources/extensions/gsd/tools/complete-slice.js +21 -0
  81. package/dist/resources/extensions/gsd/tools/complete-task.js +31 -0
  82. package/dist/resources/extensions/gsd/uok/audit.js +18 -2
  83. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  84. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  85. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  86. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  87. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  88. package/dist/resources/extensions/gsd/uok/plan-v2.js +30 -7
  89. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  90. package/dist/resources/extensions/gsd/workflow-logger.js +10 -2
  91. package/dist/resources/extensions/gsd/worktree-manager.js +1 -0
  92. package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
  93. package/dist/resources/extensions/mcp-client/auth.js +10 -1
  94. package/dist/resources/extensions/mcp-client/index.js +118 -9
  95. package/dist/resources/extensions/shared/cmux-events.js +12 -0
  96. package/dist/resources/extensions/shared/rtk-session-stats.js +1 -2
  97. package/dist/resources/skills/create-skill/SKILL.md +2 -2
  98. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  99. package/dist/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  100. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  101. package/dist/resources/skills/verify-before-complete/SKILL.md +2 -1
  102. package/dist/resources/skills/write-docs/SKILL.md +2 -1
  103. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  104. package/dist/web/standalone/.next/BUILD_ID +1 -1
  105. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  106. package/dist/web/standalone/.next/build-manifest.json +3 -3
  107. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  108. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  135. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  157. package/dist/web/standalone/.next/server/app/api/notifications/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  159. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  161. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  163. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  165. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/session/events/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/index.html +1 -1
  190. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  191. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  192. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  193. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  194. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  195. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  196. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  197. package/dist/web/standalone/.next/server/chunks/1926.js +1 -0
  198. package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
  199. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  201. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  203. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  204. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  205. package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
  206. package/dist/web/standalone/.next/static/chunks/{webpack-5fc74f13a25fa1bb.js → webpack-2e68521d7c82f7c2.js} +1 -1
  207. package/dist/welcome-screen.js +6 -1
  208. package/dist/wizard.js +2 -0
  209. package/package.json +16 -14
  210. package/packages/daemon/package.json +2 -2
  211. package/packages/mcp-server/README.md +3 -3
  212. package/packages/mcp-server/dist/env-writer.d.ts +1 -0
  213. package/packages/mcp-server/dist/env-writer.d.ts.map +1 -1
  214. package/packages/mcp-server/dist/env-writer.js +74 -6
  215. package/packages/mcp-server/dist/env-writer.js.map +1 -1
  216. package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
  217. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
  218. package/packages/mcp-server/dist/remote-questions.js +732 -0
  219. package/packages/mcp-server/dist/remote-questions.js.map +1 -0
  220. package/packages/mcp-server/dist/server.d.ts +7 -0
  221. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  222. package/packages/mcp-server/dist/server.js +95 -10
  223. package/packages/mcp-server/dist/server.js.map +1 -1
  224. package/packages/mcp-server/dist/session-manager.d.ts +14 -0
  225. package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
  226. package/packages/mcp-server/dist/session-manager.js +49 -1
  227. package/packages/mcp-server/dist/session-manager.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/package.json +9 -3
  232. package/packages/mcp-server/src/env-writer.test.ts +79 -1
  233. package/packages/mcp-server/src/env-writer.ts +76 -6
  234. package/packages/mcp-server/src/mcp-server.test.ts +67 -0
  235. package/packages/mcp-server/src/readers/readers.test.ts +5 -1
  236. package/packages/mcp-server/src/remote-questions.test.ts +294 -0
  237. package/packages/mcp-server/src/remote-questions.ts +916 -0
  238. package/packages/mcp-server/src/server.ts +118 -16
  239. package/packages/mcp-server/src/session-manager.ts +43 -1
  240. package/packages/mcp-server/src/workflow-tools.test.ts +44 -0
  241. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  242. package/packages/mcp-server/tsconfig.test.json +19 -0
  243. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  244. package/packages/native/package.json +6 -1
  245. package/packages/native/src/__tests__/clipboard.test.mjs +69 -23
  246. package/packages/native/tsconfig.tsbuildinfo +1 -1
  247. package/packages/pi-agent-core/package.json +6 -1
  248. package/packages/pi-agent-core/src/agent-loop.test.ts +220 -15
  249. package/packages/pi-ai/dist/models/custom.d.ts +38 -0
  250. package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/models/custom.js +41 -0
  252. package/packages/pi-ai/dist/models/custom.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
  254. package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
  255. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  256. package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
  257. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  258. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  259. package/packages/pi-ai/dist/providers/anthropic.js +8 -3
  260. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  261. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
  262. package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
  263. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
  264. package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
  265. package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
  266. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  267. package/packages/pi-ai/dist/providers/simple-options.js +16 -1
  268. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  269. package/packages/pi-ai/package.json +6 -1
  270. package/packages/pi-ai/src/models/custom.ts +42 -0
  271. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
  272. package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
  273. package/packages/pi-ai/src/providers/anthropic.ts +9 -3
  274. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
  275. package/packages/pi-ai/src/providers/simple-options.ts +17 -1
  276. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  277. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
  278. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -0
  280. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/agent-session.js +7 -0
  282. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +25 -0
  284. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +105 -6
  286. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +230 -28
  288. package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts +30 -2
  290. package/packages/pi-coding-agent/dist/core/compaction/utils.d.ts.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/compaction/utils.js +113 -12
  292. package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts +1 -0
  294. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +29 -18
  296. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts +2 -0
  298. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.d.ts.map +1 -0
  299. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js +130 -0
  300. package/packages/pi-coding-agent/dist/core/compaction-orchestrator.test.js.map +1 -0
  301. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +56 -1
  302. package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -1
  303. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +8 -15
  304. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
  305. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts +25 -0
  306. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.d.ts.map +1 -0
  307. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js +109 -0
  308. package/packages/pi-coding-agent/dist/core/extensions/extension-discovery.js.map +1 -0
  309. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts +67 -0
  310. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.d.ts.map +1 -0
  311. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js +167 -0
  312. package/packages/pi-coding-agent/dist/core/extensions/extension-registry.js.map +1 -0
  313. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +3 -2
  314. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  315. package/packages/pi-coding-agent/dist/core/extensions/loader.js +24 -8
  316. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  317. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
  318. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  319. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  320. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +14 -0
  321. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  322. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  323. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +11 -0
  324. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  325. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +2 -2
  326. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  327. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
  328. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
  329. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
  330. package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
  331. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  332. package/packages/pi-coding-agent/dist/core/model-registry.js +14 -0
  333. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  334. package/packages/pi-coding-agent/dist/core/resource-loader.js +1 -1
  335. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  336. package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -0
  337. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  338. package/packages/pi-coding-agent/dist/core/sdk.js +4 -1
  339. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  340. package/packages/pi-coding-agent/dist/core/sdk.test.js +19 -1
  341. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  342. package/packages/pi-coding-agent/dist/core/session-manager.js +1 -1
  343. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  344. package/packages/pi-coding-agent/dist/core/session-manager.test.js +21 -1
  345. package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
  346. package/packages/pi-coding-agent/dist/core/system-prompt.js +3 -3
  347. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js +2 -1
  349. package/packages/pi-coding-agent/dist/core/tools/path-utils.test.js.map +1 -1
  350. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +15 -6
  351. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -1
  352. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  353. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
  354. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  355. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +7 -1
  356. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  357. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +31 -9
  358. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  359. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -0
  360. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  361. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  362. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
  363. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  364. package/packages/pi-coding-agent/package.json +6 -1
  365. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
  366. package/packages/pi-coding-agent/src/core/agent-session.ts +11 -0
  367. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +368 -28
  368. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +122 -6
  369. package/packages/pi-coding-agent/src/core/compaction/utils.ts +111 -13
  370. package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
  371. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +32 -18
  372. package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +68 -1
  373. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +9 -18
  374. package/packages/pi-coding-agent/src/core/extensions/extension-discovery.ts +119 -0
  375. package/packages/pi-coding-agent/src/core/extensions/extension-registry.ts +222 -0
  376. package/packages/pi-coding-agent/src/core/extensions/loader.ts +24 -11
  377. package/packages/pi-coding-agent/src/core/extensions/runner.ts +2 -0
  378. package/packages/pi-coding-agent/src/core/extensions/types.ts +15 -0
  379. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +13 -0
  380. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -2
  381. package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
  382. package/packages/pi-coding-agent/src/core/model-registry.ts +16 -0
  383. package/packages/pi-coding-agent/src/core/resource-loader.ts +1 -1
  384. package/packages/pi-coding-agent/src/core/sdk.test.ts +25 -1
  385. package/packages/pi-coding-agent/src/core/sdk.ts +10 -3
  386. package/packages/pi-coding-agent/src/core/session-manager.test.ts +30 -1
  387. package/packages/pi-coding-agent/src/core/session-manager.ts +1 -1
  388. package/packages/pi-coding-agent/src/core/system-prompt.ts +3 -3
  389. package/packages/pi-coding-agent/src/core/tools/path-utils.test.ts +2 -1
  390. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +17 -7
  391. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +14 -5
  392. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +45 -11
  393. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +14 -0
  394. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
  395. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  396. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +12 -5
  397. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  398. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +21 -0
  399. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  400. package/packages/pi-tui/dist/stdin-buffer.d.ts +7 -0
  401. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  402. package/packages/pi-tui/dist/stdin-buffer.js +20 -0
  403. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  404. package/packages/pi-tui/package.json +6 -1
  405. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -5
  406. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +27 -0
  407. package/packages/pi-tui/src/stdin-buffer.ts +26 -0
  408. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  409. package/packages/rpc-client/package.json +6 -1
  410. package/pkg/package.json +1 -1
  411. package/scripts/install.js +512 -0
  412. package/scripts/lib/workspace-manifest.cjs +86 -0
  413. package/scripts/link-workspace-packages.cjs +5 -17
  414. package/scripts/postinstall.js +9 -178
  415. package/src/resources/extensions/claude-code-cli/readiness.ts +4 -3
  416. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +91 -63
  417. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +114 -12
  418. package/src/resources/extensions/cmux/index.ts +35 -10
  419. package/src/resources/extensions/github-sync/templates.ts +151 -0
  420. package/src/resources/extensions/github-sync/tests/templates.test.ts +59 -0
  421. package/src/resources/extensions/google-search/extension-manifest.json +5 -4
  422. package/src/resources/extensions/google-search/index.ts +9 -470
  423. package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
  424. package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -1
  425. package/src/resources/extensions/gsd/auto/loop.ts +104 -2
  426. package/src/resources/extensions/gsd/auto/phases.ts +123 -21
  427. package/src/resources/extensions/gsd/auto/resolve.ts +29 -0
  428. package/src/resources/extensions/gsd/auto/run-unit.ts +56 -4
  429. package/src/resources/extensions/gsd/auto/session.ts +28 -1
  430. package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
  431. package/src/resources/extensions/gsd/auto/types.ts +1 -1
  432. package/src/resources/extensions/gsd/auto-dispatch.ts +117 -16
  433. package/src/resources/extensions/gsd/auto-loop.ts +1 -1
  434. package/src/resources/extensions/gsd/auto-model-selection.ts +1 -1
  435. package/src/resources/extensions/gsd/auto-post-unit.ts +92 -3
  436. package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
  437. package/src/resources/extensions/gsd/auto-recovery.ts +40 -1
  438. package/src/resources/extensions/gsd/auto-start.ts +48 -52
  439. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -5
  440. package/src/resources/extensions/gsd/auto-unit-closeout.ts +14 -3
  441. package/src/resources/extensions/gsd/auto-worktree.ts +122 -68
  442. package/src/resources/extensions/gsd/auto.ts +105 -35
  443. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -1
  444. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -2
  445. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +11 -0
  446. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +18 -6
  447. package/src/resources/extensions/gsd/bootstrap/system-context.ts +13 -9
  448. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
  449. package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
  450. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +27 -8
  451. package/src/resources/extensions/gsd/commands-cmux.ts +10 -6
  452. package/src/resources/extensions/gsd/commands-extensions.ts +747 -41
  453. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
  454. package/src/resources/extensions/gsd/dispatch-guard.ts +26 -2
  455. package/src/resources/extensions/gsd/file-lock.ts +84 -11
  456. package/src/resources/extensions/gsd/git-service.ts +1 -0
  457. package/src/resources/extensions/gsd/gitignore.ts +2 -1
  458. package/src/resources/extensions/gsd/gsd-db.ts +92 -32
  459. package/src/resources/extensions/gsd/guided-flow-queue.ts +4 -1
  460. package/src/resources/extensions/gsd/guided-flow.ts +259 -10
  461. package/src/resources/extensions/gsd/health-widget.ts +3 -1
  462. package/src/resources/extensions/gsd/journal.ts +29 -3
  463. package/src/resources/extensions/gsd/key-manager.ts +22 -0
  464. package/src/resources/extensions/gsd/milestone-actions.ts +18 -0
  465. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  466. package/src/resources/extensions/gsd/model-router.ts +42 -1
  467. package/src/resources/extensions/gsd/notifications.ts +27 -15
  468. package/src/resources/extensions/gsd/pre-execution-checks.ts +33 -7
  469. package/src/resources/extensions/gsd/preferences-types.ts +8 -0
  470. package/src/resources/extensions/gsd/prompts/discuss-headless.md +29 -2
  471. package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
  472. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  473. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
  474. package/src/resources/extensions/gsd/prompts/system.md +1 -0
  475. package/src/resources/extensions/gsd/reports.ts +5 -4
  476. package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
  477. package/src/resources/extensions/gsd/safety/file-change-validator.ts +16 -3
  478. package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
  479. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  480. package/src/resources/extensions/gsd/state.ts +35 -30
  481. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +238 -4
  482. package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
  483. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
  484. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +122 -0
  485. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
  486. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +63 -0
  487. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
  488. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
  489. package/src/resources/extensions/gsd/tests/cmux.test.ts +5 -9
  490. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +15 -0
  491. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
  492. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
  493. package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
  494. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +161 -0
  495. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  496. package/src/resources/extensions/gsd/tests/derive-state.test.ts +1 -2
  497. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +14 -9
  498. package/src/resources/extensions/gsd/tests/dispatch-guard-summary-db-mismatch.test.ts +77 -0
  499. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  500. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  501. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +31 -0
  502. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
  503. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +1 -1
  504. package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
  505. package/src/resources/extensions/gsd/tests/exec-history.test.ts +113 -0
  506. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  507. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +38 -0
  508. package/src/resources/extensions/gsd/tests/file-lock.test.ts +86 -12
  509. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +131 -0
  510. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +296 -1
  511. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  512. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +30 -0
  513. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +4 -2
  514. package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
  515. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
  516. package/src/resources/extensions/gsd/tests/integration/worktree-e2e.test.ts +11 -0
  517. package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
  518. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +66 -0
  519. package/src/resources/extensions/gsd/tests/key-manager.test.ts +2 -0
  520. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +76 -0
  521. package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
  522. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
  523. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  524. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +3 -3
  525. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  526. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +4 -2
  527. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +5 -0
  528. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
  529. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +150 -0
  530. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
  531. package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
  532. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +337 -0
  533. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
  534. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +39 -25
  535. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +181 -0
  536. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +13 -7
  537. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
  538. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
  539. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
  540. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
  541. package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
  542. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
  543. package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
  544. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
  545. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  546. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
  547. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +24 -0
  548. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  549. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +2 -2
  550. package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
  551. package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
  552. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +50 -2
  553. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +162 -0
  554. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  555. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  556. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  557. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  558. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +42 -2
  559. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  560. package/src/resources/extensions/gsd/tests/validate-extension-package.test.ts +168 -0
  561. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +138 -5
  562. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +25 -2
  563. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
  564. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
  565. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
  566. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
  567. package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
  568. package/src/resources/extensions/gsd/token-counter.ts +22 -5
  569. package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
  570. package/src/resources/extensions/gsd/tools/complete-slice.ts +38 -0
  571. package/src/resources/extensions/gsd/tools/complete-task.ts +49 -0
  572. package/src/resources/extensions/gsd/uok/audit.ts +20 -2
  573. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  574. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  575. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  576. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  577. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  578. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  579. package/src/resources/extensions/gsd/uok/plan-v2.ts +39 -8
  580. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  581. package/src/resources/extensions/gsd/workflow-logger.ts +23 -3
  582. package/src/resources/extensions/gsd/worktree-manager.ts +1 -0
  583. package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
  584. package/src/resources/extensions/mcp-client/auth.ts +12 -1
  585. package/src/resources/extensions/mcp-client/index.ts +129 -10
  586. package/src/resources/extensions/shared/cmux-events.ts +59 -0
  587. package/src/resources/extensions/shared/rtk-session-stats.ts +1 -2
  588. package/src/resources/skills/create-skill/SKILL.md +2 -2
  589. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +4 -4
  590. package/src/resources/skills/create-skill/workflows/audit-skill.md +4 -4
  591. package/src/resources/skills/create-skill/workflows/create-new-skill.md +5 -5
  592. package/src/resources/skills/verify-before-complete/SKILL.md +2 -1
  593. package/src/resources/skills/write-docs/SKILL.md +2 -1
  594. package/dist/web/standalone/.next/server/chunks/7461.js +0 -1
  595. package/dist/web/standalone/.next/static/chunks/2826.e59e8578e2e28639.js +0 -9
  596. /package/dist/web/standalone/.next/static/{n21VtX2hZlkpdEUO_nU4z → vidAVJkURvTJ0_V2-64ro}/_buildManifest.js +0 -0
  597. /package/dist/web/standalone/.next/static/{n21VtX2hZlkpdEUO_nU4z → vidAVJkURvTJ0_V2-64ro}/_ssgManifest.js +0 -0
@@ -8,6 +8,12 @@ import { ModelDiscoveryCache } from "./discovery-cache.js";
8
8
  let testDir: string;
9
9
  let cachePath: string;
10
10
 
11
+ function markEntryStale(cache: ModelDiscoveryCache, provider: string): void {
12
+ const entry = cache.get(provider);
13
+ assert.ok(entry, `expected cache entry for ${provider}`);
14
+ entry.fetchedAt = Date.now() - entry.ttlMs - 1;
15
+ }
16
+
11
17
  beforeEach(() => {
12
18
  testDir = join(tmpdir(), `discovery-cache-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
13
19
  mkdirSync(testDir, { recursive: true });
@@ -92,12 +98,7 @@ describe("ModelDiscoveryCache — staleness", () => {
92
98
  it("entries with expired TTL are stale", () => {
93
99
  const cache = new ModelDiscoveryCache(cachePath);
94
100
  cache.set("openai", [{ id: "gpt-4o" }], 1); // 1ms TTL
95
-
96
- // Wait for TTL to expire
97
- const start = Date.now();
98
- while (Date.now() - start < 5) {
99
- // busy wait
100
- }
101
+ markEntryStale(cache, "openai");
101
102
 
102
103
  assert.equal(cache.isStale("openai"), true);
103
104
  });
@@ -110,12 +111,7 @@ describe("ModelDiscoveryCache — getAll", () => {
110
111
  const cache = new ModelDiscoveryCache(cachePath);
111
112
  cache.set("openai", [{ id: "gpt-4o" }]);
112
113
  cache.set("stale", [{ id: "old" }], 1);
113
-
114
- // Wait for stale TTL
115
- const start = Date.now();
116
- while (Date.now() - start < 5) {
117
- // busy wait
118
- }
114
+ markEntryStale(cache, "stale");
119
115
 
120
116
  const all = cache.getAll();
121
117
  assert.ok(all.has("openai"));
@@ -126,12 +122,7 @@ describe("ModelDiscoveryCache — getAll", () => {
126
122
  const cache = new ModelDiscoveryCache(cachePath);
127
123
  cache.set("openai", [{ id: "gpt-4o" }]);
128
124
  cache.set("stale", [{ id: "old" }], 1);
129
-
130
- // Wait for stale TTL
131
- const start = Date.now();
132
- while (Date.now() - start < 5) {
133
- // busy wait
134
- }
125
+ markEntryStale(cache, "stale");
135
126
 
136
127
  const all = cache.getAll(true);
137
128
  assert.ok(all.has("openai"));
@@ -0,0 +1,119 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs'
2
+ import { join, resolve } from 'node:path'
3
+ import { readManifest, readManifestFromEntryPath } from './extension-registry.js'
4
+
5
+ function isExtensionFile(name: string): boolean {
6
+ return name.endsWith('.ts') || name.endsWith('.js')
7
+ }
8
+
9
+ /**
10
+ * Resolves the entry-point file(s) for a single extension directory.
11
+ *
12
+ * 1. If the directory contains a package.json with a `pi` manifest object,
13
+ * the manifest is authoritative:
14
+ * - `pi.extensions` array → resolve each entry relative to the directory.
15
+ * - `pi: {}` (no extensions) → return empty (library opt-out, e.g. cmux).
16
+ * 2. Only when no `pi` manifest exists does it fall back to `index.ts` → `index.js`.
17
+ */
18
+ export function resolveExtensionEntries(dir: string): string[] {
19
+ const packageJsonPath = join(dir, 'package.json')
20
+ if (existsSync(packageJsonPath)) {
21
+ try {
22
+ const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'))
23
+ if (pkg?.pi && typeof pkg.pi === 'object') {
24
+ // When a pi manifest exists, it is authoritative — don't fall through
25
+ // to index.ts/index.js auto-detection. This allows library directories
26
+ // (like cmux) to opt out by declaring "pi": {} with no extensions.
27
+ const declared = pkg.pi.extensions
28
+ if (!Array.isArray(declared) || declared.length === 0) {
29
+ return []
30
+ }
31
+ return declared
32
+ .filter((entry: unknown): entry is string => typeof entry === 'string')
33
+ .map((entry: string) => resolve(dir, entry))
34
+ .filter((entry: string) => existsSync(entry))
35
+ }
36
+ } catch {
37
+ // Ignore malformed manifests and fall back to index.ts/index.js discovery.
38
+ }
39
+ }
40
+
41
+ const indexTs = join(dir, 'index.ts')
42
+ if (existsSync(indexTs)) {
43
+ return [indexTs]
44
+ }
45
+
46
+ const indexJs = join(dir, 'index.js')
47
+ if (existsSync(indexJs)) {
48
+ return [indexJs]
49
+ }
50
+
51
+ return []
52
+ }
53
+
54
+ /**
55
+ * Discovers all extension entry-point paths under an extensions directory.
56
+ *
57
+ * - Top-level .ts/.js files are treated as standalone extension entry points.
58
+ * - Subdirectories are resolved via `resolveExtensionEntries()` (package.json →
59
+ * pi.extensions, then index.ts/index.js fallback).
60
+ */
61
+ export function discoverExtensionEntryPaths(extensionsDir: string): string[] {
62
+ if (!existsSync(extensionsDir)) {
63
+ return []
64
+ }
65
+
66
+ const discovered: string[] = []
67
+ for (const entry of readdirSync(extensionsDir, { withFileTypes: true })) {
68
+ const entryPath = join(extensionsDir, entry.name)
69
+
70
+ if ((entry.isFile() || entry.isSymbolicLink()) && isExtensionFile(entry.name)) {
71
+ discovered.push(entryPath)
72
+ continue
73
+ }
74
+
75
+ if (entry.isDirectory() || entry.isSymbolicLink()) {
76
+ discovered.push(...resolveExtensionEntries(entryPath))
77
+ }
78
+ }
79
+
80
+ return discovered
81
+ }
82
+
83
+ /**
84
+ * Merge bundled and installed extension entry paths.
85
+ * Installed extensions with the same manifest ID as a bundled extension take precedence (D-14).
86
+ * Loader stays dumb — receives a pre-merged path list (D-15).
87
+ */
88
+ export function mergeExtensionEntryPaths(bundledPaths: string[], installedExtDir: string): string[] {
89
+ if (!existsSync(installedExtDir)) return bundledPaths
90
+
91
+ // Build map: manifest ID → entry paths for installed extensions
92
+ const installedById = new Map<string, string[]>()
93
+ for (const entry of readdirSync(installedExtDir, { withFileTypes: true })) {
94
+ if (!entry.isDirectory()) continue
95
+ const dir = join(installedExtDir, entry.name)
96
+ const manifest = readManifest(dir)
97
+ const entries = resolveExtensionEntries(dir)
98
+ if (manifest && entries.length > 0) {
99
+ installedById.set(manifest.id, entries)
100
+ }
101
+ }
102
+
103
+ if (installedById.size === 0) return bundledPaths
104
+
105
+ // Filter bundled paths: skip any whose manifest id is shadowed by installed
106
+ const merged: string[] = []
107
+ for (const entryPath of bundledPaths) {
108
+ const manifest = readManifestFromEntryPath(entryPath)
109
+ if (manifest && installedById.has(manifest.id)) continue // shadowed by installed
110
+ merged.push(entryPath)
111
+ }
112
+
113
+ // Append all installed entries
114
+ for (const entries of installedById.values()) {
115
+ merged.push(...entries)
116
+ }
117
+
118
+ return merged
119
+ }
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Extension Registry — manages manifest reading, registry persistence, and enable/disable state.
3
+ *
4
+ * Extensions without manifests always load (backwards compatible).
5
+ * A fresh install has an empty registry — all extensions enabled by default.
6
+ * The only way an extension stops loading is an explicit `gsd extensions disable <id>`.
7
+ */
8
+
9
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from "node:fs";
10
+ import { getAgentDir } from "../../config.js";
11
+ import { dirname, join } from "node:path";
12
+
13
+ // ─── Types ──────────────────────────────────────────────────────────────────
14
+
15
+ export interface ExtensionManifest {
16
+ id: string;
17
+ name: string;
18
+ version: string;
19
+ description: string;
20
+ tier: "core" | "bundled" | "community";
21
+ requires: { platform: string };
22
+ provides?: {
23
+ tools?: string[];
24
+ commands?: string[];
25
+ hooks?: string[];
26
+ shortcuts?: string[];
27
+ };
28
+ dependencies?: {
29
+ extensions?: string[];
30
+ runtime?: string[];
31
+ };
32
+ }
33
+
34
+ export interface ExtensionRegistryEntry {
35
+ id: string;
36
+ enabled: boolean;
37
+ source: "bundled" | "user" | "project";
38
+ disabledAt?: string;
39
+ disabledReason?: string;
40
+ version?: string; // From manifest, used for semver comparison
41
+ installedFrom?: string; // Original specifier: npm package name, git URL, or local path
42
+ installType?: "npm" | "git" | "local"; // Explicit source type
43
+ }
44
+
45
+ export interface ExtensionRegistry {
46
+ version: 1;
47
+ entries: Record<string, ExtensionRegistryEntry>;
48
+ }
49
+
50
+ // ─── Validation ─────────────────────────────────────────────────────────────
51
+
52
+ function isRegistry(data: unknown): data is ExtensionRegistry {
53
+ if (typeof data !== "object" || data === null) return false;
54
+ const obj = data as Record<string, unknown>;
55
+ return obj.version === 1 && typeof obj.entries === "object" && obj.entries !== null;
56
+ }
57
+
58
+ function isManifest(data: unknown): data is ExtensionManifest {
59
+ if (typeof data !== "object" || data === null) return false;
60
+ const obj = data as Record<string, unknown>;
61
+ return (
62
+ typeof obj.id === "string" &&
63
+ typeof obj.name === "string" &&
64
+ typeof obj.version === "string" &&
65
+ typeof obj.tier === "string"
66
+ );
67
+ }
68
+
69
+ // ─── Registry Path ──────────────────────────────────────────────────────────
70
+
71
+ export function getRegistryPath(): string {
72
+ return join(dirname(getAgentDir()), "extensions", "registry.json");
73
+ }
74
+
75
+ // ─── Registry I/O ───────────────────────────────────────────────────────────
76
+
77
+ function defaultRegistry(): ExtensionRegistry {
78
+ return { version: 1, entries: {} };
79
+ }
80
+
81
+ export function loadRegistry(): ExtensionRegistry {
82
+ const filePath = getRegistryPath();
83
+ try {
84
+ if (!existsSync(filePath)) return defaultRegistry();
85
+ const raw = readFileSync(filePath, "utf-8");
86
+ const parsed = JSON.parse(raw);
87
+ return isRegistry(parsed) ? parsed : defaultRegistry();
88
+ } catch {
89
+ return defaultRegistry();
90
+ }
91
+ }
92
+
93
+ export function saveRegistry(registry: ExtensionRegistry): void {
94
+ const filePath = getRegistryPath();
95
+ try {
96
+ mkdirSync(dirname(filePath), { recursive: true });
97
+ const tmp = filePath + ".tmp";
98
+ writeFileSync(tmp, JSON.stringify(registry, null, 2), "utf-8");
99
+ renameSync(tmp, filePath);
100
+ } catch {
101
+ // Non-fatal — don't let persistence failures break operation
102
+ }
103
+ }
104
+
105
+ // ─── Query ──────────────────────────────────────────────────────────────────
106
+
107
+ /** Returns true if the extension is enabled (missing entries default to enabled). */
108
+ export function isExtensionEnabled(registry: ExtensionRegistry, id: string): boolean {
109
+ const entry = registry.entries[id];
110
+ if (!entry) return true;
111
+ return entry.enabled;
112
+ }
113
+
114
+ // ─── Mutations ──────────────────────────────────────────────────────────────
115
+
116
+ export function enableExtension(registry: ExtensionRegistry, id: string): void {
117
+ const entry = registry.entries[id];
118
+ if (entry) {
119
+ entry.enabled = true;
120
+ delete entry.disabledAt;
121
+ delete entry.disabledReason;
122
+ } else {
123
+ registry.entries[id] = { id, enabled: true, source: "bundled" };
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Disable an extension. Returns an error string if the extension is core (cannot disable),
129
+ * or null on success.
130
+ */
131
+ export function disableExtension(
132
+ registry: ExtensionRegistry,
133
+ id: string,
134
+ manifest: ExtensionManifest | null,
135
+ reason?: string,
136
+ ): string | null {
137
+ if (manifest?.tier === "core") {
138
+ return `Cannot disable "${id}" — it is a core extension.`;
139
+ }
140
+ const entry = registry.entries[id];
141
+ if (entry) {
142
+ entry.enabled = false;
143
+ entry.disabledAt = new Date().toISOString();
144
+ entry.disabledReason = reason;
145
+ } else {
146
+ registry.entries[id] = {
147
+ id,
148
+ enabled: false,
149
+ source: "bundled",
150
+ disabledAt: new Date().toISOString(),
151
+ disabledReason: reason,
152
+ };
153
+ }
154
+ return null;
155
+ }
156
+
157
+ // ─── Manifest Reading ───────────────────────────────────────────────────────
158
+
159
+ /** Read extension-manifest.json from a directory. Returns null if missing or invalid. */
160
+ export function readManifest(extensionDir: string): ExtensionManifest | null {
161
+ const manifestPath = join(extensionDir, "extension-manifest.json");
162
+ if (!existsSync(manifestPath)) return null;
163
+ try {
164
+ const raw = JSON.parse(readFileSync(manifestPath, "utf-8"));
165
+ return isManifest(raw) ? raw : null;
166
+ } catch {
167
+ return null;
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Given an entry path (e.g. `.../extensions/browser-tools/index.ts`),
173
+ * resolve the parent directory and read its manifest.
174
+ */
175
+ export function readManifestFromEntryPath(entryPath: string): ExtensionManifest | null {
176
+ const dir = dirname(entryPath);
177
+ return readManifest(dir);
178
+ }
179
+
180
+ // ─── Discovery ──────────────────────────────────────────────────────────────
181
+
182
+ /** Scan all subdirectories of extensionsDir for manifests. Returns a Map<id, manifest>. */
183
+ export function discoverAllManifests(extensionsDir: string): Map<string, ExtensionManifest> {
184
+ const manifests = new Map<string, ExtensionManifest>();
185
+ if (!existsSync(extensionsDir)) return manifests;
186
+
187
+ for (const entry of readdirSync(extensionsDir, { withFileTypes: true })) {
188
+ if (!entry.isDirectory()) continue;
189
+ const manifest = readManifest(join(extensionsDir, entry.name));
190
+ if (manifest) {
191
+ manifests.set(manifest.id, manifest);
192
+ }
193
+ }
194
+ return manifests;
195
+ }
196
+
197
+ /**
198
+ * Auto-populate registry entries for newly discovered extensions.
199
+ * Extensions already in the registry are left untouched.
200
+ */
201
+ export function ensureRegistryEntries(extensionsDir: string): void {
202
+ const manifests = discoverAllManifests(extensionsDir);
203
+ if (manifests.size === 0) return;
204
+
205
+ const registry = loadRegistry();
206
+ let changed = false;
207
+
208
+ for (const [id, manifest] of manifests) {
209
+ if (!registry.entries[id]) {
210
+ registry.entries[id] = {
211
+ id,
212
+ enabled: true,
213
+ source: "bundled",
214
+ };
215
+ changed = true;
216
+ }
217
+ }
218
+
219
+ if (changed) {
220
+ saveRegistry(registry);
221
+ }
222
+ }
@@ -39,6 +39,8 @@ import { execCommand } from "../exec.js";
39
39
  import { getUntrustedExtensionPaths } from "./project-trust.js";
40
40
  export { isProjectTrusted, trustProject, getUntrustedExtensionPaths } from "./project-trust.js";
41
41
  import { registerToolCompatibility } from "../tools/tool-compatibility-registry.js";
42
+ import { mergeExtensionEntryPaths } from "./extension-discovery.js";
43
+ import { sortExtensionPaths } from "./extension-sort.js";
42
44
  import type {
43
45
  Extension,
44
46
  ExtensionAPI,
@@ -847,24 +849,21 @@ export async function loadExtensionFromFactory(
847
849
  /**
848
850
  * Load extensions from paths.
849
851
  *
850
- * Extensions are loaded in parallel to reduce wall-clock time (~30-50% faster
851
- * than sequential loading for I/O-bound jiti compilation).
852
+ * Paths are expected to be topologically sorted by caller (see sortExtensionPaths).
853
+ * Factories are awaited sequentially so a dependency's factory fully initializes
854
+ * (registers tools, commands, hooks on `pi`) before any dependent's factory runs.
852
855
  */
853
856
  export async function loadExtensions(paths: string[], cwd: string, eventBus?: EventBus): Promise<LoadExtensionsResult> {
854
857
  const resolvedEventBus = eventBus ?? createEventBus();
855
858
  const runtime = createExtensionRuntime();
856
859
 
857
- const results = await Promise.all(
858
- paths.map((extPath) => loadExtension(extPath, cwd, resolvedEventBus, runtime)),
859
- );
860
-
861
860
  const extensions: Extension[] = [];
862
861
  const errors: Array<{ path: string; error: string }> = [];
863
862
 
864
- for (let i = 0; i < results.length; i++) {
865
- const { extension, error } = results[i];
863
+ for (const extPath of paths) {
864
+ const { extension, error } = await loadExtension(extPath, cwd, resolvedEventBus, runtime);
866
865
  if (error) {
867
- errors.push({ path: paths[i], error });
866
+ errors.push({ path: extPath, error });
868
867
  } else if (extension) {
869
868
  extensions.push(extension);
870
869
  }
@@ -873,6 +872,7 @@ export async function loadExtensions(paths: string[], cwd: string, eventBus?: Ev
873
872
  return {
874
873
  extensions,
875
874
  errors,
875
+ warnings: [],
876
876
  runtime,
877
877
  };
878
878
  }
@@ -1034,7 +1034,12 @@ export async function discoverAndLoadExtensions(
1034
1034
 
1035
1035
  // 2. Global extensions: agentDir/extensions/
1036
1036
  const globalExtDir = path.join(agentDir, "extensions");
1037
- addPaths(discoverExtensionsInDir(globalExtDir));
1037
+ // 2b. Installed extensions: ~/.gsd/extensions/ merged with bundled (D-14, D-15)
1038
+ // Discovery handles ID-based merge — loader stays dumb.
1039
+ const installedExtDir = path.join(path.dirname(agentDir), "extensions");
1040
+ const globalPaths = discoverExtensionsInDir(globalExtDir);
1041
+ const mergedPaths = mergeExtensionEntryPaths(globalPaths, installedExtDir);
1042
+ addPaths(mergedPaths);
1038
1043
 
1039
1044
  // 3. Explicitly configured paths
1040
1045
  for (const p of configuredPaths) {
@@ -1054,5 +1059,13 @@ export async function discoverAndLoadExtensions(
1054
1059
  addPaths([resolved]);
1055
1060
  }
1056
1061
 
1057
- return loadExtensions(allPaths, cwd, eventBus);
1062
+ // Topological sort: ensure declared dependencies load first (D-06, D-07)
1063
+ const { sortedPaths, warnings: sortWarnings } = sortExtensionPaths(allPaths)
1064
+ // Emit warnings to stderr immediately — loader runs before ctx.ui is ready (D-08)
1065
+ for (const w of sortWarnings) {
1066
+ process.stderr.write(`[gsd] ${w.message}\n`)
1067
+ }
1068
+ const result = await loadExtensions(sortedPaths, cwd, eventBus)
1069
+ result.warnings.push(...sortWarnings)
1070
+ return result
1058
1071
  }
@@ -164,6 +164,8 @@ export type ExtensionErrorListener = (error: ExtensionError) => void;
164
164
  export type NewSessionHandler = (options?: {
165
165
  parentSession?: string;
166
166
  setup?: (sessionManager: SessionManager) => Promise<void>;
167
+ /** See ExtensionCommandContext.newSession for docs (#3731). */
168
+ abortSignal?: AbortSignal;
167
169
  }) => Promise<{ cancelled: boolean }>;
168
170
 
169
171
  export type ForkHandler = (entryId: string) => Promise<{ cancelled: boolean }>;
@@ -303,6 +303,11 @@ export interface ExtensionCommandContext extends ExtensionContext {
303
303
  newSession(options?: {
304
304
  parentSession?: string;
305
305
  setup?: (sessionManager: SessionManager) => Promise<void>;
306
+ /** When aborted before the session is fully configured, newSession() returns
307
+ * early without rebuilding the tool runtime. Used by runUnit() to discard
308
+ * a late-resolving newSession() after the session-creation timeout fires,
309
+ * preventing the tool runtime from being rebuilt with the wrong cwd (#3731). */
310
+ abortSignal?: AbortSignal;
306
311
  }): Promise<{ cancelled: boolean }>;
307
312
 
308
313
  /** Fork from a specific entry, creating a new session file. */
@@ -1747,6 +1752,8 @@ export interface ExtensionCommandContextActions {
1747
1752
  newSession: (options?: {
1748
1753
  parentSession?: string;
1749
1754
  setup?: (sessionManager: SessionManager) => Promise<void>;
1755
+ /** See ExtensionCommandContext.newSession for docs (#3731). */
1756
+ abortSignal?: AbortSignal;
1750
1757
  }) => Promise<{ cancelled: boolean }>;
1751
1758
  fork: (entryId: string) => Promise<{ cancelled: boolean }>;
1752
1759
  navigateTree: (
@@ -1776,10 +1783,18 @@ export interface Extension {
1776
1783
  lifecycleHooks: LifecycleHookMap;
1777
1784
  }
1778
1785
 
1786
+ /** Warning from extension dependency sort (missing deps, cycles). */
1787
+ export interface ExtensionLoadWarning {
1788
+ declaringId: string;
1789
+ missingId: string;
1790
+ message: string;
1791
+ }
1792
+
1779
1793
  /** Result of loading extensions. */
1780
1794
  export interface LoadExtensionsResult {
1781
1795
  extensions: Extension[];
1782
1796
  errors: Array<{ path: string; error: string }>;
1797
+ warnings: ExtensionLoadWarning[];
1783
1798
  /** Shared runtime - actions are throwing stubs until runner.initialize() */
1784
1799
  runtime: ExtensionRuntime;
1785
1800
  }
@@ -14,6 +14,7 @@ import { spawn } from "node:child_process";
14
14
  import * as fs from "node:fs";
15
15
  import * as path from "node:path";
16
16
  import * as os from "node:os";
17
+ import { spawnSync } from "node:child_process";
17
18
 
18
19
  // ---------------------------------------------------------------------------
19
20
  // Helpers — lightweight JSON-RPC over stdio (no dependency on our LSP code)
@@ -251,11 +252,23 @@ function fileToUri(filePath: string): string {
251
252
  return `file://${path.resolve(filePath)}`;
252
253
  }
253
254
 
255
+ function hasTypescriptLanguageServer(): boolean {
256
+ const probe = spawnSync("typescript-language-server", ["--help"], {
257
+ stdio: "ignore",
258
+ });
259
+ return probe.status === 0 || probe.status === 1;
260
+ }
261
+
254
262
  // ---------------------------------------------------------------------------
255
263
  // Tests
256
264
  // ---------------------------------------------------------------------------
257
265
 
258
266
  test("LSP integration: typescript-language-server", async (t) => {
267
+ if (!hasTypescriptLanguageServer()) {
268
+ t.skip("typescript-language-server not installed in this environment");
269
+ return;
270
+ }
271
+
259
272
  const { dir, cleanup } = createTempProject();
260
273
  const mainPath = path.join(dir, "src", "main.ts");
261
274
  const mathPath = path.join(dir, "src", "math.ts");
@@ -15,11 +15,11 @@ function createRegistry(hasAuthFn?: (provider: string) => boolean): ModelRegistr
15
15
  getApiKey: async () => undefined,
16
16
  } as unknown as AuthStorage;
17
17
 
18
- return new ModelRegistry(authStorage, undefined);
18
+ return new ModelRegistry(authStorage, "");
19
19
  }
20
20
 
21
21
  function createInMemoryRegistry(data: AuthStorageData = {}): ModelRegistry {
22
- return new ModelRegistry(AuthStorage.inMemory(data), undefined);
22
+ return new ModelRegistry(AuthStorage.inMemory(data), "");
23
23
  }
24
24
 
25
25
  function createProviderModel(id: string, api?: string): NonNullable<Parameters<ModelRegistry["registerProvider"]>[1]["models"]>[number] {