@opengsd/gsd-pi 1.3.0-dev.65546769 → 1.3.0-dev.72e3af2a

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 (357) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +11 -2
  3. package/dist/resources/extensions/google-cli/stream-adapter.js +82 -15
  4. package/dist/resources/extensions/gsd/artifact-verification.js +427 -0
  5. package/dist/resources/extensions/gsd/auto/orchestrator.js +12 -3
  6. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  7. package/dist/resources/extensions/gsd/auto-artifact-paths.js +28 -1
  8. package/dist/resources/extensions/gsd/auto-dispatch.js +20 -19
  9. package/dist/resources/extensions/gsd/auto-prompts.js +26 -11
  10. package/dist/resources/extensions/gsd/auto-recovery.js +6 -507
  11. package/dist/resources/extensions/gsd/auto-runtime-state.js +4 -5
  12. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +3 -3
  13. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -13
  14. package/dist/resources/extensions/gsd/bootstrap/core-session-tools.js +38 -0
  15. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +6 -1
  16. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -0
  17. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +10 -19
  18. package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -19
  19. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +68 -10
  20. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
  21. package/dist/resources/extensions/gsd/commands-context.js +19 -1
  22. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +16 -10
  23. package/dist/resources/extensions/gsd/commands-worktree.js +12 -10
  24. package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -3
  25. package/dist/resources/extensions/gsd/db/queries.js +60 -0
  26. package/dist/resources/extensions/gsd/db-workspace.js +55 -3
  27. package/dist/resources/extensions/gsd/doctor-providers.js +92 -8
  28. package/dist/resources/extensions/gsd/exec-sandbox.js +45 -9
  29. package/dist/resources/extensions/gsd/forensics.js +2 -32
  30. package/dist/resources/extensions/gsd/git-service.js +4 -4
  31. package/dist/resources/extensions/gsd/guided-flow-queue.js +66 -5
  32. package/dist/resources/extensions/gsd/health-widget.js +55 -29
  33. package/dist/resources/extensions/gsd/layout-policy.js +3 -1
  34. package/dist/resources/extensions/gsd/markdown-renderer.js +8 -9
  35. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +44 -21
  36. package/dist/resources/extensions/gsd/migration-auto-check.js +22 -0
  37. package/dist/resources/extensions/gsd/milestone-ids.js +32 -2
  38. package/dist/resources/extensions/gsd/milestone-implementation-evidence.js +26 -20
  39. package/dist/resources/extensions/gsd/prompts/code-review.md +6 -4
  40. package/dist/resources/extensions/gsd/quick.js +45 -2
  41. package/dist/resources/extensions/gsd/session-forensics.js +11 -1
  42. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  43. package/dist/resources/extensions/gsd/state/derive/cache.js +28 -0
  44. package/dist/resources/extensions/gsd/state/derive/db-open.js +39 -0
  45. package/dist/resources/extensions/gsd/state/derive/from-db.js +452 -0
  46. package/dist/resources/extensions/gsd/state/derive/index.js +75 -0
  47. package/dist/resources/extensions/gsd/state/derive/interrupted-work.js +21 -0
  48. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +45 -2
  49. package/dist/resources/extensions/gsd/state-reconciliation/index.js +48 -23
  50. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +32 -28
  51. package/dist/resources/extensions/gsd/state.js +12 -611
  52. package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
  53. package/dist/resources/extensions/gsd/tools/complete-task.js +43 -14
  54. package/dist/resources/extensions/gsd/tools/exec-tool.js +7 -2
  55. package/dist/resources/extensions/gsd/unit-context-composer.js +23 -7
  56. package/dist/resources/extensions/gsd/unit-registry.js +32 -4
  57. package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +33 -3
  58. package/dist/resources/extensions/gsd/validation-block-guard.js +9 -4
  59. package/dist/resources/extensions/gsd/workflow-projections.js +19 -14
  60. package/dist/resources/extensions/gsd/workspace-git-preflight.js +30 -1
  61. package/dist/resources/extensions/gsd/worktree-manager.js +44 -2
  62. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  63. package/dist/web/standalone/.next/BUILD_ID +1 -1
  64. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  65. package/dist/web/standalone/.next/build-manifest.json +3 -3
  66. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  67. package/dist/web/standalone/.next/react-loadable-manifest.json +9 -9
  68. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  69. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  75. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  87. package/dist/web/standalone/.next/server/app/index.html +1 -1
  88. package/dist/web/standalone/.next/server/app/index.rsc +2 -2
  89. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  90. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  91. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  95. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  96. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  97. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  99. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  100. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  101. package/dist/web/standalone/.next/static/chunks/{2659.b7b129ee6a769448.js → 2659.58e950899a9bb82f.js} +1 -1
  102. package/dist/web/standalone/.next/static/chunks/2772.a7c1fcc69a4685ef.js +1 -0
  103. package/dist/web/standalone/.next/static/chunks/{3616.3c60753b8ffcbd2e.js → 3616.61a2af74bb8833c8.js} +1 -1
  104. package/dist/web/standalone/.next/static/chunks/{4283.8e446784528ed9dc.js → 4283.d0d9e0a955e441cb.js} +1 -1
  105. package/dist/web/standalone/.next/static/chunks/{5826.a46ecdd1cfe8dabc.js → 5826.5421d66c72b9f34e.js} +1 -1
  106. package/dist/web/standalone/.next/static/chunks/{8785.481aa5869991b760.js → 8785.e29b3134cab1d153.js} +1 -1
  107. package/dist/web/standalone/.next/static/chunks/8937.640dc9c2aaa1dfad.js +10 -0
  108. package/dist/web/standalone/.next/static/chunks/app/{page-6644fc6ee8ca1247.js → page-72a856634ad14c10.js} +1 -1
  109. package/dist/web/standalone/.next/static/chunks/webpack-9c401904f87ded16.js +1 -0
  110. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  111. package/package.json +1 -1
  112. package/packages/cloud-mcp-gateway/package.json +2 -2
  113. package/packages/contracts/dist/workflow.d.ts +1 -0
  114. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  115. package/packages/contracts/dist/workflow.js +2 -0
  116. package/packages/contracts/dist/workflow.js.map +1 -1
  117. package/packages/contracts/package.json +1 -1
  118. package/packages/daemon/package.json +4 -4
  119. package/packages/gsd-agent-core/dist/agent-session.d.ts +1 -0
  120. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  121. package/packages/gsd-agent-core/dist/agent-session.js +3 -0
  122. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  123. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts +41 -0
  124. package/packages/gsd-agent-core/dist/extension-ui-snapshot.d.ts.map +1 -0
  125. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js +62 -0
  126. package/packages/gsd-agent-core/dist/extension-ui-snapshot.js.map +1 -0
  127. package/packages/gsd-agent-core/dist/index.d.ts +2 -0
  128. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  129. package/packages/gsd-agent-core/dist/index.js +2 -0
  130. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  131. package/packages/gsd-agent-core/dist/session/agent-session-events.js +1 -1
  132. package/packages/gsd-agent-core/dist/session/agent-session-events.js.map +1 -1
  133. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +1 -0
  134. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  135. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  136. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts +5 -0
  137. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  138. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +60 -3
  139. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  140. package/packages/gsd-agent-core/dist/transcript-store.d.ts +58 -0
  141. package/packages/gsd-agent-core/dist/transcript-store.d.ts.map +1 -0
  142. package/packages/gsd-agent-core/dist/transcript-store.js +132 -0
  143. package/packages/gsd-agent-core/dist/transcript-store.js.map +1 -0
  144. package/packages/gsd-agent-core/package.json +5 -5
  145. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +2 -0
  146. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  147. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -11
  148. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  149. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts +4 -0
  150. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.d.ts.map +1 -0
  151. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js +7 -0
  152. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller-latency.js.map +1 -0
  153. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +3 -24
  154. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  155. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +26 -829
  156. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  157. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts +58 -0
  158. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.d.ts.map +1 -0
  159. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js +312 -0
  160. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-handoff-filter.js.map +1 -0
  161. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts +31 -0
  162. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.d.ts.map +1 -0
  163. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js +130 -0
  164. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-pinned-zone.js.map +1 -0
  165. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts +15 -0
  166. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -0
  167. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +258 -0
  168. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -0
  169. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts +13 -0
  170. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.d.ts.map +1 -0
  171. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js +118 -0
  172. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-tool-rollup.js.map +1 -0
  173. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts +9 -0
  174. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  175. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js +1 -1
  176. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  177. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts +54 -0
  178. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.d.ts.map +1 -0
  179. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js +20 -0
  180. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-ui-state.js.map +1 -0
  181. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +4 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +9 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts +56 -0
  186. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.d.ts.map +1 -0
  187. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js +44 -0
  188. package/packages/gsd-agent-modes/dist/modes/interactive/streaming-render-state.js.map +1 -0
  189. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts +5 -0
  190. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.d.ts.map +1 -0
  191. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js +77 -0
  192. package/packages/gsd-agent-modes/dist/modes/interactive/tui-transcript-tracker.js.map +1 -0
  193. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  194. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js +18 -0
  195. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-mode.js.map +1 -1
  196. package/packages/gsd-agent-modes/package.json +7 -7
  197. package/packages/mcp-server/README.md +1 -1
  198. package/packages/mcp-server/dist/server.d.ts +1 -1
  199. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  200. package/packages/mcp-server/dist/server.js +3 -3
  201. package/packages/mcp-server/dist/server.js.map +1 -1
  202. package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
  203. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  204. package/packages/mcp-server/dist/workflow-tools.js +34 -20
  205. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  206. package/packages/mcp-server/package.json +4 -4
  207. package/packages/native/package.json +1 -1
  208. package/packages/pi-agent-core/package.json +1 -1
  209. package/packages/pi-ai/package.json +1 -1
  210. package/packages/pi-coding-agent/README.md +3 -2
  211. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts +9 -0
  212. package/packages/pi-coding-agent/dist/core/session-manager-context.d.ts.map +1 -0
  213. package/packages/pi-coding-agent/dist/core/session-manager-context.js +94 -0
  214. package/packages/pi-coding-agent/dist/core/session-manager-context.js.map +1 -0
  215. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts +8 -0
  216. package/packages/pi-coding-agent/dist/core/session-manager-list.d.ts.map +1 -0
  217. package/packages/pi-coding-agent/dist/core/session-manager-list.js +244 -0
  218. package/packages/pi-coding-agent/dist/core/session-manager-list.js.map +1 -0
  219. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts +12 -0
  220. package/packages/pi-coding-agent/dist/core/session-manager-migration.d.ts.map +1 -0
  221. package/packages/pi-coding-agent/dist/core/session-manager-migration.js +84 -0
  222. package/packages/pi-coding-agent/dist/core/session-manager-migration.js.map +1 -0
  223. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +135 -0
  224. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -0
  225. package/packages/pi-coding-agent/dist/core/session-manager-types.js +2 -0
  226. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -0
  227. package/packages/pi-coding-agent/dist/core/session-manager.d.ts +6 -154
  228. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  229. package/packages/pi-coding-agent/dist/core/session-manager.js +22 -459
  230. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  231. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts +75 -75
  232. package/packages/pi-coding-agent/dist/theme/theme-schema.d.ts.map +1 -1
  233. package/packages/pi-coding-agent/dist/theme/theme-schema.js +1 -1
  234. package/packages/pi-coding-agent/dist/theme/theme-schema.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  236. package/packages/pi-coding-agent/dist/theme/theme.js +11 -7
  237. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  238. package/packages/pi-coding-agent/package.json +7 -7
  239. package/packages/pi-tui/package.json +2 -2
  240. package/packages/rpc-client/package.json +2 -2
  241. package/pkg/dist/theme/theme-schema.d.ts +75 -75
  242. package/pkg/dist/theme/theme-schema.d.ts.map +1 -1
  243. package/pkg/dist/theme/theme-schema.js +1 -1
  244. package/pkg/dist/theme/theme-schema.js.map +1 -1
  245. package/pkg/dist/theme/theme.d.ts.map +1 -1
  246. package/pkg/dist/theme/theme.js +11 -7
  247. package/pkg/dist/theme/theme.js.map +1 -1
  248. package/pkg/package.json +1 -1
  249. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +20 -2
  250. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -0
  251. package/src/resources/extensions/google-cli/stream-adapter.ts +106 -19
  252. package/src/resources/extensions/gsd/artifact-verification.ts +464 -0
  253. package/src/resources/extensions/gsd/auto/orchestrator.ts +25 -11
  254. package/src/resources/extensions/gsd/auto/session.ts +5 -0
  255. package/src/resources/extensions/gsd/auto-artifact-paths.ts +47 -1
  256. package/src/resources/extensions/gsd/auto-dispatch.ts +21 -23
  257. package/src/resources/extensions/gsd/auto-prompts.ts +38 -12
  258. package/src/resources/extensions/gsd/auto-recovery.ts +10 -508
  259. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -5
  260. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +3 -2
  261. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +125 -12
  262. package/src/resources/extensions/gsd/bootstrap/core-session-tools.ts +43 -0
  263. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +6 -1
  264. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -0
  265. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +11 -19
  266. package/src/resources/extensions/gsd/bootstrap/system-context.ts +52 -18
  267. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +74 -10
  268. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
  269. package/src/resources/extensions/gsd/commands-context.ts +18 -1
  270. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +14 -9
  271. package/src/resources/extensions/gsd/commands-worktree.ts +12 -10
  272. package/src/resources/extensions/gsd/dashboard-overlay.ts +32 -3
  273. package/src/resources/extensions/gsd/db/queries.ts +79 -0
  274. package/src/resources/extensions/gsd/db-workspace.ts +61 -3
  275. package/src/resources/extensions/gsd/doctor-providers.ts +103 -9
  276. package/src/resources/extensions/gsd/exec-sandbox.ts +49 -9
  277. package/src/resources/extensions/gsd/forensics.ts +2 -33
  278. package/src/resources/extensions/gsd/git-service.ts +5 -5
  279. package/src/resources/extensions/gsd/guided-flow-queue.ts +89 -4
  280. package/src/resources/extensions/gsd/health-widget.ts +69 -32
  281. package/src/resources/extensions/gsd/layout-policy.ts +2 -1
  282. package/src/resources/extensions/gsd/markdown-renderer.ts +8 -11
  283. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +51 -19
  284. package/src/resources/extensions/gsd/migration-auto-check.ts +23 -0
  285. package/src/resources/extensions/gsd/milestone-ids.ts +31 -2
  286. package/src/resources/extensions/gsd/milestone-implementation-evidence.ts +35 -21
  287. package/src/resources/extensions/gsd/prompts/code-review.md +6 -4
  288. package/src/resources/extensions/gsd/quick.ts +43 -2
  289. package/src/resources/extensions/gsd/session-forensics.ts +11 -1
  290. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -1
  291. package/src/resources/extensions/gsd/state/derive/cache.ts +46 -0
  292. package/src/resources/extensions/gsd/state/derive/db-open.ts +45 -0
  293. package/src/resources/extensions/gsd/state/derive/from-db.ts +561 -0
  294. package/src/resources/extensions/gsd/state/derive/index.ts +104 -0
  295. package/src/resources/extensions/gsd/state/derive/interrupted-work.ts +31 -0
  296. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +81 -7
  297. package/src/resources/extensions/gsd/state-reconciliation/index.ts +50 -24
  298. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +43 -28
  299. package/src/resources/extensions/gsd/state.ts +32 -732
  300. package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +98 -1
  301. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +111 -1
  302. package/src/resources/extensions/gsd/tests/commands-context.test.ts +26 -0
  303. package/src/resources/extensions/gsd/tests/commands-gsd-core.test.ts +1 -0
  304. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +80 -0
  305. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +11 -0
  306. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +48 -8
  307. package/src/resources/extensions/gsd/tests/complete-task.test.ts +75 -0
  308. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +55 -2
  309. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +26 -1
  310. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +70 -2
  311. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +107 -0
  312. package/src/resources/extensions/gsd/tests/exec-graceful-kill.test.ts +38 -0
  313. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +45 -1
  314. package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +88 -0
  315. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +42 -0
  316. package/src/resources/extensions/gsd/tests/health-widget.test.ts +268 -3
  317. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +119 -1
  318. package/src/resources/extensions/gsd/tests/integration/queue-active-milestone-context-budget.test.ts +93 -0
  319. package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +56 -9
  320. package/src/resources/extensions/gsd/tests/knowledge-cold-start.test.ts +14 -0
  321. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +78 -0
  322. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +70 -0
  323. package/src/resources/extensions/gsd/tests/orchestrator-logs.test.ts +43 -1
  324. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +26 -0
  325. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +2 -1
  326. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +1 -1
  327. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +54 -1
  328. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +50 -14
  329. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +195 -1
  330. package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +185 -0
  331. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +87 -0
  332. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +7 -0
  333. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +56 -0
  334. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  335. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +151 -0
  336. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +26 -0
  337. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +193 -14
  338. package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +25 -0
  339. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +79 -0
  340. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +66 -0
  341. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +151 -2
  342. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +39 -0
  343. package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
  344. package/src/resources/extensions/gsd/tools/complete-task.ts +53 -15
  345. package/src/resources/extensions/gsd/tools/exec-tool.ts +7 -3
  346. package/src/resources/extensions/gsd/unit-context-composer.ts +33 -7
  347. package/src/resources/extensions/gsd/unit-registry.ts +32 -4
  348. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +41 -5
  349. package/src/resources/extensions/gsd/validation-block-guard.ts +13 -7
  350. package/src/resources/extensions/gsd/workflow-projections.ts +20 -14
  351. package/src/resources/extensions/gsd/workspace-git-preflight.ts +31 -0
  352. package/src/resources/extensions/gsd/worktree-manager.ts +41 -1
  353. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +0 -1
  354. package/dist/web/standalone/.next/static/chunks/796.e0bdc932325d7e03.js +0 -10
  355. package/dist/web/standalone/.next/static/chunks/webpack-f46ea08200a0227e.js +0 -1
  356. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → O7xDYXO0r4zFhIzY1hrWV}/_buildManifest.js +0 -0
  357. /package/dist/web/standalone/.next/static/{BTKtGFF1Y-hvVJEGhBRo9 → O7xDYXO0r4zFhIzY1hrWV}/_ssgManifest.js +0 -0
@@ -232,7 +232,7 @@ test("dispatch-rule-coverage: planning boundary without planner handoff → rese
232
232
  assertMatch(
233
233
  match,
234
234
  {
235
- ruleName: "planning (no research, not S01) → research-slice",
235
+ ruleName: "planning (no research) → research-slice",
236
236
  action: "dispatch",
237
237
  unitType: "research-slice",
238
238
  },
@@ -240,6 +240,31 @@ test("dispatch-rule-coverage: planning boundary without planner handoff → rese
240
240
  );
241
241
  });
242
242
 
243
+ test("dispatch-rule-coverage: S01 still researches when only milestone research exists", async (t) => {
244
+ const tmp = mkdtempSync(join(tmpdir(), "gsd-disp-cov-s01-research-"));
245
+ t.after(() => rmSync(tmp, { recursive: true, force: true }));
246
+
247
+ writeMilestoneFile(tmp, "M001", "CONTEXT", "# Context\n");
248
+ writeMilestoneFile(tmp, "M001", "ROADMAP", "# Roadmap\n");
249
+ writeMilestoneFile(tmp, "M001", "RESEARCH", "# Milestone Research\n");
250
+
251
+ const state = makeState({
252
+ phase: "planning",
253
+ activeSlice: { id: "S01", title: "First Slice" },
254
+ nextAction: "Plan slice S01 (First Slice).",
255
+ });
256
+ const match = await findFirstMatch(makeCtx(tmp, state));
257
+ assertMatch(
258
+ match,
259
+ {
260
+ ruleName: "planning (no research) → research-slice",
261
+ action: "dispatch",
262
+ unitType: "research-slice",
263
+ },
264
+ "S01 missing slice research despite milestone research",
265
+ );
266
+ });
267
+
243
268
  test("dispatch-rule-coverage: executing with task plan present → execute-task", async (t) => {
244
269
  const tmp = mkdtempSync(join(tmpdir(), "gsd-disp-cov-exec-"));
245
270
  t.after(() => rmSync(tmp, { recursive: true, force: true }));
@@ -1,10 +1,18 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
3
+ import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
 
7
- import { closeDatabase } from "../gsd-db.ts";
7
+ import {
8
+ _getAdapter,
9
+ closeDatabase,
10
+ getHierarchyCompletionCounts,
11
+ insertMilestone,
12
+ insertSlice,
13
+ insertTask,
14
+ openDatabase,
15
+ } from "../gsd-db.ts";
8
16
  import { buildForensicReport } from "../forensics.ts";
9
17
  import { handleDoctor } from "../commands-handlers.ts";
10
18
  import { withCommandCwd } from "../commands/context.ts";
@@ -23,6 +31,66 @@ test("#5194 forensics opens DB before computing completion counts", async (t) =>
23
31
  assert.equal(report.dbCompletionCounts?.tasksTotal, 0);
24
32
  });
25
33
 
34
+ test("#968 completion counts use fixed aggregate queries and canonical closed statuses", (t) => {
35
+ const base = mkdtempSync(join(tmpdir(), "gsd-forensics-counts-"));
36
+ const dbPath = join(base, "gsd.db");
37
+ t.after(() => {
38
+ closeDatabase();
39
+ rmSync(base, { recursive: true, force: true });
40
+ });
41
+
42
+ openDatabase(dbPath);
43
+
44
+ insertMilestone({ id: "M001", status: "complete" });
45
+ insertMilestone({ id: "M002", status: "active" });
46
+ insertMilestone({ id: "M003", status: "closed" });
47
+
48
+ insertSlice({ milestoneId: "M001", id: "S01", status: "done" });
49
+ insertSlice({ milestoneId: "M001", id: "S02", status: "pending" });
50
+ insertSlice({ milestoneId: "M002", id: "S01", status: "skipped" });
51
+ insertSlice({ milestoneId: "M003", id: "S01", status: "active" });
52
+
53
+ insertTask({ milestoneId: "M001", sliceId: "S01", id: "T01", status: "complete" });
54
+ insertTask({ milestoneId: "M001", sliceId: "S01", id: "T02", status: "done" });
55
+ insertTask({ milestoneId: "M001", sliceId: "S02", id: "T01", status: "skipped" });
56
+ insertTask({ milestoneId: "M002", sliceId: "S01", id: "T01", status: "closed" });
57
+ insertTask({ milestoneId: "M002", sliceId: "S01", id: "T02", status: "pending" });
58
+ insertTask({ milestoneId: "M003", sliceId: "S01", id: "T01", status: "active" });
59
+
60
+ const adapter = _getAdapter()!;
61
+ const originalPrepare = adapter.prepare.bind(adapter);
62
+ const preparedSql: string[] = [];
63
+ adapter.prepare = (sql) => {
64
+ preparedSql.push(sql);
65
+ return originalPrepare(sql);
66
+ };
67
+
68
+ assert.deepEqual(getHierarchyCompletionCounts(), {
69
+ milestones: 2,
70
+ milestonesTotal: 3,
71
+ slices: 2,
72
+ slicesTotal: 4,
73
+ tasks: 4,
74
+ tasksTotal: 6,
75
+ });
76
+
77
+ assert.equal(preparedSql.length, 3);
78
+ assert.ok(preparedSql.every((sql) => /COUNT\(\*\)/i.test(sql)));
79
+ assert.doesNotMatch(preparedSql.join("\n"), /SELECT\s+\*/i);
80
+ });
81
+
82
+ test("#968 forensics completion counts do not re-query slices and tasks", () => {
83
+ const source = readFileSync(join(process.cwd(), "src/resources/extensions/gsd/forensics.ts"), "utf-8");
84
+ const start = source.indexOf("function getDbCompletionCounts()");
85
+ const end = source.indexOf("// ─── Anomaly Detectors", start);
86
+ assert.notEqual(start, -1);
87
+ assert.notEqual(end, -1);
88
+ const body = source.slice(start, end);
89
+
90
+ assert.match(body, /getHierarchyCompletionCounts\(\)/);
91
+ assert.doesNotMatch(body, /getAllMilestones|getMilestoneSlices|getSliceTasks/);
92
+ });
93
+
26
94
  test("#5194 doctor command does not emit false db_unavailable when gsd.db exists", async (t) => {
27
95
  const base = mkdtempSync(join(tmpdir(), "gsd-doctor-db-open-"));
28
96
  t.after(() => rmSync(base, { recursive: true, force: true }));
@@ -20,6 +20,7 @@ import { tmpdir } from "node:os";
20
20
 
21
21
  import {
22
22
  runProviderChecks,
23
+ runProviderChecksAsync,
23
24
  formatProviderReport,
24
25
  summariseProviderIssues,
25
26
  type ProviderCheckResult,
@@ -47,6 +48,26 @@ function withEnv(vars: Record<string, string | undefined>, fn: () => void): void
47
48
  }
48
49
  }
49
50
 
51
+ async function withEnvAsync(vars: Record<string, string | undefined>, fn: () => Promise<void>): Promise<void> {
52
+ const saved: Record<string, string | undefined> = {};
53
+ for (const [k, v] of Object.entries(vars)) {
54
+ saved[k] = process.env[k];
55
+ if (v === undefined) {
56
+ delete process.env[k];
57
+ } else {
58
+ process.env[k] = v;
59
+ }
60
+ }
61
+ try {
62
+ await fn();
63
+ } finally {
64
+ for (const [k, v] of Object.entries(saved)) {
65
+ if (v === undefined) delete process.env[k];
66
+ else process.env[k] = v;
67
+ }
68
+ }
69
+ }
70
+
50
71
  function withCwd(nextCwd: string, fn: () => void): void {
51
72
  const saved = process.cwd();
52
73
  process.chdir(nextCwd);
@@ -57,6 +78,22 @@ function withCwd(nextCwd: string, fn: () => void): void {
57
78
  }
58
79
  }
59
80
 
81
+ async function withCwdAsync(nextCwd: string, fn: () => Promise<void>): Promise<void> {
82
+ const saved = process.cwd();
83
+ process.chdir(nextCwd);
84
+ try {
85
+ await fn();
86
+ } finally {
87
+ process.chdir(saved);
88
+ }
89
+ }
90
+
91
+ function normalizeProviderResults(results: ProviderCheckResult[]): string[] {
92
+ return results
93
+ .map(r => `${r.name}|${r.label}|${r.category}|${r.status}|${r.message}|${r.detail ?? ""}|${r.required}`)
94
+ .sort();
95
+ }
96
+
60
97
  const PRESENT_TEST_VALUE = "configured";
61
98
 
62
99
  // ─── formatProviderReport ─────────────────────────────────────────────────────
@@ -377,6 +414,76 @@ test("runProviderChecks detects custom provider keys from models.json", () => {
377
414
  rmSync(tmpHome, { recursive: true, force: true });
378
415
  });
379
416
 
417
+ test("runProviderChecksAsync matches sync for models.json keys and PATH CLI checks", async () => {
418
+ const tmpHome = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-async-home-")));
419
+ const repo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-async-repo-")));
420
+ const agentDir = join(tmpHome, ".gsd", "agent");
421
+ const binDir = join(tmpHome, "bin");
422
+ mkdirSync(agentDir, { recursive: true });
423
+ mkdirSync(binDir, { recursive: true });
424
+ mkdirSync(join(repo, ".gsd"), { recursive: true });
425
+
426
+ writeFileSync(
427
+ join(repo, ".gsd", "PREFERENCES.md"),
428
+ [
429
+ "---",
430
+ "models:",
431
+ " execution:",
432
+ " model: custom-model",
433
+ " provider: custom-provider",
434
+ " validation:",
435
+ " model: gemini-2.5-pro",
436
+ " provider: google-gemini-cli",
437
+ "---",
438
+ "",
439
+ ].join("\n"),
440
+ );
441
+ writeFileSync(join(agentDir, "models.json"), JSON.stringify({
442
+ providers: {
443
+ "custom-provider": {
444
+ api: "openai-completions",
445
+ apiKey: "x",
446
+ baseUrl: "https://example.invalid/v1",
447
+ models: [{ id: "custom-model", name: "Custom Model" }],
448
+ },
449
+ },
450
+ }));
451
+
452
+ const fakeGemini = join(binDir, "gemini");
453
+ writeFileSync(fakeGemini, "#!/bin/sh\necho mock\n");
454
+ chmodSync(fakeGemini, 0o755);
455
+
456
+ try {
457
+ await withEnvAsync({
458
+ HOME: tmpHome,
459
+ CUSTOM_PROVIDER_API_KEY: undefined,
460
+ GEMINI_API_KEY: undefined,
461
+ GOOGLE_API_KEY: undefined,
462
+ PATH: binDir,
463
+ }, async () => {
464
+ await withCwdAsync(repo, async () => {
465
+ const syncResults = runProviderChecks();
466
+ const asyncResults = await runProviderChecksAsync();
467
+
468
+ assert.deepEqual(normalizeProviderResults(asyncResults), normalizeProviderResults(syncResults));
469
+ assert.equal(
470
+ asyncResults.find(r => r.name === "custom-provider")?.status,
471
+ "ok",
472
+ "models.json apiKey should satisfy custom provider auth",
473
+ );
474
+ assert.equal(
475
+ asyncResults.find(r => r.name === "google-gemini-cli")?.status,
476
+ "ok",
477
+ "gemini CLI binary should satisfy explicit CLI provider",
478
+ );
479
+ });
480
+ });
481
+ } finally {
482
+ rmSync(repo, { recursive: true, force: true });
483
+ rmSync(tmpHome, { recursive: true, force: true });
484
+ }
485
+ });
486
+
380
487
  test("runProviderChecks reports missing custom provider key without models.json apiKey", () => {
381
488
  const tmpHome = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-custom-missing-home-")));
382
489
  const repo = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-custom-missing-repo-")));
@@ -63,6 +63,44 @@ function wallClockGuard<T>(promise: Promise<T>, ms: number): Promise<T> {
63
63
  ]);
64
64
  }
65
65
 
66
+ test(
67
+ 'runExecSandbox: aborted signal terminates promptly without waiting for timeout',
68
+ { timeout: 10_000 },
69
+ async (t) => {
70
+ const base = freshBase();
71
+ t.after(() => cleanup(base));
72
+
73
+ const controller = new AbortController();
74
+ controller.abort();
75
+ const TIMEOUT_MS = 10_000;
76
+
77
+ const start = Date.now();
78
+ const result = await wallClockGuard(
79
+ runExecSandbox(
80
+ { runtime: 'node', script: 'setTimeout(() => {}, 30_000);', timeout_ms: TIMEOUT_MS },
81
+ baseOpts(base, {
82
+ signal: controller.signal,
83
+ kill_grace_ms: 500,
84
+ force_resolve_delay_ms: 2_000,
85
+ }),
86
+ ),
87
+ 5_000,
88
+ );
89
+ const elapsed = Date.now() - start;
90
+
91
+ assert.equal(result.aborted, true, 'aborted signal must be recorded on the sandbox result');
92
+ assert.equal(result.timed_out, false, 'client abort must not be reported as a sandbox timeout');
93
+ assert.ok(elapsed < TIMEOUT_MS, `expected abort before ${TIMEOUT_MS}ms timeout, took ${elapsed}ms`);
94
+ assert.ok(
95
+ result.duration_ms < TIMEOUT_MS,
96
+ `expected result duration before timeout, got ${result.duration_ms}ms`,
97
+ );
98
+ const meta = JSON.parse(readFileSync(result.meta_path, 'utf-8'));
99
+ assert.equal(meta.aborted, true, 'meta.json must persist the aborted marker');
100
+ assert.equal(meta.timed_out, false, 'meta.json must not report timed_out when abort caused the kill');
101
+ },
102
+ );
103
+
66
104
  // Clean up a detached child (and its process group) that a large kill_grace_ms
67
105
  // intentionally leaves alive past the force-resolve deadline.
68
106
  function cleanupByPidFile(pidFile: string): void {
@@ -3,7 +3,7 @@ import assert from "node:assert/strict";
3
3
 
4
4
  import { registerExecTools } from "../bootstrap/exec-tools.ts";
5
5
  import { executeGsdExec, executeUatExec } from "../tools/exec-tool.ts";
6
- import type { ExecSandboxRequest, ExecSandboxResult } from "../exec-sandbox.ts";
6
+ import type { ExecSandboxOptions, ExecSandboxRequest, ExecSandboxResult } from "../exec-sandbox.ts";
7
7
 
8
8
  function makeExecResult(request: ExecSandboxRequest): ExecSandboxResult {
9
9
  return {
@@ -12,6 +12,7 @@ function makeExecResult(request: ExecSandboxRequest): ExecSandboxResult {
12
12
  exit_code: 0,
13
13
  signal: null,
14
14
  timed_out: false,
15
+ aborted: false,
15
16
  force_resolved: false,
16
17
  duration_ms: 1,
17
18
  stdout_bytes: 12,
@@ -52,6 +53,49 @@ test("executeUatExec accepts evidence-mode aliases for intent", async () => {
52
53
  assert.equal(requests[0]?.metadata?.intent, "uat-artifact-check");
53
54
  });
54
55
 
56
+ test("executeGsdExec passes AbortSignal into sandbox options", async () => {
57
+ const controller = new AbortController();
58
+ let capturedSignal: AbortSignal | undefined;
59
+
60
+ const result = await executeGsdExec(
61
+ { runtime: "bash", script: "sleep 60" },
62
+ {
63
+ baseDir: "/tmp/gsd-exec-abort-signal-test",
64
+ preferences: null,
65
+ signal: controller.signal,
66
+ run: async (request, opts: ExecSandboxOptions) => {
67
+ capturedSignal = opts.signal;
68
+ return makeExecResult(request);
69
+ },
70
+ },
71
+ );
72
+
73
+ assert.equal(result.isError, false);
74
+ assert.equal(capturedSignal, controller.signal);
75
+ });
76
+
77
+ test("gsd_exec surfaces aborted child termination distinctly from a clean exit", async () => {
78
+ const result = await executeGsdExec(
79
+ { runtime: "bash", script: "trap 'exit 0' TERM; sleep 60" },
80
+ {
81
+ baseDir: "/tmp/gsd-exec-aborted-test",
82
+ preferences: null,
83
+ run: async (request) => ({
84
+ ...makeExecResult(request),
85
+ aborted: true,
86
+ exit_code: 0,
87
+ signal: null,
88
+ digest: "[no stdout — aborted]",
89
+ }),
90
+ },
91
+ );
92
+
93
+ assert.equal(result.isError, true, "an aborted run must be an error even if the child exits 0");
94
+ assert.equal(result.details?.aborted, true, "details must expose aborted");
95
+ const text = result.content.map((c) => c.text ?? "").join("\n");
96
+ assert.match(text, /exit=aborted/, "summary must distinguish an aborted result");
97
+ });
98
+
55
99
  test("gsd_exec surfaces a force-resolved (D-state) kill distinctly from a clean exit", async () => {
56
100
  // A hard-deadline force-resolve sets force_resolved=true with a synthetic SIGKILL
57
101
  // signal and null exit code. The tool result must carry that flag in details and
@@ -119,3 +119,91 @@ describe("extractTrace error filtering (#2539)", () => {
119
119
  assert.equal(trace.errors.length, 1, "lint error with output should be counted");
120
120
  });
121
121
  });
122
+
123
+ describe("extractTrace pending tool calls (#945)", () => {
124
+ test("tool call without a toolResult is counted as an error", () => {
125
+ const entries = [
126
+ {
127
+ type: "message",
128
+ message: {
129
+ role: "assistant",
130
+ content: [
131
+ {
132
+ type: "toolCall",
133
+ id: "toolu_missing",
134
+ name: "gsd_summary_save",
135
+ arguments: { content: "unfinished summary" },
136
+ },
137
+ ],
138
+ },
139
+ },
140
+ ];
141
+
142
+ const trace = extractTrace(entries);
143
+
144
+ assert.equal(trace.toolCalls.length, 1);
145
+ assert.equal(trace.toolCalls[0]?.name, "gsd_summary_save");
146
+ assert.equal(trace.toolCalls[0]?.isError, true);
147
+ assert.equal(trace.toolCalls[0]?.result, "missing tool result (stream/tool-call abort before execution)");
148
+ assert.equal(trace.errors.length, 1);
149
+ assert.equal(trace.errors[0], "Tool call gsd_summary_save started but no toolResult was recorded");
150
+ });
151
+
152
+ test("pending bash call with no toolResult marks commandsRun entry as failed", () => {
153
+ // A bash tool call that was initiated but never got a toolResult (stream abort).
154
+ const entries = [
155
+ {
156
+ type: "message",
157
+ message: {
158
+ role: "assistant",
159
+ content: [
160
+ {
161
+ type: "toolCall",
162
+ id: "toolu_bash_missing",
163
+ name: "bash",
164
+ arguments: { command: "npm run build" },
165
+ },
166
+ ],
167
+ },
168
+ },
169
+ ];
170
+
171
+ const trace = extractTrace(entries);
172
+
173
+ // The tool call should be recorded as an error.
174
+ assert.equal(trace.toolCalls.length, 1);
175
+ assert.equal(trace.toolCalls[0]?.name, "bash");
176
+ assert.equal(trace.toolCalls[0]?.isError, true);
177
+
178
+ // The commandsRun entry must be consistent: failed: true, not failed: false.
179
+ assert.equal(trace.commandsRun.length, 1);
180
+ assert.equal(trace.commandsRun[0]?.command, "npm run build");
181
+ assert.equal(trace.commandsRun[0]?.failed, true,
182
+ "commandsRun entry should be failed when its bash call never returned a result");
183
+ });
184
+
185
+ test("pending bg_shell call with no toolResult marks commandsRun entry as failed", () => {
186
+ const entries = [
187
+ {
188
+ type: "message",
189
+ message: {
190
+ role: "assistant",
191
+ content: [
192
+ {
193
+ type: "toolCall",
194
+ id: "toolu_bg_missing",
195
+ name: "bg_shell",
196
+ arguments: { command: "sleep 30" },
197
+ },
198
+ ],
199
+ },
200
+ },
201
+ ];
202
+
203
+ const trace = extractTrace(entries);
204
+
205
+ assert.equal(trace.commandsRun.length, 1);
206
+ assert.equal(trace.commandsRun[0]?.failed, true,
207
+ "bg_shell commandsRun entry should be failed when no toolResult was recorded");
208
+ });
209
+ });
@@ -86,3 +86,45 @@ test("guided milestone prompt builder preloads milestone planning context", asyn
86
86
  rmSync(base, { recursive: true, force: true });
87
87
  }
88
88
  });
89
+
90
+ test("guided milestone prompt builder caps prior draft seed before interpolation", async () => {
91
+ const base = mkdtempSync(join(tmpdir(), "gsd-guided-milestone-draft-cap-"));
92
+ const previousGsdHome = process.env.GSD_HOME;
93
+ process.env.GSD_HOME = join(base, ".gsd-home");
94
+
95
+ try {
96
+ const currentDir = join(base, ".gsd", "milestones", "M001");
97
+ mkdirSync(currentDir, { recursive: true });
98
+
99
+ const draftPath = join(currentDir, "M001-CONTEXT-DRAFT.md");
100
+ writeFileSync(draftPath, "# Draft\n\nSMALL-DRAFT-SIGNAL", "utf-8");
101
+ const smallPrompt = await buildDiscussMilestonePrompt("M001", "Draft Resume", base, "true", {
102
+ includeContextMode: false,
103
+ });
104
+
105
+ writeFileSync(
106
+ draftPath,
107
+ ["# Draft", "", "SMALL-DRAFT-SIGNAL", "", "A".repeat(200_000), "", "OVERSIZED-DRAFT-TAIL-SIGNAL"].join("\n"),
108
+ "utf-8",
109
+ );
110
+ const largePrompt = await buildDiscussMilestonePrompt("M001", "Draft Resume", base, "true", {
111
+ includeContextMode: false,
112
+ });
113
+
114
+ const addedChars = largePrompt.length - smallPrompt.length;
115
+
116
+ assert.match(largePrompt, /## Prior Discussion \(Draft Seed\)/);
117
+ assert.match(largePrompt, /### Prior Discussion Draft/);
118
+ assert.match(largePrompt, /SMALL-DRAFT-SIGNAL/);
119
+ assert.doesNotMatch(largePrompt, /OVERSIZED-DRAFT-TAIL-SIGNAL/);
120
+ assert.match(
121
+ largePrompt,
122
+ /Draft seed truncated; read the full draft at `\.gsd\/milestones\/M001\/M001-CONTEXT-DRAFT\.md` if needed\./,
123
+ );
124
+ assert.ok(addedChars < 25_000, `large draft should add bounded seed chars, added ${addedChars}`);
125
+ } finally {
126
+ if (previousGsdHome === undefined) delete process.env.GSD_HOME;
127
+ else process.env.GSD_HOME = previousGsdHome;
128
+ rmSync(base, { recursive: true, force: true });
129
+ }
130
+ });