@opengsd/gsd-pi 1.8.1 → 1.9.0-dev.97ef11e3

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 (613) hide show
  1. package/README.md +10 -8
  2. package/dist/cli.js +5 -1
  3. package/dist/headless-events.d.ts +2 -1
  4. package/dist/headless-events.js +11 -3
  5. package/dist/headless-milestone-readiness.d.ts +29 -0
  6. package/dist/headless-milestone-readiness.js +161 -0
  7. package/dist/headless.js +27 -3
  8. package/dist/print-mode-exit.d.ts +12 -0
  9. package/dist/print-mode-exit.js +14 -0
  10. package/dist/resources/.managed-resources-content-hash +1 -1
  11. package/dist/resources/GSD-WORKFLOW.md +18 -49
  12. package/dist/resources/extensions/browser-tools/capture.js +2 -77
  13. package/dist/resources/extensions/browser-tools/screenshot-constraints.js +83 -0
  14. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +17 -2
  15. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +30 -2
  16. package/dist/resources/extensions/gsd/artifact-verification.js +3 -4
  17. package/dist/resources/extensions/gsd/auto/loop.js +24 -4
  18. package/dist/resources/extensions/gsd/auto/run-unit.js +19 -1
  19. package/dist/resources/extensions/gsd/auto/unit-phase.js +37 -5
  20. package/dist/resources/extensions/gsd/auto-artifact-paths.js +16 -10
  21. package/dist/resources/extensions/gsd/auto-dispatch.js +76 -19
  22. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -0
  23. package/dist/resources/extensions/gsd/auto-prompts.js +137 -22
  24. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  25. package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -5
  26. package/dist/resources/extensions/gsd/auto-start.js +29 -9
  27. package/dist/resources/extensions/gsd/auto-tool-tracking.js +40 -0
  28. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
  29. package/dist/resources/extensions/gsd/auto-worktree-sync.js +7 -3
  30. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
  31. package/dist/resources/extensions/gsd/auto.js +20 -6
  32. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -4
  33. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -7
  34. package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
  35. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -50
  36. package/dist/resources/extensions/gsd/command-feedback.js +16 -12
  37. package/dist/resources/extensions/gsd/commands-verdict.js +10 -9
  38. package/dist/resources/extensions/gsd/compat/compat-marker.js +98 -6
  39. package/dist/resources/extensions/gsd/constants.js +12 -13
  40. package/dist/resources/extensions/gsd/context-masker.js +97 -21
  41. package/dist/resources/extensions/gsd/db/command-queue.js +7 -2
  42. package/dist/resources/extensions/gsd/db/engine.js +56 -18
  43. package/dist/resources/extensions/gsd/db/writers/cascades.js +5 -1
  44. package/dist/resources/extensions/gsd/db/writers/status.js +13 -3
  45. package/dist/resources/extensions/gsd/db-base-schema.js +28 -0
  46. package/dist/resources/extensions/gsd/db-migration-steps.js +30 -0
  47. package/dist/resources/extensions/gsd/db-schema-metadata.js +4 -1
  48. package/dist/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  49. package/dist/resources/extensions/gsd/doctor-engine-checks.js +24 -8
  50. package/dist/resources/extensions/gsd/error-classifier.js +12 -2
  51. package/dist/resources/extensions/gsd/exec-sandbox.js +1 -0
  52. package/dist/resources/extensions/gsd/flat-phase-migration.js +168 -21
  53. package/dist/resources/extensions/gsd/git-service.js +19 -7
  54. package/dist/resources/extensions/gsd/gsd-db.js +262 -76
  55. package/dist/resources/extensions/gsd/guided-flow.js +40 -15
  56. package/dist/resources/extensions/gsd/markdown-renderer.js +20 -22
  57. package/dist/resources/extensions/gsd/md-importer.js +107 -20
  58. package/dist/resources/extensions/gsd/migrate/command.js +19 -162
  59. package/dist/resources/extensions/gsd/migrate/execution.js +98 -0
  60. package/dist/resources/extensions/gsd/migrate/plan.js +49 -0
  61. package/dist/resources/extensions/gsd/migrate/planning-writer.js +12 -17
  62. package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
  63. package/dist/resources/extensions/gsd/model-cost-table.js +2 -0
  64. package/dist/resources/extensions/gsd/model-router.js +11 -0
  65. package/dist/resources/extensions/gsd/parallel-eligibility.js +5 -4
  66. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +28 -43
  67. package/dist/resources/extensions/gsd/paths.js +70 -16
  68. package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
  69. package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
  70. package/dist/resources/extensions/gsd/planning-subagent-registry.js +25 -0
  71. package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
  72. package/dist/resources/extensions/gsd/preferences-types.js +5 -0
  73. package/dist/resources/extensions/gsd/preferences-validation.js +48 -1
  74. package/dist/resources/extensions/gsd/preferences.js +17 -0
  75. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  76. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
  77. package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
  78. package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
  79. package/dist/resources/extensions/gsd/safety/evidence-collector.js +26 -1
  80. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +30 -5
  81. package/dist/resources/extensions/gsd/skill-activation.js +17 -3
  82. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +125 -15
  83. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +17 -4
  84. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +5 -2
  85. package/dist/resources/extensions/gsd/stop-notice.js +24 -1
  86. package/dist/resources/extensions/gsd/sync-lock.js +13 -7
  87. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  88. package/dist/resources/extensions/gsd/tools/complete-task.js +94 -6
  89. package/dist/resources/extensions/gsd/tools/plan-task.js +13 -15
  90. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +18 -15
  91. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
  92. package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
  93. package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
  94. package/dist/resources/extensions/gsd/tools/replan-task.js +128 -0
  95. package/dist/resources/extensions/gsd/tools/rework-brief.js +74 -0
  96. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +81 -0
  97. package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
  98. package/dist/resources/extensions/gsd/unit-registry.js +4 -0
  99. package/dist/resources/extensions/gsd/uok/plan-v2.js +19 -3
  100. package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
  101. package/dist/resources/extensions/gsd/workspace.js +2 -1
  102. package/dist/resources/extensions/gsd/worktree-state-projection.js +26 -18
  103. package/dist/resources/extensions/mac-tools/index.js +31 -9
  104. package/dist/resources/extensions/shared/interview-ui.js +43 -6
  105. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  106. package/dist/web/standalone/.next/BUILD_ID +1 -1
  107. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  108. package/dist/web/standalone/.next/build-manifest.json +3 -3
  109. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  110. package/dist/web/standalone/.next/required-server-files.json +3 -3
  111. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  112. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  122. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  125. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  126. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  131. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  138. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  150. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  172. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  182. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  188. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  204. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  205. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  206. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  207. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  208. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  209. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  210. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  211. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  212. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  214. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  215. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  216. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/app/index.html +1 -1
  218. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  219. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  220. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  221. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  222. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  223. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  224. package/dist/web/standalone/.next/server/app/page.js +2 -2
  225. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  226. package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
  227. package/dist/web/standalone/.next/server/chunks/1991.js +2 -2
  228. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  229. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  230. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  231. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  232. package/dist/web/standalone/.next/server/middleware.js +3 -3
  233. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  234. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  235. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  236. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  237. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  238. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  239. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  240. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  241. package/dist/web/standalone/.next/static/css/3b1ceb7abfb9a230.css +1 -0
  242. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  243. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  244. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  245. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  246. package/dist/web/standalone/package.json +0 -1
  247. package/dist/web/standalone/server.js +1 -1
  248. package/dist/web-mode.js +31 -3
  249. package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
  250. package/integrations/hermes/pyproject.toml +1 -1
  251. package/package.json +13 -10
  252. package/packages/cloud-mcp-gateway/package.json +2 -2
  253. package/packages/contracts/dist/workflow.d.ts +14 -0
  254. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  255. package/packages/contracts/dist/workflow.js +16 -0
  256. package/packages/contracts/dist/workflow.js.map +1 -1
  257. package/packages/contracts/package.json +1 -1
  258. package/packages/daemon/dist/cloud-config.d.ts +1 -1
  259. package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
  260. package/packages/daemon/dist/cloud-config.js +5 -1
  261. package/packages/daemon/dist/cloud-config.js.map +1 -1
  262. package/packages/daemon/dist/cloud-config.test.js +51 -1
  263. package/packages/daemon/dist/cloud-config.test.js.map +1 -1
  264. package/packages/daemon/dist/local-tool-executor.d.ts.map +1 -1
  265. package/packages/daemon/dist/local-tool-executor.js +2 -0
  266. package/packages/daemon/dist/local-tool-executor.js.map +1 -1
  267. package/packages/daemon/package.json +6 -6
  268. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  269. package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
  270. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  271. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  272. package/packages/gsd-agent-core/dist/sdk.js +1 -0
  273. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  274. package/packages/gsd-agent-core/package.json +5 -5
  275. package/packages/gsd-agent-modes/package.json +7 -7
  276. package/packages/gsd-cloud/README.md +9 -3
  277. package/packages/gsd-cloud/dist/background-cli.test.d.ts +2 -0
  278. package/packages/gsd-cloud/dist/background-cli.test.d.ts.map +1 -0
  279. package/packages/gsd-cloud/dist/background-cli.test.js +248 -0
  280. package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -0
  281. package/packages/gsd-cloud/dist/cli.d.ts +5 -0
  282. package/packages/gsd-cloud/dist/cli.d.ts.map +1 -0
  283. package/packages/gsd-cloud/dist/cli.js +266 -0
  284. package/packages/gsd-cloud/dist/cli.js.map +1 -0
  285. package/packages/gsd-cloud/dist/cloud-config.d.ts +19 -0
  286. package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -0
  287. package/packages/gsd-cloud/dist/cloud-config.js +237 -0
  288. package/packages/gsd-cloud/dist/cloud-config.js.map +1 -0
  289. package/packages/gsd-cloud/dist/cloud-config.test.d.ts +2 -0
  290. package/packages/gsd-cloud/dist/cloud-config.test.d.ts.map +1 -0
  291. package/packages/gsd-cloud/dist/cloud-config.test.js +118 -0
  292. package/packages/gsd-cloud/dist/cloud-config.test.js.map +1 -0
  293. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts +2 -0
  294. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts.map +1 -0
  295. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js +37 -0
  296. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js.map +1 -0
  297. package/packages/gsd-cloud/dist/cloud-runtime.d.ts +33 -0
  298. package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -0
  299. package/packages/gsd-cloud/dist/cloud-runtime.js +260 -0
  300. package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -0
  301. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts +2 -0
  302. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts.map +1 -0
  303. package/packages/gsd-cloud/dist/cloud-runtime.test.js +88 -0
  304. package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -0
  305. package/packages/gsd-cloud/dist/cloud-token.d.ts +3 -0
  306. package/packages/gsd-cloud/dist/cloud-token.d.ts.map +1 -0
  307. package/packages/gsd-cloud/dist/cloud-token.js +37 -0
  308. package/packages/gsd-cloud/dist/cloud-token.js.map +1 -0
  309. package/packages/gsd-cloud/dist/config.d.ts +17 -0
  310. package/packages/gsd-cloud/dist/config.d.ts.map +1 -0
  311. package/packages/gsd-cloud/dist/config.js +146 -0
  312. package/packages/gsd-cloud/dist/config.js.map +1 -0
  313. package/packages/gsd-cloud/dist/device-flow.d.ts +24 -0
  314. package/packages/gsd-cloud/dist/device-flow.d.ts.map +1 -0
  315. package/packages/gsd-cloud/dist/device-flow.js +128 -0
  316. package/packages/gsd-cloud/dist/device-flow.js.map +1 -0
  317. package/packages/gsd-cloud/dist/device-flow.test.d.ts +2 -0
  318. package/packages/gsd-cloud/dist/device-flow.test.d.ts.map +1 -0
  319. package/packages/gsd-cloud/dist/device-flow.test.js +155 -0
  320. package/packages/gsd-cloud/dist/device-flow.test.js.map +1 -0
  321. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts +6 -0
  322. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts.map +1 -0
  323. package/packages/gsd-cloud/dist/executors/claude-executor.js +15 -0
  324. package/packages/gsd-cloud/dist/executors/claude-executor.js.map +1 -0
  325. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts +6 -0
  326. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts.map +1 -0
  327. package/packages/gsd-cloud/dist/executors/codex-executor.js +15 -0
  328. package/packages/gsd-cloud/dist/executors/codex-executor.js.map +1 -0
  329. package/packages/gsd-cloud/dist/executors/executor.d.ts +28 -0
  330. package/packages/gsd-cloud/dist/executors/executor.d.ts.map +1 -0
  331. package/packages/gsd-cloud/dist/executors/executor.js +11 -0
  332. package/packages/gsd-cloud/dist/executors/executor.js.map +1 -0
  333. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts +34 -0
  334. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts.map +1 -0
  335. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js +179 -0
  336. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js.map +1 -0
  337. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts +2 -0
  338. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts.map +1 -0
  339. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js +44 -0
  340. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js.map +1 -0
  341. package/packages/gsd-cloud/dist/executors/index.d.ts +17 -0
  342. package/packages/gsd-cloud/dist/executors/index.d.ts.map +1 -0
  343. package/packages/gsd-cloud/dist/executors/index.js +29 -0
  344. package/packages/gsd-cloud/dist/executors/index.js.map +1 -0
  345. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts +36 -0
  346. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts.map +1 -0
  347. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js +176 -0
  348. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js.map +1 -0
  349. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts +2 -0
  350. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts.map +1 -0
  351. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js +34 -0
  352. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js.map +1 -0
  353. package/packages/gsd-cloud/dist/index.d.ts +7 -0
  354. package/packages/gsd-cloud/dist/index.d.ts.map +1 -0
  355. package/packages/gsd-cloud/dist/index.js +8 -0
  356. package/packages/gsd-cloud/dist/index.js.map +1 -0
  357. package/packages/gsd-cloud/dist/inject-gateway.d.ts +16 -0
  358. package/packages/gsd-cloud/dist/inject-gateway.d.ts.map +1 -0
  359. package/packages/gsd-cloud/dist/inject-gateway.js +29 -0
  360. package/packages/gsd-cloud/dist/inject-gateway.js.map +1 -0
  361. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts +2 -0
  362. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts.map +1 -0
  363. package/packages/gsd-cloud/dist/inject-gateway.test.js +41 -0
  364. package/packages/gsd-cloud/dist/inject-gateway.test.js.map +1 -0
  365. package/packages/gsd-cloud/dist/logger.d.ts +25 -0
  366. package/packages/gsd-cloud/dist/logger.d.ts.map +1 -0
  367. package/packages/gsd-cloud/dist/logger.js +72 -0
  368. package/packages/gsd-cloud/dist/logger.js.map +1 -0
  369. package/packages/gsd-cloud/dist/runtime-process.d.ts +27 -0
  370. package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -0
  371. package/packages/gsd-cloud/dist/runtime-process.js +272 -0
  372. package/packages/gsd-cloud/dist/runtime-process.js.map +1 -0
  373. package/packages/gsd-cloud/dist/runtime-process.test.d.ts +2 -0
  374. package/packages/gsd-cloud/dist/runtime-process.test.d.ts.map +1 -0
  375. package/packages/gsd-cloud/dist/runtime-process.test.js +97 -0
  376. package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -0
  377. package/packages/gsd-cloud/dist/types.d.ts +51 -0
  378. package/packages/gsd-cloud/dist/types.d.ts.map +1 -0
  379. package/packages/gsd-cloud/dist/types.js +9 -0
  380. package/packages/gsd-cloud/dist/types.js.map +1 -0
  381. package/packages/gsd-cloud/package.json +3 -3
  382. package/packages/mcp-server/README.md +15 -2
  383. package/packages/mcp-server/dist/cli-runner.d.ts +3 -0
  384. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -1
  385. package/packages/mcp-server/dist/cli-runner.js +119 -33
  386. package/packages/mcp-server/dist/cli-runner.js.map +1 -1
  387. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  388. package/packages/mcp-server/dist/server.js +5 -5
  389. package/packages/mcp-server/dist/server.js.map +1 -1
  390. package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
  391. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  392. package/packages/mcp-server/dist/workflow-tools.js +64 -2
  393. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  394. package/packages/mcp-server/package.json +4 -4
  395. package/packages/native/package.json +1 -1
  396. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  397. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  398. package/packages/pi-agent-core/dist/agent.js +2 -0
  399. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  400. package/packages/pi-agent-core/package.json +1 -1
  401. package/packages/pi-ai/dist/models.generated.d.ts +136 -0
  402. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  403. package/packages/pi-ai/dist/models.generated.js +124 -0
  404. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  405. package/packages/pi-ai/dist/providers/amazon-bedrock.js +1 -0
  406. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  407. package/packages/pi-ai/dist/providers/anthropic.js +25 -1
  408. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  409. package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
  410. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  411. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  412. package/packages/pi-ai/dist/providers/openai-completions.js +103 -0
  413. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  414. package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
  415. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  416. package/packages/pi-ai/package.json +1 -1
  417. package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
  418. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  419. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
  420. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  421. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +11 -1
  422. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  423. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  424. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  425. package/packages/pi-coding-agent/package.json +7 -7
  426. package/packages/pi-tui/package.json +2 -2
  427. package/packages/rpc-client/package.json +2 -2
  428. package/pkg/package.json +1 -1
  429. package/src/resources/GSD-WORKFLOW.md +18 -49
  430. package/src/resources/extensions/browser-tools/capture.ts +2 -86
  431. package/src/resources/extensions/browser-tools/screenshot-constraints.ts +94 -0
  432. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -1
  433. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -0
  434. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +30 -2
  435. package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
  436. package/src/resources/extensions/gsd/auto/loop.ts +48 -4
  437. package/src/resources/extensions/gsd/auto/run-unit.ts +20 -1
  438. package/src/resources/extensions/gsd/auto/unit-phase.ts +41 -5
  439. package/src/resources/extensions/gsd/auto-artifact-paths.ts +16 -9
  440. package/src/resources/extensions/gsd/auto-dispatch.ts +87 -19
  441. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -0
  442. package/src/resources/extensions/gsd/auto-prompts.ts +156 -20
  443. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  444. package/src/resources/extensions/gsd/auto-runtime-state.ts +12 -7
  445. package/src/resources/extensions/gsd/auto-start.ts +31 -8
  446. package/src/resources/extensions/gsd/auto-tool-tracking.ts +56 -0
  447. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
  448. package/src/resources/extensions/gsd/auto-worktree-sync.ts +10 -3
  449. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
  450. package/src/resources/extensions/gsd/auto.ts +25 -8
  451. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +92 -4
  452. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +41 -12
  453. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
  454. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +87 -53
  455. package/src/resources/extensions/gsd/command-feedback.ts +19 -12
  456. package/src/resources/extensions/gsd/commands-verdict.ts +16 -9
  457. package/src/resources/extensions/gsd/compat/compat-marker.ts +119 -8
  458. package/src/resources/extensions/gsd/constants.ts +14 -13
  459. package/src/resources/extensions/gsd/context-masker.ts +98 -2
  460. package/src/resources/extensions/gsd/db/command-queue.ts +7 -1
  461. package/src/resources/extensions/gsd/db/engine.ts +58 -19
  462. package/src/resources/extensions/gsd/db/writers/cascades.ts +5 -1
  463. package/src/resources/extensions/gsd/db/writers/status.ts +25 -8
  464. package/src/resources/extensions/gsd/db-base-schema.ts +30 -0
  465. package/src/resources/extensions/gsd/db-migration-steps.ts +32 -0
  466. package/src/resources/extensions/gsd/db-schema-metadata.ts +4 -1
  467. package/src/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  468. package/src/resources/extensions/gsd/doctor-engine-checks.ts +30 -7
  469. package/src/resources/extensions/gsd/error-classifier.ts +13 -2
  470. package/src/resources/extensions/gsd/exec-sandbox.ts +1 -0
  471. package/src/resources/extensions/gsd/flat-phase-migration.ts +174 -19
  472. package/src/resources/extensions/gsd/git-service.ts +19 -6
  473. package/src/resources/extensions/gsd/gsd-db.ts +340 -85
  474. package/src/resources/extensions/gsd/guided-flow.ts +50 -14
  475. package/src/resources/extensions/gsd/markdown-renderer.ts +28 -30
  476. package/src/resources/extensions/gsd/md-importer.ts +114 -16
  477. package/src/resources/extensions/gsd/migrate/command.ts +21 -227
  478. package/src/resources/extensions/gsd/migrate/execution.ts +136 -0
  479. package/src/resources/extensions/gsd/migrate/plan.ts +101 -0
  480. package/src/resources/extensions/gsd/migrate/planning-writer.ts +12 -20
  481. package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
  482. package/src/resources/extensions/gsd/model-cost-table.ts +2 -0
  483. package/src/resources/extensions/gsd/model-router.ts +12 -0
  484. package/src/resources/extensions/gsd/parallel-eligibility.ts +5 -4
  485. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +37 -40
  486. package/src/resources/extensions/gsd/paths.ts +77 -16
  487. package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
  488. package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
  489. package/src/resources/extensions/gsd/planning-subagent-registry.ts +31 -0
  490. package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
  491. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  492. package/src/resources/extensions/gsd/preferences-validation.ts +62 -0
  493. package/src/resources/extensions/gsd/preferences.ts +25 -0
  494. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  495. package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
  496. package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
  497. package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
  498. package/src/resources/extensions/gsd/safety/evidence-collector.ts +28 -1
  499. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +31 -5
  500. package/src/resources/extensions/gsd/skill-activation.ts +17 -3
  501. package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +162 -15
  502. package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +20 -4
  503. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +4 -2
  504. package/src/resources/extensions/gsd/state-reconciliation/types.ts +2 -2
  505. package/src/resources/extensions/gsd/stop-notice.ts +29 -1
  506. package/src/resources/extensions/gsd/sync-lock.ts +14 -6
  507. package/src/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  508. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
  509. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +264 -0
  510. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
  511. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +21 -1
  512. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +74 -1
  513. package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
  514. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +96 -1
  515. package/src/resources/extensions/gsd/tests/command-feedback.test.ts +12 -0
  516. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +10 -0
  517. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +129 -0
  518. package/src/resources/extensions/gsd/tests/complete-task.test.ts +362 -1
  519. package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
  520. package/src/resources/extensions/gsd/tests/db-engine-cjs-compat.test.ts +12 -0
  521. package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
  522. package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
  523. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
  524. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
  525. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
  526. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +123 -0
  527. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +50 -0
  528. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +49 -0
  529. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +83 -0
  530. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +81 -0
  531. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +22 -0
  532. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +33 -1
  533. package/src/resources/extensions/gsd/tests/external-edit-scoped-import.test.ts +262 -0
  534. package/src/resources/extensions/gsd/tests/external-markdown-edit.test.ts +38 -1
  535. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +201 -0
  536. package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +20 -1
  537. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +29 -0
  538. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +57 -0
  539. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +22 -0
  540. package/src/resources/extensions/gsd/tests/import-slice-milestone-completion-preserve.test.ts +116 -0
  541. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +13 -0
  542. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
  543. package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
  544. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
  545. package/src/resources/extensions/gsd/tests/migrate-plan.test.ts +68 -0
  546. package/src/resources/extensions/gsd/tests/migrate-presentation.test.ts +98 -0
  547. package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +1 -1
  548. package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +55 -0
  549. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  550. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  551. package/src/resources/extensions/gsd/tests/parallel-eligibility-file-overlap.test.ts +146 -0
  552. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +59 -0
  553. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
  554. package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +32 -4
  555. package/src/resources/extensions/gsd/tests/plan-task.test.ts +26 -23
  556. package/src/resources/extensions/gsd/tests/planning-writer.test.ts +29 -0
  557. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
  558. package/src/resources/extensions/gsd/tests/preferences.test.ts +84 -0
  559. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +4 -0
  560. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +87 -0
  561. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +121 -1
  562. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
  563. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +50 -0
  564. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +105 -0
  565. package/src/resources/extensions/gsd/tests/replan-task-handler.test.ts +103 -0
  566. package/src/resources/extensions/gsd/tests/rework-brief.test.ts +197 -0
  567. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  568. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
  569. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
  570. package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
  571. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +52 -0
  572. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +38 -1
  573. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +19 -0
  574. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
  575. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +14 -0
  576. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  577. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
  578. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +73 -0
  579. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +93 -1
  580. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +7 -0
  581. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -0
  582. package/src/resources/extensions/gsd/tests/workflow-migration-gates.test.ts +139 -0
  583. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
  584. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
  585. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +60 -0
  586. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
  587. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
  588. package/src/resources/extensions/gsd/tools/complete-task.ts +140 -5
  589. package/src/resources/extensions/gsd/tools/plan-task.ts +14 -16
  590. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +18 -17
  591. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
  592. package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
  593. package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
  594. package/src/resources/extensions/gsd/tools/replan-task.ts +160 -0
  595. package/src/resources/extensions/gsd/tools/rework-brief.ts +91 -0
  596. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +92 -0
  597. package/src/resources/extensions/gsd/types.ts +11 -0
  598. package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
  599. package/src/resources/extensions/gsd/unit-registry.ts +4 -0
  600. package/src/resources/extensions/gsd/uok/plan-v2.ts +20 -3
  601. package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
  602. package/src/resources/extensions/gsd/workspace.ts +2 -1
  603. package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -24
  604. package/src/resources/extensions/mac-tools/index.ts +52 -9
  605. package/src/resources/extensions/mac-tools/tests/mac-screenshot-payload.test.cjs +70 -0
  606. package/src/resources/extensions/shared/interview-ui.ts +47 -8
  607. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +29 -0
  608. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  609. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  610. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  611. package/dist/web/standalone/.next/static/css/18c2fdf261bfc1b7.css +0 -1
  612. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → DXD9fZPnqtjZSlT5xdC3v}/_buildManifest.js +0 -0
  613. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → DXD9fZPnqtjZSlT5xdC3v}/_ssgManifest.js +0 -0
@@ -6,58 +6,14 @@
6
6
  */
7
7
 
8
8
  import type { Frame, Page } from "playwright";
9
-
10
- // sharp is an optional native dependency. Load it lazily so that the extension
11
- // can still be loaded on platforms where sharp is unavailable (e.g. bunx on
12
- // Raspberry Pi). constrainScreenshot falls back to returning the raw buffer
13
- // when sharp is not installed, which means screenshots won't be resized but
14
- // the tool remains functional.
15
- let _sharp: typeof import("sharp") | null | undefined;
16
- async function getSharp(): Promise<typeof import("sharp") | null> {
17
- if (_sharp !== undefined) return _sharp;
18
- try {
19
- _sharp = (await import("sharp")).default;
20
- } catch {
21
- _sharp = null;
22
- }
23
- return _sharp;
24
- }
25
-
26
- /**
27
- * Test-only seam: override the cached sharp module. Pass `null` to simulate
28
- * an environment where the sharp native dep is unavailable; pass `undefined`
29
- * to clear the cache and let the next getSharp() call re-import. See
30
- * tests/capture-sharp-optional.test.cjs.
31
- */
32
- export function __setSharpForTesting(
33
- value: typeof import("sharp") | null | undefined,
34
- ): void {
35
- _sharp = value;
36
- }
9
+ import { constrainScreenshot } from "./screenshot-constraints.js";
10
+ export { constrainScreenshot, __setSharpForTesting } from "./screenshot-constraints.js";
37
11
  import type { CompactPageState, CompactSelectorState } from "./state.js";
38
12
  import { formatCompactStateSummary } from "./utils.js";
39
13
 
40
- // Anthropic vision: 1568px is the recommended optimal width. Height is capped
41
- // generously at 8000px so tall full-page screenshots remain readable rather
42
- // than being squished into a square constraint.
43
- //
44
14
  // Override via environment variables:
45
- // SCREENSHOT_MAX_WIDTH=0 → uncap width (use raw resolution)
46
- // SCREENSHOT_MAX_HEIGHT=0 → uncap height
47
15
  // SCREENSHOT_FORMAT=png → lossless PNG for all viewport/fullpage screenshots
48
16
  // SCREENSHOT_QUALITY=100 → max JPEG quality (1-100, default 80)
49
- const MAX_SCREENSHOT_WIDTH = parseScreenshotDimension(process.env.SCREENSHOT_MAX_WIDTH, 1568);
50
- const MAX_SCREENSHOT_HEIGHT = parseScreenshotDimension(process.env.SCREENSHOT_MAX_HEIGHT, 8000);
51
-
52
- /** Parse a dimension env var: positive int = that value, 0 = Infinity (uncapped), absent/invalid = default. */
53
- function parseScreenshotDimension(value: string | undefined, fallback: number): number {
54
- if (value === undefined || value === "") return fallback;
55
- const n = parseInt(value, 10);
56
- if (isNaN(n) || n < 0) return fallback;
57
- if (n === 0) return Infinity;
58
- return n;
59
- }
60
-
61
17
  /** Return the user-configured screenshot format override, or null for default behavior. */
62
18
  export function getScreenshotFormatOverride(): "png" | "jpeg" | null {
63
19
  const fmt = process.env.SCREENSHOT_FORMAT?.toLowerCase();
@@ -176,46 +132,6 @@ export async function postActionSummary(p: Page, target?: Page | Frame): Promise
176
132
  }
177
133
  }
178
134
 
179
- // ---------------------------------------------------------------------------
180
- // Screenshot helpers
181
- // ---------------------------------------------------------------------------
182
-
183
- /**
184
- * Constrain screenshot dimensions for the Anthropic vision API.
185
- * Width is capped at 1568px (optimal) and height at 8000px, each
186
- * independently, using `fit: "inside"` so aspect ratio is preserved.
187
- * Small images are never upscaled.
188
- *
189
- * `page` parameter is retained for ToolDeps signature stability (D008)
190
- * but is no longer used — all processing is server-side via sharp.
191
- */
192
- export async function constrainScreenshot(
193
- _page: Page,
194
- buffer: Buffer,
195
- mimeType: string,
196
- quality: number,
197
- ): Promise<Buffer> {
198
- const sharp = await getSharp();
199
- if (!sharp) return buffer;
200
-
201
- const meta = await sharp(buffer).metadata();
202
- const width = meta.width;
203
- const height = meta.height;
204
-
205
- if (width === undefined || height === undefined) return buffer;
206
- if (width <= MAX_SCREENSHOT_WIDTH && height <= MAX_SCREENSHOT_HEIGHT) return buffer;
207
-
208
- const resizer = sharp(buffer).resize(MAX_SCREENSHOT_WIDTH, MAX_SCREENSHOT_HEIGHT, {
209
- fit: "inside",
210
- withoutEnlargement: true,
211
- });
212
-
213
- if (mimeType === "image/png") {
214
- return Buffer.from(await resizer.png().toBuffer());
215
- }
216
- return Buffer.from(await resizer.jpeg({ quality }).toBuffer());
217
- }
218
-
219
135
  /** Capture a JPEG screenshot for error debugging. Returns base64 or null. */
220
136
  export async function captureErrorScreenshot(p: Page | null): Promise<{ data: string; mimeType: string } | null> {
221
137
  if (!p) return null;
@@ -0,0 +1,94 @@
1
+ import type { Page } from "playwright";
2
+
3
+ // sharp is an optional native dependency. Load it lazily so that screenshot
4
+ // emitters still work on platforms where sharp is unavailable (e.g. bunx on
5
+ // Raspberry Pi). constrainScreenshot falls back to returning the raw buffer
6
+ // when sharp is not installed.
7
+ let _sharp: typeof import("sharp") | null | undefined;
8
+ async function getSharp(): Promise<typeof import("sharp") | null> {
9
+ if (_sharp !== undefined) return _sharp;
10
+ try {
11
+ _sharp = (await import("sharp")).default;
12
+ } catch {
13
+ _sharp = null;
14
+ }
15
+ return _sharp;
16
+ }
17
+
18
+ /**
19
+ * Test-only seam: override the cached sharp module. Pass `null` to simulate
20
+ * an environment where the sharp native dep is unavailable; pass `undefined`
21
+ * to clear the cache and let the next getSharp() call re-import. See
22
+ * tests/capture-sharp-optional.test.cjs.
23
+ */
24
+ export function __setSharpForTesting(
25
+ value: typeof import("sharp") | null | undefined,
26
+ ): void {
27
+ _sharp = value;
28
+ }
29
+
30
+ // Anthropic vision: 1568px is the recommended optimal width. Height is capped
31
+ // generously at 8000px so tall full-page screenshots remain readable rather
32
+ // than being squished into a square constraint.
33
+ //
34
+ // Override via environment variables:
35
+ // SCREENSHOT_MAX_WIDTH=0 -> uncap width (use raw resolution)
36
+ // SCREENSHOT_MAX_HEIGHT=0 -> uncap height
37
+ export const MAX_SCREENSHOT_WIDTH = parseScreenshotDimension(process.env.SCREENSHOT_MAX_WIDTH, 1568);
38
+ export const MAX_SCREENSHOT_HEIGHT = parseScreenshotDimension(process.env.SCREENSHOT_MAX_HEIGHT, 8000);
39
+
40
+ /** Parse a dimension env var: positive int = that value, 0 = Infinity (uncapped), absent/invalid = default. */
41
+ function parseScreenshotDimension(value: string | undefined, fallback: number): number {
42
+ if (value === undefined || value === "") return fallback;
43
+ const n = parseInt(value, 10);
44
+ if (isNaN(n) || n < 0) return fallback;
45
+ if (n === 0) return Infinity;
46
+ return n;
47
+ }
48
+
49
+ export async function getScreenshotBufferDimensions(
50
+ buffer: Buffer,
51
+ ): Promise<{ width: number; height: number } | null> {
52
+ const sharp = await getSharp();
53
+ if (!sharp) return null;
54
+
55
+ const meta = await sharp(buffer).metadata();
56
+ if (meta.width === undefined || meta.height === undefined) return null;
57
+ return { width: meta.width, height: meta.height };
58
+ }
59
+
60
+ /**
61
+ * Constrain screenshot dimensions for the Anthropic vision API.
62
+ * Width is capped at 1568px (optimal) and height at 8000px, each
63
+ * independently, using `fit: "inside"` so aspect ratio is preserved.
64
+ * Small images are never upscaled.
65
+ *
66
+ * `page` parameter is retained for ToolDeps signature stability (D008)
67
+ * but is no longer used — all processing is server-side via sharp.
68
+ */
69
+ export async function constrainScreenshot(
70
+ _page: Page | null,
71
+ buffer: Buffer,
72
+ mimeType: string,
73
+ quality: number,
74
+ ): Promise<Buffer> {
75
+ const sharp = await getSharp();
76
+ if (!sharp) return buffer;
77
+
78
+ const dimensions = await getScreenshotBufferDimensions(buffer);
79
+ const width = dimensions?.width;
80
+ const height = dimensions?.height;
81
+
82
+ if (width === undefined || height === undefined) return buffer;
83
+ if (width <= MAX_SCREENSHOT_WIDTH && height <= MAX_SCREENSHOT_HEIGHT) return buffer;
84
+
85
+ const resizer = sharp(buffer).resize(MAX_SCREENSHOT_WIDTH, MAX_SCREENSHOT_HEIGHT, {
86
+ fit: "inside",
87
+ withoutEnlargement: true,
88
+ });
89
+
90
+ if (mimeType === "image/png") {
91
+ return Buffer.from(await resizer.png().toBuffer());
92
+ }
93
+ return Buffer.from(await resizer.jpeg({ quality }).toBuffer());
94
+ }
@@ -22,6 +22,7 @@ import type {
22
22
  import type { ExtensionUIContext } from "@gsd/pi-coding-agent";
23
23
  import { EventStream } from "@gsd/pi-ai";
24
24
  import { execSync } from "node:child_process";
25
+ import { createHash } from "node:crypto";
25
26
  import { existsSync, readFileSync } from "node:fs";
26
27
  import { homedir } from "node:os";
27
28
  import { createRequire } from "node:module";
@@ -583,6 +584,7 @@ function inferMimeTypeFromDataUri(value: string): string | null {
583
584
  /** Collect all base64 image blocks from user messages in the context for inclusion in the SDK prompt. */
584
585
  export function extractImageBlocksFromContext(context: Context): SDKInputImageBlock[] {
585
586
  const imageBlocks: SDKInputImageBlock[] = [];
587
+ const seenImageKeys = new Set<string>();
586
588
 
587
589
  for (const msg of context.messages) {
588
590
  if (msg.role !== "user" || !Array.isArray(msg.content)) continue;
@@ -597,12 +599,17 @@ export function extractImageBlocksFromContext(context: Context): SDKInputImageBl
597
599
  : inferMimeTypeFromDataUri(block.data);
598
600
  if (!mimeType) continue;
599
601
 
602
+ const data = stripDataUriPrefix(block.data);
603
+ const imageKey = `${mimeType}\0${createHash("sha1").update(data).digest("hex")}`;
604
+ if (seenImageKeys.has(imageKey)) continue;
605
+ seenImageKeys.add(imageKey);
606
+
600
607
  imageBlocks.push({
601
608
  type: "image",
602
609
  source: {
603
610
  type: "base64",
604
611
  media_type: mimeType,
605
- data: stripDataUriPrefix(block.data),
612
+ data,
606
613
  },
607
614
  });
608
615
  }
@@ -2252,6 +2259,7 @@ export function streamViaClaudeCode(
2252
2259
  interface SdkAttemptMessageState {
2253
2260
  builder: PartialMessageBuilder | null;
2254
2261
  intermediateToolBlocks: AssistantMessage["content"];
2262
+ intermediateTextBlocks: AssistantMessage["content"];
2255
2263
  toolResultsById: Map<string, ExternalToolResultPayload>;
2256
2264
  toolCompletionTargetsById: Map<string, { partial: AssistantMessage; contentIndex: number }>;
2257
2265
  emittedExternalToolResultIds: Set<string>;
@@ -2261,6 +2269,7 @@ function createSdkAttemptMessageState(): SdkAttemptMessageState {
2261
2269
  return {
2262
2270
  builder: null,
2263
2271
  intermediateToolBlocks: [],
2272
+ intermediateTextBlocks: [],
2264
2273
  toolResultsById: new Map<string, ExternalToolResultPayload>(),
2265
2274
  toolCompletionTargetsById: new Map<string, { partial: AssistantMessage; contentIndex: number }>(),
2266
2275
  emittedExternalToolResultIds: new Set<string>(),
@@ -2402,6 +2411,7 @@ async function pumpSdkMessages(
2402
2411
  let {
2403
2412
  builder,
2404
2413
  intermediateToolBlocks,
2414
+ intermediateTextBlocks,
2405
2415
  toolResultsById,
2406
2416
  toolCompletionTargetsById,
2407
2417
  emittedExternalToolResultIds,
@@ -2542,8 +2552,14 @@ async function pumpSdkMessages(
2542
2552
  for (const [contentIndex, block] of builder.message.content.entries()) {
2543
2553
  if (block.type === "text" && block.text) {
2544
2554
  lastTextContent = block.text;
2555
+ // Accumulate completed prose in order — a multi-question
2556
+ // turn commits [prose][elicitation] segments across several
2557
+ // synthetic-user boundaries, and overwriting a single
2558
+ // scalar would drop every explanation but the last.
2559
+ intermediateTextBlocks.push({ type: "text", text: block.text });
2545
2560
  } else if (block.type === "thinking" && block.thinking) {
2546
2561
  lastThinkingContent = block.thinking;
2562
+ intermediateTextBlocks.push({ type: "thinking", thinking: block.thinking });
2547
2563
  } else if (block.type === "toolCall" || block.type === "serverToolUse") {
2548
2564
  // Collect tool blocks for externalToolExecution rendering
2549
2565
  intermediateToolBlocks.push(block);
@@ -2641,6 +2657,7 @@ async function pumpSdkMessages(
2641
2657
  const result = msg as SDKResultMessage;
2642
2658
  const finalContent = buildFinalAssistantContent({
2643
2659
  intermediateToolBlocks,
2660
+ intermediateTextBlocks,
2644
2661
  pendingContent: builder?.message.content,
2645
2662
  toolResultsById,
2646
2663
  lastThinkingContent,
@@ -363,6 +363,53 @@ describe("stream-adapter — image prompt forwarding (#4183)", () => {
363
363
  ]);
364
364
  });
365
365
 
366
+ test("extractImageBlocksFromContext deduplicates byte-identical image parts", () => {
367
+ const context: Context = {
368
+ messages: [
369
+ {
370
+ role: "user",
371
+ content: [
372
+ {
373
+ type: "image",
374
+ data: "data:image/png;base64,abc123",
375
+ mimeType: "image/png",
376
+ },
377
+ {
378
+ type: "image",
379
+ data: "abc123",
380
+ mimeType: "image/png",
381
+ },
382
+ {
383
+ type: "image",
384
+ data: "def456",
385
+ mimeType: "image/png",
386
+ },
387
+ ],
388
+ } as Message,
389
+ ],
390
+ };
391
+
392
+ const imageBlocks = extractImageBlocksFromContext(context);
393
+ assert.deepEqual(imageBlocks, [
394
+ {
395
+ type: "image",
396
+ source: {
397
+ type: "base64",
398
+ media_type: "image/png",
399
+ data: "abc123",
400
+ },
401
+ },
402
+ {
403
+ type: "image",
404
+ source: {
405
+ type: "base64",
406
+ media_type: "image/png",
407
+ data: "def456",
408
+ },
409
+ },
410
+ ]);
411
+ });
412
+
366
413
  test("buildSdkQueryPrompt returns plain string when no images exist in context", () => {
367
414
  const context: Context = {
368
415
  messages: [{ role: "user", content: "hello" } as Message],
@@ -1365,6 +1412,67 @@ describe("stream-adapter — Claude Code external tool results", () => {
1365
1412
  });
1366
1413
  assert.deepEqual(finalContent[1], { type: "text", text: "Read complete." });
1367
1414
  });
1415
+
1416
+ test("buildFinalAssistantContent keeps every prose segment across successive elicitation boundaries (#1284)", () => {
1417
+ // A multi-question /gsd discuss turn: [prose A][Q1][prose B][Q2][prose C].
1418
+ // Prose A and B are committed at synthetic-user boundaries (intermediate),
1419
+ // prose C is still in the builder (pending) when `result` arrives.
1420
+ const finalContent = buildFinalAssistantContent({
1421
+ intermediateToolBlocks: [
1422
+ { type: "toolCall", id: "q1", name: "ask_user_questions", arguments: {} } as any,
1423
+ { type: "toolCall", id: "q2", name: "ask_user_questions", arguments: {} } as any,
1424
+ ],
1425
+ intermediateTextBlocks: [
1426
+ { type: "text", text: "prose A" },
1427
+ { type: "text", text: "prose B" },
1428
+ ],
1429
+ pendingContent: [{ type: "text", text: "prose C" }],
1430
+ toolResultsById: new Map(),
1431
+ });
1432
+
1433
+ const textBlocks = finalContent.filter((b) => b.type === "text").map((b) => (b as any).text);
1434
+ assert.deepEqual(textBlocks, ["prose A", "prose B", "prose C"]);
1435
+ });
1436
+
1437
+ test("buildFinalAssistantContent does not duplicate the last prose when the turn ends on an elicitation (#1284)", () => {
1438
+ // [prose A][Q1][prose B][Q2] — builder was reset at the final boundary, so
1439
+ // pendingContent is empty and lastTextContent still holds "prose B".
1440
+ const finalContent = buildFinalAssistantContent({
1441
+ intermediateToolBlocks: [
1442
+ { type: "toolCall", id: "q1", name: "ask_user_questions", arguments: {} } as any,
1443
+ { type: "toolCall", id: "q2", name: "ask_user_questions", arguments: {} } as any,
1444
+ ],
1445
+ intermediateTextBlocks: [
1446
+ { type: "text", text: "prose A" },
1447
+ { type: "text", text: "prose B" },
1448
+ ],
1449
+ toolResultsById: new Map(),
1450
+ lastTextContent: "prose B",
1451
+ });
1452
+
1453
+ const textBlocks = finalContent.filter((b) => b.type === "text").map((b) => (b as any).text);
1454
+ assert.deepEqual(textBlocks, ["prose A", "prose B"]);
1455
+ });
1456
+
1457
+ test("buildFinalAssistantContent emits scalar fallback prose/thinking not captured in the accumulator", () => {
1458
+ // A non-streaming `assistant` SDK message sets lastText/lastThinkingContent
1459
+ // only (never pushed to intermediateTextBlocks). With pendingContent empty
1460
+ // and intermediate blocks present, the fallback must still be emitted.
1461
+ const finalContent = buildFinalAssistantContent({
1462
+ intermediateToolBlocks: [
1463
+ { type: "toolCall", id: "q1", name: "ask_user_questions", arguments: {} } as any,
1464
+ ],
1465
+ intermediateTextBlocks: [{ type: "text", text: "prose A" }],
1466
+ toolResultsById: new Map(),
1467
+ lastThinkingContent: "final thinking",
1468
+ lastTextContent: "final prose",
1469
+ });
1470
+
1471
+ const textBlocks = finalContent.filter((b) => b.type === "text").map((b) => (b as any).text);
1472
+ const thinkingBlocks = finalContent.filter((b) => b.type === "thinking").map((b) => (b as any).thinking);
1473
+ assert.deepEqual(textBlocks, ["prose A", "final prose"]);
1474
+ assert.deepEqual(thinkingBlocks, ["final thinking"]);
1475
+ });
1368
1476
  });
1369
1477
 
1370
1478
  describe("claude-code-cli — Claude Fable 5 Opus-tier support", () => {
@@ -244,6 +244,7 @@ export function shouldSuppressDuplicateToolUnavailableBlock(
244
244
  */
245
245
  export function buildFinalAssistantContent(params: {
246
246
  intermediateToolBlocks: AssistantMessage["content"];
247
+ intermediateTextBlocks?: AssistantMessage["content"];
247
248
  pendingContent?: AssistantMessage["content"];
248
249
  toolResultsById: ReadonlyMap<string, ExternalToolResultPayload>;
249
250
  lastThinkingContent?: string;
@@ -259,6 +260,15 @@ export function buildFinalAssistantContent(params: {
259
260
  const finalContent: AssistantMessage["content"] = mergedToolBlocks.filter(
260
261
  (block) => !shouldSuppressDuplicateToolUnavailableBlock(block, mergedToolBlocks),
261
262
  );
263
+ // Emit prose/thinking captured at earlier turn-boundaries (each successive
264
+ // `ask_user_questions` elicitation completes a turn) before the final
265
+ // segment. Capturing these in an ordered accumulator — symmetric with
266
+ // `intermediateToolBlocks` — is what keeps intermediate explanations from
267
+ // being collapsed to a single overwritten scalar and silently dropped.
268
+ const intermediateTextBlocks = params.intermediateTextBlocks ?? [];
269
+ for (const block of intermediateTextBlocks) {
270
+ finalContent.push(block);
271
+ }
262
272
  if (params.pendingContent && params.pendingContent.length > 0) {
263
273
  for (const block of params.pendingContent) {
264
274
  if (block.type === "text" || block.type === "thinking") {
@@ -266,11 +276,29 @@ export function buildFinalAssistantContent(params: {
266
276
  }
267
277
  }
268
278
  } else {
279
+ // No builder content survived to this turn boundary, so fall back to the
280
+ // last scalar thinking/text captured off the stream. When the turn ends
281
+ // on an elicitation these scalars just mirror the final intermediate
282
+ // block (they are overwritten at each synthetic-user boundary), so only
283
+ // emit them when they carry content not already accumulated — otherwise
284
+ // a non-streaming `assistant` message's prose/thinking is silently lost.
285
+ const lastBlockOfType = (type: "text" | "thinking") => {
286
+ for (let i = intermediateTextBlocks.length - 1; i >= 0; i--) {
287
+ if (intermediateTextBlocks[i].type === type) return intermediateTextBlocks[i];
288
+ }
289
+ return undefined;
290
+ };
269
291
  if (params.lastThinkingContent) {
270
- finalContent.push({ type: "thinking", thinking: params.lastThinkingContent });
292
+ const lastThinking = lastBlockOfType("thinking") as { thinking?: string } | undefined;
293
+ if (lastThinking?.thinking !== params.lastThinkingContent) {
294
+ finalContent.push({ type: "thinking", thinking: params.lastThinkingContent });
295
+ }
271
296
  }
272
297
  if (params.lastTextContent) {
273
- finalContent.push({ type: "text", text: params.lastTextContent });
298
+ const lastText = lastBlockOfType("text") as { text?: string } | undefined;
299
+ if (lastText?.text !== params.lastTextContent) {
300
+ finalContent.push({ type: "text", text: params.lastTextContent });
301
+ }
274
302
  }
275
303
  }
276
304
 
@@ -22,6 +22,7 @@ import {
22
22
  resolveSliceFile,
23
23
  resolveTasksDir,
24
24
  resolveTaskFiles,
25
+ resolveTaskFile,
25
26
  relSliceFile,
26
27
  resolveMilestoneFile,
27
28
  clearPathCache,
@@ -223,15 +224,9 @@ export function verifyExpectedArtifact(
223
224
  const batchIds = batchPart.slice(plusIdx + 1).split(",").filter(Boolean);
224
225
  if (batchIds.length === 0) return false;
225
226
 
226
- const tDir = resolveTasksDir(base, mid, sid) ?? slicePath;
227
- const existingSummaries = new Set(
228
- resolveTaskFiles(tDir, "SUMMARY").map((f) =>
229
- f.replace(/-SUMMARY\.md$/i, "").toUpperCase(),
230
- ),
231
- );
232
-
233
227
  for (const tid of batchIds) {
234
- if (!existingSummaries.has(tid.toUpperCase())) return false;
228
+ const summaryPath = resolveTaskFile(base, mid, sid, tid, "SUMMARY");
229
+ if (!summaryPath || !existsSync(summaryPath)) return false;
235
230
  }
236
231
  return true;
237
232
  }
@@ -355,7 +355,41 @@ async function enforceMinRequestInterval(s: AutoSession, prefs: IterationContext
355
355
  }
356
356
  }
357
357
 
358
- function closeOutCrashedUnit(s: AutoSession, iterData: IterationData, err: unknown): void {
358
+ async function snapshotCrashedUnitWork(
359
+ ctx: ExtensionContext,
360
+ s: AutoSession,
361
+ deps: LoopDeps,
362
+ iterData: IterationData,
363
+ ): Promise<void> {
364
+ try {
365
+ const commitMsg = await deps.autoCommitUnit?.(
366
+ s.basePath,
367
+ iterData.unitType,
368
+ iterData.unitId,
369
+ ctx,
370
+ );
371
+ if (commitMsg) {
372
+ debugLog("autoLoop", {
373
+ phase: "crash-snapshot-commit",
374
+ unitType: iterData.unitType,
375
+ unitId: iterData.unitId,
376
+ });
377
+ }
378
+ } catch (snapshotErr) {
379
+ logWarning(
380
+ "dispatch",
381
+ `unit crash snapshot failed: ${snapshotErr instanceof Error ? snapshotErr.message : String(snapshotErr)}`,
382
+ );
383
+ }
384
+ }
385
+
386
+ async function closeOutCrashedUnit(
387
+ ctx: ExtensionContext,
388
+ s: AutoSession,
389
+ deps: LoopDeps,
390
+ iterData: IterationData,
391
+ err: unknown,
392
+ ): Promise<void> {
359
393
  const summary = formatDispatchExceptionSummary({ error: err });
360
394
  try {
361
395
  emitOpenUnitEndForUnit(
@@ -383,6 +417,7 @@ function closeOutCrashedUnit(s: AutoSession, iterData: IterationData, err: unkno
383
417
  } catch (closeoutErr) {
384
418
  logWarning("dispatch", `unit crash closeout failed: ${closeoutErr instanceof Error ? closeoutErr.message : String(closeoutErr)}`);
385
419
  }
420
+ await snapshotCrashedUnitWork(ctx, s, deps, iterData);
386
421
  }
387
422
 
388
423
  /**
@@ -526,11 +561,20 @@ export async function autoLoop(
526
561
  active: s.active,
527
562
  iteration,
528
563
  maxIterations: MAX_LOOP_ITERATIONS,
529
- hasCommandContext: Boolean(s.cmdCtx),
564
+ hasCommandContext: typeof s.cmdCtx?.newSession === "function",
530
565
  sessionLockValid: true,
531
566
  });
532
567
  if (commandContextDecision.action === "stop" && commandContextDecision.reason === "missing-command-context") {
533
568
  debugLog("autoLoop", { phase: "exit", reason: "no-cmdCtx" });
569
+ if (s.currentUnit) {
570
+ await deps.autoCommitUnit?.(
571
+ s.basePath,
572
+ s.currentUnit.type,
573
+ s.currentUnit.id,
574
+ ctx,
575
+ );
576
+ }
577
+ await deps.stopAuto(ctx, pi, commandContextDecision.message, { preserveWorktree: true });
534
578
  finishTurn("stopped", "manual-attention", commandContextDecision.reason);
535
579
  break;
536
580
  }
@@ -730,7 +774,7 @@ export async function autoLoop(
730
774
  if (err instanceof ModelPolicyDispatchBlockedError) {
731
775
  throw err;
732
776
  }
733
- closeOutCrashedUnit(s, iterData, err);
777
+ await closeOutCrashedUnit(ctx, s, deps, iterData, err);
734
778
  throw err;
735
779
  }
736
780
  if (unitPhaseResult.action === "next") {
@@ -1285,7 +1329,7 @@ export async function autoLoop(
1285
1329
  if (err instanceof ModelPolicyDispatchBlockedError) {
1286
1330
  throw err;
1287
1331
  }
1288
- closeOutCrashedUnit(s, iterData, err);
1332
+ await closeOutCrashedUnit(ctx, s, deps, iterData, err);
1289
1333
  dispatchSettled = settleDispatchFailed(
1290
1334
  dispatchId,
1291
1335
  formatDispatchExceptionSummary({ error: err }),
@@ -91,6 +91,25 @@ export async function runUnit(
91
91
  // ── Session creation with timeout ──
92
92
  debugLog("runUnit", { phase: "session-create", unitType, unitId });
93
93
 
94
+ const cmdCtx = s.cmdCtx;
95
+ if (typeof cmdCtx?.newSession !== "function") {
96
+ const msg = "command context is missing newSession";
97
+ debugLog("runUnit", {
98
+ phase: "session-error",
99
+ unitType,
100
+ unitId,
101
+ error: msg,
102
+ });
103
+ return {
104
+ status: "cancelled",
105
+ errorContext: {
106
+ message: `Session creation failed: ${msg}`,
107
+ category: "session-failed",
108
+ isTransient: false,
109
+ },
110
+ };
111
+ }
112
+
94
113
  let sessionResult: { cancelled: boolean };
95
114
  let sessionTimeoutHandle: ReturnType<typeof setTimeout> | undefined;
96
115
  const mySessionSwitchGeneration = ++sessionSwitchGeneration;
@@ -100,7 +119,7 @@ export async function runUnit(
100
119
  const sessionAbortController = new AbortController();
101
120
  _setSessionSwitchInFlight(true);
102
121
  try {
103
- const sessionPromise = s.cmdCtx!.newSession({
122
+ const sessionPromise = cmdCtx.newSession({
104
123
  abortSignal: sessionAbortController.signal,
105
124
  workspaceRoot: s.basePath,
106
125
  }).finally(() => {