@opengsd/gsd-pi 1.1.1-dev.74e8dd1 → 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 (329) 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/gsd/auto/orchestrator.js +0 -1
  10. package/dist/resources/extensions/gsd/auto-dashboard.js +77 -13
  11. package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
  12. package/dist/resources/extensions/gsd/auto-post-unit.js +21 -3
  13. package/dist/resources/extensions/gsd/auto-prompts.js +63 -22
  14. package/dist/resources/extensions/gsd/auto-recovery.js +3 -4
  15. package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
  16. package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
  17. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +18 -66
  18. package/dist/resources/extensions/gsd/auto-worktree.js +18 -5
  19. package/dist/resources/extensions/gsd/auto.js +9 -2
  20. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +20 -14
  21. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +28 -13
  22. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +18 -29
  23. package/dist/resources/extensions/gsd/browser-evidence.js +29 -2
  24. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +61 -0
  25. package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
  26. package/dist/resources/extensions/gsd/commands-handlers.js +76 -11
  27. package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -1
  28. package/dist/resources/extensions/gsd/dashboard-overlay.js +21 -7
  29. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  30. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +2 -2
  31. package/dist/resources/extensions/gsd/escalation.js +4 -4
  32. package/dist/resources/extensions/gsd/forensics.js +74 -2
  33. package/dist/resources/extensions/gsd/gsd-db.js +5 -2
  34. package/dist/resources/extensions/gsd/guided-flow.js +118 -175
  35. package/dist/resources/extensions/gsd/mcp-project-config.js +9 -76
  36. package/dist/resources/extensions/gsd/memory-store.js +4 -1
  37. package/dist/resources/extensions/gsd/milestone-closeout.js +3 -1
  38. package/dist/resources/extensions/gsd/pending-auto-start.js +0 -1
  39. package/dist/resources/extensions/gsd/post-unit-hooks.js +9 -0
  40. package/dist/resources/extensions/gsd/preferences-validation.js +39 -0
  41. package/dist/resources/extensions/gsd/prompt-loader.js +7 -0
  42. package/dist/resources/extensions/gsd/prompts/forensics.md +61 -1
  43. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  44. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  45. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  46. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  47. package/dist/resources/extensions/gsd/prompts/run-uat.md +25 -21
  48. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  49. package/dist/resources/extensions/gsd/recovery-classification.js +20 -0
  50. package/dist/resources/extensions/gsd/rule-registry.js +428 -52
  51. package/dist/resources/extensions/gsd/state.js +2 -2
  52. package/dist/resources/extensions/gsd/templates/plan.md +3 -1
  53. package/dist/resources/extensions/gsd/tool-contract.js +5 -0
  54. package/dist/resources/extensions/gsd/tool-presentation-plan.js +30 -7
  55. package/dist/resources/extensions/gsd/tools/complete-slice.js +15 -1
  56. package/dist/resources/extensions/gsd/tools/complete-task.js +11 -1
  57. package/dist/resources/extensions/gsd/tools/validate-milestone.js +46 -16
  58. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +132 -18
  59. package/dist/resources/extensions/gsd/unit-tool-contracts.js +169 -0
  60. package/dist/resources/extensions/gsd/verdict-parser.js +59 -15
  61. package/dist/resources/extensions/gsd/verification-gate.js +72 -1
  62. package/dist/resources/extensions/gsd/workflow-mcp.js +3 -75
  63. package/dist/resources/extensions/shared/gsd-browser-cli.js +145 -0
  64. package/dist/rtk.d.ts +7 -1
  65. package/dist/rtk.js +27 -11
  66. package/dist/update-check.d.ts +15 -1
  67. package/dist/update-check.js +87 -12
  68. package/dist/update-cmd.d.ts +1 -0
  69. package/dist/update-cmd.js +53 -2
  70. package/dist/web/standalone/.next/BUILD_ID +1 -1
  71. package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
  72. package/dist/web/standalone/.next/build-manifest.json +2 -2
  73. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  74. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  75. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  83. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  84. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  85. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  86. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  87. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  88. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  89. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  90. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/index.html +1 -1
  92. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
  99. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  100. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  101. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  102. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  103. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  104. package/package.json +4 -2
  105. package/packages/cloud-mcp-gateway/package.json +2 -2
  106. package/packages/contracts/package.json +1 -1
  107. package/packages/daemon/package.json +4 -4
  108. package/packages/gsd-agent-core/dist/agent-session.d.ts +9 -0
  109. package/packages/gsd-agent-core/dist/agent-session.d.ts.map +1 -1
  110. package/packages/gsd-agent-core/dist/agent-session.js +32 -0
  111. package/packages/gsd-agent-core/dist/agent-session.js.map +1 -1
  112. package/packages/gsd-agent-core/dist/index.d.ts +1 -0
  113. package/packages/gsd-agent-core/dist/index.d.ts.map +1 -1
  114. package/packages/gsd-agent-core/dist/index.js +1 -0
  115. package/packages/gsd-agent-core/dist/index.js.map +1 -1
  116. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts +2 -0
  117. package/packages/gsd-agent-core/dist/session/agent-session-compaction.d.ts.map +1 -1
  118. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js +8 -2
  119. package/packages/gsd-agent-core/dist/session/agent-session-compaction.js.map +1 -1
  120. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts +7 -0
  121. package/packages/gsd-agent-core/dist/session/agent-session-host.d.ts.map +1 -1
  122. package/packages/gsd-agent-core/dist/session/agent-session-host.js.map +1 -1
  123. package/packages/gsd-agent-core/dist/session/agent-session-prompt.d.ts.map +1 -1
  124. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js +69 -1
  125. package/packages/gsd-agent-core/dist/session/agent-session-prompt.js.map +1 -1
  126. package/packages/gsd-agent-core/dist/turn-latency.d.ts +47 -0
  127. package/packages/gsd-agent-core/dist/turn-latency.d.ts.map +1 -0
  128. package/packages/gsd-agent-core/dist/turn-latency.js +123 -0
  129. package/packages/gsd-agent-core/dist/turn-latency.js.map +1 -0
  130. package/packages/gsd-agent-core/package.json +6 -6
  131. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts +21 -0
  132. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.d.ts.map +1 -0
  133. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js +213 -0
  134. package/packages/gsd-agent-modes/dist/modes/interactive/components/__prototype__/gsd-widget-prototype.js.map +1 -0
  135. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  136. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +5 -0
  137. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  138. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  139. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +20 -0
  140. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  141. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  142. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js +7 -1
  143. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  144. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.d.ts.map +1 -1
  145. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js +6 -0
  146. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-command-handlers.js.map +1 -1
  147. package/packages/gsd-agent-modes/package.json +7 -7
  148. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  149. package/packages/mcp-server/dist/remote-questions.js +23 -9
  150. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  151. package/packages/mcp-server/dist/workflow-tools.js +2 -2
  152. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  153. package/packages/mcp-server/package.json +3 -3
  154. package/packages/native/package.json +1 -1
  155. package/packages/pi-agent-core/dist/agent-loop.js +42 -3
  156. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  157. package/packages/pi-agent-core/dist/agent.d.ts +5 -1
  158. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  159. package/packages/pi-agent-core/dist/agent.js +2 -0
  160. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  161. package/packages/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  162. package/packages/pi-agent-core/dist/harness/agent-harness.js +3 -1
  163. package/packages/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  164. package/packages/pi-agent-core/dist/harness/types.d.ts +1 -0
  165. package/packages/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  166. package/packages/pi-agent-core/dist/harness/types.js.map +1 -1
  167. package/packages/pi-agent-core/dist/types.d.ts +6 -1
  168. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  169. package/packages/pi-agent-core/dist/types.js.map +1 -1
  170. package/packages/pi-agent-core/package.json +1 -1
  171. package/packages/pi-ai/dist/api-registry.d.ts +2 -0
  172. package/packages/pi-ai/dist/api-registry.d.ts.map +1 -1
  173. package/packages/pi-ai/dist/api-registry.js +23 -0
  174. package/packages/pi-ai/dist/api-registry.js.map +1 -1
  175. package/packages/pi-ai/dist/models.generated.d.ts +74 -23
  176. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  177. package/packages/pi-ai/dist/models.generated.js +82 -31
  178. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  179. package/packages/pi-ai/dist/stream.js +6 -6
  180. package/packages/pi-ai/dist/stream.js.map +1 -1
  181. package/packages/pi-ai/package.json +1 -1
  182. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +3 -0
  183. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -2
  187. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  188. package/packages/pi-coding-agent/dist/core/tools/bash.js +2 -2
  189. package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
  190. package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/tools/edit.js +3 -2
  192. package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  193. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts +1 -0
  194. package/packages/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
  195. package/packages/pi-coding-agent/dist/core/tools/render-utils.js +6 -0
  196. package/packages/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
  197. package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  198. package/packages/pi-coding-agent/dist/core/tools/write.js +3 -2
  199. package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  200. package/packages/pi-coding-agent/package.json +7 -7
  201. package/packages/pi-tui/package.json +1 -1
  202. package/packages/rpc-client/package.json +2 -2
  203. package/pkg/package.json +1 -1
  204. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +579 -0
  205. package/src/resources/extensions/browser-tools/engine/selection.ts +19 -0
  206. package/src/resources/extensions/browser-tools/extension-manifest.json +2 -2
  207. package/src/resources/extensions/browser-tools/index.ts +60 -9
  208. package/src/resources/extensions/browser-tools/package.json +5 -1
  209. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +35 -0
  210. package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +33 -0
  211. package/src/resources/extensions/gsd/auto/orchestrator.ts +0 -1
  212. package/src/resources/extensions/gsd/auto-dashboard.ts +82 -14
  213. package/src/resources/extensions/gsd/auto-dispatch.ts +19 -0
  214. package/src/resources/extensions/gsd/auto-post-unit.ts +28 -2
  215. package/src/resources/extensions/gsd/auto-prompts.ts +97 -15
  216. package/src/resources/extensions/gsd/auto-recovery.ts +3 -3
  217. package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
  218. package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
  219. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +43 -74
  220. package/src/resources/extensions/gsd/auto-worktree.ts +23 -5
  221. package/src/resources/extensions/gsd/auto.ts +12 -2
  222. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +20 -14
  223. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +32 -13
  224. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +50 -54
  225. package/src/resources/extensions/gsd/browser-evidence.ts +26 -2
  226. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +137 -0
  227. package/src/resources/extensions/gsd/commands/handlers/ops.ts +2 -2
  228. package/src/resources/extensions/gsd/commands-handlers.ts +76 -11
  229. package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -1
  230. package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -7
  231. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -0
  232. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +2 -2
  233. package/src/resources/extensions/gsd/escalation.ts +4 -4
  234. package/src/resources/extensions/gsd/forensics.ts +99 -5
  235. package/src/resources/extensions/gsd/gsd-db.ts +5 -2
  236. package/src/resources/extensions/gsd/guided-flow.ts +214 -216
  237. package/src/resources/extensions/gsd/mcp-project-config.ts +13 -78
  238. package/src/resources/extensions/gsd/memory-store.ts +4 -1
  239. package/src/resources/extensions/gsd/milestone-closeout.ts +3 -1
  240. package/src/resources/extensions/gsd/pending-auto-start.ts +0 -2
  241. package/src/resources/extensions/gsd/post-unit-hooks.ts +14 -1
  242. package/src/resources/extensions/gsd/preferences-validation.ts +36 -0
  243. package/src/resources/extensions/gsd/prompt-loader.ts +8 -0
  244. package/src/resources/extensions/gsd/prompts/forensics.md +61 -1
  245. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +3 -1
  246. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +3 -1
  247. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  248. package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -1
  249. package/src/resources/extensions/gsd/prompts/run-uat.md +25 -21
  250. package/src/resources/extensions/gsd/prompts/validate-milestone.md +3 -3
  251. package/src/resources/extensions/gsd/recovery-classification.ts +20 -0
  252. package/src/resources/extensions/gsd/rule-registry.ts +558 -58
  253. package/src/resources/extensions/gsd/rule-types.ts +2 -0
  254. package/src/resources/extensions/gsd/state.ts +2 -2
  255. package/src/resources/extensions/gsd/templates/plan.md +3 -1
  256. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +105 -4
  257. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +37 -0
  258. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +10 -2
  259. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +4 -1
  260. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +12 -2
  261. package/src/resources/extensions/gsd/tests/browser-evidence.test.ts +142 -0
  262. package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +9 -15
  263. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +26 -16
  264. package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +21 -0
  265. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +30 -0
  266. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  267. package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +45 -0
  268. package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +53 -0
  269. package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +31 -0
  270. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +40 -1
  271. package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +27 -0
  272. package/src/resources/extensions/gsd/tests/escalation.test.ts +16 -27
  273. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +20 -0
  274. package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +3 -0
  275. package/src/resources/extensions/gsd/tests/forensics-tool-scope.test.ts +69 -0
  276. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +31 -79
  277. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +40 -1
  278. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +86 -0
  279. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +5 -3
  280. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +40 -4
  281. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +12 -9
  282. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +4 -4
  283. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +8 -0
  284. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +16 -0
  285. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +72 -10
  286. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +32 -0
  287. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +2 -0
  288. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +39 -8
  289. package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +63 -0
  290. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +10 -1
  291. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +9 -1
  292. package/src/resources/extensions/gsd/tests/new-milestone-discuss-routing.test.ts +3 -3
  293. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +9 -0
  294. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +157 -0
  295. package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +179 -0
  296. package/src/resources/extensions/gsd/tests/preferences.test.ts +29 -0
  297. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +73 -1
  298. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +14 -0
  299. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +7 -8
  300. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +44 -0
  301. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +75 -0
  302. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +4 -0
  303. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +36 -0
  304. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +100 -0
  305. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +139 -0
  306. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -4
  307. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
  308. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +7 -1
  309. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +6 -3
  310. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +133 -0
  311. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +51 -0
  312. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +410 -0
  313. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -0
  314. package/src/resources/extensions/gsd/tool-contract.ts +6 -0
  315. package/src/resources/extensions/gsd/tool-presentation-plan.ts +63 -7
  316. package/src/resources/extensions/gsd/tools/complete-slice.ts +14 -1
  317. package/src/resources/extensions/gsd/tools/complete-task.ts +20 -2
  318. package/src/resources/extensions/gsd/tools/validate-milestone.ts +46 -15
  319. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +163 -20
  320. package/src/resources/extensions/gsd/types.ts +69 -5
  321. package/src/resources/extensions/gsd/unit-tool-contracts.ts +186 -0
  322. package/src/resources/extensions/gsd/verdict-parser.ts +54 -13
  323. package/src/resources/extensions/gsd/verification-gate.ts +87 -1
  324. package/src/resources/extensions/gsd/workflow-mcp.ts +3 -75
  325. package/src/resources/extensions/shared/gsd-browser-cli.ts +172 -0
  326. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +0 -246
  327. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +0 -218
  328. /package/dist/web/standalone/.next/static/{eRWf-RI9bzbrwEurm_3uI → h4TGni4xJzlZjGkxaT6uU}/_buildManifest.js +0 -0
  329. /package/dist/web/standalone/.next/static/{eRWf-RI9bzbrwEurm_3uI → h4TGni4xJzlZjGkxaT6uU}/_ssgManifest.js +0 -0
@@ -5,7 +5,62 @@
5
5
  * (e.g. `passed` → `pass`) are applied consistently across the codebase.
6
6
  */
7
7
  import { extractUatType } from "./files.js";
8
+ import { splitFrontmatter, parseFrontmatterMap } from "../shared/frontmatter.js";
9
+ import { parse as parseYaml } from "yaml";
10
+ function normalizeVerdict(value) {
11
+ if (typeof value !== "string")
12
+ return undefined;
13
+ let verdict = value.trim().toLowerCase();
14
+ if (!verdict)
15
+ return undefined;
16
+ if (verdict === "passed")
17
+ verdict = "pass";
18
+ return verdict;
19
+ }
20
+ function getCaseInsensitive(obj, key) {
21
+ const lowerKey = key.toLowerCase();
22
+ for (const [candidate, value] of Object.entries(obj)) {
23
+ if (candidate.toLowerCase() === lowerKey)
24
+ return value;
25
+ }
26
+ return undefined;
27
+ }
8
28
  // ── Verdict extraction ──────────────────────────────────────────────────
29
+ /**
30
+ * Extract and normalize the frontmatter `verdict` value.
31
+ *
32
+ * Supports both top-level `verdict` and the hook outcome shape
33
+ * `outcome.verdict`. Returns `undefined` when frontmatter is absent or has no
34
+ * verdict field.
35
+ */
36
+ export function extractFrontmatterVerdict(content) {
37
+ const [frontmatterLines] = splitFrontmatter(content);
38
+ if (!frontmatterLines)
39
+ return undefined;
40
+ try {
41
+ const parsed = parseYaml(frontmatterLines.join("\n"));
42
+ if (parsed && typeof parsed === "object") {
43
+ const root = parsed;
44
+ const topLevel = normalizeVerdict(getCaseInsensitive(root, "verdict"));
45
+ if (topLevel)
46
+ return topLevel;
47
+ const outcome = getCaseInsensitive(root, "outcome");
48
+ if (outcome && typeof outcome === "object") {
49
+ const nested = normalizeVerdict(getCaseInsensitive(outcome, "verdict"));
50
+ if (nested)
51
+ return nested;
52
+ }
53
+ }
54
+ }
55
+ catch {
56
+ // Fall through to the permissive parser used by legacy frontmatter paths.
57
+ }
58
+ const frontmatter = parseFrontmatterMap(frontmatterLines);
59
+ const topLevel = normalizeVerdict(getCaseInsensitive(frontmatter, "verdict"));
60
+ if (topLevel)
61
+ return topLevel;
62
+ return undefined;
63
+ }
9
64
  /**
10
65
  * Extract and normalize the `verdict` value from YAML frontmatter.
11
66
  *
@@ -17,25 +72,14 @@ import { extractUatType } from "./files.js";
17
72
  */
18
73
  export function extractVerdict(content) {
19
74
  // Primary: YAML frontmatter verdict (canonical format)
20
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
21
- if (fmMatch) {
22
- const verdictMatch = fmMatch[1].match(/verdict:\s*([\w-]+)/i);
23
- if (verdictMatch) {
24
- let v = verdictMatch[1].toLowerCase();
25
- if (v === "passed")
26
- v = "pass";
27
- return v;
28
- }
29
- return undefined;
30
- }
75
+ const [frontmatterLines] = splitFrontmatter(content);
76
+ if (frontmatterLines)
77
+ return extractFrontmatterVerdict(content);
31
78
  // Fallback: detect verdict in markdown body (LLM manual writes, #2960).
32
79
  // Matches patterns like: **Verdict:** PASS, **Verdict:** ✅ PASS, **Verdict** needs-remediation
33
80
  const bodyMatch = content.match(/\*\*Verdict:?\*\*\s*(?:✅\s*)?(\w[\w-]*)/i);
34
81
  if (bodyMatch) {
35
- let v = bodyMatch[1].toLowerCase();
36
- if (v === "passed")
37
- v = "pass";
38
- return v;
82
+ return normalizeVerdict(bodyMatch[1]);
39
83
  }
40
84
  return undefined;
41
85
  }
@@ -246,6 +246,76 @@ function hasUnsafeShellSyntax(cmd) {
246
246
  }
247
247
  return false;
248
248
  }
249
+ function splitLeadingShellWords(cmd) {
250
+ const words = [];
251
+ let current = "";
252
+ let inSingle = false;
253
+ let inDouble = false;
254
+ let escaped = false;
255
+ for (let i = 0; i < cmd.length; i += 1) {
256
+ const ch = cmd[i];
257
+ if (escaped) {
258
+ current += ch;
259
+ escaped = false;
260
+ continue;
261
+ }
262
+ if (ch === "\\" && !inSingle) {
263
+ escaped = true;
264
+ continue;
265
+ }
266
+ if (ch === "'" && !inDouble) {
267
+ inSingle = !inSingle;
268
+ continue;
269
+ }
270
+ if (ch === "\"" && !inSingle) {
271
+ inDouble = !inDouble;
272
+ continue;
273
+ }
274
+ if (!inSingle && !inDouble) {
275
+ if (/\s/.test(ch)) {
276
+ if (current) {
277
+ words.push(current);
278
+ current = "";
279
+ }
280
+ continue;
281
+ }
282
+ if ([";", "|", "&", "<", ">"].includes(ch)) {
283
+ break;
284
+ }
285
+ }
286
+ current += ch;
287
+ }
288
+ if (current) {
289
+ words.push(current);
290
+ }
291
+ return words;
292
+ }
293
+ function isCountFlag(token) {
294
+ return (token === "--count" ||
295
+ token.startsWith("--count=") ||
296
+ token === "--count-matches" ||
297
+ token.startsWith("--count-matches=") ||
298
+ /^-[A-Za-z]*c[A-Za-z]*$/.test(token));
299
+ }
300
+ function countSearchWarning(command, exitCode) {
301
+ if (exitCode !== 1)
302
+ return null;
303
+ const trimmed = command.trim();
304
+ if (trimmed.startsWith("!"))
305
+ return null;
306
+ const [tool, ...args] = splitLeadingShellWords(trimmed);
307
+ if (tool !== "grep" && tool !== "rg")
308
+ return null;
309
+ if (!args.some(isCountFlag))
310
+ return null;
311
+ return `verification-gate: warning: '${tool} -c' returns exit 1 when count=0; for absence checks use '! ${tool} -q ...' instead.`;
312
+ }
313
+ function appendStderrWarning(stderr, warning) {
314
+ if (!warning)
315
+ return stderr;
316
+ const trimmed = stderr.trimEnd();
317
+ return trimmed ? `${trimmed}\n${warning}` : warning;
318
+ }
249
319
  /**
250
320
  * Known executable first-tokens that are safe to run.
251
321
  * Lowercase commands, common build/test tools, and npm/yarn/pnpm invocations.
@@ -411,11 +481,12 @@ export function runVerificationGate(options) {
411
481
  exitCode = result.status ?? 1;
412
482
  stderr = truncate(result.stderr, MAX_OUTPUT_BYTES);
413
483
  }
484
+ const warning = countSearchWarning(command, exitCode);
414
485
  checks.push({
415
486
  command,
416
487
  exitCode,
417
488
  stdout: truncate(result.stdout, MAX_OUTPUT_BYTES),
418
- stderr,
489
+ stderr: truncate(appendStderrWarning(stderr, warning), MAX_OUTPUT_BYTES),
419
490
  durationMs,
420
491
  });
421
492
  }
@@ -2,7 +2,7 @@ import { execSync } from "node:child_process";
2
2
  import { existsSync, realpathSync } from "node:fs";
3
3
  import { dirname, resolve, sep } from "node:path";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
- import { RUN_UAT_WORKFLOW_TOOL_NAMES } from "./tool-presentation-plan.js";
5
+ import { getRequiredWorkflowToolsForUnit } from "./unit-tool-contracts.js";
6
6
  /** Session cwd may be a milestone worktree; MCP config and server discovery use the project root. */
7
7
  export function resolveWorkflowMcpProjectRoot(sessionCwd) {
8
8
  let resolved;
@@ -350,82 +350,10 @@ export function buildWorkflowMcpServers(projectRoot = process.cwd(), env = proce
350
350
  };
351
351
  }
352
352
  export function getRequiredWorkflowToolsForGuidedUnit(unitType) {
353
- switch (unitType) {
354
- case "discuss-project":
355
- return ["ask_user_questions", "gsd_summary_save"];
356
- case "discuss-requirements":
357
- return ["ask_user_questions", "gsd_requirement_save", "gsd_summary_save"];
358
- case "research-decision":
359
- return ["ask_user_questions"];
360
- case "discuss-milestone":
361
- return [
362
- "gsd_summary_save",
363
- "gsd_requirement_save",
364
- "gsd_requirement_update",
365
- "gsd_plan_milestone",
366
- "gsd_milestone_generate_id",
367
- ];
368
- case "discuss-slice":
369
- return ["gsd_summary_save"];
370
- case "research-milestone":
371
- case "research-slice":
372
- return ["gsd_summary_save"];
373
- case "plan-milestone":
374
- return ["gsd_plan_milestone"];
375
- case "plan-slice":
376
- return ["gsd_plan_slice"];
377
- case "execute-task":
378
- return ["gsd_task_complete"];
379
- case "complete-slice":
380
- return ["gsd_slice_complete", "gsd_task_reopen", "gsd_replan_slice"];
381
- default:
382
- return [];
383
- }
353
+ return getRequiredWorkflowToolsForUnit(unitType);
384
354
  }
385
355
  export function getRequiredWorkflowToolsForAutoUnit(unitType) {
386
- switch (unitType) {
387
- case "discuss-project":
388
- return ["ask_user_questions", "gsd_summary_save"];
389
- case "discuss-requirements":
390
- return ["ask_user_questions", "gsd_requirement_save", "gsd_summary_save"];
391
- case "research-decision":
392
- return ["ask_user_questions"];
393
- case "discuss-milestone":
394
- return [
395
- "gsd_summary_save",
396
- "gsd_requirement_save",
397
- "gsd_requirement_update",
398
- "gsd_plan_milestone",
399
- "gsd_milestone_generate_id",
400
- ];
401
- case "research-milestone":
402
- case "research-slice":
403
- return ["gsd_summary_save"];
404
- case "run-uat":
405
- return [...RUN_UAT_WORKFLOW_TOOL_NAMES];
406
- case "plan-milestone":
407
- return ["gsd_plan_milestone"];
408
- case "plan-slice":
409
- return ["gsd_plan_slice"];
410
- case "execute-task":
411
- case "execute-task-simple":
412
- case "reactive-execute":
413
- return ["gsd_task_complete"];
414
- case "complete-slice":
415
- return ["gsd_slice_complete", "gsd_task_reopen", "gsd_replan_slice"];
416
- case "replan-slice":
417
- return ["gsd_replan_slice"];
418
- case "reassess-roadmap":
419
- return ["gsd_milestone_status", "gsd_reassess_roadmap"];
420
- case "gate-evaluate":
421
- return ["gsd_save_gate_result"];
422
- case "validate-milestone":
423
- return ["gsd_milestone_status", "gsd_validate_milestone", "gsd_reassess_roadmap"];
424
- case "complete-milestone":
425
- return ["gsd_milestone_status", "gsd_complete_milestone"];
426
- default:
427
- return [];
428
- }
356
+ return getRequiredWorkflowToolsForUnit(unitType);
429
357
  }
430
358
  export function usesWorkflowMcpTransport(authMode, baseUrl) {
431
359
  return authMode === "externalCli" && typeof baseUrl === "string" && baseUrl.startsWith("local://");
@@ -0,0 +1,145 @@
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
+ export const GSD_BROWSER_MCP_SERVER_NAME = "gsd-browser";
8
+ function parseJsonEnv(env, name) {
9
+ const raw = env[name];
10
+ if (!raw)
11
+ return undefined;
12
+ try {
13
+ return JSON.parse(raw);
14
+ }
15
+ catch {
16
+ throw new Error(`Invalid JSON in ${name}`);
17
+ }
18
+ }
19
+ function sanitizeSessionSegment(value) {
20
+ return value
21
+ .replace(/[^a-zA-Z0-9._-]+/g, "-")
22
+ .replace(/^-+|-+$/g, "")
23
+ .slice(0, 40);
24
+ }
25
+ function compareSemverLocal(a, b) {
26
+ const left = a.split(".").map(Number);
27
+ const right = b.split(".").map(Number);
28
+ for (let index = 0; index < Math.max(left.length, right.length); index++) {
29
+ const leftValue = left[index] || 0;
30
+ const rightValue = right[index] || 0;
31
+ if (leftValue > rightValue)
32
+ return 1;
33
+ if (leftValue < rightValue)
34
+ return -1;
35
+ }
36
+ return 0;
37
+ }
38
+ function parseGsdBrowserVersion(output) {
39
+ return output.match(/\b(\d+\.\d+\.\d+)\b/)?.[1] ?? null;
40
+ }
41
+ function resolveBundledGsdBrowserPackageVersion() {
42
+ try {
43
+ const requireFromHere = createRequire(import.meta.url);
44
+ const packageJsonPath = requireFromHere.resolve("@opengsd/gsd-browser/package.json");
45
+ const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
46
+ return typeof pkg.version === "string" ? parseGsdBrowserVersion(pkg.version) : null;
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ function resolvePathGsdBrowserVersion(env) {
53
+ const explicit = env.GSD_BROWSER_PATH_VERSION?.trim();
54
+ if (explicit)
55
+ return parseGsdBrowserVersion(explicit);
56
+ try {
57
+ return parseGsdBrowserVersion(execFileSync("gsd-browser", ["--version"], {
58
+ encoding: "utf-8",
59
+ env,
60
+ stdio: ["ignore", "pipe", "ignore"],
61
+ timeout: 2000,
62
+ }));
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ function shouldPreferPathGsdBrowser(env) {
69
+ const pathVersion = resolvePathGsdBrowserVersion(env);
70
+ if (!pathVersion)
71
+ return false;
72
+ const bundledVersion = resolveBundledGsdBrowserPackageVersion();
73
+ return !bundledVersion || compareSemverLocal(pathVersion, bundledVersion) > 0;
74
+ }
75
+ export function resolveBundledGsdBrowserCliPath(env = process.env) {
76
+ const explicit = env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim();
77
+ if (explicit)
78
+ return explicit;
79
+ try {
80
+ const requireFromHere = createRequire(import.meta.url);
81
+ const packageJsonPath = requireFromHere.resolve("@opengsd/gsd-browser/package.json");
82
+ const candidate = resolve(packageJsonPath, "..", "bin", "gsd-browser");
83
+ if (existsSync(candidate))
84
+ return candidate;
85
+ }
86
+ catch {
87
+ // Fall through to path candidates for source/dist layouts.
88
+ }
89
+ const candidates = [
90
+ resolve(fileURLToPath(new URL("../../../../node_modules/@opengsd/gsd-browser/bin/gsd-browser", import.meta.url))),
91
+ resolve(fileURLToPath(new URL("../../../../node_modules/.bin/gsd-browser", import.meta.url))),
92
+ ];
93
+ for (const candidate of candidates) {
94
+ if (existsSync(candidate))
95
+ return candidate;
96
+ }
97
+ return null;
98
+ }
99
+ export function buildGsdBrowserSessionName(projectRoot, suffix) {
100
+ const resolvedProjectRoot = resolve(projectRoot);
101
+ const base = sanitizeSessionSegment(basename(resolvedProjectRoot)) || "project";
102
+ const hash = createHash("sha1").update(resolvedProjectRoot).digest("hex").slice(0, 8);
103
+ const cleanSuffix = suffix ? sanitizeSessionSegment(suffix) : "";
104
+ return cleanSuffix ? `gsd-${base}-${hash}-${cleanSuffix}` : `gsd-${base}-${hash}`;
105
+ }
106
+ export function resolveGsdBrowserMcpLaunchConfig(projectRoot, env = process.env, options = {}) {
107
+ const resolvedProjectRoot = resolve(projectRoot);
108
+ const serverName = env.GSD_BROWSER_MCP_NAME?.trim() || GSD_BROWSER_MCP_SERVER_NAME;
109
+ const explicitArgs = parseJsonEnv(env, "GSD_BROWSER_MCP_ARGS");
110
+ const explicitEnv = parseJsonEnv(env, "GSD_BROWSER_MCP_ENV");
111
+ const explicitCommand = env.GSD_BROWSER_MCP_COMMAND?.trim();
112
+ const explicitCliPath = env.GSD_BROWSER_CLI_PATH?.trim() || env.GSD_BROWSER_BIN_PATH?.trim();
113
+ const preferPathCli = !explicitCommand && !explicitCliPath && shouldPreferPathGsdBrowser(env);
114
+ const bundledCliPath = !explicitCommand && !explicitCliPath && !preferPathCli
115
+ ? resolveBundledGsdBrowserCliPath(env)
116
+ : null;
117
+ const sessionName = options.sessionName?.trim() || buildGsdBrowserSessionName(resolvedProjectRoot, options.sessionSuffix);
118
+ const command = explicitCommand
119
+ || explicitCliPath
120
+ || (preferPathCli ? "gsd-browser" : undefined)
121
+ || (bundledCliPath ? process.execPath : undefined)
122
+ || "gsd-browser";
123
+ const args = Array.isArray(explicitArgs) && explicitArgs.length > 0
124
+ ? explicitArgs.map(String)
125
+ : [
126
+ ...(bundledCliPath ? [bundledCliPath] : []),
127
+ "mcp",
128
+ "--session",
129
+ sessionName,
130
+ "--identity-scope",
131
+ "project",
132
+ "--identity-project",
133
+ resolvedProjectRoot,
134
+ ];
135
+ const cwd = env.GSD_BROWSER_MCP_CWD?.trim() || resolvedProjectRoot;
136
+ return {
137
+ serverName,
138
+ command,
139
+ args,
140
+ cwd,
141
+ ...(explicitEnv ? { env: explicitEnv } : {}),
142
+ projectRoot: resolvedProjectRoot,
143
+ sessionName,
144
+ };
145
+ }
package/dist/rtk.d.ts CHANGED
@@ -40,6 +40,12 @@ export interface ValidateRtkBinaryOptions {
40
40
  spawnSyncImpl?: typeof spawnSync;
41
41
  env?: NodeJS.ProcessEnv;
42
42
  }
43
- export declare function validateRtkBinary(binaryPath: string, options?: ValidateRtkBinaryOptions): boolean;
43
+ export type ValidateRtkBinaryResult = {
44
+ valid: true;
45
+ } | {
46
+ valid: false;
47
+ error: string;
48
+ };
49
+ export declare function validateRtkBinary(binaryPath: string, options?: ValidateRtkBinaryOptions): ValidateRtkBinaryResult;
44
50
  export declare function ensureRtkAvailable(options?: EnsureRtkOptions): Promise<EnsureRtkResult>;
45
51
  export declare function bootstrapRtk(options?: EnsureRtkOptions): Promise<EnsureRtkResult>;
package/dist/rtk.js CHANGED
@@ -162,19 +162,28 @@ export function rewriteCommandWithRtk(command, options = {}) {
162
162
  const rewritten = (result.stdout ?? "").trimEnd();
163
163
  return rewritten || command;
164
164
  }
165
+ function trimSpawnOutput(output) {
166
+ return output?.toString().trim() ?? "";
167
+ }
165
168
  export function validateRtkBinary(binaryPath, options = {}) {
166
169
  const run = options.spawnSyncImpl ?? spawnSync;
167
170
  const result = run(binaryPath, ["rewrite", "git status"], {
168
171
  encoding: "utf-8",
169
172
  env: buildRtkEnv(options.env ?? process.env),
170
- stdio: ["ignore", "pipe", "ignore"],
173
+ stdio: ["ignore", "pipe", "pipe"],
171
174
  timeout: RTK_REWRITE_TIMEOUT_MS,
172
175
  });
173
176
  if (result.error)
174
- return false;
175
- if (result.status !== 0)
176
- return false;
177
- return (result.stdout ?? "").trim() === "rtk git status";
177
+ return { valid: false, error: result.error.message };
178
+ if (result.status !== 0) {
179
+ const stderr = trimSpawnOutput(result.stderr);
180
+ return { valid: false, error: stderr || `exit code ${result.status ?? "unknown"}` };
181
+ }
182
+ const stdout = trimSpawnOutput(result.stdout);
183
+ if (stdout !== "rtk git status") {
184
+ return { valid: false, error: stdout ? `unexpected output: ${stdout}` : "unexpected empty output" };
185
+ }
186
+ return { valid: true };
178
187
  }
179
188
  export async function ensureRtkAvailable(options = {}) {
180
189
  const env = options.env ?? process.env;
@@ -190,12 +199,18 @@ export async function ensureRtkAvailable(options = {}) {
190
199
  }
191
200
  const targetDir = options.targetDir ?? getManagedRtkDir(env);
192
201
  const managedPath = getManagedRtkPath(process.platform, targetDir);
193
- if (existsSync(managedPath) && validateRtkBinary(managedPath, { env })) {
194
- return { enabled: true, supported: true, available: true, source: "managed", binaryPath: managedPath };
202
+ if (existsSync(managedPath)) {
203
+ const managedValidation = validateRtkBinary(managedPath, { env });
204
+ if (managedValidation.valid) {
205
+ return { enabled: true, supported: true, available: true, source: "managed", binaryPath: managedPath };
206
+ }
195
207
  }
196
208
  const systemPath = resolveSystemRtkPath(options.pathValue ?? getPathValue(env));
197
- if (systemPath && validateRtkBinary(systemPath, { env })) {
198
- return { enabled: true, supported: true, available: true, source: "system", binaryPath: systemPath };
209
+ if (systemPath) {
210
+ const systemValidation = validateRtkBinary(systemPath, { env });
211
+ if (systemValidation.valid) {
212
+ return { enabled: true, supported: true, available: true, source: "system", binaryPath: systemPath };
213
+ }
199
214
  }
200
215
  const version = options.releaseVersion ?? RTK_VERSION;
201
216
  const assetName = resolveRtkAssetName(process.platform, osArch(), version);
@@ -241,9 +256,10 @@ export async function ensureRtkAvailable(options = {}) {
241
256
  if (process.platform !== "win32") {
242
257
  chmodSync(managedPath, 0o755);
243
258
  }
244
- if (!validateRtkBinary(managedPath, { env })) {
259
+ const downloadedValidation = validateRtkBinary(managedPath, { env });
260
+ if (!downloadedValidation.valid) {
245
261
  rmSync(managedPath, { force: true });
246
- throw new Error("downloaded RTK binary failed validation");
262
+ throw new Error(`downloaded RTK binary failed validation: ${downloadedValidation.error}`);
247
263
  }
248
264
  options.log?.(`installed RTK ${version} to ${managedPath}`);
249
265
  return { enabled: true, supported: true, available: true, source: "downloaded", binaryPath: managedPath };
@@ -1,5 +1,9 @@
1
1
  import { isPnpmInstall } from './resources/shared/package-manager-detection.js';
2
2
  export { isPnpmInstall };
3
+ export declare const GSD_PI_PACKAGE_NAME = "@opengsd/gsd-pi";
4
+ export declare const GSD_BROWSER_PACKAGE_NAME = "@opengsd/gsd-browser";
5
+ export declare const DEFAULT_REGISTRY_URL = "https://registry.npmjs.org/@opengsd%2fgsd-pi/latest";
6
+ export declare const GSD_BROWSER_REGISTRY_URL = "https://registry.npmjs.org/@opengsd%2fgsd-browser/latest";
3
7
  interface UpdateCheckCache {
4
8
  lastCheck: number;
5
9
  latestVersion: string;
@@ -13,6 +17,14 @@ export declare function readUpdateCache(cachePath?: string, packageName?: string
13
17
  export declare function writeUpdateCache(cache: Omit<UpdateCheckCache, 'packageName'> & {
14
18
  packageName?: string;
15
19
  }, cachePath?: string, packageName?: string): void;
20
+ export declare function resolveInstalledPackageVersion(packageName: string): string | null;
21
+ /**
22
+ * Resolves the gsd-browser version from PATH (via `gsd-browser --version`).
23
+ * Respects GSD_BROWSER_PATH_VERSION env override for testing.
24
+ * Returns null if gsd-browser is not on PATH or times out.
25
+ */
26
+ export declare function resolveGsdBrowserPathVersion(env?: NodeJS.ProcessEnv): string | null;
27
+ export declare function pickHigherVersion(a: string | null, b: string | null): string | null;
16
28
  export declare function fetchLatestVersionFromRegistry(registryUrl?: string, fetchTimeoutMs?: number): Promise<string | null>;
17
29
  /**
18
30
  * Detects whether the currently-running gsd binary was installed via `bun add -g`.
@@ -29,18 +41,20 @@ export declare function resolveInstallCommand(pkg: string, options?: {
29
41
  env?: NodeJS.ProcessEnv;
30
42
  }): string;
31
43
  export interface UpdateCheckOptions {
44
+ packageName?: string;
32
45
  currentVersion?: string;
33
46
  cachePath?: string;
34
47
  registryUrl?: string;
35
48
  checkIntervalMs?: number;
36
49
  fetchTimeoutMs?: number;
37
- onUpdate?: (current: string, latest: string) => void;
50
+ onUpdate?: (current: string, latest: string, packageName: string) => void;
38
51
  }
39
52
  /**
40
53
  * Non-blocking update check. Queries npm registry at most once per 24h,
41
54
  * caches the result, and prints a banner if a newer version is available.
42
55
  */
43
56
  export declare function checkForUpdates(options?: UpdateCheckOptions): Promise<void>;
57
+ export declare function checkForGsdBrowserUpdates(options?: UpdateCheckOptions): Promise<void>;
44
58
  /**
45
59
  * Interactive update prompt shown at startup when a newer version is available.
46
60
  * Fetches the latest version (with cache), then asks the user whether to