@opengsd/gsd-pi 1.9.0 → 1.10.0-dev.a5e42e99

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 (502) hide show
  1. package/README.md +10 -9
  2. package/dist/headless.js +2 -1
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/GSD-WORKFLOW.md +2 -2
  5. package/dist/resources/extensions/gsd/artifact-verification.js +3 -4
  6. package/dist/resources/extensions/gsd/auto/loop.js +24 -4
  7. package/dist/resources/extensions/gsd/auto/run-unit.js +19 -1
  8. package/dist/resources/extensions/gsd/auto/unit-phase.js +37 -5
  9. package/dist/resources/extensions/gsd/auto-artifact-paths.js +14 -8
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +2 -0
  11. package/dist/resources/extensions/gsd/auto-model-selection.js +1 -0
  12. package/dist/resources/extensions/gsd/auto-prompts.js +102 -21
  13. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  14. package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -5
  15. package/dist/resources/extensions/gsd/auto-start.js +30 -10
  16. package/dist/resources/extensions/gsd/auto-tool-tracking.js +40 -0
  17. package/dist/resources/extensions/gsd/auto-verification.js +25 -12
  18. package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
  19. package/dist/resources/extensions/gsd/auto-worktree-sync.js +7 -3
  20. package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
  21. package/dist/resources/extensions/gsd/auto.js +15 -5
  22. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -0
  23. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -7
  24. package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
  25. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +7 -26
  26. package/dist/resources/extensions/gsd/commands-verdict.js +10 -9
  27. package/dist/resources/extensions/gsd/compat/compat-marker.js +80 -5
  28. package/dist/resources/extensions/gsd/constants.js +12 -13
  29. package/dist/resources/extensions/gsd/context-masker.js +97 -21
  30. package/dist/resources/extensions/gsd/db/engine.js +5 -2
  31. package/dist/resources/extensions/gsd/docs/preferences-reference.md +33 -2
  32. package/dist/resources/extensions/gsd/doctor-engine-checks.js +40 -12
  33. package/dist/resources/extensions/gsd/error-classifier.js +12 -2
  34. package/dist/resources/extensions/gsd/exec-sandbox.js +1 -0
  35. package/dist/resources/extensions/gsd/flat-phase-migration.js +12 -0
  36. package/dist/resources/extensions/gsd/git-service.js +19 -7
  37. package/dist/resources/extensions/gsd/gsd-db.js +75 -31
  38. package/dist/resources/extensions/gsd/guided-flow.js +11 -5
  39. package/dist/resources/extensions/gsd/markdown-renderer.js +5 -21
  40. package/dist/resources/extensions/gsd/md-importer.js +5 -6
  41. package/dist/resources/extensions/gsd/model-cost-table.js +6 -1
  42. package/dist/resources/extensions/gsd/model-router.js +16 -0
  43. package/dist/resources/extensions/gsd/paths.js +66 -15
  44. package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
  45. package/dist/resources/extensions/gsd/planning-subagent-registry.js +33 -0
  46. package/dist/resources/extensions/gsd/preferences-models.js +50 -10
  47. package/dist/resources/extensions/gsd/preferences-types.js +6 -0
  48. package/dist/resources/extensions/gsd/preferences-validation.js +86 -4
  49. package/dist/resources/extensions/gsd/preferences.js +24 -0
  50. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
  51. package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
  52. package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
  53. package/dist/resources/extensions/gsd/skill-activation.js +17 -3
  54. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +98 -2
  55. package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +4 -1
  56. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +5 -2
  57. package/dist/resources/extensions/gsd/stop-notice.js +9 -0
  58. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +8 -0
  59. package/dist/resources/extensions/gsd/tools/complete-task.js +12 -5
  60. package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -1
  61. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
  62. package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
  63. package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
  64. package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
  65. package/dist/resources/extensions/gsd/verification-evidence.js +5 -3
  66. package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
  67. package/dist/resources/extensions/gsd/workspace.js +2 -1
  68. package/dist/resources/extensions/gsd/worktree-state-projection.js +20 -18
  69. package/dist/resources/extensions/ollama/ollama-chat-provider.js +2 -2
  70. package/dist/resources/extensions/shared/interview-ui.js +43 -6
  71. package/dist/resources/extensions/subagent/index.js +1 -1
  72. package/dist/startup-model-validation.d.ts +1 -1
  73. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  74. package/dist/web/standalone/.next/BUILD_ID +1 -1
  75. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  76. package/dist/web/standalone/.next/build-manifest.json +3 -3
  77. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  78. package/dist/web/standalone/.next/required-server-files.json +3 -3
  79. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  80. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  82. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  90. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  92. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  93. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  94. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  96. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  106. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  118. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  140. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  150. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  156. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  170. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  172. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  176. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/index.html +1 -1
  186. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  187. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  188. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  189. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  190. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  191. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  192. package/dist/web/standalone/.next/server/app/page.js +2 -2
  193. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  194. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  195. package/dist/web/standalone/.next/server/chunks/1991.js +2 -2
  196. package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
  197. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  198. package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
  199. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  200. package/dist/web/standalone/.next/server/middleware.js +3 -3
  201. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  202. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  203. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  204. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
  205. package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
  206. package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
  207. package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
  208. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
  209. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  210. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  211. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  212. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  213. package/dist/web/standalone/server.js +1 -1
  214. package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
  215. package/integrations/hermes/pyproject.toml +1 -1
  216. package/package.json +8 -6
  217. package/packages/cloud-mcp-gateway/package.json +2 -2
  218. package/packages/contracts/dist/rpc.d.ts +1 -1
  219. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  220. package/packages/contracts/dist/rpc.js +1 -1
  221. package/packages/contracts/dist/rpc.js.map +1 -1
  222. package/packages/contracts/dist/rpc.test.js +1 -1
  223. package/packages/contracts/dist/rpc.test.js.map +1 -1
  224. package/packages/contracts/package.json +1 -1
  225. package/packages/daemon/package.json +4 -4
  226. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  227. package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
  228. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  229. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  230. package/packages/gsd-agent-core/dist/sdk.js +1 -0
  231. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  232. package/packages/gsd-agent-core/package.json +5 -5
  233. package/packages/gsd-agent-modes/dist/cli/args.js +2 -2
  234. package/packages/gsd-agent-modes/dist/cli/args.js.map +1 -1
  235. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  236. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +1 -0
  237. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  238. package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  239. package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.js +1 -0
  240. package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  241. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  242. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js +1 -0
  243. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  244. package/packages/gsd-agent-modes/package.json +7 -7
  245. package/packages/gsd-cloud/README.md +21 -5
  246. package/packages/gsd-cloud/dist/background-cli.test.d.ts +2 -0
  247. package/packages/gsd-cloud/dist/background-cli.test.d.ts.map +1 -0
  248. package/packages/gsd-cloud/dist/background-cli.test.js +325 -0
  249. package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -0
  250. package/packages/gsd-cloud/dist/cli.d.ts.map +1 -1
  251. package/packages/gsd-cloud/dist/cli.js +146 -16
  252. package/packages/gsd-cloud/dist/cli.js.map +1 -1
  253. package/packages/gsd-cloud/dist/cloud-config.d.ts +1 -1
  254. package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -1
  255. package/packages/gsd-cloud/dist/cloud-config.js +7 -1
  256. package/packages/gsd-cloud/dist/cloud-config.js.map +1 -1
  257. package/packages/gsd-cloud/dist/cloud-runtime.d.ts +7 -4
  258. package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -1
  259. package/packages/gsd-cloud/dist/cloud-runtime.js +115 -31
  260. package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -1
  261. package/packages/gsd-cloud/dist/cloud-runtime.test.js +224 -59
  262. package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -1
  263. package/packages/gsd-cloud/dist/runtime-artifacts.d.ts +3 -0
  264. package/packages/gsd-cloud/dist/runtime-artifacts.d.ts.map +1 -0
  265. package/packages/gsd-cloud/dist/runtime-artifacts.js +36 -0
  266. package/packages/gsd-cloud/dist/runtime-artifacts.js.map +1 -0
  267. package/packages/gsd-cloud/dist/runtime-process.d.ts +32 -0
  268. package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -0
  269. package/packages/gsd-cloud/dist/runtime-process.js +640 -0
  270. package/packages/gsd-cloud/dist/runtime-process.js.map +1 -0
  271. package/packages/gsd-cloud/dist/runtime-process.test.d.ts +2 -0
  272. package/packages/gsd-cloud/dist/runtime-process.test.d.ts.map +1 -0
  273. package/packages/gsd-cloud/dist/runtime-process.test.js +543 -0
  274. package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -0
  275. package/packages/gsd-cloud/dist/runtime-telemetry.d.ts +117 -0
  276. package/packages/gsd-cloud/dist/runtime-telemetry.d.ts.map +1 -0
  277. package/packages/gsd-cloud/dist/runtime-telemetry.js +291 -0
  278. package/packages/gsd-cloud/dist/runtime-telemetry.js.map +1 -0
  279. package/packages/gsd-cloud/dist/runtime-telemetry.test.d.ts +2 -0
  280. package/packages/gsd-cloud/dist/runtime-telemetry.test.d.ts.map +1 -0
  281. package/packages/gsd-cloud/dist/runtime-telemetry.test.js +434 -0
  282. package/packages/gsd-cloud/dist/runtime-telemetry.test.js.map +1 -0
  283. package/packages/gsd-cloud/package.json +2 -2
  284. package/packages/mcp-server/README.md +7 -2
  285. package/packages/mcp-server/dist/cli-runner.d.ts +3 -0
  286. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -1
  287. package/packages/mcp-server/dist/cli-runner.js +119 -33
  288. package/packages/mcp-server/dist/cli-runner.js.map +1 -1
  289. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  290. package/packages/mcp-server/dist/server.js +5 -5
  291. package/packages/mcp-server/dist/server.js.map +1 -1
  292. package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
  293. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  294. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  295. package/packages/mcp-server/package.json +4 -4
  296. package/packages/native/package.json +1 -1
  297. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  298. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  299. package/packages/pi-agent-core/dist/agent.js +2 -0
  300. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  301. package/packages/pi-agent-core/dist/types.d.ts +2 -2
  302. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  303. package/packages/pi-agent-core/dist/types.js.map +1 -1
  304. package/packages/pi-agent-core/package.json +1 -1
  305. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  306. package/packages/pi-ai/dist/models.generated.d.ts +187 -0
  307. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  308. package/packages/pi-ai/dist/models.generated.js +145 -0
  309. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  310. package/packages/pi-ai/dist/models.js +18 -6
  311. package/packages/pi-ai/dist/models.js.map +1 -1
  312. package/packages/pi-ai/dist/providers/amazon-bedrock.js +3 -2
  313. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  314. package/packages/pi-ai/dist/providers/anthropic.js +6 -1
  315. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  316. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts +1 -1
  317. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  318. package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  319. package/packages/pi-ai/dist/providers/google-vertex.js.map +1 -1
  320. package/packages/pi-ai/dist/providers/google.js.map +1 -1
  321. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts +1 -1
  322. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  323. package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
  324. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  325. package/packages/pi-ai/dist/providers/openai-completions.d.ts +1 -1
  326. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  327. package/packages/pi-ai/dist/providers/openai-completions.js +103 -0
  328. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  329. package/packages/pi-ai/dist/providers/openai-responses.d.ts +1 -1
  330. package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  331. package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
  332. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  333. package/packages/pi-ai/dist/providers/simple-options.d.ts +1 -1
  334. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  335. package/packages/pi-ai/dist/providers/simple-options.js +1 -1
  336. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  337. package/packages/pi-ai/dist/types.d.ts +9 -1
  338. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  339. package/packages/pi-ai/dist/types.js.map +1 -1
  340. package/packages/pi-ai/package.json +1 -1
  341. package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
  342. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  343. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  344. package/packages/pi-coding-agent/dist/core/model-registry.js +1 -0
  345. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  346. package/packages/pi-coding-agent/dist/core/model-resolver.js +2 -2
  347. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  348. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +14 -4
  349. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  350. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  351. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  352. package/packages/pi-coding-agent/dist/core/skills.d.ts +5 -0
  353. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  354. package/packages/pi-coding-agent/dist/core/skills.js +54 -0
  355. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  356. package/packages/pi-coding-agent/dist/theme/theme.d.ts +1 -1
  357. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  358. package/packages/pi-coding-agent/dist/theme/theme.js +1 -0
  359. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  360. package/packages/pi-coding-agent/package.json +7 -7
  361. package/packages/pi-tui/package.json +2 -2
  362. package/packages/rpc-client/package.json +2 -2
  363. package/pkg/dist/theme/theme.d.ts +1 -1
  364. package/pkg/dist/theme/theme.d.ts.map +1 -1
  365. package/pkg/dist/theme/theme.js +1 -0
  366. package/pkg/dist/theme/theme.js.map +1 -1
  367. package/pkg/package.json +1 -1
  368. package/src/resources/GSD-WORKFLOW.md +2 -2
  369. package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
  370. package/src/resources/extensions/gsd/auto/loop.ts +48 -4
  371. package/src/resources/extensions/gsd/auto/run-unit.ts +20 -1
  372. package/src/resources/extensions/gsd/auto/unit-phase.ts +41 -5
  373. package/src/resources/extensions/gsd/auto-artifact-paths.ts +14 -7
  374. package/src/resources/extensions/gsd/auto-dispatch.ts +1 -0
  375. package/src/resources/extensions/gsd/auto-model-selection.ts +1 -0
  376. package/src/resources/extensions/gsd/auto-prompts.ts +118 -19
  377. package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
  378. package/src/resources/extensions/gsd/auto-runtime-state.ts +12 -7
  379. package/src/resources/extensions/gsd/auto-start.ts +32 -9
  380. package/src/resources/extensions/gsd/auto-tool-tracking.ts +56 -0
  381. package/src/resources/extensions/gsd/auto-verification.ts +46 -12
  382. package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
  383. package/src/resources/extensions/gsd/auto-worktree-sync.ts +10 -3
  384. package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
  385. package/src/resources/extensions/gsd/auto.ts +20 -7
  386. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +1 -0
  387. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +41 -12
  388. package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
  389. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +10 -31
  390. package/src/resources/extensions/gsd/commands-verdict.ts +16 -9
  391. package/src/resources/extensions/gsd/compat/compat-marker.ts +99 -5
  392. package/src/resources/extensions/gsd/constants.ts +14 -13
  393. package/src/resources/extensions/gsd/context-masker.ts +98 -2
  394. package/src/resources/extensions/gsd/db/engine.ts +5 -2
  395. package/src/resources/extensions/gsd/docs/preferences-reference.md +33 -2
  396. package/src/resources/extensions/gsd/doctor-engine-checks.ts +45 -11
  397. package/src/resources/extensions/gsd/error-classifier.ts +13 -2
  398. package/src/resources/extensions/gsd/exec-sandbox.ts +1 -0
  399. package/src/resources/extensions/gsd/flat-phase-migration.ts +14 -0
  400. package/src/resources/extensions/gsd/git-service.ts +19 -6
  401. package/src/resources/extensions/gsd/gsd-db.ts +85 -33
  402. package/src/resources/extensions/gsd/guided-flow.ts +11 -4
  403. package/src/resources/extensions/gsd/markdown-renderer.ts +5 -23
  404. package/src/resources/extensions/gsd/md-importer.ts +5 -5
  405. package/src/resources/extensions/gsd/model-cost-table.ts +14 -1
  406. package/src/resources/extensions/gsd/model-router.ts +17 -0
  407. package/src/resources/extensions/gsd/paths.ts +73 -15
  408. package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
  409. package/src/resources/extensions/gsd/planning-subagent-registry.ts +45 -0
  410. package/src/resources/extensions/gsd/preferences-models.ts +54 -10
  411. package/src/resources/extensions/gsd/preferences-types.ts +26 -2
  412. package/src/resources/extensions/gsd/preferences-validation.ts +108 -3
  413. package/src/resources/extensions/gsd/preferences.ts +38 -0
  414. package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
  415. package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
  416. package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
  417. package/src/resources/extensions/gsd/skill-activation.ts +17 -3
  418. package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +132 -2
  419. package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +4 -1
  420. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +4 -2
  421. package/src/resources/extensions/gsd/stop-notice.ts +11 -0
  422. package/src/resources/extensions/gsd/templates/PREFERENCES.md +8 -0
  423. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
  424. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +264 -0
  425. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
  426. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +21 -1
  427. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +74 -1
  428. package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
  429. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +10 -0
  430. package/src/resources/extensions/gsd/tests/compat-marker.test.ts +25 -0
  431. package/src/resources/extensions/gsd/tests/complete-task.test.ts +76 -1
  432. package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
  433. package/src/resources/extensions/gsd/tests/db-engine-cjs-compat.test.ts +12 -0
  434. package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
  435. package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
  436. package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
  437. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +147 -0
  438. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +33 -1
  439. package/src/resources/extensions/gsd/tests/external-markdown-edit.test.ts +38 -1
  440. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +8 -9
  441. package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +20 -1
  442. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +32 -0
  443. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +22 -0
  444. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +13 -0
  445. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
  446. package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
  447. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
  448. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +23 -0
  449. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +55 -0
  450. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  451. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
  452. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +24 -0
  453. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +38 -1
  454. package/src/resources/extensions/gsd/tests/preferences.test.ts +151 -0
  455. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +7 -0
  456. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +87 -0
  457. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +121 -1
  458. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
  459. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +105 -0
  460. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  461. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
  462. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
  463. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +52 -0
  464. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +21 -1
  465. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
  466. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +14 -0
  467. package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +1 -1
  468. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  469. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
  470. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +39 -0
  471. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +7 -0
  472. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +12 -0
  473. package/src/resources/extensions/gsd/tests/workflow-authority-faults.test.ts +238 -0
  474. package/src/resources/extensions/gsd/tests/workflow-authority-fixture.test.ts +48 -0
  475. package/src/resources/extensions/gsd/tests/workflow-authority-fixture.ts +141 -0
  476. package/src/resources/extensions/gsd/tests/workflow-authority-projection-conflict.test.ts +177 -0
  477. package/src/resources/extensions/gsd/tests/workflow-fault-harness.test.ts +39 -0
  478. package/src/resources/extensions/gsd/tests/workflow-fault-harness.ts +72 -0
  479. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
  480. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +2 -2
  481. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +60 -0
  482. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +74 -0
  483. package/src/resources/extensions/gsd/tools/complete-task.ts +20 -5
  484. package/src/resources/extensions/gsd/tools/plan-slice.ts +5 -1
  485. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
  486. package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
  487. package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
  488. package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
  489. package/src/resources/extensions/gsd/verification-evidence.ts +5 -2
  490. package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
  491. package/src/resources/extensions/gsd/workspace.ts +2 -1
  492. package/src/resources/extensions/gsd/worktree-state-projection.ts +21 -24
  493. package/src/resources/extensions/ollama/ollama-chat-provider.ts +2 -2
  494. package/src/resources/extensions/ollama/tests/ollama-chat-provider-think.test.ts +4 -0
  495. package/src/resources/extensions/shared/interview-ui.ts +47 -8
  496. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +29 -0
  497. package/src/resources/extensions/subagent/index.ts +1 -1
  498. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
  499. package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
  500. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
  501. /package/dist/web/standalone/.next/static/{BE5XoklToI6lZjRzpXih8 → xwUaOqui04jIIFVsIBLiL}/_buildManifest.js +0 -0
  502. /package/dist/web/standalone/.next/static/{BE5XoklToI6lZjRzpXih8 → xwUaOqui04jIIFVsIBLiL}/_ssgManifest.js +0 -0
@@ -56,6 +56,26 @@ const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE =
56
56
  /^(?:api error(?::|$|\s*\()|provider error(?::|$|\s*\()|request failed\b|(?:http\s*)?(?:429|500|502|503)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|socket hang up\b|fetch failed\b|(?:network|connection|server) error(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|dns\b.*(?:fail|error|timeout)|unexpected eof\b|stream idle timeout\b|partial response received\b|stream_exhausted\b|terminated(?::|$)|(?:connection|stream|request)\b.{0,40}\bterminated\b|other side closed\b|rate.?limit(?:ed| exceeded| reached| error)|too many requests\b|you(?:'ve| have) (?:hit|reached) your (?:\w+ )?limit\b|.*\b(?:usage|session|weekly|daily|monthly|quota) limit\b|limit\b.{0,40}\bresets?\b|out of extra usage\b|service.?unavailable\b|internal(?: server)? error(?::|$)|internal(?:[_-]server)?[_-]error\b|server[_-]error\b|(?:provider|server|api|model|codex|claude|openai|anthropic|gemini)\b.{0,80}\boverloaded\b|overloaded\b.{0,80}\b(?:provider|server|api|model)\b|context (?:window|length) exceed|context window exceed)/i;
57
57
  const ZERO_TOOL_PROVIDER_ERROR_SIGNAL_RE =
58
58
  /(?:\b(?:http|status(?: code)?|code|error:)\s*(?:429|500|502|503)\b|\b(?:api|provider) error\s*[:(]?\s*(?:429|500|502|503)\b|\b(?:typeerror|error):\s*(?:fetch failed\b|socket hang up\b|terminated(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|(?:network|connection|server) error(?::|$)|stream idle timeout\b|partial response received\b|unexpected eof\b)|\b(?:server_error|api_error|stream_exhausted(?:_without_result)?)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|context (?:window|length) exceed|context window exceed)/i;
59
+ const ZERO_TOOL_PSEUDO_TOOL_CALL_RE =
60
+ /<arg_key>[\s\S]*?<\/arg_key>\s*<arg_value>[\s\S]*?<\/arg_value>[\s\S]*?<\/tool_call>/i;
61
+ const ZERO_TOOL_PSEUDO_TOOL_CALL_SNIPPET_CHARS = 200;
62
+
63
+ function zeroToolMessageSnippet(message: string): string {
64
+ const compact = message.trim().replace(/\s+/g, " ");
65
+ if (compact.length <= ZERO_TOOL_PSEUDO_TOOL_CALL_SNIPPET_CHARS) return compact;
66
+ return `${compact.slice(0, ZERO_TOOL_PSEUDO_TOOL_CALL_SNIPPET_CHARS - 3)}...`;
67
+ }
68
+
69
+ // Provider serialization drift: the model emitted a tool call as plain assistant
70
+ // text (`toolName<arg_key>…</arg_key><arg_value>…</arg_value></tool_call>`)
71
+ // instead of a structured tool call. Returns an operator-visible snippet when
72
+ // detected. Kept separate from error classification so a drift snippet is never
73
+ // conflated with an ErrorClass (which would force a fragile union whose
74
+ // narrowing the root and extensions tsconfigs disagree on).
75
+ function zeroToolPseudoToolCallSnippet(message: string): string | null {
76
+ if (!ZERO_TOOL_PSEUDO_TOOL_CALL_RE.test(message)) return null;
77
+ return zeroToolMessageSnippet(message);
78
+ }
59
79
 
60
80
  function classifyZeroToolProviderMessage(message: string): ReturnType<typeof classifyError> | null {
61
81
  const firstLine = message.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
@@ -68,6 +88,7 @@ function classifyZeroToolProviderMessage(message: string): ReturnType<typeof cla
68
88
  }
69
89
 
70
90
  export const _classifyZeroToolProviderMessageForTest = classifyZeroToolProviderMessage;
91
+ export const _zeroToolPseudoToolCallSnippetForTest = zeroToolPseudoToolCallSnippet;
71
92
 
72
93
  export function resolveDispatchRecoveryAttempts(
73
94
  unitRecoveryCount: Map<string, number>,
@@ -767,15 +788,30 @@ export async function runUnitPhase(
767
788
  );
768
789
  if (lastUnit && lastUnit.toolCalls === 0) {
769
790
  const lastAssistantMessage = lastAssistantText(s.lastUnitAgentEndMessages);
770
- const providerMessageClass = classifyZeroToolProviderMessage(lastAssistantMessage);
771
- if (providerMessageClass && isTransient(providerMessageClass)) {
772
- const retryAfterMs = "retryAfterMs" in providerMessageClass ? providerMessageClass.retryAfterMs : 15_000;
791
+ const pseudoToolCallSnippet = zeroToolPseudoToolCallSnippet(lastAssistantMessage);
792
+ if (pseudoToolCallSnippet) {
793
+ debugLog("runUnitPhase", {
794
+ phase: "zero-tool-serialization-drift",
795
+ unitType,
796
+ unitId,
797
+ snippet: pseudoToolCallSnippet,
798
+ });
799
+ ctx.ui.notify(
800
+ `${unitType} ${unitId} completed with 0 tool calls - provider serialization drift: model emitted pseudo-tool-call text. Snippet: ${pseudoToolCallSnippet}`,
801
+ "error",
802
+ );
803
+ await deps.pauseAuto(ctx, pi);
804
+ return { action: "break", reason: "zero-tool-serialization-drift" };
805
+ }
806
+ const providerErrorClass = classifyZeroToolProviderMessage(lastAssistantMessage);
807
+ if (providerErrorClass && isTransient(providerErrorClass)) {
808
+ const retryAfterMs = "retryAfterMs" in providerErrorClass ? providerErrorClass.retryAfterMs : 15_000;
773
809
  await pauseAutoForProviderError(
774
810
  ctx.ui,
775
811
  ` for ${unitType} ${unitId}`,
776
812
  () => deps.pauseAuto(ctx, pi),
777
813
  {
778
- isRateLimit: providerMessageClass.kind === "rate-limit",
814
+ isRateLimit: providerErrorClass.kind === "rate-limit",
779
815
  isTransient: true,
780
816
  retryAfterMs,
781
817
  resume: () => {
@@ -793,7 +829,7 @@ export async function runUnitPhase(
793
829
  });
794
830
  return {
795
831
  action: "break",
796
- reason: providerMessageClass.kind === "rate-limit" ? "rate-limit" : "api-timeout",
832
+ reason: providerErrorClass.kind === "rate-limit" ? "rate-limit" : "api-timeout",
797
833
  };
798
834
  }
799
835
  if (USER_DRIVEN_DEEP_UNITS.has(unitType) && isAwaitingUserInput(s.lastUnitAgentEndMessages ?? undefined)) {
@@ -15,6 +15,7 @@ import {
15
15
  resolveSliceFile,
16
16
  relMilestoneFile,
17
17
  relSliceFile,
18
+ buildFlatTaskFileName,
18
19
  buildTaskFileName,
19
20
  resolveSlicePath,
20
21
  resolveTasksDir,
@@ -103,12 +104,15 @@ function resolveProjectMilestonePath(base: string, mid: string): string | null {
103
104
  const milestonesDir = join(gsdRoot(base), "milestones");
104
105
  const dir = resolveDir(milestonesDir, mid);
105
106
  if (!dir) return null;
106
- // git-service.ts creates milestones/<MID>/ for integration-branch metadata
107
- // (<MID>-META.json) even in flat-phase projects. A dir that holds ONLY
108
- // *-META.json files must not be treated as a real legacy milestone dir
109
- // otherwise this early-return resolves CONTEXT/ROADMAP/SUMMARY to the legacy
110
- // path (milestones/<MID>/<MID>-<SUFFIX>.md) before the flat-phase fallback
111
- // can run, trapping the unit in a finalize-retry loop (#852 follow-up).
107
+ // Historically git-service.ts wrote integration-branch metadata into
108
+ // milestones/<MID>/<MID>-META.json, which could create that dir in flat-phase
109
+ // projects and poison layout detection. As of ADR-045 that META lives flat at
110
+ // .gsd/<MID>-META.json and no longer poisons detection. A dir that holds ONLY
111
+ // *-META.json files (a pre-migration on-disk tree) must still not be treated
112
+ // as a real legacy milestone dir otherwise this early-return resolves
113
+ // CONTEXT/ROADMAP/SUMMARY to the legacy path (milestones/<MID>/<MID>-<SUFFIX>.md)
114
+ // before the flat-phase fallback can run, trapping the unit in a
115
+ // finalize-retry loop (#852 follow-up).
112
116
  //
113
117
  // We use dirIsMetaOnlyLegacyMilestone rather than !dirIsContentBearingLegacyMilestone
114
118
  // so that an EMPTY dir (a new milestone before any content is written) is NOT
@@ -232,7 +236,10 @@ export function resolveExpectedArtifactPath(
232
236
  const summaryDir = isLegacySlice
233
237
  ? (resolveTasksDir(base, mid, sid!) ?? slicePath)
234
238
  : slicePath;
235
- return join(summaryDir, buildTaskFileName(tid, "SUMMARY"));
239
+ const fileName = isLegacySlice
240
+ ? buildTaskFileName(tid, "SUMMARY")
241
+ : buildFlatTaskFileName(sid!, tid, "SUMMARY");
242
+ return join(summaryDir, fileName);
236
243
  }
237
244
  case "complete-slice": {
238
245
  return resolveSliceArtifactPath(base, mid, sid!, "SUMMARY");
@@ -1956,6 +1956,7 @@ function applyLanguageDirectiveToDispatch(
1956
1956
  if (action.action !== "dispatch" || !action.prompt) return action;
1957
1957
  const directive = renderLanguageDirectiveForPrompt(prefs);
1958
1958
  if (!directive) return action;
1959
+ if (action.prompt.startsWith(directive)) return action;
1959
1960
  return { ...action, prompt: `${directive}\n\n${action.prompt}` };
1960
1961
  }
1961
1962
 
@@ -390,6 +390,7 @@ const THINKING_LEVEL_ORDER: readonly EffectiveThinkingLevel[] = [
390
390
  "medium",
391
391
  "high",
392
392
  "xhigh",
393
+ "max",
393
394
  ] as EffectiveThinkingLevel[];
394
395
 
395
396
  /**
@@ -16,10 +16,11 @@ import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
16
16
  import {
17
17
  resolveMilestoneFile, resolveSliceFile, resolveSlicePath,
18
18
  resolveTasksDir, resolveTaskFiles, resolveTaskFile,
19
+ taskIdFromTaskFileName,
19
20
  relMilestoneFile, relSliceFile, relSlicePath, relMilestonePath,
20
21
  relTaskFile, resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile,
21
22
  } from "./paths.js";
22
- import { resolveInlineLevel, loadEffectiveGSDPreferences } from "./preferences.js";
23
+ import { resolveInlineLevel, loadEffectiveGSDPreferences, renderLanguageDirectiveForPrompt } from "./preferences.js";
23
24
  import { createRepositoryRegistryFromPreferences } from "./repository-registry.js";
24
25
  import { isContextModeEnabled } from "./preferences-types.js";
25
26
  import { parseRoadmap } from "./parsers-legacy.js";
@@ -28,6 +29,7 @@ import type { GSDPreferences } from "./preferences.js";
28
29
  import { join, basename, relative, sep } from "node:path";
29
30
  import { existsSync } from "node:fs";
30
31
  import { computeBudgets, resolveExecutorContextWindow, truncateAtSectionBoundary, type MinimalModelRegistry } from "./context-budget.js";
32
+ import type { TokenProvider } from "./token-counter.js";
31
33
  import { getBlockingReworkFindingsForTask, getGateResults, getPendingGates, getPendingGatesForTurn } from "./gsd-db.js";
32
34
  import {
33
35
  GATE_REGISTRY,
@@ -76,6 +78,14 @@ export { buildSkillActivationBlock, buildSkillDiscoveryVars };
76
78
  */
77
79
  const MAX_PREAMBLE_CHARS = 20_000;
78
80
 
81
+ function prependLanguageDirectiveForBase(base: string, prompt: string): string {
82
+ const directive = renderLanguageDirectiveForPrompt(
83
+ loadEffectiveGSDPreferences(base)?.preferences,
84
+ );
85
+ if (!directive || prompt.startsWith(directive)) return prompt;
86
+ return `${directive}\n\n${prompt}`;
87
+ }
88
+
79
89
  /**
80
90
  * Resolve prompt budgets from the configured executor context window.
81
91
  *
@@ -91,13 +101,29 @@ function resolvePromptBudgets(): ReturnType<typeof computeBudgets> {
91
101
  const prefs = loadEffectiveGSDPreferences();
92
102
  const sessionWindow = prefs?.preferences.context_window_override;
93
103
  const windowTokens = resolveExecutorContextWindow(undefined, prefs?.preferences, sessionWindow);
94
- return computeBudgets(windowTokens);
104
+ return computeBudgets(windowTokens, resolveExecutionProvider(prefs?.preferences));
95
105
  } catch (e) {
96
106
  logWarning("prompt", `resolvePromptBudgets failed: ${(e as Error).message}`);
97
107
  return computeBudgets(200_000);
98
108
  }
99
109
  }
100
110
 
111
+ /**
112
+ * Best-effort provider for the chars/token ratio: the executor's configured
113
+ * model profile is the only provider source reachable here (the runtime
114
+ * `sessionProvider` that reaches `formatExecutorConstraints` isn't threaded to
115
+ * `capPreamble`/summary callers). Undefined when no explicit provider is set —
116
+ * `computeBudgets` then uses the 4.0 default, i.e. today's behavior.
117
+ */
118
+ function resolveExecutionProvider(prefs?: { models?: { execution?: unknown } }): TokenProvider | undefined {
119
+ const exec = prefs?.models?.execution;
120
+ if (exec && typeof exec === "object" && "provider" in exec) {
121
+ const provider = (exec as { provider?: unknown }).provider;
122
+ if (typeof provider === "string" && provider) return provider as TokenProvider;
123
+ }
124
+ return undefined;
125
+ }
126
+
101
127
  /**
102
128
  * Character budget for dependency/prior slice summaries injected into dispatch
103
129
  * prompts. Scales with the executor's configured context window (issue #4435).
@@ -236,7 +262,7 @@ function formatCloseoutReviewInstructions(validationContent: string | null, vali
236
262
  ].join("\n");
237
263
  }
238
264
 
239
- function capPreamble(preamble: string): string {
265
+ export function capPreamble(preamble: string): string {
240
266
  // Cap inlined context at min(static ceiling, scaled inline budget).
241
267
  // The ceiling bounds repeated auto prompt payloads; the scaled
242
268
  // budget tightens the cap for small-window users whose true safe limit is
@@ -246,6 +272,41 @@ function capPreamble(preamble: string): string {
246
272
  return truncateAtSectionBoundary(preamble, budget).content;
247
273
  }
248
274
 
275
+ /**
276
+ * Cap the execute-task inline blocks against one shared budget in priority
277
+ * order. Unlike `capPreamble` (single concatenated preamble), execute-task
278
+ * feeds these blocks into separate, non-contiguous template placeholders, so
279
+ * they can't be joined and re-split — the budget is spent block-by-block.
280
+ *
281
+ * The task plan is the authoritative execution contract: it is never truncated
282
+ * here (it consumes budget first, whole). Remaining budget flows to the slice
283
+ * excerpt, then templates, each truncated at section boundaries so the lowest-
284
+ * priority context drops whole trailing sections first. When the task plan
285
+ * alone meets or exceeds the budget, the trailing blocks are dropped rather
286
+ * than the task plan being cut.
287
+ */
288
+ function capExecuteTaskInlineBlocks(
289
+ taskPlan: string,
290
+ slicePlan: string,
291
+ templates: string,
292
+ budgetChars: number,
293
+ ): { taskPlan: string; slicePlan: string; templates: string } {
294
+ let remaining = budgetChars - taskPlan.length;
295
+ if (remaining <= 0) {
296
+ return { taskPlan, slicePlan: "", templates: "" };
297
+ }
298
+ const cappedSlice = slicePlan.length <= remaining
299
+ ? slicePlan
300
+ : truncateAtSectionBoundary(slicePlan, remaining).content;
301
+ remaining -= cappedSlice.length;
302
+ const cappedTemplates = remaining <= 0
303
+ ? ""
304
+ : templates.length <= remaining
305
+ ? templates
306
+ : truncateAtSectionBoundary(templates, remaining).content;
307
+ return { taskPlan, slicePlan: cappedSlice, templates: cappedTemplates };
308
+ }
309
+
249
310
  type PromptContextMode = "inline" | "excerpt" | "on-demand" | "skipped";
250
311
 
251
312
  interface PromptContextTelemetryEntry {
@@ -324,7 +385,7 @@ function prependContextModeToBlock(
324
385
  block: string,
325
386
  renderMode: ContextModeRenderMode = "standalone",
326
387
  ): string {
327
- const toolSurface = composeToolSurfaceInstructions(unitType, { renderMode });
388
+ const toolSurface = composeToolSurfaceInstructions(unitType, { renderMode, basePath: base });
328
389
  const contextMode = renderContextModeBlockForPrompt(unitType, base, renderMode);
329
390
  const guidance = [toolSurface, contextMode].filter(Boolean).join("\n\n");
330
391
  if (!guidance) return block;
@@ -405,7 +466,7 @@ function formatExecutorConstraints(
405
466
  // so DEFAULT_CONTEXT_WINDOW stays the single source of truth.
406
467
  windowTokens = resolveExecutorContextWindow(undefined, undefined, sessionContextWindow, sessionProvider);
407
468
  }
408
- const budgets = computeBudgets(windowTokens);
469
+ const budgets = computeBudgets(windowTokens, sessionProvider as TokenProvider | undefined);
409
470
  const { min, max } = budgets.taskCountRange;
410
471
  const execWindowK = Math.round(windowTokens / 1000);
411
472
  const perTaskBudgetK = Math.round(budgets.inlineContextBudgetChars / 1000);
@@ -1431,6 +1492,18 @@ function resolveTaskSummariesLocation(
1431
1492
  return { dir: slicePath, relPrefix: sRel };
1432
1493
  }
1433
1494
 
1495
+ function summaryFileBelongsToSlice(
1496
+ fileName: string,
1497
+ base: string,
1498
+ mid: string,
1499
+ sid: string,
1500
+ ): boolean {
1501
+ const tid = taskIdFromTaskFileName(fileName, "SUMMARY");
1502
+ if (!tid) return false;
1503
+ const resolved = resolveTaskFile(base, mid, sid, tid, "SUMMARY");
1504
+ return resolved !== null && basename(resolved) === fileName;
1505
+ }
1506
+
1434
1507
  export async function getPriorTaskSummaryPaths(
1435
1508
  mid: string, sid: string, currentTid: string, base: string,
1436
1509
  ): Promise<string[]> {
@@ -1442,7 +1515,10 @@ export async function getPriorTaskSummaryPaths(
1442
1515
 
1443
1516
  return summaryFiles
1444
1517
  .filter(f => {
1445
- const num = parseInt(f.replace(/^T/, ""), 10);
1518
+ if (!summaryFileBelongsToSlice(f, base, mid, sid)) return false;
1519
+ const tid = taskIdFromTaskFileName(f, "SUMMARY");
1520
+ if (!tid) return false;
1521
+ const num = parseInt(tid.replace(/^T/, ""), 10);
1446
1522
  return num < currentNum;
1447
1523
  })
1448
1524
  .map(f => `${loc.relPrefix}/${f}`);
@@ -1475,8 +1551,9 @@ export async function getDependencyTaskSummaryPaths(
1475
1551
 
1476
1552
  return summaryFiles
1477
1553
  .filter((f) => {
1478
- // Extract task ID from filename: "T02-SUMMARY.md" → "T02"
1479
- const tid = f.replace(/-SUMMARY\.md$/i, "").toUpperCase();
1554
+ if (!summaryFileBelongsToSlice(f, base, mid, sid)) return false;
1555
+ const tid = taskIdFromTaskFileName(f, "SUMMARY");
1556
+ if (!tid) return false;
1480
1557
  return depSet.has(tid);
1481
1558
  })
1482
1559
  .map((f) => `${loc.relPrefix}/${f}`);
@@ -1661,7 +1738,7 @@ export async function buildDiscussMilestonePrompt(
1661
1738
  if (headless) {
1662
1739
  const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
1663
1740
  const roadmapContent = roadmapPath ? await loadFile(roadmapPath) : null;
1664
- return loadPrompt("discuss-headless", {
1741
+ const prompt = loadPrompt("discuss-headless", {
1665
1742
  seedContext: roadmapContent ?? "",
1666
1743
  inlinedTemplates: contextTemplate,
1667
1744
  workingDirectory: base,
@@ -1670,6 +1747,7 @@ export async function buildDiscussMilestonePrompt(
1670
1747
  commitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
1671
1748
  multiMilestoneCommitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
1672
1749
  });
1750
+ return prependLanguageDirectiveForBase(base, prompt);
1673
1751
  }
1674
1752
 
1675
1753
  const rawInlinedContext = await buildDiscussMilestoneInlinedContext(mid, base);
@@ -1700,10 +1778,11 @@ export async function buildDiscussMilestonePrompt(
1700
1778
  const truncationNote = cappedDraftSeed !== draftSeed
1701
1779
  ? `\n\n_(Draft seed truncated; read the full draft at \`${draftRelPath}\` if needed.)_`
1702
1780
  : "";
1703
- return `${promptWithContextMode}\n\n## Prior Discussion (Draft Seed)\n\nThe following draft was captured from a prior multi-milestone discussion. Use it as seed material — the user has already provided this context. Start with a brief reflection on what the draft covers, then probe for any gaps or open questions before writing the full CONTEXT.md.\n\n${cappedDraftSeed}${truncationNote}`;
1781
+ const promptWithDraftSeed = `${promptWithContextMode}\n\n## Prior Discussion (Draft Seed)\n\nThe following draft was captured from a prior multi-milestone discussion. Use it as seed material — the user has already provided this context. Start with a brief reflection on what the draft covers, then probe for any gaps or open questions before writing the full CONTEXT.md.\n\n${cappedDraftSeed}${truncationNote}`;
1782
+ return prependLanguageDirectiveForBase(base, promptWithDraftSeed);
1704
1783
  }
1705
1784
 
1706
- return promptWithContextMode;
1785
+ return prependLanguageDirectiveForBase(base, promptWithContextMode);
1707
1786
  }
1708
1787
 
1709
1788
  /**
@@ -2725,7 +2804,7 @@ export async function buildExecuteTaskPrompt(
2725
2804
  // Compute verification budget for the executor's context window (issue #707)
2726
2805
  const prefs = loadEffectiveGSDPreferences();
2727
2806
  const contextWindow = resolveExecutorContextWindow(opts.modelRegistry, prefs?.preferences, opts.sessionContextWindow, opts.sessionProvider);
2728
- const budgets = computeBudgets(contextWindow);
2807
+ const budgets = computeBudgets(contextWindow, opts.sessionProvider as TokenProvider | undefined);
2729
2808
  const verificationBudget = `~${Math.round(budgets.verificationBudgetChars / 1000)}K chars`;
2730
2809
 
2731
2810
  // Truncate carry-forward section when it exceeds 40% of inline context budget.
@@ -2842,10 +2921,26 @@ export async function buildExecuteTaskPrompt(
2842
2921
  }
2843
2922
  },
2844
2923
  });
2845
- const taskPlanInline = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "task-plan");
2846
- const slicePlanExcerpt = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "slice-plan");
2924
+ const rawTaskPlanInline = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "task-plan");
2925
+ const rawSlicePlanExcerpt = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "slice-plan");
2847
2926
  const contractedCarryForward = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "prior-task-summaries");
2848
- const contractedTemplates = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "templates");
2927
+ const rawContractedTemplates = requireComposedArtifactBlock(contractedContext.blocks, "execute-task", "templates");
2928
+ // Cap the static inline blocks against one shared budget so a small-window
2929
+ // executor can't overflow (the sibling builders cap via `capPreamble`;
2930
+ // execute-task's blocks feed separate template slots, so they share a budget
2931
+ // block-by-block). Carry-forward already has its own truncation above.
2932
+ const inlineBudget = Math.min(MAX_PREAMBLE_CHARS, budgets.inlineContextBudgetChars);
2933
+ const { taskPlan: taskPlanInline, slicePlan: slicePlanExcerpt, templates: contractedTemplates } =
2934
+ capExecuteTaskInlineBlocks(rawTaskPlanInline, rawSlicePlanExcerpt, rawContractedTemplates, inlineBudget);
2935
+ const inlineDropped = (rawTaskPlanInline.length + rawSlicePlanExcerpt.length + rawContractedTemplates.length)
2936
+ - (taskPlanInline.length + slicePlanExcerpt.length + contractedTemplates.length);
2937
+ trackPromptContext(
2938
+ contextTelemetry,
2939
+ "inline-cap",
2940
+ inlineDropped > 0 ? "excerpt" : "skipped",
2941
+ null,
2942
+ inlineDropped > 0 ? `dropped ${inlineDropped} chars (budget ${inlineBudget})` : "within budget",
2943
+ );
2849
2944
  const onDemandResult = renderExecuteTaskOnDemandContext(base, mid, sid, contractedContext.onDemand);
2850
2945
  const onDemandContext = onDemandResult.text;
2851
2946
  trackPromptContext(
@@ -2941,12 +3036,14 @@ export async function buildCompleteSlicePrompt(
2941
3036
  trackPromptContext(contextTelemetry, "prior-task-summaries", "skipped", null, "missing tasks dir");
2942
3037
  return null;
2943
3038
  }
2944
- const summaryFiles = resolveTaskFiles(loc.dir, "SUMMARY").sort();
3039
+ const summaryFiles = resolveTaskFiles(loc.dir, "SUMMARY")
3040
+ .filter((file) => summaryFileBelongsToSlice(file, base, mid, sid))
3041
+ .sort();
2945
3042
  const blocks: string[] = [];
2946
3043
  for (const file of summaryFiles) {
2947
3044
  const absPath = join(loc.dir, file);
2948
3045
  const relPath = `${loc.relPrefix}/${file}`;
2949
- const taskId = file.replace(/-SUMMARY\.md$/i, "");
3046
+ const taskId = taskIdFromTaskFileName(file, "SUMMARY") ?? file.replace(/-SUMMARY\.md$/i, "");
2950
3047
  blocks.push(await buildTaskSummaryExcerpt(absPath, relPath, taskId));
2951
3048
  }
2952
3049
  const body = blocks.length > 0 ? blocks.join("\n\n---\n\n") : null;
@@ -3559,7 +3656,9 @@ export async function buildReplanSlicePrompt(
3559
3656
  let blockerTaskId = "";
3560
3657
  const summaryLoc = resolveTaskSummariesLocation(base, mid, sid);
3561
3658
  if (summaryLoc) {
3562
- const summaryFiles = resolveTaskFiles(summaryLoc.dir, "SUMMARY").sort();
3659
+ const summaryFiles = resolveTaskFiles(summaryLoc.dir, "SUMMARY")
3660
+ .filter((file) => summaryFileBelongsToSlice(file, base, mid, sid))
3661
+ .sort();
3563
3662
  for (const file of summaryFiles) {
3564
3663
  const absPath = join(summaryLoc.dir, file);
3565
3664
  const content = await loadFile(absPath);
@@ -3567,7 +3666,7 @@ export async function buildReplanSlicePrompt(
3567
3666
  const summary = parseSummary(content);
3568
3667
  const relPath = `${summaryLoc.relPrefix}/${file}`;
3569
3668
  if (summary.frontmatter.blocker_discovered) {
3570
- blockerTaskId = summary.frontmatter.id || file.replace(/-SUMMARY\.md$/i, "");
3669
+ blockerTaskId = summary.frontmatter.id || taskIdFromTaskFileName(file, "SUMMARY") || file.replace(/-SUMMARY\.md$/i, "");
3571
3670
  inlined.push(await buildTaskSummaryExcerpt(absPath, relPath, blockerTaskId, { blocker: true }));
3572
3671
  }
3573
3672
  }
@@ -39,8 +39,7 @@ import { isClosedStatus, isInactiveStatus } from "./status-guards.js";
39
39
  import {
40
40
  resolveSlicePath,
41
41
  resolveSliceFile,
42
- resolveTasksDir,
43
- resolveTaskFiles,
42
+ resolveTaskFile,
44
43
  relMilestoneFile,
45
44
  relSliceFile,
46
45
  buildSliceFileName,
@@ -324,13 +323,16 @@ export function writeReactiveExecuteBlocker(
324
323
  const slicePath = resolveSlicePath(base, mid, sid);
325
324
  if (!slicePath) return null;
326
325
 
327
- const tasksDir = resolveTasksDir(base, mid, sid) ?? slicePath;
328
- const existingSummaries = new Set(
329
- resolveTaskFiles(tasksDir, "SUMMARY").map((f) => f.replace(/-SUMMARY\.md$/i, "").toUpperCase()),
330
- );
326
+ // Resolve each batch task's SUMMARY with slice-qualified paths so flat-phase
327
+ // slices that reuse a task id (e.g. two T03s in one phase) don't collide: a
328
+ // sibling slice's summary must never make this slice's task look complete.
329
+ const hasSummary = (tid: string): boolean => {
330
+ const summaryPath = resolveTaskFile(base, mid, sid, tid, "SUMMARY");
331
+ return summaryPath !== null && existsSync(summaryPath);
332
+ };
331
333
 
332
- const summaryPresent = batchIds.filter((tid) => existingSummaries.has(tid.toUpperCase()));
333
- const summaryMissing = batchIds.filter((tid) => !existingSummaries.has(tid.toUpperCase()));
334
+ const summaryPresent = batchIds.filter((tid) => hasSummary(tid));
335
+ const summaryMissing = batchIds.filter((tid) => !hasSummary(tid));
334
336
  const completedTaskIds: string[] = [];
335
337
  const skippedTaskIds: string[] = [];
336
338
  const unchangedTaskIds: string[] = [];
@@ -3,11 +3,10 @@ import { AutoSession } from "./auto/session.js";
3
3
  import type { CurrentUnit } from "./auto/session.js";
4
4
  import type { SourceObservationStore } from "./source-observations.js";
5
5
  import {
6
- isDeterministicPolicyError,
7
- isQueuedUserMessageSkip,
8
- isToolInvocationError,
9
6
  markToolEnd as markTrackedToolEnd,
10
7
  markToolStart as markTrackedToolStart,
8
+ shouldClearToolInvocationErrorAfterSuccess,
9
+ updateToolInvocationError,
11
10
  } from "./auto-tool-tracking.js";
12
11
  // Re-exported as a pure pass-through. Must stay UNGATED (no autoSession.active
13
12
  // argument, unlike markToolStart at the bottom of this file) so it is true in
@@ -99,13 +98,19 @@ export function markToolEnd(toolCallId: string): void {
99
98
 
100
99
  export function recordToolInvocationError(toolName: string, errorMsg: string): void {
101
100
  if (!autoSession.active) return;
102
- if (isToolInvocationError(errorMsg) || isQueuedUserMessageSkip(errorMsg) || isDeterministicPolicyError(errorMsg)) {
103
- autoSession.lastToolInvocationError = `${toolName}: ${errorMsg}`;
104
- }
101
+ autoSession.lastToolInvocationError = updateToolInvocationError(
102
+ autoSession.lastToolInvocationError,
103
+ toolName,
104
+ errorMsg,
105
+ );
105
106
  }
106
107
 
107
- export function clearToolInvocationError(): void {
108
+ export function clearToolInvocationError(successfulToolName?: string): void {
108
109
  if (!autoSession.active) return;
110
+ if (!shouldClearToolInvocationErrorAfterSuccess(
111
+ autoSession.lastToolInvocationError,
112
+ successfulToolName,
113
+ )) return;
109
114
  autoSession.lastToolInvocationError = null;
110
115
  }
111
116
 
@@ -88,6 +88,7 @@ import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.
88
88
  import { extractVerdict } from "./verdict-parser.js";
89
89
  import { auditOrphanedPreflightStashes } from "./orphan-stash-audit.js";
90
90
  import { parseProject } from "./schemas/parsers.js";
91
+ import { LAYOUT_SEGMENTS } from "./layout-policy.js";
91
92
 
92
93
  import {
93
94
  debugLog,
@@ -152,6 +153,33 @@ export function hasGitIndexLockForTest(basePath: string): boolean {
152
153
  return existsSync(join(basePath, ".git", "index.lock"));
153
154
  }
154
155
 
156
+ function isEmptyDirectory(dirPath: string): boolean {
157
+ try {
158
+ return existsSync(dirPath) && readdirSync(dirPath).length === 0;
159
+ } catch {
160
+ return false;
161
+ }
162
+ }
163
+
164
+ export function reconcileFlatPhaseBootstrapLayout(basePath: string): boolean {
165
+ const gsdDir = join(basePath, ".gsd");
166
+ const phasesPath = join(gsdDir, LAYOUT_SEGMENTS.level1);
167
+ const milestonesPath = join(gsdDir, "milestones");
168
+
169
+ if (isEmptyDirectory(milestonesPath)) {
170
+ if (!existsSync(phasesPath)) mkdirSync(phasesPath, { recursive: true });
171
+ rmSync(milestonesPath, { recursive: true, force: true });
172
+ return true;
173
+ }
174
+
175
+ if (!existsSync(phasesPath) && !existsSync(milestonesPath)) {
176
+ mkdirSync(phasesPath, { recursive: true });
177
+ return true;
178
+ }
179
+
180
+ return false;
181
+ }
182
+
155
183
  export function _shouldAbortBootstrapForUnavailableDbForTest(
156
184
  gsdDbPath: string,
157
185
  dbAvailable: boolean,
@@ -1057,7 +1085,7 @@ export async function bootstrapAutoSession(
1057
1085
  // provider the user is not logged into and surface as "Not logged in · Please
1058
1086
  // run /login" before pausing and resetting to claude-code/claude-sonnet-4-6.
1059
1087
  const manualSessionOverride = getSessionModelOverride(ctx.sessionManager.getSessionId());
1060
- const sessionProviderIsCustom = isCustomProvider(ctx.model?.provider);
1088
+ const sessionProviderIsCustom = isCustomProvider(ctx.model?.provider, ctx.modelRegistry);
1061
1089
  const profileModelIds = modelIdsForProfileResolution(
1062
1090
  ctx.modelRegistry,
1063
1091
  resolveProfileAnchorProvider(ctx.model?.provider),
@@ -1152,19 +1180,14 @@ export async function bootstrapAutoSession(
1152
1180
  ensureGitignore(base, { manageGitignore });
1153
1181
  if (manageGitignore !== false) untrackRuntimeFiles(base);
1154
1182
 
1155
- // Bootstrap milestones/ if it doesn't exist.
1156
- // Check milestones/ directly — ensureGsdSymlink above already created .gsd/,
1157
- // so checking .gsd/ existence would be dead code (#2942).
1158
- const gsdDir = join(base, ".gsd");
1159
- const milestonesPath = join(gsdDir, "milestones");
1160
- if (!existsSync(milestonesPath)) {
1161
- mkdirSync(milestonesPath, { recursive: true });
1183
+ // Bootstrap the flat-phase projection root and clean empty legacy scaffolds.
1184
+ if (reconcileFlatPhaseBootstrapLayout(base)) {
1162
1185
  try {
1163
1186
  nativeAddAll(base);
1164
1187
  nativeCommit(base, "chore: init gsd");
1165
1188
  } catch (err) {
1166
1189
  /* nothing to commit */
1167
- logWarning("engine", `mkdir failed: ${err instanceof Error ? err.message : String(err)}`);
1190
+ logWarning("engine", `layout bootstrap commit failed: ${err instanceof Error ? err.message : String(err)}`);
1168
1191
  }
1169
1192
  }
1170
1193
 
@@ -132,6 +132,8 @@ export function clearInFlightTools(): void {
132
132
  */
133
133
  const TOOL_INVOCATION_ERROR_RE = /Validation failed for tool|Input validation error|Invalid arguments for tool|MCP error -32602|No such tool available|Expected ',' or '\}'(?: after property value)?(?: in JSON)?|Unexpected end of JSON|Unexpected token.*in JSON|does not provide an export named|Named export .* not found|Cannot find module|ERR_MODULE_NOT_FOUND|ERR_MODULE_NOT_EXPORTED|ERR_PACKAGE_PATH_NOT_EXPORTED/i;
134
134
  const DETERMINISTIC_POLICY_ERROR_RE = /(?:^|\b)(?:HARD BLOCK:|Blocked: \/gsd queue is a planning tool|Direct writes to \.gsd\/STATE\.md and \.gsd\/gsd\.db are blocked|This is a mechanical gate)/i;
135
+ const SCHEDULE_WAKEUP_TOOL_NAME = "ScheduleWakeup";
136
+ const SCHEDULE_WAKEUP_CONTINUATION_ERROR = "`prompt` is required when `stop` is not true";
135
137
 
136
138
  /**
137
139
  * Matches the runtime's "tool not registered" error. Unlike the deterministic
@@ -151,6 +153,60 @@ export function isToolInvocationError(errorMsg: string): boolean {
151
153
  return TOOL_INVOCATION_ERROR_RE.test(errorMsg) || isDeterministicPolicyError(errorMsg);
152
154
  }
153
155
 
156
+ /**
157
+ * Claude Code validates its native ScheduleWakeup tool outside GSD's schema.
158
+ * Keep this exact and tool-scoped so similarly worded business validation from
159
+ * unrelated tools does not pause auto-mode.
160
+ */
161
+ export function isScheduleWakeupContinuationError(toolName: string, errorMsg: string): boolean {
162
+ return stripMcpToolPrefix(toolName) === SCHEDULE_WAKEUP_TOOL_NAME
163
+ && errorMsg.trim() === SCHEDULE_WAKEUP_CONTINUATION_ERROR;
164
+ }
165
+
166
+ function shouldRecordToolInvocationError(toolName: string, errorMsg: string): boolean {
167
+ return isScheduleWakeupContinuationError(toolName, errorMsg)
168
+ || isToolInvocationError(errorMsg)
169
+ || isQueuedUserMessageSkip(errorMsg);
170
+ }
171
+
172
+ function isRecordedScheduleWakeupContinuationError(recordedError: string | null): boolean {
173
+ if (!recordedError) return false;
174
+
175
+ const separator = recordedError.indexOf(": ");
176
+ return separator >= 0 && isScheduleWakeupContinuationError(
177
+ recordedError.slice(0, separator),
178
+ recordedError.slice(separator + 2),
179
+ );
180
+ }
181
+
182
+ export function updateToolInvocationError(
183
+ recordedError: string | null,
184
+ toolName: string,
185
+ errorMsg: string,
186
+ ): string | null {
187
+ if (!shouldRecordToolInvocationError(toolName, errorMsg)) return recordedError;
188
+ if (
189
+ isRecordedScheduleWakeupContinuationError(recordedError)
190
+ && !isScheduleWakeupContinuationError(toolName, errorMsg)
191
+ ) return recordedError;
192
+
193
+ return `${toolName}: ${errorMsg}`;
194
+ }
195
+
196
+ /**
197
+ * A failed continuation must survive successful diagnostic/read calls in the
198
+ * same turn. Only a later successful ScheduleWakeup proves the continuation
199
+ * was armed; all other invocation errors retain their existing clear-on-success
200
+ * behavior.
201
+ */
202
+ export function shouldClearToolInvocationErrorAfterSuccess(
203
+ recordedError: string | null,
204
+ successfulToolName?: string,
205
+ ): boolean {
206
+ return !isRecordedScheduleWakeupContinuationError(recordedError)
207
+ || stripMcpToolPrefix(successfulToolName ?? "") === SCHEDULE_WAKEUP_TOOL_NAME;
208
+ }
209
+
154
210
  /**
155
211
  * Returns true if the error message indicates the called tool was not on the
156
212
  * session's tool surface (MCP startup race — see TOOL_UNAVAILABLE_ERROR_RE).