@opengsd/gsd-pi 1.0.2-dev.867e002 → 1.0.2-dev.cce3612

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 (318) hide show
  1. package/dist/onboarding.js +22 -3
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/context7/index.js +12 -2
  4. package/dist/resources/extensions/get-secrets-from-user.js +16 -16
  5. package/dist/resources/extensions/google-cli/index.js +30 -0
  6. package/dist/resources/extensions/google-cli/models.js +55 -0
  7. package/dist/resources/extensions/google-cli/package.json +11 -0
  8. package/dist/resources/extensions/google-cli/readiness.js +12 -0
  9. package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
  10. package/dist/resources/extensions/gsd/auto/loop.js +62 -1
  11. package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
  12. package/dist/resources/extensions/gsd/auto/phases.js +37 -0
  13. package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
  14. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  15. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
  16. package/dist/resources/extensions/gsd/auto-post-unit.js +18 -2
  17. package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
  18. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  19. package/dist/resources/extensions/gsd/auto-start.js +232 -49
  20. package/dist/resources/extensions/gsd/auto.js +6 -1
  21. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
  22. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
  23. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -7
  24. package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
  25. package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
  26. package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
  27. package/dist/resources/extensions/gsd/commands-usage.js +105 -1
  28. package/dist/resources/extensions/gsd/config-overlay.js +20 -14
  29. package/dist/resources/extensions/gsd/context-overlay.js +22 -16
  30. package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
  31. package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
  32. package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
  33. package/dist/resources/extensions/gsd/doctor.js +6 -1
  34. package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
  35. package/dist/resources/extensions/gsd/guided-flow.js +5 -6
  36. package/dist/resources/extensions/gsd/key-manager.js +45 -13
  37. package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
  38. package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
  39. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
  40. package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
  41. package/dist/resources/extensions/gsd/preferences.js +14 -2
  42. package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
  43. package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
  44. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  45. package/dist/resources/extensions/gsd/prompts/system.md +1 -3
  46. package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
  47. package/dist/resources/extensions/gsd/repository-registry.js +3 -1
  48. package/dist/resources/extensions/gsd/skill-activation.js +233 -0
  49. package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
  50. package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
  51. package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
  52. package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
  53. package/dist/resources/extensions/gsd/skill-scope.js +52 -0
  54. package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
  55. package/dist/resources/extensions/gsd/skills.js +60 -0
  56. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
  57. package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
  58. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
  59. package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
  60. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
  61. package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
  62. package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
  63. package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
  64. package/dist/resources/extensions/gsd/vision-ask.js +22 -0
  65. package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
  66. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
  67. package/dist/resources/extensions/search-the-web/native-search.js +57 -8
  68. package/dist/resources/extensions/shared/confirm-ui.js +9 -6
  69. package/dist/resources/extensions/shared/dialog-frame.js +42 -0
  70. package/dist/resources/extensions/shared/interview-ui.js +42 -30
  71. package/dist/resources/extensions/shared/next-action-ui.js +6 -6
  72. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  73. package/dist/web/standalone/.next/BUILD_ID +1 -1
  74. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  75. package/dist/web/standalone/.next/build-manifest.json +2 -2
  76. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  77. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  78. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  86. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/index.html +1 -1
  94. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  101. package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
  102. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  104. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  105. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  106. package/package.json +1 -1
  107. package/packages/cloud-mcp-gateway/package.json +2 -2
  108. package/packages/contracts/package.json +1 -1
  109. package/packages/daemon/package.json +4 -4
  110. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
  111. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  112. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
  113. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  114. package/packages/gsd-agent-core/package.json +5 -5
  115. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
  116. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
  117. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
  118. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
  119. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
  120. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  121. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
  122. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
  123. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
  124. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  125. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
  126. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
  127. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
  128. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  129. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
  130. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
  131. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
  132. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
  133. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
  134. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
  135. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  136. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  137. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
  138. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
  139. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
  140. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  141. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
  142. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  143. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  144. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -1
  145. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  146. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
  147. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  148. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
  149. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  150. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
  151. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
  152. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
  153. package/packages/gsd-agent-modes/package.json +7 -7
  154. package/packages/mcp-server/dist/workflow-tools.js +1 -1
  155. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  156. package/packages/mcp-server/package.json +3 -3
  157. package/packages/native/package.json +1 -1
  158. package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
  159. package/packages/pi-agent-core/dist/harness/skills.js +6 -0
  160. package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
  161. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
  162. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
  163. package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
  164. package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
  165. package/packages/pi-agent-core/package.json +1 -1
  166. package/packages/pi-ai/dist/models.generated.d.ts +8 -59
  167. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  168. package/packages/pi-ai/dist/models.generated.js +21 -72
  169. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  170. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  171. package/packages/pi-ai/dist/providers/anthropic.js +50 -0
  172. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  173. package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
  174. package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
  175. package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
  176. package/packages/pi-ai/dist/types.d.ts +2 -0
  177. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  178. package/packages/pi-ai/dist/types.js.map +1 -1
  179. package/packages/pi-ai/package.json +1 -1
  180. package/packages/pi-coding-agent/README.md +1 -1
  181. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
  182. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
  185. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
  188. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
  190. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/skills.js +3 -0
  192. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  193. package/packages/pi-coding-agent/package.json +7 -7
  194. package/packages/pi-tui/package.json +1 -1
  195. package/packages/rpc-client/package.json +2 -2
  196. package/pkg/package.json +1 -1
  197. package/src/resources/extensions/context7/index.ts +15 -2
  198. package/src/resources/extensions/get-secrets-from-user.ts +17 -16
  199. package/src/resources/extensions/google-cli/index.ts +34 -0
  200. package/src/resources/extensions/google-cli/models.ts +57 -0
  201. package/src/resources/extensions/google-cli/package.json +11 -0
  202. package/src/resources/extensions/google-cli/readiness.ts +15 -0
  203. package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
  204. package/src/resources/extensions/gsd/auto/loop.ts +74 -1
  205. package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
  206. package/src/resources/extensions/gsd/auto/phases.ts +46 -0
  207. package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
  208. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  209. package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
  210. package/src/resources/extensions/gsd/auto-post-unit.ts +37 -2
  211. package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
  212. package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
  213. package/src/resources/extensions/gsd/auto-start.ts +307 -56
  214. package/src/resources/extensions/gsd/auto.ts +6 -1
  215. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
  216. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
  217. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +18 -6
  218. package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
  219. package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
  220. package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
  221. package/src/resources/extensions/gsd/commands-usage.ts +110 -5
  222. package/src/resources/extensions/gsd/config-overlay.ts +19 -16
  223. package/src/resources/extensions/gsd/context-overlay.ts +24 -19
  224. package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
  225. package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
  226. package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
  227. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  228. package/src/resources/extensions/gsd/doctor.ts +6 -1
  229. package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
  230. package/src/resources/extensions/gsd/guided-flow.ts +5 -6
  231. package/src/resources/extensions/gsd/key-manager.ts +57 -14
  232. package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
  233. package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
  234. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
  235. package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
  236. package/src/resources/extensions/gsd/preferences.ts +17 -2
  237. package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
  238. package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
  239. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  240. package/src/resources/extensions/gsd/prompts/system.md +1 -3
  241. package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
  242. package/src/resources/extensions/gsd/repository-registry.ts +3 -1
  243. package/src/resources/extensions/gsd/skill-activation.ts +292 -0
  244. package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
  245. package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
  246. package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
  247. package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
  248. package/src/resources/extensions/gsd/skill-scope.ts +63 -0
  249. package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
  250. package/src/resources/extensions/gsd/skills.ts +75 -0
  251. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
  252. package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
  253. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
  254. package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
  255. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
  256. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +21 -0
  257. package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
  258. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
  259. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
  260. package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
  261. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
  262. package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
  263. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
  264. package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
  265. package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
  266. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
  267. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
  268. package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
  269. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
  270. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
  271. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
  272. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
  273. package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
  274. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
  275. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
  276. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
  277. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
  278. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
  279. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
  280. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
  281. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
  282. package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
  283. package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
  284. package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
  285. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
  286. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
  287. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +19 -0
  288. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
  289. package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
  290. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
  291. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
  292. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
  293. package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
  294. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
  295. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +74 -1
  296. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
  297. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
  298. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
  299. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
  300. package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
  301. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
  302. package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
  303. package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
  304. package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
  305. package/src/resources/extensions/gsd/vision-ask.ts +28 -0
  306. package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
  307. package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
  308. package/src/resources/extensions/search-the-web/native-search.ts +60 -8
  309. package/src/resources/extensions/shared/confirm-ui.ts +8 -12
  310. package/src/resources/extensions/shared/dialog-frame.ts +71 -0
  311. package/src/resources/extensions/shared/interview-ui.ts +43 -42
  312. package/src/resources/extensions/shared/next-action-ui.ts +6 -6
  313. package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
  314. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
  315. package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
  316. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  317. /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → orfEoZqDIo6Be_Z9ZFipD}/_buildManifest.js +0 -0
  318. /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → orfEoZqDIo6Be_Z9ZFipD}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengsd/rpc-client",
3
- "version": "1.0.2-dev.867e002",
3
+ "version": "1.0.2-dev.cce3612",
4
4
  "description": "Standalone RPC client SDK for GSD — zero internal dependencies",
5
5
  "license": "MIT",
6
6
  "gsd": {
@@ -34,7 +34,7 @@
34
34
  "test": "node --test dist/rpc-client.test.js"
35
35
  },
36
36
  "dependencies": {
37
- "@opengsd/contracts": "^1.0.2-dev.867e002"
37
+ "@opengsd/contracts": "^1.0.2-dev.cce3612"
38
38
  },
39
39
  "engines": {
40
40
  "node": ">=22.0.0"
package/pkg/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glittercowboy/gsd",
3
- "version": "1.0.2-dev.867e002",
3
+ "version": "1.0.2-dev.cce3612",
4
4
  "piConfig": {
5
5
  "name": "gsd",
6
6
  "configDir": ".gsd"
@@ -132,6 +132,19 @@ function formatLibraryList(libs: C7Library[], query: string): string {
132
132
  return lines.join("\n");
133
133
  }
134
134
 
135
+ function getFirstTextContent(result: { content?: unknown }): string | undefined {
136
+ const content = result.content;
137
+ if (!Array.isArray(content)) return undefined;
138
+ const textBlock = content.find(
139
+ (block: unknown) =>
140
+ typeof block === "object" &&
141
+ block !== null &&
142
+ (block as { type?: unknown }).type === "text" &&
143
+ typeof (block as { text?: unknown }).text === "string",
144
+ ) as { text: string } | undefined;
145
+ return textBlock?.text.trim() || undefined;
146
+ }
147
+
135
148
  // ─── Tool details types ───────────────────────────────────────────────────────
136
149
 
137
150
  interface ResolveDetails {
@@ -234,7 +247,7 @@ export default function (pi: ExtensionAPI) {
234
247
  const d = result.details as ResolveDetails | undefined;
235
248
  if (isPartial) return new Text(theme.fg("warning", "Searching Context7..."), 0, 0);
236
249
  if ((result as any).isError || d?.error) {
237
- return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
250
+ return new Text(theme.fg("error", `Error: ${d?.error ?? getFirstTextContent(result) ?? "unknown"}`), 0, 0);
238
251
  }
239
252
  let text = theme.fg("success", `${d?.resultCount ?? 0} ${d?.resultCount === 1 ? "library" : "libraries"} found`);
240
253
  if (d?.cached) text += theme.fg("dim", " (cached)");
@@ -389,7 +402,7 @@ export default function (pi: ExtensionAPI) {
389
402
 
390
403
  if (isPartial) return new Text(theme.fg("warning", "Fetching documentation..."), 0, 0);
391
404
  if ((result as any).isError || d?.error) {
392
- return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
405
+ return new Text(theme.fg("error", `Error: ${d?.error ?? getFirstTextContent(result) ?? "unknown"}`), 0, 0);
393
406
  }
394
407
 
395
408
  let text = theme.fg("success", `${(d?.charCount ?? 0).toLocaleString()} chars`);
@@ -13,6 +13,7 @@ import { resolve } from "node:path";
13
13
  import type { ExtensionAPI, Theme } from "@gsd/pi-coding-agent";
14
14
  import { Editor, type EditorTheme, Key, matchesKey, Text, truncateToWidth, wrapTextWithAnsi } from "@gsd/pi-tui";
15
15
  import { Type } from "@sinclair/typebox";
16
+ import { renderSharedDialogFrame } from "./shared/dialog-frame.js";
16
17
  import { makeUI } from "./shared/tui.js";
17
18
  import { maskEditorLine, type ProgressStatus } from "./shared/mod.js";
18
19
  import { parseSecretsManifest, formatSecretsManifest } from "./gsd/files.js";
@@ -43,6 +44,10 @@ function maskPreview(value: string): string {
43
44
  return `${value.slice(0, 4)}${"*".repeat(Math.max(4, value.length - 8))}${value.slice(-4)}`;
44
45
  }
45
46
 
47
+ function dialogContentWidth(width: number): number {
48
+ return width < 4 ? Math.max(1, width) : Math.max(1, width - 4);
49
+ }
50
+
46
51
  function shellEscapeSingle(value: string): string {
47
52
  return `'${value.replace(/'/g, `'\\''`)}'`;
48
53
  }
@@ -168,10 +173,10 @@ async function collectOneSecret(
168
173
 
169
174
  function render(width: number): string[] {
170
175
  if (cachedLines) return cachedLines;
176
+ const contentWidth = dialogContentWidth(width);
171
177
  const lines: string[] = [];
172
- const add = (s: string) => lines.push(truncateToWidth(s, width));
178
+ const add = (s: string) => lines.push(truncateToWidth(s, contentWidth));
173
179
 
174
- add(theme.fg("accent", "─".repeat(width)));
175
180
  add(theme.fg("dim", ` Page ${pageIndex + 1}/${totalPages} · Secure Env Setup`));
176
181
  lines.push("");
177
182
 
@@ -187,7 +192,7 @@ async function collectOneSecret(
187
192
  for (let g = 0; g < guidance.length; g++) {
188
193
  const prefix = ` ${g + 1}. `;
189
194
  const step = guidance[g] as string;
190
- const wrappedLines = wrapTextWithAnsi(step, width - 4);
195
+ const wrappedLines = wrapTextWithAnsi(step, Math.max(1, contentWidth - 4));
191
196
  for (let w = 0; w < wrappedLines.length; w++) {
192
197
  const indent = w === 0 ? prefix : " ".repeat(prefix.length);
193
198
  lines.push(theme.fg("dim", `${indent}${wrappedLines[w]}`));
@@ -205,16 +210,15 @@ async function collectOneSecret(
205
210
 
206
211
  // Editor
207
212
  add(theme.fg("muted", " Enter value:"));
208
- for (const line of editor.render(width - 2)) {
213
+ for (const line of editor.render(Math.max(1, contentWidth - 2))) {
209
214
  add(theme.fg("text", maskEditorLine(line)));
210
215
  }
211
216
 
212
217
  lines.push("");
213
- add(theme.fg("dim", ` enter to confirm | ctrl+s or esc to skip | esc cancels`));
214
- add(theme.fg("accent", "─".repeat(width)));
218
+ const footer = theme.fg("dim", " enter to confirm | ctrl+s or esc to skip | esc cancels");
215
219
 
216
- cachedLines = lines;
217
- return lines;
220
+ cachedLines = renderSharedDialogFrame(theme, "Secure Env Setup", lines, width, { footer });
221
+ return cachedLines;
218
222
  }
219
223
 
220
224
  return {
@@ -286,13 +290,11 @@ export async function showSecretsSummary(
286
290
  function render(width: number): string[] {
287
291
  if (cachedLines) return cachedLines;
288
292
 
289
- const ui = makeUI(theme, width);
293
+ const contentWidth = dialogContentWidth(width);
294
+ const ui = makeUI(theme, contentWidth);
290
295
  const lines: string[] = [];
291
296
  const push = (...rows: string[][]) => { for (const r of rows) lines.push(...r); };
292
297
 
293
- push(ui.bar());
294
- push(ui.blank());
295
- push(ui.header(" Secrets Summary"));
296
298
  push(ui.blank());
297
299
 
298
300
  for (const entry of entries) {
@@ -314,11 +316,10 @@ export async function showSecretsSummary(
314
316
  }
315
317
 
316
318
  push(ui.blank());
317
- push(ui.hints(["any key to continue"]));
318
- push(ui.bar());
319
+ const footer = ui.hints(["any key to continue"])[0] ?? "";
319
320
 
320
- cachedLines = lines;
321
- return lines;
321
+ cachedLines = renderSharedDialogFrame(theme, "Secrets Summary", lines, width, { footer });
322
+ return cachedLines;
322
323
  }
323
324
 
324
325
  return {
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Google local CLI providers.
3
+ *
4
+ * These deliberately use authMode "externalCli": GSD never owns the browser
5
+ * OAuth flow or cached tokens. Users authenticate with the official CLI, then
6
+ * /login activates the provider once the local binary is available.
7
+ */
8
+
9
+ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
10
+ import { GOOGLE_ANTIGRAVITY_MODELS, GOOGLE_GEMINI_CLI_MODELS } from "./models.js";
11
+ import { isAntigravityCliReady, isGeminiCliReady } from "./readiness.js";
12
+ import { streamViaGoogleCli } from "./stream-adapter.js";
13
+
14
+ export default function googleCli(pi: ExtensionAPI) {
15
+ pi.registerProvider("google-gemini-cli", {
16
+ name: "Google Gemini CLI",
17
+ authMode: "externalCli",
18
+ api: "google-gemini-cli",
19
+ baseUrl: "local://google-gemini-cli",
20
+ isReady: isGeminiCliReady,
21
+ streamSimple: streamViaGoogleCli,
22
+ models: GOOGLE_GEMINI_CLI_MODELS,
23
+ });
24
+
25
+ pi.registerProvider("google-antigravity", {
26
+ name: "Google Antigravity",
27
+ authMode: "externalCli",
28
+ api: "google-antigravity",
29
+ baseUrl: "local://google-antigravity",
30
+ isReady: isAntigravityCliReady,
31
+ streamSimple: streamViaGoogleCli,
32
+ models: GOOGLE_ANTIGRAVITY_MODELS,
33
+ });
34
+ }
@@ -0,0 +1,57 @@
1
+ const ZERO_COST = {
2
+ input: 0,
3
+ output: 0,
4
+ cacheRead: 0,
5
+ cacheWrite: 0,
6
+ };
7
+
8
+ export const GOOGLE_GEMINI_CLI_MODELS = [
9
+ {
10
+ id: "gemini-2.5-flash",
11
+ name: "Gemini 2.5 Flash",
12
+ reasoning: true,
13
+ input: ["text" as const],
14
+ cost: ZERO_COST,
15
+ contextWindow: 1_000_000,
16
+ maxTokens: 65_536,
17
+ },
18
+ {
19
+ id: "gemini-2.5-pro",
20
+ name: "Gemini 2.5 Pro",
21
+ reasoning: true,
22
+ input: ["text" as const],
23
+ cost: ZERO_COST,
24
+ contextWindow: 1_000_000,
25
+ maxTokens: 65_536,
26
+ },
27
+ {
28
+ id: "gemini-3-flash-preview",
29
+ name: "Gemini 3 Flash Preview",
30
+ reasoning: true,
31
+ input: ["text" as const],
32
+ cost: ZERO_COST,
33
+ contextWindow: 1_000_000,
34
+ maxTokens: 65_536,
35
+ },
36
+ {
37
+ id: "gemini-3.1-pro-preview",
38
+ name: "Gemini 3.1 Pro Preview",
39
+ reasoning: true,
40
+ input: ["text" as const],
41
+ cost: ZERO_COST,
42
+ contextWindow: 1_000_000,
43
+ maxTokens: 65_536,
44
+ },
45
+ ];
46
+
47
+ export const GOOGLE_ANTIGRAVITY_MODELS = [
48
+ {
49
+ id: "default",
50
+ name: "Antigravity Default",
51
+ reasoning: true,
52
+ input: ["text" as const],
53
+ cost: ZERO_COST,
54
+ contextWindow: 1_000_000,
55
+ maxTokens: 65_536,
56
+ },
57
+ ];
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "@gsd/google-cli",
3
+ "private": true,
4
+ "version": "1.0.0",
5
+ "type": "module",
6
+ "pi": {
7
+ "extensions": [
8
+ "./index.ts"
9
+ ]
10
+ }
11
+ }
@@ -0,0 +1,15 @@
1
+ import { spawnSync } from "node:child_process";
2
+
3
+ function isCommandInPath(command: string): boolean {
4
+ const resolver = process.platform === "win32" ? "where" : "which";
5
+ const result = spawnSync(resolver, [command], { stdio: "ignore" });
6
+ return result.status === 0;
7
+ }
8
+
9
+ export function isGeminiCliReady(): boolean {
10
+ return isCommandInPath("gemini");
11
+ }
12
+
13
+ export function isAntigravityCliReady(): boolean {
14
+ return isCommandInPath("agy");
15
+ }
@@ -0,0 +1,245 @@
1
+ import { spawn } from "node:child_process";
2
+ import type {
3
+ Api,
4
+ AssistantMessage,
5
+ AssistantMessageEventStream,
6
+ Context,
7
+ Message,
8
+ Model,
9
+ SimpleStreamOptions,
10
+ TextContent,
11
+ } from "@gsd/pi-ai";
12
+ import { createAssistantMessageEventStream } from "@gsd/pi-ai";
13
+
14
+ const ZERO_USAGE = {
15
+ input: 0,
16
+ output: 0,
17
+ cacheRead: 0,
18
+ cacheWrite: 0,
19
+ totalTokens: 0,
20
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
21
+ };
22
+
23
+ type GoogleCliProviderId = "google-gemini-cli" | "google-antigravity";
24
+
25
+ interface CliRunResult {
26
+ stdout: string;
27
+ stderr: string;
28
+ code: number | null;
29
+ signal: NodeJS.Signals | null;
30
+ }
31
+
32
+ function textBlocks(content: (TextContent | { type: string })[]): string {
33
+ return content
34
+ .map((block) => block.type === "text" ? (block as TextContent).text : `[${block.type} omitted]`)
35
+ .join("\n");
36
+ }
37
+
38
+ function messageToText(message: Message): string {
39
+ if (message.role === "user") {
40
+ const content = typeof message.content === "string" ? message.content : textBlocks(message.content);
41
+ return `User:\n${content}`;
42
+ }
43
+
44
+ if (message.role === "assistant") {
45
+ const text = message.content
46
+ .map((block) => {
47
+ if (block.type === "text") return block.text;
48
+ if (block.type === "thinking") return `[thinking omitted]`;
49
+ if (block.type === "toolCall") return `[tool call: ${block.name}]`;
50
+ if (block.type === "serverToolUse") return `[server tool: ${block.name}]`;
51
+ if (block.type === "webSearchResult") return `[web search result omitted]`;
52
+ return `[${(block as { type: string }).type} omitted]`;
53
+ })
54
+ .join("\n");
55
+ return `Assistant:\n${text}`;
56
+ }
57
+
58
+ return `Tool result (${message.toolName}):\n${textBlocks(message.content)}`;
59
+ }
60
+
61
+ export function buildGoogleCliPrompt(context: Context): string {
62
+ const parts: string[] = [];
63
+
64
+ if (context.systemPrompt?.trim()) {
65
+ parts.push(`System instructions:\n${context.systemPrompt.trim()}`);
66
+ }
67
+
68
+ if (context.messages.length > 0) {
69
+ parts.push(context.messages.map(messageToText).join("\n\n"));
70
+ }
71
+
72
+ if (context.tools?.length) {
73
+ const names = context.tools.map((tool) => tool.name).join(", ");
74
+ parts.push(
75
+ `Available local GSD tools were not forwarded to this external CLI bridge. ` +
76
+ `If you need to act, use the CLI's own tools or ask the user to switch to a provider with native tool-call support. ` +
77
+ `Requested GSD tools: ${names}`,
78
+ );
79
+ }
80
+
81
+ return parts.join("\n\n").trim();
82
+ }
83
+
84
+ function buildAssistantMessage(
85
+ model: Model<Api>,
86
+ text: string,
87
+ stopReason: AssistantMessage["stopReason"] = "stop",
88
+ errorMessage?: string,
89
+ ): AssistantMessage {
90
+ return {
91
+ role: "assistant",
92
+ content: text ? [{ type: "text", text }] : [],
93
+ api: model.api,
94
+ provider: model.provider,
95
+ model: model.id,
96
+ usage: { ...ZERO_USAGE, cost: { ...ZERO_USAGE.cost } },
97
+ stopReason,
98
+ ...(errorMessage ? { errorMessage } : {}),
99
+ timestamp: Date.now(),
100
+ };
101
+ }
102
+
103
+ function extractGeminiJsonResponse(raw: string): string {
104
+ const trimmed = raw.trim();
105
+ if (!trimmed) return "";
106
+
107
+ try {
108
+ const parsed = JSON.parse(trimmed) as Record<string, unknown>;
109
+ for (const key of ["response", "text", "content", "message"]) {
110
+ const value = parsed[key];
111
+ if (typeof value === "string") return value;
112
+ }
113
+ return JSON.stringify(parsed, null, 2);
114
+ } catch {
115
+ return trimmed;
116
+ }
117
+ }
118
+
119
+ function commandForProvider(provider: GoogleCliProviderId): string {
120
+ return provider === "google-gemini-cli" ? "gemini" : "agy";
121
+ }
122
+
123
+ function argsForProvider(provider: GoogleCliProviderId, model: Model<Api>, prompt: string): string[] {
124
+ if (provider === "google-gemini-cli") {
125
+ const args = ["-p", prompt, "--output-format", "json"];
126
+ if (model.id !== "default") args.unshift("-m", model.id);
127
+ return args;
128
+ }
129
+
130
+ const args = ["-p", prompt];
131
+ if (model.id !== "default") args.unshift("-m", model.id);
132
+ return args;
133
+ }
134
+
135
+ export function buildGoogleCliSpawnInvocation(
136
+ command: string,
137
+ args: string[],
138
+ platform: NodeJS.Platform = process.platform,
139
+ ): { command: string; args: string[] } {
140
+ if (platform === "win32") {
141
+ return { command: "cmd", args: ["/c", command, ...args] };
142
+ }
143
+ return { command, args };
144
+ }
145
+
146
+ function runCli(command: string, args: string[], options?: SimpleStreamOptions): Promise<CliRunResult> {
147
+ return new Promise((resolve, reject) => {
148
+ const invocation = buildGoogleCliSpawnInvocation(command, args);
149
+ const child = spawn(invocation.command, invocation.args, {
150
+ cwd: options?.cwd || process.cwd(),
151
+ env: process.env,
152
+ stdio: ["ignore", "pipe", "pipe"],
153
+ });
154
+
155
+ let stdout = "";
156
+ let stderr = "";
157
+ let settled = false;
158
+
159
+ const settle = (fn: () => void) => {
160
+ if (settled) return;
161
+ settled = true;
162
+ options?.signal?.removeEventListener("abort", onAbort);
163
+ fn();
164
+ };
165
+
166
+ const onAbort = () => {
167
+ child.kill("SIGTERM");
168
+ settle(() => reject(new Error("Request was aborted")));
169
+ };
170
+
171
+ if (options?.signal?.aborted) {
172
+ onAbort();
173
+ return;
174
+ }
175
+ options?.signal?.addEventListener("abort", onAbort);
176
+
177
+ child.stdout.setEncoding("utf8");
178
+ child.stderr.setEncoding("utf8");
179
+ child.stdout.on("data", (chunk) => {
180
+ stdout += chunk;
181
+ });
182
+ child.stderr.on("data", (chunk) => {
183
+ stderr += chunk;
184
+ });
185
+
186
+ child.on("error", (error) => {
187
+ settle(() => reject(error));
188
+ });
189
+
190
+ child.on("close", (code, signal) => {
191
+ settle(() => resolve({ stdout, stderr, code, signal }));
192
+ });
193
+ });
194
+ }
195
+
196
+ function emitText(stream: AssistantMessageEventStream, message: AssistantMessage, text: string): void {
197
+ stream.push({ type: "start", partial: { ...message, content: [] } });
198
+ if (text) {
199
+ stream.push({ type: "text_start", contentIndex: 0, partial: message });
200
+ stream.push({ type: "text_delta", contentIndex: 0, delta: text, partial: message });
201
+ stream.push({ type: "text_end", contentIndex: 0, content: text, partial: message });
202
+ }
203
+ stream.push({ type: "done", reason: "stop", message });
204
+ stream.end(message);
205
+ }
206
+
207
+ function emitError(stream: AssistantMessageEventStream, model: Model<Api>, error: unknown): void {
208
+ const message = error instanceof Error ? error.message : String(error);
209
+ const output = buildAssistantMessage(model, "", "error", message);
210
+ stream.push({ type: "error", reason: "error", error: output });
211
+ stream.end(output);
212
+ }
213
+
214
+ export function streamViaGoogleCli(
215
+ model: Model<Api>,
216
+ context: Context,
217
+ options?: SimpleStreamOptions,
218
+ ): AssistantMessageEventStream {
219
+ const stream = createAssistantMessageEventStream();
220
+ const provider = model.provider as GoogleCliProviderId;
221
+
222
+ queueMicrotask(async () => {
223
+ try {
224
+ const prompt = buildGoogleCliPrompt(context);
225
+ const command = commandForProvider(provider);
226
+ const args = argsForProvider(provider, model, prompt);
227
+ const result = await runCli(command, args, options);
228
+
229
+ if (result.code !== 0) {
230
+ const detail = (result.stderr || result.stdout || `CLI exited with code ${result.code}`).trim();
231
+ throw new Error(detail);
232
+ }
233
+
234
+ const text = provider === "google-gemini-cli"
235
+ ? extractGeminiJsonResponse(result.stdout)
236
+ : result.stdout.trim();
237
+ const message = buildAssistantMessage(model, text);
238
+ emitText(stream, message, text);
239
+ } catch (error) {
240
+ emitError(stream, model, error);
241
+ }
242
+ });
243
+
244
+ return stream;
245
+ }
@@ -881,10 +881,37 @@ export async function autoLoop(
881
881
  message: orchestrationResult.reason,
882
882
  category: "unknown",
883
883
  });
884
+ finishTurn("paused", "manual-attention", "orchestration-blocked");
884
885
  } else {
885
886
  await deps.stopAuto(ctx, pi, orchestrationResult.reason);
887
+ finishTurn("stopped", "manual-attention", "orchestration-blocked");
886
888
  }
887
- finishTurn("stopped", "manual-attention", "orchestration-blocked");
889
+ finishIncompleteIteration({
890
+ status: orchestrationResult.action === "pause" ? "paused" : "stopped",
891
+ reason: orchestrationResult.reason,
892
+ failureClass: "manual-attention",
893
+ });
894
+ break;
895
+ }
896
+
897
+ if (orchestrationResult.kind === "paused") {
898
+ s.pendingOrchestrationDispatch = null;
899
+ finishTurn("skipped");
900
+ continue;
901
+ }
902
+
903
+ if (orchestrationResult.kind === "error") {
904
+ s.pendingOrchestrationDispatch = null;
905
+ await deps.pauseAuto(ctx, pi, {
906
+ message: orchestrationResult.reason,
907
+ category: "unknown",
908
+ });
909
+ finishTurn("paused", "manual-attention", `orchestration-${orchestrationResult.kind}`);
910
+ finishIncompleteIteration({
911
+ status: "paused",
912
+ reason: orchestrationResult.reason,
913
+ failureClass: "manual-attention",
914
+ });
888
915
  break;
889
916
  }
890
917
 
@@ -918,6 +945,52 @@ export async function autoLoop(
918
945
  isRetry: false,
919
946
  previousTier: undefined,
920
947
  };
948
+ const preDispatchResult = deps.runPreDispatchHooks(
949
+ iterData.unitType,
950
+ iterData.unitId,
951
+ iterData.prompt,
952
+ s.basePath,
953
+ );
954
+ if (preDispatchResult.firedHooks.length > 0) {
955
+ ctx.ui.notify(
956
+ `Pre-dispatch hook${preDispatchResult.firedHooks.length > 1 ? "s" : ""}: ${preDispatchResult.firedHooks.join(", ")}`,
957
+ "info",
958
+ );
959
+ deps.emitJournalEvent({
960
+ ts: new Date().toISOString(),
961
+ flowId: ic.flowId,
962
+ seq: ic.nextSeq(),
963
+ eventType: "pre-dispatch-hook",
964
+ data: {
965
+ firedHooks: preDispatchResult.firedHooks,
966
+ action: preDispatchResult.action,
967
+ },
968
+ });
969
+ }
970
+ if (preDispatchResult.action === "skip") {
971
+ ctx.ui.notify(
972
+ `Skipping ${iterData.unitType} ${iterData.unitId} (pre-dispatch hook).`,
973
+ "info",
974
+ );
975
+ s.pendingOrchestrationDispatch = null;
976
+ emitIterationEnd({ skipped: true });
977
+ completeIteration();
978
+ finishTurn("skipped");
979
+ continue;
980
+ }
981
+ if (preDispatchResult.action === "replace") {
982
+ iterData.prompt = preDispatchResult.prompt ?? iterData.prompt;
983
+ iterData.finalPrompt = iterData.prompt;
984
+ if (preDispatchResult.unitType) {
985
+ iterData.unitType = preDispatchResult.unitType;
986
+ }
987
+ } else if (preDispatchResult.prompt) {
988
+ iterData.prompt = preDispatchResult.prompt;
989
+ iterData.finalPrompt = preDispatchResult.prompt;
990
+ }
991
+ if (preDispatchResult.model) {
992
+ iterData.hookModelOverride = preDispatchResult.model;
993
+ }
921
994
  s.pendingOrchestrationDispatch = null;
922
995
  phaseReporter.report("dispatch", "next", {
923
996
  unitType: iterData.unitType,
@@ -396,9 +396,11 @@ export class AutoOrchestrator implements AutoOrchestrationModule {
396
396
  const activeUnitKey = this.status.activeUnit
397
397
  ? `${this.status.activeUnit.unitType}:${this.status.activeUnit.unitId}`
398
398
  : null;
399
- if (activeUnitKey !== unitKey) return;
399
+ if (activeUnitKey !== unitKey && this.lastFinalizedUnitKey !== unitKey) return;
400
400
 
401
- this.status.activeUnit = undefined;
401
+ if (activeUnitKey === unitKey) {
402
+ this.status.activeUnit = undefined;
403
+ }
402
404
  this.lastAdvanceKey = null;
403
405
  this.lastFinalizedUnitKey = null;
404
406
  this.bumpTransition();