@opengsd/gsd-pi 1.1.1-dev.616a1a1 → 1.1.1-dev.75048e7

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 (452) hide show
  1. package/dist/cli.js +3 -2
  2. package/dist/help-text.js +10 -6
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +495 -0
  5. package/dist/resources/extensions/browser-tools/engine/selection.js +16 -0
  6. package/dist/resources/extensions/browser-tools/extension-manifest.json +2 -2
  7. package/dist/resources/extensions/browser-tools/index.js +57 -9
  8. package/dist/resources/extensions/browser-tools/package.json +5 -1
  9. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +167 -16
  10. package/dist/resources/extensions/gsd/auto/orchestrator.js +0 -1
  11. package/dist/resources/extensions/gsd/auto/phases.js +4 -3
  12. package/dist/resources/extensions/gsd/auto-dashboard.js +92 -17
  13. package/dist/resources/extensions/gsd/auto-dispatch.js +55 -0
  14. package/dist/resources/extensions/gsd/auto-post-unit.js +134 -10
  15. package/dist/resources/extensions/gsd/auto-prompts.js +72 -22
  16. package/dist/resources/extensions/gsd/auto-recovery.js +7 -8
  17. package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
  18. package/dist/resources/extensions/gsd/auto-start.js +94 -15
  19. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  20. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +18 -65
  21. package/dist/resources/extensions/gsd/auto-worktree.js +18 -5
  22. package/dist/resources/extensions/gsd/auto.js +31 -6
  23. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +89 -4
  24. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +43 -0
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +56 -20
  26. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +33 -38
  27. package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
  28. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +61 -0
  29. package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
  30. package/dist/resources/extensions/gsd/commands/handlers/core.js +6 -2
  31. package/dist/resources/extensions/gsd/commands/handlers/ops.js +9 -5
  32. package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
  33. package/dist/resources/extensions/gsd/commands-maintenance.js +172 -2
  34. package/dist/resources/extensions/gsd/commands-mcp-status.js +109 -60
  35. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +3 -1
  36. package/dist/resources/extensions/gsd/commands-verdict.js +1 -1
  37. package/dist/resources/extensions/gsd/config-overlay.js +2 -1
  38. package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  40. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
  41. package/dist/resources/extensions/gsd/error-classifier.js +2 -1
  42. package/dist/resources/extensions/gsd/escalation.js +4 -4
  43. package/dist/resources/extensions/gsd/exec-sandbox.js +2 -0
  44. package/dist/resources/extensions/gsd/forensics.js +74 -2
  45. package/dist/resources/extensions/gsd/gsd-db.js +42 -6
  46. package/dist/resources/extensions/gsd/guided-flow.js +119 -176
  47. package/dist/resources/extensions/gsd/mcp-filter.js +3 -0
  48. package/dist/resources/extensions/gsd/mcp-project-config.js +76 -84
  49. package/dist/resources/extensions/gsd/memory-store.js +4 -1
  50. package/dist/resources/extensions/gsd/migration-auto-check.js +2 -2
  51. package/dist/resources/extensions/gsd/milestone-closeout.js +3 -1
  52. package/dist/resources/extensions/gsd/pending-auto-start.js +0 -1
  53. package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
  54. package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
  55. package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
  56. package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
  57. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  58. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  59. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  60. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  61. package/dist/resources/extensions/gsd/prompts/run-uat.md +33 -23
  62. package/dist/resources/extensions/gsd/prompts/system.md +3 -1
  63. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  64. package/dist/resources/extensions/gsd/recovery-classification.js +20 -0
  65. package/dist/resources/extensions/gsd/rule-registry.js +428 -52
  66. package/dist/resources/extensions/gsd/safety/destructive-guard.js +3 -0
  67. package/dist/resources/extensions/gsd/skill-activation.js +20 -3
  68. package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +4 -2
  69. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +1 -1
  70. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +18 -1
  71. package/dist/resources/extensions/gsd/state-reconciliation/index.js +6 -0
  72. package/dist/resources/extensions/gsd/state.js +17 -14
  73. package/dist/resources/extensions/gsd/templates/plan.md +3 -1
  74. package/dist/resources/extensions/gsd/tool-contract.js +5 -0
  75. package/dist/resources/extensions/gsd/tool-presentation-plan.js +143 -0
  76. package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
  77. package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
  78. package/dist/resources/extensions/gsd/tools/exec-tool.js +109 -0
  79. package/dist/resources/extensions/gsd/tools/plan-slice.js +14 -9
  80. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  81. package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
  82. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +483 -6
  83. package/dist/resources/extensions/gsd/unit-context-manifest.js +8 -3
  84. package/dist/resources/extensions/gsd/unit-tool-contracts.js +169 -0
  85. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  86. package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
  87. package/dist/resources/extensions/gsd/verification-gate.js +72 -1
  88. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -1
  89. package/dist/resources/extensions/gsd/workflow-mcp.js +5 -73
  90. package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -0
  91. package/dist/resources/extensions/mcp-client/manager.js +31 -1
  92. package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
  93. package/dist/rtk.d.ts +7 -1
  94. package/dist/rtk.js +27 -11
  95. package/dist/update-check.d.ts +15 -1
  96. package/dist/update-check.js +87 -12
  97. package/dist/update-cmd.d.ts +1 -0
  98. package/dist/update-cmd.js +53 -2
  99. package/dist/web/standalone/.next/BUILD_ID +1 -1
  100. package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
  101. package/dist/web/standalone/.next/build-manifest.json +2 -2
  102. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  103. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  104. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  112. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  120. package/dist/web/standalone/.next/server/app/index.html +1 -1
  121. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  126. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app-paths-manifest.json +5 -5
  128. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  129. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  131. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  132. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  133. package/package.json +5 -3
  134. package/packages/cloud-mcp-gateway/package.json +2 -2
  135. package/packages/contracts/dist/workflow.d.ts +14 -0
  136. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  137. package/packages/contracts/dist/workflow.js +16 -0
  138. package/packages/contracts/dist/workflow.js.map +1 -1
  139. package/packages/contracts/package.json +1 -1
  140. package/packages/daemon/package.json +4 -4
  141. package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
  142. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  143. package/packages/gsd-agent-core/dist/agent-session.js +32 -0
  144. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  145. package/packages/gsd-agent-core/dist/index.d.ts +1 -0
  146. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  147. package/packages/gsd-agent-core/dist/index.js +1 -0
  148. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  149. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
  150. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
  151. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
  152. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
  153. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
  154. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  155. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  156. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  157. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
  158. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  159. package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
  160. package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
  161. package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
  162. package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
  163. package/packages/gsd-agent-core/package.json +6 -6
  164. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
  165. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
  166. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
  167. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
  168. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  169. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  170. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  171. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  172. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  173. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  174. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  175. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
  176. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  177. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +92 -31
  178. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  179. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  180. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
  181. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  182. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
  183. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
  184. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
  185. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.d.ts.map +1 -1
  186. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js +2 -0
  187. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  188. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -1
  189. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
  190. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -1
  191. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
  192. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  193. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +1 -0
  194. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  195. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  196. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +5 -0
  197. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  198. package/packages/gsd-agent-modes/package.json +7 -7
  199. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  200. package/packages/mcp-server/dist/remote-questions.js +23 -9
  201. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  202. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  203. package/packages/mcp-server/dist/workflow-tools.js +84 -2
  204. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  205. package/packages/mcp-server/package.json +3 -3
  206. package/packages/native/package.json +1 -1
  207. package/packages/pi-agent-core/dist/agent-loop.js +42 -3
  208. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  209. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  210. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  211. package/packages/pi-agent-core/dist/agent.js +2 -0
  212. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  213. package/packages/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  214. package/packages/pi-agent-core/dist/harness/agent-harness.js +3 -1
  215. package/packages/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  216. package/packages/pi-agent-core/dist/harness/types.d.ts +1 -0
  217. package/packages/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  218. package/packages/pi-agent-core/dist/harness/types.js.map +1 -1
  219. package/packages/pi-agent-core/dist/types.d.ts +6 -1
  220. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  221. package/packages/pi-agent-core/dist/types.js.map +1 -1
  222. package/packages/pi-agent-core/package.json +1 -1
  223. package/packages/pi-ai/dist/api-registry.d.ts +2 -0
  224. package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
  225. package/packages/pi-ai/dist/api-registry.js +23 -0
  226. package/packages/pi-ai/dist/api-registry.js.map +1 -1
  227. package/packages/pi-ai/dist/image-models.generated.d.ts +15 -0
  228. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  229. package/packages/pi-ai/dist/image-models.generated.js +15 -0
  230. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  231. package/packages/pi-ai/dist/models.generated.d.ts +411 -39
  232. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  233. package/packages/pi-ai/dist/models.generated.js +504 -153
  234. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  235. package/packages/pi-ai/dist/stream.js +6 -6
  236. package/packages/pi-ai/dist/stream.js.map +1 -1
  237. package/packages/pi-ai/package.json +1 -1
  238. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +3 -0
  239. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  240. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  242. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  243. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  244. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  245. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  246. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  247. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  248. package/packages/pi-coding-agent/dist/core/tools/bash.js +2 -2
  249. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  250. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  251. package/packages/pi-coding-agent/dist/core/tools/edit.js +3 -2
  252. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  253. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts +1 -0
  254. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
  255. package/packages/pi-coding-agent/dist/core/tools/render-utils.js +6 -0
  256. package/packages/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
  257. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/core/tools/write.js +3 -2
  259. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  260. package/packages/pi-coding-agent/package.json +7 -7
  261. package/packages/pi-tui/dist/terminal.d.ts +1 -0
  262. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  263. package/packages/pi-tui/dist/terminal.js +8 -4
  264. package/packages/pi-tui/dist/terminal.js.map +1 -1
  265. package/packages/pi-tui/package.json +1 -1
  266. package/packages/rpc-client/package.json +2 -2
  267. package/pkg/package.json +1 -1
  268. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
  269. package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
  270. package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
  271. package/src/resources/extensions/browser-tools/index.ts +60 -9
  272. package/src/resources/extensions/browser-tools/package.json +5 -1
  273. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
  274. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
  275. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +196 -16
  276. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +239 -63
  277. package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
  278. package/src/resources/extensions/gsd/auto/phases.ts +5 -3
  279. package/src/resources/extensions/gsd/auto-dashboard.ts +98 -18
  280. package/src/resources/extensions/gsd/auto-dispatch.ts +67 -0
  281. package/src/resources/extensions/gsd/auto-post-unit.ts +166 -9
  282. package/src/resources/extensions/gsd/auto-prompts.ts +106 -15
  283. package/src/resources/extensions/gsd/auto-recovery.ts +7 -7
  284. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
  285. package/src/resources/extensions/gsd/auto-start.ts +112 -17
  286. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  287. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +43 -73
  288. package/src/resources/extensions/gsd/auto-worktree.ts +23 -5
  289. package/src/resources/extensions/gsd/auto.ts +47 -5
  290. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +96 -4
  291. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +51 -0
  292. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +81 -25
  293. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +70 -63
  294. package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
  295. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +137 -0
  296. package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
  297. package/src/resources/extensions/gsd/commands/handlers/core.ts +6 -2
  298. package/src/resources/extensions/gsd/commands/handlers/ops.ts +9 -5
  299. package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
  300. package/src/resources/extensions/gsd/commands-maintenance.ts +197 -2
  301. package/src/resources/extensions/gsd/commands-mcp-status.ts +136 -58
  302. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +4 -1
  303. package/src/resources/extensions/gsd/commands-verdict.ts +1 -1
  304. package/src/resources/extensions/gsd/config-overlay.ts +3 -1
  305. package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
  306. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  307. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
  308. package/src/resources/extensions/gsd/error-classifier.ts +2 -1
  309. package/src/resources/extensions/gsd/escalation.ts +4 -4
  310. package/src/resources/extensions/gsd/exec-sandbox.ts +4 -0
  311. package/src/resources/extensions/gsd/forensics.ts +99 -5
  312. package/src/resources/extensions/gsd/gsd-db.ts +46 -8
  313. package/src/resources/extensions/gsd/guided-flow.ts +215 -217
  314. package/src/resources/extensions/gsd/mcp-filter.ts +3 -0
  315. package/src/resources/extensions/gsd/mcp-project-config.ts +105 -88
  316. package/src/resources/extensions/gsd/memory-store.ts +4 -1
  317. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  318. package/src/resources/extensions/gsd/milestone-closeout.ts +3 -1
  319. package/src/resources/extensions/gsd/pending-auto-start.ts +0 -2
  320. package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
  321. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  322. package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
  323. package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
  324. package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
  325. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  326. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  327. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  328. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  329. package/src/resources/extensions/gsd/prompts/run-uat.md +33 -23
  330. package/src/resources/extensions/gsd/prompts/system.md +3 -1
  331. package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  332. package/src/resources/extensions/gsd/recovery-classification.ts +20 -0
  333. package/src/resources/extensions/gsd/rule-registry.ts +558 -58
  334. package/src/resources/extensions/gsd/rule-types.ts +2 -0
  335. package/src/resources/extensions/gsd/safety/destructive-guard.ts +3 -0
  336. package/src/resources/extensions/gsd/skill-activation.ts +20 -2
  337. package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +4 -2
  338. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +1 -1
  339. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +20 -0
  340. package/src/resources/extensions/gsd/state-reconciliation/index.ts +6 -0
  341. package/src/resources/extensions/gsd/state-reconciliation/types.ts +1 -0
  342. package/src/resources/extensions/gsd/state.ts +18 -14
  343. package/src/resources/extensions/gsd/templates/plan.md +3 -1
  344. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +156 -4
  345. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +123 -0
  346. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +10 -2
  347. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +4 -1
  348. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +143 -2
  349. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +24 -2
  350. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +12 -2
  351. package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
  352. package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +9 -15
  353. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +26 -16
  354. package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +21 -0
  355. package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +38 -3
  356. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +6 -2
  357. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
  358. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  359. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
  360. package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
  361. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +8 -0
  362. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +50 -13
  363. package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
  364. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +40 -1
  365. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +60 -0
  366. package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
  367. package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
  368. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +18 -0
  369. package/src/resources/extensions/gsd/tests/exec-tool.test.ts +69 -0
  370. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
  371. package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
  372. package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
  373. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +31 -79
  374. package/src/resources/extensions/gsd/tests/gsd-rebuild.test.ts +199 -0
  375. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +75 -0
  376. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
  377. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
  378. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +5 -3
  379. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +40 -4
  380. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
  381. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
  382. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +8 -0
  383. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +16 -0
  384. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +72 -10
  385. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +13 -6
  386. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +15 -0
  387. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +100 -0
  388. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +179 -0
  389. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
  390. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +63 -0
  391. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +10 -1
  392. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +3 -3
  393. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +9 -1
  394. package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
  395. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +54 -7
  396. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
  397. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +39 -1
  398. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
  399. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
  400. package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
  401. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +83 -1
  402. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
  403. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +18 -1
  404. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
  405. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +36 -0
  406. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +79 -0
  407. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +1 -1
  408. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
  409. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +4 -0
  410. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +36 -0
  411. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
  412. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +55 -0
  413. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +6 -2
  414. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +191 -0
  415. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +84 -10
  416. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  417. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +12 -2
  418. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
  419. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +29 -6
  420. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +29 -6
  421. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
  422. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
  423. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +21 -0
  424. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
  425. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +17 -2
  426. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +493 -0
  427. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +40 -0
  428. package/src/resources/extensions/gsd/tool-contract.ts +6 -0
  429. package/src/resources/extensions/gsd/tool-presentation-plan.ts +223 -0
  430. package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
  431. package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
  432. package/src/resources/extensions/gsd/tools/exec-tool.ts +130 -0
  433. package/src/resources/extensions/gsd/tools/plan-slice.ts +14 -9
  434. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  435. package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
  436. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +589 -8
  437. package/src/resources/extensions/gsd/types.ts +69 -5
  438. package/src/resources/extensions/gsd/unit-context-manifest.ts +14 -5
  439. package/src/resources/extensions/gsd/unit-tool-contracts.ts +186 -0
  440. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  441. package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
  442. package/src/resources/extensions/gsd/verification-gate.ts +87 -1
  443. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -1
  444. package/src/resources/extensions/gsd/workflow-mcp.ts +5 -73
  445. package/src/resources/extensions/gsd/worktree-lifecycle.ts +26 -0
  446. package/src/resources/extensions/mcp-client/manager.ts +33 -1
  447. package/src/resources/extensions/mcp-client/tests/manager.test.ts +35 -0
  448. package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
  449. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +0 -246
  450. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +0 -218
  451. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → h4TGni4xJzlZjGkxaT6uU}/_buildManifest.js +0 -0
  452. /package/dist/web/standalone/.next/static/{L9N5SPFi7f-Ne4u2uXzCe → h4TGni4xJzlZjGkxaT6uU}/_ssgManifest.js +0 -0
@@ -49,6 +49,8 @@ import {
49
49
  import { loadEffectiveGSDPreferences, getIsolationMode } from "./preferences.js";
50
50
  import { invalidateAllCaches } from "./cache.js";
51
51
  import { resolveMilestoneFile } from "./paths.js";
52
+ import { getMilestone, insertMilestone, isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
53
+ import { isClosedStatus } from "./status-guards.js";
52
54
  import type { WorktreeStateProjection } from "./worktree-state-projection.js";
53
55
  import { createWorkspace, scopeMilestone } from "./workspace.js";
54
56
  // ADR-016 phase 2 / C1 (#5624): file-system + git-CLI leaf primitives
@@ -85,6 +87,28 @@ export function resetRecentWorktreeMergeFailuresForTest(): void {
85
87
  recentWorktreeMergeFailures.clear();
86
88
  }
87
89
 
90
+ function markMilestoneClosedAfterMerge(milestoneId: string, completedAt: string): void {
91
+ if (!isDbAvailable()) return;
92
+ try {
93
+ const existing = getMilestone(milestoneId);
94
+ if (!existing) {
95
+ insertMilestone({ id: milestoneId, title: milestoneId, status: "complete" });
96
+ updateMilestoneStatus(milestoneId, "complete", completedAt);
97
+ invalidateAllCaches();
98
+ return;
99
+ }
100
+ if (!isClosedStatus(existing.status)) {
101
+ updateMilestoneStatus(milestoneId, "complete", completedAt);
102
+ invalidateAllCaches();
103
+ }
104
+ } catch (err) {
105
+ logWarning(
106
+ "worktree",
107
+ `Merged ${milestoneId} but failed to mark milestone complete in DB: ${err instanceof Error ? err.message : String(err)}`,
108
+ );
109
+ }
110
+ }
111
+
88
112
  // ─── Types ───────────────────────────────────────────────────────────────
89
113
 
90
114
  export interface NotifyCtx {
@@ -1716,6 +1740,8 @@ export class WorktreeLifecycle {
1716
1740
 
1717
1741
  // #4764 — record merge completion. Only reaches here when an actual
1718
1742
  // merge ran; failure paths throw out before this point.
1743
+ const mergeCompletedAt = new Date().toISOString();
1744
+ markMilestoneClosedAfterMerge(milestoneId, mergeCompletedAt);
1719
1745
  try {
1720
1746
  emitWorktreeMerged(
1721
1747
  this.s.originalBasePath || this.s.basePath,
@@ -103,6 +103,8 @@ const CHILD_ENV_ALLOWLIST = new Set([
103
103
  "XDG_CACHE_HOME",
104
104
  ]);
105
105
 
106
+ const MCP_STDERR_MAX_BYTES = 4096;
107
+
106
108
  let cachedStatus: ManagedMcpStatus | null = null;
107
109
  let cachedStatusKey = "";
108
110
 
@@ -231,6 +233,34 @@ export function resolveMcpString(value: string): string {
231
233
  );
232
234
  }
233
235
 
236
+ function captureTransportStderr(transport: StdioClientTransport): () => string {
237
+ const chunks: Buffer[] = [];
238
+ let totalBytes = 0;
239
+ const stderr = transport.stderr;
240
+ stderr?.on("data", (chunk: Buffer | string) => {
241
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
242
+ totalBytes += buffer.byteLength;
243
+ chunks.push(buffer);
244
+ while (chunks.reduce((sum, entry) => sum + entry.byteLength, 0) > MCP_STDERR_MAX_BYTES) {
245
+ chunks.shift();
246
+ }
247
+ });
248
+
249
+ return () => {
250
+ const captured = Buffer.concat(chunks).toString("utf-8").trim();
251
+ if (!captured) return "";
252
+ return totalBytes > MCP_STDERR_MAX_BYTES
253
+ ? `[stderr truncated to last ${MCP_STDERR_MAX_BYTES} bytes]\n${captured}`
254
+ : captured;
255
+ };
256
+ }
257
+
258
+ function formatConnectionError(error: unknown, stderr: string): string {
259
+ const message = error instanceof Error ? error.message : String(error);
260
+ if (!stderr) return message;
261
+ return `${message}\nStderr:\n${stderr}`;
262
+ }
263
+
234
264
  export function upsertProjectLocalMcpServer(
235
265
  input: ManagedMcpServerInput,
236
266
  options: { projectDir?: string; previousName?: string } = {},
@@ -348,6 +378,7 @@ export async function testMcpServerConnection(
348
378
 
349
379
  const client = new Client({ name: "gsd", version: "1.0.0" });
350
380
  let transport: StdioClientTransport | StreamableHTTPClientTransport | undefined;
381
+ let readCapturedStderr: (() => string) | undefined;
351
382
  const timeout = options.timeoutMs ?? 30_000;
352
383
  try {
353
384
  if (config.transport === "stdio") {
@@ -358,6 +389,7 @@ export async function testMcpServerConnection(
358
389
  cwd: config.cwd,
359
390
  stderr: "pipe",
360
391
  });
392
+ readCapturedStderr = captureTransportStderr(transport);
361
393
  } else {
362
394
  const resolvedUrl = resolveMcpString(config.url ?? "");
363
395
  transport = new StreamableHTTPClientTransport(
@@ -385,7 +417,7 @@ export async function testMcpServerConnection(
385
417
  toolCount: 0,
386
418
  tools: [],
387
419
  warnings: config.envWarnings,
388
- error: error instanceof Error ? error.message : String(error),
420
+ error: formatConnectionError(error, readCapturedStderr?.() ?? ""),
389
421
  };
390
422
  } finally {
391
423
  if (transport) {
@@ -163,3 +163,38 @@ test("MCP connection test performs handshake and tools/list without invoking too
163
163
  cleanup();
164
164
  }
165
165
  });
166
+
167
+ test("MCP connection test includes stdio stderr when discovery fails", async () => {
168
+ const { projectDir, cleanup } = makeProject();
169
+ try {
170
+ const serverPath = join(projectDir, "crashing-mcp-server.mjs");
171
+ writeFileSync(
172
+ serverPath,
173
+ [
174
+ 'console.error("fatal browser bootstrap failed");',
175
+ 'console.error("missing browser profile");',
176
+ "process.exit(1);",
177
+ ].join("\n"),
178
+ "utf-8",
179
+ );
180
+
181
+ const result = await testMcpServerConnection({
182
+ name: "crashing",
183
+ transport: "stdio",
184
+ sourcePath: join(projectDir, ".gsd", "mcp.json"),
185
+ sourceKind: "project-local",
186
+ disabled: false,
187
+ command: process.execPath,
188
+ args: [serverPath],
189
+ envWarnings: [],
190
+ } satisfies ManagedMcpServerConfig, { projectDir, timeoutMs: 10_000 });
191
+
192
+ assert.equal(result.ok, false);
193
+ assert.match(result.error ?? "", /Connection closed|closed|exit/i);
194
+ assert.match(result.error ?? "", /Stderr:/);
195
+ assert.match(result.error ?? "", /fatal browser bootstrap failed/);
196
+ assert.match(result.error ?? "", /missing browser profile/);
197
+ } finally {
198
+ cleanup();
199
+ }
200
+ });
@@ -0,0 +1,172 @@
1
+ import { createHash } from "node:crypto";
2
+ import { execFileSync } from "node:child_process";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { createRequire } from "node:module";
5
+ import { basename, resolve } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ export const GSD_BROWSER_MCP_SERVER_NAME = "gsd-browser";
9
+
10
+ export interface GsdBrowserMcpLaunchConfig {
11
+ serverName: string;
12
+ command: string;
13
+ args: string[];
14
+ cwd: string;
15
+ env?: Record<string, string>;
16
+ projectRoot: string;
17
+ sessionName: string;
18
+ }
19
+
20
+ export interface GsdBrowserMcpLaunchOptions {
21
+ sessionName?: string;
22
+ sessionSuffix?: string;
23
+ }
24
+
25
+ function parseJsonEnv<T>(env: NodeJS.ProcessEnv, name: string): T | undefined {
26
+ const raw = env[name];
27
+ if (!raw) return undefined;
28
+ try {
29
+ return JSON.parse(raw) as T;
30
+ } catch {
31
+ throw new Error(`Invalid JSON in ${name}`);
32
+ }
33
+ }
34
+
35
+ function sanitizeSessionSegment(value: string): string {
36
+ return value
37
+ .replace(/[^a-zA-Z0-9._-]+/g, "-")
38
+ .replace(/^-+|-+$/g, "")
39
+ .slice(0, 40);
40
+ }
41
+
42
+ function compareSemverLocal(a: string, b: string): number {
43
+ const left = a.split(".").map(Number);
44
+ const right = b.split(".").map(Number);
45
+ for (let index = 0; index < Math.max(left.length, right.length); index++) {
46
+ const leftValue = left[index] || 0;
47
+ const rightValue = right[index] || 0;
48
+ if (leftValue > rightValue) return 1;
49
+ if (leftValue < rightValue) return -1;
50
+ }
51
+ return 0;
52
+ }
53
+
54
+ function parseGsdBrowserVersion(output: string): string | null {
55
+ return output.match(/\b(\d+\.\d+\.\d+)\b/)?.[1] ?? null;
56
+ }
57
+
58
+ function resolveBundledGsdBrowserPackageVersion(): string | null {
59
+ try {
60
+ const requireFromHere = createRequire(import.meta.url);
61
+ const packageJsonPath = requireFromHere.resolve("@opengsd/gsd-browser/package.json");
62
+ const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as { version?: unknown };
63
+ return typeof pkg.version === "string" ? parseGsdBrowserVersion(pkg.version) : null;
64
+ } catch {
65
+ return null;
66
+ }
67
+ }
68
+
69
+ function resolvePathGsdBrowserVersion(env: NodeJS.ProcessEnv): string | null {
70
+ const explicit = env.GSD_BROWSER_PATH_VERSION?.trim();
71
+ if (explicit) return parseGsdBrowserVersion(explicit);
72
+
73
+ try {
74
+ return parseGsdBrowserVersion(execFileSync("gsd-browser", ["--version"], {
75
+ encoding: "utf-8",
76
+ env,
77
+ stdio: ["ignore", "pipe", "ignore"],
78
+ timeout: 2000,
79
+ }));
80
+ } catch {
81
+ return null;
82
+ }
83
+ }
84
+
85
+ function shouldPreferPathGsdBrowser(env: NodeJS.ProcessEnv): boolean {
86
+ const pathVersion = resolvePathGsdBrowserVersion(env);
87
+ if (!pathVersion) return false;
88
+
89
+ const bundledVersion = resolveBundledGsdBrowserPackageVersion();
90
+ return !bundledVersion || compareSemverLocal(pathVersion, bundledVersion) > 0;
91
+ }
92
+
93
+ export function resolveBundledGsdBrowserCliPath(env: NodeJS.ProcessEnv = process.env): string | null {
94
+ const explicit = env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim();
95
+ if (explicit) return explicit;
96
+
97
+ try {
98
+ const requireFromHere = createRequire(import.meta.url);
99
+ const packageJsonPath = requireFromHere.resolve("@opengsd/gsd-browser/package.json");
100
+ const candidate = resolve(packageJsonPath, "..", "bin", "gsd-browser");
101
+ if (existsSync(candidate)) return candidate;
102
+ } catch {
103
+ // Fall through to path candidates for source/dist layouts.
104
+ }
105
+
106
+ const candidates = [
107
+ resolve(fileURLToPath(new URL("../../../../node_modules/@opengsd/gsd-browser/bin/gsd-browser", import.meta.url))),
108
+ resolve(fileURLToPath(new URL("../../../../node_modules/.bin/gsd-browser", import.meta.url))),
109
+ ];
110
+
111
+ for (const candidate of candidates) {
112
+ if (existsSync(candidate)) return candidate;
113
+ }
114
+
115
+ return null;
116
+ }
117
+
118
+ export function buildGsdBrowserSessionName(projectRoot: string, suffix?: string): string {
119
+ const resolvedProjectRoot = resolve(projectRoot);
120
+ const base = sanitizeSessionSegment(basename(resolvedProjectRoot)) || "project";
121
+ const hash = createHash("sha1").update(resolvedProjectRoot).digest("hex").slice(0, 8);
122
+ const cleanSuffix = suffix ? sanitizeSessionSegment(suffix) : "";
123
+ return cleanSuffix ? `gsd-${base}-${hash}-${cleanSuffix}` : `gsd-${base}-${hash}`;
124
+ }
125
+
126
+ export function resolveGsdBrowserMcpLaunchConfig(
127
+ projectRoot: string,
128
+ env: NodeJS.ProcessEnv = process.env,
129
+ options: GsdBrowserMcpLaunchOptions = {},
130
+ ): GsdBrowserMcpLaunchConfig {
131
+ const resolvedProjectRoot = resolve(projectRoot);
132
+ const serverName = env.GSD_BROWSER_MCP_NAME?.trim() || GSD_BROWSER_MCP_SERVER_NAME;
133
+ const explicitArgs = parseJsonEnv<unknown>(env, "GSD_BROWSER_MCP_ARGS");
134
+ const explicitEnv = parseJsonEnv<Record<string, string>>(env, "GSD_BROWSER_MCP_ENV");
135
+ const explicitCommand = env.GSD_BROWSER_MCP_COMMAND?.trim();
136
+ const explicitCliPath = env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim();
137
+ const preferPathCli = !explicitCommand && !explicitCliPath && shouldPreferPathGsdBrowser(env);
138
+ const bundledCliPath = !explicitCommand && !explicitCliPath && !preferPathCli
139
+ ? resolveBundledGsdBrowserCliPath(env)
140
+ : null;
141
+ const sessionName =
142
+ options.sessionName?.trim() || buildGsdBrowserSessionName(resolvedProjectRoot, options.sessionSuffix);
143
+ const command =
144
+ explicitCommand
145
+ || explicitCliPath
146
+ || (preferPathCli ? "gsd-browser" : undefined)
147
+ || (bundledCliPath ? process.execPath : undefined)
148
+ || "gsd-browser";
149
+ const args = Array.isArray(explicitArgs) && explicitArgs.length > 0
150
+ ? explicitArgs.map(String)
151
+ : [
152
+ ...(bundledCliPath ? [bundledCliPath] : []),
153
+ "mcp",
154
+ "--session",
155
+ sessionName,
156
+ "--identity-scope",
157
+ "project",
158
+ "--identity-project",
159
+ resolvedProjectRoot,
160
+ ];
161
+ const cwd = env.GSD_BROWSER_MCP_CWD?.trim() || resolvedProjectRoot;
162
+
163
+ return {
164
+ serverName,
165
+ command,
166
+ args,
167
+ cwd,
168
+ ...(explicitEnv ? { env: explicitEnv } : {}),
169
+ projectRoot: resolvedProjectRoot,
170
+ sessionName,
171
+ };
172
+ }
@@ -1,246 +0,0 @@
1
- // gsd-pi + Gate 1b recovery bound corrections — regression tests for the two bugs
2
- // found in peer review of the H1 fix (commit f0e1d42a2):
3
- // 1. Escalation message must describe /gsd (counter reset) AND /gsd-debug (diagnose).
4
- // 2. planBlockedRecoveryCount must NOT increment when pi.sendMessage throws.
5
-
6
- import { describe, test, beforeEach, afterEach } from "node:test";
7
- import assert from "node:assert/strict";
8
- import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
9
- import { join } from "node:path";
10
- import { tmpdir } from "node:os";
11
-
12
- import {
13
- checkAutoStartAfterDiscuss,
14
- setPendingAutoStart,
15
- clearPendingAutoStart,
16
- _getPendingAutoStart,
17
- } from "../guided-flow.ts";
18
- import { drainLogs } from "../workflow-logger.ts";
19
- import {
20
- openDatabase,
21
- closeDatabase,
22
- insertMilestone,
23
- } from "../gsd-db.ts";
24
-
25
- // ─── Harness ───────────────────────────────────────────────────────────────
26
-
27
- interface MockCapture {
28
- notifies: Array<{ msg: string; level: string }>;
29
- messages: Array<{ payload: any; options: any }>;
30
- }
31
-
32
- function mkCapture(): MockCapture {
33
- return { notifies: [], messages: [] };
34
- }
35
-
36
- function mkCtx(cap: MockCapture): any {
37
- return {
38
- ui: {
39
- notify: (msg: string, level: string) => {
40
- cap.notifies.push({ msg, level });
41
- },
42
- },
43
- };
44
- }
45
-
46
- /** Returns a pi stub whose sendMessage throws on the first call, succeeds after. */
47
- function mkPiThrowOnce(cap: MockCapture): any {
48
- let callCount = 0;
49
- return {
50
- sendMessage: (payload: any, options: any) => {
51
- callCount += 1;
52
- if (callCount === 1) {
53
- throw new Error("transient network error");
54
- }
55
- cap.messages.push({ payload, options });
56
- },
57
- setActiveTools: () => undefined,
58
- getActiveTools: () => [],
59
- };
60
- }
61
-
62
- function mkPi(cap: MockCapture): any {
63
- return {
64
- sendMessage: (payload: any, options: any) => {
65
- cap.messages.push({ payload, options });
66
- },
67
- setActiveTools: () => undefined,
68
- getActiveTools: () => [],
69
- };
70
- }
71
-
72
- function mkBase(): string {
73
- const base = mkdtempSync(join(tmpdir(), "gsd-gate1b-corrections-"));
74
- mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
75
- writeFileSync(
76
- join(base, ".gsd", "milestones", "M001", "M001-CONTEXT.md"),
77
- "# M001: Corrections Test\n\nContext written by discuss phase.\n",
78
- );
79
- return base;
80
- }
81
-
82
- // ─── Tests ─────────────────────────────────────────────────────────────────
83
-
84
- describe("Gate 1b recovery bound corrections", () => {
85
- let base: string;
86
- let cap: MockCapture;
87
-
88
- beforeEach(() => {
89
- clearPendingAutoStart();
90
- drainLogs();
91
- });
92
-
93
- afterEach(() => {
94
- closeDatabase();
95
- clearPendingAutoStart();
96
- if (base) {
97
- rmSync(base, { recursive: true, force: true });
98
- }
99
- });
100
-
101
- // ── Fix 1: escalation message ──────────────────────────────────────────
102
-
103
- test("escalation message describes /gsd for reset AND /gsd-debug for diagnosis", () => {
104
- base = mkBase();
105
- openDatabase(":memory:");
106
- insertMilestone({ id: "M001", title: "Corrections Test", status: "queued" });
107
-
108
- cap = mkCapture();
109
- setPendingAutoStart(base, {
110
- basePath: base,
111
- milestoneId: "M001",
112
- ctx: mkCtx(cap),
113
- pi: mkPi(cap),
114
- });
115
-
116
- // Exhaust the recovery budget (MAX = 3)
117
- checkAutoStartAfterDiscuss(); // count → 1
118
- checkAutoStartAfterDiscuss(); // count → 2
119
- checkAutoStartAfterDiscuss(); // count → 3
120
-
121
- cap.notifies = [];
122
- drainLogs();
123
-
124
- // This call hits the cap and must escalate
125
- const result = checkAutoStartAfterDiscuss();
126
- assert.equal(result, false, "escalation call must return false");
127
-
128
- const errorNotify = cap.notifies.find((n) => n.level === "error");
129
- assert.ok(errorNotify, "escalation must emit a notify with level 'error'");
130
-
131
- // Must mention /gsd with reset semantics
132
- assert.match(
133
- errorNotify.msg,
134
- /\/gsd\b/,
135
- "escalation message must reference /gsd (the command that resets the counter)",
136
- );
137
- assert.match(
138
- errorNotify.msg,
139
- /reset/i,
140
- "escalation message must use the word 'reset' so users know /gsd resets the counter",
141
- );
142
-
143
- // Must also mention /gsd-debug
144
- assert.match(
145
- errorNotify.msg,
146
- /\/gsd-debug/i,
147
- "escalation message must also reference /gsd-debug for diagnosis",
148
- );
149
-
150
- // Must NOT suggest /gsd-debug alone as the sole remediation
151
- assert.doesNotMatch(
152
- errorNotify.msg,
153
- /^[^/]*\/gsd-debug[^/]*$/,
154
- "escalation message must not mention /gsd-debug as the only option",
155
- );
156
- });
157
-
158
- // ── Fix 2: counter ordering ────────────────────────────────────────────
159
-
160
- test("counter stays at 0 when sendMessage throws on the first call", () => {
161
- base = mkBase();
162
- openDatabase(":memory:");
163
- insertMilestone({ id: "M001", title: "Corrections Test", status: "queued" });
164
-
165
- cap = mkCapture();
166
- setPendingAutoStart(base, {
167
- basePath: base,
168
- milestoneId: "M001",
169
- ctx: mkCtx(cap),
170
- pi: mkPiThrowOnce(cap),
171
- });
172
-
173
- // First call: sendMessage throws — counter must NOT increment
174
- const result = checkAutoStartAfterDiscuss();
175
- assert.equal(result, false, "must return false even when sendMessage throws");
176
-
177
- const entry = _getPendingAutoStart(base);
178
- assert.ok(entry, "entry must still exist after a failed sendMessage");
179
- assert.equal(
180
- entry.planBlockedRecoveryCount,
181
- 0,
182
- "counter must remain 0 when sendMessage throws — no budget burned by transient failure",
183
- );
184
- });
185
-
186
- test("counter increments to 1 on the second call when first sendMessage threw", () => {
187
- base = mkBase();
188
- openDatabase(":memory:");
189
- insertMilestone({ id: "M001", title: "Corrections Test", status: "queued" });
190
-
191
- cap = mkCapture();
192
- setPendingAutoStart(base, {
193
- basePath: base,
194
- milestoneId: "M001",
195
- ctx: mkCtx(cap),
196
- pi: mkPiThrowOnce(cap),
197
- });
198
-
199
- checkAutoStartAfterDiscuss(); // sendMessage throws → count stays 0
200
-
201
- const entryAfterThrow = _getPendingAutoStart(base);
202
- assert.equal(entryAfterThrow!.planBlockedRecoveryCount, 0, "count is 0 after throw");
203
-
204
- checkAutoStartAfterDiscuss(); // sendMessage succeeds → count becomes 1
205
- assert.equal(cap.messages.length, 1, "second call must produce one successful sendMessage");
206
-
207
- const entryAfterSuccess = _getPendingAutoStart(base);
208
- assert.equal(
209
- entryAfterSuccess!.planBlockedRecoveryCount,
210
- 1,
211
- "counter must be 1 after first successful dispatch",
212
- );
213
- });
214
-
215
- test("3 successful sendMessage calls exhaust the budget; 4th emits escalation notify", () => {
216
- base = mkBase();
217
- openDatabase(":memory:");
218
- insertMilestone({ id: "M001", title: "Corrections Test", status: "queued" });
219
-
220
- cap = mkCapture();
221
- setPendingAutoStart(base, {
222
- basePath: base,
223
- milestoneId: "M001",
224
- ctx: mkCtx(cap),
225
- pi: mkPi(cap),
226
- });
227
-
228
- // Three successful recoveries
229
- checkAutoStartAfterDiscuss(); // count → 1
230
- checkAutoStartAfterDiscuss(); // count → 2
231
- checkAutoStartAfterDiscuss(); // count → 3
232
-
233
- const entry = _getPendingAutoStart(base);
234
- assert.equal(entry!.planBlockedRecoveryCount, 3, "counter must be 3 after three successes");
235
- assert.equal(cap.messages.length, 3, "three sendMessage calls must have occurred");
236
-
237
- // Fourth call hits the cap
238
- cap.notifies = [];
239
- cap.messages = [];
240
- const resultAtCap = checkAutoStartAfterDiscuss();
241
- assert.equal(resultAtCap, false, "4th call must return false");
242
- assert.equal(cap.messages.length, 0, "4th call must NOT call sendMessage");
243
- const errorNotify = cap.notifies.find((n) => n.level === "error");
244
- assert.ok(errorNotify, "4th call must emit escalation notify with level 'error'");
245
- });
246
- });