@opengsd/gsd-pi 1.0.2-dev.e9a1b49 → 1.0.2-dev.fb7ddf1

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 (490) hide show
  1. package/README.md +63 -12
  2. package/dist/headless-answers.js +2 -1
  3. package/dist/headless-events.d.ts +1 -0
  4. package/dist/headless-events.js +8 -1
  5. package/dist/onboarding.js +22 -3
  6. package/dist/resource-loader.d.ts +7 -0
  7. package/dist/resource-loader.js +44 -9
  8. package/dist/resources/.managed-resources-content-hash +1 -1
  9. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +34 -11
  10. package/dist/resources/extensions/context7/index.js +12 -2
  11. package/dist/resources/extensions/get-secrets-from-user.js +16 -16
  12. package/dist/resources/extensions/google-cli/index.js +30 -0
  13. package/dist/resources/extensions/google-cli/models.js +55 -0
  14. package/dist/resources/extensions/google-cli/package.json +11 -0
  15. package/dist/resources/extensions/google-cli/readiness.js +12 -0
  16. package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
  17. package/dist/resources/extensions/gsd/auto/loop.js +81 -1
  18. package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
  19. package/dist/resources/extensions/gsd/auto/phases.js +38 -1
  20. package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
  21. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  22. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
  23. package/dist/resources/extensions/gsd/auto-post-unit.js +65 -16
  24. package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
  25. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  26. package/dist/resources/extensions/gsd/auto-start.js +232 -49
  27. package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -1
  28. package/dist/resources/extensions/gsd/auto-verification.js +14 -2
  29. package/dist/resources/extensions/gsd/auto-worktree.js +36 -55
  30. package/dist/resources/extensions/gsd/auto.js +40 -2
  31. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
  32. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -2
  33. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
  34. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -27
  35. package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
  36. package/dist/resources/extensions/gsd/bootstrap/tool-search-shim.js +4 -4
  37. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
  38. package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
  39. package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
  40. package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
  41. package/dist/resources/extensions/gsd/commands-usage.js +105 -1
  42. package/dist/resources/extensions/gsd/config-overlay.js +20 -14
  43. package/dist/resources/extensions/gsd/context-overlay.js +22 -16
  44. package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
  45. package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
  46. package/dist/resources/extensions/gsd/doctor-git-checks.js +70 -5
  47. package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
  48. package/dist/resources/extensions/gsd/doctor.js +7 -2
  49. package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
  50. package/dist/resources/extensions/gsd/guided-flow.js +5 -6
  51. package/dist/resources/extensions/gsd/key-manager.js +45 -13
  52. package/dist/resources/extensions/gsd/mcp-filter.js +57 -18
  53. package/dist/resources/extensions/gsd/mcp-project-config.js +15 -9
  54. package/dist/resources/extensions/gsd/migration-auto-check.js +5 -1
  55. package/dist/resources/extensions/gsd/milestone-actions.js +3 -0
  56. package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
  57. package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
  58. package/dist/resources/extensions/gsd/parallel-merge.js +6 -4
  59. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
  60. package/dist/resources/extensions/gsd/post-execution-checks.js +5 -4
  61. package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
  62. package/dist/resources/extensions/gsd/preferences.js +14 -2
  63. package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
  64. package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
  65. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
  66. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  67. package/dist/resources/extensions/gsd/prompts/system.md +3 -20
  68. package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
  69. package/dist/resources/extensions/gsd/repo-identity.js +36 -6
  70. package/dist/resources/extensions/gsd/repository-registry.js +3 -1
  71. package/dist/resources/extensions/gsd/safety/evidence-collector.js +13 -6
  72. package/dist/resources/extensions/gsd/skill-activation.js +233 -0
  73. package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
  74. package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
  75. package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
  76. package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
  77. package/dist/resources/extensions/gsd/skill-scope.js +52 -0
  78. package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
  79. package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
  80. package/dist/resources/extensions/gsd/skills.js +60 -0
  81. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
  82. package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
  83. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
  84. package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
  85. package/dist/resources/extensions/gsd/tools/exec-tool.js +42 -8
  86. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
  87. package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
  88. package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
  89. package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
  90. package/dist/resources/extensions/gsd/vision-ask.js +22 -0
  91. package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
  92. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
  93. package/dist/resources/extensions/gsd/worktree-post-create-hook.js +117 -0
  94. package/dist/resources/extensions/gsd/worktree-state-projection.js +29 -0
  95. package/dist/resources/extensions/search-the-web/native-search.js +57 -8
  96. package/dist/resources/extensions/shared/confirm-ui.js +9 -6
  97. package/dist/resources/extensions/shared/dialog-frame.js +42 -0
  98. package/dist/resources/extensions/shared/interview-ui.js +42 -30
  99. package/dist/resources/extensions/shared/next-action-ui.js +6 -6
  100. package/dist/resources/extensions/subagent/index.js +8 -15
  101. package/dist/resources/shared/package-manager-detection.js +36 -0
  102. package/dist/resources/skills/agent-browser/SKILL.md +1 -1
  103. package/dist/resources/skills/api-design/SKILL.md +1 -1
  104. package/dist/resources/skills/code-optimizer/SKILL.md +6 -11
  105. package/dist/resources/skills/create-gsd-extension/SKILL.md +1 -1
  106. package/dist/resources/skills/create-mcp-server/SKILL.md +1 -1
  107. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  108. package/dist/resources/skills/create-skill/workflows/verify-skill.md +2 -10
  109. package/dist/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
  110. package/dist/resources/skills/decompose-into-slices/SKILL.md +3 -3
  111. package/dist/resources/skills/dependency-upgrade/SKILL.md +1 -1
  112. package/dist/resources/skills/forensics/SKILL.md +2 -2
  113. package/dist/resources/skills/grill-me/SKILL.md +1 -1
  114. package/dist/resources/skills/handoff/SKILL.md +1 -1
  115. package/dist/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
  116. package/dist/resources/skills/observability/SKILL.md +1 -1
  117. package/dist/resources/skills/security-review/SKILL.md +1 -1
  118. package/dist/resources/skills/spike-wrap-up/SKILL.md +1 -1
  119. package/dist/resources/skills/tdd/SKILL.md +1 -1
  120. package/dist/resources/skills/write-docs/SKILL.md +1 -1
  121. package/dist/resources/skills/write-milestone-brief/SKILL.md +1 -1
  122. package/dist/update-check.d.ts +6 -2
  123. package/dist/update-check.js +7 -3
  124. package/dist/web/standalone/.next/BUILD_ID +1 -1
  125. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  126. package/dist/web/standalone/.next/build-manifest.json +2 -2
  127. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  128. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  129. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  134. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  137. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  141. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  142. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  143. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  144. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/index.html +1 -1
  146. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  147. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  148. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  149. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  150. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  153. package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
  154. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  156. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  157. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  158. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  159. package/dist/worktree-cli.d.ts +0 -2
  160. package/dist/worktree-cli.js +21 -9
  161. package/package.json +5 -2
  162. package/packages/cloud-mcp-gateway/bin/gsd-cloud-mcp-gateway.js +14 -0
  163. package/packages/cloud-mcp-gateway/package.json +4 -3
  164. package/packages/contracts/dist/rpc.test.js +5 -0
  165. package/packages/contracts/dist/rpc.test.js.map +1 -1
  166. package/packages/contracts/dist/workflow.d.ts +15 -0
  167. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  168. package/packages/contracts/dist/workflow.js +16 -0
  169. package/packages/contracts/dist/workflow.js.map +1 -1
  170. package/packages/contracts/dist/workflow.test.js +1 -0
  171. package/packages/contracts/dist/workflow.test.js.map +1 -1
  172. package/packages/contracts/package.json +1 -1
  173. package/packages/daemon/package.json +4 -4
  174. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
  175. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  176. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
  177. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  178. package/packages/gsd-agent-core/package.json +5 -5
  179. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
  180. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
  181. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
  182. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
  183. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
  184. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
  186. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
  187. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
  188. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
  190. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
  192. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  193. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
  194. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
  196. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
  197. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
  198. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
  199. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  200. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  201. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
  202. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
  203. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
  204. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  205. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
  206. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  207. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  208. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -1
  209. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  210. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  211. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -2
  212. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  213. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -0
  214. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
  215. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -0
  216. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
  217. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  218. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +2 -1
  219. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  220. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
  221. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  222. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
  223. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  224. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
  225. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
  226. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
  227. package/packages/gsd-agent-modes/package.json +7 -7
  228. package/packages/mcp-server/bin/gsd-mcp-server.js +14 -0
  229. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  230. package/packages/mcp-server/dist/server.js +7 -1
  231. package/packages/mcp-server/dist/server.js.map +1 -1
  232. package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
  233. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  234. package/packages/mcp-server/dist/workflow-tools.js +47 -8
  235. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  236. package/packages/mcp-server/package.json +5 -4
  237. package/packages/native/package.json +1 -1
  238. package/packages/pi-agent-core/dist/agent-loop.js +16 -14
  239. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  240. package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
  241. package/packages/pi-agent-core/dist/harness/skills.js +6 -0
  242. package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
  243. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
  244. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
  245. package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
  246. package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
  247. package/packages/pi-agent-core/package.json +1 -1
  248. package/packages/pi-ai/bin/pi-ai.js +14 -0
  249. package/packages/pi-ai/dist/models.generated.d.ts +48 -206
  250. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  251. package/packages/pi-ai/dist/models.generated.js +73 -226
  252. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  253. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  254. package/packages/pi-ai/dist/providers/anthropic.js +50 -0
  255. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  256. package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
  257. package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
  258. package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
  259. package/packages/pi-ai/dist/types.d.ts +2 -0
  260. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  261. package/packages/pi-ai/dist/types.js.map +1 -1
  262. package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js +29 -1
  263. package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js.map +1 -1
  264. package/packages/pi-ai/dist/utils/tool-search-shim.d.ts +4 -1
  265. package/packages/pi-ai/dist/utils/tool-search-shim.d.ts.map +1 -1
  266. package/packages/pi-ai/dist/utils/tool-search-shim.js +58 -10
  267. package/packages/pi-ai/dist/utils/tool-search-shim.js.map +1 -1
  268. package/packages/pi-ai/dist/utils/tool-shims.d.ts +1 -1
  269. package/packages/pi-ai/dist/utils/tool-shims.d.ts.map +1 -1
  270. package/packages/pi-ai/dist/utils/tool-shims.js.map +1 -1
  271. package/packages/pi-ai/package.json +3 -2
  272. package/packages/pi-coding-agent/README.md +1 -1
  273. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
  274. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  275. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
  277. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  278. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
  280. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  281. package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
  282. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/skills.js +3 -0
  284. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  286. package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -7
  287. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  288. package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -2
  289. package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  290. package/packages/pi-coding-agent/dist/core/tools/read.js +5 -4
  291. package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  292. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/tools/write.js +0 -1
  294. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  295. package/packages/pi-coding-agent/package.json +8 -8
  296. package/packages/pi-tui/package.json +1 -1
  297. package/packages/rpc-client/package.json +2 -2
  298. package/pkg/package.json +1 -1
  299. package/scripts/install/deps.js +10 -0
  300. package/scripts/install/detect-existing.js +17 -3
  301. package/scripts/install/npm-global.js +103 -33
  302. package/scripts/install.js +1 -0
  303. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +36 -11
  304. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +86 -19
  305. package/src/resources/extensions/context7/index.ts +15 -2
  306. package/src/resources/extensions/get-secrets-from-user.ts +17 -16
  307. package/src/resources/extensions/google-cli/index.ts +34 -0
  308. package/src/resources/extensions/google-cli/models.ts +57 -0
  309. package/src/resources/extensions/google-cli/package.json +11 -0
  310. package/src/resources/extensions/google-cli/readiness.ts +15 -0
  311. package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
  312. package/src/resources/extensions/gsd/auto/loop.ts +96 -1
  313. package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
  314. package/src/resources/extensions/gsd/auto/phases.ts +47 -1
  315. package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
  316. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  317. package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
  318. package/src/resources/extensions/gsd/auto-post-unit.ts +101 -18
  319. package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
  320. package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
  321. package/src/resources/extensions/gsd/auto-start.ts +307 -56
  322. package/src/resources/extensions/gsd/auto-tool-tracking.ts +3 -1
  323. package/src/resources/extensions/gsd/auto-verification.ts +18 -2
  324. package/src/resources/extensions/gsd/auto-worktree.ts +47 -57
  325. package/src/resources/extensions/gsd/auto.ts +50 -2
  326. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
  327. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +9 -4
  328. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
  329. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +124 -25
  330. package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
  331. package/src/resources/extensions/gsd/bootstrap/tool-search-shim.ts +4 -4
  332. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
  333. package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
  334. package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
  335. package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
  336. package/src/resources/extensions/gsd/commands-usage.ts +110 -5
  337. package/src/resources/extensions/gsd/config-overlay.ts +19 -16
  338. package/src/resources/extensions/gsd/context-overlay.ts +24 -19
  339. package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
  340. package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
  341. package/src/resources/extensions/gsd/doctor-git-checks.ts +72 -5
  342. package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
  343. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  344. package/src/resources/extensions/gsd/doctor.ts +7 -2
  345. package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
  346. package/src/resources/extensions/gsd/guided-flow.ts +5 -6
  347. package/src/resources/extensions/gsd/key-manager.ts +57 -14
  348. package/src/resources/extensions/gsd/mcp-filter.ts +64 -17
  349. package/src/resources/extensions/gsd/mcp-project-config.ts +24 -9
  350. package/src/resources/extensions/gsd/migration-auto-check.ts +6 -0
  351. package/src/resources/extensions/gsd/milestone-actions.ts +2 -0
  352. package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
  353. package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
  354. package/src/resources/extensions/gsd/parallel-merge.ts +6 -4
  355. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
  356. package/src/resources/extensions/gsd/post-execution-checks.ts +7 -4
  357. package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
  358. package/src/resources/extensions/gsd/preferences.ts +17 -2
  359. package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
  360. package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
  361. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
  362. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  363. package/src/resources/extensions/gsd/prompts/system.md +3 -20
  364. package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
  365. package/src/resources/extensions/gsd/repo-identity.ts +35 -7
  366. package/src/resources/extensions/gsd/repository-registry.ts +3 -1
  367. package/src/resources/extensions/gsd/safety/evidence-collector.ts +13 -6
  368. package/src/resources/extensions/gsd/skill-activation.ts +292 -0
  369. package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
  370. package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
  371. package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
  372. package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
  373. package/src/resources/extensions/gsd/skill-scope.ts +63 -0
  374. package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
  375. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
  376. package/src/resources/extensions/gsd/skills.ts +75 -0
  377. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
  378. package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
  379. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
  380. package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
  381. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
  382. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +75 -0
  383. package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
  384. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +30 -0
  385. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
  386. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +24 -0
  387. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
  388. package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +53 -0
  389. package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
  390. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
  391. package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
  392. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
  393. package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
  394. package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +40 -3
  395. package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
  396. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +64 -0
  397. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
  398. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
  399. package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
  400. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
  401. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +71 -1
  402. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
  403. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
  404. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +30 -0
  405. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
  406. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +22 -3
  407. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +43 -0
  408. package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +8 -0
  409. package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
  410. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +19 -1
  411. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +24 -0
  412. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +56 -1
  413. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
  414. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
  415. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
  416. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +9 -0
  417. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +127 -10
  418. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +44 -0
  419. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
  420. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +101 -0
  421. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
  422. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
  423. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +27 -0
  424. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
  425. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
  426. package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
  427. package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
  428. package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
  429. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
  430. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
  431. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +67 -1
  432. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
  433. package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
  434. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
  435. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
  436. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
  437. package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
  438. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
  439. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +133 -0
  440. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
  441. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
  442. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
  443. package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +141 -1
  444. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +38 -1
  445. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +10 -0
  446. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
  447. package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
  448. package/src/resources/extensions/gsd/tools/exec-tool.ts +42 -10
  449. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
  450. package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
  451. package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
  452. package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
  453. package/src/resources/extensions/gsd/vision-ask.ts +28 -0
  454. package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
  455. package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
  456. package/src/resources/extensions/gsd/worktree-post-create-hook.ts +127 -0
  457. package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -0
  458. package/src/resources/extensions/search-the-web/native-search.ts +60 -8
  459. package/src/resources/extensions/shared/confirm-ui.ts +8 -12
  460. package/src/resources/extensions/shared/dialog-frame.ts +71 -0
  461. package/src/resources/extensions/shared/interview-ui.ts +43 -42
  462. package/src/resources/extensions/shared/next-action-ui.ts +6 -6
  463. package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
  464. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
  465. package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
  466. package/src/resources/extensions/subagent/index.ts +8 -15
  467. package/src/resources/shared/package-manager-detection.ts +39 -0
  468. package/src/resources/skills/agent-browser/SKILL.md +1 -1
  469. package/src/resources/skills/api-design/SKILL.md +1 -1
  470. package/src/resources/skills/code-optimizer/SKILL.md +6 -11
  471. package/src/resources/skills/create-gsd-extension/SKILL.md +1 -1
  472. package/src/resources/skills/create-mcp-server/SKILL.md +1 -1
  473. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  474. package/src/resources/skills/create-skill/workflows/verify-skill.md +2 -10
  475. package/src/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
  476. package/src/resources/skills/decompose-into-slices/SKILL.md +3 -3
  477. package/src/resources/skills/dependency-upgrade/SKILL.md +1 -1
  478. package/src/resources/skills/forensics/SKILL.md +2 -2
  479. package/src/resources/skills/grill-me/SKILL.md +1 -1
  480. package/src/resources/skills/handoff/SKILL.md +1 -1
  481. package/src/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
  482. package/src/resources/skills/observability/SKILL.md +1 -1
  483. package/src/resources/skills/security-review/SKILL.md +1 -1
  484. package/src/resources/skills/spike-wrap-up/SKILL.md +1 -1
  485. package/src/resources/skills/tdd/SKILL.md +1 -1
  486. package/src/resources/skills/write-docs/SKILL.md +1 -1
  487. package/src/resources/skills/write-milestone-brief/SKILL.md +1 -1
  488. package/dist/tsconfig.extensions.tsbuildinfo +0 -1
  489. /package/dist/web/standalone/.next/static/{BEjZM0MLHLibeMFbjtMol → tH1tnDYt1E0hK9Ien73Z0}/_buildManifest.js +0 -0
  490. /package/dist/web/standalone/.next/static/{BEjZM0MLHLibeMFbjtMol → tH1tnDYt1E0hK9Ien73Z0}/_ssgManifest.js +0 -0
@@ -0,0 +1,55 @@
1
+ const ZERO_COST = {
2
+ input: 0,
3
+ output: 0,
4
+ cacheRead: 0,
5
+ cacheWrite: 0,
6
+ };
7
+ export const GOOGLE_GEMINI_CLI_MODELS = [
8
+ {
9
+ id: "gemini-2.5-flash",
10
+ name: "Gemini 2.5 Flash",
11
+ reasoning: true,
12
+ input: ["text"],
13
+ cost: ZERO_COST,
14
+ contextWindow: 1_000_000,
15
+ maxTokens: 65_536,
16
+ },
17
+ {
18
+ id: "gemini-2.5-pro",
19
+ name: "Gemini 2.5 Pro",
20
+ reasoning: true,
21
+ input: ["text"],
22
+ cost: ZERO_COST,
23
+ contextWindow: 1_000_000,
24
+ maxTokens: 65_536,
25
+ },
26
+ {
27
+ id: "gemini-3-flash-preview",
28
+ name: "Gemini 3 Flash Preview",
29
+ reasoning: true,
30
+ input: ["text"],
31
+ cost: ZERO_COST,
32
+ contextWindow: 1_000_000,
33
+ maxTokens: 65_536,
34
+ },
35
+ {
36
+ id: "gemini-3.1-pro-preview",
37
+ name: "Gemini 3.1 Pro Preview",
38
+ reasoning: true,
39
+ input: ["text"],
40
+ cost: ZERO_COST,
41
+ contextWindow: 1_000_000,
42
+ maxTokens: 65_536,
43
+ },
44
+ ];
45
+ export const GOOGLE_ANTIGRAVITY_MODELS = [
46
+ {
47
+ id: "default",
48
+ name: "Antigravity Default",
49
+ reasoning: true,
50
+ input: ["text"],
51
+ cost: ZERO_COST,
52
+ contextWindow: 1_000_000,
53
+ maxTokens: 65_536,
54
+ },
55
+ ];
@@ -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.js"
9
+ ]
10
+ }
11
+ }
@@ -0,0 +1,12 @@
1
+ import { spawnSync } from "node:child_process";
2
+ function isCommandInPath(command) {
3
+ const resolver = process.platform === "win32" ? "where" : "which";
4
+ const result = spawnSync(resolver, [command], { stdio: "ignore" });
5
+ return result.status === 0;
6
+ }
7
+ export function isGeminiCliReady() {
8
+ return isCommandInPath("gemini");
9
+ }
10
+ export function isAntigravityCliReady() {
11
+ return isCommandInPath("agy");
12
+ }
@@ -0,0 +1,191 @@
1
+ import { spawn } from "node:child_process";
2
+ import { createAssistantMessageEventStream } from "@gsd/pi-ai";
3
+ const ZERO_USAGE = {
4
+ input: 0,
5
+ output: 0,
6
+ cacheRead: 0,
7
+ cacheWrite: 0,
8
+ totalTokens: 0,
9
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
10
+ };
11
+ function textBlocks(content) {
12
+ return content
13
+ .map((block) => block.type === "text" ? block.text : `[${block.type} omitted]`)
14
+ .join("\n");
15
+ }
16
+ function messageToText(message) {
17
+ if (message.role === "user") {
18
+ const content = typeof message.content === "string" ? message.content : textBlocks(message.content);
19
+ return `User:\n${content}`;
20
+ }
21
+ if (message.role === "assistant") {
22
+ const text = message.content
23
+ .map((block) => {
24
+ if (block.type === "text")
25
+ return block.text;
26
+ if (block.type === "thinking")
27
+ return `[thinking omitted]`;
28
+ if (block.type === "toolCall")
29
+ return `[tool call: ${block.name}]`;
30
+ if (block.type === "serverToolUse")
31
+ return `[server tool: ${block.name}]`;
32
+ if (block.type === "webSearchResult")
33
+ return `[web search result omitted]`;
34
+ return `[${block.type} omitted]`;
35
+ })
36
+ .join("\n");
37
+ return `Assistant:\n${text}`;
38
+ }
39
+ return `Tool result (${message.toolName}):\n${textBlocks(message.content)}`;
40
+ }
41
+ export function buildGoogleCliPrompt(context) {
42
+ const parts = [];
43
+ if (context.systemPrompt?.trim()) {
44
+ parts.push(`System instructions:\n${context.systemPrompt.trim()}`);
45
+ }
46
+ if (context.messages.length > 0) {
47
+ parts.push(context.messages.map(messageToText).join("\n\n"));
48
+ }
49
+ if (context.tools?.length) {
50
+ const names = context.tools.map((tool) => tool.name).join(", ");
51
+ parts.push(`Available local GSD tools were not forwarded to this external CLI bridge. ` +
52
+ `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. ` +
53
+ `Requested GSD tools: ${names}`);
54
+ }
55
+ return parts.join("\n\n").trim();
56
+ }
57
+ function buildAssistantMessage(model, text, stopReason = "stop", errorMessage) {
58
+ return {
59
+ role: "assistant",
60
+ content: text ? [{ type: "text", text }] : [],
61
+ api: model.api,
62
+ provider: model.provider,
63
+ model: model.id,
64
+ usage: { ...ZERO_USAGE, cost: { ...ZERO_USAGE.cost } },
65
+ stopReason,
66
+ ...(errorMessage ? { errorMessage } : {}),
67
+ timestamp: Date.now(),
68
+ };
69
+ }
70
+ function extractGeminiJsonResponse(raw) {
71
+ const trimmed = raw.trim();
72
+ if (!trimmed)
73
+ return "";
74
+ try {
75
+ const parsed = JSON.parse(trimmed);
76
+ for (const key of ["response", "text", "content", "message"]) {
77
+ const value = parsed[key];
78
+ if (typeof value === "string")
79
+ return value;
80
+ }
81
+ return JSON.stringify(parsed, null, 2);
82
+ }
83
+ catch {
84
+ return trimmed;
85
+ }
86
+ }
87
+ function commandForProvider(provider) {
88
+ return provider === "google-gemini-cli" ? "gemini" : "agy";
89
+ }
90
+ function argsForProvider(provider, model, prompt) {
91
+ if (provider === "google-gemini-cli") {
92
+ const args = ["-p", prompt, "--output-format", "json"];
93
+ if (model.id !== "default")
94
+ args.unshift("-m", model.id);
95
+ return args;
96
+ }
97
+ const args = ["-p", prompt];
98
+ if (model.id !== "default")
99
+ args.unshift("-m", model.id);
100
+ return args;
101
+ }
102
+ export function buildGoogleCliSpawnInvocation(command, args, platform = process.platform) {
103
+ if (platform === "win32") {
104
+ return { command: "cmd", args: ["/c", command, ...args] };
105
+ }
106
+ return { command, args };
107
+ }
108
+ function runCli(command, args, options) {
109
+ return new Promise((resolve, reject) => {
110
+ const invocation = buildGoogleCliSpawnInvocation(command, args);
111
+ const child = spawn(invocation.command, invocation.args, {
112
+ cwd: options?.cwd || process.cwd(),
113
+ env: process.env,
114
+ stdio: ["ignore", "pipe", "pipe"],
115
+ });
116
+ let stdout = "";
117
+ let stderr = "";
118
+ let settled = false;
119
+ const settle = (fn) => {
120
+ if (settled)
121
+ return;
122
+ settled = true;
123
+ options?.signal?.removeEventListener("abort", onAbort);
124
+ fn();
125
+ };
126
+ const onAbort = () => {
127
+ child.kill("SIGTERM");
128
+ settle(() => reject(new Error("Request was aborted")));
129
+ };
130
+ if (options?.signal?.aborted) {
131
+ onAbort();
132
+ return;
133
+ }
134
+ options?.signal?.addEventListener("abort", onAbort);
135
+ child.stdout.setEncoding("utf8");
136
+ child.stderr.setEncoding("utf8");
137
+ child.stdout.on("data", (chunk) => {
138
+ stdout += chunk;
139
+ });
140
+ child.stderr.on("data", (chunk) => {
141
+ stderr += chunk;
142
+ });
143
+ child.on("error", (error) => {
144
+ settle(() => reject(error));
145
+ });
146
+ child.on("close", (code, signal) => {
147
+ settle(() => resolve({ stdout, stderr, code, signal }));
148
+ });
149
+ });
150
+ }
151
+ function emitText(stream, message, text) {
152
+ stream.push({ type: "start", partial: { ...message, content: [] } });
153
+ if (text) {
154
+ stream.push({ type: "text_start", contentIndex: 0, partial: message });
155
+ stream.push({ type: "text_delta", contentIndex: 0, delta: text, partial: message });
156
+ stream.push({ type: "text_end", contentIndex: 0, content: text, partial: message });
157
+ }
158
+ stream.push({ type: "done", reason: "stop", message });
159
+ stream.end(message);
160
+ }
161
+ function emitError(stream, model, error) {
162
+ const message = error instanceof Error ? error.message : String(error);
163
+ const output = buildAssistantMessage(model, "", "error", message);
164
+ stream.push({ type: "error", reason: "error", error: output });
165
+ stream.end(output);
166
+ }
167
+ export function streamViaGoogleCli(model, context, options) {
168
+ const stream = createAssistantMessageEventStream();
169
+ const provider = model.provider;
170
+ queueMicrotask(async () => {
171
+ try {
172
+ const prompt = buildGoogleCliPrompt(context);
173
+ const command = commandForProvider(provider);
174
+ const args = argsForProvider(provider, model, prompt);
175
+ const result = await runCli(command, args, options);
176
+ if (result.code !== 0) {
177
+ const detail = (result.stderr || result.stdout || `CLI exited with code ${result.code}`).trim();
178
+ throw new Error(detail);
179
+ }
180
+ const text = provider === "google-gemini-cli"
181
+ ? extractGeminiJsonResponse(result.stdout)
182
+ : result.stdout.trim();
183
+ const message = buildAssistantMessage(model, text);
184
+ emitText(stream, message, text);
185
+ }
186
+ catch (error) {
187
+ emitError(stream, model, error);
188
+ }
189
+ });
190
+ return stream;
191
+ }
@@ -50,6 +50,7 @@ import { handleCustomEngineVerifyPause, handleCustomEngineVerifyRetryOutcome, }
50
50
  import { handleCustomEngineReconcile } from "./workflow-custom-engine-reconcile.js";
51
51
  import { handleCustomEngineReconcileOutcome } from "./workflow-custom-engine-reconcile-outcome.js";
52
52
  import { formatLeaseConflictNotice } from "./lease-conflict-notice.js";
53
+ import { setAutoOutcomeWidget, unitVerb } from "../auto-dashboard.js";
53
54
  /**
54
55
  * Returns true if workerId is an active worker in this project whose OS
55
56
  * process no longer exists. Used to detect dead lease holders before
@@ -690,6 +691,24 @@ export async function autoLoop(ctx, pi, s, deps, options) {
690
691
  });
691
692
  if (reconcileFlow.action === "break")
692
693
  break;
694
+ if (s.stepMode) {
695
+ if (ctx.hasUI) {
696
+ ctx.ui.setWidget?.("gsd-progress", undefined);
697
+ setAutoOutcomeWidget(ctx, {
698
+ status: "step",
699
+ title: "Step complete",
700
+ detail: `Completed ${unitVerb(iterData.unitType)} ${iterData.unitId}.`,
701
+ unitLabel: `${unitVerb(iterData.unitType)} ${iterData.unitId}`,
702
+ nextAction: "Advance one step, or resume automatic mode.",
703
+ commands: ["/gsd next", "/gsd auto", "/gsd status for overview"],
704
+ startedAt: s.autoStartTime,
705
+ });
706
+ }
707
+ ctx.ui.setStatus("gsd-auto", "next");
708
+ ctx.ui.notify(`Step complete: ${unitVerb(iterData.unitType)} ${iterData.unitId}. Run /gsd next for the next step, or /gsd auto to continue automatically.`, "info");
709
+ s.preserveStepSurfaceAfterLoopExit = true;
710
+ break;
711
+ }
693
712
  continue;
694
713
  }
695
714
  if (!sidecarItem) {
@@ -713,11 +732,36 @@ export async function autoLoop(ctx, pi, s, deps, options) {
713
732
  message: orchestrationResult.reason,
714
733
  category: "unknown",
715
734
  });
735
+ finishTurn("paused", "manual-attention", "orchestration-blocked");
716
736
  }
717
737
  else {
718
738
  await deps.stopAuto(ctx, pi, orchestrationResult.reason);
739
+ finishTurn("stopped", "manual-attention", "orchestration-blocked");
719
740
  }
720
- finishTurn("stopped", "manual-attention", "orchestration-blocked");
741
+ finishIncompleteIteration({
742
+ status: orchestrationResult.action === "pause" ? "paused" : "stopped",
743
+ reason: orchestrationResult.reason,
744
+ failureClass: "manual-attention",
745
+ });
746
+ break;
747
+ }
748
+ if (orchestrationResult.kind === "paused") {
749
+ s.pendingOrchestrationDispatch = null;
750
+ finishTurn("skipped");
751
+ continue;
752
+ }
753
+ if (orchestrationResult.kind === "error") {
754
+ s.pendingOrchestrationDispatch = null;
755
+ await deps.pauseAuto(ctx, pi, {
756
+ message: orchestrationResult.reason,
757
+ category: "unknown",
758
+ });
759
+ finishTurn("paused", "manual-attention", `orchestration-${orchestrationResult.kind}`);
760
+ finishIncompleteIteration({
761
+ status: "paused",
762
+ reason: orchestrationResult.reason,
763
+ failureClass: "manual-attention",
764
+ });
721
765
  break;
722
766
  }
723
767
  if (orchestrationResult.kind === "stopped") {
@@ -750,6 +794,42 @@ export async function autoLoop(ctx, pi, s, deps, options) {
750
794
  isRetry: false,
751
795
  previousTier: undefined,
752
796
  };
797
+ const preDispatchResult = deps.runPreDispatchHooks(iterData.unitType, iterData.unitId, iterData.prompt, s.basePath);
798
+ if (preDispatchResult.firedHooks.length > 0) {
799
+ ctx.ui.notify(`Pre-dispatch hook${preDispatchResult.firedHooks.length > 1 ? "s" : ""}: ${preDispatchResult.firedHooks.join(", ")}`, "info");
800
+ deps.emitJournalEvent({
801
+ ts: new Date().toISOString(),
802
+ flowId: ic.flowId,
803
+ seq: ic.nextSeq(),
804
+ eventType: "pre-dispatch-hook",
805
+ data: {
806
+ firedHooks: preDispatchResult.firedHooks,
807
+ action: preDispatchResult.action,
808
+ },
809
+ });
810
+ }
811
+ if (preDispatchResult.action === "skip") {
812
+ ctx.ui.notify(`Skipping ${iterData.unitType} ${iterData.unitId} (pre-dispatch hook).`, "info");
813
+ s.pendingOrchestrationDispatch = null;
814
+ emitIterationEnd({ skipped: true });
815
+ completeIteration();
816
+ finishTurn("skipped");
817
+ continue;
818
+ }
819
+ if (preDispatchResult.action === "replace") {
820
+ iterData.prompt = preDispatchResult.prompt ?? iterData.prompt;
821
+ iterData.finalPrompt = iterData.prompt;
822
+ if (preDispatchResult.unitType) {
823
+ iterData.unitType = preDispatchResult.unitType;
824
+ }
825
+ }
826
+ else if (preDispatchResult.prompt) {
827
+ iterData.prompt = preDispatchResult.prompt;
828
+ iterData.finalPrompt = preDispatchResult.prompt;
829
+ }
830
+ if (preDispatchResult.model) {
831
+ iterData.hookModelOverride = preDispatchResult.model;
832
+ }
753
833
  s.pendingOrchestrationDispatch = null;
754
834
  phaseReporter.report("dispatch", "next", {
755
835
  unitType: iterData.unitType,
@@ -369,9 +369,11 @@ export class AutoOrchestrator {
369
369
  const activeUnitKey = this.status.activeUnit
370
370
  ? `${this.status.activeUnit.unitType}:${this.status.activeUnit.unitId}`
371
371
  : null;
372
- if (activeUnitKey !== unitKey)
372
+ if (activeUnitKey !== unitKey && this.lastFinalizedUnitKey !== unitKey)
373
373
  return;
374
- this.status.activeUnit = undefined;
374
+ if (activeUnitKey === unitKey) {
375
+ this.status.activeUnit = undefined;
376
+ }
375
377
  this.lastAdvanceKey = null;
376
378
  this.lastFinalizedUnitKey = null;
377
379
  this.bumpTransition();
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import { importExtensionModule } from "@gsd/pi-coding-agent";
12
12
  import { USER_DRIVEN_DEEP_UNITS, isAwaitingUserInput, } from "../auto-post-unit.js";
13
+ import { lastAssistantText } from "../user-input-boundary.js";
13
14
  import { MAX_RECOVERY_CHARS, BUDGET_THRESHOLDS, MAX_FINALIZE_TIMEOUTS, } from "./types.js";
14
15
  import { detectStuck } from "./detect-stuck.js";
15
16
  import { runUnit } from "./run-unit.js";
@@ -52,8 +53,19 @@ import { decideVerificationRetry, verificationRetryKey } from "./verification-re
52
53
  import { buildPhaseHandoffOutcome, setAutoOutcomeWidget } from "../auto-dashboard.js";
53
54
  import { getConsecutiveDispatchBlocker } from "../dispatch-guard.js";
54
55
  import { captureRootDirtySnapshot, detectRootWriteLeak, formatRootWriteLeakMessage, } from "../root-write-leak-guard.js";
56
+ import { classifyError, isTransient } from "../error-classifier.js";
55
57
  export const STUCK_WINDOW_SIZE = 6;
56
58
  const STUCK_RECOVERY_ATTEMPTS_KEY = "stuck_recovery_attempts";
59
+ const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE = /^(?:api error(?::|$|\s*\()|provider error(?::|$|\s*\()|request failed\b|(?:http\s*)?(?:429|500|502|503)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|socket hang up\b|fetch failed\b|(?:network|connection|server) error(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|dns\b.*(?:fail|error|timeout)|unexpected eof\b|stream idle timeout\b|partial response received\b|stream_exhausted\b|terminated(?::|$)|(?:connection|stream|request)\b.{0,40}\bterminated\b|other side closed\b|rate.?limit(?:ed| exceeded| reached| error)|too many requests\b|you(?:'ve| have) hit your limit\b|usage limit\b|out of extra usage\b|service.?unavailable\b|internal(?: server)? error(?::|$)|internal(?:[_-]server)?[_-]error\b|server[_-]error\b|(?:provider|server|api|model|codex|claude|openai|anthropic|gemini)\b.{0,80}\boverloaded\b|overloaded\b.{0,80}\b(?:provider|server|api|model)\b|context (?:window|length) exceed|context window exceed)/i;
60
+ const ZERO_TOOL_PROVIDER_ERROR_SIGNAL_RE = /(?:\b(?:http|status(?: code)?|code|error:)\s*(?:429|500|502|503)\b|\b(?:api|provider) error\s*[:(]?\s*(?:429|500|502|503)\b|\b(?:typeerror|error):\s*(?:fetch failed\b|socket hang up\b|terminated(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|(?:network|connection|server) error(?::|$)|stream idle timeout\b|partial response received\b|unexpected eof\b)|\b(?:server_error|api_error|stream_exhausted(?:_without_result)?)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|context (?:window|length) exceed|context window exceed)/i;
61
+ function classifyZeroToolProviderMessage(message) {
62
+ const firstLine = message.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
63
+ if (!firstLine ||
64
+ (!ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE.test(firstLine) &&
65
+ !ZERO_TOOL_PROVIDER_ERROR_SIGNAL_RE.test(firstLine)))
66
+ return null;
67
+ return classifyError(firstLine);
68
+ }
57
69
  export function resolveDispatchRecoveryAttempts(unitRecoveryCount, unitType, unitId) {
58
70
  return (unitRecoveryCount.get(`${unitType}/${unitId}`) ?? 0) > 0
59
71
  ? 0
@@ -1568,7 +1580,7 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
1568
1580
  const dispatchKey = `${unitType}/${unitId}`;
1569
1581
  const nextDispatchCount = (s.unitDispatchCount.get(dispatchKey) ?? 0) + 1;
1570
1582
  // Status bar (widget + preconditions deferred until after model selection — see #2899)
1571
- ctx.ui.setStatus("gsd-auto", "auto");
1583
+ ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
1572
1584
  if (mid)
1573
1585
  deps.updateSliceProgressCache(s.basePath, mid, state.activeSlice?.id);
1574
1586
  // ── Safety harness: reset evidence + create checkpoint ──
@@ -1999,6 +2011,31 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
1999
2011
  if (currentLedger?.units) {
2000
2012
  const lastUnit = [...currentLedger.units].reverse().find((u) => u.type === unitType && u.id === unitId && u.startedAt === _resolveCurrentUnitStartedAtForTest(s.currentUnit));
2001
2013
  if (lastUnit && lastUnit.toolCalls === 0) {
2014
+ const lastAssistantMessage = lastAssistantText(s.lastUnitAgentEndMessages);
2015
+ const providerMessageClass = classifyZeroToolProviderMessage(lastAssistantMessage);
2016
+ if (providerMessageClass && isTransient(providerMessageClass)) {
2017
+ const retryAfterMs = "retryAfterMs" in providerMessageClass ? providerMessageClass.retryAfterMs : 15_000;
2018
+ await pauseAutoForProviderError(ctx.ui, ` for ${unitType} ${unitId}`, () => deps.pauseAuto(ctx, pi), {
2019
+ isRateLimit: providerMessageClass.kind === "rate-limit",
2020
+ isTransient: true,
2021
+ retryAfterMs,
2022
+ resume: () => {
2023
+ void resumeAutoAfterProviderDelay(pi, ctx).catch((err) => {
2024
+ logWarning("engine", `Provider error auto-resume failed: ${err instanceof Error ? err.message : String(err)}`);
2025
+ });
2026
+ },
2027
+ });
2028
+ await emitCancelledUnitEnd(ic, unitType, unitId, unitStartSeq, {
2029
+ message: lastAssistantMessage.slice(0, 200),
2030
+ category: "provider",
2031
+ isTransient: true,
2032
+ retryAfterMs,
2033
+ });
2034
+ return {
2035
+ action: "break",
2036
+ reason: providerMessageClass.kind === "rate-limit" ? "rate-limit" : "api-timeout",
2037
+ };
2038
+ }
2002
2039
  if (USER_DRIVEN_DEEP_UNITS.has(unitType) && isAwaitingUserInput(s.lastUnitAgentEndMessages ?? undefined)) {
2003
2040
  debugLog("runUnitPhase", {
2004
2041
  phase: "zero-tool-calls-awaiting-user-input",
@@ -7,6 +7,7 @@ import { logWarning } from "../workflow-logger.js";
7
7
  import { resolveAutoSupervisorConfig } from "../preferences.js";
8
8
  import { readUnitRuntimeRecord } from "../unit-runtime.js";
9
9
  import { consumeAutoWakeup } from "./schedule-wakeup.js";
10
+ import { applyUnitSkillVisibility } from "../skill-scope.js";
10
11
  const UNIT_FAILSAFE_BUFFER_MS = 30_000;
11
12
  const UNIT_FAILSAFE_RECHECK_MS = 30_000;
12
13
  const WAKEUP_SLEEP_CHUNK_MS = 1_000;
@@ -123,6 +124,10 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
123
124
  };
124
125
  }
125
126
  }
127
+ const setVisibleSkills = typeof pi.setVisibleSkills === "function" ? pi.setVisibleSkills.bind(pi) : undefined;
128
+ if (setVisibleSkills) {
129
+ applyUnitSkillVisibility({ setVisibleSkills }, unitType);
130
+ }
126
131
  // ── Create the agent_end promise (per-unit one-shot) ──
127
132
  // This happens after newSession completes so session-switch agent_end events
128
133
  // from the previous session cannot resolve the new unit.
@@ -134,6 +139,7 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
134
139
  const pendingSwitchCancellation = _consumePendingSwitchCancellation();
135
140
  if (pendingSwitchCancellation) {
136
141
  _clearCurrentResolve();
142
+ setVisibleSkills?.(undefined);
137
143
  return {
138
144
  status: "cancelled",
139
145
  ...(pendingSwitchCancellation.errorContext ? { errorContext: pendingSwitchCancellation.errorContext } : {}),
@@ -156,6 +162,7 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
156
162
  }
157
163
  if (!ready) {
158
164
  _clearCurrentResolve();
165
+ setVisibleSkills?.(undefined);
159
166
  return {
160
167
  status: "cancelled",
161
168
  errorContext: {
@@ -290,6 +297,7 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
290
297
  if (unitTimeoutHandle)
291
298
  clearTimeout(unitTimeoutHandle);
292
299
  ctx.ui.setWorkingMessage?.(undefined);
300
+ setVisibleSkills?.(undefined);
293
301
  }
294
302
  debugLog("runUnit", {
295
303
  phase: "agent-end-received",
@@ -132,6 +132,8 @@ export class AutoSession {
132
132
  // ── Isolation degradation ────────────────────────────────────────────
133
133
  /** Set to true when worktree creation fails; prevents merge of nonexistent branch. */
134
134
  isolationDegraded = false;
135
+ /** Temporary recovery mode for stranded work adopted from physical git evidence. */
136
+ strandedRecoveryIsolationMode = null;
135
137
  /** Project-root dirty snapshot captured before an isolated worktree unit runs. */
136
138
  rootWriteBaseline = null;
137
139
  // ── Merge guard ──────────────────────────────────────────────────────
@@ -285,6 +287,7 @@ export class AutoSession {
285
287
  this.lastGitActionFailure = null;
286
288
  this.lastGitActionStatus = null;
287
289
  this.isolationDegraded = false;
290
+ this.strandedRecoveryIsolationMode = null;
288
291
  this.rootWriteBaseline = null;
289
292
  this.milestoneMergedInPhases = false;
290
293
  this.milestoneStartShas = new Map();
@@ -33,6 +33,11 @@ import { resolveWorktreeProjectRoot } from "./worktree-root.js";
33
33
  import { probeGitConflictState } from "./git-conflict-state.js";
34
34
  import { runTurnGitAction } from "./git-service.js";
35
35
  import { parseUnitId } from "./unit-id.js";
36
+ import { resolveExpectedArtifactPath } from "./auto-artifact-paths.js";
37
+ function resolveExistingExpectedArtifact(unitType, unitId, basePath) {
38
+ const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
39
+ return artifactPath && existsSync(artifactPath) ? artifactPath : null;
40
+ }
36
41
  let reassessmentChecker = checkNeedsReassessment;
37
42
  let researchProjectPromptBuilder = buildResearchProjectPrompt;
38
43
  function shouldBypassMilestoneDepthGateInAuto(prefs) {
@@ -808,13 +813,15 @@ export const DISPATCH_RULES = [
808
813
  if (await getMilestonePipelineVariant(mid) === "trivial")
809
814
  return null;
810
815
  // Load roadmap to find all slices
811
- const roadmapFile = resolveMilestoneFile(basePath, mid, "ROADMAP");
816
+ const roadmapFile = resolveExistingExpectedArtifact("plan-milestone", mid, basePath) ??
817
+ resolveMilestoneFile(basePath, mid, "ROADMAP");
812
818
  const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
813
819
  if (!roadmapContent)
814
820
  return null;
815
821
  const roadmap = parseRoadmap(roadmapContent);
816
822
  // Find slices that need research (no RESEARCH file, dependencies done)
817
- const milestoneResearchFile = resolveMilestoneFile(basePath, mid, "RESEARCH");
823
+ const milestoneResearchFile = resolveExistingExpectedArtifact("research-milestone", mid, basePath) ??
824
+ resolveMilestoneFile(basePath, mid, "RESEARCH");
818
825
  const researchReadySlices = [];
819
826
  for (const slice of roadmap.slices) {
820
827
  if (slice.done)
@@ -823,10 +830,10 @@ export const DISPATCH_RULES = [
823
830
  if (milestoneResearchFile && slice.id === "S01")
824
831
  continue;
825
832
  // Skip if already has research
826
- if (resolveSliceFile(basePath, mid, slice.id, "RESEARCH"))
833
+ if (resolveExistingExpectedArtifact("research-slice", `${mid}/${slice.id}`, basePath))
827
834
  continue;
828
835
  // Skip if dependencies aren't done (check for SUMMARY files)
829
- const depsComplete = (slice.depends ?? []).every((depId) => !!resolveSliceFile(basePath, mid, depId, "SUMMARY"));
836
+ const depsComplete = (slice.depends ?? []).every((depId) => !!resolveExistingExpectedArtifact("complete-slice", `${mid}/${depId}`, basePath));
830
837
  if (!depsComplete)
831
838
  continue;
832
839
  researchReadySlices.push({ id: slice.id, title: slice.title });
@@ -837,7 +844,8 @@ export const DISPATCH_RULES = [
837
844
  // #4414: If a previous parallel-research attempt escalated to a blocker
838
845
  // placeholder, skip this rule and fall through to per-slice research
839
846
  // (or other rules) rather than re-dispatching the same failing unit.
840
- const parallelBlocker = resolveMilestoneFile(basePath, mid, "PARALLEL-BLOCKER");
847
+ const parallelBlocker = resolveExistingExpectedArtifact("research-slice", `${mid}/parallel-research`, basePath) ??
848
+ resolveMilestoneFile(basePath, mid, "PARALLEL-BLOCKER");
841
849
  if (parallelBlocker)
842
850
  return null;
843
851
  return {
@@ -863,12 +871,14 @@ export const DISPATCH_RULES = [
863
871
  return missingSliceStop(mid, state.phase);
864
872
  const sid = state.activeSlice.id;
865
873
  const sTitle = state.activeSlice.title;
866
- const researchFile = resolveSliceFile(basePath, mid, sid, "RESEARCH");
874
+ const researchFile = resolveExistingExpectedArtifact("research-slice", `${mid}/${sid}`, basePath) ??
875
+ resolveSliceFile(basePath, mid, sid, "RESEARCH");
867
876
  if (researchFile)
868
877
  return null; // has research, fall through
869
878
  // Skip slice research for S01 when milestone research already exists —
870
879
  // the milestone research already covers the same ground for the first slice.
871
- const milestoneResearchFile = resolveMilestoneFile(basePath, mid, "RESEARCH");
880
+ const milestoneResearchFile = resolveExistingExpectedArtifact("research-milestone", mid, basePath) ??
881
+ resolveMilestoneFile(basePath, mid, "RESEARCH");
872
882
  if (milestoneResearchFile && sid === "S01")
873
883
  return null; // fall through to plan-slice
874
884
  return {