@opengsd/gsd-pi 1.4.0 → 1.5.0

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/README.md +11 -11
  2. package/dist/onboarding.js +11 -0
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/GSD-WORKFLOW.md +20 -25
  5. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +118 -53
  6. package/dist/resources/extensions/cursor-cli/index.js +16 -0
  7. package/dist/resources/extensions/cursor-cli/models.js +63 -0
  8. package/dist/resources/extensions/cursor-cli/package.json +11 -0
  9. package/dist/resources/extensions/cursor-cli/readiness.js +128 -0
  10. package/dist/resources/extensions/cursor-cli/stream-adapter.js +353 -0
  11. package/dist/resources/extensions/gsd/activity-log.js +4 -1
  12. package/dist/resources/extensions/gsd/artifact-verification.js +25 -9
  13. package/dist/resources/extensions/gsd/auto/closeout.js +45 -42
  14. package/dist/resources/extensions/gsd/auto/finalize.js +9 -0
  15. package/dist/resources/extensions/gsd/auto/orchestrator.js +1 -1
  16. package/dist/resources/extensions/gsd/auto/run-unit.js +5 -2
  17. package/dist/resources/extensions/gsd/auto/schedule-wakeup.js +3 -0
  18. package/dist/resources/extensions/gsd/auto-dispatch.js +15 -5
  19. package/dist/resources/extensions/gsd/auto-model-selection.js +36 -18
  20. package/dist/resources/extensions/gsd/auto-prompts.js +76 -2
  21. package/dist/resources/extensions/gsd/auto-start.js +4 -3
  22. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -0
  23. package/dist/resources/extensions/gsd/auto-worktree.js +38 -11
  24. package/dist/resources/extensions/gsd/auto.js +23 -3
  25. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -0
  26. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +114 -5
  27. package/dist/resources/extensions/gsd/bootstrap/schedule-wakeup-tool.js +58 -9
  28. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +10 -2
  29. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +14 -1
  30. package/dist/resources/extensions/gsd/codebase-generator.js +157 -19
  31. package/dist/resources/extensions/gsd/commands/handlers/core.js +40 -4
  32. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +153 -1
  33. package/dist/resources/extensions/gsd/commands-worktree.js +11 -2
  34. package/dist/resources/extensions/gsd/db/queries.js +39 -0
  35. package/dist/resources/extensions/gsd/discussion-handoff.js +8 -3
  36. package/dist/resources/extensions/gsd/docs/preferences-reference.md +8 -2
  37. package/dist/resources/extensions/gsd/doctor-engine-checks.js +206 -14
  38. package/dist/resources/extensions/gsd/doctor-providers.js +38 -10
  39. package/dist/resources/extensions/gsd/doctor.js +93 -3
  40. package/dist/resources/extensions/gsd/exec-sandbox.js +6 -2
  41. package/dist/resources/extensions/gsd/flat-phase-migration.js +74 -23
  42. package/dist/resources/extensions/gsd/git-service.js +14 -18
  43. package/dist/resources/extensions/gsd/gsd-db.js +52 -0
  44. package/dist/resources/extensions/gsd/guidance.js +1 -0
  45. package/dist/resources/extensions/gsd/guided-flow.js +40 -2
  46. package/dist/resources/extensions/gsd/key-manager.js +1 -0
  47. package/dist/resources/extensions/gsd/markdown-renderer.js +25 -8
  48. package/dist/resources/extensions/gsd/migrate-external.js +24 -7
  49. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +3 -3
  50. package/dist/resources/extensions/gsd/preferences-diagnostics.js +24 -1
  51. package/dist/resources/extensions/gsd/preferences-models.js +6 -4
  52. package/dist/resources/extensions/gsd/preferences-validation.js +25 -2
  53. package/dist/resources/extensions/gsd/preferences.js +29 -2
  54. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -2
  55. package/dist/resources/extensions/gsd/redact-secrets.js +37 -0
  56. package/dist/resources/extensions/gsd/repo-identity.js +16 -0
  57. package/dist/resources/extensions/gsd/repository-registry.js +6 -1
  58. package/dist/resources/extensions/gsd/root-write-leak-guard.js +4 -2
  59. package/dist/resources/extensions/gsd/safe-fs.js +23 -2
  60. package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
  61. package/dist/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -0
  62. package/dist/resources/extensions/gsd/tools/plan-task.js +76 -8
  63. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +40 -0
  64. package/dist/resources/extensions/gsd/unit-context-manifest.js +5 -4
  65. package/dist/resources/extensions/gsd/unit-registry.js +27 -2
  66. package/dist/resources/extensions/gsd/unit-runtime.js +21 -0
  67. package/dist/resources/extensions/gsd/workspace.js +26 -8
  68. package/dist/resources/extensions/gsd/worktree-lifecycle.js +67 -5
  69. package/dist/resources/extensions/gsd/worktree-manager.js +97 -4
  70. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  71. package/dist/web/standalone/.next/BUILD_ID +1 -1
  72. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  73. package/dist/web/standalone/.next/build-manifest.json +2 -2
  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 +7 -7
  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/node_modules/@gsd/native/package.json +1 -1
  104. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  105. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  106. package/dist/wizard.d.ts +8 -0
  107. package/dist/wizard.js +8 -1
  108. package/integrations/hermes/CONTEXT.md +47 -0
  109. package/integrations/hermes/README.md +21 -0
  110. package/integrations/hermes/__init__.py +31 -0
  111. package/integrations/hermes/docs/issue-1162-grilling.md +197 -0
  112. package/integrations/hermes/docs/setup.md +4 -0
  113. package/integrations/hermes/open_gsd_hermes/commands.py +141 -0
  114. package/integrations/hermes/open_gsd_hermes/config.py +2 -0
  115. package/integrations/hermes/open_gsd_hermes/gsd_client.py +594 -31
  116. package/integrations/hermes/open_gsd_hermes/notifications.py +10 -1
  117. package/integrations/hermes/plugin.yaml +4 -0
  118. package/integrations/hermes/tests/test_config.py +6 -0
  119. package/integrations/hermes/tests/test_directory_loader.py +37 -0
  120. package/integrations/hermes/tests/test_gsd_client_cache.py +3 -0
  121. package/integrations/hermes/tests/test_gsd_client_execute.py +35 -0
  122. package/integrations/hermes/tests/test_gsd_client_process_cwd.py +22 -0
  123. package/integrations/hermes/tests/test_gsd_client_timeout.py +98 -0
  124. package/integrations/hermes/tests/test_milestone_client.py +447 -0
  125. package/integrations/hermes/tests/test_new_milestone_command.py +313 -0
  126. package/integrations/hermes/tests/test_supervisor_fsm.py +40 -0
  127. package/package.json +8 -8
  128. package/packages/cloud-mcp-gateway/dist/auth-store.d.ts +1 -0
  129. package/packages/cloud-mcp-gateway/dist/auth-store.d.ts.map +1 -1
  130. package/packages/cloud-mcp-gateway/dist/auth-store.js +21 -1
  131. package/packages/cloud-mcp-gateway/dist/auth-store.js.map +1 -1
  132. package/packages/cloud-mcp-gateway/dist/auth-store.test.js +34 -0
  133. package/packages/cloud-mcp-gateway/dist/auth-store.test.js.map +1 -1
  134. package/packages/cloud-mcp-gateway/package.json +2 -2
  135. package/packages/contracts/package.json +1 -1
  136. package/packages/daemon/dist/cloud-runtime.d.ts +2 -0
  137. package/packages/daemon/dist/cloud-runtime.d.ts.map +1 -1
  138. package/packages/daemon/dist/cloud-runtime.js +25 -1
  139. package/packages/daemon/dist/cloud-runtime.js.map +1 -1
  140. package/packages/daemon/dist/cloud-runtime.test.js +51 -0
  141. package/packages/daemon/dist/cloud-runtime.test.js.map +1 -1
  142. package/packages/daemon/dist/message-batcher.d.ts +7 -0
  143. package/packages/daemon/dist/message-batcher.d.ts.map +1 -1
  144. package/packages/daemon/dist/message-batcher.js +13 -0
  145. package/packages/daemon/dist/message-batcher.js.map +1 -1
  146. package/packages/daemon/dist/message-batcher.test.js +48 -0
  147. package/packages/daemon/dist/message-batcher.test.js.map +1 -1
  148. package/packages/daemon/dist/session-manager.js +1 -1
  149. package/packages/daemon/dist/session-manager.js.map +1 -1
  150. package/packages/daemon/package.json +5 -5
  151. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts +13 -1
  152. package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
  153. package/packages/gsd-agent-core/dist/compaction/compaction.js +15 -1
  154. package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
  155. package/packages/gsd-agent-core/dist/session/agent-session-navigation.d.ts.map +1 -1
  156. package/packages/gsd-agent-core/dist/session/agent-session-navigation.js +4 -1
  157. package/packages/gsd-agent-core/dist/session/agent-session-navigation.js.map +1 -1
  158. package/packages/gsd-agent-core/package.json +5 -5
  159. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.d.ts.map +1 -1
  160. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js +1 -0
  161. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-segment-walker.js.map +1 -1
  162. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js +1 -1
  163. package/packages/gsd-agent-modes/dist/modes/rpc/rpc-client.js.map +1 -1
  164. package/packages/gsd-agent-modes/package.json +7 -7
  165. package/packages/mcp-server/dist/server.d.ts +18 -5
  166. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  167. package/packages/mcp-server/dist/server.js +46 -5
  168. package/packages/mcp-server/dist/server.js.map +1 -1
  169. package/packages/mcp-server/dist/session-manager.js +1 -1
  170. package/packages/mcp-server/dist/session-manager.js.map +1 -1
  171. package/packages/mcp-server/package.json +4 -4
  172. package/packages/native/package.json +1 -1
  173. package/packages/pi-agent-core/package.json +1 -1
  174. package/packages/pi-ai/dist/env-api-keys.d.ts.map +1 -1
  175. package/packages/pi-ai/dist/env-api-keys.js +3 -0
  176. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  177. package/packages/pi-ai/dist/types.d.ts +2 -2
  178. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  179. package/packages/pi-ai/dist/types.js.map +1 -1
  180. package/packages/pi-ai/package.json +1 -1
  181. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  183. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts +1 -0
  185. package/packages/pi-coding-agent/dist/core/session-manager-types.d.ts.map +1 -1
  186. package/packages/pi-coding-agent/dist/core/session-manager-types.js.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  188. package/packages/pi-coding-agent/dist/core/session-manager.js +3 -0
  189. package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  190. package/packages/pi-coding-agent/package.json +7 -7
  191. package/packages/pi-tui/package.json +2 -2
  192. package/packages/rpc-client/dist/rpc-client.js +1 -1
  193. package/packages/rpc-client/dist/rpc-client.js.map +1 -1
  194. package/packages/rpc-client/package.json +2 -2
  195. package/pkg/package.json +1 -1
  196. package/scripts/link-workspace-packages.cjs +14 -4
  197. package/src/resources/GSD-WORKFLOW.md +20 -25
  198. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +130 -51
  199. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +371 -39
  200. package/src/resources/extensions/cursor-cli/index.ts +18 -0
  201. package/src/resources/extensions/cursor-cli/models.ts +65 -0
  202. package/src/resources/extensions/cursor-cli/package.json +11 -0
  203. package/src/resources/extensions/cursor-cli/readiness.ts +143 -0
  204. package/src/resources/extensions/cursor-cli/stream-adapter.ts +440 -0
  205. package/src/resources/extensions/cursor-cli/tests/index.test.ts +54 -0
  206. package/src/resources/extensions/cursor-cli/tests/readiness.test.ts +29 -0
  207. package/src/resources/extensions/cursor-cli/tests/stream-adapter.test.ts +166 -0
  208. package/src/resources/extensions/gsd/activity-log.ts +4 -1
  209. package/src/resources/extensions/gsd/artifact-verification.ts +25 -9
  210. package/src/resources/extensions/gsd/auto/closeout.ts +54 -56
  211. package/src/resources/extensions/gsd/auto/finalize.ts +8 -0
  212. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  213. package/src/resources/extensions/gsd/auto/orchestrator.ts +1 -1
  214. package/src/resources/extensions/gsd/auto/run-unit.ts +5 -2
  215. package/src/resources/extensions/gsd/auto/schedule-wakeup.ts +8 -0
  216. package/src/resources/extensions/gsd/auto-dispatch.ts +17 -5
  217. package/src/resources/extensions/gsd/auto-model-selection.ts +49 -18
  218. package/src/resources/extensions/gsd/auto-prompts.ts +73 -2
  219. package/src/resources/extensions/gsd/auto-start.ts +4 -3
  220. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +4 -0
  221. package/src/resources/extensions/gsd/auto-worktree.ts +50 -11
  222. package/src/resources/extensions/gsd/auto.ts +22 -3
  223. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -0
  224. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +128 -5
  225. package/src/resources/extensions/gsd/bootstrap/schedule-wakeup-tool.ts +80 -12
  226. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +12 -2
  227. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +23 -1
  228. package/src/resources/extensions/gsd/codebase-generator.ts +179 -18
  229. package/src/resources/extensions/gsd/commands/handlers/core.ts +39 -3
  230. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +135 -1
  231. package/src/resources/extensions/gsd/commands-worktree.ts +13 -2
  232. package/src/resources/extensions/gsd/db/queries.ts +40 -0
  233. package/src/resources/extensions/gsd/discussion-handoff.ts +10 -2
  234. package/src/resources/extensions/gsd/docs/preferences-reference.md +8 -2
  235. package/src/resources/extensions/gsd/doctor-engine-checks.ts +269 -18
  236. package/src/resources/extensions/gsd/doctor-providers.ts +39 -10
  237. package/src/resources/extensions/gsd/doctor-types.ts +5 -1
  238. package/src/resources/extensions/gsd/doctor.ts +95 -3
  239. package/src/resources/extensions/gsd/exec-sandbox.ts +6 -2
  240. package/src/resources/extensions/gsd/flat-phase-migration.ts +98 -22
  241. package/src/resources/extensions/gsd/git-service.ts +14 -17
  242. package/src/resources/extensions/gsd/gsd-db.ts +72 -0
  243. package/src/resources/extensions/gsd/guidance.ts +2 -0
  244. package/src/resources/extensions/gsd/guided-flow.ts +45 -2
  245. package/src/resources/extensions/gsd/key-manager.ts +1 -0
  246. package/src/resources/extensions/gsd/markdown-renderer.ts +25 -7
  247. package/src/resources/extensions/gsd/migrate-external.ts +23 -6
  248. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +4 -4
  249. package/src/resources/extensions/gsd/model-router.ts +4 -5
  250. package/src/resources/extensions/gsd/preferences-diagnostics.ts +24 -0
  251. package/src/resources/extensions/gsd/preferences-models.ts +6 -3
  252. package/src/resources/extensions/gsd/preferences-validation.ts +28 -2
  253. package/src/resources/extensions/gsd/preferences.ts +38 -4
  254. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -2
  255. package/src/resources/extensions/gsd/redact-secrets.ts +40 -0
  256. package/src/resources/extensions/gsd/repo-identity.ts +17 -0
  257. package/src/resources/extensions/gsd/repository-registry.ts +7 -1
  258. package/src/resources/extensions/gsd/root-write-leak-guard.ts +3 -2
  259. package/src/resources/extensions/gsd/safe-fs.ts +22 -2
  260. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +7 -9
  261. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +1 -0
  262. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +131 -5
  263. package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +18 -0
  264. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +178 -0
  265. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +43 -1
  266. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +54 -0
  267. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +41 -0
  268. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +41 -0
  269. package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +4 -4
  270. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +3 -0
  271. package/src/resources/extensions/gsd/tests/auto-timeout-recovery-harness-abort.test.ts +55 -0
  272. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +8 -0
  273. package/src/resources/extensions/gsd/tests/batch-task-query.test.ts +85 -0
  274. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +29 -0
  275. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +365 -0
  276. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +62 -1
  277. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +138 -1
  278. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +397 -5
  279. package/src/resources/extensions/gsd/tests/doctor-workspace.test.ts +207 -0
  280. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +38 -1
  281. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +87 -19
  282. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +89 -0
  283. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +9 -0
  284. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
  285. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +122 -0
  286. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +4 -4
  287. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +116 -0
  288. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +152 -22
  289. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +1 -1
  290. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +2 -2
  291. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +50 -6
  292. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +17 -0
  293. package/src/resources/extensions/gsd/tests/plan-task.test.ts +264 -1
  294. package/src/resources/extensions/gsd/tests/preferences.test.ts +150 -0
  295. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +142 -0
  296. package/src/resources/extensions/gsd/tests/recovery-verify-logs.test.ts +4 -4
  297. package/src/resources/extensions/gsd/tests/redact-secrets.test.ts +56 -0
  298. package/src/resources/extensions/gsd/tests/register-hooks-flat-phase-migration.test.ts +73 -0
  299. package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +275 -0
  300. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +41 -2
  301. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +55 -0
  302. package/src/resources/extensions/gsd/tests/root-write-leak-guard.test.ts +31 -9
  303. package/src/resources/extensions/gsd/tests/schedule-wakeup-tool.test.ts +167 -0
  304. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -0
  305. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -1
  306. package/src/resources/extensions/gsd/tests/status-per-repo.test.ts +94 -0
  307. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +35 -0
  308. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +63 -0
  309. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +66 -18
  310. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +56 -0
  311. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +30 -0
  312. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +52 -0
  313. package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +53 -1
  314. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +208 -1
  315. package/src/resources/extensions/gsd/tests/workspace.test.ts +18 -4
  316. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +4 -4
  317. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +2 -2
  318. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +31 -1
  319. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +32 -0
  320. package/src/resources/extensions/gsd/tools/plan-task.ts +107 -9
  321. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +58 -0
  322. package/src/resources/extensions/gsd/unit-context-manifest.ts +11 -5
  323. package/src/resources/extensions/gsd/unit-registry.ts +34 -2
  324. package/src/resources/extensions/gsd/unit-runtime.ts +42 -0
  325. package/src/resources/extensions/gsd/workspace.ts +42 -8
  326. package/src/resources/extensions/gsd/worktree-lifecycle.ts +135 -11
  327. package/src/resources/extensions/gsd/worktree-manager.ts +143 -5
  328. /package/dist/web/standalone/.next/static/{zQLcXm0Za8lexoXtgDpMG → bCg3aYrFN1DKZr2dqgE7L}/_buildManifest.js +0 -0
  329. /package/dist/web/standalone/.next/static/{zQLcXm0Za8lexoXtgDpMG → bCg3aYrFN1DKZr2dqgE7L}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"message-batcher.test.js","sourceRoot":"","sources":["../src/message-batcher.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, beforeEach, afterEach, mock } from 'node:test';\nimport assert from 'node:assert/strict';\nimport { MessageBatcher } from './message-batcher.js';\nimport type { SendPayload, BatcherLogger } from './message-batcher.js';\nimport type { FormattedEvent } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Create a minimal FormattedEvent for testing. */\nfunction fakeEvent(content: string, hasEmbed = false): FormattedEvent {\n const fe: FormattedEvent = { content };\n if (hasEmbed) {\n // Minimal mock embed — just needs to be truthy and pass through\n fe.embed = { data: { title: content } } as any;\n }\n return fe;\n}\n\n/** Create a tracking send function. */\nfunction createSend() {\n const calls: SendPayload[] = [];\n const fn = mock.fn(async (payload: SendPayload) => {\n calls.push(payload);\n });\n return { fn, calls };\n}\n\n/** Create a logger that captures error/warn calls. */\nfunction createLogger() {\n const errors: string[] = [];\n const warns: string[] = [];\n const debugs: string[] = [];\n const logger: BatcherLogger = {\n error(msg: string) { errors.push(msg); },\n warn(msg: string) { warns.push(msg); },\n debug(msg: string) { debugs.push(msg); },\n };\n return { logger, errors, warns, debugs };\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe('MessageBatcher', () => {\n describe('enqueue + capacity flush', () => {\n it('flushes when buffer reaches maxBatchSize', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 3, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('a'));\n batcher.enqueue(fakeEvent('b'));\n assert.equal(calls.length, 0, 'should not flush yet');\n\n batcher.enqueue(fakeEvent('c')); // hits capacity\n // flush is async — give it a tick\n await new Promise((r) => setTimeout(r, 10));\n\n assert.equal(calls.length, 1, 'should have flushed once');\n assert.equal(calls[0].content, 'a\\nb\\nc');\n assert.equal(batcher.pending, 0);\n\n await batcher.destroy();\n });\n\n it('skips embeds for batched messages (only content)', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 2, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('a', true));\n batcher.enqueue(fakeEvent('b', true)); // triggers flush\n await new Promise((r) => setTimeout(r, 10));\n\n assert.equal(calls.length, 1);\n assert.equal(calls[0].embeds.length, 0, 'batched sends skip embeds to avoid duplication');\n assert.equal(calls[0].content, 'a\\nb');\n\n await batcher.destroy();\n });\n });\n\n describe('enqueueImmediate', () => {\n it('flushes pending buffer then sends immediately', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 10, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('buffered-1'));\n batcher.enqueue(fakeEvent('buffered-2'));\n\n await batcher.enqueueImmediate(fakeEvent('blocker!'));\n\n // First call: the pending buffer flush\n // Second call: the immediate event\n assert.equal(calls.length, 2, 'should have two send calls');\n assert.equal(calls[0].content, 'buffered-1\\nbuffered-2');\n assert.equal(calls[1].content, 'blocker!');\n assert.equal(batcher.pending, 0);\n\n await batcher.destroy();\n });\n\n it('sends immediately when buffer is empty', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 10, flushIntervalMs: 60_000 });\n\n await batcher.enqueueImmediate(fakeEvent('urgent'));\n\n assert.equal(calls.length, 1);\n assert.equal(calls[0].content, 'urgent');\n\n await batcher.destroy();\n });\n });\n\n describe('timer-based flush', () => {\n it('flushes on interval', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 50 });\n batcher.start();\n\n batcher.enqueue(fakeEvent('timed-1'));\n batcher.enqueue(fakeEvent('timed-2'));\n\n // Wait longer than flushIntervalMs\n await new Promise((r) => setTimeout(r, 120));\n\n assert.ok(calls.length >= 1, 'timer should have triggered at least one flush');\n assert.equal(calls[0].content, 'timed-1\\ntimed-2');\n assert.equal(batcher.pending, 0);\n\n await batcher.destroy();\n });\n\n it('stop prevents further timer flushes', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 30 });\n batcher.start();\n batcher.stop();\n\n batcher.enqueue(fakeEvent('orphan'));\n await new Promise((r) => setTimeout(r, 80));\n\n assert.equal(calls.length, 0, 'no flush after stop');\n // Cleanup without triggering flush timer\n batcher.stop(); // idempotent\n // Manually drain for cleanup\n await batcher.destroy();\n });\n });\n\n describe('destroy', () => {\n it('flushes remaining buffer on destroy', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('leftover-1'));\n batcher.enqueue(fakeEvent('leftover-2'));\n\n await batcher.destroy();\n\n assert.equal(calls.length, 1);\n assert.equal(calls[0].content, 'leftover-1\\nleftover-2');\n });\n\n it('is idempotent — second destroy is no-op', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('once'));\n await batcher.destroy();\n await batcher.destroy(); // second call\n\n assert.equal(calls.length, 1, 'only flushed once');\n });\n\n it('enqueue after destroy is silently ignored', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 2, flushIntervalMs: 60_000 });\n await batcher.destroy();\n\n batcher.enqueue(fakeEvent('post-destroy'));\n await new Promise((r) => setTimeout(r, 10));\n\n assert.equal(calls.length, 0, 'no sends after destroy');\n });\n });\n\n describe('empty buffer', () => {\n it('flush of empty buffer is no-op', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 60_000 });\n batcher.start();\n\n // Force a timer tick with an empty buffer\n await new Promise((r) => setTimeout(r, 10));\n await batcher.destroy();\n\n // Only the destroy-triggered flush, which should also be a no-op\n assert.equal(calls.length, 0, 'no sends for empty buffer');\n });\n });\n\n describe('single-item flush', () => {\n it('handles a single item in buffer at destroy', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('solo'));\n await batcher.destroy();\n\n assert.equal(calls.length, 1);\n assert.equal(calls[0].content, 'solo');\n assert.equal(calls[0].embeds.length, 0);\n assert.equal(calls[0].components.length, 0);\n });\n });\n\n describe('error handling', () => {\n it('logs error and continues when send throws', async () => {\n let attempt = 0;\n const sendFn = async () => {\n attempt++;\n throw new Error('Discord rate limit');\n };\n const { logger, errors, warns } = createLogger();\n const batcher = new MessageBatcher(sendFn, logger, { maxBatchSize: 2, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('x'));\n batcher.enqueue(fakeEvent('y')); // triggers flush\n // Wait for flush + retry\n await new Promise((r) => setTimeout(r, 1500));\n\n assert.ok(errors.length >= 1, 'should have logged an error');\n assert.ok(warns.length >= 1, 'should have logged a warning on retry failure');\n assert.equal(batcher.pending, 0, 'buffer cleared even on error');\n\n // Batcher should still be alive — enqueue more\n batcher.enqueue(fakeEvent('after-error'));\n assert.equal(batcher.pending, 1, 'can still enqueue after error');\n\n await batcher.destroy();\n });\n\n it('succeeds on retry if first attempt fails', async () => {\n let attempt = 0;\n const calls: SendPayload[] = [];\n const sendFn = async (payload: SendPayload) => {\n attempt++;\n if (attempt === 1) throw new Error('transient');\n calls.push(payload);\n };\n const { logger, errors } = createLogger();\n const batcher = new MessageBatcher(sendFn, logger, { maxBatchSize: 2, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('retry-me'));\n batcher.enqueue(fakeEvent('retry-too'));\n // Wait for flush + retry delay\n await new Promise((r) => setTimeout(r, 1500));\n\n assert.equal(errors.length, 1, 'logged one error on first attempt');\n assert.equal(calls.length, 1, 'retry succeeded');\n assert.equal(calls[0].content, 'retry-me\\nretry-too');\n\n await batcher.destroy();\n });\n });\n\n describe('buffer at exactly capacity', () => {\n it('flushes at exactly maxBatchSize', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 4, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('1'));\n batcher.enqueue(fakeEvent('2'));\n batcher.enqueue(fakeEvent('3'));\n assert.equal(calls.length, 0, 'not flushed at 3/4');\n\n batcher.enqueue(fakeEvent('4')); // exactly at capacity\n await new Promise((r) => setTimeout(r, 10));\n\n assert.equal(calls.length, 1);\n assert.equal(calls[0].content, '1\\n2\\n3\\n4');\n\n await batcher.destroy();\n });\n });\n\n describe('components handling', () => {\n it('uses components from the last event that has them', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 3, flushIntervalMs: 60_000 });\n\n const fakeRow = { type: 'ActionRow', components: [] };\n batcher.enqueue(fakeEvent('no-components'));\n batcher.enqueue({ content: 'with-components', components: [fakeRow] } as any);\n batcher.enqueue(fakeEvent('also-no-components')); // triggers flush\n\n await new Promise((r) => setTimeout(r, 10));\n\n assert.equal(calls.length, 1);\n assert.deepEqual(calls[0].components, [fakeRow]);\n\n await batcher.destroy();\n });\n });\n});\n"]}
1
+ {"version":3,"file":"message-batcher.test.js","sourceRoot":"","sources":["../src/message-batcher.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, beforeEach, afterEach, mock } from 'node:test';\nimport assert from 'node:assert/strict';\nimport { MessageBatcher } from './message-batcher.js';\nimport type { SendPayload, BatcherLogger } from './message-batcher.js';\nimport type { FormattedEvent } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Create a minimal FormattedEvent for testing. */\nfunction fakeEvent(content: string, hasEmbed = false): FormattedEvent {\n const fe: FormattedEvent = { content };\n if (hasEmbed) {\n // Minimal mock embed — just needs to be truthy and pass through\n fe.embed = { data: { title: content } } as any;\n }\n return fe;\n}\n\n/** Create a tracking send function. */\nfunction createSend() {\n const calls: SendPayload[] = [];\n const fn = mock.fn(async (payload: SendPayload) => {\n calls.push(payload);\n });\n return { fn, calls };\n}\n\n/** Create a logger that captures error/warn calls. */\nfunction createLogger() {\n const errors: string[] = [];\n const warns: string[] = [];\n const debugs: string[] = [];\n const logger: BatcherLogger = {\n error(msg: string) { errors.push(msg); },\n warn(msg: string) { warns.push(msg); },\n debug(msg: string) { debugs.push(msg); },\n };\n return { logger, errors, warns, debugs };\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe('MessageBatcher', () => {\n describe('enqueue + capacity flush', () => {\n it('flushes when buffer reaches maxBatchSize', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 3, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('a'));\n batcher.enqueue(fakeEvent('b'));\n assert.equal(calls.length, 0, 'should not flush yet');\n\n batcher.enqueue(fakeEvent('c')); // hits capacity\n // flush is async — give it a tick\n await new Promise((r) => setTimeout(r, 10));\n\n assert.equal(calls.length, 1, 'should have flushed once');\n assert.equal(calls[0].content, 'a\\nb\\nc');\n assert.equal(batcher.pending, 0);\n\n await batcher.destroy();\n });\n\n it('skips embeds for batched messages (only content)', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 2, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('a', true));\n batcher.enqueue(fakeEvent('b', true)); // triggers flush\n await new Promise((r) => setTimeout(r, 10));\n\n assert.equal(calls.length, 1);\n assert.equal(calls[0].embeds.length, 0, 'batched sends skip embeds to avoid duplication');\n assert.equal(calls[0].content, 'a\\nb');\n\n await batcher.destroy();\n });\n });\n\n describe('enqueueImmediate', () => {\n it('flushes pending buffer then sends immediately', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 10, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('buffered-1'));\n batcher.enqueue(fakeEvent('buffered-2'));\n\n await batcher.enqueueImmediate(fakeEvent('blocker!'));\n\n // First call: the pending buffer flush\n // Second call: the immediate event\n assert.equal(calls.length, 2, 'should have two send calls');\n assert.equal(calls[0].content, 'buffered-1\\nbuffered-2');\n assert.equal(calls[1].content, 'blocker!');\n assert.equal(batcher.pending, 0);\n\n await batcher.destroy();\n });\n\n it('sends immediately when buffer is empty', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 10, flushIntervalMs: 60_000 });\n\n await batcher.enqueueImmediate(fakeEvent('urgent'));\n\n assert.equal(calls.length, 1);\n assert.equal(calls[0].content, 'urgent');\n\n await batcher.destroy();\n });\n });\n\n describe('timer-based flush', () => {\n it('flushes on interval', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 50 });\n batcher.start();\n\n batcher.enqueue(fakeEvent('timed-1'));\n batcher.enqueue(fakeEvent('timed-2'));\n\n // Wait longer than flushIntervalMs\n await new Promise((r) => setTimeout(r, 120));\n\n assert.ok(calls.length >= 1, 'timer should have triggered at least one flush');\n assert.equal(calls[0].content, 'timed-1\\ntimed-2');\n assert.equal(batcher.pending, 0);\n\n await batcher.destroy();\n });\n\n it('stop prevents further timer flushes', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 30 });\n batcher.start();\n batcher.stop();\n\n batcher.enqueue(fakeEvent('orphan'));\n await new Promise((r) => setTimeout(r, 80));\n\n assert.equal(calls.length, 0, 'no flush after stop');\n // Cleanup without triggering flush timer\n batcher.stop(); // idempotent\n // Manually drain for cleanup\n await batcher.destroy();\n });\n });\n\n describe('destroy', () => {\n it('flushes remaining buffer on destroy', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('leftover-1'));\n batcher.enqueue(fakeEvent('leftover-2'));\n\n await batcher.destroy();\n\n assert.equal(calls.length, 1);\n assert.equal(calls[0].content, 'leftover-1\\nleftover-2');\n });\n\n it('is idempotent — second destroy is no-op', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('once'));\n await batcher.destroy();\n await batcher.destroy(); // second call\n\n assert.equal(calls.length, 1, 'only flushed once');\n });\n\n it('enqueue after destroy is silently ignored', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 2, flushIntervalMs: 60_000 });\n await batcher.destroy();\n\n batcher.enqueue(fakeEvent('post-destroy'));\n await new Promise((r) => setTimeout(r, 10));\n\n assert.equal(calls.length, 0, 'no sends after destroy');\n });\n });\n\n describe('empty buffer', () => {\n it('flush of empty buffer is no-op', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 60_000 });\n batcher.start();\n\n // Force a timer tick with an empty buffer\n await new Promise((r) => setTimeout(r, 10));\n await batcher.destroy();\n\n // Only the destroy-triggered flush, which should also be a no-op\n assert.equal(calls.length, 0, 'no sends for empty buffer');\n });\n });\n\n describe('single-item flush', () => {\n it('handles a single item in buffer at destroy', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('solo'));\n await batcher.destroy();\n\n assert.equal(calls.length, 1);\n assert.equal(calls[0].content, 'solo');\n assert.equal(calls[0].embeds.length, 0);\n assert.equal(calls[0].components.length, 0);\n });\n });\n\n describe('error handling', () => {\n it('logs error and continues when send throws', async () => {\n let attempt = 0;\n const sendFn = async () => {\n attempt++;\n throw new Error('Discord rate limit');\n };\n const { logger, errors, warns } = createLogger();\n const batcher = new MessageBatcher(sendFn, logger, { maxBatchSize: 2, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('x'));\n batcher.enqueue(fakeEvent('y')); // triggers flush\n // Wait for flush + retry\n await new Promise((r) => setTimeout(r, 1500));\n\n assert.ok(errors.length >= 1, 'should have logged an error');\n assert.ok(warns.length >= 1, 'should have logged a warning on retry failure');\n assert.equal(batcher.pending, 0, 'buffer cleared even on error');\n\n // Batcher should still be alive — enqueue more\n batcher.enqueue(fakeEvent('after-error'));\n assert.equal(batcher.pending, 1, 'can still enqueue after error');\n\n await batcher.destroy();\n });\n\n it('succeeds on retry if first attempt fails', async () => {\n let attempt = 0;\n const calls: SendPayload[] = [];\n const sendFn = async (payload: SendPayload) => {\n attempt++;\n if (attempt === 1) throw new Error('transient');\n calls.push(payload);\n };\n const { logger, errors } = createLogger();\n const batcher = new MessageBatcher(sendFn, logger, { maxBatchSize: 2, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('retry-me'));\n batcher.enqueue(fakeEvent('retry-too'));\n // Wait for flush + retry delay\n await new Promise((r) => setTimeout(r, 1500));\n\n assert.equal(errors.length, 1, 'logged one error on first attempt');\n assert.equal(calls.length, 1, 'retry succeeded');\n assert.equal(calls[0].content, 'retry-me\\nretry-too');\n\n await batcher.destroy();\n });\n });\n\n describe('buffer at exactly capacity', () => {\n it('flushes at exactly maxBatchSize', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 4, flushIntervalMs: 60_000 });\n\n batcher.enqueue(fakeEvent('1'));\n batcher.enqueue(fakeEvent('2'));\n batcher.enqueue(fakeEvent('3'));\n assert.equal(calls.length, 0, 'not flushed at 3/4');\n\n batcher.enqueue(fakeEvent('4')); // exactly at capacity\n await new Promise((r) => setTimeout(r, 10));\n\n assert.equal(calls.length, 1);\n assert.equal(calls[0].content, '1\\n2\\n3\\n4');\n\n await batcher.destroy();\n });\n });\n\n describe('components handling', () => {\n it('uses components from the last event that has them', async () => {\n const { fn, calls } = createSend();\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 3, flushIntervalMs: 60_000 });\n\n const fakeRow = { type: 'ActionRow', components: [] };\n batcher.enqueue(fakeEvent('no-components'));\n batcher.enqueue({ content: 'with-components', components: [fakeRow] } as any);\n batcher.enqueue(fakeEvent('also-no-components')); // triggers flush\n\n await new Promise((r) => setTimeout(r, 10));\n\n assert.equal(calls.length, 1);\n assert.deepEqual(calls[0].components, [fakeRow]);\n\n await batcher.destroy();\n });\n });\n\n describe('buffer cap (maxBufferSize)', () => {\n it('caps the buffer at maxBufferSize, dropping oldest', async () => {\n const { fn, calls } = createSend();\n // maxBatchSize high so capacity flush never fires; small maxBufferSize.\n const batcher = new MessageBatcher(fn, undefined, { maxBatchSize: 100, maxBufferSize: 3, flushIntervalMs: 60_000 });\n for (let i = 0; i < 10; i++) batcher.enqueue(fakeEvent(`e${i}`));\n assert.equal(batcher.pending, 3);\n await batcher.destroy();\n // Only the newest three survived; e0..e6 were dropped.\n assert.equal(calls.length, 1);\n assert.equal(calls[0].content, 'e7\\ne8\\ne9');\n });\n\n it('warns once per saturation, not once per dropped event', async () => {\n const { fn } = createSend();\n const { logger, warns } = createLogger();\n const batcher = new MessageBatcher(fn, logger, { maxBatchSize: 100, maxBufferSize: 3, flushIntervalMs: 60_000 });\n for (let i = 0; i < 10; i++) batcher.enqueue(fakeEvent(`e${i}`));\n assert.equal(warns.filter((w) => w.includes('saturated')).length, 1);\n await batcher.destroy();\n });\n\n it('allows a fresh saturation warning after the buffer drains', async () => {\n const { fn } = createSend();\n const { logger, warns } = createLogger();\n const batcher = new MessageBatcher(fn, logger, { maxBatchSize: 100, maxBufferSize: 3, flushIntervalMs: 60_000 });\n for (let i = 0; i < 10; i++) batcher.enqueue(fakeEvent(`a${i}`));\n // enqueueImmediate flushes the buffer first, draining it and resetting saturation.\n await batcher.enqueueImmediate(fakeEvent('drain'));\n assert.equal(batcher.pending, 0);\n for (let i = 0; i < 10; i++) batcher.enqueue(fakeEvent(`b${i}`));\n assert.equal(warns.filter((w) => w.includes('saturated')).length, 2);\n await batcher.destroy();\n });\n\n it('does not drop or warn under default options', async () => {\n const { fn, calls } = createSend();\n const { logger, warns } = createLogger();\n const batcher = new MessageBatcher(fn, logger, { flushIntervalMs: 60_000 }); // default cap 1000\n batcher.enqueue(fakeEvent('1'));\n batcher.enqueue(fakeEvent('2'));\n assert.equal(batcher.pending, 2);\n assert.equal(warns.filter((w) => w.includes('saturated')).length, 0);\n await batcher.destroy();\n assert.equal(calls[0].content, '1\\n2');\n });\n });\n});\n"]}
@@ -97,7 +97,7 @@ export class SessionManager extends EventEmitter {
97
97
  }
98
98
  }
99
99
  const cliPath = options.cliPath ?? SessionManager.resolveCLIPath();
100
- const args = ['--mode', 'rpc'];
100
+ const args = [];
101
101
  if (options.model)
102
102
  args.push('--model', options.model);
103
103
  if (options.bare)
@@ -1 +1 @@
1
- {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SessionManager — manages RpcClient lifecycle for daemon-driven GSD execution.\n *\n * Extends EventEmitter to emit typed session lifecycle events.\n * One active session per projectDir. Tracks events in a ring buffer,\n * detects blockers, tracks terminal state, and accumulates cost using\n * the cumulative-max pattern (K004).\n *\n * Adapted from packages/mcp-server/src/session-manager.ts with:\n * - Logger integration for structured logging\n * - EventEmitter for session lifecycle events\n * - getAllSessions() for cross-project status (R035)\n * - projectName field on ManagedSession\n */\n\nimport { execSync } from 'node:child_process';\nimport { basename, resolve } from 'node:path';\nimport { EventEmitter } from 'node:events';\nimport { RpcClient } from '@opengsd/rpc-client';\nimport type { RpcCostUpdateEvent, RpcExtensionUIRequest, RpcInitResult, SdkAgentEvent } from '@opengsd/contracts';\nimport type {\n ManagedSession,\n StartSessionOptions,\n PendingBlocker,\n} from './types.js';\nimport { MAX_EVENTS, INIT_TIMEOUT_MS } from './types.js';\nimport type { Logger } from './logger.js';\n\n// ---------------------------------------------------------------------------\n// Inlined detection logic (from headless-events.ts — no internal package imports)\n// ---------------------------------------------------------------------------\n\nconst FIRE_AND_FORGET_METHODS = new Set([\n 'notify', 'setStatus', 'setWidget', 'setTitle', 'set_editor_text',\n]);\n\nconst TERMINAL_PREFIXES = [\n 'auto-mode stopped',\n 'step-mode stopped',\n 'auto-mode complete',\n 'no active milestone',\n 'auto-mode idle',\n];\n\nfunction isTerminalNotification(event: Record<string, unknown>): boolean {\n if (event.type !== 'extension_ui_request' || event.method !== 'notify') return false;\n const message = String(event.message ?? '').toLowerCase();\n return TERMINAL_PREFIXES.some((prefix) => message.startsWith(prefix));\n}\n\nfunction isBlockedNotification(event: Record<string, unknown>): boolean {\n if (event.type !== 'extension_ui_request' || event.method !== 'notify') return false;\n const message = String(event.message ?? '').toLowerCase();\n return message.includes('blocked:');\n}\n\nfunction isBlockingUIRequest(event: Record<string, unknown>): boolean {\n if (event.type !== 'extension_ui_request') return false;\n const method = String(event.method ?? '');\n return !FIRE_AND_FORGET_METHODS.has(method);\n}\n\n// ---------------------------------------------------------------------------\n// SessionManager\n// ---------------------------------------------------------------------------\n\n/** Terminal lifecycle states — work is finished, process may be reclaimed. */\nconst TERMINAL_STATUSES: ReadonlySet<string> = new Set(['completed', 'error', 'cancelled']);\n\n/**\n * How many terminal (completed/cancelled/errored) sessions to retain for\n * inspection before evicting the oldest. Bounds heap growth on a daemon that\n * services many distinct project dirs over its lifetime — without this, every\n * session ever run stays resident forever (events buffer + RpcClient ref).\n */\nconst MAX_TERMINAL_SESSIONS = 50;\n\nexport class SessionManager extends EventEmitter {\n /** Sessions keyed by resolved projectDir for duplicate-start prevention */\n private sessions = new Map<string, ManagedSession>();\n\n /** Resolved dirs of terminal sessions, oldest-first — for bounded retention. */\n private terminalOrder: string[] = [];\n\n constructor(private readonly logger: Logger) {\n super();\n }\n\n /**\n * Start a new GSD auto-mode session for the given project directory.\n *\n * Rejects if a session already exists for this projectDir.\n * Creates an RpcClient, starts the process, performs the v2 init handshake,\n * wires event tracking, and sends '/gsd auto' to begin execution.\n */\n async startSession(options: StartSessionOptions): Promise<string> {\n const { projectDir } = options;\n\n if (!projectDir || projectDir.trim() === '') {\n throw new Error('projectDir is required and cannot be empty');\n }\n\n const resolvedDir = resolve(projectDir);\n const projectName = basename(resolvedDir);\n\n const existing = this.sessions.get(resolvedDir);\n if (existing) {\n // A terminal session (completed/cancelled/error) is retained only for\n // inspection — it must not block a fresh start for the same dir. Evict it\n // and reclaim its process before starting anew.\n if (TERMINAL_STATUSES.has(existing.status)) {\n this.evictSession(resolvedDir);\n } else {\n throw new Error(\n `Session already active for ${resolvedDir} (sessionId: ${existing.sessionId}, status: ${existing.status})`\n );\n }\n }\n\n const cliPath = options.cliPath ?? SessionManager.resolveCLIPath();\n\n const args: string[] = ['--mode', 'rpc'];\n if (options.model) args.push('--model', options.model);\n if (options.bare) args.push('--bare');\n\n const client = new RpcClient({\n cliPath,\n cwd: resolvedDir,\n args,\n });\n\n // Build the session shell before async operations so we can track state\n const session: ManagedSession = {\n sessionId: '', // filled after init\n projectDir: resolvedDir,\n projectName,\n status: 'starting',\n client,\n events: [],\n pendingBlocker: null,\n cost: { totalCost: 0, tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 } },\n startTime: Date.now(),\n };\n\n // Insert into map early (keyed by dir) so concurrent starts are rejected\n this.sessions.set(resolvedDir, session);\n\n try {\n // Start the process with timeout\n await Promise.race([\n client.start(),\n timeout(INIT_TIMEOUT_MS, `RpcClient.start() timed out after ${INIT_TIMEOUT_MS}ms`),\n ]);\n\n // Perform v2 init handshake\n const initResult: RpcInitResult = await Promise.race([\n client.init(),\n timeout(INIT_TIMEOUT_MS, `RpcClient.init() timed out after ${INIT_TIMEOUT_MS}ms`),\n ]) as RpcInitResult;\n\n session.sessionId = initResult.sessionId;\n session.status = 'running';\n\n // Wire event tracking\n session.unsubscribe = client.onEvent((event: SdkAgentEvent) => {\n this.handleEvent(session, event);\n });\n\n // Kick off auto-mode\n const command = options.command ?? '/gsd auto';\n await client.prompt(command);\n\n this.logger.info('session started', { sessionId: session.sessionId, projectDir: resolvedDir });\n this.emit('session:started', { sessionId: session.sessionId, projectDir: resolvedDir, projectName });\n\n return session.sessionId;\n } catch (err) {\n session.status = 'error';\n session.error = err instanceof Error ? err.message : String(err);\n\n // Attempt cleanup\n try { await client.stop(); } catch { /* swallow cleanup errors */ }\n\n this.logger.error('session error', { sessionId: session.sessionId, projectDir: resolvedDir, error: session.error });\n this.emit('session:error', { sessionId: session.sessionId, projectDir: resolvedDir, projectName, error: session.error });\n\n // Keep session in map so callers can inspect the error, but under the\n // bounded terminal-retention policy so it is eventually reclaimed.\n this.markTerminal(resolvedDir);\n throw new Error(`Failed to start session for ${resolvedDir}: ${session.error}`);\n }\n }\n\n /**\n * Look up a session by sessionId.\n * Linear scan is fine — we expect <10 concurrent sessions.\n */\n getSession(sessionId: string): ManagedSession | undefined {\n for (const session of this.sessions.values()) {\n if (session.sessionId === sessionId) return session;\n }\n return undefined;\n }\n\n /**\n * Look up a session by project directory (direct map lookup).\n */\n getSessionByDir(projectDir: string): ManagedSession | undefined {\n return this.sessions.get(resolve(projectDir));\n }\n\n /**\n * Return all tracked sessions (R035 — cross-project status).\n */\n getAllSessions(): ManagedSession[] {\n return Array.from(this.sessions.values());\n }\n\n /**\n * Resolve a pending blocker by sending a UI response.\n */\n async resolveBlocker(sessionId: string, response: string): Promise<void> {\n const session = this.getSession(sessionId);\n if (!session) throw new Error(`Session not found: ${sessionId}`);\n if (!session.pendingBlocker) throw new Error(`No pending blocker for session ${sessionId}`);\n\n const blocker = session.pendingBlocker;\n session.client.sendUIResponse(blocker.id, { value: response });\n session.pendingBlocker = null;\n if (session.status === 'blocked') {\n session.status = 'running';\n }\n\n this.logger.info('blocker resolved', {\n sessionId,\n projectDir: session.projectDir,\n blockerId: blocker.id,\n blockerMethod: blocker.method,\n });\n }\n\n /**\n * Cancel a running session — abort current operation then stop the process.\n */\n async cancelSession(sessionId: string): Promise<void> {\n const session = this.getSession(sessionId);\n if (!session) throw new Error(`Session not found: ${sessionId}`);\n\n try {\n await session.client.abort();\n } catch { /* may already be stopped */ }\n\n try {\n await session.client.stop();\n } catch { /* swallow */ }\n\n session.status = 'cancelled';\n session.unsubscribe?.();\n session.unsubscribe = undefined;\n\n this.logger.info('session cancelled', { sessionId, projectDir: session.projectDir });\n\n // Symmetric teardown: notify listeners (EventBridge) so they can dispose the\n // session's batcher, channel mappings, and any blocker collectors — the\n // start path emits 'session:started', so cancel must emit too.\n this.emit('session:cancelled', {\n sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n });\n\n this.markTerminal(session.projectDir);\n }\n\n async cancelSessionByDir(projectDir: string): Promise<void> {\n const session = this.getSessionByDir(projectDir);\n if (!session) throw new Error(`Session not found for projectDir: ${projectDir}`);\n await this.cancelSession(session.sessionId);\n }\n\n /**\n * Build a HeadlessJsonResult-shaped object from accumulated session state.\n */\n getResult(sessionId: string): Record<string, unknown> {\n const session = this.getSession(sessionId);\n if (!session) throw new Error(`Session not found: ${sessionId}`);\n\n const durationMs = Date.now() - session.startTime;\n\n return {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n status: session.status,\n durationMs,\n cost: session.cost,\n recentEvents: session.events.slice(-10),\n pendingBlocker: session.pendingBlocker\n ? { id: session.pendingBlocker.id, method: session.pendingBlocker.method, message: session.pendingBlocker.message }\n : null,\n error: session.error ?? null,\n };\n }\n\n /**\n * Stop all active sessions and clean up resources.\n */\n async cleanup(): Promise<void> {\n const stopPromises: Promise<void>[] = [];\n\n for (const session of this.sessions.values()) {\n session.unsubscribe?.();\n if (session.status === 'running' || session.status === 'starting' || session.status === 'blocked') {\n stopPromises.push(\n session.client.stop().catch(() => { /* swallow */ })\n );\n session.status = 'cancelled';\n }\n }\n\n await Promise.allSettled(stopPromises);\n\n this.sessions.clear();\n this.terminalOrder = [];\n }\n\n // ---------------------------------------------------------------------------\n // Private: Terminal-session retention (bounded)\n // ---------------------------------------------------------------------------\n\n /**\n * Record a session (by resolved dir) as terminal and evict the oldest\n * terminal sessions once the retention cap is exceeded. Retains recent\n * terminal sessions for inspection while bounding heap growth.\n */\n private markTerminal(resolvedDir: string): void {\n // Move to most-recent position (dedupe if it was already terminal).\n const existingIdx = this.terminalOrder.indexOf(resolvedDir);\n if (existingIdx !== -1) this.terminalOrder.splice(existingIdx, 1);\n this.terminalOrder.push(resolvedDir);\n\n while (this.terminalOrder.length > MAX_TERMINAL_SESSIONS) {\n const oldest = this.terminalOrder.shift();\n if (oldest) this.evictSession(oldest);\n }\n }\n\n /**\n * Remove a session from tracking and best-effort reclaim its agent process.\n */\n private evictSession(resolvedDir: string): void {\n const session = this.sessions.get(resolvedDir);\n this.sessions.delete(resolvedDir);\n const orderIdx = this.terminalOrder.indexOf(resolvedDir);\n if (orderIdx !== -1) this.terminalOrder.splice(orderIdx, 1);\n\n if (session) {\n session.unsubscribe?.();\n session.unsubscribe = undefined;\n // The agent child process may still be alive (e.g. a completed session\n // kept for follow-up relay) — reclaim it on eviction.\n void session.client.stop().catch(() => { /* swallow */ });\n }\n }\n\n /**\n * Resolve the GSD CLI path.\n *\n * 1. GSD_CLI_PATH env var (highest priority)\n * 2. `which gsd` → resolve to the actual dist/cli.js\n */\n static resolveCLIPath(): string {\n const envPath = process.env['GSD_CLI_PATH'];\n if (envPath) return resolve(envPath);\n\n try {\n const gsdBin = execSync('which gsd', { encoding: 'utf-8' }).trim();\n if (gsdBin) return resolve(gsdBin);\n } catch {\n // which failed\n }\n\n throw new Error(\n 'Cannot find GSD CLI. Set GSD_CLI_PATH environment variable or ensure `gsd` is in PATH.'\n );\n }\n\n // ---------------------------------------------------------------------------\n // Private: Event Handling\n // ---------------------------------------------------------------------------\n\n private handleEvent(session: ManagedSession, event: SdkAgentEvent): void {\n // Ring buffer: push and trim\n session.events.push(event);\n if (session.events.length > MAX_EVENTS) {\n session.events.splice(0, session.events.length - MAX_EVENTS);\n }\n\n // Forward event to listeners\n this.logger.debug('session event', { sessionId: session.sessionId, type: (event as Record<string, unknown>).type as string });\n this.emit('session:event', { sessionId: session.sessionId, projectDir: session.projectDir, event });\n\n // Cost tracking (K004 — cumulative-max)\n if ((event as Record<string, unknown>).type === 'cost_update') {\n const costEvent = event as unknown as RpcCostUpdateEvent;\n session.cost.totalCost = Math.max(session.cost.totalCost, costEvent.cumulativeCost ?? 0);\n if (costEvent.tokens) {\n session.cost.tokens.input = Math.max(session.cost.tokens.input, costEvent.tokens.input ?? 0);\n session.cost.tokens.output = Math.max(session.cost.tokens.output, costEvent.tokens.output ?? 0);\n session.cost.tokens.cacheRead = Math.max(session.cost.tokens.cacheRead, costEvent.tokens.cacheRead ?? 0);\n session.cost.tokens.cacheWrite = Math.max(session.cost.tokens.cacheWrite, costEvent.tokens.cacheWrite ?? 0);\n }\n }\n\n // Terminal detection — auto-mode/step-mode stopped\n if (isTerminalNotification(event as Record<string, unknown>)) {\n if (isBlockedNotification(event as Record<string, unknown>)) {\n session.status = 'blocked';\n session.pendingBlocker = extractBlocker(event);\n this.logger.info('session blocked', {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n blockerId: session.pendingBlocker.id,\n blockerMethod: session.pendingBlocker.method,\n });\n this.emit('session:blocked', {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n blocker: session.pendingBlocker,\n });\n } else {\n session.status = 'completed';\n session.unsubscribe?.();\n session.unsubscribe = undefined;\n this.logger.info('session completed', { sessionId: session.sessionId, projectDir: session.projectDir });\n this.emit('session:completed', {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n });\n this.markTerminal(session.projectDir);\n }\n return;\n }\n\n // Blocker detection — non-fire-and-forget extension_ui_request\n if (isBlockingUIRequest(event as Record<string, unknown>)) {\n session.status = 'blocked';\n session.pendingBlocker = extractBlocker(event);\n this.logger.info('session blocked', {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n blockerId: session.pendingBlocker.id,\n blockerMethod: session.pendingBlocker.method,\n });\n this.emit('session:blocked', {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n blocker: session.pendingBlocker,\n });\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction timeout(ms: number, message: string): Promise<never> {\n return new Promise((_, reject) => {\n setTimeout(() => reject(new Error(message)), ms);\n });\n}\n\nfunction extractBlocker(event: SdkAgentEvent): PendingBlocker {\n const uiEvent = event as unknown as RpcExtensionUIRequest;\n return {\n id: String(uiEvent.id ?? ''),\n method: uiEvent.method,\n message: String((uiEvent as Record<string, unknown>).title ?? (uiEvent as Record<string, unknown>).message ?? ''),\n event: uiEvent,\n };\n}\n"]}
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SessionManager — manages RpcClient lifecycle for daemon-driven GSD execution.\n *\n * Extends EventEmitter to emit typed session lifecycle events.\n * One active session per projectDir. Tracks events in a ring buffer,\n * detects blockers, tracks terminal state, and accumulates cost using\n * the cumulative-max pattern (K004).\n *\n * Adapted from packages/mcp-server/src/session-manager.ts with:\n * - Logger integration for structured logging\n * - EventEmitter for session lifecycle events\n * - getAllSessions() for cross-project status (R035)\n * - projectName field on ManagedSession\n */\n\nimport { execSync } from 'node:child_process';\nimport { basename, resolve } from 'node:path';\nimport { EventEmitter } from 'node:events';\nimport { RpcClient } from '@opengsd/rpc-client';\nimport type { RpcCostUpdateEvent, RpcExtensionUIRequest, RpcInitResult, SdkAgentEvent } from '@opengsd/contracts';\nimport type {\n ManagedSession,\n StartSessionOptions,\n PendingBlocker,\n} from './types.js';\nimport { MAX_EVENTS, INIT_TIMEOUT_MS } from './types.js';\nimport type { Logger } from './logger.js';\n\n// ---------------------------------------------------------------------------\n// Inlined detection logic (from headless-events.ts — no internal package imports)\n// ---------------------------------------------------------------------------\n\nconst FIRE_AND_FORGET_METHODS = new Set([\n 'notify', 'setStatus', 'setWidget', 'setTitle', 'set_editor_text',\n]);\n\nconst TERMINAL_PREFIXES = [\n 'auto-mode stopped',\n 'step-mode stopped',\n 'auto-mode complete',\n 'no active milestone',\n 'auto-mode idle',\n];\n\nfunction isTerminalNotification(event: Record<string, unknown>): boolean {\n if (event.type !== 'extension_ui_request' || event.method !== 'notify') return false;\n const message = String(event.message ?? '').toLowerCase();\n return TERMINAL_PREFIXES.some((prefix) => message.startsWith(prefix));\n}\n\nfunction isBlockedNotification(event: Record<string, unknown>): boolean {\n if (event.type !== 'extension_ui_request' || event.method !== 'notify') return false;\n const message = String(event.message ?? '').toLowerCase();\n return message.includes('blocked:');\n}\n\nfunction isBlockingUIRequest(event: Record<string, unknown>): boolean {\n if (event.type !== 'extension_ui_request') return false;\n const method = String(event.method ?? '');\n return !FIRE_AND_FORGET_METHODS.has(method);\n}\n\n// ---------------------------------------------------------------------------\n// SessionManager\n// ---------------------------------------------------------------------------\n\n/** Terminal lifecycle states — work is finished, process may be reclaimed. */\nconst TERMINAL_STATUSES: ReadonlySet<string> = new Set(['completed', 'error', 'cancelled']);\n\n/**\n * How many terminal (completed/cancelled/errored) sessions to retain for\n * inspection before evicting the oldest. Bounds heap growth on a daemon that\n * services many distinct project dirs over its lifetime — without this, every\n * session ever run stays resident forever (events buffer + RpcClient ref).\n */\nconst MAX_TERMINAL_SESSIONS = 50;\n\nexport class SessionManager extends EventEmitter {\n /** Sessions keyed by resolved projectDir for duplicate-start prevention */\n private sessions = new Map<string, ManagedSession>();\n\n /** Resolved dirs of terminal sessions, oldest-first — for bounded retention. */\n private terminalOrder: string[] = [];\n\n constructor(private readonly logger: Logger) {\n super();\n }\n\n /**\n * Start a new GSD auto-mode session for the given project directory.\n *\n * Rejects if a session already exists for this projectDir.\n * Creates an RpcClient, starts the process, performs the v2 init handshake,\n * wires event tracking, and sends '/gsd auto' to begin execution.\n */\n async startSession(options: StartSessionOptions): Promise<string> {\n const { projectDir } = options;\n\n if (!projectDir || projectDir.trim() === '') {\n throw new Error('projectDir is required and cannot be empty');\n }\n\n const resolvedDir = resolve(projectDir);\n const projectName = basename(resolvedDir);\n\n const existing = this.sessions.get(resolvedDir);\n if (existing) {\n // A terminal session (completed/cancelled/error) is retained only for\n // inspection — it must not block a fresh start for the same dir. Evict it\n // and reclaim its process before starting anew.\n if (TERMINAL_STATUSES.has(existing.status)) {\n this.evictSession(resolvedDir);\n } else {\n throw new Error(\n `Session already active for ${resolvedDir} (sessionId: ${existing.sessionId}, status: ${existing.status})`\n );\n }\n }\n\n const cliPath = options.cliPath ?? SessionManager.resolveCLIPath();\n\n const args: string[] = [];\n if (options.model) args.push('--model', options.model);\n if (options.bare) args.push('--bare');\n\n const client = new RpcClient({\n cliPath,\n cwd: resolvedDir,\n args,\n });\n\n // Build the session shell before async operations so we can track state\n const session: ManagedSession = {\n sessionId: '', // filled after init\n projectDir: resolvedDir,\n projectName,\n status: 'starting',\n client,\n events: [],\n pendingBlocker: null,\n cost: { totalCost: 0, tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 } },\n startTime: Date.now(),\n };\n\n // Insert into map early (keyed by dir) so concurrent starts are rejected\n this.sessions.set(resolvedDir, session);\n\n try {\n // Start the process with timeout\n await Promise.race([\n client.start(),\n timeout(INIT_TIMEOUT_MS, `RpcClient.start() timed out after ${INIT_TIMEOUT_MS}ms`),\n ]);\n\n // Perform v2 init handshake\n const initResult: RpcInitResult = await Promise.race([\n client.init(),\n timeout(INIT_TIMEOUT_MS, `RpcClient.init() timed out after ${INIT_TIMEOUT_MS}ms`),\n ]) as RpcInitResult;\n\n session.sessionId = initResult.sessionId;\n session.status = 'running';\n\n // Wire event tracking\n session.unsubscribe = client.onEvent((event: SdkAgentEvent) => {\n this.handleEvent(session, event);\n });\n\n // Kick off auto-mode\n const command = options.command ?? '/gsd auto';\n await client.prompt(command);\n\n this.logger.info('session started', { sessionId: session.sessionId, projectDir: resolvedDir });\n this.emit('session:started', { sessionId: session.sessionId, projectDir: resolvedDir, projectName });\n\n return session.sessionId;\n } catch (err) {\n session.status = 'error';\n session.error = err instanceof Error ? err.message : String(err);\n\n // Attempt cleanup\n try { await client.stop(); } catch { /* swallow cleanup errors */ }\n\n this.logger.error('session error', { sessionId: session.sessionId, projectDir: resolvedDir, error: session.error });\n this.emit('session:error', { sessionId: session.sessionId, projectDir: resolvedDir, projectName, error: session.error });\n\n // Keep session in map so callers can inspect the error, but under the\n // bounded terminal-retention policy so it is eventually reclaimed.\n this.markTerminal(resolvedDir);\n throw new Error(`Failed to start session for ${resolvedDir}: ${session.error}`);\n }\n }\n\n /**\n * Look up a session by sessionId.\n * Linear scan is fine — we expect <10 concurrent sessions.\n */\n getSession(sessionId: string): ManagedSession | undefined {\n for (const session of this.sessions.values()) {\n if (session.sessionId === sessionId) return session;\n }\n return undefined;\n }\n\n /**\n * Look up a session by project directory (direct map lookup).\n */\n getSessionByDir(projectDir: string): ManagedSession | undefined {\n return this.sessions.get(resolve(projectDir));\n }\n\n /**\n * Return all tracked sessions (R035 — cross-project status).\n */\n getAllSessions(): ManagedSession[] {\n return Array.from(this.sessions.values());\n }\n\n /**\n * Resolve a pending blocker by sending a UI response.\n */\n async resolveBlocker(sessionId: string, response: string): Promise<void> {\n const session = this.getSession(sessionId);\n if (!session) throw new Error(`Session not found: ${sessionId}`);\n if (!session.pendingBlocker) throw new Error(`No pending blocker for session ${sessionId}`);\n\n const blocker = session.pendingBlocker;\n session.client.sendUIResponse(blocker.id, { value: response });\n session.pendingBlocker = null;\n if (session.status === 'blocked') {\n session.status = 'running';\n }\n\n this.logger.info('blocker resolved', {\n sessionId,\n projectDir: session.projectDir,\n blockerId: blocker.id,\n blockerMethod: blocker.method,\n });\n }\n\n /**\n * Cancel a running session — abort current operation then stop the process.\n */\n async cancelSession(sessionId: string): Promise<void> {\n const session = this.getSession(sessionId);\n if (!session) throw new Error(`Session not found: ${sessionId}`);\n\n try {\n await session.client.abort();\n } catch { /* may already be stopped */ }\n\n try {\n await session.client.stop();\n } catch { /* swallow */ }\n\n session.status = 'cancelled';\n session.unsubscribe?.();\n session.unsubscribe = undefined;\n\n this.logger.info('session cancelled', { sessionId, projectDir: session.projectDir });\n\n // Symmetric teardown: notify listeners (EventBridge) so they can dispose the\n // session's batcher, channel mappings, and any blocker collectors — the\n // start path emits 'session:started', so cancel must emit too.\n this.emit('session:cancelled', {\n sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n });\n\n this.markTerminal(session.projectDir);\n }\n\n async cancelSessionByDir(projectDir: string): Promise<void> {\n const session = this.getSessionByDir(projectDir);\n if (!session) throw new Error(`Session not found for projectDir: ${projectDir}`);\n await this.cancelSession(session.sessionId);\n }\n\n /**\n * Build a HeadlessJsonResult-shaped object from accumulated session state.\n */\n getResult(sessionId: string): Record<string, unknown> {\n const session = this.getSession(sessionId);\n if (!session) throw new Error(`Session not found: ${sessionId}`);\n\n const durationMs = Date.now() - session.startTime;\n\n return {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n status: session.status,\n durationMs,\n cost: session.cost,\n recentEvents: session.events.slice(-10),\n pendingBlocker: session.pendingBlocker\n ? { id: session.pendingBlocker.id, method: session.pendingBlocker.method, message: session.pendingBlocker.message }\n : null,\n error: session.error ?? null,\n };\n }\n\n /**\n * Stop all active sessions and clean up resources.\n */\n async cleanup(): Promise<void> {\n const stopPromises: Promise<void>[] = [];\n\n for (const session of this.sessions.values()) {\n session.unsubscribe?.();\n if (session.status === 'running' || session.status === 'starting' || session.status === 'blocked') {\n stopPromises.push(\n session.client.stop().catch(() => { /* swallow */ })\n );\n session.status = 'cancelled';\n }\n }\n\n await Promise.allSettled(stopPromises);\n\n this.sessions.clear();\n this.terminalOrder = [];\n }\n\n // ---------------------------------------------------------------------------\n // Private: Terminal-session retention (bounded)\n // ---------------------------------------------------------------------------\n\n /**\n * Record a session (by resolved dir) as terminal and evict the oldest\n * terminal sessions once the retention cap is exceeded. Retains recent\n * terminal sessions for inspection while bounding heap growth.\n */\n private markTerminal(resolvedDir: string): void {\n // Move to most-recent position (dedupe if it was already terminal).\n const existingIdx = this.terminalOrder.indexOf(resolvedDir);\n if (existingIdx !== -1) this.terminalOrder.splice(existingIdx, 1);\n this.terminalOrder.push(resolvedDir);\n\n while (this.terminalOrder.length > MAX_TERMINAL_SESSIONS) {\n const oldest = this.terminalOrder.shift();\n if (oldest) this.evictSession(oldest);\n }\n }\n\n /**\n * Remove a session from tracking and best-effort reclaim its agent process.\n */\n private evictSession(resolvedDir: string): void {\n const session = this.sessions.get(resolvedDir);\n this.sessions.delete(resolvedDir);\n const orderIdx = this.terminalOrder.indexOf(resolvedDir);\n if (orderIdx !== -1) this.terminalOrder.splice(orderIdx, 1);\n\n if (session) {\n session.unsubscribe?.();\n session.unsubscribe = undefined;\n // The agent child process may still be alive (e.g. a completed session\n // kept for follow-up relay) — reclaim it on eviction.\n void session.client.stop().catch(() => { /* swallow */ });\n }\n }\n\n /**\n * Resolve the GSD CLI path.\n *\n * 1. GSD_CLI_PATH env var (highest priority)\n * 2. `which gsd` → resolve to the actual dist/cli.js\n */\n static resolveCLIPath(): string {\n const envPath = process.env['GSD_CLI_PATH'];\n if (envPath) return resolve(envPath);\n\n try {\n const gsdBin = execSync('which gsd', { encoding: 'utf-8' }).trim();\n if (gsdBin) return resolve(gsdBin);\n } catch {\n // which failed\n }\n\n throw new Error(\n 'Cannot find GSD CLI. Set GSD_CLI_PATH environment variable or ensure `gsd` is in PATH.'\n );\n }\n\n // ---------------------------------------------------------------------------\n // Private: Event Handling\n // ---------------------------------------------------------------------------\n\n private handleEvent(session: ManagedSession, event: SdkAgentEvent): void {\n // Ring buffer: push and trim\n session.events.push(event);\n if (session.events.length > MAX_EVENTS) {\n session.events.splice(0, session.events.length - MAX_EVENTS);\n }\n\n // Forward event to listeners\n this.logger.debug('session event', { sessionId: session.sessionId, type: (event as Record<string, unknown>).type as string });\n this.emit('session:event', { sessionId: session.sessionId, projectDir: session.projectDir, event });\n\n // Cost tracking (K004 — cumulative-max)\n if ((event as Record<string, unknown>).type === 'cost_update') {\n const costEvent = event as unknown as RpcCostUpdateEvent;\n session.cost.totalCost = Math.max(session.cost.totalCost, costEvent.cumulativeCost ?? 0);\n if (costEvent.tokens) {\n session.cost.tokens.input = Math.max(session.cost.tokens.input, costEvent.tokens.input ?? 0);\n session.cost.tokens.output = Math.max(session.cost.tokens.output, costEvent.tokens.output ?? 0);\n session.cost.tokens.cacheRead = Math.max(session.cost.tokens.cacheRead, costEvent.tokens.cacheRead ?? 0);\n session.cost.tokens.cacheWrite = Math.max(session.cost.tokens.cacheWrite, costEvent.tokens.cacheWrite ?? 0);\n }\n }\n\n // Terminal detection — auto-mode/step-mode stopped\n if (isTerminalNotification(event as Record<string, unknown>)) {\n if (isBlockedNotification(event as Record<string, unknown>)) {\n session.status = 'blocked';\n session.pendingBlocker = extractBlocker(event);\n this.logger.info('session blocked', {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n blockerId: session.pendingBlocker.id,\n blockerMethod: session.pendingBlocker.method,\n });\n this.emit('session:blocked', {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n blocker: session.pendingBlocker,\n });\n } else {\n session.status = 'completed';\n session.unsubscribe?.();\n session.unsubscribe = undefined;\n this.logger.info('session completed', { sessionId: session.sessionId, projectDir: session.projectDir });\n this.emit('session:completed', {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n });\n this.markTerminal(session.projectDir);\n }\n return;\n }\n\n // Blocker detection — non-fire-and-forget extension_ui_request\n if (isBlockingUIRequest(event as Record<string, unknown>)) {\n session.status = 'blocked';\n session.pendingBlocker = extractBlocker(event);\n this.logger.info('session blocked', {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n blockerId: session.pendingBlocker.id,\n blockerMethod: session.pendingBlocker.method,\n });\n this.emit('session:blocked', {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n blocker: session.pendingBlocker,\n });\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction timeout(ms: number, message: string): Promise<never> {\n return new Promise((_, reject) => {\n setTimeout(() => reject(new Error(message)), ms);\n });\n}\n\nfunction extractBlocker(event: SdkAgentEvent): PendingBlocker {\n const uiEvent = event as unknown as RpcExtensionUIRequest;\n return {\n id: String(uiEvent.id ?? ''),\n method: uiEvent.method,\n message: String((uiEvent as Record<string, unknown>).title ?? (uiEvent as Record<string, unknown>).message ?? ''),\n event: uiEvent,\n };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengsd/daemon",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "GSD daemon — background process for project monitoring and Discord integration",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -27,13 +27,13 @@
27
27
  },
28
28
  "scripts": {
29
29
  "build": "node ../../scripts/clean-package-dist.cjs && tsc",
30
- "test": "node --test dist/daemon.test.js dist/cloud-config.test.js dist/cloud-runtime.test.js dist/local-tool-executor.test.js dist/mcp-cli.test.js"
30
+ "test": "node --test dist/daemon.test.js dist/cloud-config.test.js dist/cloud-runtime.test.js dist/local-tool-executor.test.js dist/mcp-cli.test.js dist/message-batcher.test.js"
31
31
  },
32
32
  "dependencies": {
33
33
  "@anthropic-ai/sdk": "^0.52.0",
34
- "@opengsd/contracts": "^1.4.0",
35
- "@opengsd/mcp-server": "^1.4.0",
36
- "@opengsd/rpc-client": "^1.4.0",
34
+ "@opengsd/contracts": "^1.5.0",
35
+ "@opengsd/mcp-server": "^1.5.0",
36
+ "@opengsd/rpc-client": "^1.5.0",
37
37
  "discord.js": "^14.25.1",
38
38
  "ws": "^8.20.0",
39
39
  "yaml": "^2.8.0",
@@ -30,7 +30,19 @@ export interface CompactionSettings {
30
30
  export declare const DEFAULT_COMPACTION_SETTINGS: CompactionSettings;
31
31
  /**
32
32
  * Calculate prompt-side context tokens from usage.
33
- * Completion/output tokens are not part of the reusable conversation context.
33
+ *
34
+ * Providers can normalize cumulative SDK usage into `totalTokens`, so prefer it
35
+ * when present. Completion/output tokens are not part of the reusable
36
+ * conversation context, so they are excluded — `totalTokens` includes them
37
+ * (direct-API providers report `input + output + cacheRead + cacheWrite`; the
38
+ * claude-code adapter reports `input + output + cacheWrite`), hence the
39
+ * subtraction. When `totalTokens` is unavailable, fall back to the prompt-side
40
+ * component sum.
41
+ *
42
+ * - Direct-API: `totalTokens - output === input + cacheRead + cacheWrite`
43
+ * (behavior-preserving, token-for-token, vs. the fallback).
44
+ * - claude-code: `totalTokens - output === input + cacheWrite`, the
45
+ * de-cumulated live-context proxy (the cumulative `cacheRead` is excluded).
34
46
  */
35
47
  export declare function calculateContextTokens(usage: Usage): number;
36
48
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../src/compaction/compaction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../src/compaction/compaction.ts"],"names":[],"mappings":"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"}
@@ -73,9 +73,23 @@ export const DEFAULT_COMPACTION_SETTINGS = {
73
73
  // ============================================================================
74
74
  /**
75
75
  * Calculate prompt-side context tokens from usage.
76
- * Completion/output tokens are not part of the reusable conversation context.
76
+ *
77
+ * Providers can normalize cumulative SDK usage into `totalTokens`, so prefer it
78
+ * when present. Completion/output tokens are not part of the reusable
79
+ * conversation context, so they are excluded — `totalTokens` includes them
80
+ * (direct-API providers report `input + output + cacheRead + cacheWrite`; the
81
+ * claude-code adapter reports `input + output + cacheWrite`), hence the
82
+ * subtraction. When `totalTokens` is unavailable, fall back to the prompt-side
83
+ * component sum.
84
+ *
85
+ * - Direct-API: `totalTokens - output === input + cacheRead + cacheWrite`
86
+ * (behavior-preserving, token-for-token, vs. the fallback).
87
+ * - claude-code: `totalTokens - output === input + cacheWrite`, the
88
+ * de-cumulated live-context proxy (the cumulative `cacheRead` is excluded).
77
89
  */
78
90
  export function calculateContextTokens(usage) {
91
+ if (usage.totalTokens > 0)
92
+ return Math.max(0, usage.totalTokens - usage.output);
79
93
  return usage.input + usage.cacheRead + usage.cacheWrite;
80
94
  }
81
95
  /**