@opengsd/gsd-pi 1.8.1 → 1.9.0-dev.5c1a3ff2

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 (546) 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 +25 -2
  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-artifact-paths.js +16 -10
  18. package/dist/resources/extensions/gsd/auto-dispatch.js +74 -19
  19. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -0
  20. package/dist/resources/extensions/gsd/auto-prompts.js +125 -18
  21. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  22. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
  23. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
  24. package/dist/resources/extensions/gsd/auto.js +5 -1
  25. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -4
  26. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +31 -5
  27. package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
  28. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -50
  29. package/dist/resources/extensions/gsd/command-feedback.js +16 -12
  30. package/dist/resources/extensions/gsd/compat/compat-marker.js +19 -2
  31. package/dist/resources/extensions/gsd/constants.js +12 -13
  32. package/dist/resources/extensions/gsd/context-masker.js +97 -21
  33. package/dist/resources/extensions/gsd/db/command-queue.js +7 -2
  34. package/dist/resources/extensions/gsd/db/engine.js +51 -16
  35. package/dist/resources/extensions/gsd/db/writers/cascades.js +5 -1
  36. package/dist/resources/extensions/gsd/db/writers/status.js +13 -3
  37. package/dist/resources/extensions/gsd/db-base-schema.js +28 -0
  38. package/dist/resources/extensions/gsd/db-migration-steps.js +30 -0
  39. package/dist/resources/extensions/gsd/db-schema-metadata.js +4 -1
  40. package/dist/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  41. package/dist/resources/extensions/gsd/doctor-engine-checks.js +3 -6
  42. package/dist/resources/extensions/gsd/flat-phase-migration.js +156 -21
  43. package/dist/resources/extensions/gsd/git-service.js +19 -7
  44. package/dist/resources/extensions/gsd/gsd-db.js +187 -45
  45. package/dist/resources/extensions/gsd/guided-flow.js +38 -13
  46. package/dist/resources/extensions/gsd/markdown-renderer.js +17 -13
  47. package/dist/resources/extensions/gsd/md-importer.js +107 -20
  48. package/dist/resources/extensions/gsd/migrate/command.js +19 -162
  49. package/dist/resources/extensions/gsd/migrate/execution.js +98 -0
  50. package/dist/resources/extensions/gsd/migrate/plan.js +49 -0
  51. package/dist/resources/extensions/gsd/migrate/planning-writer.js +12 -17
  52. package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
  53. package/dist/resources/extensions/gsd/model-cost-table.js +2 -0
  54. package/dist/resources/extensions/gsd/model-router.js +11 -0
  55. package/dist/resources/extensions/gsd/parallel-eligibility.js +5 -4
  56. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +28 -43
  57. package/dist/resources/extensions/gsd/paths.js +55 -11
  58. package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
  59. package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
  60. package/dist/resources/extensions/gsd/planning-subagent-registry.js +25 -0
  61. package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
  62. package/dist/resources/extensions/gsd/preferences-types.js +5 -0
  63. package/dist/resources/extensions/gsd/preferences-validation.js +48 -1
  64. package/dist/resources/extensions/gsd/preferences.js +17 -0
  65. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  66. package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
  67. package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
  68. package/dist/resources/extensions/gsd/safety/evidence-collector.js +26 -1
  69. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +30 -5
  70. package/dist/resources/extensions/gsd/skill-activation.js +17 -3
  71. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +27 -13
  72. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +13 -3
  73. package/dist/resources/extensions/gsd/stop-notice.js +15 -1
  74. package/dist/resources/extensions/gsd/sync-lock.js +13 -7
  75. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  76. package/dist/resources/extensions/gsd/tools/complete-task.js +94 -6
  77. package/dist/resources/extensions/gsd/tools/plan-task.js +13 -15
  78. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +18 -15
  79. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
  80. package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
  81. package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
  82. package/dist/resources/extensions/gsd/tools/replan-task.js +128 -0
  83. package/dist/resources/extensions/gsd/tools/rework-brief.js +74 -0
  84. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +81 -0
  85. package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
  86. package/dist/resources/extensions/gsd/unit-registry.js +4 -0
  87. package/dist/resources/extensions/gsd/uok/plan-v2.js +19 -3
  88. package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
  89. package/dist/resources/extensions/gsd/workspace.js +2 -1
  90. package/dist/resources/extensions/gsd/worktree-state-projection.js +6 -0
  91. package/dist/resources/extensions/mac-tools/index.js +31 -9
  92. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  93. package/dist/web/standalone/.next/BUILD_ID +1 -1
  94. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  95. package/dist/web/standalone/.next/build-manifest.json +3 -3
  96. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  97. package/dist/web/standalone/.next/required-server-files.json +3 -3
  98. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  99. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  101. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  109. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
  112. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  118. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  125. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  137. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  159. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  169. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  175. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  176. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  190. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  191. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  192. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  195. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  203. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  204. package/dist/web/standalone/.next/server/app/index.html +1 -1
  205. package/dist/web/standalone/.next/server/app/index.rsc +5 -5
  206. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  207. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
  208. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  209. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
  210. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  211. package/dist/web/standalone/.next/server/app/page.js +2 -2
  212. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  213. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  214. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  215. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  216. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/middleware.js +3 -3
  218. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  219. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  220. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  221. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  222. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  223. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  224. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  225. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  226. package/dist/web/standalone/.next/static/css/3b1ceb7abfb9a230.css +1 -0
  227. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  228. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  229. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  230. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  231. package/dist/web/standalone/package.json +0 -1
  232. package/dist/web/standalone/server.js +1 -1
  233. package/dist/web-mode.js +31 -3
  234. package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
  235. package/integrations/hermes/pyproject.toml +1 -1
  236. package/package.json +12 -10
  237. package/packages/cloud-mcp-gateway/package.json +2 -2
  238. package/packages/contracts/dist/workflow.d.ts +14 -0
  239. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  240. package/packages/contracts/dist/workflow.js +16 -0
  241. package/packages/contracts/dist/workflow.js.map +1 -1
  242. package/packages/contracts/package.json +1 -1
  243. package/packages/daemon/dist/cloud-config.d.ts +1 -1
  244. package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
  245. package/packages/daemon/dist/cloud-config.js +5 -1
  246. package/packages/daemon/dist/cloud-config.js.map +1 -1
  247. package/packages/daemon/dist/cloud-config.test.js +51 -1
  248. package/packages/daemon/dist/cloud-config.test.js.map +1 -1
  249. package/packages/daemon/dist/local-tool-executor.d.ts.map +1 -1
  250. package/packages/daemon/dist/local-tool-executor.js +2 -0
  251. package/packages/daemon/dist/local-tool-executor.js.map +1 -1
  252. package/packages/daemon/package.json +6 -6
  253. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  254. package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
  255. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  256. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  257. package/packages/gsd-agent-core/dist/sdk.js +1 -0
  258. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  259. package/packages/gsd-agent-core/package.json +5 -5
  260. package/packages/gsd-agent-modes/package.json +7 -7
  261. package/packages/gsd-cloud/dist/cli.d.ts +5 -0
  262. package/packages/gsd-cloud/dist/cli.d.ts.map +1 -0
  263. package/packages/gsd-cloud/dist/cli.js +160 -0
  264. package/packages/gsd-cloud/dist/cli.js.map +1 -0
  265. package/packages/gsd-cloud/dist/cloud-config.d.ts +19 -0
  266. package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -0
  267. package/packages/gsd-cloud/dist/cloud-config.js +231 -0
  268. package/packages/gsd-cloud/dist/cloud-config.js.map +1 -0
  269. package/packages/gsd-cloud/dist/cloud-config.test.d.ts +2 -0
  270. package/packages/gsd-cloud/dist/cloud-config.test.d.ts.map +1 -0
  271. package/packages/gsd-cloud/dist/cloud-config.test.js +118 -0
  272. package/packages/gsd-cloud/dist/cloud-config.test.js.map +1 -0
  273. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts +2 -0
  274. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts.map +1 -0
  275. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js +37 -0
  276. package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js.map +1 -0
  277. package/packages/gsd-cloud/dist/cloud-runtime.d.ts +35 -0
  278. package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -0
  279. package/packages/gsd-cloud/dist/cloud-runtime.js +258 -0
  280. package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -0
  281. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts +2 -0
  282. package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts.map +1 -0
  283. package/packages/gsd-cloud/dist/cloud-runtime.test.js +88 -0
  284. package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -0
  285. package/packages/gsd-cloud/dist/cloud-token.d.ts +3 -0
  286. package/packages/gsd-cloud/dist/cloud-token.d.ts.map +1 -0
  287. package/packages/gsd-cloud/dist/cloud-token.js +37 -0
  288. package/packages/gsd-cloud/dist/cloud-token.js.map +1 -0
  289. package/packages/gsd-cloud/dist/config.d.ts +17 -0
  290. package/packages/gsd-cloud/dist/config.d.ts.map +1 -0
  291. package/packages/gsd-cloud/dist/config.js +146 -0
  292. package/packages/gsd-cloud/dist/config.js.map +1 -0
  293. package/packages/gsd-cloud/dist/device-flow.d.ts +24 -0
  294. package/packages/gsd-cloud/dist/device-flow.d.ts.map +1 -0
  295. package/packages/gsd-cloud/dist/device-flow.js +128 -0
  296. package/packages/gsd-cloud/dist/device-flow.js.map +1 -0
  297. package/packages/gsd-cloud/dist/device-flow.test.d.ts +2 -0
  298. package/packages/gsd-cloud/dist/device-flow.test.d.ts.map +1 -0
  299. package/packages/gsd-cloud/dist/device-flow.test.js +155 -0
  300. package/packages/gsd-cloud/dist/device-flow.test.js.map +1 -0
  301. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts +6 -0
  302. package/packages/gsd-cloud/dist/executors/claude-executor.d.ts.map +1 -0
  303. package/packages/gsd-cloud/dist/executors/claude-executor.js +15 -0
  304. package/packages/gsd-cloud/dist/executors/claude-executor.js.map +1 -0
  305. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts +6 -0
  306. package/packages/gsd-cloud/dist/executors/codex-executor.d.ts.map +1 -0
  307. package/packages/gsd-cloud/dist/executors/codex-executor.js +15 -0
  308. package/packages/gsd-cloud/dist/executors/codex-executor.js.map +1 -0
  309. package/packages/gsd-cloud/dist/executors/executor.d.ts +28 -0
  310. package/packages/gsd-cloud/dist/executors/executor.d.ts.map +1 -0
  311. package/packages/gsd-cloud/dist/executors/executor.js +11 -0
  312. package/packages/gsd-cloud/dist/executors/executor.js.map +1 -0
  313. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts +34 -0
  314. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts.map +1 -0
  315. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js +179 -0
  316. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js.map +1 -0
  317. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts +2 -0
  318. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts.map +1 -0
  319. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js +44 -0
  320. package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js.map +1 -0
  321. package/packages/gsd-cloud/dist/executors/index.d.ts +17 -0
  322. package/packages/gsd-cloud/dist/executors/index.d.ts.map +1 -0
  323. package/packages/gsd-cloud/dist/executors/index.js +29 -0
  324. package/packages/gsd-cloud/dist/executors/index.js.map +1 -0
  325. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts +36 -0
  326. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts.map +1 -0
  327. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js +176 -0
  328. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js.map +1 -0
  329. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts +2 -0
  330. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts.map +1 -0
  331. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js +34 -0
  332. package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js.map +1 -0
  333. package/packages/gsd-cloud/dist/index.d.ts +7 -0
  334. package/packages/gsd-cloud/dist/index.d.ts.map +1 -0
  335. package/packages/gsd-cloud/dist/index.js +8 -0
  336. package/packages/gsd-cloud/dist/index.js.map +1 -0
  337. package/packages/gsd-cloud/dist/inject-gateway.d.ts +16 -0
  338. package/packages/gsd-cloud/dist/inject-gateway.d.ts.map +1 -0
  339. package/packages/gsd-cloud/dist/inject-gateway.js +29 -0
  340. package/packages/gsd-cloud/dist/inject-gateway.js.map +1 -0
  341. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts +2 -0
  342. package/packages/gsd-cloud/dist/inject-gateway.test.d.ts.map +1 -0
  343. package/packages/gsd-cloud/dist/inject-gateway.test.js +41 -0
  344. package/packages/gsd-cloud/dist/inject-gateway.test.js.map +1 -0
  345. package/packages/gsd-cloud/dist/logger.d.ts +25 -0
  346. package/packages/gsd-cloud/dist/logger.d.ts.map +1 -0
  347. package/packages/gsd-cloud/dist/logger.js +72 -0
  348. package/packages/gsd-cloud/dist/logger.js.map +1 -0
  349. package/packages/gsd-cloud/dist/types.d.ts +51 -0
  350. package/packages/gsd-cloud/dist/types.d.ts.map +1 -0
  351. package/packages/gsd-cloud/dist/types.js +9 -0
  352. package/packages/gsd-cloud/dist/types.js.map +1 -0
  353. package/packages/gsd-cloud/package.json +3 -3
  354. package/packages/mcp-server/README.md +15 -2
  355. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  356. package/packages/mcp-server/dist/server.js +5 -5
  357. package/packages/mcp-server/dist/server.js.map +1 -1
  358. package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
  359. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  360. package/packages/mcp-server/dist/workflow-tools.js +64 -2
  361. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  362. package/packages/mcp-server/package.json +4 -4
  363. package/packages/native/package.json +1 -1
  364. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  365. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  366. package/packages/pi-agent-core/dist/agent.js +2 -0
  367. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  368. package/packages/pi-agent-core/package.json +1 -1
  369. package/packages/pi-ai/dist/models.generated.d.ts +119 -0
  370. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  371. package/packages/pi-ai/dist/models.generated.js +107 -0
  372. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  373. package/packages/pi-ai/dist/providers/amazon-bedrock.js +1 -0
  374. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  375. package/packages/pi-ai/dist/providers/anthropic.js +25 -1
  376. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  377. package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
  378. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  379. package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
  380. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  381. package/packages/pi-ai/package.json +1 -1
  382. package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
  383. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  384. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
  385. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  386. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +11 -1
  387. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  388. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  389. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  390. package/packages/pi-coding-agent/package.json +7 -7
  391. package/packages/pi-tui/package.json +2 -2
  392. package/packages/rpc-client/package.json +2 -2
  393. package/pkg/package.json +1 -1
  394. package/src/resources/GSD-WORKFLOW.md +18 -49
  395. package/src/resources/extensions/browser-tools/capture.ts +2 -86
  396. package/src/resources/extensions/browser-tools/screenshot-constraints.ts +94 -0
  397. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -1
  398. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -0
  399. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +30 -2
  400. package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
  401. package/src/resources/extensions/gsd/auto-artifact-paths.ts +16 -9
  402. package/src/resources/extensions/gsd/auto-dispatch.ts +86 -19
  403. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -0
  404. package/src/resources/extensions/gsd/auto-prompts.ts +142 -16
  405. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  406. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
  407. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
  408. package/src/resources/extensions/gsd/auto.ts +5 -1
  409. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +92 -4
  410. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +39 -10
  411. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
  412. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +87 -53
  413. package/src/resources/extensions/gsd/command-feedback.ts +19 -12
  414. package/src/resources/extensions/gsd/compat/compat-marker.ts +21 -4
  415. package/src/resources/extensions/gsd/constants.ts +14 -13
  416. package/src/resources/extensions/gsd/context-masker.ts +98 -2
  417. package/src/resources/extensions/gsd/db/command-queue.ts +7 -1
  418. package/src/resources/extensions/gsd/db/engine.ts +53 -17
  419. package/src/resources/extensions/gsd/db/writers/cascades.ts +5 -1
  420. package/src/resources/extensions/gsd/db/writers/status.ts +25 -8
  421. package/src/resources/extensions/gsd/db-base-schema.ts +30 -0
  422. package/src/resources/extensions/gsd/db-migration-steps.ts +32 -0
  423. package/src/resources/extensions/gsd/db-schema-metadata.ts +4 -1
  424. package/src/resources/extensions/gsd/docs/preferences-reference.md +26 -4
  425. package/src/resources/extensions/gsd/doctor-engine-checks.ts +3 -5
  426. package/src/resources/extensions/gsd/flat-phase-migration.ts +160 -19
  427. package/src/resources/extensions/gsd/git-service.ts +19 -6
  428. package/src/resources/extensions/gsd/gsd-db.ts +255 -52
  429. package/src/resources/extensions/gsd/guided-flow.ts +48 -12
  430. package/src/resources/extensions/gsd/markdown-renderer.ts +25 -21
  431. package/src/resources/extensions/gsd/md-importer.ts +114 -16
  432. package/src/resources/extensions/gsd/migrate/command.ts +21 -227
  433. package/src/resources/extensions/gsd/migrate/execution.ts +136 -0
  434. package/src/resources/extensions/gsd/migrate/plan.ts +101 -0
  435. package/src/resources/extensions/gsd/migrate/planning-writer.ts +12 -20
  436. package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
  437. package/src/resources/extensions/gsd/model-cost-table.ts +2 -0
  438. package/src/resources/extensions/gsd/model-router.ts +12 -0
  439. package/src/resources/extensions/gsd/parallel-eligibility.ts +5 -4
  440. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +37 -40
  441. package/src/resources/extensions/gsd/paths.ts +62 -11
  442. package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
  443. package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
  444. package/src/resources/extensions/gsd/planning-subagent-registry.ts +31 -0
  445. package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
  446. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  447. package/src/resources/extensions/gsd/preferences-validation.ts +62 -0
  448. package/src/resources/extensions/gsd/preferences.ts +25 -0
  449. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  450. package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
  451. package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
  452. package/src/resources/extensions/gsd/safety/evidence-collector.ts +28 -1
  453. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +31 -5
  454. package/src/resources/extensions/gsd/skill-activation.ts +17 -3
  455. package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +30 -13
  456. package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +16 -3
  457. package/src/resources/extensions/gsd/state-reconciliation/types.ts +2 -2
  458. package/src/resources/extensions/gsd/stop-notice.ts +18 -1
  459. package/src/resources/extensions/gsd/sync-lock.ts +14 -6
  460. package/src/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
  461. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
  462. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
  463. package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
  464. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +96 -1
  465. package/src/resources/extensions/gsd/tests/command-feedback.test.ts +12 -0
  466. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +104 -0
  467. package/src/resources/extensions/gsd/tests/complete-task.test.ts +362 -1
  468. package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
  469. package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
  470. package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
  471. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
  472. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
  473. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
  474. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +123 -0
  475. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +50 -0
  476. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +49 -0
  477. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +81 -0
  478. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +22 -0
  479. package/src/resources/extensions/gsd/tests/external-edit-scoped-import.test.ts +262 -0
  480. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +202 -0
  481. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +29 -0
  482. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +25 -0
  483. package/src/resources/extensions/gsd/tests/import-slice-milestone-completion-preserve.test.ts +116 -0
  484. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
  485. package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
  486. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
  487. package/src/resources/extensions/gsd/tests/migrate-plan.test.ts +68 -0
  488. package/src/resources/extensions/gsd/tests/migrate-presentation.test.ts +98 -0
  489. package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +1 -1
  490. package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +55 -0
  491. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  492. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  493. package/src/resources/extensions/gsd/tests/parallel-eligibility-file-overlap.test.ts +146 -0
  494. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +59 -0
  495. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
  496. package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +32 -4
  497. package/src/resources/extensions/gsd/tests/plan-task.test.ts +26 -23
  498. package/src/resources/extensions/gsd/tests/planning-writer.test.ts +29 -0
  499. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
  500. package/src/resources/extensions/gsd/tests/preferences.test.ts +84 -0
  501. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +4 -0
  502. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +66 -0
  503. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
  504. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +50 -0
  505. package/src/resources/extensions/gsd/tests/replan-task-handler.test.ts +103 -0
  506. package/src/resources/extensions/gsd/tests/rework-brief.test.ts +197 -0
  507. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  508. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
  509. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
  510. package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
  511. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +17 -0
  512. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +19 -0
  513. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
  514. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
  515. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +73 -0
  516. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +93 -1
  517. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -0
  518. package/src/resources/extensions/gsd/tests/workflow-migration-gates.test.ts +139 -0
  519. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
  520. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
  521. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
  522. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
  523. package/src/resources/extensions/gsd/tools/complete-task.ts +140 -5
  524. package/src/resources/extensions/gsd/tools/plan-task.ts +14 -16
  525. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +18 -17
  526. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
  527. package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
  528. package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
  529. package/src/resources/extensions/gsd/tools/replan-task.ts +160 -0
  530. package/src/resources/extensions/gsd/tools/rework-brief.ts +91 -0
  531. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +92 -0
  532. package/src/resources/extensions/gsd/types.ts +11 -0
  533. package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
  534. package/src/resources/extensions/gsd/unit-registry.ts +4 -0
  535. package/src/resources/extensions/gsd/uok/plan-v2.ts +20 -3
  536. package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
  537. package/src/resources/extensions/gsd/workspace.ts +2 -1
  538. package/src/resources/extensions/gsd/worktree-state-projection.ts +12 -0
  539. package/src/resources/extensions/mac-tools/index.ts +52 -9
  540. package/src/resources/extensions/mac-tools/tests/mac-screenshot-payload.test.cjs +70 -0
  541. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  542. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  543. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  544. package/dist/web/standalone/.next/static/css/18c2fdf261bfc1b7.css +0 -1
  545. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → 6YWV7VAPg-jqjfPswrKZb}/_buildManifest.js +0 -0
  546. /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → 6YWV7VAPg-jqjfPswrKZb}/_ssgManifest.js +0 -0
@@ -0,0 +1,83 @@
1
+ // sharp is an optional native dependency. Load it lazily so that screenshot
2
+ // emitters still work on platforms where sharp is unavailable (e.g. bunx on
3
+ // Raspberry Pi). constrainScreenshot falls back to returning the raw buffer
4
+ // when sharp is not installed.
5
+ let _sharp;
6
+ async function getSharp() {
7
+ if (_sharp !== undefined)
8
+ return _sharp;
9
+ try {
10
+ _sharp = (await import("sharp")).default;
11
+ }
12
+ catch {
13
+ _sharp = null;
14
+ }
15
+ return _sharp;
16
+ }
17
+ /**
18
+ * Test-only seam: override the cached sharp module. Pass `null` to simulate
19
+ * an environment where the sharp native dep is unavailable; pass `undefined`
20
+ * to clear the cache and let the next getSharp() call re-import. See
21
+ * tests/capture-sharp-optional.test.cjs.
22
+ */
23
+ export function __setSharpForTesting(value) {
24
+ _sharp = value;
25
+ }
26
+ // Anthropic vision: 1568px is the recommended optimal width. Height is capped
27
+ // generously at 8000px so tall full-page screenshots remain readable rather
28
+ // than being squished into a square constraint.
29
+ //
30
+ // Override via environment variables:
31
+ // SCREENSHOT_MAX_WIDTH=0 -> uncap width (use raw resolution)
32
+ // SCREENSHOT_MAX_HEIGHT=0 -> uncap height
33
+ export const MAX_SCREENSHOT_WIDTH = parseScreenshotDimension(process.env.SCREENSHOT_MAX_WIDTH, 1568);
34
+ export const MAX_SCREENSHOT_HEIGHT = parseScreenshotDimension(process.env.SCREENSHOT_MAX_HEIGHT, 8000);
35
+ /** Parse a dimension env var: positive int = that value, 0 = Infinity (uncapped), absent/invalid = default. */
36
+ function parseScreenshotDimension(value, fallback) {
37
+ if (value === undefined || value === "")
38
+ return fallback;
39
+ const n = parseInt(value, 10);
40
+ if (isNaN(n) || n < 0)
41
+ return fallback;
42
+ if (n === 0)
43
+ return Infinity;
44
+ return n;
45
+ }
46
+ export async function getScreenshotBufferDimensions(buffer) {
47
+ const sharp = await getSharp();
48
+ if (!sharp)
49
+ return null;
50
+ const meta = await sharp(buffer).metadata();
51
+ if (meta.width === undefined || meta.height === undefined)
52
+ return null;
53
+ return { width: meta.width, height: meta.height };
54
+ }
55
+ /**
56
+ * Constrain screenshot dimensions for the Anthropic vision API.
57
+ * Width is capped at 1568px (optimal) and height at 8000px, each
58
+ * independently, using `fit: "inside"` so aspect ratio is preserved.
59
+ * Small images are never upscaled.
60
+ *
61
+ * `page` parameter is retained for ToolDeps signature stability (D008)
62
+ * but is no longer used — all processing is server-side via sharp.
63
+ */
64
+ export async function constrainScreenshot(_page, buffer, mimeType, quality) {
65
+ const sharp = await getSharp();
66
+ if (!sharp)
67
+ return buffer;
68
+ const dimensions = await getScreenshotBufferDimensions(buffer);
69
+ const width = dimensions?.width;
70
+ const height = dimensions?.height;
71
+ if (width === undefined || height === undefined)
72
+ return buffer;
73
+ if (width <= MAX_SCREENSHOT_WIDTH && height <= MAX_SCREENSHOT_HEIGHT)
74
+ return buffer;
75
+ const resizer = sharp(buffer).resize(MAX_SCREENSHOT_WIDTH, MAX_SCREENSHOT_HEIGHT, {
76
+ fit: "inside",
77
+ withoutEnlargement: true,
78
+ });
79
+ if (mimeType === "image/png") {
80
+ return Buffer.from(await resizer.png().toBuffer());
81
+ }
82
+ return Buffer.from(await resizer.jpeg({ quality }).toBuffer());
83
+ }
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import { EventStream } from "@gsd/pi-ai";
12
12
  import { execSync } from "node:child_process";
13
+ import { createHash } from "node:crypto";
13
14
  import { existsSync, readFileSync } from "node:fs";
14
15
  import { homedir } from "node:os";
15
16
  import { createRequire } from "node:module";
@@ -368,6 +369,7 @@ function inferMimeTypeFromDataUri(value) {
368
369
  /** Collect all base64 image blocks from user messages in the context for inclusion in the SDK prompt. */
369
370
  export function extractImageBlocksFromContext(context) {
370
371
  const imageBlocks = [];
372
+ const seenImageKeys = new Set();
371
373
  for (const msg of context.messages) {
372
374
  if (msg.role !== "user" || !Array.isArray(msg.content))
373
375
  continue;
@@ -382,12 +384,17 @@ export function extractImageBlocksFromContext(context) {
382
384
  : inferMimeTypeFromDataUri(block.data);
383
385
  if (!mimeType)
384
386
  continue;
387
+ const data = stripDataUriPrefix(block.data);
388
+ const imageKey = `${mimeType}\0${createHash("sha1").update(data).digest("hex")}`;
389
+ if (seenImageKeys.has(imageKey))
390
+ continue;
391
+ seenImageKeys.add(imageKey);
385
392
  imageBlocks.push({
386
393
  type: "image",
387
394
  source: {
388
395
  type: "base64",
389
396
  media_type: mimeType,
390
- data: stripDataUriPrefix(block.data),
397
+ data,
391
398
  },
392
399
  });
393
400
  }
@@ -1831,6 +1838,7 @@ function createSdkAttemptMessageState() {
1831
1838
  return {
1832
1839
  builder: null,
1833
1840
  intermediateToolBlocks: [],
1841
+ intermediateTextBlocks: [],
1834
1842
  toolResultsById: new Map(),
1835
1843
  toolCompletionTargetsById: new Map(),
1836
1844
  emittedExternalToolResultIds: new Set(),
@@ -1939,7 +1947,7 @@ async function pumpSdkMessages(model, context, options, stream) {
1939
1947
  }
1940
1948
  }
1941
1949
  sdkAttemptLoop: for (let readinessAttempt = 0;; readinessAttempt++) {
1942
- let { builder, intermediateToolBlocks, toolResultsById, toolCompletionTargetsById, emittedExternalToolResultIds, } = createSdkAttemptMessageState();
1950
+ let { builder, intermediateToolBlocks, intermediateTextBlocks, toolResultsById, toolCompletionTargetsById, emittedExternalToolResultIds, } = createSdkAttemptMessageState();
1943
1951
  const controller = new AbortController();
1944
1952
  const forwardAbort = () => controller.abort();
1945
1953
  if (options?.signal) {
@@ -2061,9 +2069,15 @@ async function pumpSdkMessages(model, context, options, stream) {
2061
2069
  for (const [contentIndex, block] of builder.message.content.entries()) {
2062
2070
  if (block.type === "text" && block.text) {
2063
2071
  lastTextContent = block.text;
2072
+ // Accumulate completed prose in order — a multi-question
2073
+ // turn commits [prose][elicitation] segments across several
2074
+ // synthetic-user boundaries, and overwriting a single
2075
+ // scalar would drop every explanation but the last.
2076
+ intermediateTextBlocks.push({ type: "text", text: block.text });
2064
2077
  }
2065
2078
  else if (block.type === "thinking" && block.thinking) {
2066
2079
  lastThinkingContent = block.thinking;
2080
+ intermediateTextBlocks.push({ type: "thinking", thinking: block.thinking });
2067
2081
  }
2068
2082
  else if (block.type === "toolCall" || block.type === "serverToolUse") {
2069
2083
  // Collect tool blocks for externalToolExecution rendering
@@ -2161,6 +2175,7 @@ async function pumpSdkMessages(model, context, options, stream) {
2161
2175
  const result = msg;
2162
2176
  const finalContent = buildFinalAssistantContent({
2163
2177
  intermediateToolBlocks,
2178
+ intermediateTextBlocks,
2164
2179
  pendingContent: builder?.message.content,
2165
2180
  toolResultsById,
2166
2181
  lastThinkingContent,
@@ -198,6 +198,15 @@ export function buildFinalAssistantContent(params) {
198
198
  }
199
199
  attachExternalResultsToToolBlocks(mergedToolBlocks, params.toolResultsById);
200
200
  const finalContent = mergedToolBlocks.filter((block) => !shouldSuppressDuplicateToolUnavailableBlock(block, mergedToolBlocks));
201
+ // Emit prose/thinking captured at earlier turn-boundaries (each successive
202
+ // `ask_user_questions` elicitation completes a turn) before the final
203
+ // segment. Capturing these in an ordered accumulator — symmetric with
204
+ // `intermediateToolBlocks` — is what keeps intermediate explanations from
205
+ // being collapsed to a single overwritten scalar and silently dropped.
206
+ const intermediateTextBlocks = params.intermediateTextBlocks ?? [];
207
+ for (const block of intermediateTextBlocks) {
208
+ finalContent.push(block);
209
+ }
201
210
  if (params.pendingContent && params.pendingContent.length > 0) {
202
211
  for (const block of params.pendingContent) {
203
212
  if (block.type === "text" || block.type === "thinking") {
@@ -206,11 +215,30 @@ export function buildFinalAssistantContent(params) {
206
215
  }
207
216
  }
208
217
  else {
218
+ // No builder content survived to this turn boundary, so fall back to the
219
+ // last scalar thinking/text captured off the stream. When the turn ends
220
+ // on an elicitation these scalars just mirror the final intermediate
221
+ // block (they are overwritten at each synthetic-user boundary), so only
222
+ // emit them when they carry content not already accumulated — otherwise
223
+ // a non-streaming `assistant` message's prose/thinking is silently lost.
224
+ const lastBlockOfType = (type) => {
225
+ for (let i = intermediateTextBlocks.length - 1; i >= 0; i--) {
226
+ if (intermediateTextBlocks[i].type === type)
227
+ return intermediateTextBlocks[i];
228
+ }
229
+ return undefined;
230
+ };
209
231
  if (params.lastThinkingContent) {
210
- finalContent.push({ type: "thinking", thinking: params.lastThinkingContent });
232
+ const lastThinking = lastBlockOfType("thinking");
233
+ if (lastThinking?.thinking !== params.lastThinkingContent) {
234
+ finalContent.push({ type: "thinking", thinking: params.lastThinkingContent });
235
+ }
211
236
  }
212
237
  if (params.lastTextContent) {
213
- finalContent.push({ type: "text", text: params.lastTextContent });
238
+ const lastText = lastBlockOfType("text");
239
+ if (lastText?.text !== params.lastTextContent) {
240
+ finalContent.push({ type: "text", text: params.lastTextContent });
241
+ }
214
242
  }
215
243
  }
216
244
  if (finalContent.length === 0 && params.fallbackResultText) {
@@ -9,7 +9,7 @@ import { refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
9
9
  import { isValidationTerminal } from "./state.js";
10
10
  import { getErrorMessage } from "./error-utils.js";
11
11
  import { logWarning, logError } from "./workflow-logger.js";
12
- import { resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, relSliceFile, resolveMilestoneFile, clearPathCache, resolveGsdRootFile, } from "./paths.js";
12
+ import { resolveSlicePath, resolveSliceFile, resolveTasksDir, resolveTaskFiles, resolveTaskFile, relSliceFile, resolveMilestoneFile, clearPathCache, resolveGsdRootFile, } from "./paths.js";
13
13
  import { existsSync, readFileSync } from "node:fs";
14
14
  import { execFileSync } from "node:child_process";
15
15
  import { LAYOUT_SEGMENTS } from "./layout-policy.js";
@@ -185,10 +185,9 @@ export function verifyExpectedArtifact(unitType, unitId, base) {
185
185
  const batchIds = batchPart.slice(plusIdx + 1).split(",").filter(Boolean);
186
186
  if (batchIds.length === 0)
187
187
  return false;
188
- const tDir = resolveTasksDir(base, mid, sid) ?? slicePath;
189
- const existingSummaries = new Set(resolveTaskFiles(tDir, "SUMMARY").map((f) => f.replace(/-SUMMARY\.md$/i, "").toUpperCase()));
190
188
  for (const tid of batchIds) {
191
- if (!existingSummaries.has(tid.toUpperCase()))
189
+ const summaryPath = resolveTaskFile(base, mid, sid, tid, "SUMMARY");
190
+ if (!summaryPath || !existsSync(summaryPath))
192
191
  return false;
193
192
  }
194
193
  return true;
@@ -5,7 +5,7 @@
5
5
  // resolveExpectedArtifactPath and diagnoseExpectedArtifact moved here from
6
6
  // auto-recovery.ts (Phase 5 dead-code cleanup). The artifact verification
7
7
  // function was removed entirely — callers now query WorkflowEngine directly.
8
- import { gsdRoot, resolveDir, resolveFile, resolveMilestonePath, resolveMilestoneFile, resolveSliceFile, relMilestoneFile, relSliceFile, buildTaskFileName, resolveSlicePath, resolveTasksDir, dirIsMetaOnlyLegacyMilestone, normalizeRealPath, } from "./paths.js";
8
+ import { gsdRoot, resolveDir, resolveFile, resolveMilestonePath, resolveMilestoneFile, resolveSliceFile, relMilestoneFile, relSliceFile, buildFlatTaskFileName, buildTaskFileName, resolveSlicePath, resolveTasksDir, dirIsMetaOnlyLegacyMilestone, normalizeRealPath, } from "./paths.js";
9
9
  import { milestoneIdToPhaseNum } from "./layout-policy.js";
10
10
  import { parseUnitId } from "./unit-id.js";
11
11
  import { basename, dirname, join, relative } from "node:path";
@@ -79,12 +79,15 @@ function resolveProjectMilestonePath(base, mid) {
79
79
  const dir = resolveDir(milestonesDir, mid);
80
80
  if (!dir)
81
81
  return null;
82
- // git-service.ts creates milestones/<MID>/ for integration-branch metadata
83
- // (<MID>-META.json) even in flat-phase projects. A dir that holds ONLY
84
- // *-META.json files must not be treated as a real legacy milestone dir
85
- // otherwise this early-return resolves CONTEXT/ROADMAP/SUMMARY to the legacy
86
- // path (milestones/<MID>/<MID>-<SUFFIX>.md) before the flat-phase fallback
87
- // can run, trapping the unit in a finalize-retry loop (#852 follow-up).
82
+ // Historically git-service.ts wrote integration-branch metadata into
83
+ // milestones/<MID>/<MID>-META.json, which could create that dir in flat-phase
84
+ // projects and poison layout detection. As of ADR-045 that META lives flat at
85
+ // .gsd/<MID>-META.json and no longer poisons detection. A dir that holds ONLY
86
+ // *-META.json files (a pre-migration on-disk tree) must still not be treated
87
+ // as a real legacy milestone dir otherwise this early-return resolves
88
+ // CONTEXT/ROADMAP/SUMMARY to the legacy path (milestones/<MID>/<MID>-<SUFFIX>.md)
89
+ // before the flat-phase fallback can run, trapping the unit in a
90
+ // finalize-retry loop (#852 follow-up).
88
91
  //
89
92
  // We use dirIsMetaOnlyLegacyMilestone rather than !dirIsContentBearingLegacyMilestone
90
93
  // so that an EMPTY dir (a new milestone before any content is written) is NOT
@@ -203,7 +206,10 @@ export function resolveExpectedArtifactPath(unitType, unitId, base) {
203
206
  const summaryDir = isLegacySlice
204
207
  ? (resolveTasksDir(base, mid, sid) ?? slicePath)
205
208
  : slicePath;
206
- return join(summaryDir, buildTaskFileName(tid, "SUMMARY"));
209
+ const fileName = isLegacySlice
210
+ ? buildTaskFileName(tid, "SUMMARY")
211
+ : buildFlatTaskFileName(sid, tid, "SUMMARY");
212
+ return join(summaryDir, fileName);
207
213
  }
208
214
  case "complete-slice": {
209
215
  return resolveSliceArtifactPath(base, mid, sid, "SUMMARY");
@@ -263,9 +269,9 @@ export function diagnoseExpectedArtifact(unitType, unitId, base) {
263
269
  }
264
270
  return `${relSliceFile(base, mid, sid, "RESEARCH")} (slice research)`;
265
271
  case "plan-slice":
266
- return `${relSliceFile(base, mid, sid, "PLAN")} plus tasks/T##-PLAN.md files (slice plan and task plans)`;
272
+ return `${relSliceFile(base, mid, sid, "PLAN")} with embedded task plans`;
267
273
  case "refine-slice":
268
- return `${relSliceFile(base, mid, sid, "PLAN")} plus tasks/T##-PLAN.md files (refined slice plan and task plans)`;
274
+ return `${relSliceFile(base, mid, sid, "PLAN")} with embedded refined task plans`;
269
275
  case "execute-task": {
270
276
  return `Task ${tid} marked [x] in ${relSliceFile(base, mid, sid, "PLAN")} + summary written`;
271
277
  }
@@ -209,7 +209,8 @@ export function shouldRunDeepProjectSetup(state, prefs, basePath, options = {})
209
209
  }
210
210
  function resolveArtifactBasePath(basePath, mid, session) {
211
211
  if (session?.basePath &&
212
- session.currentMilestoneId === mid &&
212
+ session.currentMilestoneId &&
213
+ milestoneIdsDispatchCompatible(session.currentMilestoneId, mid) &&
213
214
  existsSync(session.basePath)) {
214
215
  return session.basePath;
215
216
  }
@@ -231,6 +232,24 @@ function normalizeMilestoneScope(value) {
231
232
  return null;
232
233
  return trimmed;
233
234
  }
235
+ function dispatchMilestoneIdentity(value) {
236
+ const normalized = normalizeMilestoneScope(value);
237
+ const match = normalized?.match(/^(M\d{3})(?:-[a-z0-9]{6})?$/);
238
+ if (!match)
239
+ return null;
240
+ return { baseId: match[1], hasSuffix: normalized !== match[1] };
241
+ }
242
+ function isBareSuffixedMilestoneAlias(left, right) {
243
+ const leftId = dispatchMilestoneIdentity(left);
244
+ const rightId = dispatchMilestoneIdentity(right);
245
+ return Boolean(leftId &&
246
+ rightId &&
247
+ leftId.baseId === rightId.baseId &&
248
+ leftId.hasSuffix !== rightId.hasSuffix);
249
+ }
250
+ function milestoneIdsDispatchCompatible(left, right) {
251
+ return left === right || isBareSuffixedMilestoneAlias(left, right);
252
+ }
234
253
  function resolveDispatchMilestoneScope(ctx) {
235
254
  const sessionMilestone = normalizeMilestoneScope(ctx.session?.currentMilestoneId);
236
255
  if (sessionMilestone)
@@ -243,6 +262,31 @@ function resolveDispatchMilestoneScope(ctx) {
243
262
  return { id: baseWorktree, source: "basePath worktree" };
244
263
  return null;
245
264
  }
265
+ function resolveEffectiveDispatchMilestoneId(ctx, scopedMilestone) {
266
+ if (scopedMilestone && isBareSuffixedMilestoneAlias(ctx.mid, scopedMilestone.id)) {
267
+ return dispatchMilestoneIdentity(scopedMilestone.id)?.hasSuffix ? scopedMilestone.id : ctx.mid;
268
+ }
269
+ const activeMid = ctx.state.activeMilestone?.id;
270
+ if (activeMid && isBareSuffixedMilestoneAlias(ctx.mid, activeMid)) {
271
+ return dispatchMilestoneIdentity(activeMid)?.hasSuffix ? activeMid : ctx.mid;
272
+ }
273
+ return ctx.mid;
274
+ }
275
+ function withEffectiveDispatchMilestone(ctx, effectiveMid) {
276
+ if (effectiveMid === ctx.mid)
277
+ return ctx;
278
+ const activeMilestone = ctx.state.activeMilestone;
279
+ const state = activeMilestone && milestoneIdsDispatchCompatible(activeMilestone.id, effectiveMid)
280
+ ? {
281
+ ...ctx.state,
282
+ activeMilestone: {
283
+ ...activeMilestone,
284
+ id: effectiveMid,
285
+ },
286
+ }
287
+ : ctx.state;
288
+ return { ...ctx, mid: effectiveMid, state };
289
+ }
246
290
  function hasMilestonePassedDiscuss(basePath, mid) {
247
291
  if (isDbAvailable()) {
248
292
  try {
@@ -510,18 +554,25 @@ export const DISPATCH_RULES = [
510
554
  // Fire BEFORE the execution-entry phase rules so we redispatch to
511
555
  // `discuss-milestone` instead of hitting the plan-v2 gate.
512
556
  name: "execution-entry phase (no context) → discuss-milestone",
513
- match: async ({ state, mid, midTitle, basePath, prefs, structuredQuestionsAvailable }) => {
557
+ match: async ({ state, mid, midTitle, basePath, session, prefs, structuredQuestionsAvailable }) => {
514
558
  if (!EXECUTION_ENTRY_PHASES.has(state.phase))
515
559
  return null;
516
560
  if (!MILESTONE_ID_RE.test(mid))
517
561
  return null;
518
562
  if (isRegistryMilestoneComplete(state, mid))
519
563
  return null;
520
- if (hasMilestonePassedDiscuss(basePath, mid))
564
+ // Resolve discuss/context artifacts against the active session worktree,
565
+ // mirroring the executing rules below. For a suffixed-worktree milestone
566
+ // the CONTEXT and slice plans live under the worktree, not the project
567
+ // root; checking the raw project-root basePath misreads the milestone as
568
+ // "never discussed" and re-dispatches discuss-milestone after task
569
+ // closeout instead of continuing execution (#1317).
570
+ const artifactBasePath = resolveArtifactBasePath(basePath, mid, session);
571
+ if (hasMilestonePassedDiscuss(artifactBasePath, mid))
521
572
  return null;
522
573
  // Align with the plan-v2 gate's lookup semantics: whitespace-only counts
523
574
  // as missing, and an auto worktree may fall back to GSD_PROJECT_ROOT.
524
- if (hasFinalizedMilestoneContext(basePath, mid))
575
+ if (hasFinalizedMilestoneContext(artifactBasePath, mid))
525
576
  return null;
526
577
  // H6 fix (#4973): non-deep auto-mode has no human to answer the
527
578
  // depth-verification question, so pre-marking avoids a write-gate
@@ -854,12 +905,14 @@ export const DISPATCH_RULES = [
854
905
  },
855
906
  {
856
907
  name: "pre-planning (no context) → discuss-milestone",
857
- match: async ({ state, mid, midTitle, basePath, prefs, structuredQuestionsAvailable }) => {
908
+ match: async ({ state, mid, midTitle, basePath, prefs, session, structuredQuestionsAvailable }) => {
858
909
  if (state.phase !== "pre-planning")
859
910
  return null;
860
911
  if (isRegistryMilestoneComplete(state, mid))
861
912
  return null;
862
- const contextFile = resolveMilestoneFile(basePath, mid, "CONTEXT");
913
+ const contextBasePath = resolveWorktreeProjectRoot(basePath, session?.originalBasePath);
914
+ const contextFile = resolveMilestoneFile(basePath, mid, "CONTEXT") ??
915
+ (contextBasePath !== basePath ? resolveMilestoneFile(contextBasePath, mid, "CONTEXT") : null);
863
916
  const hasContext = !!(contextFile && (await loadFile(contextFile)));
864
917
  if (hasContext)
865
918
  return null; // fall through to next rule
@@ -1562,31 +1615,33 @@ function applyLanguageDirectiveToDispatch(action, prefs) {
1562
1615
  * resolveDispatch directly without registry initialization).
1563
1616
  */
1564
1617
  export async function resolveDispatch(ctx) {
1565
- if (ctx.mid && isDbAvailable()) {
1566
- const milestone = getMilestone(ctx.mid);
1618
+ const scopedMilestone = resolveDispatchMilestoneScope(ctx);
1619
+ const effectiveMid = resolveEffectiveDispatchMilestoneId(ctx, scopedMilestone);
1620
+ const dispatchCtx = withEffectiveDispatchMilestone(ctx, effectiveMid);
1621
+ if (dispatchCtx.mid && isDbAvailable()) {
1622
+ const milestone = getMilestone(dispatchCtx.mid);
1567
1623
  if (milestone && isClosedStatus(milestone.status)) {
1568
1624
  return {
1569
1625
  action: "stop",
1570
- reason: `Milestone ${ctx.mid} is closed (status: ${milestone.status}); auto-mode will not reopen or recover it implicitly. ` +
1626
+ reason: `Milestone ${dispatchCtx.mid} is closed (status: ${milestone.status}); auto-mode will not reopen or recover it implicitly. ` +
1571
1627
  "Use an explicit reopen command before planning or executing more work for this milestone.",
1572
1628
  level: "warning",
1573
1629
  };
1574
1630
  }
1575
1631
  }
1576
- const activeMid = ctx.state.activeMilestone?.id;
1577
- if (activeMid && ctx.mid !== activeMid) {
1632
+ const activeMid = dispatchCtx.state.activeMilestone?.id;
1633
+ if (activeMid && !milestoneIdsDispatchCompatible(dispatchCtx.mid, activeMid)) {
1578
1634
  return {
1579
1635
  action: "stop",
1580
- reason: `Dispatch milestone mismatch: context mid "${ctx.mid}" does not match active milestone "${activeMid}". ` +
1636
+ reason: `Dispatch milestone mismatch: context mid "${dispatchCtx.mid}" does not match active milestone "${activeMid}". ` +
1581
1637
  "This usually means a project-level deep setup pseudo-id leaked into milestone dispatch; rerun /gsd auto after setup state is reconciled.",
1582
1638
  level: "warning",
1583
1639
  };
1584
1640
  }
1585
- const scopedMilestone = resolveDispatchMilestoneScope(ctx);
1586
- if (scopedMilestone && ctx.mid !== scopedMilestone.id) {
1641
+ if (scopedMilestone && !milestoneIdsDispatchCompatible(dispatchCtx.mid, scopedMilestone.id)) {
1587
1642
  return {
1588
1643
  action: "stop",
1589
- reason: `Dispatch milestone mismatch: context mid "${ctx.mid}" does not match ${scopedMilestone.source} "${scopedMilestone.id}". ` +
1644
+ reason: `Dispatch milestone mismatch: context mid "${dispatchCtx.mid}" does not match ${scopedMilestone.source} "${scopedMilestone.id}". ` +
1590
1645
  "The active worktree/session and derived project state disagree; recover, park, or discard the stranded milestone before continuing.",
1591
1646
  level: "warning",
1592
1647
  };
@@ -1594,9 +1649,9 @@ export async function resolveDispatch(ctx) {
1594
1649
  // Delegate to registry when available
1595
1650
  try {
1596
1651
  const registry = getRegistry();
1597
- const action = annotateBackgroundable(await registry.evaluateDispatch(ctx));
1652
+ const action = annotateBackgroundable(await registry.evaluateDispatch(dispatchCtx));
1598
1653
  if (action.action === "dispatch" &&
1599
- ctx.session?.exhaustedVerificationUnits?.has(`${action.unitType}:${action.unitId}`)) {
1654
+ dispatchCtx.session?.exhaustedVerificationUnits?.has(`${action.unitType}:${action.unitId}`)) {
1600
1655
  return {
1601
1656
  action: "stop",
1602
1657
  reason: `Unit ${action.unitId} exhausted verification retries this session.`,
@@ -1610,13 +1665,13 @@ export async function resolveDispatch(ctx) {
1610
1665
  logWarning("dispatch", `registry dispatch failed, falling back to inline rules: ${err instanceof Error ? err.message : String(err)}`);
1611
1666
  }
1612
1667
  for (const rule of DISPATCH_RULES) {
1613
- const result = await rule.match(ctx);
1668
+ const result = await rule.match(dispatchCtx);
1614
1669
  if (result) {
1615
1670
  if (result.action !== "skip")
1616
1671
  result.matchedRule = rule.name;
1617
1672
  const action = annotateBackgroundable(result);
1618
1673
  if (action.action === "dispatch" &&
1619
- ctx.session?.exhaustedVerificationUnits?.has(`${action.unitType}:${action.unitId}`)) {
1674
+ dispatchCtx.session?.exhaustedVerificationUnits?.has(`${action.unitType}:${action.unitId}`)) {
1620
1675
  return {
1621
1676
  action: "stop",
1622
1677
  reason: `Unit ${action.unitId} exhausted verification retries this session.`,
@@ -1411,6 +1411,10 @@ export async function postUnitPreVerification(pctx, opts) {
1411
1411
  const blockingMismatch = mismatches.find((mismatch) => mismatch.severity === "error");
1412
1412
  if (blockingMismatch) {
1413
1413
  ctx.ui.notify(`Safety: task ${sTid} claimed passing verification that failed in recorded execution`, "error");
1414
+ const gitActionResult = await runCloseoutGitAction(pctx, s.currentUnit);
1415
+ if (gitActionResult === "dispatched") {
1416
+ return "dispatched";
1417
+ }
1414
1418
  await pauseAuto(ctx, pi);
1415
1419
  return "dispatched";
1416
1420
  }