@opengsd/gsd-pi 1.0.2-dev.867e002 → 1.0.2-dev.aed3486

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 (328) hide show
  1. package/dist/onboarding.js +22 -3
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/context7/index.js +12 -2
  4. package/dist/resources/extensions/get-secrets-from-user.js +16 -16
  5. package/dist/resources/extensions/google-cli/index.js +30 -0
  6. package/dist/resources/extensions/google-cli/models.js +55 -0
  7. package/dist/resources/extensions/google-cli/package.json +11 -0
  8. package/dist/resources/extensions/google-cli/readiness.js +12 -0
  9. package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
  10. package/dist/resources/extensions/gsd/auto/loop.js +62 -1
  11. package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
  12. package/dist/resources/extensions/gsd/auto/phases.js +37 -0
  13. package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
  14. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  15. package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
  16. package/dist/resources/extensions/gsd/auto-post-unit.js +21 -11
  17. package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
  18. package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
  19. package/dist/resources/extensions/gsd/auto-start.js +232 -49
  20. package/dist/resources/extensions/gsd/auto.js +6 -1
  21. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
  22. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -2
  23. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
  24. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -7
  25. package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
  26. package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
  27. package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
  28. package/dist/resources/extensions/gsd/commands-usage.js +105 -1
  29. package/dist/resources/extensions/gsd/config-overlay.js +20 -14
  30. package/dist/resources/extensions/gsd/context-overlay.js +22 -16
  31. package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
  32. package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
  33. package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
  34. package/dist/resources/extensions/gsd/doctor.js +6 -1
  35. package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
  36. package/dist/resources/extensions/gsd/guided-flow.js +5 -6
  37. package/dist/resources/extensions/gsd/key-manager.js +45 -13
  38. package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
  39. package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
  40. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
  41. package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
  42. package/dist/resources/extensions/gsd/preferences.js +14 -2
  43. package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
  44. package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
  45. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  46. package/dist/resources/extensions/gsd/prompts/system.md +1 -3
  47. package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
  48. package/dist/resources/extensions/gsd/repository-registry.js +3 -1
  49. package/dist/resources/extensions/gsd/safety/evidence-collector.js +11 -4
  50. package/dist/resources/extensions/gsd/skill-activation.js +233 -0
  51. package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
  52. package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
  53. package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
  54. package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
  55. package/dist/resources/extensions/gsd/skill-scope.js +52 -0
  56. package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
  57. package/dist/resources/extensions/gsd/skills.js +60 -0
  58. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
  59. package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
  60. package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
  61. package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
  62. package/dist/resources/extensions/gsd/tools/exec-tool.js +42 -8
  63. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
  64. package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
  65. package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
  66. package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
  67. package/dist/resources/extensions/gsd/vision-ask.js +22 -0
  68. package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
  69. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
  70. package/dist/resources/extensions/search-the-web/native-search.js +57 -8
  71. package/dist/resources/extensions/shared/confirm-ui.js +9 -6
  72. package/dist/resources/extensions/shared/dialog-frame.js +42 -0
  73. package/dist/resources/extensions/shared/interview-ui.js +42 -30
  74. package/dist/resources/extensions/shared/next-action-ui.js +6 -6
  75. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  76. package/dist/web/standalone/.next/BUILD_ID +1 -1
  77. package/dist/web/standalone/.next/app-path-routes-manifest.json +4 -4
  78. package/dist/web/standalone/.next/build-manifest.json +2 -2
  79. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  80. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  83. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  91. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/index.html +1 -1
  97. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app-paths-manifest.json +4 -4
  104. package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
  105. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  107. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  108. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  109. package/package.json +1 -1
  110. package/packages/cloud-mcp-gateway/package.json +2 -2
  111. package/packages/contracts/package.json +1 -1
  112. package/packages/daemon/package.json +4 -4
  113. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
  114. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  115. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
  116. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  117. package/packages/gsd-agent-core/package.json +5 -5
  118. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
  119. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
  120. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
  121. package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
  122. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
  123. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  124. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
  125. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
  126. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
  127. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  128. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
  129. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
  130. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
  131. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  132. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
  133. package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
  134. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
  135. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
  136. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
  137. package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
  138. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  139. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  140. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
  141. package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
  142. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
  143. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  144. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
  145. package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  146. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  147. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -1
  148. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  149. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
  150. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
  151. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
  152. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
  153. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
  154. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
  155. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
  156. package/packages/gsd-agent-modes/package.json +7 -7
  157. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  158. package/packages/mcp-server/dist/workflow-tools.js +10 -5
  159. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  160. package/packages/mcp-server/package.json +3 -3
  161. package/packages/native/package.json +1 -1
  162. package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
  163. package/packages/pi-agent-core/dist/harness/skills.js +6 -0
  164. package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
  165. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
  166. package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
  167. package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
  168. package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
  169. package/packages/pi-agent-core/package.json +1 -1
  170. package/packages/pi-ai/dist/models.generated.d.ts +8 -59
  171. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  172. package/packages/pi-ai/dist/models.generated.js +21 -72
  173. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  174. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  175. package/packages/pi-ai/dist/providers/anthropic.js +50 -0
  176. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  177. package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
  178. package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
  179. package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
  180. package/packages/pi-ai/dist/types.d.ts +2 -0
  181. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  182. package/packages/pi-ai/dist/types.js.map +1 -1
  183. package/packages/pi-ai/package.json +1 -1
  184. package/packages/pi-coding-agent/README.md +1 -1
  185. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
  186. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  188. package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
  189. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  190. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
  192. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  193. package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
  194. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  195. package/packages/pi-coding-agent/dist/core/skills.js +3 -0
  196. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  197. package/packages/pi-coding-agent/package.json +7 -7
  198. package/packages/pi-tui/package.json +1 -1
  199. package/packages/rpc-client/package.json +2 -2
  200. package/pkg/package.json +1 -1
  201. package/src/resources/extensions/context7/index.ts +15 -2
  202. package/src/resources/extensions/get-secrets-from-user.ts +17 -16
  203. package/src/resources/extensions/google-cli/index.ts +34 -0
  204. package/src/resources/extensions/google-cli/models.ts +57 -0
  205. package/src/resources/extensions/google-cli/package.json +11 -0
  206. package/src/resources/extensions/google-cli/readiness.ts +15 -0
  207. package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
  208. package/src/resources/extensions/gsd/auto/loop.ts +74 -1
  209. package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
  210. package/src/resources/extensions/gsd/auto/phases.ts +46 -0
  211. package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
  212. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  213. package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
  214. package/src/resources/extensions/gsd/auto-post-unit.ts +43 -14
  215. package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
  216. package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
  217. package/src/resources/extensions/gsd/auto-start.ts +307 -56
  218. package/src/resources/extensions/gsd/auto.ts +6 -1
  219. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
  220. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +9 -4
  221. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
  222. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +18 -6
  223. package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
  224. package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
  225. package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
  226. package/src/resources/extensions/gsd/commands-usage.ts +110 -5
  227. package/src/resources/extensions/gsd/config-overlay.ts +19 -16
  228. package/src/resources/extensions/gsd/context-overlay.ts +24 -19
  229. package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
  230. package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
  231. package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
  232. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  233. package/src/resources/extensions/gsd/doctor.ts +6 -1
  234. package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
  235. package/src/resources/extensions/gsd/guided-flow.ts +5 -6
  236. package/src/resources/extensions/gsd/key-manager.ts +57 -14
  237. package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
  238. package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
  239. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
  240. package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
  241. package/src/resources/extensions/gsd/preferences.ts +17 -2
  242. package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
  243. package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
  244. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
  245. package/src/resources/extensions/gsd/prompts/system.md +1 -3
  246. package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
  247. package/src/resources/extensions/gsd/repository-registry.ts +3 -1
  248. package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -4
  249. package/src/resources/extensions/gsd/skill-activation.ts +292 -0
  250. package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
  251. package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
  252. package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
  253. package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
  254. package/src/resources/extensions/gsd/skill-scope.ts +63 -0
  255. package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
  256. package/src/resources/extensions/gsd/skills.ts +75 -0
  257. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
  258. package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
  259. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
  260. package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
  261. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
  262. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +21 -0
  263. package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
  264. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +30 -0
  265. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
  266. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +12 -0
  267. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
  268. package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
  269. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
  270. package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
  271. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
  272. package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
  273. package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
  274. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
  275. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
  276. package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
  277. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
  278. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
  279. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
  280. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +30 -0
  281. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
  282. package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
  283. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
  284. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
  285. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
  286. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
  287. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
  288. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
  289. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
  290. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
  291. package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
  292. package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
  293. package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
  294. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
  295. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
  296. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +19 -0
  297. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
  298. package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
  299. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
  300. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
  301. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
  302. package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
  303. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
  304. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +74 -1
  305. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
  306. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
  307. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
  308. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
  309. package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
  310. package/src/resources/extensions/gsd/tools/exec-tool.ts +42 -10
  311. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
  312. package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
  313. package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
  314. package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
  315. package/src/resources/extensions/gsd/vision-ask.ts +28 -0
  316. package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
  317. package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
  318. package/src/resources/extensions/search-the-web/native-search.ts +60 -8
  319. package/src/resources/extensions/shared/confirm-ui.ts +8 -12
  320. package/src/resources/extensions/shared/dialog-frame.ts +71 -0
  321. package/src/resources/extensions/shared/interview-ui.ts +43 -42
  322. package/src/resources/extensions/shared/next-action-ui.ts +6 -6
  323. package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
  324. package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
  325. package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
  326. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
  327. /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → _LIEWYP8ISVAPKAEEXxFr}/_buildManifest.js +0 -0
  328. /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → _LIEWYP8ISVAPKAEEXxFr}/_ssgManifest.js +0 -0
@@ -191,6 +191,32 @@ test("resolveAgentEnd resolves a pending runUnit promise", async () => {
191
191
  assert.deepEqual(result.event, event);
192
192
  });
193
193
 
194
+ test("runUnit clears scoped skill visibility after a manifest-scoped unit completes", async () => {
195
+ _resetPendingResolve();
196
+
197
+ const ctx = makeMockCtx();
198
+ const pi = makeMockPi();
199
+ const skillVisibilityCalls: Array<string[] | undefined> = [];
200
+ let visibleSkills: string[] | undefined;
201
+ pi.setVisibleSkills = (names: string[] | undefined) => {
202
+ visibleSkills = names;
203
+ skillVisibilityCalls.push(names);
204
+ };
205
+ const s = makeMockSession();
206
+
207
+ const resultPromise = runUnit(ctx, pi, s, "plan-slice", "M001/S01", "prompt");
208
+
209
+ await new Promise((r) => setTimeout(r, 10));
210
+ assert.ok(Array.isArray(visibleSkills), "unit dispatch should scope skills before the turn starts");
211
+
212
+ resolveAgentEnd(makeEvent());
213
+
214
+ const result = await resultPromise;
215
+ assert.equal(result.status, "completed");
216
+ assert.equal(visibleSkills, undefined);
217
+ assert.equal(skillVisibilityCalls.at(-1), undefined);
218
+ });
219
+
194
220
  test("runUnit honors ScheduleWakeup by continuing the same unit session", async () => {
195
221
  _resetPendingResolve();
196
222
  _resetAutoWakeupsForTest();
@@ -1773,6 +1799,11 @@ test("autoLoop dev path dispatches orchestration.advance results without legacy
1773
1799
  const ctx = makeMockCtx();
1774
1800
  ctx.ui.setStatus = () => {};
1775
1801
  ctx.sessionManager = { getSessionFile: () => "/tmp/session.json" };
1802
+ ctx.modelRegistry = {
1803
+ getAvailable: () => [{ provider: "test", id: "hook-model" }],
1804
+ getProviderAuthMode: () => undefined,
1805
+ isProviderRequestReady: () => true,
1806
+ };
1776
1807
  const pi = makeMockPi();
1777
1808
  const stateSnapshot = {
1778
1809
  phase: "executing",
@@ -1784,6 +1815,7 @@ test("autoLoop dev path dispatches orchestration.advance results without legacy
1784
1815
  } as any;
1785
1816
  let advanceCalls = 0;
1786
1817
  const finalizedUnits: string[] = [];
1818
+ const journalEvents: any[] = [];
1787
1819
  let s: any;
1788
1820
  s = makeLoopSession({
1789
1821
  currentMilestoneId: "M002",
@@ -1821,6 +1853,15 @@ test("autoLoop dev path dispatches orchestration.advance results without legacy
1821
1853
  deps.callLog.push("resolveDispatch");
1822
1854
  throw new Error("legacy resolveDispatch must not run when orchestration is wired");
1823
1855
  },
1856
+ runPreDispatchHooks: () => ({
1857
+ firedHooks: ["complete-slice-policies"],
1858
+ action: "proceed",
1859
+ prompt: "hooked prompt",
1860
+ model: "hook-model",
1861
+ }),
1862
+ emitJournalEvent: (entry: any) => {
1863
+ journalEvents.push(entry);
1864
+ },
1824
1865
  postUnitPostVerification: async () => {
1825
1866
  deps.callLog.push("postUnitPostVerification");
1826
1867
  s.active = false;
@@ -1841,11 +1882,115 @@ test("autoLoop dev path dispatches orchestration.advance results without legacy
1841
1882
  );
1842
1883
  assert.equal(
1843
1884
  (pi.calls[0] as any[])[0].content,
1844
- "advance prompt",
1845
- "runUnit should receive the dispatch prompt captured by advance()",
1885
+ "hooked prompt",
1886
+ "runUnit should receive the dispatch prompt after pre-dispatch hooks",
1887
+ );
1888
+ assert.deepEqual(
1889
+ pi.setModelCalls.map((call: any[]) => call[0]),
1890
+ [
1891
+ { provider: "test", id: "hook-model" },
1892
+ { provider: "test", id: "hook-model" },
1893
+ ],
1894
+ "proceed hooks should apply model overrides before dispatch",
1846
1895
  );
1847
1896
  assert.deepEqual(finalizedUnits, ["execute-task:M002/S03/T05"]);
1848
1897
  assert.equal(s.pendingOrchestrationDispatch, null, "pending dispatch should be one-shot");
1898
+ assert.equal(
1899
+ journalEvents.filter((entry) => entry.eventType === "pre-dispatch-hook").length,
1900
+ 1,
1901
+ "hook dispatch should emit one pre-dispatch-hook journal event",
1902
+ );
1903
+ });
1904
+
1905
+ test("autoLoop pauses once when orchestration reports reconciliation drift error", async () => {
1906
+ _resetPendingResolve();
1907
+
1908
+ const ctx = makeMockCtx();
1909
+ ctx.ui.setStatus = () => {};
1910
+ ctx.sessionManager = { getSessionFile: () => "/tmp/session.json" };
1911
+ const pi = makeMockPi();
1912
+ let advanceCalls = 0;
1913
+ const s = makeLoopSession({
1914
+ currentMilestoneId: "M002",
1915
+ orchestration: {
1916
+ start: async () => ({ kind: "stopped" as const, reason: "unused" }),
1917
+ advance: async () => {
1918
+ advanceCalls++;
1919
+ return {
1920
+ kind: "error" as const,
1921
+ reason: "Reconciliation drift: Reconciliation repair failed in pass 0",
1922
+ };
1923
+ },
1924
+ completeActiveUnit: async () => {},
1925
+ retryActiveUnit: async () => {},
1926
+ resume: async () => ({ kind: "stopped" as const, reason: "unused" }),
1927
+ stop: async () => ({ kind: "stopped" as const, reason: "unused" }),
1928
+ getStatus: () => ({ phase: "error" as const, transitionCount: 1 }),
1929
+ },
1930
+ });
1931
+
1932
+ const deps = makeMockDeps({
1933
+ resolveDispatch: async () => {
1934
+ deps.callLog.push("resolveDispatch");
1935
+ throw new Error("legacy resolveDispatch must not run after orchestration error");
1936
+ },
1937
+ });
1938
+
1939
+ await autoLoop(ctx, pi, s, deps);
1940
+
1941
+ assert.equal(advanceCalls, 1, "orchestration error must not be retried in the same loop");
1942
+ assert.ok(deps.callLog.includes("pauseAuto"), "orchestration error should pause auto-mode");
1943
+ assert.equal(
1944
+ deps.callLog.includes("resolveDispatch"),
1945
+ false,
1946
+ "orchestration error must not fall back to legacy dispatch",
1947
+ );
1948
+ assert.equal(s.pendingOrchestrationDispatch, null, "no orchestration dispatch should remain pending");
1949
+ });
1950
+
1951
+ test("autoLoop retries next iteration when orchestration reports paused", async () => {
1952
+ _resetPendingResolve();
1953
+
1954
+ const ctx = makeMockCtx();
1955
+ ctx.ui.setStatus = () => {};
1956
+ ctx.sessionManager = { getSessionFile: () => "/tmp/session.json" };
1957
+ const pi = makeMockPi();
1958
+ let advanceCalls = 0;
1959
+ const s = makeLoopSession({
1960
+ currentMilestoneId: "M002",
1961
+ orchestration: {
1962
+ start: async () => ({ kind: "stopped" as const, reason: "unused" }),
1963
+ advance: async () => {
1964
+ advanceCalls++;
1965
+ return advanceCalls === 1
1966
+ ? { kind: "paused" as const, reason: "provider transient; retry" }
1967
+ : { kind: "stopped" as const, reason: "done retrying" };
1968
+ },
1969
+ completeActiveUnit: async () => {},
1970
+ retryActiveUnit: async () => {},
1971
+ resume: async () => ({ kind: "stopped" as const, reason: "unused" }),
1972
+ stop: async () => ({ kind: "stopped" as const, reason: "unused" }),
1973
+ getStatus: () => ({ phase: "running" as const, transitionCount: advanceCalls }),
1974
+ },
1975
+ });
1976
+
1977
+ const deps = makeMockDeps({
1978
+ resolveDispatch: async () => {
1979
+ deps.callLog.push("resolveDispatch");
1980
+ throw new Error("legacy resolveDispatch must not run after orchestration paused");
1981
+ },
1982
+ });
1983
+
1984
+ await autoLoop(ctx, pi, s, deps);
1985
+
1986
+ assert.equal(advanceCalls, 2, "orchestration paused should retry on the next loop iteration");
1987
+ assert.equal(deps.callLog.includes("pauseAuto"), false, "orchestration paused should not pause auto-mode");
1988
+ assert.equal(
1989
+ deps.callLog.includes("resolveDispatch"),
1990
+ false,
1991
+ "orchestration paused must not fall back to legacy dispatch",
1992
+ );
1993
+ assert.equal(s.pendingOrchestrationDispatch, null, "no orchestration dispatch should remain pending");
1849
1994
  });
1850
1995
 
1851
1996
  test("autoLoop consumes pending orchestration dispatch without advancing twice", async () => {
@@ -4453,6 +4598,101 @@ test("autoLoop rejects execute-task with 0 tool calls as hallucinated (#1833)",
4453
4598
  );
4454
4599
  });
4455
4600
 
4601
+ test("runUnitPhase retries 0-tool units with ordinary network-related assistant text", async (t) => {
4602
+ _resetPendingResolve();
4603
+
4604
+ const basePath = mkdtempSync(join(tmpdir(), "gsd-zero-tool-network-text-"));
4605
+ t.after(() => {
4606
+ rmSync(basePath, { recursive: true, force: true });
4607
+ });
4608
+
4609
+ const ctx = {
4610
+ ...makeMockCtx(),
4611
+ ui: {
4612
+ notify: () => {},
4613
+ setStatus: () => {},
4614
+ setWorkingMessage: () => {},
4615
+ },
4616
+ sessionManager: {
4617
+ getEntries: () => [],
4618
+ },
4619
+ modelRegistry: {
4620
+ getProviderAuthMode: () => undefined,
4621
+ isProviderRequestReady: () => true,
4622
+ },
4623
+ } as any;
4624
+ const pi = {
4625
+ ...makeMockPi(),
4626
+ sendMessage: () => {
4627
+ queueMicrotask(() => resolveAgentEnd(makeEvent([
4628
+ {
4629
+ role: "assistant",
4630
+ content: [
4631
+ { type: "text", text: "Error: I'll investigate the network error handling next." },
4632
+ ],
4633
+ },
4634
+ ])));
4635
+ },
4636
+ } as any;
4637
+ const s = makeLoopSession({
4638
+ basePath,
4639
+ canonicalProjectRoot: basePath,
4640
+ originalBasePath: basePath,
4641
+ });
4642
+ const mockLedger = {
4643
+ version: 1,
4644
+ projectStartedAt: Date.now(),
4645
+ units: [] as any[],
4646
+ };
4647
+ const deps = makeMockDeps({
4648
+ closeoutUnit: async () => {
4649
+ mockLedger.units.push({
4650
+ type: "execute-task",
4651
+ id: "M001/S01/T01",
4652
+ startedAt: s.currentUnit?.startedAt ?? Date.now(),
4653
+ toolCalls: 0,
4654
+ assistantMessages: 1,
4655
+ tokens: { input: 100, output: 20, total: 120, cacheRead: 0, cacheWrite: 0 },
4656
+ cost: 0.01,
4657
+ });
4658
+ },
4659
+ getLedger: () => mockLedger,
4660
+ });
4661
+ let seq = 0;
4662
+
4663
+ const result = await runUnitPhase(
4664
+ { ctx, pi, s, deps, prefs: undefined, iteration: 1, flowId: "flow-zero-tool-network-text", nextSeq: () => ++seq },
4665
+ {
4666
+ unitType: "execute-task",
4667
+ unitId: "M001/S01/T01",
4668
+ prompt: "do work",
4669
+ finalPrompt: "do work",
4670
+ pauseAfterUatDispatch: false,
4671
+ state: {
4672
+ phase: "executing",
4673
+ activeMilestone: { id: "M001", title: "Milestone" },
4674
+ activeSlice: { id: "S01", title: "Slice" },
4675
+ activeTask: { id: "T01", title: "Task" },
4676
+ registry: [{ id: "M001", title: "Milestone", status: "active" }],
4677
+ recentDecisions: [],
4678
+ blockers: [],
4679
+ nextAction: "",
4680
+ progress: { milestones: { done: 0, total: 1 } },
4681
+ requirements: { active: 0, validated: 0, deferred: 0, outOfScope: 0, blocked: 0, total: 0 },
4682
+ } as any,
4683
+ mid: "M001",
4684
+ midTitle: "Milestone",
4685
+ isRetry: false,
4686
+ previousTier: undefined,
4687
+ },
4688
+ { recentUnits: [{ key: "execute-task/M001/S01/T01" }], stuckRecoveryAttempts: 0, consecutiveFinalizeTimeouts: 0 },
4689
+ );
4690
+
4691
+ assert.equal(result.action, "retry");
4692
+ assert.equal((result as any).reason, "zero-tool-calls");
4693
+ assert.equal(deps.callLog.includes("pauseAuto"), false);
4694
+ });
4695
+
4456
4696
  test("autoLoop pauses user-driven deep question instead of flagging 0 tool calls", async () => {
4457
4697
  _resetPendingResolve();
4458
4698
 
@@ -4640,6 +4880,92 @@ test("autoLoop rejects complete-slice with 0 tool calls as context-exhausted (#2
4640
4880
  );
4641
4881
  });
4642
4882
 
4883
+ test("autoLoop pauses on zero-tool-call rate-limit assistant messages instead of immediate retry", async (t) => {
4884
+ _resetPendingResolve();
4885
+
4886
+ const basePath = mkdtempSync(join(tmpdir(), "gsd-zero-tool-rate-limit-"));
4887
+ t.after(() => {
4888
+ _resetPendingResolve();
4889
+ rmSync(basePath, { recursive: true, force: true });
4890
+ });
4891
+
4892
+ const originalSetTimeout = globalThis.setTimeout;
4893
+ const timers: Array<{ fn: () => void; delay: number }> = [];
4894
+ globalThis.setTimeout = ((fn: () => void, delay?: number) => {
4895
+ timers.push({ fn, delay: delay ?? 0 });
4896
+ return 0 as unknown as ReturnType<typeof setTimeout>;
4897
+ }) as typeof setTimeout;
4898
+
4899
+ try {
4900
+ const ctx = makeMockCtx();
4901
+ ctx.ui.setStatus = () => {};
4902
+ const notifications: string[] = [];
4903
+ ctx.ui.notify = (msg: string) => { notifications.push(msg); };
4904
+ ctx.sessionManager = { getSessionFile: () => "/tmp/session.json" };
4905
+ ctx.modelRegistry = {
4906
+ getProviderAuthMode: () => undefined,
4907
+ isProviderRequestReady: () => true,
4908
+ };
4909
+ const pi = makeMockPi();
4910
+ const s = makeLoopSession({
4911
+ basePath,
4912
+ canonicalProjectRoot: basePath,
4913
+ originalBasePath: basePath,
4914
+ });
4915
+
4916
+ const mockLedger = {
4917
+ version: 1,
4918
+ projectStartedAt: Date.now(),
4919
+ units: [] as any[],
4920
+ };
4921
+
4922
+ const deps = makeMockDeps({
4923
+ closeoutUnit: async () => {
4924
+ mockLedger.units.push({
4925
+ type: "execute-task",
4926
+ id: "M001/S01/T01",
4927
+ startedAt: s.currentUnit?.startedAt ?? Date.now(),
4928
+ toolCalls: 0,
4929
+ assistantMessages: 1,
4930
+ tokens: { input: 100, output: 100, total: 200, cacheRead: 0, cacheWrite: 0 },
4931
+ cost: 0.05,
4932
+ });
4933
+ },
4934
+ getLedger: () => mockLedger,
4935
+ });
4936
+
4937
+ const loopPromise = autoLoop(ctx as any, pi as any, s, deps);
4938
+
4939
+ await new Promise((r) => originalSetTimeout(r, 50));
4940
+ resolveAgentEnd(makeEvent([
4941
+ {
4942
+ role: "assistant",
4943
+ content: [{ type: "text", text: "You've hit your limit · resets Jun 1 at 8am" }],
4944
+ },
4945
+ ]));
4946
+
4947
+ await loopPromise;
4948
+
4949
+ assert.equal(deps.callLog.includes("pauseAuto"), true);
4950
+ assert.ok(
4951
+ timers.some((timer) => timer.delay === 60_000),
4952
+ "rate-limit message should schedule delayed auto-resume instead of immediate retry",
4953
+ );
4954
+ assert.ok(
4955
+ notifications.some((msg) => msg.includes("Auto-resuming in 60s")),
4956
+ "rate-limit pause should announce delayed resume",
4957
+ );
4958
+ assert.ok(
4959
+ !notifications.some((msg) => msg.includes("context exhaustion")),
4960
+ "rate-limit message should not be classified as context exhaustion",
4961
+ );
4962
+ const deriveCount = deps.callLog.filter((entry) => entry === "deriveState").length;
4963
+ assert.equal(deriveCount, 1, "loop should pause after first iteration instead of redispatching");
4964
+ } finally {
4965
+ globalThis.setTimeout = originalSetTimeout;
4966
+ }
4967
+ });
4968
+
4643
4969
  // ─── Worktree health check (#1833) ────────────────────────────────────────
4644
4970
 
4645
4971
  test("autoLoop stops when Worktree Safety finds no .git marker for execute-task (#1833)", async (t) => {
@@ -592,6 +592,27 @@ test("retryActiveUnit clears in-flight idempotency without marking the unit fina
592
592
  assert.equal(prepareCalls, 2, "retry should intentionally redispatch the same unit");
593
593
  });
594
594
 
595
+ test("retryActiveUnit clears finalized same-unit guard for post-hook retries", async () => {
596
+ const { deps, calls } = makeDeps();
597
+ const orchestrator = createAutoOrchestrator(deps);
598
+
599
+ const first = await orchestrator.advance();
600
+ assert.equal(first.kind, "advanced");
601
+ if (first.kind !== "advanced") throw new Error("expected first advance");
602
+
603
+ await orchestrator.completeActiveUnit(first.unit);
604
+ await orchestrator.retryActiveUnit(first.unit);
605
+ const second = await orchestrator.advance();
606
+
607
+ assert.equal(second.kind, "advanced");
608
+ if (second.kind !== "advanced") throw new Error("expected retry advance");
609
+ assert.deepEqual(second.unit, first.unit);
610
+ assert.ok(calls.includes("journal:unit-finalized"));
611
+ assert.ok(calls.includes("journal:unit-retry"));
612
+ const prepareCalls = calls.filter((c) => c === "worktree.prepare").length;
613
+ assert.equal(prepareCalls, 2, "post-hook retry should redispatch the finalized unit");
614
+ });
615
+
595
616
  test("resume() re-enters running phase", async () => {
596
617
  const { deps } = makeDeps();
597
618
  const orchestrator = createAutoOrchestrator(deps);
@@ -1,9 +1,13 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { mkdtempSync, mkdirSync } from "node:fs";
3
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
- import { _describeArtifactVerificationFailureForTest } from "../auto-post-unit.ts";
6
+ import {
7
+ _describeArtifactVerificationFailureForTest,
8
+ maybeWriteParallelResearchCostSpikeBlocker,
9
+ } from "../auto-post-unit.ts";
10
+ import { resolveExpectedArtifactPath } from "../auto-recovery.ts";
7
11
 
8
12
  test("missing execute-task artifact includes completion contract and completion-tool hint", () => {
9
13
  const base = mkdtempSync(join(tmpdir(), "gsd-artifact-diag-"));
@@ -30,3 +34,25 @@ test("missing execute-task artifact skips completion-tool hint when completion t
30
34
  assert.match(msg, /was not found on disk after unit execution/);
31
35
  assert.doesNotMatch(msg, /No completion tool call detected \(`gsd_task_complete`\/alias\)/);
32
36
  });
37
+
38
+ test("parallel research cost spike writes durable PARALLEL-BLOCKER", () => {
39
+ const base = mkdtempSync(join(tmpdir(), "gsd-parallel-cost-blocker-"));
40
+ try {
41
+ mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
42
+ const blocker = maybeWriteParallelResearchCostSpikeBlocker(
43
+ "research-slice",
44
+ "M001/parallel-research",
45
+ base,
46
+ 3.73,
47
+ 1.02,
48
+ );
49
+
50
+ const expected = resolveExpectedArtifactPath("research-slice", "M001/parallel-research", base);
51
+ assert.match(blocker ?? "", /M001-PARALLEL-BLOCKER\.md/);
52
+ assert.ok(expected);
53
+ assert.equal(existsSync(expected!), true);
54
+ assert.match(readFileSync(expected!, "utf-8"), /cost spike detected \(3\.73 vs avg 1\.02\)/);
55
+ } finally {
56
+ rmSync(base, { recursive: true, force: true });
57
+ }
58
+ });
@@ -58,3 +58,33 @@ test("detects top-level bash tool call via toolName field", () => {
58
58
 
59
59
  assert.equal(_hasExecutionToolCallsInSessionForTest(entries), true);
60
60
  });
61
+
62
+ test("detects session execution tools supported by the evidence collector", () => {
63
+ const entries = [
64
+ {
65
+ type: "message",
66
+ message: {
67
+ role: "assistant",
68
+ content: [
69
+ {
70
+ type: "toolCall",
71
+ toolName: "async_bash",
72
+ arguments: { command: "npm test" },
73
+ },
74
+ {
75
+ type: "toolCall",
76
+ toolName: "PowerShell",
77
+ arguments: { command: "Get-ChildItem" },
78
+ },
79
+ {
80
+ type: "toolCall",
81
+ toolName: "functions.exec_command",
82
+ arguments: { cmd: "pnpm test" },
83
+ },
84
+ ],
85
+ },
86
+ },
87
+ ];
88
+
89
+ assert.equal(_hasExecutionToolCallsInSessionForTest(entries), true);
90
+ });
@@ -1837,3 +1837,44 @@ test("#4414: verifyExpectedArtifact parallel-research succeeds when all research
1837
1837
  cleanup(base);
1838
1838
  }
1839
1839
  });
1840
+
1841
+ test("parallel-research verification accepts canonical project artifacts from a worktree base", () => {
1842
+ const base = makeTmpBase();
1843
+ try {
1844
+ const milestoneDir = join(base, ".gsd", "milestones", "M001");
1845
+ mkdirSync(join(milestoneDir, "slices", "S02", "tasks"), { recursive: true });
1846
+ mkdirSync(join(milestoneDir, "slices", "S03", "tasks"), { recursive: true });
1847
+
1848
+ writeFileSync(
1849
+ join(milestoneDir, "M001-ROADMAP.md"),
1850
+ [
1851
+ "# M001: Regression",
1852
+ "",
1853
+ "## Slices",
1854
+ "",
1855
+ "- [ ] **S01: Alpha** `risk:low` `depends:[]`",
1856
+ "- [ ] **S02: Beta** `risk:low` `depends:[]`",
1857
+ "- [ ] **S03: Gamma** `risk:low` `depends:[]`",
1858
+ "",
1859
+ ].join("\n"),
1860
+ "utf-8",
1861
+ );
1862
+ writeFileSync(join(milestoneDir, "M001-RESEARCH.md"), "# milestone research\n", "utf-8");
1863
+ writeFileSync(join(milestoneDir, "slices", "S02", "S02-RESEARCH.md"), "# research\n", "utf-8");
1864
+ writeFileSync(join(milestoneDir, "slices", "S03", "S03-RESEARCH.md"), "# research\n", "utf-8");
1865
+
1866
+ const worktree = join(base, ".gsd", "worktrees", "M001");
1867
+ mkdirSync(join(worktree, ".gsd", "milestones", "M001"), { recursive: true });
1868
+ writeFileSync(join(worktree, ".git"), "gitdir: ../../../../.git/worktrees/M001\n", "utf-8");
1869
+
1870
+ clearParseCache();
1871
+ invalidateAllCaches();
1872
+ assert.equal(
1873
+ verifyExpectedArtifact("research-slice", "M001/parallel-research", worktree),
1874
+ true,
1875
+ "worktree verification should use the same canonical artifacts as dispatch",
1876
+ );
1877
+ } finally {
1878
+ cleanup(base);
1879
+ }
1880
+ });
@@ -95,4 +95,16 @@ describe("evidence-collector: toolCallId-based matching (A-3)", () => {
95
95
  assert.equal(entries[1].kind, "bash");
96
96
  assert.equal(entries[1].command, "npm run build");
97
97
  });
98
+
99
+ it("treats Codex exec_command tool names as execution evidence", () => {
100
+ recordToolCall("tc-exec", "exec_command", { cmd: "pnpm test" });
101
+ recordToolCall("tc-namespaced-exec", "functions.exec_command", { cmd: "pnpm lint" });
102
+
103
+ const entries = getEvidence() as readonly BashEvidence[];
104
+ assert.equal(entries.length, 2);
105
+ assert.equal(entries[0].kind, "bash");
106
+ assert.equal(entries[0].command, "pnpm test");
107
+ assert.equal(entries[1].kind, "bash");
108
+ assert.equal(entries[1].command, "pnpm lint");
109
+ });
98
110
  });