@opengsd/gsd-pi 1.2.0-dev.fb12b103 → 1.2.0-dev.fbdca60b

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 (580) hide show
  1. package/dist/cli-model-override.d.ts +15 -0
  2. package/dist/cli-model-override.js +21 -0
  3. package/dist/cli.js +1 -18
  4. package/dist/headless-events.js +7 -5
  5. package/dist/loader.js +6 -4
  6. package/dist/mcp-server.js +2 -1
  7. package/dist/register-agent-bundles.d.ts +11 -2
  8. package/dist/register-agent-bundles.js +18 -4
  9. package/dist/resource-loader.d.ts +10 -5
  10. package/dist/resource-loader.js +121 -6
  11. package/dist/resources/.managed-resources-content-hash +1 -1
  12. package/dist/resources/GSD-WORKFLOW.md +5 -4
  13. package/dist/resources/extensions/ask-user-questions.js +3 -2
  14. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
  15. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
  16. package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
  17. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  18. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  19. package/dist/resources/extensions/gsd/auto/dispatch-history.js +120 -0
  20. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  21. package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
  22. package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
  23. package/dist/resources/extensions/gsd/auto/loop.js +7 -1
  24. package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
  25. package/dist/resources/extensions/gsd/auto/orchestrator.js +167 -64
  26. package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
  27. package/dist/resources/extensions/gsd/auto/phases.js +17 -2329
  28. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +534 -0
  29. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  30. package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
  31. package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
  32. package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
  33. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
  34. package/dist/resources/extensions/gsd/auto-dispatch.js +39 -58
  35. package/dist/resources/extensions/gsd/auto-model-selection.js +11 -7
  36. package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
  37. package/dist/resources/extensions/gsd/auto-prompts.js +66 -9
  38. package/dist/resources/extensions/gsd/auto-start.js +26 -8
  39. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  40. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
  41. package/dist/resources/extensions/gsd/auto-verification.js +23 -30
  42. package/dist/resources/extensions/gsd/auto-worktree.js +15 -2
  43. package/dist/resources/extensions/gsd/auto.js +52 -2
  44. package/dist/resources/extensions/gsd/blocked-models.js +28 -0
  45. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
  46. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
  47. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
  48. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -45
  49. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
  50. package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
  51. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  52. package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
  53. package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
  54. package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
  55. package/dist/resources/extensions/gsd/consent-question.js +353 -0
  56. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  57. package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
  58. package/dist/resources/extensions/gsd/db/engine.js +24 -6
  59. package/dist/resources/extensions/gsd/db/queries.js +56 -0
  60. package/dist/resources/extensions/gsd/db-migration-backup.js +51 -8
  61. package/dist/resources/extensions/gsd/db-transaction.js +27 -23
  62. package/dist/resources/extensions/gsd/db-writer.js +8 -17
  63. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  64. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  65. package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
  66. package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
  67. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  68. package/dist/resources/extensions/gsd/files.js +33 -19
  69. package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
  70. package/dist/resources/extensions/gsd/gsd-db.js +17 -21
  71. package/dist/resources/extensions/gsd/guidance.js +60 -0
  72. package/dist/resources/extensions/gsd/guided-flow.js +93 -4
  73. package/dist/resources/extensions/gsd/health-widget.js +87 -28
  74. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  75. package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
  76. package/dist/resources/extensions/gsd/memory-relations.js +1 -1
  77. package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
  78. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
  79. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  80. package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
  81. package/dist/resources/extensions/gsd/notifications.js +12 -7
  82. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  83. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  84. package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  85. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
  86. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  87. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  88. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  89. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  90. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  91. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  92. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  93. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  94. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  95. package/dist/resources/extensions/gsd/prompts/run-uat.md +8 -4
  96. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  97. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  98. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  99. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  100. package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
  101. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  102. package/dist/resources/extensions/gsd/skill-activation.js +3 -6
  103. package/dist/resources/extensions/gsd/state.js +11 -2
  104. package/dist/resources/extensions/gsd/tool-contract.js +14 -3
  105. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  106. package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
  107. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  108. package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
  109. package/dist/resources/extensions/gsd/tools/complete-task.js +65 -2
  110. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
  111. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  112. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
  113. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  114. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
  115. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  116. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  117. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
  118. package/dist/resources/extensions/gsd/uat-policy.js +40 -15
  119. package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
  120. package/dist/resources/extensions/gsd/unit-registry.js +34 -4
  121. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  122. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  123. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  124. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  125. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  126. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
  127. package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
  128. package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
  129. package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
  130. package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
  131. package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
  132. package/dist/resources/extensions/gsd/worktree.js +8 -1
  133. package/dist/resources/extensions/mcp-client/manager.js +6 -1
  134. package/dist/resources/extensions/shared/gsd-browser-cli.js +21 -2
  135. package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
  136. package/dist/resources/shared/package-manager-detection.js +1 -1
  137. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  138. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  139. package/dist/runtime-checks.d.ts +10 -0
  140. package/dist/runtime-checks.js +27 -0
  141. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  142. package/dist/update-check.d.ts +2 -0
  143. package/dist/update-check.js +24 -1
  144. package/dist/update-cmd.js +20 -3
  145. package/dist/web/standalone/.next/BUILD_ID +1 -1
  146. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  147. package/dist/web/standalone/.next/build-manifest.json +2 -2
  148. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  149. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  150. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  153. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  154. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  155. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  156. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  157. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  158. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  159. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  161. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  162. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  163. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  164. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  165. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  168. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  170. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  172. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  174. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  176. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  178. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  180. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  182. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  184. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  186. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  188. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  190. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  191. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  192. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  194. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  195. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  196. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  197. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  199. package/dist/web/standalone/.next/server/app/index.html +1 -1
  200. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  201. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  202. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  203. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  204. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  205. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  206. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  207. package/dist/web/standalone/.next/server/chunks/{5942.js → 1128.js} +1 -1
  208. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  209. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  211. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  212. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  213. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  214. package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
  215. package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
  216. package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
  217. package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
  218. package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
  219. package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
  220. package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
  221. package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
  222. package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
  223. package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
  224. package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
  225. package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
  226. package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
  227. package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
  228. package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
  229. package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
  230. package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
  231. package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
  232. package/dist/web/standalone/node_modules/postcss/package.json +48 -48
  233. package/package.json +3 -3
  234. package/packages/cloud-mcp-gateway/package.json +2 -2
  235. package/packages/contracts/package.json +1 -1
  236. package/packages/daemon/package.json +4 -4
  237. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  238. package/packages/gsd-agent-core/dist/sdk.js +6 -4
  239. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  240. package/packages/gsd-agent-core/package.json +5 -5
  241. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  242. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  243. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  244. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  245. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +8 -0
  246. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  247. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +50 -6
  248. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  249. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +2 -0
  250. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  251. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +34 -5
  252. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  253. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +1 -0
  254. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  255. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +17 -0
  256. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  257. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  258. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
  259. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  260. package/packages/gsd-agent-modes/package.json +7 -7
  261. package/packages/mcp-server/README.md +12 -3
  262. package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
  263. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
  264. package/packages/mcp-server/dist/cli-runner.js +137 -0
  265. package/packages/mcp-server/dist/cli-runner.js.map +1 -0
  266. package/packages/mcp-server/dist/cli.js +2 -53
  267. package/packages/mcp-server/dist/cli.js.map +1 -1
  268. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
  269. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
  270. package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
  271. package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
  272. package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
  273. package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
  274. package/packages/mcp-server/dist/pid-registry.js +459 -0
  275. package/packages/mcp-server/dist/pid-registry.js.map +1 -0
  276. package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
  277. package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
  278. package/packages/mcp-server/dist/probe-mode.js +10 -0
  279. package/packages/mcp-server/dist/probe-mode.js.map +1 -0
  280. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  281. package/packages/mcp-server/dist/server.js +4 -0
  282. package/packages/mcp-server/dist/server.js.map +1 -1
  283. package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
  284. package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
  285. package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
  286. package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
  287. package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
  288. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  289. package/packages/mcp-server/dist/workflow-tools.js +161 -81
  290. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  291. package/packages/mcp-server/package.json +5 -4
  292. package/packages/native/package.json +1 -1
  293. package/packages/pi-agent-core/dist/agent-loop.js +43 -2
  294. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  295. package/packages/pi-agent-core/package.json +1 -1
  296. package/packages/pi-ai/README.md +1 -0
  297. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  298. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  299. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  300. package/packages/pi-ai/dist/index.d.ts +2 -0
  301. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  302. package/packages/pi-ai/dist/index.js +2 -0
  303. package/packages/pi-ai/dist/index.js.map +1 -1
  304. package/packages/pi-ai/dist/models.generated.d.ts +419 -221
  305. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  306. package/packages/pi-ai/dist/models.generated.js +468 -269
  307. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  308. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  309. package/packages/pi-ai/dist/providers/anthropic.js +12 -7
  310. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  311. package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
  312. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  313. package/packages/pi-ai/dist/providers/google-shared.js +12 -3
  314. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  315. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  316. package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
  317. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  318. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
  319. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
  320. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
  321. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
  322. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  323. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
  324. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  325. package/packages/pi-ai/package.json +3 -2
  326. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  327. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  328. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  329. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  330. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
  332. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  333. package/packages/pi-coding-agent/package.json +7 -7
  334. package/packages/pi-tui/README.md +15 -0
  335. package/packages/pi-tui/dist/index.d.ts +2 -2
  336. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  337. package/packages/pi-tui/dist/index.js +2 -2
  338. package/packages/pi-tui/dist/index.js.map +1 -1
  339. package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
  340. package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
  341. package/packages/pi-tui/dist/terminal-image.js +54 -2
  342. package/packages/pi-tui/dist/terminal-image.js.map +1 -1
  343. package/packages/pi-tui/dist/terminal.d.ts +12 -0
  344. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  345. package/packages/pi-tui/dist/terminal.js +70 -25
  346. package/packages/pi-tui/dist/terminal.js.map +1 -1
  347. package/packages/pi-tui/dist/tui.d.ts +15 -0
  348. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  349. package/packages/pi-tui/dist/tui.js +106 -21
  350. package/packages/pi-tui/dist/tui.js.map +1 -1
  351. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  352. package/packages/pi-tui/dist/utils.js +110 -36
  353. package/packages/pi-tui/dist/utils.js.map +1 -1
  354. package/packages/pi-tui/package.json +2 -2
  355. package/packages/rpc-client/package.json +2 -2
  356. package/pkg/dist/theme/theme.d.ts.map +1 -1
  357. package/pkg/dist/theme/theme.js +45 -17
  358. package/pkg/dist/theme/theme.js.map +1 -1
  359. package/pkg/package.json +1 -1
  360. package/src/resources/GSD-WORKFLOW.md +5 -4
  361. package/src/resources/extensions/ask-user-questions.ts +7 -2
  362. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +11 -0
  363. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
  364. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
  365. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
  366. package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
  367. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  368. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  369. package/src/resources/extensions/gsd/auto/dispatch-history.ts +168 -0
  370. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  371. package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
  372. package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
  373. package/src/resources/extensions/gsd/auto/loop.ts +7 -1
  374. package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
  375. package/src/resources/extensions/gsd/auto/orchestrator.ts +186 -66
  376. package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
  377. package/src/resources/extensions/gsd/auto/phases.ts +58 -3022
  378. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +704 -0
  379. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  380. package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
  381. package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
  382. package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
  383. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
  384. package/src/resources/extensions/gsd/auto-dispatch.ts +37 -62
  385. package/src/resources/extensions/gsd/auto-model-selection.ts +16 -7
  386. package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
  387. package/src/resources/extensions/gsd/auto-prompts.ts +78 -9
  388. package/src/resources/extensions/gsd/auto-start.ts +27 -11
  389. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  390. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
  391. package/src/resources/extensions/gsd/auto-verification.ts +26 -28
  392. package/src/resources/extensions/gsd/auto-worktree.ts +15 -2
  393. package/src/resources/extensions/gsd/auto.ts +64 -2
  394. package/src/resources/extensions/gsd/blocked-models.ts +49 -0
  395. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
  396. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
  397. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
  398. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +118 -50
  399. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
  400. package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
  401. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  402. package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
  403. package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
  404. package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
  405. package/src/resources/extensions/gsd/consent-question.ts +431 -0
  406. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  407. package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
  408. package/src/resources/extensions/gsd/db/engine.ts +26 -6
  409. package/src/resources/extensions/gsd/db/queries.ts +66 -0
  410. package/src/resources/extensions/gsd/db-migration-backup.ts +56 -7
  411. package/src/resources/extensions/gsd/db-transaction.ts +37 -20
  412. package/src/resources/extensions/gsd/db-writer.ts +11 -19
  413. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  414. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  415. package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
  416. package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
  417. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  418. package/src/resources/extensions/gsd/files.ts +33 -12
  419. package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
  420. package/src/resources/extensions/gsd/gsd-db.ts +19 -22
  421. package/src/resources/extensions/gsd/guidance.ts +78 -0
  422. package/src/resources/extensions/gsd/guided-flow.ts +145 -24
  423. package/src/resources/extensions/gsd/health-widget.ts +91 -27
  424. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  425. package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
  426. package/src/resources/extensions/gsd/memory-relations.ts +1 -1
  427. package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
  428. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
  429. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  430. package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
  431. package/src/resources/extensions/gsd/notifications.ts +13 -6
  432. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  433. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  434. package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  435. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
  436. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  437. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  438. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  439. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  440. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  441. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  442. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  443. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  444. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  445. package/src/resources/extensions/gsd/prompts/run-uat.md +8 -4
  446. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  447. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  448. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  449. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  450. package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
  451. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  452. package/src/resources/extensions/gsd/skill-activation.ts +3 -6
  453. package/src/resources/extensions/gsd/state.ts +12 -1
  454. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
  455. package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
  456. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
  457. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +75 -1
  458. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +257 -18
  459. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
  460. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +77 -1
  461. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
  462. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  463. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
  464. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
  465. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
  466. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  467. package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
  468. package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
  469. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  470. package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +68 -19
  471. package/src/resources/extensions/gsd/tests/db-transaction.test.ts +59 -0
  472. package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
  473. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +12 -11
  474. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +62 -0
  475. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  476. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +328 -0
  477. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
  478. package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
  479. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  480. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
  481. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
  482. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
  483. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +46 -0
  484. package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
  485. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +18 -6
  486. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
  487. package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
  488. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +217 -0
  489. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
  490. package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
  491. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
  492. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
  493. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
  494. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
  495. package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
  496. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
  497. package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
  498. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  499. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
  500. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +143 -0
  501. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
  502. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  503. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
  504. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  505. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -2
  506. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  507. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
  508. package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
  509. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  510. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +26 -2
  511. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +170 -48
  512. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
  513. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
  514. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
  515. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  516. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -2
  517. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
  518. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  519. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  520. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +88 -0
  521. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  522. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  523. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  524. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  525. package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
  526. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
  527. package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
  528. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  529. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
  530. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
  531. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
  532. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
  533. package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
  534. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
  535. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
  536. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  537. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  538. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
  539. package/src/resources/extensions/gsd/tool-contract.ts +38 -3
  540. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  541. package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
  542. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  543. package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
  544. package/src/resources/extensions/gsd/tools/complete-task.ts +90 -2
  545. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
  546. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  547. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
  548. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  549. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
  550. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  551. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  552. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
  553. package/src/resources/extensions/gsd/uat-policy.ts +60 -15
  554. package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
  555. package/src/resources/extensions/gsd/unit-registry.ts +34 -4
  556. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  557. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  558. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  559. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  560. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  561. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
  562. package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
  563. package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
  564. package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
  565. package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
  566. package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
  567. package/src/resources/extensions/gsd/worktree.ts +7 -1
  568. package/src/resources/extensions/mcp-client/manager.ts +7 -1
  569. package/src/resources/extensions/shared/gsd-browser-cli.ts +23 -2
  570. package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
  571. package/src/resources/shared/package-manager-detection.ts +1 -1
  572. package/src/resources/skills/create-skill/SKILL.md +3 -0
  573. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  574. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  575. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  576. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  577. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  578. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  579. /package/dist/web/standalone/.next/static/{mU4QIDlpVHDdjDpeEKh5W → 2T9IOdiiM3o3gZ4UbPi8E}/_buildManifest.js +0 -0
  580. /package/dist/web/standalone/.next/static/{mU4QIDlpVHDdjDpeEKh5W → 2T9IOdiiM3o3gZ4UbPi8E}/_ssgManifest.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moonshot-tool-schema.js","sourceRoot":"","sources":["../src/moonshot-tool-schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,4DAA4D,CAAC;AAChG,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,wBAAwB,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAW,CAAC;AAoB7E;;;GAGG;AACH,MAAM,UAAU,oCAAoC,CAAC,SAAuC;IAC3F,SAAS,CAAC,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC;QACjE,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,gBAAgB,CAAC;aAC/C,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;aAClC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;YACrB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC,WAA0D,CAAC,CAAC;YACxG,MAAM,cAAc,GAAG,QAAQ;gBAC9B,CAAC,CAAC,kBAAkB,CAAC,QAAQ,EAAE;oBAC7B,YAAY,EAAE,IAAI;oBAClB,YAAY,EAAE,OAAO;iBACrB,CAAC;gBACH,CAAC,CAAC,wBAAwB,CAAC;YAE5B,MAAM,cAAc,GAA4B;gBAC/C,IAAI;gBACJ,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,WAAW,EAAE,yBAAyB,CAAC,cAAc,CAAC;gBACtD,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,KAAK,EAAE,IAAI,CAAC,KAAK;aACjB,CAAC;YAEF,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACvB,MAAM,SAAS,GAAG,qBAAqB,CAAC,IAAI,CAAC,YAA2D,CAAC,CAAC;gBAC1G,IAAI,SAAS,EAAE,CAAC;oBACf,cAAc,CAAC,YAAY,GAAG,yBAAyB,CACtD,kBAAkB,CAAC,SAAS,EAAE;wBAC7B,YAAY,EAAE,IAAI;wBAClB,YAAY,EAAE,QAAQ;qBACtB,CAAC,CACF,CAAC;gBACH,CAAC;YACF,CAAC;YAED,OAAO,cAAc,CAAC;QACvB,CAAC,CAAC;KACH,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Moonshot-compatible MCP tool list schemas for Kimi Code and Moonshot API hosts.\n *\n * The MCP SDK converts Zod shapes to JSON Schema with anyOf for unions/nullable\n * fields. Moonshot rejects those patterns on tools.function.parameters.\n */\n\nimport { ListToolsRequestSchema } from \"@modelcontextprotocol/sdk/types.js\";\nimport { normalizeObjectSchema } from \"@modelcontextprotocol/sdk/server/zod-compat.js\";\nimport { toJsonSchemaCompat } from \"@modelcontextprotocol/sdk/server/zod-json-schema-compat.js\";\nimport { sanitizeSchemaForMoonshot } from \"@gsd/pi-ai\";\n\nconst EMPTY_OBJECT_JSON_SCHEMA = { type: \"object\", properties: {} } as const;\n\ntype RegisteredTool = {\n\tenabled: boolean;\n\ttitle?: string;\n\tdescription?: string;\n\tinputSchema?: unknown;\n\toutputSchema?: unknown;\n\tannotations?: unknown;\n\texecution?: unknown;\n\t_meta?: unknown;\n};\n\ntype McpServerWithRegisteredTools = {\n\tserver: {\n\t\tsetRequestHandler: (schema: unknown, handler: () => unknown) => void;\n\t};\n\t_registeredTools: Record<string, RegisteredTool>;\n};\n\n/**\n * Replace the MCP SDK ListTools handler so every advertised inputSchema is\n * flattened for Moonshot/Kimi grammar. Call after all tools are registered.\n */\nexport function installMoonshotCompatibleToolSchemas(mcpServer: McpServerWithRegisteredTools): void {\n\tmcpServer.server.setRequestHandler(ListToolsRequestSchema, () => ({\n\t\ttools: Object.entries(mcpServer._registeredTools)\n\t\t\t.filter(([, tool]) => tool.enabled)\n\t\t\t.map(([name, tool]) => {\n\t\t\t\tconst inputObj = normalizeObjectSchema(tool.inputSchema as Parameters<typeof normalizeObjectSchema>[0]);\n\t\t\t\tconst rawInputSchema = inputObj\n\t\t\t\t\t? toJsonSchemaCompat(inputObj, {\n\t\t\t\t\t\t\tstrictUnions: true,\n\t\t\t\t\t\t\tpipeStrategy: \"input\",\n\t\t\t\t\t\t})\n\t\t\t\t\t: EMPTY_OBJECT_JSON_SCHEMA;\n\n\t\t\t\tconst toolDefinition: Record<string, unknown> = {\n\t\t\t\t\tname,\n\t\t\t\t\ttitle: tool.title,\n\t\t\t\t\tdescription: tool.description,\n\t\t\t\t\tinputSchema: sanitizeSchemaForMoonshot(rawInputSchema),\n\t\t\t\t\tannotations: tool.annotations,\n\t\t\t\t\texecution: tool.execution,\n\t\t\t\t\t_meta: tool._meta,\n\t\t\t\t};\n\n\t\t\t\tif (tool.outputSchema) {\n\t\t\t\t\tconst outputObj = normalizeObjectSchema(tool.outputSchema as Parameters<typeof normalizeObjectSchema>[0]);\n\t\t\t\t\tif (outputObj) {\n\t\t\t\t\t\ttoolDefinition.outputSchema = sanitizeSchemaForMoonshot(\n\t\t\t\t\t\t\ttoJsonSchemaCompat(outputObj, {\n\t\t\t\t\t\t\t\tstrictUnions: true,\n\t\t\t\t\t\t\t\tpipeStrategy: \"output\",\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn toolDefinition;\n\t\t\t}),\n\t}));\n}\n"]}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * MCP server PID registry — tracks running instances per project so new
3
+ * launches can kill stale ones. Mirrors web-mode's web-instances.json pattern.
4
+ */
5
+ export interface McpInstanceEntry {
6
+ pid: number;
7
+ projectDir: string;
8
+ startedAt: string;
9
+ }
10
+ export type McpInstanceRegistry = Record<string, McpInstanceEntry>;
11
+ export interface RegisterMcpInstanceOptions {
12
+ kill?: (pid: number, signal?: NodeJS.Signals | 0) => void;
13
+ getProcessCommand?: (pid: number) => string | null;
14
+ getProcessCwd?: (pid: number) => string | null;
15
+ getProcessStartTime?: (pid: number) => number | null;
16
+ waitForExit?: () => void;
17
+ }
18
+ export interface McpProcessSnapshot {
19
+ pid: number;
20
+ ppid: number;
21
+ command: string;
22
+ }
23
+ export interface SweepProjectOrphanMcpServersOptions {
24
+ kill?: (pid: number, signal?: NodeJS.Signals | 0) => void;
25
+ getProcessCwd?: (pid: number) => string | null;
26
+ listProcesses?: () => McpProcessSnapshot[];
27
+ isOrphaned?: (proc: McpProcessSnapshot) => boolean;
28
+ waitForExit?: () => void;
29
+ }
30
+ export interface SweepProjectOrphanMcpServersResult {
31
+ matched: number[];
32
+ terminated: number[];
33
+ forceKilled: number[];
34
+ skipped: number[];
35
+ }
36
+ export declare function readMcpRegistry(registryPath?: string): McpInstanceRegistry;
37
+ export declare function sweepProjectOrphanMcpServers(projectDir: string, options?: SweepProjectOrphanMcpServersOptions): SweepProjectOrphanMcpServersResult;
38
+ /**
39
+ * Kill any existing MCP server for this project, then register our PID.
40
+ */
41
+ export declare function registerMcpInstance(projectDir: string, registryPath?: string, options?: RegisterMcpInstanceOptions): boolean;
42
+ /**
43
+ * Remove our PID from the registry on shutdown.
44
+ */
45
+ export declare function unregisterMcpInstance(projectDir: string, registryPath?: string): void;
46
+ //# sourceMappingURL=pid-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pid-registry.d.ts","sourceRoot":"","sources":["../src/pid-registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAEnE,MAAM,WAAW,0BAA0B;IACzC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,IAAI,CAAC;IAC1D,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACnD,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC/C,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACrD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mCAAmC;IAClD,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,IAAI,CAAC;IAC1D,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC/C,aAAa,CAAC,EAAE,MAAM,kBAAkB,EAAE,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,OAAO,CAAC;IACnD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,kCAAkC;IACjD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAaD,wBAAgB,eAAe,CAAC,YAAY,SAAgB,GAAG,mBAAmB,CAwCjF;AAwRD,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,mCAAwC,GAChD,kCAAkC,CAgDpC;AAkED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,YAAY,SAAgB,EAC5B,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAgCT;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,SAAgB,GAAG,IAAI,CAa5F"}
@@ -0,0 +1,459 @@
1
+ /**
2
+ * MCP server PID registry — tracks running instances per project so new
3
+ * launches can kill stale ones. Mirrors web-mode's web-instances.json pattern.
4
+ */
5
+ import { execFileSync } from 'node:child_process';
6
+ import { readFileSync, writeFileSync, mkdirSync, renameSync } from 'node:fs';
7
+ import { homedir } from 'node:os';
8
+ import { dirname, join, resolve } from 'node:path';
9
+ const REGISTRY_PATH = join(process.env.GSD_HOME || join(homedir(), '.gsd'), 'mcp-instances.json');
10
+ // A live PID is only treated as "our" stale server if its OS start time is no
11
+ // later than the moment we recorded the registry entry (plus a small skew for
12
+ // clock granularity / start-vs-register delay). A PID that started materially
13
+ // later has been recycled by a different process and must not be signalled.
14
+ const STALE_PID_START_SKEW_MS = 60_000;
15
+ export function readMcpRegistry(registryPath = REGISTRY_PATH) {
16
+ let raw;
17
+ try {
18
+ raw = readFileSync(registryPath, 'utf8');
19
+ }
20
+ catch (err) {
21
+ // A missing file is the normal first-run case — start with an empty
22
+ // registry silently. Any other read error is worth surfacing.
23
+ if (err.code !== 'ENOENT') {
24
+ process.stderr.write(`[gsd-mcp-server] failed to read MCP registry ${registryPath}: ${err instanceof Error ? err.message : String(err)}\n`);
25
+ }
26
+ return {};
27
+ }
28
+ try {
29
+ const parsed = JSON.parse(raw);
30
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
31
+ return parsed;
32
+ }
33
+ throw new Error('registry is not a JSON object');
34
+ }
35
+ catch (err) {
36
+ // The file exists but is unparseable. Returning {} here means the next
37
+ // registerMcpInstance would overwrite the file and silently drop every
38
+ // other project's entry. The corrupt bytes can't be recovered, but we
39
+ // preserve them for forensics and warn loudly instead of dropping them
40
+ // without a trace.
41
+ const backup = `${registryPath}.corrupt-${Date.now()}`;
42
+ try {
43
+ renameSync(registryPath, backup);
44
+ process.stderr.write(`[gsd-mcp-server] MCP registry ${registryPath} was corrupt (${err instanceof Error ? err.message : String(err)}); preserved as ${backup}\n`);
45
+ }
46
+ catch {
47
+ process.stderr.write(`[gsd-mcp-server] MCP registry ${registryPath} was corrupt (${err instanceof Error ? err.message : String(err)}) and could not be preserved\n`);
48
+ }
49
+ return {};
50
+ }
51
+ }
52
+ function writeMcpRegistry(registry, registryPath = REGISTRY_PATH) {
53
+ mkdirSync(dirname(registryPath), { recursive: true });
54
+ writeFileSync(registryPath, JSON.stringify(registry, null, 2), 'utf8');
55
+ }
56
+ function defaultGetProcessCommand(pid) {
57
+ try {
58
+ if (process.platform === 'win32') {
59
+ // `ps` does not exist on Windows; query the process command line via CIM
60
+ // so stale same-project cleanup is not silently disabled there.
61
+ const out = execFileSync('powershell.exe', [
62
+ '-NoProfile',
63
+ '-NonInteractive',
64
+ '-Command',
65
+ `(Get-CimInstance Win32_Process -Filter "ProcessId=${pid}").CommandLine`,
66
+ ], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
67
+ return out || null;
68
+ }
69
+ const command = execFileSync('ps', ['-p', String(pid), '-o', 'command='], {
70
+ encoding: 'utf8',
71
+ stdio: ['ignore', 'pipe', 'ignore'],
72
+ env: { ...process.env, LC_ALL: 'C' },
73
+ }).trim();
74
+ return command || null;
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ function defaultGetProcessStartTime(pid) {
81
+ try {
82
+ if (process.platform === 'win32') {
83
+ const out = execFileSync('powershell.exe', [
84
+ '-NoProfile',
85
+ '-NonInteractive',
86
+ '-Command',
87
+ `$p = Get-CimInstance Win32_Process -Filter "ProcessId=${pid}"; if ($p) { [int64](($p.CreationDate.ToUniversalTime() - [datetime]'1970-01-01T00:00:00Z').TotalMilliseconds) }`,
88
+ ], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
89
+ const ms = Number(out);
90
+ return Number.isFinite(ms) && ms > 0 ? ms : null;
91
+ }
92
+ // `lstart` is supported by both Linux (procps) and macOS (BSD) ps. Force
93
+ // the C locale so the timestamp is parseable regardless of the user's LANG.
94
+ const lstart = execFileSync('ps', ['-p', String(pid), '-o', 'lstart='], {
95
+ encoding: 'utf8',
96
+ stdio: ['ignore', 'pipe', 'ignore'],
97
+ env: { ...process.env, LC_ALL: 'C' },
98
+ }).trim();
99
+ if (!lstart)
100
+ return null;
101
+ const ms = new Date(lstart).getTime();
102
+ return Number.isFinite(ms) ? ms : null;
103
+ }
104
+ catch {
105
+ return null;
106
+ }
107
+ }
108
+ function normalizeProcessCwd(value) {
109
+ return value.startsWith('\\\\?\\') ? value.slice(4) : value;
110
+ }
111
+ function defaultGetProcessCwd(pid) {
112
+ if (process.platform === 'win32') {
113
+ try {
114
+ const out = execFileSync('powershell.exe', [
115
+ '-NoProfile',
116
+ '-NonInteractive',
117
+ '-Command',
118
+ `$pid=${pid};$t=@'
119
+ using System;using System.Runtime.InteropServices;using System.Text;
120
+ public static class GsdProcCwd{
121
+ [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(int a,bool b,int p);
122
+ [DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr h);
123
+ [DllImport("kernel32.dll")] public static extern bool ReadProcessMemory(IntPtr h,IntPtr a,byte[] b,int l,out int r);
124
+ [DllImport("ntdll.dll")] public static extern int NtQueryInformationProcess(IntPtr h,int c,byte[] i,int l,out int o);
125
+ public static string G(int pid){
126
+ IntPtr h=OpenProcess(0x1010,false,pid);if(h==IntPtr.Zero)return null;
127
+ try{bool x=IntPtr.Size==8;int n=IntPtr.Size*6;byte[] pbi=new byte[n];int o;
128
+ if(NtQueryInformationProcess(h,0,pbi,n,out o)!=0)return null;
129
+ IntPtr peb=x?(IntPtr)BitConverter.ToInt64(pbi,IntPtr.Size):(IntPtr)BitConverter.ToInt32(pbi,4);
130
+ byte[] ptr=new byte[IntPtr.Size];int rd;
131
+ if(!ReadProcessMemory(h,IntPtr.Add(peb,x?0x20:0x10),ptr,ptr.Length,out rd))return null;
132
+ IntPtr pp=x?(IntPtr)BitConverter.ToInt64(ptr,0):(IntPtr)BitConverter.ToInt32(ptr,0);
133
+ byte[] us=new byte[16];
134
+ if(!ReadProcessMemory(h,IntPtr.Add(pp,x?0x38:0x24),us,us.Length,out rd))return null;
135
+ int len=BitConverter.ToUInt16(us,0);if(len<=0||len>32766)return null;
136
+ IntPtr buf=x?(IntPtr)BitConverter.ToInt64(us,8):(IntPtr)BitConverter.ToInt32(us,4);
137
+ byte[] ch=new byte[len];
138
+ if(!ReadProcessMemory(h,buf,ch,ch.Length,out rd))return null;
139
+ return Encoding.Unicode.GetString(ch,0,len);}finally{CloseHandle(h);}}
140
+ }
141
+ '@;Add-Type -TypeDefinition $t -ErrorAction Stop;[GsdProcCwd]::G($pid)`,
142
+ ], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
143
+ if (!out)
144
+ return null;
145
+ return normalizeProcessCwd(out);
146
+ }
147
+ catch {
148
+ return null;
149
+ }
150
+ }
151
+ try {
152
+ const out = execFileSync('lsof', ['-a', '-p', String(pid), '-d', 'cwd', '-Fn'], {
153
+ encoding: 'utf8',
154
+ stdio: ['ignore', 'pipe', 'ignore'],
155
+ env: { ...process.env, LC_ALL: 'C' },
156
+ });
157
+ const cwd = out.split('\n').find((line) => line.startsWith('n'))?.slice(1).trim();
158
+ if (cwd)
159
+ return cwd;
160
+ }
161
+ catch {
162
+ }
163
+ try {
164
+ const out = execFileSync('pwdx', [String(pid)], {
165
+ encoding: 'utf8',
166
+ stdio: ['ignore', 'pipe', 'ignore'],
167
+ env: { ...process.env, LC_ALL: 'C' },
168
+ }).trim();
169
+ const match = /^\d+:\s+(.+)$/.exec(out);
170
+ return match?.[1]?.trim() || null;
171
+ }
172
+ catch {
173
+ return null;
174
+ }
175
+ }
176
+ function isSafePid(pid) {
177
+ return typeof pid === 'number' && Number.isSafeInteger(pid) && pid > 1;
178
+ }
179
+ function isMcpServerCommand(command) {
180
+ if (!command)
181
+ return false;
182
+ const normalized = command.replace(/\\/g, '/');
183
+ return (command.includes('gsd-mcp-server') ||
184
+ command.includes('@opengsd/mcp-server') ||
185
+ normalized.includes('/packages/mcp-server/'));
186
+ }
187
+ function defaultListProcesses() {
188
+ if (process.platform === 'win32') {
189
+ try {
190
+ const out = execFileSync('powershell.exe', [
191
+ '-NoProfile',
192
+ '-NonInteractive',
193
+ '-Command',
194
+ 'Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,CommandLine | ConvertTo-Json -Compress',
195
+ ], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
196
+ if (!out)
197
+ return [];
198
+ const parsed = JSON.parse(out);
199
+ const rows = Array.isArray(parsed) ? parsed : [parsed];
200
+ return rows.flatMap((row) => {
201
+ if (!row || typeof row !== 'object')
202
+ return [];
203
+ const record = row;
204
+ const pid = Number(record.ProcessId);
205
+ const ppid = Number(record.ParentProcessId);
206
+ const command = typeof record.CommandLine === 'string' ? record.CommandLine : '';
207
+ if (!Number.isSafeInteger(pid) || !Number.isSafeInteger(ppid))
208
+ return [];
209
+ return [{ pid, ppid, command }];
210
+ });
211
+ }
212
+ catch {
213
+ return [];
214
+ }
215
+ }
216
+ try {
217
+ const out = execFileSync('ps', ['-axo', 'pid=,ppid=,command='], {
218
+ encoding: 'utf8',
219
+ stdio: ['ignore', 'pipe', 'ignore'],
220
+ env: { ...process.env, LC_ALL: 'C' },
221
+ });
222
+ return out.split('\n').flatMap((line) => {
223
+ const match = /^\s*(\d+)\s+(\d+)\s+(.+)$/.exec(line);
224
+ if (!match)
225
+ return [];
226
+ return [{
227
+ pid: Number(match[1]),
228
+ ppid: Number(match[2]),
229
+ command: match[3],
230
+ }];
231
+ });
232
+ }
233
+ catch {
234
+ return [];
235
+ }
236
+ }
237
+ function defaultWaitForExit() {
238
+ const shared = new Int32Array(new SharedArrayBuffer(4));
239
+ Atomics.wait(shared, 0, 0, 250);
240
+ }
241
+ function escapeRegExp(value) {
242
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
243
+ }
244
+ function normalizeCommandPath(value) {
245
+ return value.replace(/\\/g, '/');
246
+ }
247
+ function resolveComparableProjectPath(projectDir) {
248
+ if (/^[A-Za-z]:[\\/]/.test(projectDir) ||
249
+ projectDir.startsWith('\\\\') ||
250
+ projectDir.startsWith('/')) {
251
+ // Already an absolute path (Windows drive-letter, UNC, or POSIX). Do NOT
252
+ // call path.resolve(), which would prepend the current drive letter on
253
+ // Windows and turn a POSIX path like /workspace/project into
254
+ // C:/workspace/project, breaking command-path matching when the process
255
+ // command still contains the raw POSIX prefix.
256
+ return normalizeCommandPath(projectDir);
257
+ }
258
+ return normalizeCommandPath(resolve(projectDir));
259
+ }
260
+ function projectRegistryKeys(projectDir) {
261
+ return [...new Set([
262
+ resolveComparableProjectPath(projectDir),
263
+ resolve(projectDir),
264
+ projectDir,
265
+ ])];
266
+ }
267
+ function commandContainsProjectPath(command, projectDir) {
268
+ const normalizedProject = resolveComparableProjectPath(projectDir);
269
+ const normalizedCommand = normalizeCommandPath(command);
270
+ const pattern = new RegExp(`(^|[\\s"'])${escapeRegExp(normalizedProject)}(?=$|[/\\s"'])`);
271
+ return pattern.test(normalizedCommand);
272
+ }
273
+ function isSameProjectMcpProcess(command, cwd, projectDir) {
274
+ if (!isMcpServerCommand(command))
275
+ return false;
276
+ if (cwd && resolveComparableProjectPath(normalizeProcessCwd(cwd)) === resolveComparableProjectPath(projectDir))
277
+ return true;
278
+ return commandContainsProjectPath(command, projectDir);
279
+ }
280
+ function isPidAlive(pid, sendSignal) {
281
+ try {
282
+ sendSignal(pid, 0);
283
+ return true;
284
+ }
285
+ catch (error) {
286
+ return !(error instanceof Error &&
287
+ 'code' in error &&
288
+ error.code === 'ESRCH');
289
+ }
290
+ }
291
+ function isOrphanedMcpProcess(proc, sendSignal) {
292
+ if (process.platform === 'win32') {
293
+ // Windows does not reparent orphans to PID 1; the PPID usually still
294
+ // points at the dead parent, so treat a missing parent as orphaned.
295
+ if (!isSafePid(proc.ppid))
296
+ return false;
297
+ return !isPidAlive(proc.ppid, sendSignal);
298
+ }
299
+ return proc.ppid === 1;
300
+ }
301
+ export function sweepProjectOrphanMcpServers(projectDir, options = {}) {
302
+ const sendSignal = options.kill ?? ((targetPid, signal) => process.kill(targetPid, signal));
303
+ const getProcessCwd = options.getProcessCwd ?? defaultGetProcessCwd;
304
+ const listProcesses = options.listProcesses ?? defaultListProcesses;
305
+ const isOrphaned = options.isOrphaned ?? ((proc) => isOrphanedMcpProcess(proc, sendSignal));
306
+ const waitForExit = options.waitForExit ?? defaultWaitForExit;
307
+ const result = {
308
+ matched: [],
309
+ terminated: [],
310
+ forceKilled: [],
311
+ skipped: [],
312
+ };
313
+ for (const proc of listProcesses()) {
314
+ if (!isSafePid(proc.pid) || proc.pid === process.pid)
315
+ continue;
316
+ if (!isOrphaned(proc))
317
+ continue;
318
+ if (!isMcpServerCommand(proc.command))
319
+ continue;
320
+ const cwd = commandContainsProjectPath(proc.command, projectDir) ? null : getProcessCwd(proc.pid);
321
+ if (!isSameProjectMcpProcess(proc.command, cwd, projectDir))
322
+ continue;
323
+ result.matched.push(proc.pid);
324
+ if (!isPidAlive(proc.pid, sendSignal)) {
325
+ result.skipped.push(proc.pid);
326
+ continue;
327
+ }
328
+ try {
329
+ sendSignal(proc.pid, 'SIGTERM');
330
+ result.terminated.push(proc.pid);
331
+ }
332
+ catch {
333
+ result.skipped.push(proc.pid);
334
+ }
335
+ }
336
+ if (result.terminated.length > 0)
337
+ waitForExit();
338
+ for (const pid of result.terminated) {
339
+ if (!isPidAlive(pid, sendSignal))
340
+ continue;
341
+ try {
342
+ sendSignal(pid, 'SIGKILL');
343
+ result.forceKilled.push(pid);
344
+ }
345
+ catch {
346
+ result.skipped.push(pid);
347
+ }
348
+ }
349
+ return result;
350
+ }
351
+ function killPid(pid, projectDir, startedAt, options = {}) {
352
+ if (!isSafePid(pid))
353
+ return 'invalid';
354
+ const sendSignal = options.kill ?? ((targetPid, signal) => process.kill(targetPid, signal));
355
+ const getProcessCommand = options.getProcessCommand ?? defaultGetProcessCommand;
356
+ const getProcessCwd = options.getProcessCwd ?? defaultGetProcessCwd;
357
+ const getProcessStartTime = options.getProcessStartTime ?? defaultGetProcessStartTime;
358
+ const waitForExit = options.waitForExit ?? defaultWaitForExit;
359
+ try {
360
+ sendSignal(pid, 0);
361
+ }
362
+ catch (error) {
363
+ const isAlreadyDead = error instanceof Error && 'code' in error && error.code === 'ESRCH';
364
+ if (isAlreadyDead)
365
+ return 'already-dead';
366
+ return { error: error instanceof Error ? error.message : String(error) };
367
+ }
368
+ const command = getProcessCommand(pid);
369
+ if (!command || !isMcpServerCommand(command))
370
+ return 'unverified';
371
+ const cwd = getProcessCwd(pid);
372
+ const recordedMs = startedAt ? Date.parse(startedAt) : NaN;
373
+ const actualStartMs = getProcessStartTime(pid);
374
+ // Guard against PID reuse: a recycled PID can belong to a *different* live
375
+ // MCP server (even for another project). If we can determine when the live
376
+ // process actually started and it began materially after we recorded this
377
+ // entry, the original server is gone and this PID is not ours — refuse to
378
+ // signal it.
379
+ if (Number.isFinite(recordedMs) &&
380
+ actualStartMs !== null &&
381
+ actualStartMs > recordedMs + STALE_PID_START_SKEW_MS) {
382
+ return 'unverified';
383
+ }
384
+ // Confirm the live MCP server is the one we registered for this project via
385
+ // the process cwd or an embedded project path. Start time alone is not enough
386
+ // to authorize a signal when cwd is unavailable — another project's global
387
+ // install can share the same command line and a coincidentally aligned start.
388
+ const sameProject = isSameProjectMcpProcess(command, cwd, projectDir);
389
+ if (!sameProject)
390
+ return 'unverified';
391
+ try {
392
+ sendSignal(pid, 'SIGTERM');
393
+ waitForExit();
394
+ if (!isPidAlive(pid, sendSignal))
395
+ return 'killed';
396
+ sendSignal(pid, 'SIGKILL');
397
+ return 'force-killed';
398
+ }
399
+ catch (error) {
400
+ const isAlreadyDead = error instanceof Error && 'code' in error && error.code === 'ESRCH';
401
+ if (isAlreadyDead)
402
+ return 'already-dead';
403
+ return { error: error instanceof Error ? error.message : String(error) };
404
+ }
405
+ }
406
+ /**
407
+ * Kill any existing MCP server for this project, then register our PID.
408
+ */
409
+ export function registerMcpInstance(projectDir, registryPath = REGISTRY_PATH, options = {}) {
410
+ const registry = readMcpRegistry(registryPath);
411
+ const keys = projectRegistryKeys(projectDir);
412
+ const key = keys[0];
413
+ const existingKey = keys.find((candidate) => candidate in registry);
414
+ const existing = existingKey ? registry[existingKey] : undefined;
415
+ if (existing && existing.pid !== process.pid) {
416
+ const result = killPid(existing.pid, key, existing.startedAt, options);
417
+ const label = result === 'killed'
418
+ ? `killed stale pid=${existing.pid}`
419
+ : result === 'force-killed'
420
+ ? `force-killed stale pid=${existing.pid}`
421
+ : result === 'already-dead'
422
+ ? `stale pid=${existing.pid} already dead`
423
+ : result === 'invalid'
424
+ ? `ignored invalid stale pid=${String(existing.pid)}`
425
+ : result === 'unverified'
426
+ ? `ignored unverified stale pid=${existing.pid}`
427
+ : `failed to kill pid=${existing.pid}: ${result.error}`;
428
+ process.stderr.write(`[gsd-mcp-server] ${label} for ${key}\n`);
429
+ if (result === 'unverified')
430
+ return false;
431
+ }
432
+ if (existingKey && existingKey !== key)
433
+ delete registry[existingKey];
434
+ registry[key] = {
435
+ pid: process.pid,
436
+ projectDir: key,
437
+ startedAt: new Date().toISOString(),
438
+ };
439
+ writeMcpRegistry(registry, registryPath);
440
+ return true;
441
+ }
442
+ /**
443
+ * Remove our PID from the registry on shutdown.
444
+ */
445
+ export function unregisterMcpInstance(projectDir, registryPath = REGISTRY_PATH) {
446
+ const keys = projectRegistryKeys(projectDir);
447
+ const registry = readMcpRegistry(registryPath);
448
+ let changed = false;
449
+ for (const key of keys) {
450
+ if (registry[key]?.pid === process.pid) {
451
+ delete registry[key];
452
+ changed = true;
453
+ }
454
+ }
455
+ if (changed) {
456
+ writeMcpRegistry(registry, registryPath);
457
+ }
458
+ }
459
+ //# sourceMappingURL=pid-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pid-registry.js","sourceRoot":"","sources":["../src/pid-registry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP server PID registry — tracks running instances per project so new\n * launches can kill stale ones. Mirrors web-mode's web-instances.json pattern.\n */\n\nimport { execFileSync } from 'node:child_process';\nimport { readFileSync, writeFileSync, mkdirSync, renameSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\n\nexport interface McpInstanceEntry {\n pid: number;\n projectDir: string;\n startedAt: string;\n}\n\nexport type McpInstanceRegistry = Record<string, McpInstanceEntry>;\n\nexport interface RegisterMcpInstanceOptions {\n kill?: (pid: number, signal?: NodeJS.Signals | 0) => void;\n getProcessCommand?: (pid: number) => string | null;\n getProcessCwd?: (pid: number) => string | null;\n getProcessStartTime?: (pid: number) => number | null;\n waitForExit?: () => void;\n}\n\nexport interface McpProcessSnapshot {\n pid: number;\n ppid: number;\n command: string;\n}\n\nexport interface SweepProjectOrphanMcpServersOptions {\n kill?: (pid: number, signal?: NodeJS.Signals | 0) => void;\n getProcessCwd?: (pid: number) => string | null;\n listProcesses?: () => McpProcessSnapshot[];\n isOrphaned?: (proc: McpProcessSnapshot) => boolean;\n waitForExit?: () => void;\n}\n\nexport interface SweepProjectOrphanMcpServersResult {\n matched: number[];\n terminated: number[];\n forceKilled: number[];\n skipped: number[];\n}\n\nconst REGISTRY_PATH = join(\n process.env.GSD_HOME || join(homedir(), '.gsd'),\n 'mcp-instances.json',\n);\n\n// A live PID is only treated as \"our\" stale server if its OS start time is no\n// later than the moment we recorded the registry entry (plus a small skew for\n// clock granularity / start-vs-register delay). A PID that started materially\n// later has been recycled by a different process and must not be signalled.\nconst STALE_PID_START_SKEW_MS = 60_000;\n\nexport function readMcpRegistry(registryPath = REGISTRY_PATH): McpInstanceRegistry {\n let raw: string;\n try {\n raw = readFileSync(registryPath, 'utf8');\n } catch (err) {\n // A missing file is the normal first-run case — start with an empty\n // registry silently. Any other read error is worth surfacing.\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n process.stderr.write(\n `[gsd-mcp-server] failed to read MCP registry ${registryPath}: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n }\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as McpInstanceRegistry;\n }\n throw new Error('registry is not a JSON object');\n } catch (err) {\n // The file exists but is unparseable. Returning {} here means the next\n // registerMcpInstance would overwrite the file and silently drop every\n // other project's entry. The corrupt bytes can't be recovered, but we\n // preserve them for forensics and warn loudly instead of dropping them\n // without a trace.\n const backup = `${registryPath}.corrupt-${Date.now()}`;\n try {\n renameSync(registryPath, backup);\n process.stderr.write(\n `[gsd-mcp-server] MCP registry ${registryPath} was corrupt (${err instanceof Error ? err.message : String(err)}); preserved as ${backup}\\n`,\n );\n } catch {\n process.stderr.write(\n `[gsd-mcp-server] MCP registry ${registryPath} was corrupt (${err instanceof Error ? err.message : String(err)}) and could not be preserved\\n`,\n );\n }\n return {};\n }\n}\n\nfunction writeMcpRegistry(registry: McpInstanceRegistry, registryPath = REGISTRY_PATH): void {\n mkdirSync(dirname(registryPath), { recursive: true });\n writeFileSync(registryPath, JSON.stringify(registry, null, 2), 'utf8');\n}\n\nfunction defaultGetProcessCommand(pid: number): string | null {\n try {\n if (process.platform === 'win32') {\n // `ps` does not exist on Windows; query the process command line via CIM\n // so stale same-project cleanup is not silently disabled there.\n const out = execFileSync(\n 'powershell.exe',\n [\n '-NoProfile',\n '-NonInteractive',\n '-Command',\n `(Get-CimInstance Win32_Process -Filter \"ProcessId=${pid}\").CommandLine`,\n ],\n { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },\n ).trim();\n return out || null;\n }\n const command = execFileSync('ps', ['-p', String(pid), '-o', 'command='], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n env: { ...process.env, LC_ALL: 'C' },\n }).trim();\n return command || null;\n } catch {\n return null;\n }\n}\n\nfunction defaultGetProcessStartTime(pid: number): number | null {\n try {\n if (process.platform === 'win32') {\n const out = execFileSync(\n 'powershell.exe',\n [\n '-NoProfile',\n '-NonInteractive',\n '-Command',\n `$p = Get-CimInstance Win32_Process -Filter \"ProcessId=${pid}\"; if ($p) { [int64](($p.CreationDate.ToUniversalTime() - [datetime]'1970-01-01T00:00:00Z').TotalMilliseconds) }`,\n ],\n { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },\n ).trim();\n const ms = Number(out);\n return Number.isFinite(ms) && ms > 0 ? ms : null;\n }\n // `lstart` is supported by both Linux (procps) and macOS (BSD) ps. Force\n // the C locale so the timestamp is parseable regardless of the user's LANG.\n const lstart = execFileSync('ps', ['-p', String(pid), '-o', 'lstart='], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n env: { ...process.env, LC_ALL: 'C' },\n }).trim();\n if (!lstart) return null;\n const ms = new Date(lstart).getTime();\n return Number.isFinite(ms) ? ms : null;\n } catch {\n return null;\n }\n}\n\nfunction normalizeProcessCwd(value: string): string {\n return value.startsWith('\\\\\\\\?\\\\') ? value.slice(4) : value;\n}\n\nfunction defaultGetProcessCwd(pid: number): string | null {\n if (process.platform === 'win32') {\n try {\n const out = execFileSync(\n 'powershell.exe',\n [\n '-NoProfile',\n '-NonInteractive',\n '-Command',\n `$pid=${pid};$t=@'\nusing System;using System.Runtime.InteropServices;using System.Text;\npublic static class GsdProcCwd{\n [DllImport(\"kernel32.dll\")] public static extern IntPtr OpenProcess(int a,bool b,int p);\n [DllImport(\"kernel32.dll\")] public static extern bool CloseHandle(IntPtr h);\n [DllImport(\"kernel32.dll\")] public static extern bool ReadProcessMemory(IntPtr h,IntPtr a,byte[] b,int l,out int r);\n [DllImport(\"ntdll.dll\")] public static extern int NtQueryInformationProcess(IntPtr h,int c,byte[] i,int l,out int o);\n public static string G(int pid){\n IntPtr h=OpenProcess(0x1010,false,pid);if(h==IntPtr.Zero)return null;\n try{bool x=IntPtr.Size==8;int n=IntPtr.Size*6;byte[] pbi=new byte[n];int o;\n if(NtQueryInformationProcess(h,0,pbi,n,out o)!=0)return null;\n IntPtr peb=x?(IntPtr)BitConverter.ToInt64(pbi,IntPtr.Size):(IntPtr)BitConverter.ToInt32(pbi,4);\n byte[] ptr=new byte[IntPtr.Size];int rd;\n if(!ReadProcessMemory(h,IntPtr.Add(peb,x?0x20:0x10),ptr,ptr.Length,out rd))return null;\n IntPtr pp=x?(IntPtr)BitConverter.ToInt64(ptr,0):(IntPtr)BitConverter.ToInt32(ptr,0);\n byte[] us=new byte[16];\n if(!ReadProcessMemory(h,IntPtr.Add(pp,x?0x38:0x24),us,us.Length,out rd))return null;\n int len=BitConverter.ToUInt16(us,0);if(len<=0||len>32766)return null;\n IntPtr buf=x?(IntPtr)BitConverter.ToInt64(us,8):(IntPtr)BitConverter.ToInt32(us,4);\n byte[] ch=new byte[len];\n if(!ReadProcessMemory(h,buf,ch,ch.Length,out rd))return null;\n return Encoding.Unicode.GetString(ch,0,len);}finally{CloseHandle(h);}}\n}\n'@;Add-Type -TypeDefinition $t -ErrorAction Stop;[GsdProcCwd]::G($pid)`,\n ],\n { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },\n ).trim();\n if (!out) return null;\n return normalizeProcessCwd(out);\n } catch {\n return null;\n }\n }\n\n try {\n const out = execFileSync('lsof', ['-a', '-p', String(pid), '-d', 'cwd', '-Fn'], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n env: { ...process.env, LC_ALL: 'C' },\n });\n const cwd = out.split('\\n').find((line) => line.startsWith('n'))?.slice(1).trim();\n if (cwd) return cwd;\n } catch {\n }\n\n try {\n const out = execFileSync('pwdx', [String(pid)], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n env: { ...process.env, LC_ALL: 'C' },\n }).trim();\n const match = /^\\d+:\\s+(.+)$/.exec(out);\n return match?.[1]?.trim() || null;\n } catch {\n return null;\n }\n}\n\nfunction isSafePid(pid: unknown): pid is number {\n return typeof pid === 'number' && Number.isSafeInteger(pid) && pid > 1;\n}\n\nfunction isMcpServerCommand(command: string | null): boolean {\n if (!command) return false;\n const normalized = command.replace(/\\\\/g, '/');\n return (\n command.includes('gsd-mcp-server') ||\n command.includes('@opengsd/mcp-server') ||\n normalized.includes('/packages/mcp-server/')\n );\n}\n\nfunction defaultListProcesses(): McpProcessSnapshot[] {\n if (process.platform === 'win32') {\n try {\n const out = execFileSync(\n 'powershell.exe',\n [\n '-NoProfile',\n '-NonInteractive',\n '-Command',\n 'Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,CommandLine | ConvertTo-Json -Compress',\n ],\n { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },\n ).trim();\n if (!out) return [];\n const parsed = JSON.parse(out) as unknown;\n const rows = Array.isArray(parsed) ? parsed : [parsed];\n return rows.flatMap((row) => {\n if (!row || typeof row !== 'object') return [];\n const record = row as Record<string, unknown>;\n const pid = Number(record.ProcessId);\n const ppid = Number(record.ParentProcessId);\n const command = typeof record.CommandLine === 'string' ? record.CommandLine : '';\n if (!Number.isSafeInteger(pid) || !Number.isSafeInteger(ppid)) return [];\n return [{ pid, ppid, command }];\n });\n } catch {\n return [];\n }\n }\n\n try {\n const out = execFileSync('ps', ['-axo', 'pid=,ppid=,command='], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n env: { ...process.env, LC_ALL: 'C' },\n });\n return out.split('\\n').flatMap((line) => {\n const match = /^\\s*(\\d+)\\s+(\\d+)\\s+(.+)$/.exec(line);\n if (!match) return [];\n return [{\n pid: Number(match[1]),\n ppid: Number(match[2]),\n command: match[3],\n }];\n });\n } catch {\n return [];\n }\n}\n\nfunction defaultWaitForExit(): void {\n const shared = new Int32Array(new SharedArrayBuffer(4));\n Atomics.wait(shared, 0, 0, 250);\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction normalizeCommandPath(value: string): string {\n return value.replace(/\\\\/g, '/');\n}\n\nfunction resolveComparableProjectPath(projectDir: string): string {\n if (\n /^[A-Za-z]:[\\\\/]/.test(projectDir) ||\n projectDir.startsWith('\\\\\\\\') ||\n projectDir.startsWith('/')\n ) {\n // Already an absolute path (Windows drive-letter, UNC, or POSIX). Do NOT\n // call path.resolve(), which would prepend the current drive letter on\n // Windows and turn a POSIX path like /workspace/project into\n // C:/workspace/project, breaking command-path matching when the process\n // command still contains the raw POSIX prefix.\n return normalizeCommandPath(projectDir);\n }\n return normalizeCommandPath(resolve(projectDir));\n}\n\nfunction projectRegistryKeys(projectDir: string): string[] {\n return [...new Set([\n resolveComparableProjectPath(projectDir),\n resolve(projectDir),\n projectDir,\n ])];\n}\n\nfunction commandContainsProjectPath(command: string, projectDir: string): boolean {\n const normalizedProject = resolveComparableProjectPath(projectDir);\n const normalizedCommand = normalizeCommandPath(command);\n const pattern = new RegExp(`(^|[\\\\s\"'])${escapeRegExp(normalizedProject)}(?=$|[/\\\\s\"'])`);\n return pattern.test(normalizedCommand);\n}\n\nfunction isSameProjectMcpProcess(command: string, cwd: string | null, projectDir: string): boolean {\n if (!isMcpServerCommand(command)) return false;\n if (cwd && resolveComparableProjectPath(normalizeProcessCwd(cwd)) === resolveComparableProjectPath(projectDir)) return true;\n return commandContainsProjectPath(command, projectDir);\n}\n\nfunction isPidAlive(\n pid: number,\n sendSignal: (pid: number, signal?: NodeJS.Signals | 0) => void,\n): boolean {\n try {\n sendSignal(pid, 0);\n return true;\n } catch (error) {\n return !(\n error instanceof Error &&\n 'code' in error &&\n (error as NodeJS.ErrnoException).code === 'ESRCH'\n );\n }\n}\n\nfunction isOrphanedMcpProcess(\n proc: McpProcessSnapshot,\n sendSignal: (pid: number, signal?: NodeJS.Signals | 0) => void,\n): boolean {\n if (process.platform === 'win32') {\n // Windows does not reparent orphans to PID 1; the PPID usually still\n // points at the dead parent, so treat a missing parent as orphaned.\n if (!isSafePid(proc.ppid)) return false;\n return !isPidAlive(proc.ppid, sendSignal);\n }\n return proc.ppid === 1;\n}\n\nexport function sweepProjectOrphanMcpServers(\n projectDir: string,\n options: SweepProjectOrphanMcpServersOptions = {},\n): SweepProjectOrphanMcpServersResult {\n const sendSignal = options.kill ?? ((targetPid, signal) => process.kill(targetPid, signal));\n const getProcessCwd = options.getProcessCwd ?? defaultGetProcessCwd;\n const listProcesses = options.listProcesses ?? defaultListProcesses;\n const isOrphaned = options.isOrphaned ?? ((proc: McpProcessSnapshot) => isOrphanedMcpProcess(proc, sendSignal));\n const waitForExit = options.waitForExit ?? defaultWaitForExit;\n\n const result: SweepProjectOrphanMcpServersResult = {\n matched: [],\n terminated: [],\n forceKilled: [],\n skipped: [],\n };\n\n for (const proc of listProcesses()) {\n if (!isSafePid(proc.pid) || proc.pid === process.pid) continue;\n if (!isOrphaned(proc)) continue;\n if (!isMcpServerCommand(proc.command)) continue;\n const cwd = commandContainsProjectPath(proc.command, projectDir) ? null : getProcessCwd(proc.pid);\n if (!isSameProjectMcpProcess(proc.command, cwd, projectDir)) continue;\n result.matched.push(proc.pid);\n\n if (!isPidAlive(proc.pid, sendSignal)) {\n result.skipped.push(proc.pid);\n continue;\n }\n\n try {\n sendSignal(proc.pid, 'SIGTERM');\n result.terminated.push(proc.pid);\n } catch {\n result.skipped.push(proc.pid);\n }\n }\n\n if (result.terminated.length > 0) waitForExit();\n\n for (const pid of result.terminated) {\n if (!isPidAlive(pid, sendSignal)) continue;\n try {\n sendSignal(pid, 'SIGKILL');\n result.forceKilled.push(pid);\n } catch {\n result.skipped.push(pid);\n }\n }\n\n return result;\n}\n\nfunction killPid(\n pid: unknown,\n projectDir: string,\n startedAt: string | undefined,\n options: RegisterMcpInstanceOptions = {},\n): 'killed' | 'force-killed' | 'already-dead' | 'invalid' | 'unverified' | { error: string } {\n if (!isSafePid(pid)) return 'invalid';\n\n const sendSignal = options.kill ?? ((targetPid, signal) => process.kill(targetPid, signal));\n const getProcessCommand = options.getProcessCommand ?? defaultGetProcessCommand;\n const getProcessCwd = options.getProcessCwd ?? defaultGetProcessCwd;\n const getProcessStartTime = options.getProcessStartTime ?? defaultGetProcessStartTime;\n const waitForExit = options.waitForExit ?? defaultWaitForExit;\n\n try {\n sendSignal(pid, 0);\n } catch (error) {\n const isAlreadyDead =\n error instanceof Error && 'code' in error && (error as NodeJS.ErrnoException).code === 'ESRCH';\n if (isAlreadyDead) return 'already-dead';\n return { error: error instanceof Error ? error.message : String(error) };\n }\n\n const command = getProcessCommand(pid);\n if (!command || !isMcpServerCommand(command)) return 'unverified';\n\n const cwd = getProcessCwd(pid);\n const recordedMs = startedAt ? Date.parse(startedAt) : NaN;\n const actualStartMs = getProcessStartTime(pid);\n\n // Guard against PID reuse: a recycled PID can belong to a *different* live\n // MCP server (even for another project). If we can determine when the live\n // process actually started and it began materially after we recorded this\n // entry, the original server is gone and this PID is not ours — refuse to\n // signal it.\n if (\n Number.isFinite(recordedMs) &&\n actualStartMs !== null &&\n actualStartMs > recordedMs + STALE_PID_START_SKEW_MS\n ) {\n return 'unverified';\n }\n\n // Confirm the live MCP server is the one we registered for this project via\n // the process cwd or an embedded project path. Start time alone is not enough\n // to authorize a signal when cwd is unavailable — another project's global\n // install can share the same command line and a coincidentally aligned start.\n const sameProject = isSameProjectMcpProcess(command, cwd, projectDir);\n if (!sameProject) return 'unverified';\n\n try {\n sendSignal(pid, 'SIGTERM');\n waitForExit();\n if (!isPidAlive(pid, sendSignal)) return 'killed';\n sendSignal(pid, 'SIGKILL');\n return 'force-killed';\n } catch (error) {\n const isAlreadyDead =\n error instanceof Error && 'code' in error && (error as NodeJS.ErrnoException).code === 'ESRCH';\n if (isAlreadyDead) return 'already-dead';\n return { error: error instanceof Error ? error.message : String(error) };\n }\n}\n\n/**\n * Kill any existing MCP server for this project, then register our PID.\n */\nexport function registerMcpInstance(\n projectDir: string,\n registryPath = REGISTRY_PATH,\n options: RegisterMcpInstanceOptions = {},\n): boolean {\n const registry = readMcpRegistry(registryPath);\n const keys = projectRegistryKeys(projectDir);\n const key = keys[0];\n const existingKey = keys.find((candidate) => candidate in registry);\n\n const existing = existingKey ? registry[existingKey] : undefined;\n if (existing && existing.pid !== process.pid) {\n const result = killPid(existing.pid, key, existing.startedAt, options);\n const label = result === 'killed'\n ? `killed stale pid=${existing.pid}`\n : result === 'force-killed'\n ? `force-killed stale pid=${existing.pid}`\n : result === 'already-dead'\n ? `stale pid=${existing.pid} already dead`\n : result === 'invalid'\n ? `ignored invalid stale pid=${String(existing.pid)}`\n : result === 'unverified'\n ? `ignored unverified stale pid=${existing.pid}`\n : `failed to kill pid=${existing.pid}: ${result.error}`;\n process.stderr.write(`[gsd-mcp-server] ${label} for ${key}\\n`);\n if (result === 'unverified') return false;\n }\n if (existingKey && existingKey !== key) delete registry[existingKey];\n\n registry[key] = {\n pid: process.pid,\n projectDir: key,\n startedAt: new Date().toISOString(),\n };\n writeMcpRegistry(registry, registryPath);\n return true;\n}\n\n/**\n * Remove our PID from the registry on shutdown.\n */\nexport function unregisterMcpInstance(projectDir: string, registryPath = REGISTRY_PATH): void {\n const keys = projectRegistryKeys(projectDir);\n const registry = readMcpRegistry(registryPath);\n let changed = false;\n for (const key of keys) {\n if (registry[key]?.pid === process.pid) {\n delete registry[key];\n changed = true;\n }\n }\n if (changed) {\n writeMcpRegistry(registry, registryPath);\n }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ /** When set, stdio MCP is a short-lived tools/list probe — skip PID registry side effects. */
2
+ export declare const GSD_MCP_PROBE_ENV = "GSD_MCP_PROBE";
3
+ export declare function isMcpProbeSession(env?: NodeJS.ProcessEnv): boolean;
4
+ //# sourceMappingURL=probe-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe-mode.d.ts","sourceRoot":"","sources":["../src/probe-mode.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAK/E"}
@@ -0,0 +1,10 @@
1
+ /** When set, stdio MCP is a short-lived tools/list probe — skip PID registry side effects. */
2
+ export const GSD_MCP_PROBE_ENV = 'GSD_MCP_PROBE';
3
+ export function isMcpProbeSession(env = process.env) {
4
+ const value = env[GSD_MCP_PROBE_ENV];
5
+ if (!value)
6
+ return false;
7
+ const normalized = value.trim().toLowerCase();
8
+ return normalized === '1' || normalized === 'true' || normalized === 'yes';
9
+ }
10
+ //# sourceMappingURL=probe-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe-mode.js","sourceRoot":"","sources":["../src/probe-mode.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEjD,MAAM,UAAU,iBAAiB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACpE,MAAM,KAAK,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,OAAO,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,KAAK,CAAC;AAC7E,CAAC","sourcesContent":["/** When set, stdio MCP is a short-lived tools/list probe — skip PID registry side effects. */\nexport const GSD_MCP_PROBE_ENV = 'GSD_MCP_PROBE';\n\nexport function isMcpProbeSession(env: NodeJS.ProcessEnv = process.env): boolean {\n const value = env[GSD_MCP_PROBE_ENV];\n if (!value) return false;\n const normalized = value.trim().toLowerCase();\n return normalized === '1' || normalized === 'true' || normalized === 'yes';\n}\n"]}